diff options
Diffstat (limited to 'net/mac80211/mesh_hwmp.c')
| -rw-r--r-- | net/mac80211/mesh_hwmp.c | 42 | 
1 files changed, 20 insertions, 22 deletions
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 5bf64d7112b..2b18053070c 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -391,7 +391,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,  			    (mpath->flags & MESH_PATH_SN_VALID)) {  				if (SN_GT(mpath->sn, orig_sn) ||  				    (mpath->sn == orig_sn && -				     action == MPATH_PREQ &&  				     new_metric >= mpath->metric)) {  					process = false;  					fresh_info = false; @@ -561,6 +560,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,  } +static inline struct sta_info * +next_hop_deref_protected(struct mesh_path *mpath) +{ +	return rcu_dereference_protected(mpath->next_hop, +					 lockdep_is_held(&mpath->state_lock)); +} + +  static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,  				    struct ieee80211_mgmt *mgmt,  				    u8 *prep_elem, u32 metric) @@ -600,7 +607,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,  		spin_unlock_bh(&mpath->state_lock);  		goto fail;  	} -	memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); +	memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN);  	spin_unlock_bh(&mpath->state_lock);  	--ttl;  	flags = PREP_IE_FLAGS(prep_elem); @@ -633,7 +640,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,  	struct mesh_path *mpath;  	u8 ttl;  	u8 *ta, *target_addr; -	u8 target_flags;  	u32 target_sn;  	u16 target_rcode; @@ -644,7 +650,6 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,  		return;  	}  	ttl--; -	target_flags = PERR_IE_TARGET_FLAGS(perr_elem);  	target_addr = PERR_IE_TARGET_ADDR(perr_elem);  	target_sn = PERR_IE_TARGET_SN(perr_elem);  	target_rcode = PERR_IE_TARGET_RCODE(perr_elem); @@ -654,7 +659,8 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata,  	if (mpath) {  		spin_lock_bh(&mpath->state_lock);  		if (mpath->flags & MESH_PATH_ACTIVE && -		    memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && +		    memcmp(ta, next_hop_deref_protected(mpath)->sta.addr, +							ETH_ALEN) == 0 &&  		    (!(mpath->flags & MESH_PATH_SN_VALID) ||  		    SN_GT(target_sn, mpath->sn))) {  			mpath->flags &= ~MESH_PATH_ACTIVE; @@ -675,12 +681,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,  {  	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;  	struct mesh_path *mpath; -	u8 *ta;  	u8 ttl, flags, hopcount;  	u8 *orig_addr;  	u32 orig_sn, metric; -	ta = mgmt->sa;  	ttl = rann->rann_ttl;  	if (ttl <= 1) {  		ifmsh->mshstats.dropped_frames_ttl++; @@ -918,6 +922,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,  {  	struct sk_buff *skb_to_free = NULL;  	struct mesh_path *mpath; +	struct sta_info *next_hop;  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;  	u8 *target_addr = hdr->addr3;  	int err = 0; @@ -945,7 +950,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb,  			mesh_queue_preq(mpath,  					PREQ_Q_F_START | PREQ_Q_F_REFRESH);  		} -		memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); +		next_hop = rcu_dereference(mpath->next_hop); +		if (next_hop) +			memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); +		else +			err = -ENOENT;  	} else {  		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);  		if (!(mpath->flags & MESH_PATH_RESOLVING)) { @@ -971,20 +980,11 @@ endlookup:  void mesh_path_timer(unsigned long data)  { -	struct ieee80211_sub_if_data *sdata; -	struct mesh_path *mpath; - -	rcu_read_lock(); -	mpath = (struct mesh_path *) data; -	mpath = rcu_dereference(mpath); -	if (!mpath) -		goto endmpathtimer; -	sdata = mpath->sdata; +	struct mesh_path *mpath = (void *) data; +	struct ieee80211_sub_if_data *sdata = mpath->sdata; -	if (sdata->local->quiescing) { -		rcu_read_unlock(); +	if (sdata->local->quiescing)  		return; -	}  	spin_lock_bh(&mpath->state_lock);  	if (mpath->flags & MESH_PATH_RESOLVED || @@ -1001,8 +1001,6 @@ void mesh_path_timer(unsigned long data)  	}  	spin_unlock_bh(&mpath->state_lock); -endmpathtimer: -	rcu_read_unlock();  }  void  |