| 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 | |