diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3ab9670f1809..2efa4dd47b5d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1107,10 +1107,6 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1107 | 1107 | ||
1108 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1108 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1109 | 1109 | ||
1110 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1111 | hdrlen += ieee80211_get_mesh_hdrlen( | ||
1112 | (struct ieee80211s_hdr *) (skb->data + hdrlen)); | ||
1113 | |||
1114 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | 1110 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet |
1115 | * header | 1111 | * header |
1116 | * IEEE 802.11 address fields: | 1112 | * IEEE 802.11 address fields: |
@@ -1134,6 +1130,15 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1134 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | 1130 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1135 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | 1131 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1136 | return -1; | 1132 | return -1; |
1133 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1134 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) | ||
1135 | (skb->data + hdrlen); | ||
1136 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
1137 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | ||
1138 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | ||
1139 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | ||
1140 | } | ||
1141 | } | ||
1137 | break; | 1142 | break; |
1138 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): | 1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1139 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | 1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
@@ -1393,6 +1398,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1393 | /* illegal frame */ | 1398 | /* illegal frame */ |
1394 | return RX_DROP_MONITOR; | 1399 | return RX_DROP_MONITOR; |
1395 | 1400 | ||
1401 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | ||
1402 | struct ieee80211_sub_if_data *sdata; | ||
1403 | struct mesh_path *mppath; | ||
1404 | |||
1405 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1406 | rcu_read_lock(); | ||
1407 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | ||
1408 | if (!mppath) { | ||
1409 | mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); | ||
1410 | } else { | ||
1411 | spin_lock_bh(&mppath->state_lock); | ||
1412 | mppath->exp_time = jiffies; | ||
1413 | if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) | ||
1414 | memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); | ||
1415 | spin_unlock_bh(&mppath->state_lock); | ||
1416 | } | ||
1417 | rcu_read_unlock(); | ||
1418 | } | ||
1419 | |||
1396 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1420 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) |
1397 | return RX_CONTINUE; | 1421 | return RX_CONTINUE; |
1398 | 1422 | ||