add statistics for all failures and/or abnormal events; still need
to add per-node statistics
This commit is contained in:
parent
627200f847
commit
1be50176db
@ -113,16 +113,23 @@ ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
|
||||
n0 = NULL;
|
||||
if ((ctx = ic->ic_wep_ctx) == NULL) {
|
||||
ctx = malloc(arc4_ctxlen(), M_DEVBUF, M_NOWAIT);
|
||||
if (ctx == NULL)
|
||||
if (ctx == NULL) {
|
||||
ic->ic_stats.is_crypto_nomem++;
|
||||
goto fail;
|
||||
}
|
||||
ic->ic_wep_ctx = ctx;
|
||||
}
|
||||
m = m0;
|
||||
left = m->m_pkthdr.len;
|
||||
MGET(n, M_DONTWAIT, m->m_type);
|
||||
n0 = n;
|
||||
if (n == NULL)
|
||||
if (n == NULL) {
|
||||
if (txflag)
|
||||
ic->ic_stats.is_tx_nombuf++;
|
||||
else
|
||||
ic->ic_stats.is_rx_nombuf++;
|
||||
goto fail;
|
||||
}
|
||||
M_MOVE_PKTHDR(n, m);
|
||||
len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
|
||||
if (txflag) {
|
||||
@ -188,8 +195,13 @@ ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
|
||||
len = n->m_len - noff;
|
||||
if (len == 0) {
|
||||
MGET(n->m_next, M_DONTWAIT, n->m_type);
|
||||
if (n->m_next == NULL)
|
||||
if (n->m_next == NULL) {
|
||||
if (txflag)
|
||||
ic->ic_stats.is_tx_nombuf++;
|
||||
else
|
||||
ic->ic_stats.is_rx_nombuf++;
|
||||
goto fail;
|
||||
}
|
||||
n = n->m_next;
|
||||
n->m_len = MLEN;
|
||||
if (left >= MINCLSIZE) {
|
||||
@ -223,8 +235,10 @@ ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
|
||||
else {
|
||||
n->m_len = noff;
|
||||
MGET(n->m_next, M_DONTWAIT, n->m_type);
|
||||
if (n->m_next == NULL)
|
||||
if (n->m_next == NULL) {
|
||||
ic->ic_stats.is_tx_nombuf++;
|
||||
goto fail;
|
||||
}
|
||||
n = n->m_next;
|
||||
n->m_len = sizeof(crcbuf);
|
||||
noff = 0;
|
||||
@ -252,6 +266,7 @@ ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
|
||||
n0->m_len, -1, -1);
|
||||
}
|
||||
#endif
|
||||
ic->ic_stats.is_rx_decryptcrc++;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
if_printf(ifp, "receive packet with wrong version: %x\n",
|
||||
wh->i_fc[0]);
|
||||
ieee80211_unref_node(&ni);
|
||||
ic->ic_stats.is_rx_badversion++;
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -124,19 +125,21 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
* them to go through bpf tapping at the 802.11 layer.
|
||||
*/
|
||||
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
|
||||
/* XXX statistic */
|
||||
IEEE80211_DPRINTF2(("%s: frame too short, len %u\n",
|
||||
__func__, m->m_pkthdr.len));
|
||||
/* XXX statistic */
|
||||
ic->ic_stats.is_rx_tooshort++;
|
||||
goto out; /* XXX */
|
||||
}
|
||||
if (ic->ic_state != IEEE80211_S_SCAN) {
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) {
|
||||
/* not interested in */
|
||||
IEEE80211_DPRINTF2(("%s: discard frame from "
|
||||
"bss %s\n", __func__,
|
||||
ether_sprintf(wh->i_addr2)));
|
||||
/* not interested in */
|
||||
ic->ic_stats.is_rx_wrongbss++;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
@ -153,6 +156,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
IEEE80211_DPRINTF2(("%s: discard frame from "
|
||||
"bss %s\n", __func__,
|
||||
ether_sprintf(bssid)));
|
||||
ic->ic_stats.is_rx_wrongbss++;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
@ -171,6 +175,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
|
||||
rxseq == ni->ni_rxseq) {
|
||||
/* duplicate, silently discarded */
|
||||
ic->ic_stats.is_rx_dup++; /* XXX per-station stat */
|
||||
goto out;
|
||||
}
|
||||
ni->ni_inact = 0;
|
||||
@ -180,8 +185,10 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
case IEEE80211_FC0_TYPE_DATA:
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
if (dir != IEEE80211_FC1_DIR_FROMDS)
|
||||
if (dir != IEEE80211_FC1_DIR_FROMDS) {
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto out;
|
||||
}
|
||||
if ((ifp->if_flags & IFF_SIMPLEX) &&
|
||||
IEEE80211_IS_MULTICAST(wh->i_addr1) &&
|
||||
IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) {
|
||||
@ -191,17 +198,22 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
* It should be silently discarded for
|
||||
* SIMPLEX interface.
|
||||
*/
|
||||
ic->ic_stats.is_rx_mcastecho++;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case IEEE80211_M_IBSS:
|
||||
case IEEE80211_M_AHDEMO:
|
||||
if (dir != IEEE80211_FC1_DIR_NODS)
|
||||
if (dir != IEEE80211_FC1_DIR_NODS) {
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case IEEE80211_M_HOSTAP:
|
||||
if (dir != IEEE80211_FC1_DIR_TODS)
|
||||
if (dir != IEEE80211_FC1_DIR_TODS) {
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto out;
|
||||
}
|
||||
/* check if source STA is associated */
|
||||
if (ni == ic->ic_bss) {
|
||||
IEEE80211_DPRINTF(("%s: data from unknown src "
|
||||
@ -215,6 +227,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
IEEE80211_REASON_NOT_AUTHED);
|
||||
ieee80211_free_node(ic, ni);
|
||||
}
|
||||
ic->ic_stats.is_rx_notassoc++;
|
||||
goto err;
|
||||
}
|
||||
if (ni->ni_associd == 0) {
|
||||
@ -225,6 +238,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
IEEE80211_FC0_SUBTYPE_DISASSOC,
|
||||
IEEE80211_REASON_NOT_ASSOCED);
|
||||
ieee80211_unref_node(&ni);
|
||||
ic->ic_stats.is_rx_notassoc++;
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
@ -234,18 +248,24 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
|
||||
if (ic->ic_flags & IEEE80211_F_WEPON) {
|
||||
m = ieee80211_wep_crypt(ifp, m, 0);
|
||||
if (m == NULL)
|
||||
if (m == NULL) {
|
||||
ic->ic_stats.is_rx_wepfail++;
|
||||
goto err;
|
||||
}
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
} else
|
||||
} else {
|
||||
ic->ic_stats.is_rx_nowep++;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* copy to listener after decrypt */
|
||||
if (ic->ic_rawbpf)
|
||||
bpf_mtap(ic->ic_rawbpf, m);
|
||||
m = ieee80211_decap(ifp, m);
|
||||
if (m == NULL)
|
||||
if (m == NULL) {
|
||||
ic->ic_stats.is_rx_decap++;
|
||||
goto err;
|
||||
}
|
||||
ifp->if_ipackets++;
|
||||
|
||||
/* perform as a bridge within the AP */
|
||||
@ -286,21 +306,29 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
return;
|
||||
|
||||
case IEEE80211_FC0_TYPE_MGT:
|
||||
if (dir != IEEE80211_FC1_DIR_NODS)
|
||||
if (dir != IEEE80211_FC1_DIR_NODS) {
|
||||
ic->ic_stats.is_rx_wrongdir++;
|
||||
goto err;
|
||||
if (ic->ic_opmode == IEEE80211_M_AHDEMO)
|
||||
}
|
||||
if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
|
||||
ic->ic_stats.is_rx_ahdemo_mgt++;
|
||||
goto out;
|
||||
}
|
||||
subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
|
||||
|
||||
/* drop frames without interest */
|
||||
if (ic->ic_state == IEEE80211_S_SCAN) {
|
||||
if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
|
||||
subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
|
||||
subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
|
||||
ic->ic_stats.is_rx_mgtdiscard++;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (ic->ic_opmode != IEEE80211_M_IBSS &&
|
||||
subtype == IEEE80211_FC0_SUBTYPE_BEACON)
|
||||
subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
|
||||
ic->ic_stats.is_rx_mgtdiscard++;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_DEBUG) {
|
||||
@ -336,6 +364,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
|
||||
return;
|
||||
|
||||
case IEEE80211_FC0_TYPE_CTL:
|
||||
ic->ic_stats.is_rx_ctl++;
|
||||
goto out;
|
||||
default:
|
||||
IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, type));
|
||||
@ -475,6 +504,7 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
IEEE80211_DPRINTF(("%s: extended rate set too large;"
|
||||
" only using %u of %u rates\n",
|
||||
__func__, nxrates, xrates[1]));
|
||||
ic->ic_stats.is_rx_rstoobig++;
|
||||
}
|
||||
memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates);
|
||||
rs->rs_nrates += nxrates;
|
||||
@ -482,13 +512,13 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
return ieee80211_fix_rate(ic, ni, flags);
|
||||
}
|
||||
|
||||
/* XXX statistics */
|
||||
/* Verify the existence and length of __elem or get out. */
|
||||
#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
|
||||
if ((__elem) == NULL) { \
|
||||
IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n", \
|
||||
__func__, ieee80211_mgt_subtype_name[subtype >> \
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT])); \
|
||||
ic->ic_stats.is_rx_elem_missing++; \
|
||||
return; \
|
||||
} \
|
||||
if ((__elem)[1] > (__maxlen)) { \
|
||||
@ -497,6 +527,7 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
ieee80211_mgt_subtype_name[subtype >> \
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT], \
|
||||
ether_sprintf(wh->i_addr2))); \
|
||||
ic->ic_stats.is_rx_elem_toobig++; \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
@ -508,6 +539,7 @@ ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
ieee80211_mgt_subtype_name[subtype >> \
|
||||
IEEE80211_FC0_SUBTYPE_SHIFT], \
|
||||
ether_sprintf(wh->i_addr2))); \
|
||||
ic->ic_stats.is_rx_elem_toosmall++; \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
@ -598,6 +630,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
IEEE80211_DPRINTF(("%s: invalid ERP "
|
||||
"element; length %u, expecting "
|
||||
"1\n", __func__, frm[1]));
|
||||
ic->ic_stats.is_rx_elem_toobig++;
|
||||
break;
|
||||
}
|
||||
erp = frm[2];
|
||||
@ -605,6 +638,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
default:
|
||||
IEEE80211_DPRINTF2(("%s: element id %u/len %u "
|
||||
"ignored\n", __func__, *frm, frm[1]));
|
||||
ic->ic_stats.is_rx_elem_unknown++;
|
||||
break;
|
||||
}
|
||||
frm += frm[1] + 2;
|
||||
@ -620,6 +654,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
"%u\n", __func__,
|
||||
ISPROBE(subtype) ? "probe response" : "beacon",
|
||||
chan));
|
||||
ic->ic_stats.is_rx_badchan++;
|
||||
return;
|
||||
}
|
||||
if (chan != bchan) {
|
||||
@ -634,7 +669,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
"for channel %u\n", __func__,
|
||||
ISPROBE(subtype) ? "probe response" : "beacon",
|
||||
bchan, chan));
|
||||
/* XXX statistic */
|
||||
ic->ic_stats.is_rx_chanmismatch++;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -669,8 +704,10 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
#endif
|
||||
if (ni == NULL) {
|
||||
ni = ieee80211_alloc_node(ic, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
if (ni == NULL) {
|
||||
ic->ic_stats.is_rx_nodealloc++;
|
||||
return;
|
||||
}
|
||||
ni->ni_esslen = ssid[1];
|
||||
memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
|
||||
memcpy(ni->ni_essid, ssid + 2, ssid[1]);
|
||||
@ -741,13 +778,16 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
printf(" from %s\n", ether_sprintf(wh->i_addr2));
|
||||
}
|
||||
#endif
|
||||
ic->ic_stats.is_rx_ssidmismatch++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ni == ic->ic_bss) {
|
||||
ni = ieee80211_dup_bss(ic, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
if (ni == NULL) {
|
||||
ic->ic_stats.is_rx_nodealloc++;
|
||||
return;
|
||||
}
|
||||
IEEE80211_DPRINTF(("%s: new req from %s\n",
|
||||
__func__, ether_sprintf(wh->i_addr2)));
|
||||
allocbs = 1;
|
||||
@ -792,12 +832,24 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
/* TODO: shared key auth */
|
||||
IEEE80211_DPRINTF(("%s: unsupported auth %d from %s\n",
|
||||
__func__, algo, ether_sprintf(wh->i_addr2)));
|
||||
ic->ic_stats.is_rx_auth_unsupported++;
|
||||
return;
|
||||
}
|
||||
if (ic->ic_state != IEEE80211_S_RUN) {
|
||||
IEEE80211_DPRINTF(("%s: discard auth from %s; "
|
||||
"state %u\n", __func__,
|
||||
ether_sprintf(wh->i_addr2), ic->ic_state));
|
||||
ic->ic_stats.is_rx_bad_auth++;
|
||||
break;
|
||||
}
|
||||
if (seq != (ic->ic_opmode == IEEE80211_M_STA ? 2 : 1)) {
|
||||
IEEE80211_DPRINTF(("%s: discard auth from %s; seq %u\n",
|
||||
__func__, ether_sprintf(wh->i_addr2), seq));
|
||||
ic->ic_stats.is_rx_bad_auth++;
|
||||
break;
|
||||
}
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_IBSS:
|
||||
if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
|
||||
return;
|
||||
ieee80211_new_state(ic, IEEE80211_S_AUTH,
|
||||
wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
|
||||
break;
|
||||
@ -807,12 +859,12 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
break;
|
||||
|
||||
case IEEE80211_M_HOSTAP:
|
||||
if (ic->ic_state != IEEE80211_S_RUN || seq != 1)
|
||||
return;
|
||||
if (ni == ic->ic_bss) {
|
||||
ni = ieee80211_alloc_node(ic, wh->i_addr2);
|
||||
if (ni == NULL)
|
||||
if (ni == NULL) {
|
||||
ic->ic_stats.is_rx_nodealloc++;
|
||||
return;
|
||||
}
|
||||
IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
|
||||
ni->ni_rssi = rssi;
|
||||
ni->ni_rstamp = rstamp;
|
||||
@ -829,8 +881,6 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
break;
|
||||
|
||||
case IEEE80211_M_STA:
|
||||
if (ic->ic_state != IEEE80211_S_AUTH || seq != 2)
|
||||
return;
|
||||
if (status != 0) {
|
||||
if_printf(&ic->ic_if,
|
||||
"authentication failed (reason %d) for %s\n",
|
||||
@ -838,6 +888,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
ether_sprintf(wh->i_addr3));
|
||||
if (ni != ic->ic_bss)
|
||||
ni->ni_fails++;
|
||||
ic->ic_stats.is_rx_auth_fail++;
|
||||
return;
|
||||
}
|
||||
ieee80211_new_state(ic, IEEE80211_S_ASSOC,
|
||||
@ -877,6 +928,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) {
|
||||
IEEE80211_DPRINTF(("%s: ignore other bss from %s\n",
|
||||
__func__, ether_sprintf(wh->i_addr2)));
|
||||
ic->ic_stats.is_rx_assoc_bss++;
|
||||
return;
|
||||
}
|
||||
capinfo = le16toh(*(u_int16_t *)frm); frm += 2;
|
||||
@ -909,6 +961,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
printf(" from %s\n", ether_sprintf(wh->i_addr2));
|
||||
}
|
||||
#endif
|
||||
ic->ic_stats.is_rx_ssidmismatch++;
|
||||
return;
|
||||
}
|
||||
if (ni == ic->ic_bss) {
|
||||
@ -921,6 +974,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
IEEE80211_REASON_ASSOC_NOT_AUTHED);
|
||||
ieee80211_free_node(ic, ni);
|
||||
}
|
||||
ic->ic_stats.is_rx_assoc_notauth++;
|
||||
return;
|
||||
}
|
||||
/* XXX per-node cipher suite */
|
||||
@ -935,6 +989,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
ni->ni_associd = 0;
|
||||
IEEE80211_SEND_MGMT(ic, ni, resp,
|
||||
IEEE80211_STATUS_CAPINFO);
|
||||
ic->ic_stats.is_rx_assoc_capmismatch++;
|
||||
return;
|
||||
}
|
||||
ieee80211_setup_rates(ic, ni, rates, xrates,
|
||||
@ -946,6 +1001,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
ni->ni_associd = 0;
|
||||
IEEE80211_SEND_MGMT(ic, ni, resp,
|
||||
IEEE80211_STATUS_BASIC_RATE);
|
||||
ic->ic_stats.is_rx_assoc_norate++;
|
||||
return;
|
||||
}
|
||||
ni->ni_rssi = rssi;
|
||||
@ -1003,6 +1059,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
status, ether_sprintf(wh->i_addr3));
|
||||
if (ni != ic->ic_bss)
|
||||
ni->ni_fails++;
|
||||
ic->ic_stats.is_rx_auth_fail++;
|
||||
return;
|
||||
}
|
||||
ni->ni_associd = le16toh(*(u_int16_t *)frm);
|
||||
@ -1039,6 +1096,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
*/
|
||||
IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
|
||||
reason = le16toh(*(u_int16_t *)frm);
|
||||
ic->ic_stats.is_rx_deauth++;
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
ieee80211_new_state(ic, IEEE80211_S_AUTH,
|
||||
@ -1068,6 +1126,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
*/
|
||||
IEEE80211_VERIFY_LENGTH(efrm - frm, 2);
|
||||
reason = le16toh(*(u_int16_t *)frm);
|
||||
ic->ic_stats.is_rx_disassoc++;
|
||||
switch (ic->ic_opmode) {
|
||||
case IEEE80211_M_STA:
|
||||
ieee80211_new_state(ic, IEEE80211_S_ASSOC,
|
||||
@ -1091,6 +1150,7 @@ ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0,
|
||||
default:
|
||||
IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not "
|
||||
"handled\n", __func__, subtype));
|
||||
ic->ic_stats.is_rx_badsubtype++;
|
||||
break;
|
||||
}
|
||||
#undef ISPROBE
|
||||
|
@ -720,6 +720,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
int error = 0;
|
||||
u_int kid, len;
|
||||
struct ieee80211req *ireq;
|
||||
struct ifreq *ifr;
|
||||
u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE];
|
||||
char tmpssid[IEEE80211_NWID_LEN];
|
||||
struct ieee80211_channel *chan;
|
||||
@ -981,6 +982,10 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
break;
|
||||
error = ieee80211_cfgset(ifp, cmd, data);
|
||||
break;
|
||||
case SIOCG80211STATS:
|
||||
ifr = (struct ifreq *)data;
|
||||
copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
|
||||
break;
|
||||
default:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
|
@ -38,6 +38,50 @@
|
||||
* IEEE 802.11 ioctls.
|
||||
*/
|
||||
|
||||
struct ieee80211_stats {
|
||||
u_int32_t is_rx_badversion; /* rx frame with bad version */
|
||||
u_int32_t is_rx_tooshort; /* rx frame too short */
|
||||
u_int32_t is_rx_wrongbss; /* rx from wrong bssid */
|
||||
u_int32_t is_rx_dup; /* rx discard 'cuz dup */
|
||||
u_int32_t is_rx_wrongdir; /* rx w/ wrong direction */
|
||||
u_int32_t is_rx_mcastecho; /* rx discard 'cuz mcast echo */
|
||||
u_int32_t is_rx_notassoc; /* rx discard 'cuz sta !assoc */
|
||||
u_int32_t is_rx_nowep; /* rx w/ wep but wep !config */
|
||||
u_int32_t is_rx_wepfail; /* rx wep processing failed */
|
||||
u_int32_t is_rx_decap; /* rx decapsulation failed */
|
||||
u_int32_t is_rx_mgtdiscard; /* rx discard mgt frames */
|
||||
u_int32_t is_rx_ctl; /* rx discard ctrl frames */
|
||||
u_int32_t is_rx_rstoobig; /* rx rate set truncated */
|
||||
u_int32_t is_rx_elem_missing; /* rx required element missing*/
|
||||
u_int32_t is_rx_elem_toobig; /* rx element too big */
|
||||
u_int32_t is_rx_elem_toosmall; /* rx element too small */
|
||||
u_int32_t is_rx_elem_unknown; /* rx element unknown */
|
||||
u_int32_t is_rx_badchan; /* rx frame w/ invalid chan */
|
||||
u_int32_t is_rx_chanmismatch; /* rx frame chan mismatch */
|
||||
u_int32_t is_rx_nodealloc; /* rx frame dropped */
|
||||
u_int32_t is_rx_ssidmismatch; /* rx frame ssid mismatch */
|
||||
u_int32_t is_rx_auth_unsupported; /* rx w/ unsupported auth alg */
|
||||
u_int32_t is_rx_auth_fail; /* rx sta auth failure */
|
||||
u_int32_t is_rx_assoc_bss; /* rx assoc from wrong bssid */
|
||||
u_int32_t is_rx_assoc_notauth; /* rx assoc w/o auth */
|
||||
u_int32_t is_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */
|
||||
u_int32_t is_rx_assoc_norate; /* rx assoc w/ no rate match */
|
||||
u_int32_t is_rx_deauth; /* rx deauthentication */
|
||||
u_int32_t is_rx_disassoc; /* rx disassociation */
|
||||
u_int32_t is_rx_badsubtype; /* rx frame w/ unknown subtype*/
|
||||
u_int32_t is_rx_nombuf; /* rx failed for lack of mbuf */
|
||||
u_int32_t is_rx_decryptcrc; /* rx decrypt failed on crc */
|
||||
u_int32_t is_rx_ahdemo_mgt; /* rx discard ahdemo mgt frame*/
|
||||
u_int32_t is_rx_bad_auth; /* rx bad auth request */
|
||||
u_int32_t is_tx_nombuf; /* tx failed for lack of mbuf */
|
||||
u_int32_t is_tx_nonode; /* tx failed for no node */
|
||||
u_int32_t is_tx_unknownmgt; /* tx of unknown mgt frame */
|
||||
u_int32_t is_scan_active; /* active scans started */
|
||||
u_int32_t is_scan_passive; /* passive scans started */
|
||||
u_int32_t is_node_timeout; /* nodes timed out inactivity */
|
||||
u_int32_t is_crypto_nomem; /* no memory for crypto ctx */
|
||||
};
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
* FreeBSD-style ioctls.
|
||||
@ -79,6 +123,8 @@ struct ieee80211req {
|
||||
#ifndef IEEE80211_CHAN_ANY
|
||||
#define IEEE80211_CHAN_ANY 0xffff /* token for ``any channel'' */
|
||||
#endif
|
||||
|
||||
#define SIOCG80211STATS _IOWR('i', 236, struct ifreq)
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#endif /* _NET80211_IEEE80211_IOCTL_H_ */
|
||||
|
@ -148,8 +148,11 @@ ieee80211_begin_scan(struct ifnet *ifp)
|
||||
* In all but hostap mode scanning starts off in
|
||||
* an active mode before switching to passive.
|
||||
*/
|
||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
|
||||
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++;
|
||||
if (ifp->if_flags & IFF_DEBUG)
|
||||
if_printf(ifp, "begin %s scan\n",
|
||||
(ic->ic_flags & IEEE80211_F_ASCAN) ?
|
||||
@ -581,6 +584,7 @@ ieee80211_timeout_nodes(struct ieee80211com *ic)
|
||||
IEEE80211_FC0_SUBTYPE_DEAUTH,
|
||||
IEEE80211_REASON_AUTH_EXPIRE);
|
||||
ieee80211_free_node(ic, ni);
|
||||
ic->ic_stats.is_node_timeout++;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
|
||||
if (m->m_len < sizeof(struct ether_header)) {
|
||||
m = m_pullup(m, sizeof(struct ether_header));
|
||||
if (m == NULL) {
|
||||
/* XXX statistic */
|
||||
ic->ic_stats.is_tx_nombuf++;
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@ -183,6 +183,7 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
|
||||
IEEE80211_DPRINTF(("%s: no node for dst %s, "
|
||||
"discard frame\n", __func__,
|
||||
ether_sprintf(eh.ether_dhost)));
|
||||
ic->ic_stats.is_tx_nonode++;
|
||||
goto bad;
|
||||
}
|
||||
ni = ic->ic_bss;
|
||||
@ -200,8 +201,10 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni)
|
||||
llc->llc_snap.org_code[2] = 0;
|
||||
llc->llc_snap.ether_type = eh.ether_type;
|
||||
M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT);
|
||||
if (m == NULL)
|
||||
if (m == NULL) {
|
||||
ic->ic_stats.is_tx_nombuf++;
|
||||
goto bad;
|
||||
}
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA;
|
||||
*(u_int16_t *)wh->i_dur = 0;
|
||||
@ -312,7 +315,7 @@ int
|
||||
ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
int type, int arg)
|
||||
{
|
||||
#define senderr(_x) do { ret = _x; goto bad; } while (0)
|
||||
#define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0)
|
||||
struct ifnet *ifp = &ic->ic_if;
|
||||
struct mbuf *m;
|
||||
u_int8_t *frm;
|
||||
@ -343,7 +346,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
+ 2 + IEEE80211_RATE_SIZE
|
||||
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM);
|
||||
senderr(ENOMEM, is_tx_nombuf);
|
||||
m->m_data += sizeof(struct ieee80211_frame);
|
||||
frm = mtod(m, u_int8_t *);
|
||||
frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen);
|
||||
@ -375,7 +378,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
+ 6
|
||||
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM);
|
||||
senderr(ENOMEM, is_tx_nombuf);
|
||||
m->m_data += sizeof(struct ieee80211_frame);
|
||||
frm = mtod(m, u_int8_t *);
|
||||
|
||||
@ -435,7 +438,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
case IEEE80211_FC0_SUBTYPE_AUTH:
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM);
|
||||
senderr(ENOMEM, is_tx_nombuf);
|
||||
MH_ALIGN(m, 2 * 3);
|
||||
m->m_pkthdr.len = m->m_len = 6;
|
||||
frm = mtod(m, u_int8_t *);
|
||||
@ -453,7 +456,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
ether_sprintf(ni->ni_macaddr), arg);
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM);
|
||||
senderr(ENOMEM, is_tx_nombuf);
|
||||
MH_ALIGN(m, 2);
|
||||
m->m_pkthdr.len = m->m_len = 2;
|
||||
*mtod(m, u_int16_t *) = htole16(arg); /* reason */
|
||||
@ -478,7 +481,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
+ 2 + IEEE80211_RATE_SIZE
|
||||
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM);
|
||||
senderr(ENOMEM, is_tx_nombuf);
|
||||
m->m_data += sizeof(struct ieee80211_frame);
|
||||
frm = mtod(m, u_int8_t *);
|
||||
|
||||
@ -534,7 +537,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
+ 2 + IEEE80211_RATE_SIZE
|
||||
+ 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE));
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM);
|
||||
senderr(ENOMEM, is_tx_nombuf);
|
||||
m->m_data += sizeof(struct ieee80211_frame);
|
||||
frm = mtod(m, u_int8_t *);
|
||||
|
||||
@ -565,7 +568,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
ether_sprintf(ni->ni_macaddr), arg);
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
senderr(ENOMEM);
|
||||
senderr(ENOMEM, is_tx_nombuf);
|
||||
MH_ALIGN(m, 2);
|
||||
m->m_pkthdr.len = m->m_len = 2;
|
||||
*mtod(m, u_int16_t *) = htole16(arg); /* reason */
|
||||
@ -574,7 +577,7 @@ ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
default:
|
||||
IEEE80211_DPRINTF(("%s: invalid mgmt frame type %u\n",
|
||||
__func__, type));
|
||||
senderr(EINVAL);
|
||||
senderr(EINVAL, is_tx_unknownmgt);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include <net80211/ieee80211.h>
|
||||
#include <net80211/ieee80211_crypto.h>
|
||||
#include <net80211/ieee80211_ioctl.h> /* for ieee80211_stats */
|
||||
#include <net80211/ieee80211_node.h>
|
||||
#include <net80211/ieee80211_proto.h>
|
||||
|
||||
@ -193,6 +194,7 @@ struct ieee80211com {
|
||||
int ic_wep_txkey; /* default tx key index */
|
||||
void *ic_wep_ctx; /* wep crypt context */
|
||||
u_int32_t ic_iv; /* initial vector for wep */
|
||||
struct ieee80211_stats ic_stats; /* statistics */
|
||||
};
|
||||
#define ic_if ic_ac.ac_if
|
||||
#define ic_softc ic_if.if_softc
|
||||
|
Loading…
Reference in New Issue
Block a user