madwifi: fix various noderef/memleak issues
[openwrt/svn-archive/archive.git] / package / madwifi / patches / 451-ibss_race_fix.patch
1 --- a/net80211/ieee80211_input.c
2 +++ b/net80211/ieee80211_input.c
3 @@ -294,10 +294,10 @@ ieee80211_input(struct ieee80211vap * va
4 break;
5 case IEEE80211_M_IBSS:
6 case IEEE80211_M_AHDEMO:
7 - if (!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) ||
8 + if ((!IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid) ||
9 (!IEEE80211_ADDR_EQ(wh->i_addr1, vap->iv_myaddr) &&
10 - !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
11 - (subtype != IEEE80211_FC0_SUBTYPE_BEACON))) {
12 + !IEEE80211_IS_MULTICAST(wh->i_addr1))) &&
13 + (type == IEEE80211_FC0_TYPE_DATA)) {
14 if (!(vap->iv_dev->flags & IFF_PROMISC)) {
15 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
16 bssid, NULL, "%s", "not to bss");
17 @@ -322,22 +322,15 @@ ieee80211_input(struct ieee80211vap * va
18 }
19 /* Do not try to find a node reference if the packet really did come from the BSS */
20 if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss &&
21 - !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2) &&
22 IEEE80211_ADDR_EQ(vap->iv_bssid, wh->i_addr3)) {
23 /* Try to find sender in local node table. */
24 - ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
25 + if (!ni_or_null) {
26 + ieee80211_unref_node(&ni);
27 + ni = ieee80211_find_txnode(vap, wh->i_addr2);
28 + }
29 if (ni == NULL) {
30 - /*
31 - * Fake up a node for this newly discovered
32 - * member of the IBSS. This should probably
33 - * done after an ACL check.
34 - */
35 - ni = ieee80211_fakeup_adhoc_node(vap,
36 - wh->i_addr2);
37 - if (ni == NULL) {
38 - /* NB: stat kept for alloc failure */
39 - goto err;
40 - }
41 + /* NB: stat kept for alloc failure */
42 + goto discard;
43 }
44 }
45 iwspy_event(vap, ni, rssi);
46 @@ -3553,8 +3546,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
47 (((vap->iv_opmode == IEEE80211_M_HOSTAP) ||
48 (vap->iv_opmode == IEEE80211_M_WDS)) &&
49 (scan.capinfo & IEEE80211_CAPINFO_ESS))) {
50 + struct ieee80211_node *tni = NULL;
51 struct ieee80211vap *avp = NULL;
52 - int do_unref = 0;
53 int found = 0;
54
55 IEEE80211_LOCK_IRQ(vap->iv_ic);
56 @@ -3568,14 +3561,12 @@ ieee80211_recv_mgmt(struct ieee80211vap
57 }
58 }
59 if (found)
60 - ni = ni_or_null = avp->iv_wdsnode;
61 + tni = ieee80211_ref_node(avp->iv_wdsnode);
62 } else if (vap->iv_opmode == IEEE80211_M_WDS) {
63 found = 1;
64 - ni = ni_or_null = vap->iv_wdsnode;
65 - } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
66 - ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
67 - if (ni_or_null)
68 - ni = ni_or_null;
69 + tni = ieee80211_ref_node(vap->iv_wdsnode);
70 + } else if ((vap->iv_opmode == IEEE80211_M_IBSS) && (vap->iv_state == IEEE80211_S_RUN)) {
71 + tni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
72 found = 1;
73 }
74 IEEE80211_UNLOCK_IRQ(vap->iv_ic);
75 @@ -3583,20 +3574,21 @@ ieee80211_recv_mgmt(struct ieee80211vap
76 if (!found)
77 break;
78
79 - if (ni_or_null == NULL) {
80 + memcpy(&SKB_CB(skb)->beacon_tsf, scan.tstamp, sizeof(u_int64_t));
81 +
82 + if (tni == NULL) {
83 if (avp) {
84 IEEE80211_LOCK_IRQ(ic);
85 - ni = ieee80211_add_neighbor(avp, wh, &scan);
86 + tni = ieee80211_add_neighbor(avp, wh, &scan);
87 /* force assoc */
88 - ni->ni_associd |= 0xc000;
89 - avp->iv_wdsnode = ieee80211_ref_node(ni);
90 + tni->ni_associd |= 0xc000;
91 + avp->iv_wdsnode = ieee80211_ref_node(tni);
92 IEEE80211_UNLOCK_IRQ(ic);
93 } else if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
94 IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
95 /* Create a new entry in the neighbor table. */
96 - ni = ieee80211_add_neighbor(vap, wh, &scan);
97 + tni = ieee80211_add_neighbor(vap, wh, &scan);
98 }
99 - do_unref = 1;
100 } else {
101 /*
102 * Copy data from beacon to neighbor table.
103 @@ -3604,39 +3596,38 @@ ieee80211_recv_mgmt(struct ieee80211vap
104 * ieee80211_add_neighbor(), so we just copy
105 * everything over to be safe.
106 */
107 - ni->ni_esslen = scan.ssid[1];
108 - memcpy(ni->ni_essid, scan.ssid + 2, scan.ssid[1]);
109 - IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
110 - memcpy(ni->ni_tstamp.data, scan.tstamp,
111 - sizeof(ni->ni_tstamp));
112 - ni->ni_inact = ni->ni_inact_reload;
113 - ni->ni_intval =
114 + tni->ni_esslen = scan.ssid[1];
115 + memcpy(tni->ni_essid, scan.ssid + 2, scan.ssid[1]);
116 + IEEE80211_ADDR_COPY(tni->ni_bssid, wh->i_addr3);
117 + memcpy(tni->ni_tstamp.data, scan.tstamp,
118 + sizeof(tni->ni_tstamp));
119 + tni->ni_inact = tni->ni_inact_reload;
120 + tni->ni_intval =
121 IEEE80211_BINTVAL_SANITISE(scan.bintval);
122 - ni->ni_capinfo = scan.capinfo;
123 - ni->ni_chan = ic->ic_curchan;
124 - ni->ni_fhdwell = scan.fhdwell;
125 - ni->ni_fhindex = scan.fhindex;
126 - ni->ni_erp = scan.erp;
127 - ni->ni_timoff = scan.timoff;
128 + tni->ni_capinfo = scan.capinfo;
129 + tni->ni_chan = ic->ic_curchan;
130 + tni->ni_fhdwell = scan.fhdwell;
131 + tni->ni_fhindex = scan.fhindex;
132 + tni->ni_erp = scan.erp;
133 + tni->ni_timoff = scan.timoff;
134 if (scan.wme != NULL)
135 - ieee80211_saveie(&ni->ni_wme_ie, scan.wme);
136 + ieee80211_saveie(&tni->ni_wme_ie, scan.wme);
137 if (scan.wpa != NULL)
138 - ieee80211_saveie(&ni->ni_wpa_ie, scan.wpa);
139 + ieee80211_saveie(&tni->ni_wpa_ie, scan.wpa);
140 if (scan.rsn != NULL)
141 - ieee80211_saveie(&ni->ni_rsn_ie, scan.rsn);
142 + ieee80211_saveie(&tni->ni_rsn_ie, scan.rsn);
143 if (scan.ath != NULL)
144 - ieee80211_saveath(ni, scan.ath);
145 + ieee80211_saveath(tni, scan.ath);
146
147 /* NB: must be after ni_chan is setup */
148 - ieee80211_setup_rates(ni, scan.rates,
149 + ieee80211_setup_rates(tni, scan.rates,
150 scan.xrates, IEEE80211_F_DOSORT);
151 }
152 - if (ni != NULL) {
153 - ni->ni_rssi = rssi;
154 - ni->ni_rtsf = rtsf;
155 - ni->ni_last_rx = jiffies;
156 - if (do_unref)
157 - ieee80211_unref_node(&ni);
158 + if (tni != NULL) {
159 + tni->ni_rssi = rssi;
160 + tni->ni_rtsf = rtsf;
161 + tni->ni_last_rx = jiffies;
162 + ieee80211_unref_node(&tni);
163 }
164 }
165 break;
166 --- a/net80211/ieee80211_node.c
167 +++ b/net80211/ieee80211_node.c
168 @@ -53,6 +53,7 @@
169
170 #include <net80211/ieee80211_var.h>
171 #include <net80211/if_athproto.h>
172 +#include <net80211/ieee80211_node.h>
173
174 /*
175 * Association IDs are managed with a bit vector.
176 @@ -317,16 +318,11 @@ ieee80211_create_ibss(struct ieee80211va
177 /* Check to see if we already have a node for this mac
178 * NB: we gain a node reference here
179 */
180 - ni = ieee80211_find_txnode(vap, vap->iv_myaddr);
181 + ieee80211_node_table_reset(&ic->ic_sta, vap);
182 + ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
183 if (ni == NULL) {
184 - ni = ieee80211_alloc_node_table(vap, vap->iv_myaddr);
185 - IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
186 - "%s: ni:%p allocated for " MAC_FMT "\n",
187 - __func__, ni, MAC_ADDR(vap->iv_myaddr));
188 - if (ni == NULL) {
189 - /* XXX recovery? */
190 - return;
191 - }
192 + /* XXX recovery? */
193 + return;
194 }
195
196 IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr);
197 @@ -429,8 +425,8 @@ ieee80211_reset_bss(struct ieee80211vap
198 __func__, ni, MAC_ADDR(vap->iv_myaddr));
199 KASSERT(ni != NULL, ("unable to setup inital BSS node"));
200
201 - vap->iv_bss = ieee80211_ref_node(ni);
202 - KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 3),
203 + vap->iv_bss = ni;
204 + KASSERT((atomic_read(&vap->iv_bss->ni_refcnt) == 2),
205 ("wrong refcount for new node."));
206
207 if (obss != NULL) {
208 @@ -647,7 +643,7 @@ ieee80211_sta_join1(struct ieee80211_nod
209 (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
210 vap->iv_bss = selbs;
211 IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
212 - if (obss != NULL) {
213 + if ((obss != NULL) && (obss != selbs)) {
214 if (obss->ni_table)
215 ieee80211_node_leave(obss);
216 ieee80211_unref_node(&obss);
217 --- a/ath/if_ath.c
218 +++ b/ath/if_ath.c
219 @@ -6625,14 +6625,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
220
221 sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
222
223 - /* Lookup the new node if any (this grabs a reference to it) */
224 - ni = ieee80211_find_rxnode(vap->iv_ic, vap,
225 - (const struct ieee80211_frame_min *)skb->data);
226 - if (ni == NULL) {
227 - DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
228 - return;
229 - }
230 -
231 switch (subtype) {
232 case IEEE80211_FC0_SUBTYPE_BEACON:
233 /* update RSSI statistics for use by the HAL */
234 @@ -6654,11 +6646,9 @@ ath_recv_mgmt(struct ieee80211vap * vap,
235 * we do the IBSS merging in software. Also do not merge
236 * if the difference it too small. Otherwise we are playing
237 * tsf-pingpong with other vendors drivers */
238 - beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
239 - if (beacon_tsf > rtsf + 0xffff) {
240 + beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
241 + if (beacon_tsf > rtsf + 0xffff)
242 ath_hal_settsf64(sc->sc_ah, beacon_tsf - rtsf);
243 - ieee80211_ibss_merge(ni);
244 - }
245 break;
246 }
247 /* NB: Fall Through */
248 @@ -6680,13 +6670,21 @@ ath_recv_mgmt(struct ieee80211vap * vap,
249 hw_tsf = ath_hal_gettsf64(sc->sc_ah);
250 hw_tu = hw_tsf >> 10;
251
252 - beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
253 + beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
254 beacon_tu = beacon_tsf >> 10;
255
256 + if (!beacon_tsf)
257 + break;
258 +
259 + if (IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid))
260 + break;
261 +
262 DPRINTF(sc, ATH_DEBUG_BEACON,
263 - "Beacon transmitted at %10llx, "
264 + "Beacon transmitted from "MAC_FMT" ("MAC_FMT") at %10llx, "
265 "received at %10llx(%lld), hw TSF "
266 "%10llx(%lld)\n",
267 + MAC_ADDR(wh->i_addr3),
268 + MAC_ADDR(vap->iv_bssid),
269 beacon_tsf,
270 rtsf, rtsf - beacon_tsf,
271 hw_tsf, hw_tsf - beacon_tsf);
272 @@ -6699,39 +6697,13 @@ ath_recv_mgmt(struct ieee80211vap * vap,
273 do_merge = 1;
274 }
275
276 - /* Check sc_nexttbtt */
277 - if (sc->sc_nexttbtt < hw_tu) {
278 - DPRINTF(sc, ATH_DEBUG_BEACON,
279 - "sc_nexttbtt (%8x TU) is in the past "
280 - "(tsf %8x TU), updating timers\n",
281 - sc->sc_nexttbtt, hw_tu);
282 - do_merge = 1;
283 - }
284 -
285 - intval = ni->ni_intval & HAL_BEACON_PERIOD;
286 -#if 0
287 - /* This code is disabled since it would produce
288 - * unwanted merge. For instance, in a two nodes network
289 - * A & B, A can merge to B and at the same time, B will
290 - * merge to A, still having a split */
291 - if (intval != 0) {
292 - if ((sc->sc_nexttbtt % intval) !=
293 - (beacon_tu % intval)) {
294 - DPRINTF(sc, ATH_DEBUG_BEACON,
295 - "ibss merge: "
296 - "sc_nexttbtt %10x TU "
297 - "(%3d) beacon %10x TU "
298 - "(%3d)\n",
299 - sc->sc_nexttbtt,
300 - sc->sc_nexttbtt % intval,
301 - beacon_tu,
302 - beacon_tu % intval);
303 - do_merge = 1;
304 - }
305 - }
306 -#endif
307 - if (do_merge)
308 + if (do_merge) {
309 + /* Lookup the new node if any (this grabs a reference to it) */
310 + ni = ieee80211_find_txnode(vap, wh->i_addr2);
311 + memcpy(ni->ni_bssid, wh->i_addr3, IEEE80211_ADDR_LEN);
312 ieee80211_ibss_merge(ni);
313 + ieee80211_unref_node(&ni);
314 + }
315
316 if ((sc->sc_opmode == HAL_M_IBSS) &&
317 ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval))
318 @@ -6739,8 +6711,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
319 }
320 break;
321 }
322 -
323 - ieee80211_unref_node(&ni);
324 }
325
326 static void
327 --- a/net80211/ieee80211_linux.h
328 +++ b/net80211/ieee80211_linux.h
329 @@ -411,7 +411,7 @@ typedef spinlock_t acl_lock_t;
330 * 8 bytes so we reserve/avoid it.
331 */
332 struct ieee80211_cb {
333 - u_int8_t vlan[8]; /* reserve for vlan tag info */
334 + u_int64_t beacon_tsf;
335 struct ieee80211_node *ni;
336 u_int32_t flags;
337 #define M_LINK0 0x01 /* frame needs WEP encryption */
338 --- a/net80211/ieee80211_scan_sta.c
339 +++ b/net80211/ieee80211_scan_sta.c
340 @@ -1125,11 +1125,8 @@ adhoc_default_action(struct ieee80211vap
341 u_int8_t zeroMacAddr[IEEE80211_ADDR_LEN];
342
343 memset(&zeroMacAddr, 0, IEEE80211_ADDR_LEN);
344 - if (IEEE80211_ADDR_EQ(se->se_bssid, &zeroMacAddr[0])) {
345 - ieee80211_create_ibss(vap, se->se_chan);
346 - return 1;
347 - } else
348 - return ieee80211_sta_join(vap, se);
349 + ieee80211_create_ibss(vap, se->se_chan);
350 + return 1;
351 }
352
353 static const struct ieee80211_scanner adhoc_default = {