mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	cfg80211/nl80211: separate unicast/multicast default TX keys
Allow userspace to specify that a given key is default only for unicast and/or multicast transmissions. Only WEP keys are for both, WPA/RSN keys set here are GTKs for multicast only. For more future flexibility, allow to specify all combiations. Wireless extensions can only set both so use nl80211; WEP keys (connect keys) must be set as default for both (but 802.1X WEP is still possible). Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
		
							parent
							
								
									897bed8b43
								
							
						
					
					
						commit
						dbd2fd656f
					
				
					 9 changed files with 153 additions and 30 deletions
				
			
		| 
						 | 
					@ -225,7 +225,8 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
 | 
					static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
 | 
				
			||||||
					struct net_device *ndev,
 | 
										struct net_device *ndev,
 | 
				
			||||||
					u8 key_index)
 | 
										u8 key_index, bool unicast,
 | 
				
			||||||
 | 
										bool multicast)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct iwm_priv *iwm = ndev_to_iwm(ndev);
 | 
						struct iwm_priv *iwm = ndev_to_iwm(ndev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1422,7 +1422,8 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int lbs_cfg_set_default_key(struct wiphy *wiphy,
 | 
					static int lbs_cfg_set_default_key(struct wiphy *wiphy,
 | 
				
			||||||
				   struct net_device *netdev,
 | 
									   struct net_device *netdev,
 | 
				
			||||||
				   u8 key_index)
 | 
									   u8 key_index, bool unicast,
 | 
				
			||||||
 | 
									   bool multicast)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct lbs_private *priv = wiphy_priv(wiphy);
 | 
						struct lbs_private *priv = wiphy_priv(wiphy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -554,7 +554,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
 | 
				
			||||||
			 u8 key_index, bool pairwise, const u8 *mac_addr);
 | 
								 u8 key_index, bool pairwise, const u8 *mac_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 | 
					static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 | 
				
			||||||
								u8 key_index);
 | 
									 u8 key_index, bool unicast, bool multicast);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
 | 
					static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
 | 
				
			||||||
					u8 *mac, struct station_info *sinfo);
 | 
										u8 *mac, struct station_info *sinfo);
 | 
				
			||||||
| 
						 | 
					@ -2381,7 +2381,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 | 
					static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 | 
				
			||||||
								u8 key_index)
 | 
									 u8 key_index, bool unicast, bool multicast)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 | 
						struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 | 
				
			||||||
	struct usbnet *usbdev = priv->usbdev;
 | 
						struct usbnet *usbdev = priv->usbdev;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -851,6 +851,10 @@ enum nl80211_commands {
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16)
 | 
					 * @NL80211_ATTR_BSS_HTOPMODE: HT operation mode (u16)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags
 | 
				
			||||||
 | 
					 *	attributes, specifying what a key should be set as default as.
 | 
				
			||||||
 | 
					 *	See &enum nl80211_key_default_types.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * @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
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -1029,6 +1033,8 @@ enum nl80211_attrs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NL80211_ATTR_BSS_HT_OPMODE,
 | 
						NL80211_ATTR_BSS_HT_OPMODE,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NL80211_ATTR_KEY_DEFAULT_TYPES,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* 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,
 | 
				
			||||||
