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.c116
1 files changed, 67 insertions, 49 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6d9ae67c27ca..6db854505193 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1109,20 +1109,9 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1109 1109
1110 hdrlen = ieee80211_get_hdrlen(fc); 1110 hdrlen = ieee80211_get_hdrlen(fc);
1111 1111
1112 if (ieee80211_vif_is_mesh(&sdata->vif)) { 1112 if (ieee80211_vif_is_mesh(&sdata->vif))
1113 int meshhdrlen = ieee80211_get_mesh_hdrlen( 1113 hdrlen += ieee80211_get_mesh_hdrlen(
1114 (struct ieee80211s_hdr *) (skb->data + hdrlen)); 1114 (struct ieee80211s_hdr *) (skb->data + hdrlen));
1115 /* Copy on cb:
1116 * - mesh header: to be used for mesh forwarding
1117 * decision. It will also be used as mesh header template at
1118 * tx.c:ieee80211_subif_start_xmit() if interface
1119 * type is mesh and skb->pkt_type == PACKET_OTHERHOST
1120 * - ta: to be used if a RERR needs to be sent.
1121 */
1122 memcpy(skb->cb, skb->data + hdrlen, meshhdrlen);
1123 memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN);
1124 hdrlen += meshhdrlen;
1125 }
1126 1115
1127 /* convert IEEE 802.11 header + possible LLC headers into Ethernet 1116 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
1128 * header 1117 * header
@@ -1269,38 +1258,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
1269 } 1258 }
1270 } 1259 }
1271 1260
1272 /* Mesh forwarding */
1273 if (ieee80211_vif_is_mesh(&sdata->vif)) {
1274 u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl;
1275 (*mesh_ttl)--;
1276
1277 if (is_multicast_ether_addr(skb->data)) {
1278 if (*mesh_ttl > 0) {
1279 xmit_skb = skb_copy(skb, GFP_ATOMIC);
1280 if (xmit_skb)
1281 xmit_skb->pkt_type = PACKET_OTHERHOST;
1282 else if (net_ratelimit())
1283 printk(KERN_DEBUG "%s: failed to clone "
1284 "multicast frame\n", dev->name);
1285 } else
1286 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
1287 dropped_frames_ttl);
1288 } else if (skb->pkt_type != PACKET_OTHERHOST &&
1289 compare_ether_addr(dev->dev_addr, skb->data) != 0) {
1290 if (*mesh_ttl == 0) {
1291 IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
1292 dropped_frames_ttl);
1293 dev_kfree_skb(skb);
1294 skb = NULL;
1295 } else {
1296 xmit_skb = skb;
1297 xmit_skb->pkt_type = PACKET_OTHERHOST;
1298 if (!(dev->flags & IFF_PROMISC))
1299 skb = NULL;
1300 }
1301 }
1302 }
1303
1304 if (skb) { 1261 if (skb) {
1305 /* deliver to local stack */ 1262 /* deliver to local stack */
1306 skb->protocol = eth_type_trans(skb, dev); 1263 skb->protocol = eth_type_trans(skb, dev);
@@ -1431,6 +1388,63 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
1431} 1388}
1432 1389
1433static ieee80211_rx_result debug_noinline 1390static ieee80211_rx_result debug_noinline
1391ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1392{
1393 struct ieee80211_hdr *hdr;
1394 struct ieee80211s_hdr *mesh_hdr;
1395 unsigned int hdrlen;
1396 struct sk_buff *skb = rx->skb, *fwd_skb;
1397
1398 hdr = (struct ieee80211_hdr *) skb->data;
1399 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1400 mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
1401
1402 if (!ieee80211_is_data(hdr->frame_control))
1403 return RX_CONTINUE;
1404
1405 if (!mesh_hdr->ttl)
1406 /* illegal frame */
1407 return RX_DROP_MONITOR;
1408
1409 if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
1410 return RX_CONTINUE;
1411
1412 mesh_hdr->ttl--;
1413
1414 if (rx->flags & IEEE80211_RX_RA_MATCH) {
1415 if (!mesh_hdr->ttl)
1416 IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta,
1417 dropped_frames_ttl);
1418 else {
1419 struct ieee80211_hdr *fwd_hdr;
1420 fwd_skb = skb_copy(skb, GFP_ATOMIC);
1421
1422 if (!fwd_skb && net_ratelimit())
1423 printk(KERN_DEBUG "%s: failed to clone mesh frame\n",
1424 rx->dev->name);
1425
1426 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
1427 /*
1428 * Save TA to addr1 to send TA a path error if a
1429 * suitable next hop is not found
1430 */
1431 memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
1432 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
1433 fwd_skb->dev = rx->local->mdev;
1434 fwd_skb->iif = rx->dev->ifindex;
1435 dev_queue_xmit(fwd_skb);
1436 }
1437 }
1438
1439 if (is_multicast_ether_addr(hdr->addr3) ||
1440 rx->dev->flags & IFF_PROMISC)
1441 return RX_CONTINUE;
1442 else
1443 return RX_DROP_MONITOR;
1444}
1445
1446
1447static ieee80211_rx_result debug_noinline
1434ieee80211_rx_h_data(struct ieee80211_rx_data *rx) 1448ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1435{ 1449{
1436 struct net_device *dev = rx->dev; 1450 struct net_device *dev = rx->dev;
@@ -1663,10 +1677,12 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
1663 rx->sdata = sdata; 1677 rx->sdata = sdata;
1664 rx->dev = sdata->dev; 1678 rx->dev = sdata->dev;
1665 1679
1666#define CALL_RXH(rxh) \ 1680#define CALL_RXH(rxh) \
1667 res = rxh(rx); \ 1681 do { \
1668 if (res != RX_CONTINUE) \ 1682 res = rxh(rx); \
1669 goto rxh_done; 1683 if (res != RX_CONTINUE) \
1684 goto rxh_done; \
1685 } while (0);
1670 1686
1671 CALL_RXH(ieee80211_rx_h_passive_scan) 1687 CALL_RXH(ieee80211_rx_h_passive_scan)
1672 CALL_RXH(ieee80211_rx_h_check) 1688 CALL_RXH(ieee80211_rx_h_check)
@@ -1678,6 +1694,8 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
1678 /* must be after MMIC verify so header is counted in MPDU mic */ 1694 /* must be after MMIC verify so header is counted in MPDU mic */
1679 CALL_RXH(ieee80211_rx_h_remove_qos_control) 1695 CALL_RXH(ieee80211_rx_h_remove_qos_control)
1680 CALL_RXH(ieee80211_rx_h_amsdu) 1696 CALL_RXH(ieee80211_rx_h_amsdu)
1697 if (ieee80211_vif_is_mesh(&sdata->vif))
1698 CALL_RXH(ieee80211_rx_h_mesh_fwding);
1681 CALL_RXH(ieee80211_rx_h_data) 1699 CALL_RXH(ieee80211_rx_h_data)
1682 CALL_RXH(ieee80211_rx_h_ctrl) 1700 CALL_RXH(ieee80211_rx_h_ctrl)
1683 CALL_RXH(ieee80211_rx_h_mgmt) 1701 CALL_RXH(ieee80211_rx_h_mgmt)