diff options
Diffstat (limited to 'net/mac80211/cfg.c')
| -rw-r--r-- | net/mac80211/cfg.c | 135 | 
1 files changed, 87 insertions, 48 deletions
| diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 12d52cec9515..be70c70d3f5b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -136,7 +136,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,  	mutex_lock(&sdata->local->sta_mtx);  	if (mac_addr) { -		sta = sta_info_get_bss(sdata, mac_addr); +		if (ieee80211_vif_is_mesh(&sdata->vif)) +			sta = sta_info_get(sdata, mac_addr); +		else +			sta = sta_info_get_bss(sdata, mac_addr);  		if (!sta) {  			ieee80211_key_free(sdata->local, key);  			err = -ENOENT; @@ -157,13 +160,14 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,  static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,  			     u8 key_idx, bool pairwise, const u8 *mac_addr)  { -	struct ieee80211_sub_if_data *sdata; +	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +	struct ieee80211_local *local = sdata->local;  	struct sta_info *sta; +	struct ieee80211_key *key = NULL;  	int ret; -	sdata = IEEE80211_DEV_TO_SUB_IF(dev); - -	mutex_lock(&sdata->local->sta_mtx); +	mutex_lock(&local->sta_mtx); +	mutex_lock(&local->key_mtx);  	if (mac_addr) {  		ret = -ENOENT; @@ -172,33 +176,24 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,  		if (!sta)  			goto out_unlock; -		if (pairwise) { -			if (sta->ptk) { -				ieee80211_key_free(sdata->local, sta->ptk); -				ret = 0; -			} -		} else { -			if (sta->gtk[key_idx]) { -				ieee80211_key_free(sdata->local, -						   sta->gtk[key_idx]); -				ret = 0; -			} -		} - -		goto out_unlock; -	} +		if (pairwise) +			key = key_mtx_dereference(local, sta->ptk); +		else +			key = key_mtx_dereference(local, sta->gtk[key_idx]); +	} else +		key = key_mtx_dereference(local, sdata->keys[key_idx]); -	if (!sdata->keys[key_idx]) { +	if (!key) {  		ret = -ENOENT;  		goto out_unlock;  	} -	ieee80211_key_free(sdata->local, sdata->keys[key_idx]); -	WARN_ON(sdata->keys[key_idx]); +	__ieee80211_key_free(key);  	ret = 0;   out_unlock: -	mutex_unlock(&sdata->local->sta_mtx); +	mutex_unlock(&local->key_mtx); +	mutex_unlock(&local->sta_mtx);  	return ret;  } @@ -228,11 +223,11 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,  			goto out;  		if (pairwise) -			key = sta->ptk; +			key = rcu_dereference(sta->ptk);  		else if (key_idx < NUM_DEFAULT_KEYS) -			key = sta->gtk[key_idx]; +			key = rcu_dereference(sta->gtk[key_idx]);  	} else -		key = sdata->keys[key_idx]; +		key = rcu_dereference(sdata->keys[key_idx]);  	if (!key)  		goto out; @@ -468,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,  	int size;  	int err = -EINVAL; -	old = sdata->u.ap.beacon; +	old = rtnl_dereference(sdata->u.ap.beacon);  	/* head must not be zero-length */  	if (params->head && !params->head_len) @@ -563,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,  	sdata = IEEE80211_DEV_TO_SUB_IF(dev); -	old = sdata->u.ap.beacon; - +	old = rtnl_dereference(sdata->u.ap.beacon);  	if (old)  		return -EALREADY; @@ -579,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,  	sdata = IEEE80211_DEV_TO_SUB_IF(dev); -	old = sdata->u.ap.beacon; - +	old = rtnl_dereference(sdata->u.ap.beacon);  	if (!old)  		return -ENOENT; @@ -594,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)  	sdata = IEEE80211_DEV_TO_SUB_IF(dev); -	old = sdata->u.ap.beacon; - +	old = rtnl_dereference(sdata->u.ap.beacon);  	if (!old)  		return -ENOENT; @@ -734,15 +726,29 @@ static void sta_apply_parameters(struct ieee80211_local *local,  						  params->ht_capa,  						  &sta->sta.ht_cap); -	if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { -		switch (params->plink_action) { -		case PLINK_ACTION_OPEN: -			mesh_plink_open(sta); -			break; -		case PLINK_ACTION_BLOCK: -			mesh_plink_block(sta); -			break; -		} +	if (ieee80211_vif_is_mesh(&sdata->vif)) { +#ifdef CONFIG_MAC80211_MESH +		if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) +			switch (params->plink_state) { +			case NL80211_PLINK_LISTEN: +			case NL80211_PLINK_ESTAB: +			case NL80211_PLINK_BLOCKED: +				sta->plink_state = params->plink_state; +				break; +			default: +				/*  nothing  */ +				break; +			} +		else +			switch (params->plink_action) { +			case PLINK_ACTION_OPEN: +				mesh_plink_open(sta); +				break; +			case PLINK_ACTION_BLOCK: +				mesh_plink_block(sta); +				break; +			} +#endif  	}  } @@ -943,8 +949,10 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,  static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,  			    struct mpath_info *pinfo)  { -	if (mpath->next_hop) -		memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); +	struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop); + +	if (next_hop_sta) +		memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN);  	else  		memset(next_hop, 0, ETH_ALEN); @@ -1064,7 +1072,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,  	memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);  	ifmsh->mesh_pp_id = setup->path_sel_proto;  	ifmsh->mesh_pm_id = setup->path_metric; -	ifmsh->is_secure = setup->is_secure; +	ifmsh->security = IEEE80211_MESH_SEC_NONE; +	if (setup->is_authenticated) +		ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; +	if (setup->is_secure) +		ifmsh->security |= IEEE80211_MESH_SEC_SECURED;  	return 0;  } @@ -1297,9 +1309,10 @@ static int ieee80211_set_channel(struct wiphy *wiphy,  }  #ifdef CONFIG_PM -static int ieee80211_suspend(struct wiphy *wiphy) +static int ieee80211_suspend(struct wiphy *wiphy, +			     struct cfg80211_wowlan *wowlan)  { -	return __ieee80211_suspend(wiphy_priv(wiphy)); +	return __ieee80211_suspend(wiphy_priv(wiphy), wowlan);  }  static int ieee80211_resume(struct wiphy *wiphy) @@ -1342,6 +1355,30 @@ static int ieee80211_scan(struct wiphy *wiphy,  	return ieee80211_request_scan(sdata, req);  } +static int +ieee80211_sched_scan_start(struct wiphy *wiphy, +			   struct net_device *dev, +			   struct cfg80211_sched_scan_request *req) +{ +	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + +	if (!sdata->local->ops->sched_scan_start) +		return -EOPNOTSUPP; + +	return ieee80211_request_sched_scan_start(sdata, req); +} + +static int +ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) +{ +	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + +	if (!sdata->local->ops->sched_scan_stop) +		return -EOPNOTSUPP; + +	return ieee80211_request_sched_scan_stop(sdata); +} +  static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,  			  struct cfg80211_auth_request *req)  { @@ -2083,6 +2120,8 @@ struct cfg80211_ops mac80211_config_ops = {  	.suspend = ieee80211_suspend,  	.resume = ieee80211_resume,  	.scan = ieee80211_scan, +	.sched_scan_start = ieee80211_sched_scan_start, +	.sched_scan_stop = ieee80211_sched_scan_stop,  	.auth = ieee80211_auth,  	.assoc = ieee80211_assoc,  	.deauth = ieee80211_deauth, | 
