diff options
author | Ron Rindjunsky <ron.rindjunsky@intel.com> | 2007-11-22 12:49:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:55:27 -0500 |
commit | 76ee65bfaa1435320a72989a6413467ce446ae23 (patch) | |
tree | f0e2dec58af542dc7ec53f7eb76c55ae4c3855e8 /net/mac80211/rx.c | |
parent | ece8edddf067d21c4e5abfe3f1205da1588edbb2 (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/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 124 |
1 files changed, 77 insertions, 47 deletions
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 | ||
965 | static ieee80211_txrx_result | 965 | static int |
966 | ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) | 966 | ieee80211_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 | ||
992 | static ieee80211_txrx_result | 988 | static int |
993 | ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) | 989 | ieee80211_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 | ||
1016 | static ieee80211_txrx_result | 1013 | static int |
1017 | ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) | 1014 | ieee80211_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; | 1142 | static void |
1143 | ieee80211_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 | |||
1199 | static ieee80211_txrx_result | ||
1200 | ieee80211_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 |