diff options
-rw-r--r-- | net/mac80211/mesh.c | 60 | ||||
-rw-r--r-- | net/mac80211/rx.c | 5 |
2 files changed, 63 insertions, 2 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6ff8ee9d9ff5..a77d40ed4e61 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -868,6 +868,63 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
868 | sdata->u.mesh.timers_running = 0; | 868 | sdata->u.mesh.timers_running = 0; |
869 | } | 869 | } |
870 | 870 | ||
871 | static void | ||
872 | ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, | ||
873 | struct ieee80211_mgmt *mgmt, size_t len) | ||
874 | { | ||
875 | struct ieee80211_local *local = sdata->local; | ||
876 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
877 | struct sk_buff *presp; | ||
878 | struct beacon_data *bcn; | ||
879 | struct ieee80211_mgmt *hdr; | ||
880 | struct ieee802_11_elems elems; | ||
881 | size_t baselen; | ||
882 | u8 *pos, *end; | ||
883 | |||
884 | end = ((u8 *) mgmt) + len; | ||
885 | pos = mgmt->u.probe_req.variable; | ||
886 | baselen = (u8 *) pos - (u8 *) mgmt; | ||
887 | if (baselen > len) | ||
888 | return; | ||
889 | |||
890 | ieee802_11_parse_elems(pos, len - baselen, &elems); | ||
891 | |||
892 | /* 802.11-2012 10.1.4.3.2 */ | ||
893 | if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) && | ||
894 | !is_broadcast_ether_addr(mgmt->da)) || | ||
895 | elems.ssid_len != 0) | ||
896 | return; | ||
897 | |||
898 | if (elems.mesh_id_len != 0 && | ||
899 | (elems.mesh_id_len != ifmsh->mesh_id_len || | ||
900 | memcmp(elems.mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len))) | ||
901 | return; | ||
902 | |||
903 | rcu_read_lock(); | ||
904 | bcn = rcu_dereference(ifmsh->beacon); | ||
905 | |||
906 | if (!bcn) | ||
907 | goto out; | ||
908 | |||
909 | presp = dev_alloc_skb(local->tx_headroom + | ||
910 | bcn->head_len + bcn->tail_len); | ||
911 | if (!presp) | ||
912 | goto out; | ||
913 | |||
914 | skb_reserve(presp, local->tx_headroom); | ||
915 | memcpy(skb_put(presp, bcn->head_len), bcn->head, bcn->head_len); | ||
916 | memcpy(skb_put(presp, bcn->tail_len), bcn->tail, bcn->tail_len); | ||
917 | hdr = (struct ieee80211_mgmt *) presp->data; | ||
918 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
919 | IEEE80211_STYPE_PROBE_RESP); | ||
920 | memcpy(hdr->da, mgmt->sa, ETH_ALEN); | ||
921 | mpl_dbg(sdata, "sending probe resp. to %pM\n", hdr->da); | ||
922 | IEEE80211_SKB_CB(presp)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
923 | ieee80211_tx_skb(sdata, presp); | ||
924 | out: | ||
925 | rcu_read_unlock(); | ||
926 | } | ||
927 | |||
871 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | 928 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, |
872 | u16 stype, | 929 | u16 stype, |
873 | struct ieee80211_mgmt *mgmt, | 930 | struct ieee80211_mgmt *mgmt, |
@@ -957,6 +1014,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
957 | ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, | 1014 | ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, |
958 | rx_status); | 1015 | rx_status); |
959 | break; | 1016 | break; |
1017 | case IEEE80211_STYPE_PROBE_REQ: | ||
1018 | ieee80211_mesh_rx_probe_req(sdata, mgmt, skb->len); | ||
1019 | break; | ||
960 | case IEEE80211_STYPE_ACTION: | 1020 | case IEEE80211_STYPE_ACTION: |
961 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); | 1021 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); |
962 | break; | 1022 | break; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 30f1ba6de8f3..296a4aeadedc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2718,8 +2718,9 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
2718 | return RX_DROP_MONITOR; | 2718 | return RX_DROP_MONITOR; |
2719 | break; | 2719 | break; |
2720 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): | 2720 | case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): |
2721 | /* process only for ibss */ | 2721 | /* process only for ibss and mesh */ |
2722 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 2722 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2723 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
2723 | return RX_DROP_MONITOR; | 2724 | return RX_DROP_MONITOR; |
2724 | break; | 2725 | break; |
2725 | default: | 2726 | default: |