aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 06:54:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-29 06:54:01 -0500
commit0ba6c33bcddc64a54b5f1c25a696c4767dc76292 (patch)
tree62e616f97a4762d8e75bf732e4827af2d15d52c5 /net/wireless
parent21af0297c7e56024a5ccc4d8ad2a590f9ec371ba (diff)
parent85040bcb4643cba578839e953f25e2d1965d83d0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.25: (1470 commits) [IPV6] ADDRLABEL: Fix double free on label deletion. [PPP]: Sparse warning fixes. [IPV4] fib_trie: remove unneeded NULL check [IPV4] fib_trie: More whitespace cleanup. [NET_SCHED]: Use nla_policy for attribute validation in ematches [NET_SCHED]: Use nla_policy for attribute validation in actions [NET_SCHED]: Use nla_policy for attribute validation in classifiers [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers [NET_SCHED]: sch_api: introduce constant for rate table size [NET_SCHED]: Use typeful attribute parsing helpers [NET_SCHED]: Use typeful attribute construction helpers [NET_SCHED]: Use NLA_PUT_STRING for string dumping [NET_SCHED]: Use nla_nest_start/nla_nest_end [NET_SCHED]: Propagate nla_parse return value [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get [NET_SCHED]: act_api: use nlmsg_parse [NET_SCHED]: act_api: fix netlink API conversion bug [NET_SCHED]: sch_netem: use nla_parse_nested_compat [NET_SCHED]: sch_atm: fix format string warning [NETNS]: Add namespace for ICMP replying code. ...
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/Kconfig10
-rw-r--r--net/wireless/core.c3
-rw-r--r--net/wireless/nl80211.c737
-rw-r--r--net/wireless/wext.c43
4 files changed, 752 insertions, 41 deletions
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 6426055a8be0..79270903bda6 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -6,13 +6,13 @@ config NL80211
6 depends on CFG80211 6 depends on CFG80211
7 default y 7 default y
8 ---help--- 8 ---help---
9 This option turns on the new netlink interface 9 This option turns on the new netlink interface
10 (nl80211) support in cfg80211. 10 (nl80211) support in cfg80211.
11 11
12 If =n, drivers using mac80211 will be configured via 12 If =n, drivers using mac80211 will be configured via
13 wireless extension support provided by that subsystem. 13 wireless extension support provided by that subsystem.
14 14
15 If unsure, say Y. 15 If unsure, say Y.
16 16
17config WIRELESS_EXT 17config WIRELESS_EXT
18 bool "Wireless extensions" 18 bool "Wireless extensions"
diff --git a/net/wireless/core.c b/net/wireless/core.c
index febc33bc9c09..cfc5fc5f9e75 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -184,6 +184,9 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
184 struct cfg80211_registered_device *drv; 184 struct cfg80211_registered_device *drv;
185 int alloc_size; 185 int alloc_size;
186 186
187 WARN_ON(!ops->add_key && ops->del_key);
188 WARN_ON(ops->add_key && !ops->del_key);
189
187 alloc_size = sizeof(*drv) + sizeof_priv; 190 alloc_size = sizeof(*drv) + sizeof_priv;
188 191
189 drv = kzalloc(alloc_size, GFP_KERNEL); 192 drv = kzalloc(alloc_size, GFP_KERNEL);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 48b0d453e4e1..e3a214f63f91 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -61,6 +61,27 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
61 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 61 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
62 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 62 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
63 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, 63 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
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 },
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 },
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 },
64}; 85};
65 86
66/* message building helper */ 87/* message building helper */
@@ -335,6 +356,655 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
335 return err; 356 return err;
336} 357}
337 358
359struct get_key_cookie {
360 struct sk_buff *msg;
361 int error;
362};
363
364static void get_key_callback(void *c, struct key_params *params)
365{
366 struct get_key_cookie *cookie = c;
367
368 if (params->key)
369 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA,
370 params->key_len, params->key);
371
372 if (params->seq)
373 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ,
374 params->seq_len, params->seq);
375
376 if (params->cipher)
377 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER,
378 params->cipher);
379
380 return;
381 nla_put_failure:
382 cookie->error = 1;
383}
384
385static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
386{
387 struct cfg80211_registered_device *drv;
388 int err;
389 struct net_device *dev;
390 u8 key_idx = 0;
391 u8 *mac_addr = NULL;
392 struct get_key_cookie cookie = {
393 .error = 0,
394 };
395 void *hdr;
396 struct sk_buff *msg;
397
398 if (info->attrs[NL80211_ATTR_KEY_IDX])
399 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
400
401 if (key_idx > 3)
402 return -EINVAL;
403
404 if (info->attrs[NL80211_ATTR_MAC])
405 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
406
407 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
408 if (err)
409 return err;
410
411 if (!drv->ops->get_key) {
412 err = -EOPNOTSUPP;
413 goto out;
414 }
415
416 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
417 if (!msg) {
418 err = -ENOMEM;
419 goto out;
420 }
421
422 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
423 NL80211_CMD_NEW_KEY);
424
425 if (IS_ERR(hdr)) {
426 err = PTR_ERR(hdr);
427 goto out;
428 }
429
430 cookie.msg = msg;
431
432 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
433 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
434 if (mac_addr)
435 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
436
437 rtnl_lock();
438 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
439 &cookie, get_key_callback);
440 rtnl_unlock();
441
442 if (err)
443 goto out;
444
445 if (cookie.error)
446 goto nla_put_failure;
447
448 genlmsg_end(msg, hdr);
449 err = genlmsg_unicast(msg, info->snd_pid);
450 goto out;
451
452 nla_put_failure:
453 err = -ENOBUFS;
454 nlmsg_free(msg);
455 out:
456 cfg80211_put_dev(drv);
457 dev_put(dev);
458 return err;
459}
460
461static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
462{
463 struct cfg80211_registered_device *drv;
464 int err;
465 struct net_device *dev;
466 u8 key_idx;
467
468 if (!info->attrs[NL80211_ATTR_KEY_IDX])
469 return -EINVAL;
470
471 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
472
473 if (key_idx > 3)
474 return -EINVAL;
475
476 /* currently only support setting default key */
477 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT])
478 return -EINVAL;
479
480 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
481 if (err)
482 return err;
483
484 if (!drv->ops->set_default_key) {
485 err = -EOPNOTSUPP;
486 goto out;
487 }
488
489 rtnl_lock();
490 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx);
491 rtnl_unlock();
492
493 out:
494 cfg80211_put_dev(drv);
495 dev_put(dev);
496 return err;
497}
498
499static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
500{
501 struct cfg80211_registered_device *drv;
502 int err;
503 struct net_device *dev;
504 struct key_params params;
505 u8 key_idx = 0;
506 u8 *mac_addr = NULL;
507
508 memset(&params, 0, sizeof(params));
509
510 if (!info->attrs[NL80211_ATTR_KEY_CIPHER])
511 return -EINVAL;
512
513 if (info->attrs[NL80211_ATTR_KEY_DATA]) {
514 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]);
515 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]);
516 }
517
518 if (info->attrs[NL80211_ATTR_KEY_IDX])
519 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
520
521 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]);
522
523 if (info->attrs[NL80211_ATTR_MAC])
524 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
525
526 if (key_idx > 3)
527 return -EINVAL;
528
529 /*
530 * Disallow pairwise keys with non-zero index unless it's WEP
531 * (because current deployments use pairwise WEP keys with
532 * non-zero indizes but 802.11i clearly specifies to use zero)
533 */
534 if (mac_addr && key_idx &&
535 params.cipher != WLAN_CIPHER_SUITE_WEP40 &&
536 params.cipher != WLAN_CIPHER_SUITE_WEP104)
537 return -EINVAL;
538
539 /* TODO: add definitions for the lengths to linux/ieee80211.h */
540 switch (params.cipher) {
541 case WLAN_CIPHER_SUITE_WEP40:
542 if (params.key_len != 5)
543 return -EINVAL;
544 break;
545 case WLAN_CIPHER_SUITE_TKIP:
546 if (params.key_len != 32)
547 return -EINVAL;
548 break;
549 case WLAN_CIPHER_SUITE_CCMP:
550 if (params.key_len != 16)
551 return -EINVAL;
552 break;
553 case WLAN_CIPHER_SUITE_WEP104:
554 if (params.key_len != 13)
555 return -EINVAL;
556 break;
557 default:
558 return -EINVAL;
559 }
560
561 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
562 if (err)
563 return err;
564
565 if (!drv->ops->add_key) {
566 err = -EOPNOTSUPP;
567 goto out;
568 }
569
570 rtnl_lock();
571 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
572 rtnl_unlock();
573
574 out:
575 cfg80211_put_dev(drv);
576 dev_put(dev);
577 return err;
578}
579
580static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
581{
582 struct cfg80211_registered_device *drv;
583 int err;
584 struct net_device *dev;
585 u8 key_idx = 0;
586 u8 *mac_addr = NULL;
587
588 if (info->attrs[NL80211_ATTR_KEY_IDX])
589 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
590
591 if (key_idx > 3)
592 return -EINVAL;
593
594 if (info->attrs[NL80211_ATTR_MAC])
595 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
596
597 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
598 if (err)
599 return err;
600
601 if (!drv->ops->del_key) {
602 err = -EOPNOTSUPP;
603 goto out;
604 }
605
606 rtnl_lock();
607 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
608 rtnl_unlock();
609
610 out:
611 cfg80211_put_dev(drv);
612 dev_put(dev);
613 return err;
614}
615
616static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
617{
618 int (*call)(struct wiphy *wiphy, struct net_device *dev,
619 struct beacon_parameters *info);
620 struct cfg80211_registered_device *drv;
621 int err;
622 struct net_device *dev;
623 struct beacon_parameters params;
624 int haveinfo = 0;
625
626 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
627 if (err)
628 return err;
629
630 switch (info->genlhdr->cmd) {
631 case NL80211_CMD_NEW_BEACON:
632 /* these are required for NEW_BEACON */
633 if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
634 !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
635 !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
636 err = -EINVAL;
637 goto out;
638 }
639
640 call = drv->ops->add_beacon;
641 break;
642 case NL80211_CMD_SET_BEACON:
643 call = drv->ops->set_beacon;
644 break;
645 default:
646 WARN_ON(1);
647 err = -EOPNOTSUPP;
648 goto out;
649 }
650
651 if (!call) {
652 err = -EOPNOTSUPP;
653 goto out;
654 }
655
656 memset(&params, 0, sizeof(params));
657
658 if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
659 params.interval =
660 nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
661 haveinfo = 1;
662 }
663
664 if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
665 params.dtim_period =
666 nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
667 haveinfo = 1;
668 }
669
670 if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
671 params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
672 params.head_len =
673 nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
674 haveinfo = 1;
675 }
676
677 if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
678 params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
679 params.tail_len =
680 nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
681 haveinfo = 1;
682 }
683
684 if (!haveinfo) {
685 err = -EINVAL;
686 goto out;
687 }
688
689 rtnl_lock();
690 err = call(&drv->wiphy, dev, &params);
691 rtnl_unlock();
692
693 out:
694 cfg80211_put_dev(drv);
695 dev_put(dev);
696 return err;
697}
698
699static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
700{
701 struct cfg80211_registered_device *drv;
702 int err;
703 struct net_device *dev;
704
705 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
706 if (err)
707 return err;
708
709 if (!drv->ops->del_beacon) {
710 err = -EOPNOTSUPP;
711 goto out;
712 }
713
714 rtnl_lock();
715 err = drv->ops->del_beacon(&drv->wiphy, dev);
716 rtnl_unlock();
717
718 out:
719 cfg80211_put_dev(drv);
720 dev_put(dev);
721 return err;
722}
723
724static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
725 [NL80211_STA_FLAG_AUTHORIZED] = { .type = NLA_FLAG },
726 [NL80211_STA_FLAG_SHORT_PREAMBLE] = { .type = NLA_FLAG },
727 [NL80211_STA_FLAG_WME] = { .type = NLA_FLAG },
728};
729
730static int parse_station_flags(struct nlattr *nla, u32 *staflags)
731{
732 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
733 int flag;
734
735 *staflags = 0;
736
737 if (!nla)
738 return 0;
739
740 if (nla_parse_nested(flags, NL80211_STA_FLAG_MAX,
741 nla, sta_flags_policy))
742 return -EINVAL;
743
744 *staflags = STATION_FLAG_CHANGED;
745
746 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
747 if (flags[flag])
748 *staflags |= (1<<flag);
749
750 return 0;
751}
752
753static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
754 int flags, struct net_device *dev,
755 u8 *mac_addr, struct station_stats *stats)
756{
757 void *hdr;
758 struct nlattr *statsattr;
759
760 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
761 if (!hdr)
762 return -1;
763
764 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
765 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
766
767 statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
768 if (!statsattr)
769 goto nla_put_failure;
770 if (stats->filled & STATION_STAT_INACTIVE_TIME)
771 NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
772 stats->inactive_time);
773 if (stats->filled & STATION_STAT_RX_BYTES)
774 NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
775 stats->rx_bytes);
776 if (stats->filled & STATION_STAT_TX_BYTES)
777 NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
778 stats->tx_bytes);
779
780 nla_nest_end(msg, statsattr);
781
782 return genlmsg_end(msg, hdr);
783
784 nla_put_failure:
785 return genlmsg_cancel(msg, hdr);
786}
787
788
789static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
790{
791 struct cfg80211_registered_device *drv;
792 int err;
793 struct net_device *dev;
794 struct station_stats stats;
795 struct sk_buff *msg;
796 u8 *mac_addr = NULL;
797
798 memset(&stats, 0, sizeof(stats));
799
800 if (!info->attrs[NL80211_ATTR_MAC])
801 return -EINVAL;
802
803 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
804
805 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
806 if (err)
807 return err;
808
809 if (!drv->ops->get_station) {
810 err = -EOPNOTSUPP;
811 goto out;
812 }
813
814 rtnl_lock();
815 err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
816 rtnl_unlock();
817
818 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
819 if (!msg)
820 goto out;
821
822 if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
823 dev, mac_addr, &stats) < 0)
824 goto out_free;
825
826 err = genlmsg_unicast(msg, info->snd_pid);
827 goto out;
828
829 out_free:
830 nlmsg_free(msg);
831
832 out:
833 cfg80211_put_dev(drv);
834 dev_put(dev);
835 return err;
836}
837
838/*
839 * Get vlan interface making sure it is on the right wiphy.
840 */
841static int get_vlan(struct nlattr *vlanattr,
842 struct cfg80211_registered_device *rdev,
843 struct net_device **vlan)
844{
845 *vlan = NULL;
846
847 if (vlanattr) {
848 *vlan = dev_get_by_index(&init_net, nla_get_u32(vlanattr));
849 if (!*vlan)
850 return -ENODEV;
851 if (!(*vlan)->ieee80211_ptr)
852 return -EINVAL;
853 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
854 return -EINVAL;
855 }
856 return 0;
857}
858
859static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
860{
861 struct cfg80211_registered_device *drv;
862 int err;
863 struct net_device *dev;
864 struct station_parameters params;
865 u8 *mac_addr = NULL;
866
867 memset(&params, 0, sizeof(params));
868
869 params.listen_interval = -1;
870
871 if (info->attrs[NL80211_ATTR_STA_AID])
872 return -EINVAL;
873
874 if (!info->attrs[NL80211_ATTR_MAC])
875 return -EINVAL;
876
877 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
878
879 if (info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) {
880 params.supported_rates =
881 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
882 params.supported_rates_len =
883 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
884 }
885
886 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
887 params.listen_interval =
888 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
889
890 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
891 &params.station_flags))
892 return -EINVAL;
893
894 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
895 if (err)
896 return err;
897
898 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
899 if (err)
900 goto out;
901
902 if (!drv->ops->change_station) {
903 err = -EOPNOTSUPP;
904 goto out;
905 }
906
907 rtnl_lock();
908 err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
909 rtnl_unlock();
910
911 out:
912 if (params.vlan)
913 dev_put(params.vlan);
914 cfg80211_put_dev(drv);
915 dev_put(dev);
916 return err;
917}
918
919static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
920{
921 struct cfg80211_registered_device *drv;
922 int err;
923 struct net_device *dev;
924 struct station_parameters params;
925 u8 *mac_addr = NULL;
926
927 memset(&params, 0, sizeof(params));
928
929 if (!info->attrs[NL80211_ATTR_MAC])
930 return -EINVAL;
931
932 if (!info->attrs[NL80211_ATTR_STA_AID])
933 return -EINVAL;
934
935 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
936 return -EINVAL;
937
938 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])
939 return -EINVAL;
940
941 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
942 params.supported_rates =
943 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
944 params.supported_rates_len =
945 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
946 params.listen_interval =
947 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
948 params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
949
950 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS],
951 &params.station_flags))
952 return -EINVAL;
953
954 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
955 if (err)
956 return err;
957
958 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
959 if (err)
960 goto out;
961
962 if (!drv->ops->add_station) {
963 err = -EOPNOTSUPP;
964 goto out;
965 }
966
967 rtnl_lock();
968 err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
969 rtnl_unlock();
970
971 out:
972 if (params.vlan)
973 dev_put(params.vlan);
974 cfg80211_put_dev(drv);
975 dev_put(dev);
976 return err;
977}
978
979static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
980{
981 struct cfg80211_registered_device *drv;
982 int err;
983 struct net_device *dev;
984 u8 *mac_addr = NULL;
985
986 if (info->attrs[NL80211_ATTR_MAC])
987 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
988
989 err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
990 if (err)
991 return err;
992
993 if (!drv->ops->del_station) {
994 err = -EOPNOTSUPP;
995 goto out;
996 }
997
998 rtnl_lock();
999 err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
1000 rtnl_unlock();
1001
1002 out:
1003 cfg80211_put_dev(drv);
1004 dev_put(dev);
1005 return err;
1006}
1007
338static struct genl_ops nl80211_ops[] = { 1008static struct genl_ops nl80211_ops[] = {
339 { 1009 {
340 .cmd = NL80211_CMD_GET_WIPHY, 1010 .cmd = NL80211_CMD_GET_WIPHY,
@@ -374,6 +1044,73 @@ static struct genl_ops nl80211_ops[] = {
374 .policy = nl80211_policy, 1044 .policy = nl80211_policy,
375 .flags = GENL_ADMIN_PERM, 1045 .flags = GENL_ADMIN_PERM,
376 }, 1046 },
1047 {
1048 .cmd = NL80211_CMD_GET_KEY,
1049 .doit = nl80211_get_key,
1050 .policy = nl80211_policy,
1051 .flags = GENL_ADMIN_PERM,
1052 },
1053 {
1054 .cmd = NL80211_CMD_SET_KEY,
1055 .doit = nl80211_set_key,
1056 .policy = nl80211_policy,
1057 .flags = GENL_ADMIN_PERM,
1058 },
1059 {
1060 .cmd = NL80211_CMD_NEW_KEY,
1061 .doit = nl80211_new_key,
1062 .policy = nl80211_policy,
1063 .flags = GENL_ADMIN_PERM,
1064 },
1065 {
1066 .cmd = NL80211_CMD_DEL_KEY,
1067 .doit = nl80211_del_key,
1068 .policy = nl80211_policy,
1069 .flags = GENL_ADMIN_PERM,
1070 },
1071 {
1072 .cmd = NL80211_CMD_SET_BEACON,
1073 .policy = nl80211_policy,
1074 .flags = GENL_ADMIN_PERM,
1075 .doit = nl80211_addset_beacon,
1076 },
1077 {
1078 .cmd = NL80211_CMD_NEW_BEACON,
1079 .policy = nl80211_policy,
1080 .flags = GENL_ADMIN_PERM,
1081 .doit = nl80211_addset_beacon,
1082 },
1083 {
1084 .cmd = NL80211_CMD_DEL_BEACON,
1085 .policy = nl80211_policy,
1086 .flags = GENL_ADMIN_PERM,
1087 .doit = nl80211_del_beacon,
1088 },
1089 {
1090 .cmd = NL80211_CMD_GET_STATION,
1091 .doit = nl80211_get_station,
1092 /* TODO: implement dumpit */
1093 .policy = nl80211_policy,
1094 .flags = GENL_ADMIN_PERM,
1095 },
1096 {
1097 .cmd = NL80211_CMD_SET_STATION,
1098 .doit = nl80211_set_station,
1099 .policy = nl80211_policy,
1100 .flags = GENL_ADMIN_PERM,
1101 },
1102 {
1103 .cmd = NL80211_CMD_NEW_STATION,
1104 .doit = nl80211_new_station,
1105 .policy = nl80211_policy,
1106 .flags = GENL_ADMIN_PERM,
1107 },
1108 {
1109 .cmd = NL80211_CMD_DEL_STATION,
1110 .doit = nl80211_del_station,
1111 .policy = nl80211_policy,
1112 .flags = GENL_ADMIN_PERM,
1113 },
377}; 1114};
378 1115
379/* multicast groups */ 1116/* multicast groups */
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index 47e80cc2077c..2c569b63e7d8 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -417,20 +417,6 @@ static const int event_type_size[] = {
417 IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ 417 IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
418}; 418};
419 419
420/* Size (in bytes) of various events, as packed */
421static const int event_type_pk_size[] = {
422 IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */
423 0,
424 IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */
425 0,
426 IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */
427 IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */
428 IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */
429 0,
430 IW_EV_POINT_PK_LEN, /* Without variable payload */
431 IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */
432 IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */
433};
434 420
435/************************ COMMON SUBROUTINES ************************/ 421/************************ COMMON SUBROUTINES ************************/
436/* 422/*
@@ -673,26 +659,8 @@ static const struct seq_operations wireless_seq_ops = {
673 659
674static int wireless_seq_open(struct inode *inode, struct file *file) 660static int wireless_seq_open(struct inode *inode, struct file *file)
675{ 661{
676 struct seq_file *seq; 662 return seq_open_net(inode, file, &wireless_seq_ops,
677 int res; 663 sizeof(struct seq_net_private));
678 res = seq_open(file, &wireless_seq_ops);
679 if (!res) {
680 seq = file->private_data;
681 seq->private = get_proc_net(inode);
682 if (!seq->private) {
683 seq_release(inode, file);
684 res = -ENXIO;
685 }
686 }
687 return res;
688}
689
690static int wireless_seq_release(struct inode *inode, struct file *file)
691{
692 struct seq_file *seq = file->private_data;
693 struct net *net = seq->private;
694 put_net(net);
695 return seq_release(inode, file);
696} 664}
697 665
698static const struct file_operations wireless_seq_fops = { 666static const struct file_operations wireless_seq_fops = {
@@ -700,7 +668,7 @@ static const struct file_operations wireless_seq_fops = {
700 .open = wireless_seq_open, 668 .open = wireless_seq_open,
701 .read = seq_read, 669 .read = seq_read,
702 .llseek = seq_lseek, 670 .llseek = seq_lseek,
703 .release = wireless_seq_release, 671 .release = seq_release_net,
704}; 672};
705 673
706int wext_proc_init(struct net *net) 674int wext_proc_init(struct net *net)
@@ -1137,7 +1105,7 @@ static void wireless_nlevent_process(unsigned long data)
1137 struct sk_buff *skb; 1105 struct sk_buff *skb;
1138 1106
1139 while ((skb = skb_dequeue(&wireless_nlevent_queue))) 1107 while ((skb = skb_dequeue(&wireless_nlevent_queue)))
1140 rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 1108 rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
1141} 1109}
1142 1110
1143static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); 1111static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
@@ -1189,6 +1157,9 @@ static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
1189 struct sk_buff *skb; 1157 struct sk_buff *skb;
1190 int err; 1158 int err;
1191 1159
1160 if (dev->nd_net != &init_net)
1161 return;
1162
1192 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1163 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1193 if (!skb) 1164 if (!skb)
1194 return; 1165 return;