diff options
Diffstat (limited to 'net/mac80211/rx.c')
| -rw-r--r-- | net/mac80211/rx.c | 85 | 
1 files changed, 45 insertions, 40 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c6844ad080b..c8447af76ea 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -648,24 +648,6 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)  	return RX_CONTINUE;  } -#define SEQ_MODULO 0x1000 -#define SEQ_MASK   0xfff - -static inline int seq_less(u16 sq1, u16 sq2) -{ -	return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); -} - -static inline u16 seq_inc(u16 sq) -{ -	return (sq + 1) & SEQ_MASK; -} - -static inline u16 seq_sub(u16 sq1, u16 sq2) -{ -	return (sq1 - sq2) & SEQ_MASK; -} -  static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,  					    struct tid_ampdu_rx *tid_agg_rx,  					    int index, @@ -687,7 +669,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata,  	__skb_queue_tail(frames, skb);  no_frame: -	tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); +	tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num);  }  static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, @@ -699,8 +681,9 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata  	lockdep_assert_held(&tid_agg_rx->reorder_lock); -	while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { -		index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % +	while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { +		index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, +					 tid_agg_rx->ssn) %  							tid_agg_rx->buf_size;  		ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,  						frames); @@ -727,8 +710,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,  	lockdep_assert_held(&tid_agg_rx->reorder_lock);  	/* release the buffer until next missing frame */ -	index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % -						tid_agg_rx->buf_size; +	index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, +				 tid_agg_rx->ssn) % tid_agg_rx->buf_size;  	if (!tid_agg_rx->reorder_buf[index] &&  	    tid_agg_rx->stored_mpdu_num) {  		/* @@ -756,19 +739,22 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata,  			 * Increment the head seq# also for the skipped slots.  			 */  			tid_agg_rx->head_seq_num = -				(tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; +				(tid_agg_rx->head_seq_num + +				 skipped) & IEEE80211_SN_MASK;  			skipped = 0;  		}  	} else while (tid_agg_rx->reorder_buf[index]) {  		ieee80211_release_reorder_frame(sdata, tid_agg_rx, index,  						frames); -		index =	seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % +		index =	ieee80211_sn_sub(tid_agg_rx->head_seq_num, +					 tid_agg_rx->ssn) %  							tid_agg_rx->buf_size;  	}  	if (tid_agg_rx->stored_mpdu_num) { -		j = index = seq_sub(tid_agg_rx->head_seq_num, -				    tid_agg_rx->ssn) % tid_agg_rx->buf_size; +		j = index = ieee80211_sn_sub(tid_agg_rx->head_seq_num, +					     tid_agg_rx->ssn) % +							tid_agg_rx->buf_size;  		for (; j != (index - 1) % tid_agg_rx->buf_size;  		     j = (j + 1) % tid_agg_rx->buf_size) { @@ -809,7 +795,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata  	head_seq_num = tid_agg_rx->head_seq_num;  	/* frame with out of date sequence number */ -	if (seq_less(mpdu_seq_num, head_seq_num)) { +	if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) {  		dev_kfree_skb(skb);  		goto out;  	} @@ -818,8 +804,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata  	 * If frame the sequence number exceeds our buffering window  	 * size release some previous frames to make room for this one.  	 */ -	if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { -		head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); +	if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) { +		head_seq_num = ieee80211_sn_inc( +				ieee80211_sn_sub(mpdu_seq_num, buf_size));  		/* release stored frames up to new head to stack */  		ieee80211_release_reorder_frames(sdata, tid_agg_rx,  						 head_seq_num, frames); @@ -827,7 +814,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata  	/* Now the new frame is always in the range of the reordering buffer */ -	index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; +	index = ieee80211_sn_sub(mpdu_seq_num, +				 tid_agg_rx->ssn) % tid_agg_rx->buf_size;  	/* check if we already stored this frame */  	if (tid_agg_rx->reorder_buf[index]) { @@ -843,7 +831,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata  	 */  	if (mpdu_seq_num == tid_agg_rx->head_seq_num &&  	    tid_agg_rx->stored_mpdu_num == 0) { -		tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); +		tid_agg_rx->head_seq_num = +			ieee80211_sn_inc(tid_agg_rx->head_seq_num);  		ret = false;  		goto out;  	} @@ -1894,8 +1883,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)  		 * 'align' will only take the values 0 or 2 here  		 * since all frames are required to be aligned  		 * to 2-byte boundaries when being passed to -		 * mac80211. That also explains the __skb_push() -		 * below. +		 * mac80211; the code here works just as well if +		 * that isn't true, but mac80211 assumes it can +		 * access fields as 2-byte aligned (e.g. for +		 * compare_ether_addr)  		 */  		align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3;  		if (align) { @@ -2094,6 +2085,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  	}  	fwd_hdr =  (struct ieee80211_hdr *) fwd_skb->data; +	fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);  	info = IEEE80211_SKB_CB(fwd_skb);  	memset(info, 0, sizeof(*info));  	info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; @@ -2432,6 +2424,22 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		}  		break; +	case WLAN_CATEGORY_PUBLIC: +		if (len < IEEE80211_MIN_ACTION_SIZE + 1) +			goto invalid; +		if (sdata->vif.type != NL80211_IFTYPE_STATION) +			break; +		if (!rx->sta) +			break; +		if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) +			break; +		if (mgmt->u.action.u.ext_chan_switch.action_code != +				WLAN_PUB_ACTION_EXT_CHANSW_ANN) +			break; +		if (len < offsetof(struct ieee80211_mgmt, +				   u.action.u.ext_chan_switch.variable)) +			goto invalid; +		goto queue;  	case WLAN_CATEGORY_VHT:  		if (sdata->vif.type != NL80211_IFTYPE_STATION &&  		    sdata->vif.type != NL80211_IFTYPE_MESH_POINT && @@ -2515,10 +2523,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  			ieee80211_process_measurement_req(sdata, mgmt, len);  			goto handled;  		case WLAN_ACTION_SPCT_CHL_SWITCH: -			if (len < (IEEE80211_MIN_ACTION_SIZE + -				   sizeof(mgmt->u.action.u.chan_switch))) -				break; -  			if (sdata->vif.type != NL80211_IFTYPE_STATION)  				break; @@ -2552,7 +2556,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		case WLAN_SP_MESH_PEERING_CONFIRM:  			if (!ieee80211_vif_is_mesh(&sdata->vif))  				goto invalid; -			if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) +			if (sdata->u.mesh.user_mpm)  				/* userspace handles this frame */  				break;  			goto queue; @@ -3051,7 +3055,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,  		    !ieee80211_is_probe_resp(hdr->frame_control) &&  		    !ieee80211_is_beacon(hdr->frame_control))  			return 0; -		if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) +		if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) && +		    !multicast)  			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;  		break;  	default:  |