diff options
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 090936388528..306ae019ea81 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -69,6 +69,13 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
69 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, | 69 | [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, |
70 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, | 70 | [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, |
71 | [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, | 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 }, | ||
72 | }; | 79 | }; |
73 | 80 | ||
74 | /* message building helper */ | 81 | /* message building helper */ |
@@ -600,6 +607,114 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
600 | return err; | 607 | return err; |
601 | } | 608 | } |
602 | 609 | ||
610 | static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | ||
611 | { | ||
612 | int (*call)(struct wiphy *wiphy, struct net_device *dev, | ||
613 | struct beacon_parameters *info); | ||
614 | struct cfg80211_registered_device *drv; | ||
615 | int err; | ||
616 | struct net_device *dev; | ||
617 | struct beacon_parameters params; | ||
618 | int haveinfo = 0; | ||
619 | |||
620 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | ||
621 | if (err) | ||
622 | return err; | ||
623 | |||
624 | switch (info->genlhdr->cmd) { | ||
625 | case NL80211_CMD_NEW_BEACON: | ||
626 | /* these are required for NEW_BEACON */ | ||
627 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || | ||
628 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || | ||
629 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) { | ||
630 | err = -EINVAL; | ||
631 | goto out; | ||
632 | } | ||
633 | |||
634 | call = drv->ops->add_beacon; | ||
635 | break; | ||
636 | case NL80211_CMD_SET_BEACON: | ||
637 | call = drv->ops->set_beacon; | ||
638 | break; | ||
639 | default: | ||
640 | WARN_ON(1); | ||
641 | err = -EOPNOTSUPP; | ||
642 | goto out; | ||
643 | } | ||
644 | |||
645 | if (!call) { | ||
646 | err = -EOPNOTSUPP; | ||
647 | goto out; | ||
648 | } | ||
649 | |||
650 | memset(¶ms, 0, sizeof(params)); | ||
651 | |||
652 | if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { | ||
653 | params.interval = | ||
654 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); | ||
655 | haveinfo = 1; | ||
656 | } | ||
657 | |||
658 | if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) { | ||
659 | params.dtim_period = | ||
660 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); | ||
661 | haveinfo = 1; | ||
662 | } | ||
663 | |||
664 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { | ||
665 | params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); | ||
666 | params.head_len = | ||
667 | nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); | ||
668 | haveinfo = 1; | ||
669 | } | ||
670 | |||
671 | if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { | ||
672 | params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); | ||
673 | params.tail_len = | ||
674 | nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); | ||
675 | haveinfo = 1; | ||
676 | } | ||
677 | |||
678 | if (!haveinfo) { | ||
679 | err = -EINVAL; | ||
680 | goto out; | ||
681 | } | ||
682 | |||
683 | rtnl_lock(); | ||
684 | err = call(&drv->wiphy, dev, ¶ms); | ||
685 | rtnl_unlock(); | ||
686 | |||
687 | out: | ||
688 | cfg80211_put_dev(drv); | ||
689 | dev_put(dev); | ||
690 | return err; | ||
691 | } | ||
692 | |||
693 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | ||
694 | { | ||
695 | struct cfg80211_registered_device *drv; | ||
696 | int err; | ||
697 | struct net_device *dev; | ||
698 | |||
699 | err = get_drv_dev_by_info_ifindex(info, &drv, &dev); | ||
700 | if (err) | ||
701 | return err; | ||
702 | |||
703 | if (!drv->ops->del_beacon) { | ||
704 | err = -EOPNOTSUPP; | ||
705 | goto out; | ||
706 | } | ||
707 | |||
708 | rtnl_lock(); | ||
709 | err = drv->ops->del_beacon(&drv->wiphy, dev); | ||
710 | rtnl_unlock(); | ||
711 | |||
712 | out: | ||
713 | cfg80211_put_dev(drv); | ||
714 | dev_put(dev); | ||
715 | return err; | ||
716 | } | ||
717 | |||
603 | static struct genl_ops nl80211_ops[] = { | 718 | static struct genl_ops nl80211_ops[] = { |
604 | { | 719 | { |
605 | .cmd = NL80211_CMD_GET_WIPHY, | 720 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -663,6 +778,24 @@ static struct genl_ops nl80211_ops[] = { | |||
663 | .policy = nl80211_policy, | 778 | .policy = nl80211_policy, |
664 | .flags = GENL_ADMIN_PERM, | 779 | .flags = GENL_ADMIN_PERM, |
665 | }, | 780 | }, |
781 | { | ||
782 | .cmd = NL80211_CMD_SET_BEACON, | ||
783 | .policy = nl80211_policy, | ||
784 | .flags = GENL_ADMIN_PERM, | ||
785 | .doit = nl80211_addset_beacon, | ||
786 | }, | ||
787 | { | ||
788 | .cmd = NL80211_CMD_NEW_BEACON, | ||
789 | .policy = nl80211_policy, | ||
790 | .flags = GENL_ADMIN_PERM, | ||
791 | .doit = nl80211_addset_beacon, | ||
792 | }, | ||
793 | { | ||
794 | .cmd = NL80211_CMD_DEL_BEACON, | ||
795 | .policy = nl80211_policy, | ||
796 | .flags = GENL_ADMIN_PERM, | ||
797 | .doit = nl80211_del_beacon, | ||
798 | }, | ||
666 | }; | 799 | }; |
667 | 800 | ||
668 | /* multicast groups */ | 801 | /* multicast groups */ |