summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2008-07-28 19:42:14 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2008-07-28 19:42:14 +0000
commit41f1fbc6549d95ec37be6c9054167724172cae62 (patch)
tree7f862e148dc689a702644b1a1736ec18c512874a
parent2e279386220f163d69d14fded311eaddc3fe1ab4 (diff)
ignore PS mode changes and PS-Poll from non-associated STAs.
keep track of the number of associated STAs in PS mode.
-rw-r--r--sys/net80211/ieee80211_input.c46
-rw-r--r--sys/net80211/ieee80211_node.c5
-rw-r--r--sys/net80211/ieee80211_var.h3
3 files changed, 28 insertions, 26 deletions
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index d801a7e03a2..a9d0c146bd8 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_input.c,v 1.86 2008/07/28 10:38:05 damien Exp $ */
+/* $OpenBSD: ieee80211_input.c,v 1.87 2008/07/28 19:42:13 damien Exp $ */
/*-
* Copyright (c) 2001 Atsushi Onoe
@@ -71,7 +71,8 @@ enum ieee80211_akm ieee80211_parse_rsn_akm(const u_int8_t[]);
int ieee80211_parse_rsn_body(struct ieee80211com *, const u_int8_t *,
u_int, struct ieee80211_rsnparams *);
int ieee80211_save_ie(const u_int8_t *, u_int8_t **);
-void ieee80211_recv_pspoll(struct ieee80211com *, struct mbuf *);
+void ieee80211_recv_pspoll(struct ieee80211com *, struct mbuf *,
+ struct ieee80211_node *);
void ieee80211_recv_probe_resp(struct ieee80211com *, struct mbuf *,
struct ieee80211_node *, struct ieee80211_rxinfo *, int);
void ieee80211_recv_probe_req(struct ieee80211com *, struct mbuf *,
@@ -210,21 +211,21 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
if ((ic->ic_caps & IEEE80211_C_PMGT) &&
ic->ic_opmode == IEEE80211_M_HOSTAP &&
- ic->ic_state == IEEE80211_S_RUN &&
- dir == IEEE80211_FC1_DIR_TODS) {
- if ((wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) &&
- ni->ni_pwrsave == IEEE80211_PS_AWAKE) {
- /* turn on PS mode */
- ni->ni_pwrsave = IEEE80211_PS_DOZE;
- DPRINTF(("power saving on for %s\n",
- ether_sprintf(wh->i_addr2)));
- }
- if (!(wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) &&
- ni->ni_pwrsave == IEEE80211_PS_DOZE) {
+ ni->ni_state == IEEE80211_STA_ASSOC) {
+ if (wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) {
+ if (ni->ni_pwrsave == IEEE80211_PS_AWAKE) {
+ /* turn on PS mode */
+ ni->ni_pwrsave = IEEE80211_PS_DOZE;
+ ic->ic_pssta++;
+ DPRINTF(("PS mode on for %s, count %d\n",
+ ether_sprintf(wh->i_addr2), ic->ic_pssta));
+ }
+ } else if (ni->ni_pwrsave == IEEE80211_PS_DOZE) {
/* turn off PS mode */
ni->ni_pwrsave = IEEE80211_PS_AWAKE;
- DPRINTF(("power saving off for %s\n",
- ether_sprintf(wh->i_addr2)));
+ ic->ic_pssta--;
+ DPRINTF(("PS mode off for %s, count %d\n",
+ ether_sprintf(wh->i_addr2), ic->ic_pssta));
(*ic->ic_set_tim)(ic, ni->ni_associd, 0);
@@ -494,7 +495,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
switch (subtype) {
case IEEE80211_FC0_SUBTYPE_PS_POLL:
- ieee80211_recv_pspoll(ic, m);
+ ieee80211_recv_pspoll(ic, m, ni);
break;
}
goto out;
@@ -536,7 +537,7 @@ ieee80211_decap(struct ifnet *ifp, struct mbuf *m, int hdrlen)
llc->llc_snap.org_code[0] == 0 &&
llc->llc_snap.org_code[1] == 0 &&
llc->llc_snap.org_code[2] == 0) {
- m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
+ m_adj(m, hdrlen + sizeof(*llc) - sizeof(*eh));
llc = NULL;
} else {
m_adj(m, hdrlen - sizeof(*eh));
@@ -1815,16 +1816,17 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
}
void
-ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m)
+ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m,
+ struct ieee80211_node *ni)
{
struct ifnet *ifp = &ic->ic_if;
struct ieee80211_frame_pspoll *psp;
struct ieee80211_frame *wh;
- struct ieee80211_node *ni;
u_int16_t aid;
if (!(ic->ic_caps & IEEE80211_C_PMGT) ||
- ic->ic_opmode != IEEE80211_M_HOSTAP)
+ ic->ic_opmode != IEEE80211_M_HOSTAP ||
+ ni->ni_state != IEEE80211_STA_ASSOC)
return;
if (m->m_len < sizeof(*psp)) {
@@ -1839,10 +1841,6 @@ ieee80211_recv_pspoll(struct ieee80211com *ic, struct mbuf *m)
ic->ic_stats.is_rx_wrongbss++;
return;
}
- if ((ni = ieee80211_find_node(ic, psp->i_ta)) == NULL) {
- DPRINTF(("no node found for %s", ether_sprintf(psp->i_ta)));
- return;
- }
aid = letoh16(*(u_int16_t *)psp->i_aid);
if (aid != ni->ni_associd) {
DPRINTF(("invalid pspoll aid %x from %s\n", aid,
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 9d8e129b793..ef2404910b3 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_node.c,v 1.36 2008/07/27 14:21:15 damien Exp $ */
+/* $OpenBSD: ieee80211_node.c,v 1.37 2008/07/28 19:42:13 damien Exp $ */
/* $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $ */
/*-
@@ -1295,6 +1295,9 @@ ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
ni->ni_associd = 0;
+ if (ni->ni_pwrsave == IEEE80211_PS_DOZE)
+ ic->ic_pssta--;
+
if (ic->ic_flags & IEEE80211_F_RSNON)
ieee80211_node_leave_rsn(ic, ni);
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index a052f55096e..b1bb482929b 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_var.h,v 1.41 2008/07/27 18:24:01 damien Exp $ */
+/* $OpenBSD: ieee80211_var.h,v 1.42 2008/07/28 19:42:13 damien Exp $ */
/* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
/*-
@@ -243,6 +243,7 @@ struct ieee80211com {
u_int16_t ic_nonerpsta; /* # non-ERP stations */
u_int16_t ic_longslotsta; /* # long slot time stations */
u_int16_t ic_rsnsta; /* # RSN stations */
+ u_int16_t ic_pssta; /* # ps mode stations */
int ic_mgt_timer; /* mgmt timeout */
int ic_inact_timer; /* inactivity timer wait */
int ic_des_esslen;