aboutsummaryrefslogtreecommitdiffstats
path: root/package/madwifi/patches/441-fix_ibss_node_handling.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/madwifi/patches/441-fix_ibss_node_handling.patch')
-rw-r--r--package/madwifi/patches/441-fix_ibss_node_handling.patch91
1 files changed, 91 insertions, 0 deletions
diff --git a/package/madwifi/patches/441-fix_ibss_node_handling.patch b/package/madwifi/patches/441-fix_ibss_node_handling.patch
new file mode 100644
index 000000000..20d59de26
--- /dev/null
+++ b/package/madwifi/patches/441-fix_ibss_node_handling.patch
@@ -0,0 +1,91 @@
+--- 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);
+@@ -3558,6 +3563,11 @@ ieee80211_recv_mgmt(struct ieee80211vap
+ } else if ((vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_wdsnode) {
+ 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);
+
+@@ -3686,19 +3696,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);