From a71123cebfbc9af46b53dec14375534ae5c7076e Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 8 Aug 2005 03:30:57 +0000 Subject: Cleanup beacon/listen interval handling: o separate configured beacon interval from listen interval; this avoids potential use of one value for the other (e.g. setting powersavesleep to 0 clobbers the beacon interval used in hostap or ibss mode) o bounds check the beacon interval received in probe response and beacon frames and drop frames with bogus settings; not clear if we should instead clamp the value as any alteration would result in mismatched sta+ap configuration and probably be more confusing (don't want to log to the console but perhaps ok with rate limiting) o while here up max beacon interval to reflect WiFi standard Noticed by: Martin MFC after: 1 week --- sys/dev/awi/awi.c | 2 +- sys/dev/ipw/if_ipw.c | 2 +- sys/dev/wi/if_wi.c | 2 +- sys/net80211/ieee80211.c | 8 +++++--- sys/net80211/ieee80211_input.c | 16 +++++++++++++--- sys/net80211/ieee80211_ioctl.c | 2 +- sys/net80211/ieee80211_ioctl.h | 3 ++- sys/net80211/ieee80211_node.c | 4 ++-- sys/net80211/ieee80211_output.c | 6 +++--- sys/net80211/ieee80211_var.h | 4 +++- 10 files changed, 32 insertions(+), 17 deletions(-) diff --git a/sys/dev/awi/awi.c b/sys/dev/awi/awi.c index 838e3fb..4e2aab1 100644 --- a/sys/dev/awi/awi.c +++ b/sys/dev/awi/awi.c @@ -660,7 +660,7 @@ awi_init(struct ifnet *ifp) if (ic->ic_opmode == IEEE80211_M_AHDEMO || ic->ic_opmode == IEEE80211_M_HOSTAP) { ni->ni_chan = ic->ic_ibss_chan; - ni->ni_intval = ic->ic_lintval; + ni->ni_intval = ic->ic_bintval; ni->ni_rssi = 0; ni->ni_rstamp = 0; memset(&ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c index 60ec63f..75af5ac 100644 --- a/sys/dev/ipw/if_ipw.c +++ b/sys/dev/ipw/if_ipw.c @@ -2001,7 +2001,7 @@ ipw_config(struct ipw_softc *sc) #endif if (ic->ic_opmode == IEEE80211_M_IBSS) { - data = htole32(ic->ic_lintval); + data = htole32(ic->ic_bintval); DPRINTF(("Setting beacon interval to %u\n", le32toh(data))); error = ipw_cmd(sc, IPW_CMD_SET_BEACON_INTERVAL, &data, sizeof data); diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index c80c939..bb545e6 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -739,7 +739,7 @@ wi_init(void *arg) if (ic->ic_opmode == IEEE80211_M_HOSTAP && sc->sc_firmware_type == WI_INTERSIL) { - wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval); + wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_bintval); wi_write_val(sc, WI_RID_BASIC_RATE, 0x03); /* 1, 2 */ wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f); /* 1, 2, 5.5, 11 */ wi_write_val(sc, WI_RID_DTIM_PERIOD, 1); diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index ea75fa0..a34f875 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -182,12 +182,14 @@ ieee80211_ifattach(struct ieee80211com *ic) #endif (void) ieee80211_setmode(ic, ic->ic_curmode); - if (ic->ic_lintval == 0) - ic->ic_lintval = IEEE80211_BINTVAL_DEFAULT; - ic->ic_bmisstimeout = 7*ic->ic_lintval; /* default 7 beacons */ + if (ic->ic_bintval == 0) + ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT; + ic->ic_bmisstimeout = 7*ic->ic_bintval; /* default 7 beacons */ ic->ic_dtim_period = IEEE80211_DTIM_DEFAULT; IEEE80211_BEACON_LOCK_INIT(ic, "beacon"); + if (ic->ic_lintval == 0) + ic->ic_lintval = ic->ic_bintval; ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; ieee80211_node_attach(ic); diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c index 808479d..8a6a499 100644 --- a/sys/net80211/ieee80211_input.c +++ b/sys/net80211/ieee80211_input.c @@ -1901,6 +1901,16 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, ic->ic_stats.is_rx_chanmismatch++; return; } + if (!(IEEE80211_BINTVAL_MIN <= bintval && + bintval <= IEEE80211_BINTVAL_MAX)) { + IEEE80211_DISCARD(ic, + IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT, + wh, ieee80211_mgt_subtype_name[subtype >> + IEEE80211_FC0_SUBTYPE_SHIFT], + "bogus beacon interval", bintval); + ic->ic_stats.is_rx_badbintval++; + return; + } /* * Count frame now that we know it's to be processed. @@ -2201,7 +2211,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: { - u_int16_t capinfo, bintval; + u_int16_t capinfo, lintval; struct ieee80211_rsnparms rsn; u_int8_t reason; @@ -2238,7 +2248,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, return; } capinfo = le16toh(*(u_int16_t *)frm); frm += 2; - bintval = le16toh(*(u_int16_t *)frm); frm += 2; + lintval = le16toh(*(u_int16_t *)frm); frm += 2; if (reassoc) frm += 6; /* ignore current AP info */ ssid = rates = xrates = wpa = wme = NULL; @@ -2366,7 +2376,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, } ni->ni_rssi = rssi; ni->ni_rstamp = rstamp; - ni->ni_intval = bintval; + ni->ni_intval = lintval; ni->ni_capinfo = capinfo; ni->ni_chan = ic->ic_bss->ni_chan; ni->ni_fhdwell = ic->ic_bss->ni_fhdwell; diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 3396934..61d8cc4 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -2317,7 +2317,7 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re return EINVAL; if (IEEE80211_BINTVAL_MIN <= ireq->i_val && ireq->i_val <= IEEE80211_BINTVAL_MAX) { - ic->ic_lintval = ireq->i_val; + ic->ic_bintval = ireq->i_val; error = ENETRESET; /* requires restart */ } else error = EINVAL; diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 4c211fe..83ff118 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -180,7 +180,8 @@ struct ieee80211_stats { u_int32_t is_ff_split; /* fast frame rx split error */ u_int32_t is_ff_decap; /* fast frames decap'd */ u_int32_t is_ff_encap; /* fast frames encap'd for tx */ - u_int32_t is_spare[10]; + u_int32_t is_rx_badbintval; /* rx frame w/ bogus bintval */ + u_int32_t is_spare[9]; }; /* diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 12ff342..ff8cfcd 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -389,7 +389,7 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan) ni->ni_esslen = ic->ic_des_esslen; memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); copy_bss(ni, ic->ic_bss); - ni->ni_intval = ic->ic_lintval; + ni->ni_intval = ic->ic_bintval; if (ic->ic_flags & IEEE80211_F_PRIVACY) ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; if (ic->ic_phytype == IEEE80211_T_FH) { @@ -441,7 +441,7 @@ ieee80211_reset_bss(struct ieee80211com *ic) ic->ic_bss = ieee80211_ref_node(ni); if (obss != NULL) { copy_bss(ni, obss); - ni->ni_intval = ic->ic_lintval; + ni->ni_intval = ic->ic_bintval; ieee80211_free_node(obss); } } diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 78b62d0..85e610d 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -1686,13 +1686,13 @@ ieee80211_pwrsave(struct ieee80211com *ic, struct ieee80211_node *ni, * using this information. */ /* XXX handle overflow? */ - age = ((ni->ni_intval * ic->ic_lintval) << 2) / 1024; /* TU -> secs */ + age = ((ni->ni_intval * ic->ic_bintval) << 2) / 1024; /* TU -> secs */ _IEEE80211_NODE_SAVEQ_ENQUEUE(ni, m, qlen, age); IEEE80211_NODE_SAVEQ_UNLOCK(ni); IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, - "[%s] save frame, %u now queued\n", - ether_sprintf(ni->ni_macaddr), qlen); + "[%s] save frame with age %d, %u now queued\n", + ether_sprintf(ni->ni_macaddr), age, qlen); if (qlen == 1) ic->ic_set_tim(ni, 1); diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index e06673d..2ef0e54 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -65,7 +65,8 @@ #define IEEE80211_DTIM_MIN 1 /* min DTIM period */ #define IEEE80211_DTIM_DEFAULT 1 /* default DTIM period */ -#define IEEE80211_BINTVAL_MAX 500 /* max beacon interval (TU's) */ +/* NB: min+max come from WiFi requirements */ +#define IEEE80211_BINTVAL_MAX 1000 /* max beacon interval (TU's) */ #define IEEE80211_BINTVAL_MIN 25 /* min beacon interval (TU's) */ #define IEEE80211_BINTVAL_DEFAULT 100 /* default beacon interval (TU's) */ @@ -143,6 +144,7 @@ struct ieee80211com { void (*ic_node_cleanup)(struct ieee80211_node *); u_int8_t (*ic_node_getrssi)(const struct ieee80211_node*); u_int16_t ic_lintval; /* listen interval */ + u_int16_t ic_bintval; /* beacon interval */ u_int16_t ic_holdover; /* PM hold over duration */ u_int16_t ic_txmin; /* min tx retry count */ u_int16_t ic_txmax; /* max tx retry count */ -- cgit v1.1