diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-12-18 19:31:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:59:45 -0500 |
commit | ce3edf6d0b979fa4d5da7204fd8c6f77f2b8622a (patch) | |
tree | 3608f59fa3c437edfe132a603775111a03dce453 /net | |
parent | 1946b74ce03c4edecabde80d027da00a7eab56ca (diff) |
mac80211: clean up eapol frame handling/port control
This cleans up the eapol frame handling and some related code in the
receive and transmit paths. After this patch
* EAPOL frames addressed to us or the EAPOL group address are
always accepted regardless of whether they are encrypted or not
* other frames from a station are dropped if PAE is enabled and
the station is not authorized
* unencrypted frames (except the EAPOL frames above) are dropped if
drop_unencrypted is enabled
* some superfluous code that eth_type_trans handles anyway is gone
* port control is done for transmitted packets
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 27 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 22 | ||||
-rw-r--r-- | net/mac80211/ieee80211_iface.c | 1 | ||||
-rw-r--r-- | net/mac80211/rx.c | 133 | ||||
-rw-r--r-- | net/mac80211/tx.c | 53 |
5 files changed, 119 insertions, 117 deletions
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index f0e6ab7eb624..bf715d28643b 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -91,8 +91,7 @@ static const struct file_operations name##_ops = { \ | |||
91 | /* common attributes */ | 91 | /* common attributes */ |
92 | IEEE80211_IF_FILE(channel_use, channel_use, DEC); | 92 | IEEE80211_IF_FILE(channel_use, channel_use, DEC); |
93 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); | 93 | IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); |
94 | IEEE80211_IF_FILE(eapol, eapol, DEC); | 94 | IEEE80211_IF_FILE(ieee802_1x_pac, ieee802_1x_pac, DEC); |
95 | IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC); | ||
96 | 95 | ||
97 | /* STA/IBSS attributes */ | 96 | /* STA/IBSS attributes */ |
98 | IEEE80211_IF_FILE(state, u.sta.state, DEC); | 97 | IEEE80211_IF_FILE(state, u.sta.state, DEC); |
@@ -170,8 +169,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
170 | { | 169 | { |
171 | DEBUGFS_ADD(channel_use, sta); | 170 | DEBUGFS_ADD(channel_use, sta); |
172 | DEBUGFS_ADD(drop_unencrypted, sta); | 171 | DEBUGFS_ADD(drop_unencrypted, sta); |
173 | DEBUGFS_ADD(eapol, sta); | 172 | DEBUGFS_ADD(ieee802_1x_pac, sta); |
174 | DEBUGFS_ADD(ieee8021_x, sta); | ||
175 | DEBUGFS_ADD(state, sta); | 173 | DEBUGFS_ADD(state, sta); |
176 | DEBUGFS_ADD(bssid, sta); | 174 | DEBUGFS_ADD(bssid, sta); |
177 | DEBUGFS_ADD(prev_bssid, sta); | 175 | DEBUGFS_ADD(prev_bssid, sta); |
@@ -192,8 +190,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
192 | { | 190 | { |
193 | DEBUGFS_ADD(channel_use, ap); | 191 | DEBUGFS_ADD(channel_use, ap); |
194 | DEBUGFS_ADD(drop_unencrypted, ap); | 192 | DEBUGFS_ADD(drop_unencrypted, ap); |
195 | DEBUGFS_ADD(eapol, ap); | 193 | DEBUGFS_ADD(ieee802_1x_pac, ap); |
196 | DEBUGFS_ADD(ieee8021_x, ap); | ||
197 | DEBUGFS_ADD(num_sta_ps, ap); | 194 | DEBUGFS_ADD(num_sta_ps, ap); |
198 | DEBUGFS_ADD(dtim_period, ap); | 195 | DEBUGFS_ADD(dtim_period, ap); |
199 | DEBUGFS_ADD(dtim_count, ap); | 196 | DEBUGFS_ADD(dtim_count, ap); |
@@ -209,8 +206,7 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) | |||
209 | { | 206 | { |
210 | DEBUGFS_ADD(channel_use, wds); | 207 | DEBUGFS_ADD(channel_use, wds); |
211 | DEBUGFS_ADD(drop_unencrypted, wds); | 208 | DEBUGFS_ADD(drop_unencrypted, wds); |
212 | DEBUGFS_ADD(eapol, wds); | 209 | DEBUGFS_ADD(ieee802_1x_pac, wds); |
213 | DEBUGFS_ADD(ieee8021_x, wds); | ||
214 | DEBUGFS_ADD(peer, wds); | 210 | DEBUGFS_ADD(peer, wds); |
215 | } | 211 | } |
216 | 212 | ||
@@ -218,8 +214,7 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
218 | { | 214 | { |
219 | DEBUGFS_ADD(channel_use, vlan); | 215 | DEBUGFS_ADD(channel_use, vlan); |
220 | DEBUGFS_ADD(drop_unencrypted, vlan); | 216 | DEBUGFS_ADD(drop_unencrypted, vlan); |
221 | DEBUGFS_ADD(eapol, vlan); | 217 | DEBUGFS_ADD(ieee802_1x_pac, vlan); |
222 | DEBUGFS_ADD(ieee8021_x, vlan); | ||
223 | } | 218 | } |
224 | 219 | ||
225 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | 220 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) |
@@ -263,8 +258,7 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) | |||
263 | { | 258 | { |
264 | DEBUGFS_DEL(channel_use, sta); | 259 | DEBUGFS_DEL(channel_use, sta); |
265 | DEBUGFS_DEL(drop_unencrypted, sta); | 260 | DEBUGFS_DEL(drop_unencrypted, sta); |
266 | DEBUGFS_DEL(eapol, sta); | 261 | DEBUGFS_DEL(ieee802_1x_pac, sta); |
267 | DEBUGFS_DEL(ieee8021_x, sta); | ||
268 | DEBUGFS_DEL(state, sta); | 262 | DEBUGFS_DEL(state, sta); |
269 | DEBUGFS_DEL(bssid, sta); | 263 | DEBUGFS_DEL(bssid, sta); |
270 | DEBUGFS_DEL(prev_bssid, sta); | 264 | DEBUGFS_DEL(prev_bssid, sta); |
@@ -285,8 +279,7 @@ static void del_ap_files(struct ieee80211_sub_if_data *sdata) | |||
285 | { | 279 | { |
286 | DEBUGFS_DEL(channel_use, ap); | 280 | DEBUGFS_DEL(channel_use, ap); |
287 | DEBUGFS_DEL(drop_unencrypted, ap); | 281 | DEBUGFS_DEL(drop_unencrypted, ap); |
288 | DEBUGFS_DEL(eapol, ap); | 282 | DEBUGFS_DEL(ieee802_1x_pac, ap); |
289 | DEBUGFS_DEL(ieee8021_x, ap); | ||
290 | DEBUGFS_DEL(num_sta_ps, ap); | 283 | DEBUGFS_DEL(num_sta_ps, ap); |
291 | DEBUGFS_DEL(dtim_period, ap); | 284 | DEBUGFS_DEL(dtim_period, ap); |
292 | DEBUGFS_DEL(dtim_count, ap); | 285 | DEBUGFS_DEL(dtim_count, ap); |
@@ -302,8 +295,7 @@ static void del_wds_files(struct ieee80211_sub_if_data *sdata) | |||
302 | { | 295 | { |
303 | DEBUGFS_DEL(channel_use, wds); | 296 | DEBUGFS_DEL(channel_use, wds); |
304 | DEBUGFS_DEL(drop_unencrypted, wds); | 297 | DEBUGFS_DEL(drop_unencrypted, wds); |
305 | DEBUGFS_DEL(eapol, wds); | 298 | DEBUGFS_DEL(ieee802_1x_pac, wds); |
306 | DEBUGFS_DEL(ieee8021_x, wds); | ||
307 | DEBUGFS_DEL(peer, wds); | 299 | DEBUGFS_DEL(peer, wds); |
308 | } | 300 | } |
309 | 301 | ||
@@ -311,8 +303,7 @@ static void del_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
311 | { | 303 | { |
312 | DEBUGFS_DEL(channel_use, vlan); | 304 | DEBUGFS_DEL(channel_use, vlan); |
313 | DEBUGFS_DEL(drop_unencrypted, vlan); | 305 | DEBUGFS_DEL(drop_unencrypted, vlan); |
314 | DEBUGFS_DEL(eapol, vlan); | 306 | DEBUGFS_DEL(ieee802_1x_pac, vlan); |
315 | DEBUGFS_DEL(ieee8021_x, vlan); | ||
316 | } | 307 | } |
317 | 308 | ||
318 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) | 309 | static void del_monitor_files(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b54ed5fe4aa3..214109b8d95a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -306,11 +306,11 @@ struct ieee80211_sub_if_data { | |||
306 | unsigned int flags; | 306 | unsigned int flags; |
307 | 307 | ||
308 | int drop_unencrypted; | 308 | int drop_unencrypted; |
309 | int eapol; /* 0 = process EAPOL frames as normal data frames, | 309 | /* |
310 | * 1 = send EAPOL frames through wlan#ap to hostapd | 310 | * IEEE 802.1X Port access control in effect, |
311 | * (default) */ | 311 | * drop packets to/from unauthorized port |
312 | int ieee802_1x; /* IEEE 802.1X PAE - drop packet to/from unauthorized | 312 | */ |
313 | * port */ | 313 | int ieee802_1x_pac; |
314 | 314 | ||
315 | u16 sequence; | 315 | u16 sequence; |
316 | 316 | ||
@@ -339,8 +339,7 @@ struct ieee80211_sub_if_data { | |||
339 | struct { | 339 | struct { |
340 | struct dentry *channel_use; | 340 | struct dentry *channel_use; |
341 | struct dentry *drop_unencrypted; | 341 | struct dentry *drop_unencrypted; |
342 | struct dentry *eapol; | 342 | struct dentry *ieee802_1x_pac; |
343 | struct dentry *ieee8021_x; | ||
344 | struct dentry *state; | 343 | struct dentry *state; |
345 | struct dentry *bssid; | 344 | struct dentry *bssid; |
346 | struct dentry *prev_bssid; | 345 | struct dentry *prev_bssid; |
@@ -359,8 +358,7 @@ struct ieee80211_sub_if_data { | |||
359 | struct { | 358 | struct { |
360 | struct dentry *channel_use; | 359 | struct dentry *channel_use; |
361 | struct dentry *drop_unencrypted; | 360 | struct dentry *drop_unencrypted; |
362 | struct dentry *eapol; | 361 | struct dentry *ieee802_1x_pac; |
363 | struct dentry *ieee8021_x; | ||
364 | struct dentry *num_sta_ps; | 362 | struct dentry *num_sta_ps; |
365 | struct dentry *dtim_period; | 363 | struct dentry *dtim_period; |
366 | struct dentry *dtim_count; | 364 | struct dentry *dtim_count; |
@@ -374,15 +372,13 @@ struct ieee80211_sub_if_data { | |||
374 | struct { | 372 | struct { |
375 | struct dentry *channel_use; | 373 | struct dentry *channel_use; |
376 | struct dentry *drop_unencrypted; | 374 | struct dentry *drop_unencrypted; |
377 | struct dentry *eapol; | 375 | struct dentry *ieee802_1x_pac; |
378 | struct dentry *ieee8021_x; | ||
379 | struct dentry *peer; | 376 | struct dentry *peer; |
380 | } wds; | 377 | } wds; |
381 | struct { | 378 | struct { |
382 | struct dentry *channel_use; | 379 | struct dentry *channel_use; |
383 | struct dentry *drop_unencrypted; | 380 | struct dentry *drop_unencrypted; |
384 | struct dentry *eapol; | 381 | struct dentry *ieee802_1x_pac; |
385 | struct dentry *ieee8021_x; | ||
386 | } vlan; | 382 | } vlan; |
387 | struct { | 383 | struct { |
388 | struct dentry *mode; | 384 | struct dentry *mode; |
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c index 43e505d29452..7cfd8660b231 100644 --- a/net/mac80211/ieee80211_iface.c +++ b/net/mac80211/ieee80211_iface.c | |||
@@ -22,7 +22,6 @@ void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata) | |||
22 | 22 | ||
23 | /* Default values for sub-interface parameters */ | 23 | /* Default values for sub-interface parameters */ |
24 | sdata->drop_unencrypted = 0; | 24 | sdata->drop_unencrypted = 0; |
25 | sdata->eapol = 1; | ||
26 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 25 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
27 | skb_queue_head_init(&sdata->fragments[i].skb_list); | 26 | skb_queue_head_init(&sdata->fragments[i].skb_list); |
28 | 27 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e65da5780cd3..505159f8dffc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -208,7 +208,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
208 | rthdr->it_len = cpu_to_le16(rtap_len); | 208 | rthdr->it_len = cpu_to_le16(rtap_len); |
209 | } | 209 | } |
210 | 210 | ||
211 | skb_set_mac_header(skb, 0); | 211 | skb_reset_mac_header(skb); |
212 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 212 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
213 | skb->pkt_type = PACKET_OTHERHOST; | 213 | skb->pkt_type = PACKET_OTHERHOST; |
214 | skb->protocol = htons(ETH_P_802_2); | 214 | skb->protocol = htons(ETH_P_802_2); |
@@ -405,18 +405,6 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) | |||
405 | return TXRX_DROP; | 405 | return TXRX_DROP; |
406 | } | 406 | } |
407 | 407 | ||
408 | if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) | ||
409 | rx->skb->pkt_type = PACKET_OTHERHOST; | ||
410 | else if (compare_ether_addr(rx->dev->dev_addr, hdr->addr1) == 0) | ||
411 | rx->skb->pkt_type = PACKET_HOST; | ||
412 | else if (is_multicast_ether_addr(hdr->addr1)) { | ||
413 | if (is_broadcast_ether_addr(hdr->addr1)) | ||
414 | rx->skb->pkt_type = PACKET_BROADCAST; | ||
415 | else | ||
416 | rx->skb->pkt_type = PACKET_MULTICAST; | ||
417 | } else | ||
418 | rx->skb->pkt_type = PACKET_OTHERHOST; | ||
419 | |||
420 | /* Drop disallowed frame classes based on STA auth/assoc state; | 408 | /* Drop disallowed frame classes based on STA auth/assoc state; |
421 | * IEEE 802.11, Chap 5.5. | 409 | * IEEE 802.11, Chap 5.5. |
422 | * | 410 | * |
@@ -990,18 +978,10 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx) | |||
990 | } | 978 | } |
991 | 979 | ||
992 | static int | 980 | static int |
993 | ieee80211_drop_802_1x_pae(struct ieee80211_txrx_data *rx, int hdrlen) | 981 | ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx) |
994 | { | 982 | { |
995 | if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb, hdrlen) && | 983 | if (unlikely(rx->sdata->ieee802_1x_pac && |
996 | rx->sdata->type != IEEE80211_IF_TYPE_STA && | 984 | (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)))) { |
997 | (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) | ||
998 | return 0; | ||
999 | |||
1000 | if (unlikely(rx->sdata->ieee802_1x && | ||
1001 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | ||
1002 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && | ||
1003 | (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) && | ||
1004 | !ieee80211_is_eapol(rx->skb, hdrlen))) { | ||
1005 | #ifdef CONFIG_MAC80211_DEBUG | 985 | #ifdef CONFIG_MAC80211_DEBUG |
1006 | printk(KERN_DEBUG "%s: dropped frame " | 986 | printk(KERN_DEBUG "%s: dropped frame " |
1007 | "(unauthorized port)\n", rx->dev->name); | 987 | "(unauthorized port)\n", rx->dev->name); |
@@ -1013,7 +993,7 @@ ieee80211_drop_802_1x_pae(struct ieee80211_txrx_data *rx, int hdrlen) | |||
1013 | } | 993 | } |
1014 | 994 | ||
1015 | static int | 995 | static int |
1016 | ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx, int hdrlen) | 996 | ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx) |
1017 | { | 997 | { |
1018 | /* | 998 | /* |
1019 | * Pass through unencrypted frames if the hardware has | 999 | * Pass through unencrypted frames if the hardware has |
@@ -1026,9 +1006,7 @@ ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx, int hdrlen) | |||
1026 | if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && | 1006 | if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && |
1027 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 1007 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && |
1028 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && | 1008 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && |
1029 | (rx->key || rx->sdata->drop_unencrypted) && | 1009 | (rx->key || rx->sdata->drop_unencrypted))) { |
1030 | (rx->sdata->eapol == 0 || | ||
1031 | !ieee80211_is_eapol(rx->skb, hdrlen)))) { | ||
1032 | if (net_ratelimit()) | 1010 | if (net_ratelimit()) |
1033 | printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " | 1011 | printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " |
1034 | "encryption\n", rx->dev->name); | 1012 | "encryption\n", rx->dev->name); |
@@ -1156,6 +1134,7 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx) | |||
1156 | } else { | 1134 | } else { |
1157 | struct ethhdr *ehdr; | 1135 | struct ethhdr *ehdr; |
1158 | __be16 len; | 1136 | __be16 len; |
1137 | |||
1159 | skb_pull(skb, hdrlen); | 1138 | skb_pull(skb, hdrlen); |
1160 | len = htons(skb->len); | 1139 | len = htons(skb->len); |
1161 | ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); | 1140 | ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); |
@@ -1166,6 +1145,34 @@ ieee80211_data_to_8023(struct ieee80211_txrx_data *rx) | |||
1166 | return 0; | 1145 | return 0; |
1167 | } | 1146 | } |
1168 | 1147 | ||
1148 | /* | ||
1149 | * requires that rx->skb is a frame with ethernet header | ||
1150 | */ | ||
1151 | static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx) | ||
1152 | { | ||
1153 | static const u8 pae_group_addr[ETH_ALEN] | ||
1154 | = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; | ||
1155 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | ||
1156 | |||
1157 | /* | ||
1158 | * Allow EAPOL frames to us/the PAE group address regardless | ||
1159 | * of whether the frame was encrypted or not. | ||
1160 | */ | ||
1161 | if (ehdr->h_proto == htons(ETH_P_PAE) && | ||
1162 | (compare_ether_addr(ehdr->h_dest, rx->dev->dev_addr) == 0 || | ||
1163 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) | ||
1164 | return true; | ||
1165 | |||
1166 | if (ieee80211_802_1x_port_control(rx) || | ||
1167 | ieee80211_drop_unencrypted(rx)) | ||
1168 | return false; | ||
1169 | |||
1170 | return true; | ||
1171 | } | ||
1172 | |||
1173 | /* | ||
1174 | * requires that rx->skb is a frame with ethernet header | ||
1175 | */ | ||
1169 | static void | 1176 | static void |
1170 | ieee80211_deliver_skb(struct ieee80211_txrx_data *rx) | 1177 | ieee80211_deliver_skb(struct ieee80211_txrx_data *rx) |
1171 | { | 1178 | { |
@@ -1173,31 +1180,32 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx) | |||
1173 | struct ieee80211_local *local = rx->local; | 1180 | struct ieee80211_local *local = rx->local; |
1174 | struct sk_buff *skb, *xmit_skb; | 1181 | struct sk_buff *skb, *xmit_skb; |
1175 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1182 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1183 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | ||
1184 | struct sta_info *dsta; | ||
1176 | 1185 | ||
1177 | skb = rx->skb; | 1186 | skb = rx->skb; |
1178 | xmit_skb = NULL; | 1187 | xmit_skb = NULL; |
1179 | 1188 | ||
1180 | if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP | 1189 | if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP || |
1181 | || sdata->type == IEEE80211_IF_TYPE_VLAN) && | 1190 | sdata->type == IEEE80211_IF_TYPE_VLAN) && |
1182 | (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) { | 1191 | (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) { |
1183 | if (is_multicast_ether_addr(skb->data)) { | 1192 | if (is_multicast_ether_addr(ehdr->h_dest)) { |
1184 | /* send multicast frames both to higher layers in | 1193 | /* |
1185 | * local net stack and back to the wireless media */ | 1194 | * send multicast frames both to higher layers in |
1195 | * local net stack and back to the wireless medium | ||
1196 | */ | ||
1186 | xmit_skb = skb_copy(skb, GFP_ATOMIC); | 1197 | xmit_skb = skb_copy(skb, GFP_ATOMIC); |
1187 | if (!xmit_skb && net_ratelimit()) | 1198 | if (!xmit_skb && net_ratelimit()) |
1188 | printk(KERN_DEBUG "%s: failed to clone " | 1199 | printk(KERN_DEBUG "%s: failed to clone " |
1189 | "multicast frame\n", dev->name); | 1200 | "multicast frame\n", dev->name); |
1190 | } else { | 1201 | } else { |
1191 | struct sta_info *dsta; | ||
1192 | dsta = sta_info_get(local, skb->data); | 1202 | dsta = sta_info_get(local, skb->data); |
1193 | if (dsta && !dsta->dev) { | 1203 | if (dsta && dsta->dev == dev) { |
1194 | if (net_ratelimit()) | 1204 | /* |
1195 | printk(KERN_DEBUG "Station with null " | 1205 | * The destination station is associated to |
1196 | "dev structure!\n"); | 1206 | * this AP (in this VLAN), so send the frame |
1197 | } else if (dsta && dsta->dev == dev) { | 1207 | * directly to it and do not pass it to local |
1198 | /* Destination station is associated to this | 1208 | * net stack. |
1199 | * AP, so send the frame directly to it and | ||
1200 | * do not pass the frame to local net stack. | ||
1201 | */ | 1209 | */ |
1202 | xmit_skb = skb; | 1210 | xmit_skb = skb; |
1203 | skb = NULL; | 1211 | skb = NULL; |
@@ -1217,8 +1225,8 @@ ieee80211_deliver_skb(struct ieee80211_txrx_data *rx) | |||
1217 | if (xmit_skb) { | 1225 | if (xmit_skb) { |
1218 | /* send to wireless media */ | 1226 | /* send to wireless media */ |
1219 | xmit_skb->protocol = htons(ETH_P_802_3); | 1227 | xmit_skb->protocol = htons(ETH_P_802_3); |
1220 | skb_set_network_header(xmit_skb, 0); | 1228 | skb_reset_network_header(xmit_skb); |
1221 | skb_set_mac_header(xmit_skb, 0); | 1229 | skb_reset_mac_header(xmit_skb); |
1222 | dev_queue_xmit(xmit_skb); | 1230 | dev_queue_xmit(xmit_skb); |
1223 | } | 1231 | } |
1224 | } | 1232 | } |
@@ -1303,38 +1311,36 @@ ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx) | |||
1303 | } | 1311 | } |
1304 | } | 1312 | } |
1305 | 1313 | ||
1306 | skb_set_network_header(frame, 0); | 1314 | skb_reset_network_header(frame); |
1307 | frame->dev = dev; | 1315 | frame->dev = dev; |
1308 | frame->priority = skb->priority; | 1316 | frame->priority = skb->priority; |
1309 | rx->skb = frame; | 1317 | rx->skb = frame; |
1310 | 1318 | ||
1311 | if ((ieee80211_drop_802_1x_pae(rx, 0)) || | ||
1312 | (ieee80211_drop_unencrypted(rx, 0))) { | ||
1313 | if (skb == frame) /* last frame */ | ||
1314 | return TXRX_DROP; | ||
1315 | dev_kfree_skb(frame); | ||
1316 | continue; | ||
1317 | } | ||
1318 | |||
1319 | payload = frame->data; | 1319 | payload = frame->data; |
1320 | ethertype = (payload[6] << 8) | payload[7]; | 1320 | ethertype = (payload[6] << 8) | payload[7]; |
1321 | 1321 | ||
1322 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && | 1322 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && |
1323 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | 1323 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || |
1324 | compare_ether_addr(payload, | 1324 | compare_ether_addr(payload, |
1325 | bridge_tunnel_header) == 0)) { | 1325 | bridge_tunnel_header) == 0)) { |
1326 | /* remove RFC1042 or Bridge-Tunnel | 1326 | /* remove RFC1042 or Bridge-Tunnel |
1327 | * encapsulation and replace EtherType */ | 1327 | * encapsulation and replace EtherType */ |
1328 | skb_pull(frame, 6); | 1328 | skb_pull(frame, 6); |
1329 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | 1329 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); |
1330 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | 1330 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); |
1331 | } else { | 1331 | } else { |
1332 | memcpy(skb_push(frame, sizeof(__be16)), &len, | 1332 | memcpy(skb_push(frame, sizeof(__be16)), |
1333 | sizeof(__be16)); | 1333 | &len, sizeof(__be16)); |
1334 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); | 1334 | memcpy(skb_push(frame, ETH_ALEN), src, ETH_ALEN); |
1335 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | 1335 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); |
1336 | } | 1336 | } |
1337 | 1337 | ||
1338 | if (!ieee80211_frame_allowed(rx)) { | ||
1339 | if (skb == frame) /* last frame */ | ||
1340 | return TXRX_DROP; | ||
1341 | dev_kfree_skb(frame); | ||
1342 | continue; | ||
1343 | } | ||
1338 | 1344 | ||
1339 | ieee80211_deliver_skb(rx); | 1345 | ieee80211_deliver_skb(rx); |
1340 | } | 1346 | } |
@@ -1347,7 +1353,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) | |||
1347 | { | 1353 | { |
1348 | struct net_device *dev = rx->dev; | 1354 | struct net_device *dev = rx->dev; |
1349 | u16 fc; | 1355 | u16 fc; |
1350 | int err, hdrlen; | 1356 | int err; |
1351 | 1357 | ||
1352 | fc = rx->fc; | 1358 | fc = rx->fc; |
1353 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) | 1359 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) |
@@ -1356,16 +1362,13 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) | |||
1356 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) | 1362 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) |
1357 | return TXRX_DROP; | 1363 | return TXRX_DROP; |
1358 | 1364 | ||
1359 | hdrlen = ieee80211_get_hdrlen(fc); | ||
1360 | |||
1361 | if ((ieee80211_drop_802_1x_pae(rx, hdrlen)) || | ||
1362 | (ieee80211_drop_unencrypted(rx, hdrlen))) | ||
1363 | return TXRX_DROP; | ||
1364 | |||
1365 | err = ieee80211_data_to_8023(rx); | 1365 | err = ieee80211_data_to_8023(rx); |
1366 | if (unlikely(err)) | 1366 | if (unlikely(err)) |
1367 | return TXRX_DROP; | 1367 | return TXRX_DROP; |
1368 | 1368 | ||
1369 | if (!ieee80211_frame_allowed(rx)) | ||
1370 | return TXRX_DROP; | ||
1371 | |||
1369 | rx->skb->dev = dev; | 1372 | rx->skb->dev = dev; |
1370 | 1373 | ||
1371 | dev->stats.rx_packets++; | 1374 | dev->stats.rx_packets++; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4655e3038658..6dbd91842881 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -261,18 +261,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx) | |||
261 | return TXRX_CONTINUE; | 261 | return TXRX_CONTINUE; |
262 | } | 262 | } |
263 | 263 | ||
264 | if (unlikely(/* !injected && */ tx->sdata->ieee802_1x && | ||
265 | !(sta_flags & WLAN_STA_AUTHORIZED))) { | ||
266 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
267 | DECLARE_MAC_BUF(mac); | ||
268 | printk(KERN_DEBUG "%s: dropped frame to %s" | ||
269 | " (unauthorized port)\n", tx->dev->name, | ||
270 | print_mac(mac, hdr->addr1)); | ||
271 | #endif | ||
272 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unauth_port); | ||
273 | return TXRX_DROP; | ||
274 | } | ||
275 | |||
276 | return TXRX_CONTINUE; | 264 | return TXRX_CONTINUE; |
277 | } | 265 | } |
278 | 266 | ||
@@ -449,8 +437,7 @@ ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx) | |||
449 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 437 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
450 | tx->key = key; | 438 | tx->key = key; |
451 | else if (tx->sdata->drop_unencrypted && | 439 | else if (tx->sdata->drop_unencrypted && |
452 | !(tx->sdata->eapol && | 440 | !ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc))) { |
453 | ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc)))) { | ||
454 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 441 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
455 | return TXRX_DROP; | 442 | return TXRX_DROP; |
456 | } else { | 443 | } else { |
@@ -1346,6 +1333,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1346 | int encaps_len, skip_header_bytes; | 1333 | int encaps_len, skip_header_bytes; |
1347 | int nh_pos, h_pos; | 1334 | int nh_pos, h_pos; |
1348 | struct sta_info *sta; | 1335 | struct sta_info *sta; |
1336 | u32 sta_flags = 0; | ||
1349 | 1337 | ||
1350 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1338 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1351 | if (unlikely(skb->len < ETH_HLEN)) { | 1339 | if (unlikely(skb->len < ETH_HLEN)) { |
@@ -1361,7 +1349,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1361 | /* convert Ethernet header to proper 802.11 header (based on | 1349 | /* convert Ethernet header to proper 802.11 header (based on |
1362 | * operation mode) */ | 1350 | * operation mode) */ |
1363 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1351 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
1364 | /* TODO: handling for 802.1x authorized/unauthorized port */ | ||
1365 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; | 1352 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; |
1366 | 1353 | ||
1367 | switch (sdata->type) { | 1354 | switch (sdata->type) { |
@@ -1403,16 +1390,42 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1403 | goto fail; | 1390 | goto fail; |
1404 | } | 1391 | } |
1405 | 1392 | ||
1406 | /* receiver is QoS enabled, use a QoS type frame */ | ||
1407 | sta = sta_info_get(local, hdr.addr1); | 1393 | sta = sta_info_get(local, hdr.addr1); |
1408 | if (sta) { | 1394 | if (sta) { |
1409 | if (sta->flags & WLAN_STA_WME) { | 1395 | sta_flags = sta->flags; |
1410 | fc |= IEEE80211_STYPE_QOS_DATA; | ||
1411 | hdrlen += 2; | ||
1412 | } | ||
1413 | sta_info_put(sta); | 1396 | sta_info_put(sta); |
1414 | } | 1397 | } |
1415 | 1398 | ||
1399 | /* receiver is QoS enabled, use a QoS type frame */ | ||
1400 | if (sta_flags & WLAN_STA_WME) { | ||
1401 | fc |= IEEE80211_STYPE_QOS_DATA; | ||
1402 | hdrlen += 2; | ||
1403 | } | ||
1404 | |||
1405 | /* | ||
1406 | * If port access control is enabled, drop frames to unauthorised | ||
1407 | * stations unless they are EAPOL frames from the local station. | ||
1408 | */ | ||
1409 | if (unlikely(sdata->ieee802_1x_pac && | ||
1410 | !(sta_flags & WLAN_STA_AUTHORIZED) && | ||
1411 | !(ethertype == ETH_P_PAE && | ||
1412 | compare_ether_addr(dev->dev_addr, | ||
1413 | skb->data + ETH_ALEN) == 0))) { | ||
1414 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1415 | DECLARE_MAC_BUF(mac); | ||
1416 | |||
1417 | if (net_ratelimit()) | ||
1418 | printk(KERN_DEBUG "%s: dropped frame to %s" | ||
1419 | " (unauthorized port)\n", dev->name, | ||
1420 | print_mac(mac, hdr.addr1)); | ||
1421 | #endif | ||
1422 | |||
1423 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); | ||
1424 | |||
1425 | ret = 0; | ||
1426 | goto fail; | ||
1427 | } | ||
1428 | |||
1416 | hdr.frame_control = cpu_to_le16(fc); | 1429 | hdr.frame_control = cpu_to_le16(fc); |
1417 | hdr.duration_id = 0; | 1430 | hdr.duration_id = 0; |
1418 | hdr.seq_ctrl = 0; | 1431 | hdr.seq_ctrl = 0; |