]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - net/wireless/nl80211.c
mac80211: split RX_DROP
[mirror_ubuntu-hirsute-kernel.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>
10#include <linux/mutex.h>
11#include <linux/list.h>
12#include <linux/if_ether.h>
13#include <linux/ieee80211.h>
14#include <linux/nl80211.h>
15#include <linux/rtnetlink.h>
16#include <linux/netlink.h>
17#include <net/genetlink.h>
18#include <net/cfg80211.h>
19#include "core.h"
20#include "nl80211.h"
21
22/* the netlink family */
23static struct genl_family nl80211_fam = {
24 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
25 .name = "nl80211", /* have users key off the name instead */
26 .hdrsize = 0, /* no private header */
27 .version = 1, /* no particular meaning now */
28 .maxattr = NL80211_ATTR_MAX,
29};
30
31/* internal helper: get drv and dev */
32static int get_drv_dev_by_info_ifindex(struct genl_info *info,
33 struct cfg80211_registered_device **drv,
34 struct net_device **dev)
35{
36 int ifindex;
37
38 if (!info->attrs[NL80211_ATTR_IFINDEX])
39 return -EINVAL;
40
41 ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
42 *dev = dev_get_by_index(&init_net, ifindex);
43 if (!*dev)
44 return -ENODEV;
45
46 *drv = cfg80211_get_dev_from_ifindex(ifindex);
47 if (IS_ERR(*drv)) {
48 dev_put(*dev);
49 return PTR_ERR(*drv);
50 }
51
52 return 0;
53}
54
55/* policy for the attributes */
56static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
57 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
58 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
59 .len = BUS_ID_SIZE-1 },
60
61 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
62 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
63 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
41ade00f
JB
64
65 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
66
67 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
68 .len = WLAN_MAX_KEY_LEN },
69 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
70 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
71 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
ed1b6cc7
JB
72
73 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
74 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
75 [NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
76 .len = IEEE80211_MAX_DATA_LEN },
77 [NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
78 .len = IEEE80211_MAX_DATA_LEN },
5727ef1b
JB
79 [NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
80 [NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
81 [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
82 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
83 .len = NL80211_MAX_SUPP_RATES },
84 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
55682965
JB
85};
86
87/* message building helper */
88static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
89 int flags, u8 cmd)
90{
91 /* since there is no private header just add the generic one */
92 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd);
93}
94
95/* netlink command implementations */
96
97static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
98 struct cfg80211_registered_device *dev)
99{
100 void *hdr;
ee688b00
JB
101 struct nlattr *nl_bands, *nl_band;
102 struct nlattr *nl_freqs, *nl_freq;
103 struct nlattr *nl_rates, *nl_rate;
104 enum ieee80211_band band;
105 struct ieee80211_channel *chan;
106 struct ieee80211_rate *rate;
107 int i;
55682965
JB
108
109 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
110 if (!hdr)
111 return -1;
112
113 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
114 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
ee688b00
JB
115
116 nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
117 if (!nl_bands)
118 goto nla_put_failure;
119
120 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
121 if (!dev->wiphy.bands[band])
122 continue;
123
124 nl_band = nla_nest_start(msg, band);
125 if (!nl_band)
126 goto nla_put_failure;
127
128 /* add frequencies */
129 nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
130 if (!nl_freqs)
131 goto nla_put_failure;
132
133 for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
134 nl_freq = nla_nest_start(msg, i);
135 if (!nl_freq)
136 goto nla_put_failure;
137
138 chan = &dev->wiphy.bands[band]->channels[i];
139 NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
140 chan->center_freq);
141
142 if (chan->flags & IEEE80211_CHAN_DISABLED)
143 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
144 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
145 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
146 if (chan->flags & IEEE80211_CHAN_NO_IBSS)
147 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
148 if (chan->flags & IEEE80211_CHAN_RADAR)
149 NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
150
151 nla_nest_end(msg, nl_freq);
152 }
153
154 nla_nest_end(msg, nl_freqs);
155
156 /* add bitrates */
157 nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
158 if (!nl_rates)
159 goto nla_put_failure;
160
161 for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
162 nl_rate = nla_nest_start(msg, i);
163 if (!nl_rate)
164 goto nla_put_failure;
165
166 rate = &dev->wiphy.bands[band]->bitrates[i];
167 NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
168 rate->bitrate);
169 if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
170 NLA_PUT_FLAG(msg,
171 NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
172
173 nla_nest_end(msg, nl_rate);
174 }
175
176 nla_nest_end(msg, nl_rates);
177
178 nla_nest_end(msg, nl_band);
179 }
180 nla_nest_end(msg, nl_bands);
181
55682965
JB
182 return genlmsg_end(msg, hdr);
183
184 nla_put_failure:
185 return genlmsg_cancel(msg, hdr);
186}
187
188static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
189{
190 int idx = 0;
191 int start = cb->args[0];
192 struct cfg80211_registered_device *dev;
193
194 mutex_lock(&cfg80211_drv_mutex);
195 list_for_each_entry(dev, &cfg80211_drv_list, list) {
196 if (++idx < start)
197 continue;
198 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
199 cb->nlh->nlmsg_seq, NLM_F_MULTI,
200 dev) < 0)
201 break;
202 }
203 mutex_unlock(&cfg80211_drv_mutex);
204
205 cb->args[0] = idx;
206
207 return skb->len;
208}
209
210static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
211{
212 struct sk_buff *msg;
213 struct cfg80211_registered_device *dev;
214
215 dev = cfg80211_get_dev_from_info(info);
216 if (IS_ERR(dev))
217 return PTR_ERR(dev);
218
219 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
220 if (!msg)
221 goto out_err;
222
223 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
224 goto out_free;
225
226 cfg80211_put_dev(dev);
227
228 return genlmsg_unicast(msg, info->snd_pid);
229
230 out_free:
231 nlmsg_free(msg);
232 out_err:
233 cfg80211_put_dev(dev);
234 return -ENOBUFS;
235}
236
237static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
238{
239 struct cfg80211_registered_device *rdev;
240 int result;
241
242 if (!info->attrs[NL80211_ATTR_WIPHY_NAME])
243 return -EINVAL;
244
245 rdev = cfg80211_get_dev_from_info(info);
246 if (IS_ERR(rdev))
247 return PTR_ERR(rdev);
248
249 result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
250
251 cfg80211_put_dev(rdev);
252 return result;
253}
254
255
256static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
257 struct net_device *dev)
258{
259 void *hdr;
260
261 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE);
262 if (!hdr)
263 return -1;
264
265 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
266 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
267 /* TODO: interface type */
268 return genlmsg_end(msg, hdr);
269
270 nla_put_failure:
271 return genlmsg_cancel(msg, hdr);
272}
273
274static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
275{
276 int wp_idx = 0;
277 int if_idx = 0;
278 int wp_start = cb->args[0];
279 int if_start = cb->args[1];
280 struct cfg80211_registered_device *dev;
281 struct wireless_dev *wdev;
282
283 mutex_lock(&cfg80211_drv_mutex);
284 list_for_each_entry(dev, &cfg80211_drv_list, list) {
285 if (++wp_idx < wp_start)
286 continue;
287 if_idx = 0;
288
289 mutex_lock(&dev->devlist_mtx);
290 list_for_each_entry(wdev, &dev->netdev_list, list) {
291 if (++if_idx < if_start)
292 continue;
293 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
294 cb->nlh->nlmsg_seq, NLM_F_MULTI,
295 wdev->netdev) < 0)
296 break;
297 }
298 mutex_unlock(&dev->devlist_mtx);
299 }
300 mutex_unlock(&cfg80211_drv_mutex);
301
302 cb->args[0] = wp_idx;
303 cb->args[1] = if_idx;
304
305 return skb->len;
306}
307
308static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
309{
310 struct sk_buff *msg;
311 struct cfg80211_registered_device *dev;
312 struct net_device *netdev;
313 int err;
314
315 err = get_drv_dev_by_info_ifindex(info, &dev, &netdev);
316 if (err)
317 return err;
318
319 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
320 if (!msg)
321 goto out_err;
322
323 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0)
324 goto out_free;
325
326 dev_put(netdev);
327 cfg80211_put_dev(dev);
328
329 return genlmsg_unicast(msg, info->snd_pid);
330
331 out_free:
332 nlmsg_free(msg);
333 out_err:
334 dev_put(netdev);
335 cfg80211_put_dev(dev);
336 return -ENOBUFS;
337}
338
339static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
340{
341 struct cfg80211_registered_device *drv;
342 int err, ifindex;
343 enum nl80211_iftype type;
344 struct net_device *dev;
345
346 if (info->attrs[NL80211_ATTR_IFTYPE]) {
347 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
348 if (type > NL80211_IFTYPE_MAX)
349 return -EINVAL;
350 } else
351 return -EINVAL;
352
353 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
354 if (err)
355 return err;
356 ifindex = dev->ifindex;
357 dev_put(dev);
358
359 if (!drv->ops->change_virtual_intf) {
360 err = -EOPNOTSUPP;
361 goto unlock;
362 }
363
364 rtnl_lock();
365 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
366 rtnl_unlock();
367
368 unlock:
369 cfg80211_put_dev(drv);
370 return err;
371}
372
373static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
374{
375 struct cfg80211_registered_device *drv;
376 int err;
377 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
378
379 if (!info->attrs[NL80211_ATTR_IFNAME])
380 return -EINVAL;
381
382 if (info->attrs[NL80211_ATTR_IFTYPE]) {
383 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
384 if (type > NL80211_IFTYPE_MAX)
385 return -EINVAL;
386 }
387
388 drv = cfg80211_get_dev_from_info(info);
389 if (IS_ERR(drv))
390 return PTR_ERR(drv);
391
392 if (!drv->ops->add_virtual_intf) {
393 err = -EOPNOTSUPP;
394 goto unlock;
395 }
396
397 rtnl_lock();
398 err = drv->ops->add_virtual_intf(&drv->wiphy,
399 nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
400 rtnl_unlock();
401
402 unlock:
403 cfg80211_put_dev(drv);
404 return err;
405}
406
407static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
408{
409 struct cfg80211_registered_device *drv;
410 int ifindex, err;
411 struct net_device *dev;
412
413 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
414 if (err)
415 return err;
416 ifindex = dev->ifindex;
417 dev_put(dev);
418
419 if (!drv->ops->del_virtual_intf) {
420 err = -EOPNOTSUPP;
421 goto out;
422 }
423
424 rtnl_lock();
425 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
426 rtnl_unlock();
427
428 out:
429 cfg80211_put_dev(drv);
430 return err;
431}
432
41ade00f
JB
433struct get_key_cookie {
434 struct sk_buff *msg;
435 int error;
436};
437
438static void get_key_callback(void *c, struct key_params *params)
439{
440 struct get_key_cookie *cookie = c;
441
442 if (params->key)
443 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
444 params->key_len, params->key);
445
446 if (params->seq)
447 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
448 params->seq_len, params->seq);
449
450 if (params->cipher)
451 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
452 params->cipher);
453
454 return;
455 nla_put_failure:
456 cookie->error = 1;
457}
458
459static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
460{
461 struct cfg80211_registered_device *drv;
462 int err;
463 struct net_device *dev;
464 u8 key_idx = 0;
465 u8 *mac_addr = NULL;
466 struct get_key_cookie cookie = {
467 .error = 0,
468 };
469 void *hdr;
470 struct sk_buff *msg;
471
472 if (info->attrs[NL80211_ATTR_KEY_IDX])
473 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
474
475 if (key_idx > 3)
476 return -EINVAL;
477
478 if (info->attrs[NL80211_ATTR_MAC])
479 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
480
481 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
482 if (err)
483 return err;
484
485 if (!drv->ops->get_key) {
486 err = -EOPNOTSUPP;
487 goto out;
488 }
489
490 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
491 if (!msg) {
492 err = -ENOMEM;
493 goto out;
494 }
495
496 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
497 NL80211_CMD_NEW_KEY);
498
499 if (IS_ERR(hdr)) {
500 err = PTR_ERR(hdr);
501 goto out;
502 }
503
504 cookie.msg = msg;
505
506 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
507 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
508 if (mac_addr)
509 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
510
511 rtnl_lock();
512 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
513 &cookie, get_key_callback);
514 rtnl_unlock();
515
516 if (err)
517 goto out;
518
519 if (cookie.error)
520 goto nla_put_failure;
521
522 genlmsg_end(msg, hdr);
523 err = genlmsg_unicast(msg, info->snd_pid);
524 goto out;
525
526 nla_put_failure:
527 err = -ENOBUFS;
528 nlmsg_free(msg);
529 out:
530 cfg80211_put_dev(drv);
531 dev_put(dev);
532 return err;
533}
534
535static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
536{
537 struct cfg80211_registered_device *drv;
538 int err;
539 struct net_device *dev;
540 u8 key_idx;
541
542 if (!info->attrs[NL80211_ATTR_KEY_IDX])
543 return -EINVAL;
544
545 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
546
547 if (key_idx > 3)
548 return -EINVAL;
549
550 /* currently only support setting default key */
551 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
552 return -EINVAL;
553
554 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
555 if (err)
556 return err;
557
558 if (!drv->ops->set_default_key) {
559 err = -EOPNOTSUPP;
560 goto out;
561 }
562
563 rtnl_lock();
564 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
565 rtnl_unlock();
566
567 out:
568 cfg80211_put_dev(drv);
569 dev_put(dev);
570 return err;
571}
572
573static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
574{
575 struct cfg80211_registered_device *drv;
576 int err;
577 struct net_device *dev;
578 struct key_params params;
579 u8 key_idx = 0;
580 u8 *mac_addr = NULL;
581
582 memset(&params, 0, sizeof(params));
583
584 if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
585 return -EINVAL;
586
587 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
588 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
589 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
590 }
591
592 if (info->attrs[NL80211_ATTR_KEY_IDX])
593 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
594
595 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
596
597 if (info->attrs[NL80211_ATTR_MAC])
598 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
599
600 if (key_idx > 3)
601 return -EINVAL;
602
603 /*
604 * Disallow pairwise keys with non-zero index unless it's WEP
605 * (because current deployments use pairwise WEP keys with
606 * non-zero indizes but 802.11i clearly specifies to use zero)
607 */
608 if (mac_addr && key_idx &&
609 params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
610 params.cipher != WLAN_CIPHER_SUITE_WEP104)
611 return -EINVAL;
612
613 /* TODO: add definitions for the lengths to linux/ieee80211.h */
614 switch (params.cipher) {
615 case WLAN_CIPHER_SUITE_WEP40:
616 if (params.key_len != 5)
617 return -EINVAL;
618 break;
619 case WLAN_CIPHER_SUITE_TKIP:
620 if (params.key_len != 32)
621 return -EINVAL;
622 break;
623 case WLAN_CIPHER_SUITE_CCMP:
624 if (params.key_len != 16)
625 return -EINVAL;
626 break;
627 case WLAN_CIPHER_SUITE_WEP104:
628 if (params.key_len != 13)
629 return -EINVAL;
630 break;
631 default:
632 return -EINVAL;
633 }
634
635 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
636 if (err)
637 return err;
638
639 if (!drv->ops->add_key) {
640 err = -EOPNOTSUPP;
641 goto out;
642 }
643
644 rtnl_lock();
645 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
646 rtnl_unlock();
647
648 out:
649 cfg80211_put_dev(drv);
650 dev_put(dev);
651 return err;
652}
653
654static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
655{
656 struct cfg80211_registered_device *drv;
657 int err;
658 struct net_device *dev;
659 u8 key_idx = 0;
660 u8 *mac_addr = NULL;
661
662 if (info->attrs[NL80211_ATTR_KEY_IDX])
663 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
664
665 if (key_idx > 3)
666 return -EINVAL;
667
668 if (info->attrs[NL80211_ATTR_MAC])
669 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
670
671 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
672 if (err)
673 return err;
674
675 if (!drv->ops->del_key) {
676 err = -EOPNOTSUPP;
677 goto out;
678 }
679
680 rtnl_lock();
681 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
682 rtnl_unlock();
683
684 out:
685 cfg80211_put_dev(drv);
686 dev_put(dev);
687 return err;
688}
689
ed1b6cc7
JB
690static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
691{
692 int (*call)(struct wiphy *wiphy, struct net_device *dev,
693 struct beacon_parameters *info);
694 struct cfg80211_registered_device *drv;
695 int err;
696 struct net_device *dev;
697 struct beacon_parameters params;
698 int haveinfo = 0;
699
700 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
701 if (err)
702 return err;
703
704 switch (info->genlhdr->cmd) {
705 case NL80211_CMD_NEW_BEACON:
706 /* these are required for NEW_BEACON */
707 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
708 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
709 !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
710 err = -EINVAL;
711 goto out;
712 }
713
714 call = drv->ops->add_beacon;
715 break;
716 case NL80211_CMD_SET_BEACON:
717 call = drv->ops->set_beacon;
718 break;
719 default:
720 WARN_ON(1);
721 err = -EOPNOTSUPP;
722 goto out;
723 }
724
725 if (!call) {
726 err = -EOPNOTSUPP;
727 goto out;
728 }
729
730 memset(&params, 0, sizeof(params));
731
732 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
733 params.interval =
734 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
735 haveinfo = 1;
736 }
737
738 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
739 params.dtim_period =
740 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
741 haveinfo = 1;
742 }
743
744 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
745 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
746 params.head_len =
747 nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
748 haveinfo = 1;
749 }
750
751 if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
752 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
753 params.tail_len =
754 nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
755 haveinfo = 1;
756 }
757
758 if (!haveinfo) {
759 err = -EINVAL;
760 goto out;
761 }
762
763 rtnl_lock();
764 err = call(&drv->wiphy, dev, &params);
765 rtnl_unlock();
766
767 out:
768 cfg80211_put_dev(drv);
769 dev_put(dev);
770 return err;
771}
772
773static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
774{
775 struct cfg80211_registered_device *drv;
776 int err;
777 struct net_device *dev;
778
779 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
780 if (err)
781 return err;
782
783 if (!drv->ops->del_beacon) {
784 err = -EOPNOTSUPP;
785 goto out;
786 }
787
788 rtnl_lock();
789 err = drv->ops->del_beacon(&drv->wiphy, dev);
790 rtnl_unlock();
791
792 out:
793 cfg80211_put_dev(drv);
794 dev_put(dev);
795 return err;
796}
797
5727ef1b
JB
798static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
799 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
800 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
801 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
802};
803
804static int parse_station_flags(struct nlattr *nla, u32 *staflags)
805{
806 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
807 int flag;
808
809 *staflags = 0;
810
811 if (!nla)
812 return 0;
813
814 if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
815 nla, sta_flags_policy))
816 return -EINVAL;
817
818 *staflags = STATION_FLAG_CHANGED;
819
820 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
821 if (flags[flag])
822 *staflags |= (1<<flag);
823
824 return 0;
825}
826
fd5b74dc
JB
827static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
828 int flags, struct net_device *dev,
829 u8 *mac_addr, struct station_stats *stats)
830{
831 void *hdr;
832 struct nlattr *statsattr;
833
834 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
835 if (!hdr)
836 return -1;
837
838 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
839 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
840
841 statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
842 if (!statsattr)
843 goto nla_put_failure;
844 if (stats->filled & STATION_STAT_INACTIVE_TIME)
845 NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
846 stats->inactive_time);
847 if (stats->filled & STATION_STAT_RX_BYTES)
848 NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
849 stats->rx_bytes);
850 if (stats->filled & STATION_STAT_TX_BYTES)
851 NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
852 stats->tx_bytes);
853
854 nla_nest_end(msg, statsattr);
855
856 return genlmsg_end(msg, hdr);
857
858 nla_put_failure:
859 return genlmsg_cancel(msg, hdr);
860}
861
862
5727ef1b
JB
863static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
864{
fd5b74dc
JB
865 struct cfg80211_registered_device *drv;
866 int err;
867 struct net_device *dev;
868 struct station_stats stats;
869 struct sk_buff *msg;
870 u8 *mac_addr = NULL;
871
872 memset(&stats, 0, sizeof(stats));
873
874 if (!info->attrs[NL80211_ATTR_MAC])
875 return -EINVAL;
876
877 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
878
879 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
880 if (err)
881 return err;
882
883 if (!drv->ops->get_station) {
884 err = -EOPNOTSUPP;
885 goto out;
886 }
887
888 rtnl_lock();
889 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
890 rtnl_unlock();
891
892 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
893 if (!msg)
894 goto out;
895
896 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
897 dev, mac_addr, &stats) < 0)
898 goto out_free;
899
900 err = genlmsg_unicast(msg, info->snd_pid);
901 goto out;
902
903 out_free:
904 nlmsg_free(msg);
905
906 out:
907 cfg80211_put_dev(drv);
908 dev_put(dev);
909 return err;
5727ef1b
JB
910}
911
912/*
913 * Get vlan interface making sure it is on the right wiphy.
914 */
915static int get_vlan(struct nlattr *vlanattr,
916 struct cfg80211_registered_device *rdev,
917 struct net_device **vlan)
918{
919 *vlan = NULL;
920
921 if (vlanattr) {
922 *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
923 if (!*vlan)
924 return -ENODEV;
925 if (!(*vlan)->ieee80211_ptr)
926 return -EINVAL;
927 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
928 return -EINVAL;
929 }
930 return 0;
931}
932
933static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
934{
935 struct cfg80211_registered_device *drv;
936 int err;
937 struct net_device *dev;
938 struct station_parameters params;
939 u8 *mac_addr = NULL;
940
941 memset(&params, 0, sizeof(params));
942
943 params.listen_interval = -1;
944
945 if (info->attrs[NL80211_ATTR_STA_AID])
946 return -EINVAL;
947
948 if (!info->attrs[NL80211_ATTR_MAC])
949 return -EINVAL;
950
951 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
952
953 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
954 params.supported_rates =
955 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
956 params.supported_rates_len =
957 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
958 }
959
960 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
961 params.listen_interval =
962 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
963
964 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
965 &params.station_flags))
966 return -EINVAL;
967
968 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
969 if (err)
970 return err;
971
972 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
973 if (err)
974 goto out;
975
976 if (!drv->ops->change_station) {
977 err = -EOPNOTSUPP;
978 goto out;
979 }
980
981 rtnl_lock();
982 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
983 rtnl_unlock();
984
985 out:
986 if (params.vlan)
987 dev_put(params.vlan);
988 cfg80211_put_dev(drv);
989 dev_put(dev);
990 return err;
991}
992
993static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
994{
995 struct cfg80211_registered_device *drv;
996 int err;
997 struct net_device *dev;
998 struct station_parameters params;
999 u8 *mac_addr = NULL;
1000
1001 memset(&params, 0, sizeof(params));
1002
1003 if (!info->attrs[NL80211_ATTR_MAC])
1004 return -EINVAL;
1005
1006 if (!info->attrs[NL80211_ATTR_STA_AID])
1007 return -EINVAL;
1008
1009 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1010 return -EINVAL;
1011
1012 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
1013 return -EINVAL;
1014
1015 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1016 params.supported_rates =
1017 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1018 params.supported_rates_len =
1019 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
1020 params.listen_interval =
1021 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1022 params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
1023
1024 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
1025 &params.station_flags))
1026 return -EINVAL;
1027
1028 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1029 if (err)
1030 return err;
1031
1032 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1033 if (err)
1034 goto out;
1035
1036 if (!drv->ops->add_station) {
1037 err = -EOPNOTSUPP;
1038 goto out;
1039 }
1040
1041 rtnl_lock();
1042 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
1043 rtnl_unlock();
1044
1045 out:
1046 if (params.vlan)
1047 dev_put(params.vlan);
1048 cfg80211_put_dev(drv);
1049 dev_put(dev);
1050 return err;
1051}
1052
1053static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1054{
1055 struct cfg80211_registered_device *drv;
1056 int err;
1057 struct net_device *dev;
1058 u8 *mac_addr = NULL;
1059
1060 if (info->attrs[NL80211_ATTR_MAC])
1061 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
1062
1063 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
1064 if (err)
1065 return err;
1066
1067 if (!drv->ops->del_station) {
1068 err = -EOPNOTSUPP;
1069 goto out;
1070 }
1071
1072 rtnl_lock();
1073 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1074 rtnl_unlock();
1075
1076 out:
1077 cfg80211_put_dev(drv);
1078 dev_put(dev);
1079 return err;
1080}
1081
55682965
JB
1082static struct genl_ops nl80211_ops[] = {
1083 {
1084 .cmd = NL80211_CMD_GET_WIPHY,
1085 .doit = nl80211_get_wiphy,
1086 .dumpit = nl80211_dump_wiphy,
1087 .policy = nl80211_policy,
1088 /* can be retrieved by unprivileged users */
1089 },
1090 {
1091 .cmd = NL80211_CMD_SET_WIPHY,
1092 .doit = nl80211_set_wiphy,
1093 .policy = nl80211_policy,
1094 .flags = GENL_ADMIN_PERM,
1095 },
1096 {
1097 .cmd = NL80211_CMD_GET_INTERFACE,
1098 .doit = nl80211_get_interface,
1099 .dumpit = nl80211_dump_interface,
1100 .policy = nl80211_policy,
1101 /* can be retrieved by unprivileged users */
1102 },
1103 {
1104 .cmd = NL80211_CMD_SET_INTERFACE,
1105 .doit = nl80211_set_interface,
1106 .policy = nl80211_policy,
1107 .flags = GENL_ADMIN_PERM,
1108 },
1109 {
1110 .cmd = NL80211_CMD_NEW_INTERFACE,
1111 .doit = nl80211_new_interface,
1112 .policy = nl80211_policy,
1113 .flags = GENL_ADMIN_PERM,
1114 },
1115 {
1116 .cmd = NL80211_CMD_DEL_INTERFACE,
1117 .doit = nl80211_del_interface,
1118 .policy = nl80211_policy,
41ade00f
JB
1119 .flags = GENL_ADMIN_PERM,
1120 },
1121 {
1122 .cmd = NL80211_CMD_GET_KEY,
1123 .doit = nl80211_get_key,
1124 .policy = nl80211_policy,
1125 .flags = GENL_ADMIN_PERM,
1126 },
1127 {
1128 .cmd = NL80211_CMD_SET_KEY,
1129 .doit = nl80211_set_key,
1130 .policy = nl80211_policy,
1131 .flags = GENL_ADMIN_PERM,
1132 },
1133 {
1134 .cmd = NL80211_CMD_NEW_KEY,
1135 .doit = nl80211_new_key,
1136 .policy = nl80211_policy,
1137 .flags = GENL_ADMIN_PERM,
1138 },
1139 {
1140 .cmd = NL80211_CMD_DEL_KEY,
1141 .doit = nl80211_del_key,
1142 .policy = nl80211_policy,
55682965
JB
1143 .flags = GENL_ADMIN_PERM,
1144 },
ed1b6cc7
JB
1145 {
1146 .cmd = NL80211_CMD_SET_BEACON,
1147 .policy = nl80211_policy,
1148 .flags = GENL_ADMIN_PERM,
1149 .doit = nl80211_addset_beacon,
1150 },
1151 {
1152 .cmd = NL80211_CMD_NEW_BEACON,
1153 .policy = nl80211_policy,
1154 .flags = GENL_ADMIN_PERM,
1155 .doit = nl80211_addset_beacon,
1156 },
1157 {
1158 .cmd = NL80211_CMD_DEL_BEACON,
1159 .policy = nl80211_policy,
1160 .flags = GENL_ADMIN_PERM,
1161 .doit = nl80211_del_beacon,
1162 },
5727ef1b
JB
1163 {
1164 .cmd = NL80211_CMD_GET_STATION,
1165 .doit = nl80211_get_station,
1166 /* TODO: implement dumpit */
1167 .policy = nl80211_policy,
1168 .flags = GENL_ADMIN_PERM,
1169 },
1170 {
1171 .cmd = NL80211_CMD_SET_STATION,
1172 .doit = nl80211_set_station,
1173 .policy = nl80211_policy,
1174 .flags = GENL_ADMIN_PERM,
1175 },
1176 {
1177 .cmd = NL80211_CMD_NEW_STATION,
1178 .doit = nl80211_new_station,
1179 .policy = nl80211_policy,
1180 .flags = GENL_ADMIN_PERM,
1181 },
1182 {
1183 .cmd = NL80211_CMD_DEL_STATION,
1184 .doit = nl80211_del_station,
1185 .policy = nl80211_policy,
1186 .flags = GENL_ADMIN_PERM,
1187 },
55682965
JB
1188};
1189
1190/* multicast groups */
1191static struct genl_multicast_group nl80211_config_mcgrp = {
1192 .name = "config",
1193};
1194
1195/* notification functions */
1196
1197void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
1198{
1199 struct sk_buff *msg;
1200
1201 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1202 if (!msg)
1203 return;
1204
1205 if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) {
1206 nlmsg_free(msg);
1207 return;
1208 }
1209
1210 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
1211}
1212
1213/* initialisation/exit functions */
1214
1215int nl80211_init(void)
1216{
1217 int err, i;
1218
1219 err = genl_register_family(&nl80211_fam);
1220 if (err)
1221 return err;
1222
1223 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) {
1224 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]);
1225 if (err)
1226 goto err_out;
1227 }
1228
1229 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
1230 if (err)
1231 goto err_out;
1232
1233 return 0;
1234 err_out:
1235 genl_unregister_family(&nl80211_fam);
1236 return err;
1237}
1238
1239void nl80211_exit(void)
1240{
1241 genl_unregister_family(&nl80211_fam);
1242}