Root/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@@ -3570,14 +3563,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) && vap->iv_wdsnode) {
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@@ -3585,20 +3576,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@@ -3606,39 +3598,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@@ -647,7 +643,7 @@ ieee80211_sta_join1(struct ieee80211_nod
198         (vap->iv_state == IEEE80211_S_RUN) && bssid_equal(obss, selbs)); */
199     vap->iv_bss = selbs;
200     IEEE80211_ADDR_COPY(vap->iv_bssid, selbs->ni_bssid);
201- if (obss != NULL) {
202+ if ((obss != NULL) && (obss != selbs)) {
203         if (obss->ni_table)
204             ieee80211_node_leave(obss);
205         ieee80211_unref_node(&obss);
206--- a/ath/if_ath.c
207+++ b/ath/if_ath.c
208@@ -6625,14 +6625,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
209 
210     sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
211 
212- /* Lookup the new node if any (this grabs a reference to it) */
213- ni = ieee80211_find_rxnode(vap->iv_ic, vap,
214- (const struct ieee80211_frame_min *)skb->data);
215- if (ni == NULL) {
216- DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
217- return;
218- }
219-
220     switch (subtype) {
221     case IEEE80211_FC0_SUBTYPE_BEACON:
222         /* update RSSI statistics for use by the HAL */
223@@ -6654,11 +6646,9 @@ ath_recv_mgmt(struct ieee80211vap * vap,
224              * we do the IBSS merging in software. Also do not merge
225              * if the difference it too small. Otherwise we are playing
226              * tsf-pingpong with other vendors drivers */
227- beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
228- if (beacon_tsf > rtsf + 0xffff) {
229+ beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
230+ if (beacon_tsf > rtsf + 0xffff)
231                 ath_hal_settsf64(sc->sc_ah, beacon_tsf - rtsf);
232- ieee80211_ibss_merge(ni);
233- }
234             break;
235         }
236         /* NB: Fall Through */
237@@ -6680,13 +6670,21 @@ ath_recv_mgmt(struct ieee80211vap * vap,
238             hw_tsf = ath_hal_gettsf64(sc->sc_ah);
239             hw_tu = hw_tsf >> 10;
240 
241- beacon_tsf = le64_to_cpu(ni->ni_tstamp.tsf);
242+ beacon_tsf = le64_to_cpu(SKB_CB(skb)->beacon_tsf);
243             beacon_tu = beacon_tsf >> 10;
244 
245+ if (!beacon_tsf)
246+ break;
247+
248+ if (IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid))
249+ break;
250+
251             DPRINTF(sc, ATH_DEBUG_BEACON,
252- "Beacon transmitted at %10llx, "
253+ "Beacon transmitted from "MAC_FMT" ("MAC_FMT") at %10llx, "
254                     "received at %10llx(%lld), hw TSF "
255                     "%10llx(%lld)\n",
256+ MAC_ADDR(wh->i_addr3),
257+ MAC_ADDR(vap->iv_bssid),
258                     beacon_tsf,
259                     rtsf, rtsf - beacon_tsf,
260                     hw_tsf, hw_tsf - beacon_tsf);
261@@ -6699,39 +6697,13 @@ ath_recv_mgmt(struct ieee80211vap * vap,
262                 do_merge = 1;
263             }
264 
265- /* Check sc_nexttbtt */
266- if (sc->sc_nexttbtt < hw_tu) {
267- DPRINTF(sc, ATH_DEBUG_BEACON,
268- "sc_nexttbtt (%8x TU) is in the past "
269- "(tsf %8x TU), updating timers\n",
270- sc->sc_nexttbtt, hw_tu);
271- do_merge = 1;
272- }
273-
274- intval = ni->ni_intval & HAL_BEACON_PERIOD;
275-#if 0
276- /* This code is disabled since it would produce
277- * unwanted merge. For instance, in a two nodes network
278- * A & B, A can merge to B and at the same time, B will
279- * merge to A, still having a split */
280- if (intval != 0) {
281- if ((sc->sc_nexttbtt % intval) !=
282- (beacon_tu % intval)) {
283- DPRINTF(sc, ATH_DEBUG_BEACON,
284- "ibss merge: "
285- "sc_nexttbtt %10x TU "
286- "(%3d) beacon %10x TU "
287- "(%3d)\n",
288- sc->sc_nexttbtt,
289- sc->sc_nexttbtt % intval,
290- beacon_tu,
291- beacon_tu % intval);
292- do_merge = 1;
293- }
294- }
295-#endif
296- if (do_merge)
297+ if (do_merge) {
298+ /* Lookup the new node if any (this grabs a reference to it) */
299+ ni = ieee80211_find_txnode(vap, wh->i_addr2);
300+ memcpy(ni->ni_bssid, wh->i_addr3, IEEE80211_ADDR_LEN);
301                 ieee80211_ibss_merge(ni);
302+ ieee80211_unref_node(&ni);
303+ }
304 
305             if ((sc->sc_opmode == HAL_M_IBSS) &&
306                     ath_hw_check_atim(sc, 1, vap->iv_bss->ni_intval))
307@@ -6739,8 +6711,6 @@ ath_recv_mgmt(struct ieee80211vap * vap,
308         }
309         break;
310     }
311-
312- ieee80211_unref_node(&ni);
313 }
314 
315 static void
316--- a/net80211/ieee80211_linux.h
317+++ b/net80211/ieee80211_linux.h
318@@ -411,7 +411,7 @@ typedef spinlock_t acl_lock_t;
319  * 8 bytes so we reserve/avoid it.
320  */
321     struct ieee80211_cb {
322- u_int8_t vlan[8]; /* reserve for vlan tag info */
323+ u_int64_t beacon_tsf;
324     struct ieee80211_node *ni;
325     u_int32_t flags;
326 #define M_LINK0 0x01 /* frame needs WEP encryption */
327--- a/net80211/ieee80211_scan_sta.c
328+++ b/net80211/ieee80211_scan_sta.c
329@@ -1125,11 +1125,8 @@ adhoc_default_action(struct ieee80211vap
330     u_int8_t zeroMacAddr[IEEE80211_ADDR_LEN];
331 
332     memset(&zeroMacAddr, 0, IEEE80211_ADDR_LEN);
333- if (IEEE80211_ADDR_EQ(se->se_bssid, &zeroMacAddr[0])) {
334- ieee80211_create_ibss(vap, se->se_chan);
335- return 1;
336- } else
337- return ieee80211_sta_join(vap, se);
338+ ieee80211_create_ibss(vap, se->se_chan);
339+ return 1;
340 }
341 
342 static const struct ieee80211_scanner adhoc_default = {
343

Archive Download this file



interactive