Root/package/mac80211/patches/541-mac80211_fix_iftype_wds.patch

1--- a/net/mac80211/rx.c
2+++ b/net/mac80211/rx.c
3@@ -2330,13 +2330,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
4 
5     if (!ieee80211_vif_is_mesh(&sdata->vif) &&
6         sdata->vif.type != NL80211_IFTYPE_ADHOC &&
7- sdata->vif.type != NL80211_IFTYPE_STATION)
8+ sdata->vif.type != NL80211_IFTYPE_STATION &&
9+ sdata->vif.type != NL80211_IFTYPE_WDS)
10         return RX_DROP_MONITOR;
11 
12     switch (stype) {
13     case cpu_to_le16(IEEE80211_STYPE_BEACON):
14     case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
15- /* process for all: mesh, mlme, ibss */
16+ /* process for all: mesh, mlme, ibss, wds */
17         break;
18     case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
19     case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
20@@ -2716,7 +2717,10 @@ static int prepare_for_handlers(struct i
21         }
22         break;
23     case NL80211_IFTYPE_WDS:
24- if (bssid || !ieee80211_is_data(hdr->frame_control))
25+ if (bssid) {
26+ if (!ieee80211_is_beacon(hdr->frame_control))
27+ return 0;
28+ } else if (!ieee80211_is_data(hdr->frame_control))
29             return 0;
30         if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
31             return 0;
32--- a/net/mac80211/iface.c
33+++ b/net/mac80211/iface.c
34@@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_
35 {
36     struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
37     struct ieee80211_local *local = sdata->local;
38- struct sta_info *sta;
39     u32 changed = 0;
40     int res;
41     u32 hw_reconf_flags = 0;
42@@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_
43 
44     set_bit(SDATA_STATE_RUNNING, &sdata->state);
45 
46- if (sdata->vif.type == NL80211_IFTYPE_WDS) {
47- /* Create STA entry for the WDS peer */
48- sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
49- GFP_KERNEL);
50- if (!sta) {
51- res = -ENOMEM;
52- goto err_del_interface;
53- }
54-
55- /* no locking required since STA is not live yet */
56- sta->flags |= WLAN_STA_AUTHORIZED;
57-
58- res = sta_info_insert(sta);
59- if (res) {
60- /* STA has been freed */
61- goto err_del_interface;
62- }
63-
64- rate_control_rate_init(sta);
65- }
66-
67     /*
68      * set_multicast_list will be invoked by the networking core
69      * which will check whether any increments here were done in
70@@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_
71     netif_tx_start_all_queues(dev);
72 
73     return 0;
74- err_del_interface:
75- drv_remove_interface(local, &sdata->vif);
76+
77  err_stop:
78     if (!local->open_count)
79         drv_stop(local);
80@@ -717,6 +694,70 @@ static void ieee80211_if_setup(struct ne
81     dev->destructor = free_netdev;
82 }
83 
84+static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
85+ struct sk_buff *skb)
86+{
87+ struct ieee80211_local *local = sdata->local;
88+ struct ieee80211_rx_status *rx_status;
89+ struct ieee802_11_elems elems;
90+ struct ieee80211_mgmt *mgmt;
91+ struct sta_info *sta;
92+ size_t baselen;
93+ u32 rates = 0;
94+ u16 stype;
95+ bool new = false;
96+ enum ieee80211_band band = local->hw.conf.channel->band;
97+ struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
98+
99+ rx_status = IEEE80211_SKB_RXCB(skb);
100+ mgmt = (struct ieee80211_mgmt *) skb->data;
101+ stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
102+
103+ if (stype != IEEE80211_STYPE_BEACON)
104+ return;
105+
106+ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
107+ if (baselen > skb->len)
108+ return;
109+
110+ ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
111+ skb->len - baselen, &elems);
112+
113+ rates = ieee80211_sta_get_rates(local, &elems, band);
114+
115+ rcu_read_lock();
116+
117+ sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
118+
119+ if (!sta) {
120+ rcu_read_unlock();
121+ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
122+ GFP_KERNEL);
123+ if (!sta)
124+ return;
125+
126+ new = true;
127+ }
128+
129+ sta->last_rx = jiffies;
130+ sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
131+
132+ if (elems.ht_cap_elem)
133+ ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
134+ elems.ht_cap_elem, &sta->sta.ht_cap);
135+
136+ if (elems.wmm_param)
137+ set_sta_flags(sta, WLAN_STA_WME);
138+
139+ if (new) {
140+ sta->flags = WLAN_STA_AUTHORIZED;
141+ rate_control_rate_init(sta);
142+ sta_info_insert_rcu(sta);
143+ }
144+
145+ rcu_read_unlock();
146+}
147+
148 static void ieee80211_iface_work(struct work_struct *work)
149 {
150     struct ieee80211_sub_if_data *sdata =
151@@ -821,6 +862,9 @@ static void ieee80211_iface_work(struct
152                 break;
153             ieee80211_mesh_rx_queued_mgmt(sdata, skb);
154             break;
155+ case NL80211_IFTYPE_WDS:
156+ ieee80211_wds_rx_queued_mgmt(sdata, skb);
157+ break;
158         default:
159             WARN(1, "frame for unexpected interface type");
160             break;
161

Archive Download this file



interactive