summaryrefslogtreecommitdiff
path: root/sys/net80211/ieee80211_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net80211/ieee80211_input.c')
-rw-r--r--sys/net80211/ieee80211_input.c88
1 files changed, 77 insertions, 11 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 53f5889af89..303df489c72 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,5 +1,5 @@
/* $NetBSD: ieee80211_input.c,v 1.24 2004/05/31 11:12:24 dyoung Exp $ */
-/* $OpenBSD: ieee80211_input.c,v 1.15 2006/03/25 22:41:48 djm Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.16 2006/06/18 18:39:41 damien Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -33,8 +33,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include "bpfilter.h"
#include <sys/param.h>
@@ -1056,7 +1054,6 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
ic->ic_stats.is_rx_chanmismatch++;
return;
}
-
/*
* Use mac, channel and rssi so we collect only the
* best potential AP with the equal bssid while scanning.
@@ -1099,6 +1096,52 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
} else
is_new = 0;
+ /*
+ * When operating in station mode, check for state updates
+ * while we're associated. We consider only 11g stuff right
+ * now.
+ */
+ if (ic->ic_opmode == IEEE80211_M_STA &&
+ ni->ni_associd != 0 &&
+ (!(ic->ic_flags & IEEE80211_F_ASCAN) ||
+ IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid))) {
+ /* record tsf of last beacon */
+ ni->ni_rstamp = rstamp;
+ memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp));
+ /*
+ * Check if protection mode has changed since last
+ * beacon.
+ */
+ if (ni->ni_erp != erp) {
+ IEEE80211_DPRINTF((
+ "[%s] erp change: was 0x%x, now 0x%x\n",
+ ether_sprintf(wh->i_addr2), ni->ni_erp,
+ erp));
+ if (ic->ic_curmode == IEEE80211_MODE_11G &&
+ (erp & IEEE80211_ERP_USE_PROTECTION))
+ ic->ic_flags |= IEEE80211_F_USEPROT;
+ else
+ ic->ic_flags &= ~IEEE80211_F_USEPROT;
+ ni->ni_erp = erp;
+ }
+
+ /*
+ * Check if AP short slot time setting has changed
+ * since last beacon and give the driver a chance to
+ * update the hardware.
+ */
+ if ((ni->ni_capinfo ^ letoh16(*(u_int16_t *)capinfo)) &
+ IEEE80211_CAPINFO_SHORT_SLOTTIME) {
+ ieee80211_set_shortslottime(ic,
+ ic->ic_curmode == IEEE80211_MODE_11A ||
+ (letoh16(*(u_int16_t *)capinfo) &
+ IEEE80211_CAPINFO_SHORT_SLOTTIME));
+ ni->ni_capinfo =
+ letoh16(*(u_int16_t *)capinfo);
+ }
+ break;
+ }
+
if (ssid[1] != 0 && ni->ni_esslen == 0) {
/*
* Update ESSID at probe response to adopt hidden AP by
@@ -1122,6 +1165,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
/* NB: must be after ni_chan is setup */
ieee80211_setup_rates(ic, ni, rates, xrates,
IEEE80211_F_DOSORT);
+
/*
* When scanning we record results (nodes) with a zero
* refcnt. Otherwise we want to hold the reference for
@@ -1145,9 +1189,8 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
case IEEE80211_FC0_SUBTYPE_PROBE_REQ: {
u_int8_t rate;
- if (ic->ic_opmode == IEEE80211_M_STA)
- return;
- if (ic->ic_state != IEEE80211_S_RUN)
+ if (ic->ic_opmode == IEEE80211_M_STA ||
+ ic->ic_state != IEEE80211_S_RUN)
return;
/*
@@ -1242,7 +1285,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
u_int16_t capinfo, bintval;
if (ic->ic_opmode != IEEE80211_M_HOSTAP ||
- (ic->ic_state != IEEE80211_S_RUN))
+ ic->ic_state != IEEE80211_S_RUN)
return;
if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) {
@@ -1409,9 +1452,32 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
ieee80211_setup_rates(ic, ni, rates, xrates,
IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
- if (ni->ni_rates.rs_nrates != 0)
- ieee80211_new_state(ic, IEEE80211_S_RUN,
- wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
+ if (ni->ni_rates.rs_nrates == 0)
+ break;
+
+ /*
+ * Configure state now that we are associated.
+ */
+ if (ic->ic_curmode == IEEE80211_MODE_11A ||
+ (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
+ ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
+ else
+ ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
+
+ ieee80211_set_shortslottime(ic,
+ ic->ic_curmode == IEEE80211_MODE_11A ||
+ (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
+ /*
+ * Honor ERP protection.
+ */
+ if (ic->ic_curmode == IEEE80211_MODE_11G &&
+ (ni->ni_erp & IEEE80211_ERP_USE_PROTECTION))
+ ic->ic_flags |= IEEE80211_F_USEPROT;
+ else
+ ic->ic_flags &= ~IEEE80211_F_USEPROT;
+
+ ieee80211_new_state(ic, IEEE80211_S_RUN,
+ wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
break;
}