diff options
Diffstat (limited to 'sys/net80211/ieee80211_input.c')
-rw-r--r-- | sys/net80211/ieee80211_input.c | 88 |
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; } |