aboutsummaryrefslogtreecommitdiff
path: root/sys/net80211/ieee80211_hostap.c
diff options
context:
space:
mode:
authorSam Leffler <sam@FreeBSD.org>2009-06-03 23:33:09 +0000
committerSam Leffler <sam@FreeBSD.org>2009-06-03 23:33:09 +0000
commit7131987ded7cb7a84d8d99f417732f22d2527739 (patch)
tree44f62b68ce9fe0c15e1bb21fc9f6d584807443ee /sys/net80211/ieee80211_hostap.c
parent4e15098821360ed9e09ee9fb518c4a101b4191c0 (diff)
downloadsrc-7131987ded7cb7a84d8d99f417732f22d2527739.tar.gz
src-7131987ded7cb7a84d8d99f417732f22d2527739.zip
When a channel switch is done to a channel with different operating
characteristics force the stations to re-associate so protocol state is re-initialized. Note that for 11h/DFS this is irrelevant as channel changes are never cross-band. Reviewed by: ctlaw
Notes
Notes: svn path=/head/; revision=193414
Diffstat (limited to 'sys/net80211/ieee80211_hostap.c')
-rw-r--r--sys/net80211/ieee80211_hostap.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 5d9c8e455102..625ee98cce03 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -127,6 +127,28 @@ sta_csa(void *arg, struct ieee80211_node *ni)
}
}
+static void
+sta_drop(void *arg, struct ieee80211_node *ni)
+{
+ struct ieee80211vap *vap = arg;
+
+ if (ni->ni_vap == vap && ni->ni_associd != 0)
+ ieee80211_node_leave(ni);
+}
+
+/*
+ * Does a channel change require associated stations to re-associate
+ * so protocol state is correct. This is used when doing CSA across
+ * bands or similar (e.g. HT -> legacy).
+ */
+static int
+isbandchange(struct ieee80211com *ic)
+{
+ return ((ic->ic_bsschan->ic_flags ^ ic->ic_csa_newchan->ic_flags) &
+ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_HALF |
+ IEEE80211_CHAN_QUARTER | IEEE80211_CHAN_HT)) != 0;
+}
+
/*
* IEEE80211_M_HOSTAP vap state machine handler.
*/
@@ -307,6 +329,18 @@ hostap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
}
ieee80211_node_authorize(vap->iv_bss);
break;
+ case IEEE80211_S_CSA:
+ if (ostate == IEEE80211_S_RUN && isbandchange(ic)) {
+ /*
+ * On a ``band change'' silently drop associated
+ * stations as they must re-associate before they
+ * can pass traffic (as otherwise protocol state
+ * such as capabilities and the negotiated rate
+ * set may/will be wrong).
+ */
+ ieee80211_iterate_nodes(&ic->ic_sta, sta_drop, vap);
+ }
+ break;
default:
break;
}