aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2007-11-22 12:49:12 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:55:27 -0500
commit76ee65bfaa1435320a72989a6413467ce446ae23 (patch)
treef0e2dec58af542dc7ec53f7eb76c55ae4c3855e8 /net/mac80211
parentece8edddf067d21c4e5abfe3f1205da1588edbb2 (diff)
mac80211: restructuring data Rx handlers
This patch restructures the Rx handlers chain by incorporating previously handlers ieee80211_rx_h_802_1x_pae and ieee80211_rx_h_drop_unencrypted into ieee80211_rx_h_data, already in 802.3 form. this scheme follows more precisely after the IEEE802.11 data plane archituecture, and will prevent code duplication to IEEE8021.11n A-MSDU handler. added function: - ieee80211_data_to_8023: transfering 802.11 data frames to 802.3 frame - ieee80211_deliver_skb: delivering the 802.3 frames to upper stack eliminated handlers: - ieee80211_rx_h_drop_unencrypted: now function ieee80211_drop_unencrypted - ieee80211_rx_h_802_1x_pae: now function ieee80211_802_1x_pae changed handlers: - ieee80211_rx_h_data: now contains calls to four above function Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Acked-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/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/rx.c124
-rw-r--r--net/mac80211/tx.c12
-rw-r--r--net/mac80211/util.c14
4 files changed, 86 insertions, 66 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e9109443cb10..e2aed0b2d8be 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -792,7 +792,7 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */
792extern const unsigned char rfc1042_header[6]; 792extern const unsigned char rfc1042_header[6];
793extern const unsigned char bridge_tunnel_header[6]; 793extern const unsigned char bridge_tunnel_header[6];
794u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); 794u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len);
795int ieee80211_is_eapol(const struct sk_buff *skb); 795int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen);
796int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 796int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
797 int rate, int erp, int short_preamble); 797 int rate, int erp, int short_preamble);
798void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, 798void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a26aa7f50495..478d85563bdb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -962,68 +962,64 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
962 return TXRX_CONTINUE; 962 return TXRX_CONTINUE;
963} 963}
964 964
965static ieee80211_txrx_result 965static int
966ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) 966ieee80211_drop_802_1x_pae(struct ieee80211_txrx_data *rx, int hdrlen)
967{ 967{
968 if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) && 968 if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb, hdrlen) &&
969 rx->sdata->type != IEEE80211_IF_TYPE_STA && 969 rx->sdata->type != IEEE80211_IF_TYPE_STA &&
970 (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) 970 (rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
971 return TXRX_CONTINUE; 971 return 0;
972 972
973 if (unlikely(rx->sdata->ieee802_1x && 973 if (unlikely(rx->sdata->ieee802_1x &&
974 (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && 974 (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
975 (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && 975 (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
976 (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) && 976 (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)) &&
977 !ieee80211_is_eapol(rx->skb))) { 977 !ieee80211_is_eapol(rx->skb, hdrlen))) {
978#ifdef CONFIG_MAC80211_DEBUG 978#ifdef CONFIG_MAC80211_DEBUG
979 struct ieee80211_hdr *hdr = 979 printk(KERN_DEBUG "%s: dropped frame "
980 (struct ieee80211_hdr *) rx->skb->data; 980 "(unauthorized port)\n", rx->dev->name);
981 DECLARE_MAC_BUF(mac);
982 printk(KERN_DEBUG "%s: dropped frame from %s"
983 " (unauthorized port)\n", rx->dev->name,
984 print_mac(mac, hdr->addr2));
985#endif /* CONFIG_MAC80211_DEBUG */ 981#endif /* CONFIG_MAC80211_DEBUG */
986 return TXRX_DROP; 982 return -EACCES;
987 } 983 }
988 984
989 return TXRX_CONTINUE; 985 return 0;
990} 986}
991 987
992static ieee80211_txrx_result 988static int
993ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) 989ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx, int hdrlen)
994{ 990{
995 /* 991 /*
996 * Pass through unencrypted frames if the hardware has 992 * Pass through unencrypted frames if the hardware has
997 * decrypted them already. 993 * decrypted them already.
998 */ 994 */
999 if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) 995 if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
1000 return TXRX_CONTINUE; 996 return 0;
1001 997
1002 /* Drop unencrypted frames if key is set. */ 998 /* Drop unencrypted frames if key is set. */
1003 if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && 999 if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
1004 (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && 1000 (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
1005 (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && 1001 (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
1006 (rx->key || rx->sdata->drop_unencrypted) && 1002 (rx->key || rx->sdata->drop_unencrypted) &&
1007 (rx->sdata->eapol == 0 || !ieee80211_is_eapol(rx->skb)))) { 1003 (rx->sdata->eapol == 0 ||
1004 !ieee80211_is_eapol(rx->skb, hdrlen)))) {
1008 if (net_ratelimit()) 1005 if (net_ratelimit())
1009 printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " 1006 printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
1010 "encryption\n", rx->dev->name); 1007 "encryption\n", rx->dev->name);
1011 return TXRX_DROP; 1008 return -EACCES;
1012 } 1009 }
1013 return TXRX_CONTINUE; 1010 return 0;
1014} 1011}
1015 1012
1016static ieee80211_txrx_result 1013static int
1017ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) 1014ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
1018{ 1015{
1019 struct net_device *dev = rx->dev; 1016 struct net_device *dev = rx->dev;
1020 struct ieee80211_local *local = rx->local;
1021 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; 1017 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
1022 u16 fc, hdrlen, ethertype; 1018 u16 fc, hdrlen, ethertype;
1023 u8 *payload; 1019 u8 *payload;
1024 u8 dst[ETH_ALEN]; 1020 u8 dst[ETH_ALEN];
1025 u8 src[ETH_ALEN]; 1021 u8 src[ETH_ALEN];
1026 struct sk_buff *skb = rx->skb, *skb2; 1022 struct sk_buff *skb = rx->skb;
1027 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1023 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1028 DECLARE_MAC_BUF(mac); 1024 DECLARE_MAC_BUF(mac);
1029 DECLARE_MAC_BUF(mac2); 1025 DECLARE_MAC_BUF(mac2);
@@ -1031,11 +1027,9 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1031 DECLARE_MAC_BUF(mac4); 1027 DECLARE_MAC_BUF(mac4);
1032 1028
1033 fc = rx->fc; 1029 fc = rx->fc;
1034 if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
1035 return TXRX_CONTINUE;
1036 1030
1037 if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) 1031 if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
1038 return TXRX_DROP; 1032 return -1;
1039 1033
1040 hdrlen = ieee80211_get_hdrlen(fc); 1034 hdrlen = ieee80211_get_hdrlen(fc);
1041 1035
@@ -1064,7 +1058,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1064 print_mac(mac, hdr->addr1), 1058 print_mac(mac, hdr->addr1),
1065 print_mac(mac2, hdr->addr2), 1059 print_mac(mac2, hdr->addr2),
1066 print_mac(mac3, hdr->addr3)); 1060 print_mac(mac3, hdr->addr3));
1067 return TXRX_DROP; 1061 return -1;
1068 } 1062 }
1069 break; 1063 break;
1070 case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): 1064 case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
@@ -1081,7 +1075,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1081 print_mac(mac2, hdr->addr2), 1075 print_mac(mac2, hdr->addr2),
1082 print_mac(mac3, hdr->addr3), 1076 print_mac(mac3, hdr->addr3),
1083 print_mac(mac4, hdr->addr4)); 1077 print_mac(mac4, hdr->addr4));
1084 return TXRX_DROP; 1078 return -1;
1085 } 1079 }
1086 break; 1080 break;
1087 case IEEE80211_FCTL_FROMDS: 1081 case IEEE80211_FCTL_FROMDS:
@@ -1092,7 +1086,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1092 if (sdata->type != IEEE80211_IF_TYPE_STA || 1086 if (sdata->type != IEEE80211_IF_TYPE_STA ||
1093 (is_multicast_ether_addr(dst) && 1087 (is_multicast_ether_addr(dst) &&
1094 !compare_ether_addr(src, dev->dev_addr))) 1088 !compare_ether_addr(src, dev->dev_addr)))
1095 return TXRX_DROP; 1089 return -1;
1096 break; 1090 break;
1097 case 0: 1091 case 0:
1098 /* DA SA BSSID */ 1092 /* DA SA BSSID */
@@ -1108,21 +1102,20 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1108 print_mac(mac2, hdr->addr2), 1102 print_mac(mac2, hdr->addr2),
1109 print_mac(mac3, hdr->addr3)); 1103 print_mac(mac3, hdr->addr3));
1110 } 1104 }
1111 return TXRX_DROP; 1105 return -1;
1112 } 1106 }
1113 break; 1107 break;
1114 } 1108 }
1115 1109
1116 payload = skb->data + hdrlen;
1117
1118 if (unlikely(skb->len - hdrlen < 8)) { 1110 if (unlikely(skb->len - hdrlen < 8)) {
1119 if (net_ratelimit()) { 1111 if (net_ratelimit()) {
1120 printk(KERN_DEBUG "%s: RX too short data frame " 1112 printk(KERN_DEBUG "%s: RX too short data frame "
1121 "payload\n", dev->name); 1113 "payload\n", dev->name);
1122 } 1114 }
1123 return TXRX_DROP; 1115 return -1;
1124 } 1116 }
1125 1117
1118 payload = skb->data + hdrlen;
1126 ethertype = (payload[6] << 8) | payload[7]; 1119 ethertype = (payload[6] << 8) | payload[7];
1127 1120
1128 if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && 1121 if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
@@ -1143,12 +1136,19 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1143 memcpy(ehdr->h_source, src, ETH_ALEN); 1136 memcpy(ehdr->h_source, src, ETH_ALEN);
1144 ehdr->h_proto = len; 1137 ehdr->h_proto = len;
1145 } 1138 }
1146 skb->dev = dev; 1139 return 0;
1140}
1147 1141
1148 skb2 = NULL; 1142static void
1143ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
1144{
1145 struct net_device *dev = rx->dev;
1146 struct ieee80211_local *local = rx->local;
1147 struct sk_buff *skb, *xmit_skb;
1148 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1149 1149
1150 dev->stats.rx_packets++; 1150 skb = rx->skb;
1151 dev->stats.rx_bytes += skb->len; 1151 xmit_skb = NULL;
1152 1152
1153 if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP 1153 if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
1154 || sdata->type == IEEE80211_IF_TYPE_VLAN) && 1154 || sdata->type == IEEE80211_IF_TYPE_VLAN) &&
@@ -1156,8 +1156,8 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1156 if (is_multicast_ether_addr(skb->data)) { 1156 if (is_multicast_ether_addr(skb->data)) {
1157 /* send multicast frames both to higher layers in 1157 /* send multicast frames both to higher layers in
1158 * local net stack and back to the wireless media */ 1158 * local net stack and back to the wireless media */
1159 skb2 = skb_copy(skb, GFP_ATOMIC); 1159 xmit_skb = skb_copy(skb, GFP_ATOMIC);
1160 if (!skb2 && net_ratelimit()) 1160 if (!xmit_skb && net_ratelimit())
1161 printk(KERN_DEBUG "%s: failed to clone " 1161 printk(KERN_DEBUG "%s: failed to clone "
1162 "multicast frame\n", dev->name); 1162 "multicast frame\n", dev->name);
1163 } else { 1163 } else {
@@ -1172,7 +1172,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1172 * AP, so send the frame directly to it and 1172 * AP, so send the frame directly to it and
1173 * do not pass the frame to local net stack. 1173 * do not pass the frame to local net stack.
1174 */ 1174 */
1175 skb2 = skb; 1175 xmit_skb = skb;
1176 skb = NULL; 1176 skb = NULL;
1177 } 1177 }
1178 if (dsta) 1178 if (dsta)
@@ -1187,13 +1187,45 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1187 netif_rx(skb); 1187 netif_rx(skb);
1188 } 1188 }
1189 1189
1190 if (skb2) { 1190 if (xmit_skb) {
1191 /* send to wireless media */ 1191 /* send to wireless media */
1192 skb2->protocol = __constant_htons(ETH_P_802_3); 1192 xmit_skb->protocol = __constant_htons(ETH_P_802_3);
1193 skb_set_network_header(skb2, 0); 1193 skb_set_network_header(xmit_skb, 0);
1194 skb_set_mac_header(skb2, 0); 1194 skb_set_mac_header(xmit_skb, 0);
1195 dev_queue_xmit(skb2); 1195 dev_queue_xmit(xmit_skb);
1196 } 1196 }
1197}
1198
1199static ieee80211_txrx_result
1200ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1201{
1202 struct net_device *dev = rx->dev;
1203 u16 fc;
1204 int err, hdrlen;
1205
1206 fc = rx->fc;
1207 if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
1208 return TXRX_CONTINUE;
1209
1210 if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
1211 return TXRX_DROP;
1212
1213 hdrlen = ieee80211_get_hdrlen(fc);
1214
1215 if ((ieee80211_drop_802_1x_pae(rx, hdrlen)) ||
1216 (ieee80211_drop_unencrypted(rx, hdrlen)))
1217 return TXRX_DROP;
1218
1219 err = ieee80211_data_to_8023(rx);
1220 if (unlikely(err))
1221 return TXRX_DROP;
1222
1223 rx->skb->dev = dev;
1224
1225 dev->stats.rx_packets++;
1226 dev->stats.rx_bytes += rx->skb->len;
1227
1228 ieee80211_deliver_skb(rx);
1197 1229
1198 return TXRX_QUEUED; 1230 return TXRX_QUEUED;
1199} 1231}
@@ -1347,8 +1379,6 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
1347 * are not passed to user space by these functions 1379 * are not passed to user space by these functions
1348 */ 1380 */
1349 ieee80211_rx_h_remove_qos_control, 1381 ieee80211_rx_h_remove_qos_control,
1350 ieee80211_rx_h_802_1x_pae,
1351 ieee80211_rx_h_drop_unencrypted,
1352 ieee80211_rx_h_data, 1382 ieee80211_rx_h_data,
1353 ieee80211_rx_h_mgmt, 1383 ieee80211_rx_h_mgmt,
1354 NULL 1384 NULL
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 50ab4b2de1e9..12c15588af68 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -420,7 +420,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
420 return TXRX_CONTINUE; 420 return TXRX_CONTINUE;
421} 421}
422 422
423
424static ieee80211_txrx_result 423static ieee80211_txrx_result
425ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx) 424ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
426{ 425{
@@ -433,13 +432,15 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
433 return ieee80211_tx_h_multicast_ps_buf(tx); 432 return ieee80211_tx_h_multicast_ps_buf(tx);
434} 433}
435 434
436
437
438
439static ieee80211_txrx_result 435static ieee80211_txrx_result
440ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx) 436ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
441{ 437{
442 struct ieee80211_key *key; 438 struct ieee80211_key *key;
439 const struct ieee80211_hdr *hdr;
440 u16 fc;
441
442 hdr = (const struct ieee80211_hdr *) tx->skb->data;
443 fc = le16_to_cpu(hdr->frame_control);
443 444
444 if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) 445 if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
445 tx->key = NULL; 446 tx->key = NULL;
@@ -448,7 +449,8 @@ ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
448 else if ((key = rcu_dereference(tx->sdata->default_key))) 449 else if ((key = rcu_dereference(tx->sdata->default_key)))
449 tx->key = key; 450 tx->key = key;
450 else if (tx->sdata->drop_unencrypted && 451 else if (tx->sdata->drop_unencrypted &&
451 !(tx->sdata->eapol && ieee80211_is_eapol(tx->skb))) { 452 !(tx->sdata->eapol &&
453 ieee80211_is_eapol(tx->skb, ieee80211_get_hdrlen(fc)))) {
452 I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); 454 I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
453 return TXRX_DROP; 455 return TXRX_DROP;
454 } else { 456 } else {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 88f262baaa5e..5227c16f113e 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -218,23 +218,11 @@ int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
218} 218}
219EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); 219EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
220 220
221int ieee80211_is_eapol(const struct sk_buff *skb) 221int ieee80211_is_eapol(const struct sk_buff *skb, int hdrlen)
222{ 222{
223 const struct ieee80211_hdr *hdr;
224 u16 fc;
225 int hdrlen;
226
227 if (unlikely(skb->len < 10)) 223 if (unlikely(skb->len < 10))
228 return 0; 224 return 0;
229 225
230 hdr = (const struct ieee80211_hdr *) skb->data;
231 fc = le16_to_cpu(hdr->frame_control);
232
233 if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
234 return 0;
235
236 hdrlen = ieee80211_get_hdrlen(fc);
237
238 if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) && 226 if (unlikely(skb->len >= hdrlen + sizeof(eapol_header) &&
239 memcmp(skb->data + hdrlen, eapol_header, 227 memcmp(skb->data + hdrlen, eapol_header,
240 sizeof(eapol_header)) == 0)) 228 sizeof(eapol_header)) == 0))