aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c94
1 files changed, 8 insertions, 86 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index f962bd1b16e2..6a9b8e63a6bf 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1247,93 +1247,12 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
1247} 1247}
1248 1248
1249static int 1249static int
1250ieee80211_data_to_8023(struct ieee80211_rx_data *rx) 1250__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1251{ 1251{
1252 struct net_device *dev = rx->dev; 1252 struct net_device *dev = rx->dev;
1253 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
1254 u16 hdrlen, ethertype;
1255 u8 *payload;
1256 u8 dst[ETH_ALEN];
1257 u8 src[ETH_ALEN] __aligned(2);
1258 struct sk_buff *skb = rx->skb;
1259 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1253 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1260 1254
1261 if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) 1255 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
1262 return -1;
1263
1264 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1265
1266 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
1267 * header
1268 * IEEE 802.11 address fields:
1269 * ToDS FromDS Addr1 Addr2 Addr3 Addr4
1270 * 0 0 DA SA BSSID n/a
1271 * 0 1 DA BSSID SA n/a
1272 * 1 0 BSSID SA DA n/a
1273 * 1 1 RA TA DA SA
1274 */
1275 memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
1276 memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
1277
1278 switch (hdr->frame_control &
1279 cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
1280 case cpu_to_le16(IEEE80211_FCTL_TODS):
1281 if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP &&
1282 sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
1283 return -1;
1284 break;
1285 case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
1286 if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS &&
1287 sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
1288 return -1;
1289 if (ieee80211_vif_is_mesh(&sdata->vif)) {
1290 struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *)
1291 (skb->data + hdrlen);
1292 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
1293 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
1294 memcpy(dst, meshdr->eaddr1, ETH_ALEN);
1295 memcpy(src, meshdr->eaddr2, ETH_ALEN);
1296 }
1297 }
1298 break;
1299 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
1300 if (sdata->vif.type != NL80211_IFTYPE_STATION ||
1301 (is_multicast_ether_addr(dst) &&
1302 !compare_ether_addr(src, dev->dev_addr)))
1303 return -1;
1304 break;
1305 case cpu_to_le16(0):
1306 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
1307 return -1;
1308 break;
1309 }
1310
1311 if (unlikely(skb->len - hdrlen < 8))
1312 return -1;
1313
1314 payload = skb->data + hdrlen;
1315 ethertype = (payload[6] << 8) | payload[7];
1316
1317 if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
1318 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1319 compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
1320 /* remove RFC1042 or Bridge-Tunnel encapsulation and
1321 * replace EtherType */
1322 skb_pull(skb, hdrlen + 6);
1323 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
1324 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
1325 } else {
1326 struct ethhdr *ehdr;
1327 __be16 len;
1328
1329 skb_pull(skb, hdrlen);
1330 len = htons(skb->len);
1331 ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
1332 memcpy(ehdr->h_dest, dst, ETH_ALEN);
1333 memcpy(ehdr->h_source, src, ETH_ALEN);
1334 ehdr->h_proto = len;
1335 }
1336 return 0;
1337} 1256}
1338 1257
1339/* 1258/*
@@ -1472,7 +1391,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
1472 if (!(rx->flags & IEEE80211_RX_AMSDU)) 1391 if (!(rx->flags & IEEE80211_RX_AMSDU))
1473 return RX_CONTINUE; 1392 return RX_CONTINUE;
1474 1393
1475 err = ieee80211_data_to_8023(rx); 1394 err = __ieee80211_data_to_8023(rx);
1476 if (unlikely(err)) 1395 if (unlikely(err))
1477 return RX_DROP_UNUSABLE; 1396 return RX_DROP_UNUSABLE;
1478 1397
@@ -1658,7 +1577,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1658 if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) 1577 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
1659 return RX_DROP_MONITOR; 1578 return RX_DROP_MONITOR;
1660 1579
1661 err = ieee80211_data_to_8023(rx); 1580 err = __ieee80211_data_to_8023(rx);
1662 if (unlikely(err)) 1581 if (unlikely(err))
1663 return RX_DROP_UNUSABLE; 1582 return RX_DROP_UNUSABLE;
1664 1583
@@ -1846,6 +1765,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1846 sizeof(mgmt->u.action.u.chan_switch))) 1765 sizeof(mgmt->u.action.u.chan_switch)))
1847 return RX_DROP_MONITOR; 1766 return RX_DROP_MONITOR;
1848 1767
1768 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1769 return RX_DROP_MONITOR;
1770
1849 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) 1771 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
1850 return RX_DROP_MONITOR; 1772 return RX_DROP_MONITOR;
1851 1773
@@ -1856,7 +1778,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1856 if (!bss) 1778 if (!bss)
1857 return RX_DROP_MONITOR; 1779 return RX_DROP_MONITOR;
1858 1780
1859 ieee80211_process_chanswitch(sdata, 1781 ieee80211_sta_process_chanswitch(sdata,
1860 &mgmt->u.action.u.chan_switch.sw_elem, bss); 1782 &mgmt->u.action.u.chan_switch.sw_elem, bss);
1861 ieee80211_rx_bss_put(local, bss); 1783 ieee80211_rx_bss_put(local, bss);
1862 break; 1784 break;