aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h24
-rw-r--r--include/net/cfg80211.h33
-rw-r--r--net/wireless/nl80211.c133
3 files changed, 190 insertions, 0 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 8dc807d9c29a..f1e455a8b4de 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -47,6 +47,15 @@
47 * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX 47 * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
48 * or %NL80211_ATTR_MAC. 48 * or %NL80211_ATTR_MAC.
49 * 49 *
50 * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a
51 * %NL80222_CMD_NEW_BEACON message)
52 * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface
53 * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD,
54 * %NL80211_BEACON_HEAD and %NL80211_BEACON_TAIL attributes.
55 * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface,
56 * parameters are like for %NL80211_CMD_SET_BEACON.
57 * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it
58 *
50 * @NL80211_CMD_MAX: highest used command number 59 * @NL80211_CMD_MAX: highest used command number
51 * @__NL80211_CMD_AFTER_LAST: internal use 60 * @__NL80211_CMD_AFTER_LAST: internal use
52 */ 61 */
@@ -69,6 +78,11 @@ enum nl80211_commands {
69 NL80211_CMD_NEW_KEY, 78 NL80211_CMD_NEW_KEY,
70 NL80211_CMD_DEL_KEY, 79 NL80211_CMD_DEL_KEY,
71 80
81 NL80211_CMD_GET_BEACON,
82 NL80211_CMD_SET_BEACON,
83 NL80211_CMD_NEW_BEACON,
84 NL80211_CMD_DEL_BEACON,
85
72 /* add commands here */ 86 /* add commands here */
73 87
74 /* used to define NL80211_CMD_MAX below */ 88 /* used to define NL80211_CMD_MAX below */
@@ -101,6 +115,11 @@ enum nl80211_commands {
101 * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and 115 * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
102 * CCMP keys, each six bytes in little endian 116 * CCMP keys, each six bytes in little endian
103 * 117 *
118 * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU
119 * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing
120 * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE
121 * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE
122 *
104 * @NL80211_ATTR_MAX: highest attribute number currently defined 123 * @NL80211_ATTR_MAX: highest attribute number currently defined
105 * @__NL80211_ATTR_AFTER_LAST: internal use 124 * @__NL80211_ATTR_AFTER_LAST: internal use
106 */ 125 */
@@ -123,6 +142,11 @@ enum nl80211_attrs {
123 NL80211_ATTR_KEY_SEQ, 142 NL80211_ATTR_KEY_SEQ,
124 NL80211_ATTR_KEY_DEFAULT, 143 NL80211_ATTR_KEY_DEFAULT,
125 144
145 NL80211_ATTR_BEACON_INTERVAL,
146 NL80211_ATTR_DTIM_PERIOD,
147 NL80211_ATTR_BEACON_HEAD,
148 NL80211_ATTR_BEACON_TAIL,
149
126 /* add attributes here, update the policy in nl80211.c */ 150 /* add attributes here, update the policy in nl80211.c */
127 151
128 __NL80211_ATTR_AFTER_LAST, 152 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3db7dfa53b6f..fc94852e967b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -69,6 +69,26 @@ struct key_params {
69 u32 cipher; 69 u32 cipher;
70}; 70};
71 71
72/**
73 * struct beacon_parameters - beacon parameters
74 *
75 * Used to configure the beacon for an interface.
76 *
77 * @head: head portion of beacon (before TIM IE)
78 * or %NULL if not changed
79 * @tail: tail portion of beacon (after TIM IE)
80 * or %NULL if not changed
81 * @interval: beacon interval or zero if not changed
82 * @dtim_period: DTIM period or zero if not changed
83 * @head_len: length of @head
84 * @tail_len: length of @tail
85 */
86struct beacon_parameters {
87 u8 *head, *tail;
88 int interval, dtim_period;
89 int head_len, tail_len;
90};
91
72/* from net/wireless.h */ 92/* from net/wireless.h */
73struct wiphy; 93struct wiphy;
74 94
@@ -103,6 +123,13 @@ struct wiphy;
103 * and @key_index 123 * and @key_index
104 * 124 *
105 * @set_default_key: set the default key on an interface 125 * @set_default_key: set the default key on an interface
126 *
127 * @add_beacon: Add a beacon with given parameters, @head, @interval
128 * and @dtim_period will be valid, @tail is optional.
129 * @set_beacon: Change the beacon parameters for an access point mode
130 * interface. This should reject the call when no beacon has been
131 * configured.
132 * @del_beacon: Remove beacon configuration and stop sending the beacon.
106 */ 133 */
107struct cfg80211_ops { 134struct cfg80211_ops {
108 int (*add_virtual_intf)(struct wiphy *wiphy, char *name, 135 int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
@@ -122,6 +149,12 @@ struct cfg80211_ops {
122 int (*set_default_key)(struct wiphy *wiphy, 149 int (*set_default_key)(struct wiphy *wiphy,
123 struct net_device *netdev, 150 struct net_device *netdev,
124 u8 key_index); 151 u8 key_index);
152
153 int (*add_beacon)(struct wiphy *wiphy, struct net_device *dev,
154 struct beacon_parameters *info);
155 int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev,
156 struct beacon_parameters *info);
157 int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev);
125}; 158};
126 159
127#endif /* __NET_CFG80211_H */ 160#endif /* __NET_CFG80211_H */
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
610static 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(&params, 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, &params);
685 rtnl_unlock();
686
687 out:
688 cfg80211_put_dev(drv);
689 dev_put(dev);
690 return err;
691}
692
693static 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
603static struct genl_ops nl80211_ops[] = { 718static 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 */