| 
						 | 
					@ -1774,6 +1780,23 @@ enum nl80211_wpa_versions {
 | 
				
			||||||
	NL80211_WPA_VERSION_2 = 1 << 1,
 | 
						NL80211_WPA_VERSION_2 = 1 << 1,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * enum nl80211_key_default_types - key default types
 | 
				
			||||||
 | 
					 * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid
 | 
				
			||||||
 | 
					 * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default
 | 
				
			||||||
 | 
					 *	unicast key
 | 
				
			||||||
 | 
					 * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default
 | 
				
			||||||
 | 
					 *	multicast key
 | 
				
			||||||
 | 
					 * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum nl80211_key_default_types {
 | 
				
			||||||
 | 
						__NL80211_KEY_DEFAULT_TYPE_INVALID,
 | 
				
			||||||
 | 
						NL80211_KEY_DEFAULT_TYPE_UNICAST,
 | 
				
			||||||
 | 
						NL80211_KEY_DEFAULT_TYPE_MULTICAST,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NUM_NL80211_KEY_DEFAULT_TYPES
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * enum nl80211_key_attributes - key attributes
 | 
					 * enum nl80211_key_attributes - key attributes
 | 
				
			||||||
 * @__NL80211_KEY_INVALID: invalid
 | 
					 * @__NL80211_KEY_INVALID: invalid
 | 
				
			||||||
| 
						 | 
					@ -1790,6 +1813,9 @@ enum nl80211_wpa_versions {
 | 
				
			||||||
 * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not
 | 
					 * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not
 | 
				
			||||||
 *	specified the default depends on whether a MAC address was
 | 
					 *	specified the default depends on whether a MAC address was
 | 
				
			||||||
 *	given with the command using the key or not (u32)
 | 
					 *	given with the command using the key or not (u32)
 | 
				
			||||||
 | 
					 * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags
 | 
				
			||||||
 | 
					 *	attributes, specifying what a key should be set as default as.
 | 
				
			||||||
 | 
					 *	See &enum nl80211_key_default_types.
 | 
				
			||||||
 * @__NL80211_KEY_AFTER_LAST: internal
 | 
					 * @__NL80211_KEY_AFTER_LAST: internal
 | 
				
			||||||
 * @NL80211_KEY_MAX: highest key attribute
 | 
					 * @NL80211_KEY_MAX: highest key attribute
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -1802,6 +1828,7 @@ enum nl80211_key_attributes {
 | 
				
			||||||
	NL80211_KEY_DEFAULT,
 | 
						NL80211_KEY_DEFAULT,
 | 
				
			||||||
	NL80211_KEY_DEFAULT_MGMT,
 | 
						NL80211_KEY_DEFAULT_MGMT,
 | 
				
			||||||
	NL80211_KEY_TYPE,
 | 
						NL80211_KEY_TYPE,
 | 
				
			||||||
 | 
						NL80211_KEY_DEFAULT_TYPES,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* keep last */
 | 
						/* keep last */
 | 
				
			||||||
	__NL80211_KEY_AFTER_LAST,
 | 
						__NL80211_KEY_AFTER_LAST,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1211,7 +1211,7 @@ struct cfg80211_ops {
 | 
				
			||||||
			   u8 key_index, bool pairwise, const u8 *mac_addr);
 | 
								   u8 key_index, bool pairwise, const u8 *mac_addr);
 | 
				
			||||||
	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, bool unicast, bool multicast);
 | 
				
			||||||
	int	(*set_default_mgmt_key)(struct wiphy *wiphy,
 | 
						int	(*set_default_mgmt_key)(struct wiphy *wiphy,
 | 
				
			||||||
					struct net_device *netdev,
 | 
										struct net_device *netdev,
 | 
				
			||||||
					u8 key_index);
 | 
										u8 key_index);
 | 
				
			||||||
| 
						 | 
					@ -1393,6 +1393,8 @@ struct cfg80211_ops {
 | 
				
			||||||
 *	control port protocol ethertype. The device also honours the
 | 
					 *	control port protocol ethertype. The device also honours the
 | 
				
			||||||
 *	control_port_no_encrypt flag.
 | 
					 *	control_port_no_encrypt flag.
 | 
				
			||||||
 * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
 | 
					 * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
 | 
				
			||||||
 | 
					 * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate
 | 
				
			||||||
 | 
					 *	unicast and multicast TX keys.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
enum wiphy_flags {
 | 
					enum wiphy_flags {
 | 
				
			||||||
	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
 | 
						WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
 | 
				
			||||||
| 
						 | 
					@ -1404,6 +1406,7 @@ enum wiphy_flags {
 | 
				
			||||||
	WIPHY_FLAG_4ADDR_STATION		= BIT(6),
 | 
						WIPHY_FLAG_4ADDR_STATION		= BIT(6),
 | 
				
			||||||
	WIPHY_FLAG_CONTROL_PORT_PROTOCOL	= BIT(7),
 | 
						WIPHY_FLAG_CONTROL_PORT_PROTOCOL	= BIT(7),
 | 
				
			||||||
	WIPHY_FLAG_IBSS_RSN			= BIT(8),
 | 
						WIPHY_FLAG_IBSS_RSN			= BIT(8),
 | 
				
			||||||
 | 
						WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mac_address {
 | 
					struct mac_address {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -295,7 +295,8 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ieee80211_config_default_key(struct wiphy *wiphy,
 | 
					static int ieee80211_config_default_key(struct wiphy *wiphy,
 | 
				
			||||||
					struct net_device *dev,
 | 
										struct net_device *dev,
 | 
				
			||||||
					u8 key_idx)
 | 
										u8 key_idx, bool uni,
 | 
				
			||||||
 | 
										bool multi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
						struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,6 +171,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 | 
				
			||||||
	[NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
 | 
						[NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 },
 | 
				
			||||||
	[NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
 | 
						[NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
 | 
				
			||||||
	[NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
 | 
						[NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
 | 
				
			||||||
 | 
						[NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* policy for the key attributes */
 | 
					/* policy for the key attributes */
 | 
				
			||||||
| 
						 | 
					@ -182,6 +183,14 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
 | 
				
			||||||
	[NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
 | 
						[NL80211_KEY_DEFAULT] = { .type = NLA_FLAG },
 | 
				
			||||||
	[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
 | 
						[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
 | 
				
			||||||
	[NL80211_KEY_TYPE] = { .type = NLA_U32 },
 | 
						[NL80211_KEY_TYPE] = { .type = NLA_U32 },
 | 
				
			||||||
 | 
						[NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* policy for the key default flags */
 | 
				
			||||||
 | 
					static const struct nla_policy
 | 
				
			||||||
 | 
					nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = {
 | 
				
			||||||
 | 
						[NL80211_KEY_DEFAULT_TYPE_UNICAST] = { .type = NLA_FLAG },
 | 
				
			||||||
 | 
						[NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ifidx get helper */
 | 
					/* ifidx get helper */
 | 
				
			||||||
| 
						 | 
					@ -314,6 +323,7 @@ struct key_parse {
 | 
				
			||||||
	int idx;
 | 
						int idx;
 | 
				
			||||||
	int type;
 | 
						int type;
 | 
				
			||||||
	bool def, defmgmt;
 | 
						bool def, defmgmt;
 | 
				
			||||||
 | 
						bool def_uni, def_multi;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
 | 
					static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
 | 
				
			||||||
| 
						 | 
					@ -327,6 +337,13 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
 | 
				
			||||||
	k->def = !!tb[NL80211_KEY_DEFAULT];
 | 
						k->def = !!tb[NL80211_KEY_DEFAULT];
 | 
				
			||||||
	k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
 | 
						k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (k->def) {
 | 
				
			||||||
 | 
							k->def_uni = true;
 | 
				
			||||||
 | 
							k->def_multi = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (k->defmgmt)
 | 
				
			||||||
 | 
							k->def_multi = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tb[NL80211_KEY_IDX])
 | 
						if (tb[NL80211_KEY_IDX])
 | 
				
			||||||
		k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
 | 
							k->idx = nla_get_u8(tb[NL80211_KEY_IDX]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,6 +366,19 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tb[NL80211_KEY_DEFAULT_TYPES]) {
 | 
				
			||||||
 | 
							struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
 | 
				
			||||||
 | 
							int err = nla_parse_nested(kdt,
 | 
				
			||||||
 | 
										   NUM_NL80211_KEY_DEFAULT_TYPES - 1,
 | 
				
			||||||
 | 
										   tb[NL80211_KEY_DEFAULT_TYPES],
 | 
				
			||||||
 | 
										   nl80211_key_default_policy);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
 | 
				
			||||||
 | 
							k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -373,12 +403,32 @@ static int nl80211_parse_key_old(struct genl_info *info, struct key_parse *k)
 | 
				
			||||||
	k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
 | 
						k->def = !!info->attrs[NL80211_ATTR_KEY_DEFAULT];
 | 
				
			||||||
	k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
 | 
						k->defmgmt = !!info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (k->def) {
 | 
				
			||||||
 | 
							k->def_uni = true;
 | 
				
			||||||
 | 
							k->def_multi = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (k->defmgmt)
 | 
				
			||||||
 | 
							k->def_multi = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
 | 
						if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
 | 
				
			||||||
		k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
 | 
							k->type = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
 | 
				
			||||||
		if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
 | 
							if (k->type < 0 || k->type >= NUM_NL80211_KEYTYPES)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES]) {
 | 
				
			||||||
 | 
							struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
 | 
				
			||||||
 | 
							int err = nla_parse_nested(
 | 
				
			||||||
 | 
									kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
 | 
				
			||||||
 | 
									info->attrs[NL80211_ATTR_KEY_DEFAULT_TYPES],
 | 
				
			||||||
 | 
									nl80211_key_default_policy);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							k->def_uni = kdt[NL80211_KEY_DEFAULT_TYPE_UNICAST];
 | 
				
			||||||
 | 
							k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -401,6 +451,11 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
 | 
				
			||||||
	if (k->def && k->defmgmt)
 | 
						if (k->def && k->defmgmt)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (k->defmgmt) {
 | 
				
			||||||
 | 
							if (k->def_uni || !k->def_multi)
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (k->idx != -1) {
 | 
						if (k->idx != -1) {
 | 
				
			||||||
		if (k->defmgmt) {
 | 
							if (k->defmgmt) {
 | 
				
			||||||
			if (k->idx < 4 || k->idx > 5)
 | 
								if (k->idx < 4 || k->idx > 5)
 | 
				
			||||||
| 
						 | 
					@ -450,6 +505,8 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
 | 
				
			||||||
				goto error;
 | 
									goto error;
 | 
				
			||||||
			def = 1;
 | 
								def = 1;
 | 
				
			||||||
			result->def = parse.idx;
 | 
								result->def = parse.idx;
 | 
				
			||||||
 | 
								if (!parse.def_uni || !parse.def_multi)
 | 
				
			||||||
 | 
									goto error;
 | 
				
			||||||
		} else if (parse.defmgmt)
 | 
							} else if (parse.defmgmt)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		err = cfg80211_validate_key_settings(rdev, &parse.p,
 | 
							err = cfg80211_validate_key_settings(rdev, &parse.p,
 | 
				
			||||||
| 
						 | 
					@ -1586,8 +1643,6 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	struct key_parse key;
 | 
						struct key_parse key;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
	struct net_device *dev = info->user_ptr[1];
 | 
						struct net_device *dev = info->user_ptr[1];
 | 
				
			||||||
	int (*func)(struct wiphy *wiphy, struct net_device *netdev,
 | 
					 | 
				
			||||||
		    u8 key_index);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = nl80211_parse_key(info, &key);
 | 
						err = nl80211_parse_key(info, &key);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
| 
						 | 
					@ -1600,27 +1655,61 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	if (!key.def && !key.defmgmt)
 | 
						if (!key.def && !key.defmgmt)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (key.def)
 | 
					 | 
				
			||||||
		func = rdev->ops->set_default_key;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		func = rdev->ops->set_default_mgmt_key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!func)
 | 
					 | 
				
			||||||
		return -EOPNOTSUPP;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wdev_lock(dev->ieee80211_ptr);
 | 
						wdev_lock(dev->ieee80211_ptr);
 | 
				
			||||||
	err = nl80211_key_allowed(dev->ieee80211_ptr);
 | 
					
 | 
				
			||||||
	if (!err)
 | 
						if (key.def) {
 | 
				
			||||||
		err = func(&rdev->wiphy, dev, key.idx);
 | 
							if (!rdev->ops->set_default_key) {
 | 
				
			||||||
 | 
								err = -EOPNOTSUPP;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = nl80211_key_allowed(dev->ieee80211_ptr);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!(rdev->wiphy.flags &
 | 
				
			||||||
 | 
									WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) {
 | 
				
			||||||
 | 
								if (!key.def_uni || !key.def_multi) {
 | 
				
			||||||
 | 
									err = -EOPNOTSUPP;
 | 
				
			||||||
 | 
									goto out;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx,
 | 
				
			||||||
 | 
											 key.def_uni, key.def_multi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_CFG80211_WEXT
 | 
					#ifdef CONFIG_CFG80211_WEXT
 | 
				
			||||||
	if (!err) {
 | 
							dev->ieee80211_ptr->wext.default_key = key.idx;
 | 
				
			||||||
		if (func == rdev->ops->set_default_key)
 | 
					 | 
				
			||||||
			dev->ieee80211_ptr->wext.default_key = key.idx;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (key.def_uni || !key.def_multi) {
 | 
				
			||||||
 | 
								err = -EINVAL;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!rdev->ops->set_default_mgmt_key) {
 | 
				
			||||||
 | 
								err = -EOPNOTSUPP;
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = nl80211_key_allowed(dev->ieee80211_ptr);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = rdev->ops->set_default_mgmt_key(&rdev->wiphy,
 | 
				
			||||||
 | 
											      dev, key.idx);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_CFG80211_WEXT
 | 
				
			||||||
 | 
							dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 out:
 | 
				
			||||||
	wdev_unlock(dev->ieee80211_ptr);
 | 
						wdev_unlock(dev->ieee80211_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -689,7 +689,8 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (wdev->connect_keys->def == i)
 | 
							if (wdev->connect_keys->def == i)
 | 
				
			||||||
			if (rdev->ops->set_default_key(wdev->wiphy, dev, i)) {
 | 
								if (rdev->ops->set_default_key(wdev->wiphy, dev,
 | 
				
			||||||
 | 
											       i, true, true)) {
 | 
				
			||||||
				netdev_err(dev, "failed to set defkey %d\n", i);
 | 
									netdev_err(dev, "failed to set defkey %d\n", i);
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -548,8 +548,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
 | 
				
			||||||
				__cfg80211_leave_ibss(rdev, wdev->netdev, true);
 | 
									__cfg80211_leave_ibss(rdev, wdev->netdev, true);
 | 
				
			||||||
				rejoin = true;
 | 
									rejoin = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			err = rdev->ops->set_default_key(&rdev->wiphy,
 | 
								err = rdev->ops->set_default_key(&rdev->wiphy, dev,
 | 
				
			||||||
							 dev, idx);
 | 
												 idx, true, true);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!err) {
 | 
							if (!err) {
 | 
				
			||||||
			wdev->wext.default_key = idx;
 | 
								wdev->wext.default_key = idx;
 | 
				
			||||||
| 
						 | 
					@ -627,8 +627,8 @@ int cfg80211_wext_siwencode(struct net_device *dev,
 | 
				
			||||||
		err = 0;
 | 
							err = 0;
 | 
				
			||||||
		wdev_lock(wdev);
 | 
							wdev_lock(wdev);
 | 
				
			||||||
		if (wdev->current_bss)
 | 
							if (wdev->current_bss)
 | 
				
			||||||
			err = rdev->ops->set_default_key(&rdev->wiphy,
 | 
								err = rdev->ops->set_default_key(&rdev->wiphy, dev,
 | 
				
			||||||
							 dev, idx);
 | 
												 idx, true, true);
 | 
				
			||||||
		if (!err)
 | 
							if (!err)
 | 
				
			||||||
			wdev->wext.default_key = idx;
 | 
								wdev->wext.default_key = idx;
 | 
				
			||||||
		wdev_unlock(wdev);
 | 
							wdev_unlock(wdev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue