aboutsummaryrefslogtreecommitdiff
path: root/sys/net80211/ieee80211_node.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net80211/ieee80211_node.c')
-rw-r--r--sys/net80211/ieee80211_node.c1145
1 files changed, 374 insertions, 771 deletions
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 9394c0f54252..690e54b4f80a 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -59,25 +59,22 @@ __FBSDID("$FreeBSD$");
#define REFCNT_LOC "%s %p<%s> refcnt %d\n", __func__
#endif
+static int ieee80211_sta_join1(struct ieee80211_node *);
+
static struct ieee80211_node *node_alloc(struct ieee80211_node_table *);
static void node_cleanup(struct ieee80211_node *);
static void node_free(struct ieee80211_node *);
-static u_int8_t node_getrssi(const struct ieee80211_node *);
+static int8_t node_getrssi(const struct ieee80211_node *);
+static void node_getsignal(const struct ieee80211_node *, int8_t *, int8_t *);
static void ieee80211_setup_node(struct ieee80211_node_table *,
- struct ieee80211_node *, const u_int8_t *);
+ struct ieee80211_node *, const uint8_t *);
static void _ieee80211_free_node(struct ieee80211_node *);
-static void ieee80211_free_allnodes(struct ieee80211_node_table *);
-
-static void ieee80211_timeout_scan_candidates(struct ieee80211_node_table *);
-static void ieee80211_timeout_stations(struct ieee80211_node_table *);
-
-static void ieee80211_set_tim(struct ieee80211_node *, int set);
static void ieee80211_node_table_init(struct ieee80211com *ic,
struct ieee80211_node_table *nt, const char *name,
- int inact, int keyixmax,
- void (*timeout)(struct ieee80211_node_table *));
+ int inact, int keymaxix);
+static void ieee80211_node_table_reset(struct ieee80211_node_table *);
static void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt);
MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
@@ -90,6 +87,7 @@ ieee80211_node_attach(struct ieee80211com *ic)
ic->ic_node_free = node_free;
ic->ic_node_cleanup = node_cleanup;
ic->ic_node_getrssi = node_getrssi;
+ ic->ic_node_getsignal = node_getsignal;
/* default station inactivity timer setings */
ic->ic_inact_init = IEEE80211_INACT_INIT;
@@ -97,9 +95,10 @@ ieee80211_node_attach(struct ieee80211com *ic)
ic->ic_inact_run = IEEE80211_INACT_RUN;
ic->ic_inact_probe = IEEE80211_INACT_PROBE;
+ callout_init(&ic->ic_inact, CALLOUT_MPSAFE);
+
/* NB: driver should override */
ic->ic_max_aid = IEEE80211_AID_DEF;
- ic->ic_set_tim = ieee80211_set_tim;
}
void
@@ -109,30 +108,17 @@ ieee80211_node_lateattach(struct ieee80211com *ic)
if (ic->ic_max_aid > IEEE80211_AID_MAX)
ic->ic_max_aid = IEEE80211_AID_MAX;
- MALLOC(ic->ic_aid_bitmap, u_int32_t *,
- howmany(ic->ic_max_aid, 32) * sizeof(u_int32_t),
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ MALLOC(ic->ic_aid_bitmap, uint32_t *,
+ howmany(ic->ic_max_aid, 32) * sizeof(uint32_t),
+ M_80211_NODE, M_NOWAIT | M_ZERO);
if (ic->ic_aid_bitmap == NULL) {
/* XXX no way to recover */
printf("%s: no memory for AID bitmap!\n", __func__);
ic->ic_max_aid = 0;
}
- /* XXX defer until using hostap/ibss mode */
- ic->ic_tim_len = howmany(ic->ic_max_aid, 8) * sizeof(u_int8_t);
- MALLOC(ic->ic_tim_bitmap, u_int8_t *, ic->ic_tim_len,
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (ic->ic_tim_bitmap == NULL) {
- /* XXX no way to recover */
- printf("%s: no memory for TIM bitmap!\n", __func__);
- }
-
ieee80211_node_table_init(ic, &ic->ic_sta, "station",
- IEEE80211_INACT_INIT, ic->ic_crypto.cs_max_keyix,
- ieee80211_timeout_stations);
- ieee80211_node_table_init(ic, &ic->ic_scan, "scan",
- IEEE80211_INACT_SCAN, 0,
- ieee80211_timeout_scan_candidates);
+ IEEE80211_INACT_INIT, ic->ic_crypto.cs_max_keyix);
ieee80211_reset_bss(ic);
/*
@@ -182,16 +168,11 @@ ieee80211_node_detach(struct ieee80211com *ic)
ieee80211_free_node(ic->ic_bss);
ic->ic_bss = NULL;
}
- ieee80211_node_table_cleanup(&ic->ic_scan);
ieee80211_node_table_cleanup(&ic->ic_sta);
if (ic->ic_aid_bitmap != NULL) {
- FREE(ic->ic_aid_bitmap, M_DEVBUF);
+ FREE(ic->ic_aid_bitmap, M_80211_NODE);
ic->ic_aid_bitmap = NULL;
}
- if (ic->ic_tim_bitmap != NULL) {
- FREE(ic->ic_tim_bitmap, M_DEVBUF);
- ic->ic_tim_bitmap = NULL;
- }
}
/*
@@ -218,133 +199,28 @@ ieee80211_node_unauthorize(struct ieee80211_node *ni)
* to insure a consistent view by drivers.
*/
static void
-ieee80211_set_chan(struct ieee80211com *ic,
- struct ieee80211_node *ni, struct ieee80211_channel *chan)
+ieee80211_node_set_chan(struct ieee80211com *ic, struct ieee80211_node *ni)
{
+ struct ieee80211_channel *chan = ic->ic_bsschan;
+
+#if 0
+ KASSERT(chan != IEEE80211_CHAN_ANYC, ("bss channel not setup"));
+#else
if (chan == IEEE80211_CHAN_ANYC) /* XXX while scanning */
chan = ic->ic_curchan;
+#endif
ni->ni_chan = chan;
- ni->ni_rates = *ieee80211_get_suprates(ic, chan);
-}
-
-/*
- * AP scanning support.
- */
-
-#ifdef IEEE80211_DEBUG
-static void
-dump_chanlist(const u_char chans[])
-{
- const char *sep;
- int i;
-
- sep = " ";
- for (i = 0; i < IEEE80211_CHAN_MAX; i++)
- if (isset(chans, i)) {
- printf("%s%u", sep, i);
- sep = ", ";
- }
-}
-#endif /* IEEE80211_DEBUG */
-
-/*
- * Initialize the channel set to scan based on the
- * of available channels and the current PHY mode.
- */
-static void
-ieee80211_reset_scan(struct ieee80211com *ic)
-{
-
- /* XXX ic_des_chan should be handled with ic_chan_active */
- if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
- memset(ic->ic_chan_scan, 0, sizeof(ic->ic_chan_scan));
- setbit(ic->ic_chan_scan,
- ieee80211_chan2ieee(ic, ic->ic_des_chan));
- } else
- memcpy(ic->ic_chan_scan, ic->ic_chan_active,
- sizeof(ic->ic_chan_active));
-#ifdef IEEE80211_DEBUG
- if (ieee80211_msg_scan(ic)) {
- printf("%s: scan set:", __func__);
- dump_chanlist(ic->ic_chan_scan);
- printf(" start chan %u\n",
- ieee80211_chan2ieee(ic, ic->ic_curchan));
+ if (IEEE80211_IS_CHAN_HT(chan)) {
+ /*
+ * XXX Gotta be careful here; the rate set returned by
+ * ieee80211_get_suprates is actually any HT rate
+ * set so blindly copying it will be bad. We must
+ * install the legacy rate est in ni_rates and the
+ * HT rate set in ni_htrates.
+ */
+ ni->ni_htrates = *ieee80211_get_suphtrates(ic, chan);
}
-#endif /* IEEE80211_DEBUG */
-}
-
-/*
- * Begin an active scan.
- */
-void
-ieee80211_begin_scan(struct ieee80211com *ic, int reset)
-{
-
- ic->ic_scan.nt_scangen++;
- /*
- * In all but hostap mode scanning starts off in
- * an active mode before switching to passive.
- */
- if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
- ic->ic_flags |= IEEE80211_F_ASCAN;
- ic->ic_stats.is_scan_active++;
- } else
- ic->ic_stats.is_scan_passive++;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
- "begin %s scan in %s mode, scangen %u\n",
- (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive",
- ieee80211_phymode_name[ic->ic_curmode], ic->ic_scan.nt_scangen);
- /*
- * Clear scan state and flush any previously seen AP's.
- */
- ieee80211_reset_scan(ic);
- if (reset)
- ieee80211_free_allnodes(&ic->ic_scan);
-
- ic->ic_flags |= IEEE80211_F_SCAN;
-
- /* Scan the next channel. */
- ieee80211_next_scan(ic);
-}
-
-/*
- * Switch to the next channel marked for scanning.
- */
-int
-ieee80211_next_scan(struct ieee80211com *ic)
-{
- struct ieee80211_channel *chan;
-
- /*
- * Insure any previous mgt frame timeouts don't fire.
- * This assumes the driver does the right thing in
- * flushing anything queued in the driver and below.
- */
- ic->ic_mgt_timer = 0;
- ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
-
- chan = ic->ic_curchan;
- do {
- if (++chan > &ic->ic_channels[IEEE80211_CHAN_MAX])
- chan = &ic->ic_channels[0];
- if (isset(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan))) {
- clrbit(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan));
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
- "%s: chan %d->%d\n", __func__,
- ieee80211_chan2ieee(ic, ic->ic_curchan),
- ieee80211_chan2ieee(ic, chan));
- ic->ic_curchan = chan;
- /*
- * XXX drivers should do this as needed,
- * XXX for now maintain compatibility
- */
- ic->ic_bss->ni_rates = *ieee80211_get_suprates(ic, chan);
- ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
- return 1;
- }
- } while (chan != ic->ic_curchan);
- ieee80211_end_scan(ic);
- return 0;
+ ni->ni_rates = *ieee80211_get_suprates(ic, chan);
}
/*
@@ -366,7 +242,7 @@ ieee80211_probe_curchan(struct ieee80211com *ic, int force)
ieee80211_send_probereq(ic->ic_bss,
ic->ic_myaddr, ifp->if_broadcastaddr,
ifp->if_broadcastaddr,
- ic->ic_des_essid, ic->ic_des_esslen,
+ ic->ic_des_ssid[0].ssid, ic->ic_des_ssid[0].len,
ic->ic_opt_ie, ic->ic_opt_ie_len);
} else
ic->ic_flags_ext |= IEEE80211_FEXT_PROBECHAN;
@@ -415,9 +291,10 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
return;
}
IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
- 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_esslen = ic->ic_des_ssid[0].len;
+ memcpy(ni->ni_essid, ic->ic_des_ssid[0].ssid, ni->ni_esslen);
+ if (ic->ic_bss != NULL)
+ copy_bss(ni, ic->ic_bss);
ni->ni_intval = ic->ic_bintval;
if (ic->ic_flags & IEEE80211_F_PRIVACY)
ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
@@ -444,29 +321,47 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
/*
* Fix the channel and related attributes.
*/
- ieee80211_set_chan(ic, ni, chan);
- ic->ic_curchan = chan;
- ic->ic_curmode = ieee80211_chan2mode(ic, chan);
+ ic->ic_bsschan = chan;
+ ieee80211_node_set_chan(ic, ni);
+ ic->ic_curmode = ieee80211_chan2mode(chan);
/*
* Do mode-specific rate setup.
*/
- if (IEEE80211_IS_CHAN_FULL(chan) &&
- (ic->ic_curmode == IEEE80211_MODE_11G ||
- ic->ic_curmode == IEEE80211_MODE_11B))
- ieee80211_set11gbasicrates(&ni->ni_rates, ic->ic_curmode);
+ if (IEEE80211_IS_CHAN_FULL(chan)) {
+ if (IEEE80211_IS_CHAN_ANYG(chan)) {
+ /*
+ * Use a mixed 11b/11g rate set.
+ */
+ ieee80211_set11gbasicrates(&ni->ni_rates,
+ IEEE80211_MODE_11G);
+ } else if (IEEE80211_IS_CHAN_B(chan)) {
+ /*
+ * Force pure 11b rate set.
+ */
+ ieee80211_set11gbasicrates(&ni->ni_rates,
+ IEEE80211_MODE_11B);
+ }
+ }
- (void) ieee80211_sta_join(ic, ieee80211_ref_node(ni));
+ (void) ieee80211_sta_join1(ieee80211_ref_node(ni));
}
+/*
+ * Reset bss state on transition to the INIT state.
+ * Clear any stations from the table (they have been
+ * deauth'd) and reset the bss node (clears key, rate
+ * etc. state).
+ */
void
ieee80211_reset_bss(struct ieee80211com *ic)
{
struct ieee80211_node *ni, *obss;
- ieee80211_node_table_reset(&ic->ic_scan);
+ callout_drain(&ic->ic_inact);
ieee80211_node_table_reset(&ic->ic_sta);
+ ieee80211_reset_erp(ic);
- ni = ieee80211_alloc_node(&ic->ic_scan, ic->ic_myaddr);
+ ni = ieee80211_alloc_node(&ic->ic_sta, ic->ic_myaddr);
KASSERT(ni != NULL, ("unable to setup inital BSS node"));
obss = ic->ic_bss;
ic->ic_bss = ieee80211_ref_node(ni);
@@ -477,21 +372,71 @@ ieee80211_reset_bss(struct ieee80211com *ic)
}
}
-/* XXX tunable */
-#define STA_FAILS_MAX 2 /* assoc failures before ignored */
+static int
+match_ssid(const struct ieee80211_node *ni,
+ int nssid, const struct ieee80211_scan_ssid ssids[])
+{
+ int i;
+ for (i = 0; i < nssid; i++) {
+ if (ni->ni_esslen == ssids[i].len &&
+ memcmp(ni->ni_essid, ssids[i].ssid, ni->ni_esslen) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Test a node for suitability/compatibility.
+ */
static int
-ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
+check_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
+{
+ uint8_t rate;
+
+ if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
+ return 0;
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
+ return 0;
+ } else {
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
+ return 0;
+ }
+ if (ic->ic_flags & IEEE80211_F_PRIVACY) {
+ if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
+ return 0;
+ } else {
+ /* XXX does this mean privacy is supported or required? */
+ if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
+ return 0;
+ }
+ rate = ieee80211_fix_rate(ni, &ni->ni_rates,
+ IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
+ if (rate & IEEE80211_RATE_BASIC)
+ return 0;
+ if (ic->ic_des_nssid != 0 &&
+ !match_ssid(ni, ic->ic_des_nssid, ic->ic_des_ssid))
+ return 0;
+ if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
+ !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
+ return 0;
+ return 1;
+}
+
+#ifdef IEEE80211_DEBUG
+/*
+ * Display node suitability/compatibility.
+ */
+static void
+check_bss_debug(struct ieee80211com *ic, struct ieee80211_node *ni)
{
- u_int8_t rate;
+ uint8_t rate;
int fail;
fail = 0;
if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
fail |= 0x01;
- if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
- ni->ni_chan != ic->ic_des_chan)
- fail |= 0x01;
if (ic->ic_opmode == IEEE80211_M_IBSS) {
if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
fail |= 0x02;
@@ -511,238 +456,32 @@ ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
if (rate & IEEE80211_RATE_BASIC)
fail |= 0x08;
- if (ic->ic_des_esslen != 0 &&
- (ni->ni_esslen != ic->ic_des_esslen ||
- memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
+ if (ic->ic_des_nssid != 0 &&
+ !match_ssid(ni, ic->ic_des_nssid, ic->ic_des_ssid))
fail |= 0x10;
if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
!IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
fail |= 0x20;
- if (ni->ni_fails >= STA_FAILS_MAX)
- fail |= 0x40;
-#ifdef IEEE80211_DEBUG
- if (ieee80211_msg_scan(ic)) {
- printf(" %c %s",
- fail & 0x40 ? '=' : fail & 0x80 ? '^' : fail ? '-' : '+',
- ether_sprintf(ni->ni_macaddr));
- printf(" %s%c", ether_sprintf(ni->ni_bssid),
- fail & 0x20 ? '!' : ' ');
- printf(" %3d%c", ieee80211_chan2ieee(ic, ni->ni_chan),
- fail & 0x01 ? '!' : ' ');
- printf(" %+4d", ni->ni_rssi);
- printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
- fail & 0x08 ? '!' : ' ');
- printf(" %4s%c",
- (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
- (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
- "????",
- fail & 0x02 ? '!' : ' ');
- printf(" %3s%c ",
- (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
- "wep" : "no",
- fail & 0x04 ? '!' : ' ');
- ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
- printf("%s\n", fail & 0x10 ? "!" : "");
- }
-#endif
- return fail;
-}
-
-static __inline u_int8_t
-maxrate(const struct ieee80211_node *ni)
-{
- const struct ieee80211_rateset *rs = &ni->ni_rates;
- /* NB: assumes rate set is sorted (happens on frame receive) */
- return rs->rs_rates[rs->rs_nrates-1] & IEEE80211_RATE_VAL;
-}
-
-/*
- * Compare the capabilities of two nodes and decide which is
- * more desirable (return >0 if a is considered better). Note
- * that we assume compatibility/usability has already been checked
- * so we don't need to (e.g. validate whether privacy is supported).
- * Used to select the best scan candidate for association in a BSS.
- */
-static int
-ieee80211_node_compare(struct ieee80211com *ic,
- const struct ieee80211_node *a,
- const struct ieee80211_node *b)
-{
- u_int8_t maxa, maxb;
- u_int8_t rssia, rssib;
- int weight;
-
- /* privacy support preferred */
- if ((a->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) &&
- (b->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
- return 1;
- if ((a->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0 &&
- (b->ni_capinfo & IEEE80211_CAPINFO_PRIVACY))
- return -1;
-
- /* compare count of previous failures */
- weight = b->ni_fails - a->ni_fails;
- if (abs(weight) > 1)
- return weight;
-
- rssia = ic->ic_node_getrssi(a);
- rssib = ic->ic_node_getrssi(b);
- if (abs(rssib - rssia) < 5) {
- /* best/max rate preferred if signal level close enough XXX */
- maxa = maxrate(a);
- maxb = maxrate(b);
- if (maxa != maxb)
- return maxa - maxb;
- /* XXX use freq for channel preference */
- /* for now just prefer 5Ghz band to all other bands */
- if (IEEE80211_IS_CHAN_5GHZ(a->ni_chan) &&
- !IEEE80211_IS_CHAN_5GHZ(b->ni_chan))
- return 1;
- if (!IEEE80211_IS_CHAN_5GHZ(a->ni_chan) &&
- IEEE80211_IS_CHAN_5GHZ(b->ni_chan))
- return -1;
- }
- /* all things being equal, use signal level */
- return rssia - rssib;
-}
-
-/*
- * Mark an ongoing scan stopped.
- */
-void
-ieee80211_cancel_scan(struct ieee80211com *ic)
-{
-
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN, "%s: end %s scan\n",
- __func__,
- (ic->ic_flags & IEEE80211_F_ASCAN) ? "active" : "passive");
-
- ic->ic_flags &= ~(IEEE80211_F_SCAN | IEEE80211_F_ASCAN);
- ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
-}
-
-/*
- * Complete a scan of potential channels.
- */
-void
-ieee80211_end_scan(struct ieee80211com *ic)
-{
- struct ieee80211_node_table *nt = &ic->ic_scan;
- struct ieee80211_node *ni, *selbs;
-
- ieee80211_cancel_scan(ic);
- ieee80211_notify_scan_done(ic);
-
- if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
- u_int8_t maxrssi[IEEE80211_CHAN_MAX]; /* XXX off stack? */
- int i, bestchan;
- u_int8_t rssi;
-
- /*
- * The passive scan to look for existing AP's completed,
- * select a channel to camp on. Identify the channels
- * that already have one or more AP's and try to locate
- * an unoccupied one. If that fails, pick a channel that
- * looks to be quietest.
- */
- memset(maxrssi, 0, sizeof(maxrssi));
- IEEE80211_NODE_LOCK(nt);
- TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
- rssi = ic->ic_node_getrssi(ni);
- i = ieee80211_chan2ieee(ic, ni->ni_chan);
- if (rssi > maxrssi[i])
- maxrssi[i] = rssi;
- }
- IEEE80211_NODE_UNLOCK(nt);
- /* XXX select channel more intelligently */
- bestchan = -1;
- for (i = 0; i < IEEE80211_CHAN_MAX; i++)
- if (isset(ic->ic_chan_active, i)) {
- /*
- * If the channel is unoccupied the max rssi
- * should be zero; just take it. Otherwise
- * track the channel with the lowest rssi and
- * use that when all channels appear occupied.
- */
- if (maxrssi[i] == 0) {
- bestchan = i;
- break;
- }
- if (bestchan == -1 ||
- maxrssi[i] < maxrssi[bestchan])
- bestchan = i;
- }
- if (bestchan != -1) {
- ieee80211_create_ibss(ic, &ic->ic_channels[bestchan]);
- return;
- }
- /* no suitable channel, should not happen */
- }
- /*
- * When manually sequencing the state machine; scan just once
- * regardless of whether we have a candidate or not. The
- * controlling application is expected to setup state and
- * initiate an association.
- */
- if (ic->ic_roaming == IEEE80211_ROAMING_MANUAL)
- return;
- /*
- * Automatic sequencing; look for a candidate and
- * if found join the network.
- */
- /* NB: unlocked read should be ok */
- if (TAILQ_FIRST(&nt->nt_node) == NULL) {
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
- "%s: no scan candidate\n", __func__);
- notfound:
- if (ic->ic_opmode == IEEE80211_M_IBSS &&
- (ic->ic_flags & IEEE80211_F_IBSSON) &&
- ic->ic_des_esslen != 0) {
- ieee80211_create_ibss(ic, ic->ic_ibss_chan);
- return;
- }
- /*
- * Decrement the failure counts so entries will be
- * reconsidered the next time around. We really want
- * to do this only for sta's where we've previously
- * had some success.
- */
- IEEE80211_NODE_LOCK(nt);
- TAILQ_FOREACH(ni, &nt->nt_node, ni_list)
- if (ni->ni_fails)
- ni->ni_fails--;
- IEEE80211_NODE_UNLOCK(nt);
- /*
- * Reset the list of channels to scan and start again.
- */
- ieee80211_reset_scan(ic);
- ic->ic_flags |= IEEE80211_F_SCAN;
- ieee80211_next_scan(ic);
- return;
- }
- selbs = NULL;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN, "\t%s\n",
- "macaddr bssid chan rssi rate flag wep essid");
- IEEE80211_NODE_LOCK(nt);
- TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
- if (ieee80211_match_bss(ic, ni) == 0) {
- if (selbs == NULL)
- selbs = ni;
- else if (ieee80211_node_compare(ic, ni, selbs) > 0)
- selbs = ni;
- }
- }
- if (selbs != NULL) /* NB: grab ref while dropping lock */
- (void) ieee80211_ref_node(selbs);
- IEEE80211_NODE_UNLOCK(nt);
- if (selbs == NULL)
- goto notfound;
- if (!ieee80211_sta_join(ic, selbs)) {
- ieee80211_free_node(selbs);
- goto notfound;
- }
+ printf(" %c %s", fail ? '-' : '+', ether_sprintf(ni->ni_macaddr));
+ printf(" %s%c", ether_sprintf(ni->ni_bssid), fail & 0x20 ? '!' : ' ');
+ printf(" %3d%c",
+ ieee80211_chan2ieee(ic, ni->ni_chan), fail & 0x01 ? '!' : ' ');
+ printf(" %+4d", ni->ni_rssi);
+ printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
+ fail & 0x08 ? '!' : ' ');
+ printf(" %4s%c",
+ (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
+ (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
+ "????",
+ fail & 0x02 ? '!' : ' ');
+ printf(" %3s%c ",
+ (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ? "wep" : "no",
+ fail & 0x04 ? '!' : ' ');
+ ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
+ printf("%s\n", fail & 0x10 ? "!" : "");
}
+#endif /* IEEE80211_DEBUG */
/*
* Handle 802.11 ad hoc network merge. The
@@ -766,9 +505,14 @@ ieee80211_ibss_merge(struct ieee80211_node *ni)
/* unchanged, nothing to do */
return 0;
}
- if (ieee80211_match_bss(ic, ni) != 0) { /* capabilities mismatch */
+ if (!check_bss(ic, ni)) {
+ /* capabilities mismatch */
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
"%s: merge failed, capabilities mismatch\n", __func__);
+#ifdef IEEE80211_DEBUG
+ if (ieee80211_msg_assoc(ic))
+ check_bss_debug(ic, ni);
+#endif
ic->ic_stats.is_ibss_capmismatch++;
return 0;
}
@@ -779,17 +523,19 @@ ieee80211_ibss_merge(struct ieee80211_node *ni)
ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : ""
);
- return ieee80211_sta_join(ic, ieee80211_ref_node(ni));
+ return ieee80211_sta_join1(ieee80211_ref_node(ni));
}
/*
* Join the specified IBSS/BSS network. The node is assumed to
* be passed in with a held reference.
*/
-int
-ieee80211_sta_join(struct ieee80211com *ic, struct ieee80211_node *selbs)
+static int
+ieee80211_sta_join1(struct ieee80211_node *selbs)
{
+ struct ieee80211com *ic = selbs->ni_ic;
struct ieee80211_node *obss;
+ int canreassoc;
if (ic->ic_opmode == IEEE80211_M_IBSS) {
struct ieee80211_node_table *nt;
@@ -809,6 +555,13 @@ ieee80211_sta_join(struct ieee80211com *ic, struct ieee80211_node *selbs)
* Committed to selbs, setup state.
*/
obss = ic->ic_bss;
+ /*
+ * Check if old+new node have the same address in which
+ * case we can reassociate when operating in sta mode.
+ */
+ canreassoc = (obss != NULL &&
+ ic->ic_state == IEEE80211_S_RUN &&
+ IEEE80211_ADDR_EQ(obss->ni_macaddr, selbs->ni_macaddr));
ic->ic_bss = selbs; /* NB: caller assumed to bump refcnt */
if (obss != NULL) {
copy_bss(selbs, obss);
@@ -822,23 +575,94 @@ ieee80211_sta_join(struct ieee80211com *ic, struct ieee80211_node *selbs)
ieee80211_fix_rate(ic->ic_bss, &ic->ic_bss->ni_rates,
IEEE80211_F_DODEL | IEEE80211_F_JOIN);
+ ic->ic_bsschan = selbs->ni_chan;
+ ic->ic_curchan = ic->ic_bsschan;
+ ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
+ ic->ic_set_channel(ic);
/*
* Set the erp state (mostly the slot time) to deal with
* the auto-select case; this should be redundant if the
* mode is locked.
*/
- ic->ic_curmode = ieee80211_chan2mode(ic, selbs->ni_chan);
- ic->ic_curchan = selbs->ni_chan;
ieee80211_reset_erp(ic);
ieee80211_wme_initparams(ic);
- if (ic->ic_opmode == IEEE80211_M_STA)
- ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
- else
+ if (ic->ic_opmode == IEEE80211_M_STA) {
+ if (canreassoc) {
+ /* Reassociate */
+ ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
+ } else {
+ /*
+ * Act as if we received a DEAUTH frame in case we
+ * are invoked from the RUN state. This will cause
+ * us to try to re-authenticate if we are operating
+ * as a station.
+ */
+ ieee80211_new_state(ic, IEEE80211_S_AUTH,
+ IEEE80211_FC0_SUBTYPE_DEAUTH);
+ }
+ } else
ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
return 1;
}
+int
+ieee80211_sta_join(struct ieee80211com *ic,
+ const struct ieee80211_scan_entry *se)
+{
+ struct ieee80211_node *ni;
+
+ ni = ieee80211_alloc_node(&ic->ic_sta, se->se_macaddr);
+ if (ni == NULL) {
+ /* XXX msg */
+ return 0;
+ }
+ /*
+ * Expand scan state into node's format.
+ * XXX may not need all this stuff
+ */
+ IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);
+ ni->ni_esslen = se->se_ssid[1];
+ memcpy(ni->ni_essid, se->se_ssid+2, ni->ni_esslen);
+ ni->ni_rstamp = se->se_rstamp;
+ ni->ni_tstamp.tsf = se->se_tstamp.tsf;
+ ni->ni_intval = se->se_intval;
+ ni->ni_capinfo = se->se_capinfo;
+ /* XXX shift to 11n channel if htinfo present */
+ ni->ni_chan = se->se_chan;
+ ni->ni_timoff = se->se_timoff;
+ ni->ni_fhdwell = se->se_fhdwell;
+ ni->ni_fhindex = se->se_fhindex;
+ ni->ni_erp = se->se_erp;
+ ni->ni_rssi = se->se_rssi;
+ ni->ni_noise = se->se_noise;
+ if (se->se_htcap_ie != NULL)
+ ieee80211_ht_node_init(ni, se->se_htcap_ie);
+ if (se->se_htinfo_ie != NULL)
+ ieee80211_parse_htinfo(ni, se->se_htinfo_ie);
+ if (se->se_wpa_ie != NULL)
+ ieee80211_saveie(&ni->ni_wpa_ie, se->se_wpa_ie);
+ if (se->se_rsn_ie != NULL)
+ ieee80211_saveie(&ni->ni_rsn_ie, se->se_rsn_ie);
+ if (se->se_wme_ie != NULL)
+ ieee80211_saveie(&ni->ni_wme_ie, se->se_wme_ie);
+ if (se->se_ath_ie != NULL)
+ ieee80211_saveath(ni, se->se_ath_ie);
+
+ ic->ic_dtim_period = se->se_dtimperiod;
+ ic->ic_dtim_count = 0;
+
+ /* NB: must be after ni_chan is setup */
+ ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,
+ IEEE80211_F_DOSORT);
+ if (se->se_htcap_ie != NULL)
+ ieee80211_setup_htrates(ni, se->se_htcap_ie, IEEE80211_F_JOIN);
+ if (se->se_htinfo_ie != NULL)
+ ieee80211_setup_basic_htrates(ni, se->se_htinfo_ie);
+
+ return ieee80211_sta_join1(ieee80211_ref_node(ni));
+}
+
/*
* Leave the specified IBSS/BSS network. The node is assumed to
* be passed in with a held reference.
@@ -871,7 +695,7 @@ node_cleanup(struct ieee80211_node *ni)
{
#define N(a) (sizeof(a)/sizeof(a[0]))
struct ieee80211com *ic = ni->ni_ic;
- int i, qlen;
+ int i;
/* NB: preserve ni_table */
if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {
@@ -892,13 +716,12 @@ node_cleanup(struct ieee80211_node *ni)
/*
* Drain power save queue and, if needed, clear TIM.
*/
- IEEE80211_NODE_SAVEQ_DRAIN(ni, qlen);
- if (qlen != 0 && ic->ic_set_tim != NULL)
+ if (ieee80211_node_saveq_drain(ni) != 0 && ic->ic_set_tim != NULL)
ic->ic_set_tim(ni, 0);
ni->ni_associd = 0;
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_DEVBUF);
+ FREE(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
/*
@@ -932,22 +755,33 @@ node_free(struct ieee80211_node *ni)
ic->ic_node_cleanup(ni);
if (ni->ni_wpa_ie != NULL)
- FREE(ni->ni_wpa_ie, M_DEVBUF);
+ FREE(ni->ni_wpa_ie, M_80211_NODE);
+ if (ni->ni_rsn_ie != NULL)
+ FREE(ni->ni_rsn_ie, M_80211_NODE);
if (ni->ni_wme_ie != NULL)
- FREE(ni->ni_wme_ie, M_DEVBUF);
+ FREE(ni->ni_wme_ie, M_80211_NODE);
+ if (ni->ni_ath_ie != NULL)
+ FREE(ni->ni_ath_ie, M_80211_NODE);
IEEE80211_NODE_SAVEQ_DESTROY(ni);
FREE(ni, M_80211_NODE);
}
-static u_int8_t
+static int8_t
node_getrssi(const struct ieee80211_node *ni)
{
return ni->ni_rssi;
}
static void
+node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
+{
+ *rssi = ni->ni_rssi;
+ *noise = ni->ni_noise;
+}
+
+static void
ieee80211_setup_node(struct ieee80211_node_table *nt,
- struct ieee80211_node *ni, const u_int8_t *macaddr)
+ struct ieee80211_node *ni, const uint8_t *macaddr)
{
struct ieee80211com *ic = nt->nt_ic;
int hash;
@@ -965,6 +799,7 @@ ieee80211_setup_node(struct ieee80211_node_table *nt,
ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE);
ni->ni_inact_reload = nt->nt_inact_init;
ni->ni_inact = ni->ni_inact_reload;
+ ni->ni_ath_defkeyix = 0x7fff;
IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
IEEE80211_NODE_LOCK(nt);
@@ -976,7 +811,7 @@ ieee80211_setup_node(struct ieee80211_node_table *nt,
}
struct ieee80211_node *
-ieee80211_alloc_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
+ieee80211_alloc_node(struct ieee80211_node_table *nt, const uint8_t *macaddr)
{
struct ieee80211com *ic = nt->nt_ic;
struct ieee80211_node *ni;
@@ -996,7 +831,7 @@ ieee80211_alloc_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
* once the send completes.
*/
struct ieee80211_node *
-ieee80211_tmp_node(struct ieee80211com *ic, const u_int8_t *macaddr)
+ieee80211_tmp_node(struct ieee80211com *ic, const uint8_t *macaddr)
{
struct ieee80211_node *ni;
@@ -1010,7 +845,7 @@ ieee80211_tmp_node(struct ieee80211com *ic, const u_int8_t *macaddr)
ieee80211_node_initref(ni); /* mark referenced */
ni->ni_txpower = ic->ic_bss->ni_txpower;
/* NB: required by ieee80211_fix_rate */
- ieee80211_set_chan(ic, ni, ic->ic_bss->ni_chan);
+ ieee80211_node_set_chan(ic, ni);
ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey,
IEEE80211_KEYIX_NONE);
/* XXX optimize away */
@@ -1026,7 +861,7 @@ ieee80211_tmp_node(struct ieee80211com *ic, const u_int8_t *macaddr)
}
struct ieee80211_node *
-ieee80211_dup_bss(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
+ieee80211_dup_bss(struct ieee80211_node_table *nt, const uint8_t *macaddr)
{
struct ieee80211com *ic = nt->nt_ic;
struct ieee80211_node *ni;
@@ -1041,7 +876,7 @@ ieee80211_dup_bss(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
ni->ni_txpower = ic->ic_bss->ni_txpower;
ni->ni_vlan = ic->ic_bss->ni_vlan; /* XXX?? */
IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
- ieee80211_set_chan(ic, ni, ic->ic_bss->ni_chan);
+ ieee80211_node_set_chan(ic, ni);
ni->ni_rsn = ic->ic_bss->ni_rsn;
} else
ic->ic_stats.is_rx_nodealloc++;
@@ -1051,10 +886,10 @@ ieee80211_dup_bss(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
static struct ieee80211_node *
#ifdef IEEE80211_DEBUG_REFCNT
_ieee80211_find_node_debug(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr, const char *func, int line)
+ const uint8_t *macaddr, const char *func, int line)
#else
_ieee80211_find_node(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr)
+ const uint8_t *macaddr)
#endif
{
struct ieee80211_node *ni;
@@ -1086,9 +921,9 @@ _ieee80211_find_node(struct ieee80211_node_table *nt,
struct ieee80211_node *
#ifdef IEEE80211_DEBUG_REFCNT
ieee80211_find_node_debug(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr, const char *func, int line)
+ const uint8_t *macaddr, const char *func, int line)
#else
-ieee80211_find_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
+ieee80211_find_node(struct ieee80211_node_table *nt, const uint8_t *macaddr)
#endif
{
struct ieee80211_node *ni;
@@ -1107,7 +942,7 @@ ieee80211_find_node(struct ieee80211_node_table *nt, const u_int8_t *macaddr)
*/
struct ieee80211_node *
ieee80211_fakeup_adhoc_node(struct ieee80211_node_table *nt,
- const u_int8_t macaddr[IEEE80211_ADDR_LEN])
+ const uint8_t macaddr[IEEE80211_ADDR_LEN])
{
struct ieee80211com *ic = nt->nt_ic;
struct ieee80211_node *ni;
@@ -1120,158 +955,30 @@ ieee80211_fakeup_adhoc_node(struct ieee80211_node_table *nt,
ni->ni_rates = ic->ic_bss->ni_rates;
if (ic->ic_newassoc != NULL)
ic->ic_newassoc(ni, 1);
- /* XXX not right for 802.1x/WPA */
- ieee80211_node_authorize(ni);
if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
/*
- * Blindly propagate capabilities based on the
- * local configuration. In particular this permits
- * us to use QoS to disable ACK's.
+ * In adhoc demo mode there are no management
+ * frames to use to discover neighbor capabilities,
+ * so blindly propagate the local configuration
+ * so we can do interesting things (e.g. use
+ * WME to disable ACK's).
*/
if (ic->ic_flags & IEEE80211_F_WME)
ni->ni_flags |= IEEE80211_NODE_QOS;
+ if (ic->ic_flags & IEEE80211_F_FF)
+ ni->ni_flags |= IEEE80211_NODE_FF;
}
+ /* XXX not right for 802.1x/WPA */
+ ieee80211_node_authorize(ni);
}
return ni;
}
-#ifdef IEEE80211_DEBUG
-static void
-dump_probe_beacon(u_int8_t subtype, int isnew,
- const u_int8_t mac[IEEE80211_ADDR_LEN],
- const struct ieee80211_scanparams *sp)
-{
-
- printf("[%s] %s%s on chan %u (bss chan %u) ",
- ether_sprintf(mac), isnew ? "new " : "",
- ieee80211_mgt_subtype_name[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT],
- sp->chan, sp->bchan);
- ieee80211_print_essid(sp->ssid + 2, sp->ssid[1]);
- printf("\n");
-
- if (isnew) {
- printf("[%s] caps 0x%x bintval %u erp 0x%x",
- ether_sprintf(mac), sp->capinfo, sp->bintval, sp->erp);
- if (sp->country != NULL) {
-#ifdef __FreeBSD__
- printf(" country info %*D",
- sp->country[1], sp->country+2, " ");
-#else
- int i;
- printf(" country info");
- for (i = 0; i < sp->country[1]; i++)
- printf(" %02x", sp->country[i+2]);
-#endif
- }
- printf("\n");
- }
-}
-#endif /* IEEE80211_DEBUG */
-
-static void
-saveie(u_int8_t **iep, const u_int8_t *ie)
-{
-
- if (ie == NULL)
- *iep = NULL;
- else
- ieee80211_saveie(iep, ie);
-}
-
-/*
- * Process a beacon or probe response frame.
- */
-void
-ieee80211_add_scan(struct ieee80211com *ic,
- const struct ieee80211_scanparams *sp,
- const struct ieee80211_frame *wh,
- int subtype, int rssi, int rstamp)
-{
-#define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
- struct ieee80211_node_table *nt = &ic->ic_scan;
- struct ieee80211_node *ni;
- int newnode = 0;
-
- ni = ieee80211_find_node(nt, wh->i_addr2);
- if (ni == NULL) {
- /*
- * Create a new entry.
- */
- ni = ic->ic_node_alloc(nt);
- if (ni == NULL) {
- ic->ic_stats.is_rx_nodealloc++;
- return;
- }
- ieee80211_setup_node(nt, ni, wh->i_addr2);
- /*
- * XXX inherit from ic_bss.
- */
- ni->ni_authmode = ic->ic_bss->ni_authmode;
- ni->ni_txpower = ic->ic_bss->ni_txpower;
- ni->ni_vlan = ic->ic_bss->ni_vlan; /* XXX?? */
- ieee80211_set_chan(ic, ni, ic->ic_curchan);
- ni->ni_rsn = ic->ic_bss->ni_rsn;
- newnode = 1;
- }
-#ifdef IEEE80211_DEBUG
- if (ieee80211_msg_scan(ic) && (ic->ic_flags & IEEE80211_F_SCAN))
- dump_probe_beacon(subtype, newnode, wh->i_addr2, sp);
-#endif
- /* XXX ap beaconing multiple ssid w/ same bssid */
- if (sp->ssid[1] != 0 &&
- (ISPROBE(subtype) || ni->ni_esslen == 0)) {
- ni->ni_esslen = sp->ssid[1];
- memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
- memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
- }
- ni->ni_scangen = ic->ic_scan.nt_scangen;
- IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
- ni->ni_rssi = rssi;
- ni->ni_rstamp = rstamp;
- memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
- ni->ni_intval = sp->bintval;
- ni->ni_capinfo = sp->capinfo;
- ni->ni_chan = &ic->ic_channels[sp->chan];
- ni->ni_fhdwell = sp->fhdwell;
- ni->ni_fhindex = sp->fhindex;
- ni->ni_erp = sp->erp;
- if (sp->tim != NULL) {
- struct ieee80211_tim_ie *ie =
- (struct ieee80211_tim_ie *) sp->tim;
-
- ni->ni_dtim_count = ie->tim_count;
- ni->ni_dtim_period = ie->tim_period;
- }
- /*
- * Record the byte offset from the mac header to
- * the start of the TIM information element for
- * use by hardware and/or to speedup software
- * processing of beacon frames.
- */
- ni->ni_timoff = sp->timoff;
- /*
- * Record optional information elements that might be
- * used by applications or drivers.
- */
- saveie(&ni->ni_wme_ie, sp->wme);
- saveie(&ni->ni_wpa_ie, sp->wpa);
-
- /* NB: must be after ni_chan is setup */
- ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
-
- if (!newnode)
- ieee80211_free_node(ni);
-#undef ISPROBE
-}
-
void
ieee80211_init_neighbor(struct ieee80211_node *ni,
const struct ieee80211_frame *wh,
const struct ieee80211_scanparams *sp)
{
-
- IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
- "%s: %p<%s>\n", __func__, ni, ether_sprintf(ni->ni_macaddr));
ni->ni_esslen = sp->ssid[1];
memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
@@ -1287,6 +994,10 @@ ieee80211_init_neighbor(struct ieee80211_node *ni,
ieee80211_saveie(&ni->ni_wme_ie, sp->wme);
if (sp->wpa != NULL)
ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
+ if (sp->rsn != NULL)
+ ieee80211_saveie(&ni->ni_rsn_ie, sp->rsn);
+ if (sp->ath != NULL)
+ ieee80211_saveath(ni, sp->ath);
/* NB: must be after ni_chan is setup */
ieee80211_setup_rates(ni, sp->rates, sp->xrates,
@@ -1324,6 +1035,9 @@ ieee80211_add_neighbor(struct ieee80211com *ic,
((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
#define IS_PSPOLL(wh) \
((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
+#define IS_BAR(wh) \
+ ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_BAR)
+
/*
* Locate the node for sender, track state, and then pass the
* (referenced) node up to the 802.11 layer for its use. We
@@ -1344,17 +1058,11 @@ ieee80211_find_rxnode(struct ieee80211com *ic,
struct ieee80211_node_table *nt;
struct ieee80211_node *ni;
- /* XXX may want scanned nodes in the neighbor table for adhoc */
- if (ic->ic_opmode == IEEE80211_M_STA ||
- ic->ic_opmode == IEEE80211_M_MONITOR ||
- (ic->ic_flags & IEEE80211_F_SCAN))
- nt = &ic->ic_scan;
- else
- nt = &ic->ic_sta;
/* XXX check ic_bss first in station mode */
/* XXX 4-address frames? */
+ nt = &ic->ic_sta;
IEEE80211_NODE_LOCK(nt);
- if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
+ if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_BAR(wh) /*&& !IS_RTS(ah)*/)
ni = _ieee80211_find_node(nt, wh->i_addr1);
else
ni = _ieee80211_find_node(nt, wh->i_addr2);
@@ -1386,19 +1094,14 @@ ieee80211_find_rxnode_withkey(struct ieee80211com *ic,
struct ieee80211_node_table *nt;
struct ieee80211_node *ni;
- if (ic->ic_opmode == IEEE80211_M_STA ||
- ic->ic_opmode == IEEE80211_M_MONITOR ||
- (ic->ic_flags & IEEE80211_F_SCAN))
- nt = &ic->ic_scan;
- else
- nt = &ic->ic_sta;
+ nt = &ic->ic_sta;
IEEE80211_NODE_LOCK(nt);
if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax)
ni = nt->nt_keyixmap[keyix];
else
ni = NULL;
if (ni == NULL) {
- if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
+ if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_BAR(wh) /*&& !IS_RTS(ah)*/)
ni = _ieee80211_find_node(nt, wh->i_addr1);
else
ni = _ieee80211_find_node(nt, wh->i_addr2);
@@ -1420,13 +1123,13 @@ ieee80211_find_rxnode_withkey(struct ieee80211com *ic,
nt->nt_keyixmap[keyix] = ieee80211_ref_node(ni);
}
}
- } else {
+ } else
ieee80211_ref_node(ni);
- }
IEEE80211_NODE_UNLOCK(nt);
return ni;
}
+#undef IS_BAR
#undef IS_PSPOLL
#undef IS_CTL
@@ -1436,10 +1139,10 @@ ieee80211_find_rxnode_withkey(struct ieee80211com *ic,
*/
struct ieee80211_node *
#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_find_txnode_debug(struct ieee80211com *ic, const u_int8_t *macaddr,
+ieee80211_find_txnode_debug(struct ieee80211com *ic, const uint8_t *macaddr,
const char *func, int line)
#else
-ieee80211_find_txnode(struct ieee80211com *ic, const u_int8_t *macaddr)
+ieee80211_find_txnode(struct ieee80211com *ic, const uint8_t *macaddr)
#endif
{
struct ieee80211_node_table *nt = &ic->ic_sta;
@@ -1492,54 +1195,21 @@ ieee80211_find_txnode(struct ieee80211com *ic, const u_int8_t *macaddr)
}
/*
- * Like find but search based on the channel too.
- */
-struct ieee80211_node *
-#ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_find_node_with_channel_debug(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr, struct ieee80211_channel *chan,
- const char *func, int line)
-#else
-ieee80211_find_node_with_channel(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr, struct ieee80211_channel *chan)
-#endif
-{
- struct ieee80211_node *ni;
- int hash;
-
- hash = IEEE80211_NODE_HASH(macaddr);
- IEEE80211_NODE_LOCK(nt);
- LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
- if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) &&
- ni->ni_chan == chan) {
- ieee80211_ref_node(ni); /* mark referenced */
- IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
- REFCNT_LOC, ni, ether_sprintf(ni->ni_macaddr),
- ieee80211_node_refcnt(ni));
- break;
- }
- }
- IEEE80211_NODE_UNLOCK(nt);
- return ni;
-}
-
-/*
* Like find but search based on the ssid too.
*/
struct ieee80211_node *
#ifdef IEEE80211_DEBUG_REFCNT
ieee80211_find_node_with_ssid_debug(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr, u_int ssidlen, const u_int8_t *ssid,
+ const uint8_t *macaddr, u_int ssidlen, const uint8_t *ssid,
const char *func, int line)
#else
ieee80211_find_node_with_ssid(struct ieee80211_node_table *nt,
- const u_int8_t *macaddr, u_int ssidlen, const u_int8_t *ssid)
+ const uint8_t *macaddr, u_int ssidlen, const uint8_t *ssid)
#endif
{
#define MATCH_SSID(ni, ssid, ssidlen) \
(ni->ni_esslen == ssidlen && memcmp(ni->ni_essid, ssid, ssidlen) == 0)
- static const u_int8_t zeromac[IEEE80211_ADDR_LEN];
- struct ieee80211com *ic = nt->nt_ic;
+ static const uint8_t zeromac[IEEE80211_ADDR_LEN];
struct ieee80211_node *ni;
int hash;
@@ -1563,7 +1233,7 @@ ieee80211_find_node_with_ssid(struct ieee80211_node_table *nt,
}
if (ni != NULL) {
ieee80211_ref_node(ni); /* mark referenced */
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
+ IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
REFCNT_LOC, ni, ether_sprintf(ni->ni_macaddr),
ieee80211_node_refcnt(ni));
}
@@ -1748,46 +1418,6 @@ ieee80211_free_allnodes_locked(struct ieee80211_node_table *nt)
}
node_reclaim(nt, ni);
}
- ieee80211_reset_erp(ic);
-}
-
-static void
-ieee80211_free_allnodes(struct ieee80211_node_table *nt)
-{
-
- IEEE80211_NODE_LOCK(nt);
- ieee80211_free_allnodes_locked(nt);
- IEEE80211_NODE_UNLOCK(nt);
-}
-
-/*
- * Timeout entries in the scan cache.
- */
-static void
-ieee80211_timeout_scan_candidates(struct ieee80211_node_table *nt)
-{
- struct ieee80211com *ic = nt->nt_ic;
- struct ieee80211_node *ni, *tni;
-
- IEEE80211_NODE_LOCK(nt);
- ni = ic->ic_bss;
- /* XXX belongs elsewhere */
- if (ni->ni_rxfrag[0] != NULL && ticks > ni->ni_rxfragstamp + hz) {
- m_freem(ni->ni_rxfrag[0]);
- ni->ni_rxfrag[0] = NULL;
- }
- TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, tni) {
- if (ni->ni_inact && --ni->ni_inact == 0) {
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
- "[%s] scan candidate purged from cache "
- "(refcnt %u)\n", ether_sprintf(ni->ni_macaddr),
- ieee80211_node_refcnt(ni));
- node_reclaim(nt, ni);
- }
- }
- IEEE80211_NODE_UNLOCK(nt);
-
- nt->nt_inact_timer = IEEE80211_INACT_WAIT;
}
/*
@@ -1812,8 +1442,6 @@ ieee80211_timeout_stations(struct ieee80211_node_table *nt)
ic->ic_opmode == IEEE80211_M_AHDEMO);
IEEE80211_SCAN_LOCK(nt);
gen = ++nt->nt_scangen;
- IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
- "%s: %s scangen %u\n", __func__, nt->nt_name, gen);
restart:
IEEE80211_NODE_LOCK(nt);
TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
@@ -1826,7 +1454,8 @@ restart:
* will be reclaimed when the last reference to them
* goes away (when frame xmits complete).
*/
- if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+ if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
+ ic->ic_opmode == IEEE80211_M_STA) &&
(ni->ni_flags & IEEE80211_NODE_AREF) == 0)
continue;
/*
@@ -1848,50 +1477,27 @@ restart:
ni->ni_inact--;
if (ni->ni_associd != 0 || isadhoc) {
/*
- * Age frames on the power save queue. The
- * aging interval is 4 times the listen
- * interval specified by the station. This
- * number is factored into the age calculations
- * when the frame is placed on the queue. We
- * store ages as time differences we can check
- * and/or adjust only the head of the list.
+ * Age frames on the power save queue.
*/
- if (IEEE80211_NODE_SAVEQ_QLEN(ni) != 0) {
- struct mbuf *m;
- int discard = 0;
-
- IEEE80211_NODE_SAVEQ_LOCK(ni);
- while (IF_POLL(&ni->ni_savedq, m) != NULL &&
- M_AGE_GET(m) < IEEE80211_INACT_WAIT) {
-IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, "[%s] discard frame, age %u\n", ether_sprintf(ni->ni_macaddr), M_AGE_GET(m));/*XXX*/
- _IEEE80211_NODE_SAVEQ_DEQUEUE_HEAD(ni, m);
- m_freem(m);
- discard++;
- }
- if (m != NULL)
- M_AGE_SUB(m, IEEE80211_INACT_WAIT);
- IEEE80211_NODE_SAVEQ_UNLOCK(ni);
-
- if (discard != 0) {
- IEEE80211_DPRINTF(ic,
- IEEE80211_MSG_POWER,
- "[%s] discard %u frames for age\n",
- ether_sprintf(ni->ni_macaddr),
- discard);
- IEEE80211_NODE_STAT_ADD(ni,
- ps_discard, discard);
- if (IEEE80211_NODE_SAVEQ_QLEN(ni) == 0)
- ic->ic_set_tim(ni, 0);
- }
- }
+ if (ieee80211_node_saveq_age(ni) != 0 &&
+ IEEE80211_NODE_SAVEQ_QLEN(ni) == 0 &&
+ ic->ic_set_tim != NULL)
+ ic->ic_set_tim(ni, 0);
/*
* Probe the station before time it out. We
* send a null data frame which may not be
* universally supported by drivers (need it
* for ps-poll support so it should be...).
+ *
+ * XXX don't probe the station unless we've
+ * received a frame from them (and have
+ * some idea of the rates they are capable
+ * of); this will get fixed more properly
+ * soon with better handling of the rate set.
*/
if (0 < ni->ni_inact &&
- ni->ni_inact <= ic->ic_inact_probe) {
+ ni->ni_inact <= ic->ic_inact_probe &&
+ ni->ni_rates.rs_nrates != 0) {
IEEE80211_NOTE(ic,
IEEE80211_MSG_INACT | IEEE80211_MSG_NODE,
ni, "%s",
@@ -1927,8 +1533,8 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, "[%s] discard frame, age %u\n", ether
* completed or by ieee80211_node_leave.
*
* Separately we must drop the node lock before sending
- * in case the driver takes a lock, as this will result
- * in LOR between the node lock and the driver lock.
+ * in case the driver takes a lock, as this can result
+ * in a LOR between the node lock and the driver lock.
*/
IEEE80211_NODE_UNLOCK(nt);
if (ni->ni_associd != 0) {
@@ -1944,8 +1550,18 @@ IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER, "[%s] discard frame, age %u\n", ether
IEEE80211_NODE_UNLOCK(nt);
IEEE80211_SCAN_UNLOCK(nt);
+}
- nt->nt_inact_timer = IEEE80211_INACT_WAIT;
+void
+ieee80211_node_timeout(void *arg)
+{
+ struct ieee80211com *ic = arg;
+
+ ieee80211_scan_timeout(ic);
+ ieee80211_timeout_stations(&ic->ic_sta);
+
+ callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
+ ieee80211_node_timeout, ic);
}
void
@@ -1987,14 +1603,20 @@ ieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
ni->ni_rxseqs[IEEE80211_NONQOS_TID] >> IEEE80211_SEQ_SEQ_SHIFT,
ni->ni_rxseqs[IEEE80211_NONQOS_TID] & IEEE80211_SEQ_FRAG_MASK,
ni->ni_rxfragstamp);
- printf("\trstamp %u rssi %u intval %u capinfo 0x%x\n",
- ni->ni_rstamp, ni->ni_rssi, ni->ni_intval, ni->ni_capinfo);
+ printf("\trstamp %u rssi %d noise %d intval %u capinfo 0x%x\n",
+ ni->ni_rstamp, ni->ni_rssi, ni->ni_noise,
+ ni->ni_intval, ni->ni_capinfo);
printf("\tbssid %s essid \"%.*s\" channel %u:0x%x\n",
ether_sprintf(ni->ni_bssid),
ni->ni_esslen, ni->ni_essid,
ni->ni_chan->ic_freq, ni->ni_chan->ic_flags);
printf("\tfails %u inact %u txrate %u\n",
ni->ni_fails, ni->ni_inact, ni->ni_txrate);
+ printf("\thtcap %x htparam %x htctlchan %u ht2ndchan %u\n",
+ ni->ni_htcap, ni->ni_htparam,
+ ni->ni_htctlchan, ni->ni_ht2ndchan);
+ printf("\thtopmode %x htstbc %x chw %u\n",
+ ni->ni_htopmode, ni->ni_htstbc, ni->ni_chw);
}
void
@@ -2024,7 +1646,14 @@ ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
"[%s] station needs long slot time, count %d\n",
ether_sprintf(ni->ni_macaddr), ic->ic_longslotsta);
/* XXX vap's w/ conflicting needs won't work */
- ieee80211_set_shortslottime(ic, 0);
+ if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) {
+ /*
+ * Don't force slot time when switched to turbo
+ * mode as non-ERP stations won't be present; this
+ * need only be done when on the normal G channel.
+ */
+ ieee80211_set_shortslottime(ic, 0);
+ }
}
/*
* If the new station is not an ERP station
@@ -2067,7 +1696,7 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
int newassoc;
if (ni->ni_associd == 0) {
- u_int16_t aid;
+ uint16_t aid;
/*
* It would be good to search the bitmap
@@ -2088,20 +1717,26 @@ ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp
IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
ic->ic_sta_assoc++;
newassoc = 1;
- if (ic->ic_curmode == IEEE80211_MODE_11G &&
- IEEE80211_IS_CHAN_FULL(ni->ni_chan))
+ if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
+ IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
ieee80211_node_join_11g(ic, ni);
} else
newassoc = 0;
IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG,
- "[%s] station %sassociated at aid %d: %s preamble, %s slot time%s%s\n",
+ "[%s] station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s\n",
ether_sprintf(ni->ni_macaddr), newassoc ? "" : "re",
IEEE80211_NODE_AID(ni),
ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "",
- ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : ""
+ ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
+ ni->ni_flags & IEEE80211_NODE_HT ?
+ (ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
+ IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_FF) ?
+ ", fast-frames" : "",
+ IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_TURBOP) ?
+ ", turbo" : ""
);
/* give driver a chance to setup state like ni_txrate */
@@ -2123,9 +1758,9 @@ static void
ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
{
- KASSERT(ic->ic_curmode == IEEE80211_MODE_11G,
- ("not in 11g, bss %u:0x%x, curmode %u", ni->ni_chan->ic_freq,
- ni->ni_chan->ic_flags, ic->ic_curmode));
+ KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),
+ ("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq,
+ ic->ic_bsschan->ic_flags, ic->ic_curmode));
/*
* If a long slot station do the slot time bookkeeping.
@@ -2191,9 +1826,7 @@ ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
"[%s] station with aid %d leaves\n",
ether_sprintf(ni->ni_macaddr), IEEE80211_NODE_AID(ni));
- KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP ||
- ic->ic_opmode == IEEE80211_M_IBSS ||
- ic->ic_opmode == IEEE80211_M_AHDEMO,
+ KASSERT(ic->ic_opmode != IEEE80211_M_STA,
("unexpected operating mode %u", ic->ic_opmode));
/*
* If node wasn't previously associated all
@@ -2214,8 +1847,8 @@ ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
ni->ni_associd = 0;
ic->ic_sta_assoc--;
- if (ic->ic_curmode == IEEE80211_MODE_11G &&
- IEEE80211_IS_CHAN_FULL(ni->ni_chan))
+ if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
+ IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
ieee80211_node_leave_11g(ic, ni);
/*
* Cleanup station state. In particular clear various
@@ -2239,38 +1872,30 @@ done:
ieee80211_free_node(ni);
}
-u_int8_t
+int8_t
ieee80211_getrssi(struct ieee80211com *ic)
{
#define NZ(x) ((x) == 0 ? 1 : (x))
struct ieee80211_node_table *nt = &ic->ic_sta;
- u_int32_t rssi_samples, rssi_total;
+ int rssi_samples;
+ int32_t rssi_total;
struct ieee80211_node *ni;
rssi_total = 0;
rssi_samples = 0;
switch (ic->ic_opmode) {
case IEEE80211_M_IBSS: /* average of all ibss neighbors */
- /* XXX locking */
- TAILQ_FOREACH(ni, &nt->nt_node, ni_list)
- if (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) {
- rssi_samples++;
- rssi_total += ic->ic_node_getrssi(ni);
- }
- break;
case IEEE80211_M_AHDEMO: /* average of all neighbors */
- /* XXX locking */
- TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
- rssi_samples++;
- rssi_total += ic->ic_node_getrssi(ni);
- }
- break;
case IEEE80211_M_HOSTAP: /* average of all associated stations */
/* XXX locking */
TAILQ_FOREACH(ni, &nt->nt_node, ni_list)
- if (IEEE80211_AID(ni->ni_associd) != 0) {
- rssi_samples++;
- rssi_total += ic->ic_node_getrssi(ni);
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
+ (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS)) {
+ int8_t rssi = ic->ic_node_getrssi(ni);
+ if (rssi != 0) {
+ rssi_samples++;
+ rssi_total += rssi;
+ }
}
break;
case IEEE80211_M_MONITOR: /* XXX */
@@ -2285,35 +1910,16 @@ ieee80211_getrssi(struct ieee80211com *ic)
#undef NZ
}
-/*
- * Indicate whether there are frames queued for a station in power-save mode.
- */
-static void
-ieee80211_set_tim(struct ieee80211_node *ni, int set)
+void
+ieee80211_getsignal(struct ieee80211com *ic, int8_t *rssi, int8_t *noise)
{
- struct ieee80211com *ic = ni->ni_ic;
- u_int16_t aid;
- KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP ||
- ic->ic_opmode == IEEE80211_M_IBSS,
- ("operating mode %u", ic->ic_opmode));
-
- aid = IEEE80211_AID(ni->ni_associd);
- KASSERT(aid < ic->ic_max_aid,
- ("bogus aid %u, max %u", aid, ic->ic_max_aid));
-
- IEEE80211_BEACON_LOCK(ic);
- if (set != (isset(ic->ic_tim_bitmap, aid) != 0)) {
- if (set) {
- setbit(ic->ic_tim_bitmap, aid);
- ic->ic_ps_pending++;
- } else {
- clrbit(ic->ic_tim_bitmap, aid);
- ic->ic_ps_pending--;
- }
- ic->ic_flags |= IEEE80211_F_TIMUPDATE;
- }
- IEEE80211_BEACON_UNLOCK(ic);
+ if (ic->ic_bss == NULL) /* NB: shouldn't happen */
+ return;
+ ic->ic_node_getsignal(ic->ic_bss, rssi, noise);
+ /* for non-station mode return avg'd rssi accounting */
+ if (ic->ic_opmode != IEEE80211_M_STA)
+ *rssi = ieee80211_getrssi(ic);
}
/*
@@ -2323,8 +1929,7 @@ ieee80211_set_tim(struct ieee80211_node *ni, int set)
static void
ieee80211_node_table_init(struct ieee80211com *ic,
struct ieee80211_node_table *nt,
- const char *name, int inact, int keyixmax,
- void (*timeout)(struct ieee80211_node_table *))
+ const char *name, int inact, int keyixmax)
{
IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
@@ -2338,7 +1943,6 @@ ieee80211_node_table_init(struct ieee80211com *ic,
nt->nt_name = name;
nt->nt_scangen = 1;
nt->nt_inact_init = inact;
- nt->nt_timeout = timeout;
nt->nt_keyixmax = keyixmax;
if (nt->nt_keyixmax > 0) {
MALLOC(nt->nt_keyixmap, struct ieee80211_node **,
@@ -2352,7 +1956,7 @@ ieee80211_node_table_init(struct ieee80211com *ic,
nt->nt_keyixmap = NULL;
}
-void
+static void
ieee80211_node_table_reset(struct ieee80211_node_table *nt)
{
@@ -2360,7 +1964,6 @@ ieee80211_node_table_reset(struct ieee80211_node_table *nt)
"%s %s table\n", __func__, nt->nt_name);
IEEE80211_NODE_LOCK(nt);
- nt->nt_inact_timer = 0;
ieee80211_free_allnodes_locked(nt);
IEEE80211_NODE_UNLOCK(nt);
}