diff options
| author | Felix Fietkau <nbd@openwrt.org> | 2011-01-18 15:48:48 +0100 | 
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-01-19 11:36:12 -0500 | 
| commit | fbb327c5945448e98480d610815143a6d4a63638 (patch) | |
| tree | af5148a50e5a7374699c157eb9ef11762f3e0878 /net/mac80211/rx.c | |
| parent | 5dd36bc933e8be84f8369ac64505a2938f9ce036 (diff) | |
mac80211: drop non-auth 3-addr data frames when running as a 4-addr station
When running as a 4-addr station against an AP that has the 4-addr VLAN
interface and the main 3-addr AP interface bridged together, sometimes
frames originating from the station were looping back from the 3-addr AP
interface, causing the bridge code to emit warnings about receiving frames
with its own source address.
I'm not sure why this is happening yet, but I think it's a good idea to
drop all frames (except 802.1x/EAP frames) that do not match the configured
addressing mode, including 4-address frames sent to a 3-address station.
User test reports indicate that the problem goes away with this patch.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
| -rw-r--r-- | net/mac80211/rx.c | 25 | 
1 files changed, 22 insertions, 3 deletions
| diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a6701ed87f0d..1236710f70e0 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1556,17 +1556,36 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)  {  	struct ieee80211_sub_if_data *sdata = rx->sdata;  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; +	bool check_port_control = false; +	struct ethhdr *ehdr; +	int ret;  	if (ieee80211_has_a4(hdr->frame_control) &&  	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)  		return -1; +	if (sdata->vif.type == NL80211_IFTYPE_STATION && +	    !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control)) { + +		if (!sdata->u.mgd.use_4addr) +			return -1; +		else +			check_port_control = true; +	} +  	if (is_multicast_ether_addr(hdr->addr1) && -	    ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) || -	     (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) +	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta)  		return -1; -	return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); +	ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); +	if (ret < 0 || !check_port_control) +		return ret; + +	ehdr = (struct ethhdr *) rx->skb->data; +	if (ehdr->h_proto != rx->sdata->control_port_protocol) +		return -1; + +	return 0;  }  /* | 
