aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2009-08-10 15:15:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:14:00 -0400
commit3c5772a5279de9eadfff7adb5ddea08106495fff (patch)
tree297772521c18283ccfa19aacb090f396fa2b399e /net/mac80211/rx.c
parenta9e3091bf08ddea35f172549a8a21d5bd6ee6129 (diff)
mac80211: Use 3-address format for mesh broadcast frames.
The 11s task group recently changed the frame mesh multicast/broadcast frame format to use 3-address. This was done to avoid interactions with widely deployed lazy-WDS access points. This patch changes the format of group addressed frames, both mesh-originated and proxied, to use the data format defined in draft D2.08 and forward. The address fields used for group addressed frames is: In 802.11 header ToDS:0 FromDS:1 addr1: DA (broadcast/multicast address) addr2: TA addr3: Mesh SA In address extension header: addr4: SA (only present if frame was proxied) Note that this change breaks backward compatibility with earlier mesh stack versions. Signed-off-by: Andrey Yurovsky <andrey@cozybit.com> Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 25a669c86e14..4cd9e45b1443 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -489,12 +489,21 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
489{ 489{
490 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 490 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
491 unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); 491 unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
492 char *dev_addr = rx->dev->dev_addr;
492 493
493 if (ieee80211_is_data(hdr->frame_control)) { 494 if (ieee80211_is_data(hdr->frame_control)) {
494 if (!ieee80211_has_a4(hdr->frame_control)) 495 if (is_multicast_ether_addr(hdr->addr1)) {
495 return RX_DROP_MONITOR; 496 if (ieee80211_has_tods(hdr->frame_control) ||
496 if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) 497 !ieee80211_has_fromds(hdr->frame_control))
497 return RX_DROP_MONITOR; 498 return RX_DROP_MONITOR;
499 if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
500 return RX_DROP_MONITOR;
501 } else {
502 if (!ieee80211_has_a4(hdr->frame_control))
503 return RX_DROP_MONITOR;
504 if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
505 return RX_DROP_MONITOR;
506 }
498 } 507 }
499 508
500 /* If there is not an established peer link and this is not a peer link 509 /* If there is not an established peer link and this is not a peer link
@@ -527,7 +536,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
527 536
528 if (ieee80211_is_data(hdr->frame_control) && 537 if (ieee80211_is_data(hdr->frame_control) &&
529 is_multicast_ether_addr(hdr->addr1) && 538 is_multicast_ether_addr(hdr->addr1) &&
530 mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) 539 mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
531 return RX_DROP_MONITOR; 540 return RX_DROP_MONITOR;
532#undef msh_h_get 541#undef msh_h_get
533 542
@@ -1495,7 +1504,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1495 /* illegal frame */ 1504 /* illegal frame */
1496 return RX_DROP_MONITOR; 1505 return RX_DROP_MONITOR;
1497 1506
1498 if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ 1507 if (!is_multicast_ether_addr(hdr->addr1) &&
1508 (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6)) {
1499 struct mesh_path *mppath; 1509 struct mesh_path *mppath;
1500 1510
1501 rcu_read_lock(); 1511 rcu_read_lock();
@@ -1512,7 +1522,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1512 rcu_read_unlock(); 1522 rcu_read_unlock();
1513 } 1523 }
1514 1524
1515 if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) 1525 /* Frame has reached destination. Don't forward */
1526 if (!is_multicast_ether_addr(hdr->addr1) &&
1527 compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
1516 return RX_CONTINUE; 1528 return RX_CONTINUE;
1517 1529
1518 mesh_hdr->ttl--; 1530 mesh_hdr->ttl--;
@@ -1532,22 +1544,21 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1532 rx->dev->name); 1544 rx->dev->name);
1533 1545
1534 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; 1546 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
1535 /*
1536 * Save TA to addr1 to send TA a path error if a
1537 * suitable next hop is not found
1538 */
1539 memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
1540 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); 1547 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
1541 info = IEEE80211_SKB_CB(fwd_skb); 1548 info = IEEE80211_SKB_CB(fwd_skb);
1542 memset(info, 0, sizeof(*info)); 1549 memset(info, 0, sizeof(*info));
1543 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 1550 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
1544 info->control.vif = &rx->sdata->vif; 1551 info->control.vif = &rx->sdata->vif;
1545 ieee80211_select_queue(local, fwd_skb); 1552 ieee80211_select_queue(local, fwd_skb);
1546 if (is_multicast_ether_addr(fwd_hdr->addr3)) 1553 if (!is_multicast_ether_addr(fwd_hdr->addr1)) {
1547 memcpy(fwd_hdr->addr1, fwd_hdr->addr3, 1554 int err;
1555 /*
1556 * Save TA to addr1 to send TA a path error if a
1557 * suitable next hop is not found
1558 */
1559 memcpy(fwd_hdr->addr1, fwd_hdr->addr2,
1548 ETH_ALEN); 1560 ETH_ALEN);
1549 else { 1561 err = mesh_nexthop_lookup(fwd_skb, sdata);
1550 int err = mesh_nexthop_lookup(fwd_skb, sdata);
1551 /* Failed to immediately resolve next hop: 1562 /* Failed to immediately resolve next hop:
1552 * fwded frame was dropped or will be added 1563 * fwded frame was dropped or will be added
1553 * later to the pending skb queue. */ 1564 * later to the pending skb queue. */
@@ -1560,7 +1571,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1560 } 1571 }
1561 } 1572 }
1562 1573
1563 if (is_multicast_ether_addr(hdr->addr3) || 1574 if (is_multicast_ether_addr(hdr->addr1) ||
1564 rx->dev->flags & IFF_PROMISC) 1575 rx->dev->flags & IFF_PROMISC)
1565 return RX_CONTINUE; 1576 return RX_CONTINUE;
1566 else 1577 else