forked from mirrors/linux
		
	cfg80211/nl80211: add beacon settings
This adds the necessary API to cfg80211/nl80211 to allow changing beaconing settings. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									62da92fb75
								
							
						
					
					
						commit
						ed1b6cc7f8
					
				
					 3 changed files with 190 additions and 0 deletions
				
			
		| 
						 | 
					@ -47,6 +47,15 @@
 | 
				
			||||||
 * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
 | 
					 * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
 | 
				
			||||||
 *	or %NL80211_ATTR_MAC.
 | 
					 *	or %NL80211_ATTR_MAC.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a
 | 
				
			||||||
 | 
					 *	%NL80222_CMD_NEW_BEACON message)
 | 
				
			||||||
 | 
					 * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface
 | 
				
			||||||
 | 
					 *	using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD,
 | 
				
			||||||
 | 
					 *	%NL80211_BEACON_HEAD and %NL80211_BEACON_TAIL attributes.
 | 
				
			||||||
 | 
					 * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface,
 | 
				
			||||||
 | 
					 *	parameters are like for %NL80211_CMD_SET_BEACON.
 | 
				
			||||||
 | 
					 * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * @NL80211_CMD_MAX: highest used command number
 | 
					 * @NL80211_CMD_MAX: highest used command number
 | 
				
			||||||
 * @__NL80211_CMD_AFTER_LAST: internal use
 | 
					 * @__NL80211_CMD_AFTER_LAST: internal use
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -69,6 +78,11 @@ enum nl80211_commands {
 | 
				
			||||||
	NL80211_CMD_NEW_KEY,
 | 
						NL80211_CMD_NEW_KEY,
 | 
				
			||||||
	NL80211_CMD_DEL_KEY,
 | 
						NL80211_CMD_DEL_KEY,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL80211_CMD_GET_BEACON,
 | 
				
			||||||
 | 
						NL80211_CMD_SET_BEACON,
 | 
				
			||||||
 | 
						NL80211_CMD_NEW_BEACON,
 | 
				
			||||||
 | 
						NL80211_CMD_DEL_BEACON,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* add commands here */
 | 
						/* add commands here */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* used to define NL80211_CMD_MAX below */
 | 
						/* used to define NL80211_CMD_MAX below */
 | 
				
			||||||
| 
						 | 
					@ -101,6 +115,11 @@ enum nl80211_commands {
 | 
				
			||||||
 * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
 | 
					 * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and
 | 
				
			||||||
 *	CCMP keys, each six bytes in little endian
 | 
					 *	CCMP keys, each six bytes in little endian
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU
 | 
				
			||||||
 | 
					 * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing
 | 
				
			||||||
 | 
					 * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE
 | 
				
			||||||
 | 
					 * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * @NL80211_ATTR_MAX: highest attribute number currently defined
 | 
					 * @NL80211_ATTR_MAX: highest attribute number currently defined
 | 
				
			||||||
 * @__NL80211_ATTR_AFTER_LAST: internal use
 | 
					 * @__NL80211_ATTR_AFTER_LAST: internal use
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -123,6 +142,11 @@ enum nl80211_attrs {
 | 
				
			||||||
	NL80211_ATTR_KEY_SEQ,
 | 
						NL80211_ATTR_KEY_SEQ,
 | 
				
			||||||
	NL80211_ATTR_KEY_DEFAULT,
 | 
						NL80211_ATTR_KEY_DEFAULT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL80211_ATTR_BEACON_INTERVAL,
 | 
				
			||||||
 | 
						NL80211_ATTR_DTIM_PERIOD,
 | 
				
			||||||
 | 
						NL80211_ATTR_BEACON_HEAD,
 | 
				
			||||||
 | 
						NL80211_ATTR_BEACON_TAIL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* add attributes here, update the policy in nl80211.c */
 | 
						/* add attributes here, update the policy in nl80211.c */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	__NL80211_ATTR_AFTER_LAST,
 | 
						__NL80211_ATTR_AFTER_LAST,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,26 @@ struct key_params {
 | 
				
			||||||
	u32 cipher;
 | 
						u32 cipher;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct beacon_parameters - beacon parameters
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Used to configure the beacon for an interface.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @head: head portion of beacon (before TIM IE)
 | 
				
			||||||
 | 
					 *     or %NULL if not changed
 | 
				
			||||||
 | 
					 * @tail: tail portion of beacon (after TIM IE)
 | 
				
			||||||
 | 
					 *     or %NULL if not changed
 | 
				
			||||||
 | 
					 * @interval: beacon interval or zero if not changed
 | 
				
			||||||
 | 
					 * @dtim_period: DTIM period or zero if not changed
 | 
				
			||||||
 | 
					 * @head_len: length of @head
 | 
				
			||||||
 | 
					 * @tail_len: length of @tail
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct beacon_parameters {
 | 
				
			||||||
 | 
						u8 *head, *tail;
 | 
				
			||||||
 | 
						int interval, dtim_period;
 | 
				
			||||||
 | 
						int head_len, tail_len;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* from net/wireless.h */
 | 
					/* from net/wireless.h */
 | 
				
			||||||
struct wiphy;
 | 
					struct wiphy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,6 +123,13 @@ struct wiphy;
 | 
				
			||||||
 *	and @key_index
 | 
					 *	and @key_index
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @set_default_key: set the default key on an interface
 | 
					 * @set_default_key: set the default key on an interface
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @add_beacon: Add a beacon with given parameters, @head, @interval
 | 
				
			||||||
 | 
					 *	and @dtim_period will be valid, @tail is optional.
 | 
				
			||||||
 | 
					 * @set_beacon: Change the beacon parameters for an access point mode
 | 
				
			||||||
 | 
					 *	interface. This should reject the call when no beacon has been
 | 
				
			||||||
 | 
					 *	configured.
 | 
				
			||||||
 | 
					 * @del_beacon: Remove beacon configuration and stop sending the beacon.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct cfg80211_ops {
 | 
					struct cfg80211_ops {
 | 
				
			||||||
	int	(*add_virtual_intf)(struct wiphy *wiphy, char *name,
 | 
						int	(*add_virtual_intf)(struct wiphy *wiphy, char *name,
 | 
				
			||||||
| 
						 | 
					@ -122,6 +149,12 @@ struct cfg80211_ops {
 | 
				
			||||||
	int	(*set_default_key)(struct wiphy *wiphy,
 | 
						int	(*set_default_key)(struct wiphy *wiphy,
 | 
				
			||||||
				   struct net_device *netdev,
 | 
									   struct net_device *netdev,
 | 
				
			||||||
				   u8 key_index);
 | 
									   u8 key_index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int	(*add_beacon)(struct wiphy *wiphy, struct net_device *dev,
 | 
				
			||||||
 | 
								      struct beacon_parameters *info);
 | 
				
			||||||
 | 
						int	(*set_beacon)(struct wiphy *wiphy, struct net_device *dev,
 | 
				
			||||||
 | 
								      struct beacon_parameters *info);
 | 
				
			||||||
 | 
						int	(*del_beacon)(struct wiphy *wiphy, struct net_device *dev);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __NET_CFG80211_H */
 | 
					#endif /* __NET_CFG80211_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,13 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
 | 
				
			||||||
	[NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
 | 
						[NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
 | 
				
			||||||
	[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
 | 
						[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
 | 
				
			||||||
	[NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
 | 
						[NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[NL80211_ATTR_BEACON_HEAD] = { .type = NLA_BINARY,
 | 
				
			||||||
 | 
									       .len = IEEE80211_MAX_DATA_LEN },
 | 
				
			||||||
 | 
						[NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
 | 
				
			||||||
 | 
									       .len = IEEE80211_MAX_DATA_LEN },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* message building helper */
 | 
					/* message building helper */
 | 
				
			||||||
| 
						 | 
					@ -600,6 +607,114 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        int (*call)(struct wiphy *wiphy, struct net_device *dev,
 | 
				
			||||||
 | 
							    struct beacon_parameters *info);
 | 
				
			||||||
 | 
						struct cfg80211_registered_device *drv;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
						struct beacon_parameters params;
 | 
				
			||||||
 | 
						int haveinfo = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (info->genlhdr->cmd) {
 | 
				
			||||||
 | 
						case NL80211_CMD_NEW_BEACON:
 | 
				
			||||||
 | 
							/* these are required for NEW_BEACON */
 | 
				
			||||||
 | 
							if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
 | 
				
			||||||
 | 
							    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
 | 
				
			||||||
 | 
							    !info->attrs[NL80211_ATTR_BEACON_HEAD]) {
 | 
				
			||||||
 | 
								err = -EINVAL;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							call = drv->ops->add_beacon;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case NL80211_CMD_SET_BEACON:
 | 
				
			||||||
 | 
							call = drv->ops->set_beacon;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							WARN_ON(1);
 | 
				
			||||||
 | 
							err = -EOPNOTSUPP;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!call) {
 | 
				
			||||||
 | 
							err = -EOPNOTSUPP;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(¶ms, 0, sizeof(params));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
 | 
				
			||||||
 | 
							params.interval =
 | 
				
			||||||
 | 
							    nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
 | 
				
			||||||
 | 
							haveinfo = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
 | 
				
			||||||
 | 
							params.dtim_period =
 | 
				
			||||||
 | 
							    nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
 | 
				
			||||||
 | 
							haveinfo = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[NL80211_ATTR_BEACON_HEAD]) {
 | 
				
			||||||
 | 
							params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]);
 | 
				
			||||||
 | 
							params.head_len =
 | 
				
			||||||
 | 
							    nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]);
 | 
				
			||||||
 | 
							haveinfo = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[NL80211_ATTR_BEACON_TAIL]) {
 | 
				
			||||||
 | 
							params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]);
 | 
				
			||||||
 | 
							params.tail_len =
 | 
				
			||||||
 | 
							    nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]);
 | 
				
			||||||
 | 
							haveinfo = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!haveinfo) {
 | 
				
			||||||
 | 
							err = -EINVAL;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rtnl_lock();
 | 
				
			||||||
 | 
						err = call(&drv->wiphy, dev, ¶ms);
 | 
				
			||||||
 | 
						rtnl_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 out:
 | 
				
			||||||
 | 
						cfg80211_put_dev(drv);
 | 
				
			||||||
 | 
						dev_put(dev);
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cfg80211_registered_device *drv;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
						struct net_device *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!drv->ops->del_beacon) {
 | 
				
			||||||
 | 
							err = -EOPNOTSUPP;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rtnl_lock();
 | 
				
			||||||
 | 
						err = drv->ops->del_beacon(&drv->wiphy, dev);
 | 
				
			||||||
 | 
						rtnl_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 out:
 | 
				
			||||||
 | 
						cfg80211_put_dev(drv);
 | 
				
			||||||
 | 
						dev_put(dev);
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct genl_ops nl80211_ops[] = {
 | 
					static struct genl_ops nl80211_ops[] = {
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		.cmd = NL80211_CMD_GET_WIPHY,
 | 
							.cmd = NL80211_CMD_GET_WIPHY,
 | 
				
			||||||
| 
						 | 
					@ -663,6 +778,24 @@ static struct genl_ops nl80211_ops[] = {
 | 
				
			||||||
		.policy = nl80211_policy,
 | 
							.policy = nl80211_policy,
 | 
				
			||||||
		.flags = GENL_ADMIN_PERM,
 | 
							.flags = GENL_ADMIN_PERM,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.cmd = NL80211_CMD_SET_BEACON,
 | 
				
			||||||
 | 
							.policy = nl80211_policy,
 | 
				
			||||||
 | 
							.flags = GENL_ADMIN_PERM,
 | 
				
			||||||
 | 
							.doit = nl80211_addset_beacon,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.cmd = NL80211_CMD_NEW_BEACON,
 | 
				
			||||||
 | 
							.policy = nl80211_policy,
 | 
				
			||||||
 | 
							.flags = GENL_ADMIN_PERM,
 | 
				
			||||||
 | 
							.doit = nl80211_addset_beacon,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.cmd = NL80211_CMD_DEL_BEACON,
 | 
				
			||||||
 | 
							.policy = nl80211_policy,
 | 
				
			||||||
 | 
							.flags = GENL_ADMIN_PERM,
 | 
				
			||||||
 | 
							.doit = nl80211_del_beacon,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* multicast groups */
 | 
					/* multicast groups */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue