1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6641,10 +6641,8 @@ static void
ath_recv_mgmt(struct ieee80211vap * vap, struct ieee80211_node *ni_or_null,
struct sk_buff *skb, int subtype, int rssi, u_int64_t rtsf)
{
+ const struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
struct ath_softc *sc = netdev_priv(vap->iv_ic->ic_dev);
-#ifdef AR_DEBUG
- struct ieee80211_frame *wh = (struct ieee80211_frame *)skb->data;
-#endif
struct ieee80211_node * ni = ni_or_null;
u_int64_t hw_tsf, beacon_tsf;
u_int32_t hw_tu, beacon_tu, intval;
@@ -6686,7 +6684,7 @@ ath_recv_mgmt(struct ieee80211vap * vap,
}
if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
(sc->sc_opmode == HAL_M_HOSTAP) &&
- IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {
+ IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
/* In this mode, we drive the HAL in HOSTAP mode. Hence
* we do the IBSS merging in software. Also do not merge
* if the difference it too small. Otherwise we are playing
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -311,7 +311,8 @@ ieee80211_input(struct ieee80211vap * va
}
/* Do not try to find a node reference if the packet really did come from the BSS */
if (type == IEEE80211_FC0_TYPE_DATA && ni == vap->iv_bss &&
- !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2)) {
+ !IEEE80211_ADDR_EQ(vap->iv_bss->ni_macaddr, wh->i_addr2) &&
+ IEEE80211_ADDR_EQ(vap->iv_bssid, wh->i_addr3)) {
/* Try to find sender in local node table. */
ni = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
if (ni == NULL) {
@@ -513,6 +514,10 @@ ieee80211_input(struct ieee80211vap * va
break;
case IEEE80211_M_IBSS:
case IEEE80211_M_AHDEMO:
+ /* ignore foreign data frames */
+ if (ni == vap->iv_bss)
+ goto out;
+
if (dir != IEEE80211_FC1_DIR_NODS) {
IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
wh, "data", "invalid dir 0x%x", dir);
@@ -3555,6 +3560,11 @@ ieee80211_recv_mgmt(struct ieee80211vap
} else if (vap->iv_opmode == IEEE80211_M_WDS) {
found = 1;
ni = ni_or_null = vap->iv_wdsnode;
+ } else if (vap->iv_opmode == IEEE80211_M_IBSS) {
+ ni_or_null = ieee80211_find_node(&ic->ic_sta, wh->i_addr2);
+ if (ni_or_null)
+ ni = ni_or_null;
+ found = 1;
}
IEEE80211_UNLOCK_IRQ(vap->iv_ic);
@@ -3683,19 +3693,8 @@ ieee80211_recv_mgmt(struct ieee80211vap
vap->iv_stats.is_rx_ssidmismatch++; /*XXX*/
return;
}
- if (ni == vap->iv_bss) {
- if (vap->iv_opmode == IEEE80211_M_IBSS) {
- /*
- * XXX Cannot tell if the sender is operating
- * in ibss mode. But we need a new node to
- * send the response so blindly add them to the
- * neighbor table.
- */
- ni = ieee80211_fakeup_adhoc_node(vap,
- wh->i_addr2);
- } else {
- ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
- }
+ if (ni == vap->iv_bss && vap->iv_opmode != IEEE80211_M_IBSS) {
+ ni = ieee80211_dup_bss(vap, wh->i_addr2, 1);
if (ni == NULL)
return;
allocbs = 1;
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -601,6 +601,8 @@ ieee80211_ibss_merge(struct ieee80211_no
ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "");
+ if (!IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bssid))
+ ieee80211_node_table_reset(&vap->iv_ic->ic_sta, vap);
return ieee80211_sta_join1(ieee80211_ref_node(ni));
}
EXPORT_SYMBOL(ieee80211_ibss_merge);
@@ -1378,9 +1380,7 @@ ieee80211_add_neighbor(struct ieee80211v
if (sp->ath != NULL)
ieee80211_saveath(ni, sp->ath);
- /* NB: must be after ni_chan is setup */
- ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
-
+ memcpy(&ni->ni_rates, &vap->iv_bss->ni_rates, sizeof(ni->ni_rates));
if (ic->ic_newassoc != NULL)
ic->ic_newassoc(ni, 1);
/* XXX not right for 802.1x/WPA */
|