161374Sdcs/*-
261374Sdcs * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
361374Sdcs * All rights reserved.
461374Sdcs *
561374Sdcs * Redistribution and use in source and binary forms, with or without
661374Sdcs * modification, are permitted provided that the following conditions
761374Sdcs * are met:
861374Sdcs * 1. Redistributions of source code must retain the above copyright
961374Sdcs *    notice, this list of conditions and the following disclaimer,
1061374Sdcs *    without modification.
1161374Sdcs * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1261374Sdcs *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
1361374Sdcs *    redistribution must be conditioned upon including a substantially
1461374Sdcs *    similar Disclaimer requirement for further binary redistribution.
1561374Sdcs *
1661374Sdcs * NO WARRANTY
1761374Sdcs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1861374Sdcs * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1961374Sdcs * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
2061374Sdcs * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2161374Sdcs * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
2261374Sdcs * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2361374Sdcs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2461374Sdcs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2561374Sdcs * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2661374Sdcs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2761374Sdcs * THE POSSIBILITY OF SUCH DAMAGES.
2861374Sdcs *
2961374Sdcs * $FreeBSD$
3061374Sdcs */
3161374Sdcs
3261374Sdcs/*
3361374Sdcs * net80211 statistics class.
3461374Sdcs */
35102215Sscottl#include <sys/types.h>
36253862Smarcel#include <sys/file.h>
37253862Smarcel#include <sys/sockio.h>
38253862Smarcel#include <sys/socket.h>
39253862Smarcel#include <net/if.h>
40253862Smarcel#include <net/if_dl.h>
41102215Sscottl#include <net/if_media.h>
42253862Smarcel#include <net/if_var.h>
43102215Sscottl#include <net/ethernet.h>
4461374Sdcs
45102215Sscottl#include <stdio.h>
4661374Sdcs#include <stdlib.h>
4761374Sdcs#include <signal.h>
4861374Sdcs#include <string.h>
4961374Sdcs#include <unistd.h>
5076116Sdcs#include <err.h>
5161374Sdcs#include <ifaddrs.h>
5261374Sdcs
5361374Sdcs#include "../../../../sys/net80211/ieee80211_ioctl.h"
5461374Sdcs
5561374Sdcs#include "wlanstats.h"
5661374Sdcs
5761374Sdcs#ifndef IEEE80211_ADDR_COPY
5865617Sdcs#define	IEEE80211_ADDR_COPY(dst, src)	memcpy(dst, src, IEEE80211_ADDR_LEN)
5965617Sdcs#define	IEEE80211_ADDR_EQ(a1,a2)	(memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)
6065617Sdcs#endif
6165617Sdcs
6276116Sdcs#define	AFTER(prev)	((prev)+1)
6361374Sdcs
6461374Sdcsstatic const struct fmt wlanstats[] = {
6561374Sdcs#define	S_RX_BADVERSION		0
6661374Sdcs	{ 5,  "rx_badversion",	"bvers",	"rx frame with bad version" },
6761374Sdcs#define	S_RX_TOOSHORT		AFTER(S_RX_BADVERSION)
68138223Sscottl	{ 5,  "rx_tooshort",	"2short",	"rx frame too short" },
69138223Sscottl#define	S_RX_WRONGBSS		AFTER(S_RX_TOOSHORT)
70138223Sscottl	{ 5,  "rx_wrongbss",	"wrbss",	"rx from wrong bssid" },
71138223Sscottl#define	S_RX_DUP		AFTER(S_RX_WRONGBSS)
7261374Sdcs	{ 5,  "rx_dup",		"rxdup",	"rx discard 'cuz dup" },
7361374Sdcs#define	S_RX_WRONGDIR		AFTER(S_RX_DUP)
7461374Sdcs	{ 5,  "rx_wrongdir",	"wrdir",	"rx w/ wrong direction" },
7561374Sdcs#define	S_RX_MCASTECHO		AFTER(S_RX_WRONGDIR)
7661374Sdcs	{ 5,  "rx_mcastecho",	"mecho",	"rx discard 'cuz mcast echo" },
7761374Sdcs#define	S_RX_NOTASSOC		AFTER(S_RX_MCASTECHO)
7861374Sdcs	{ 6,  "rx_notassoc",	"!assoc",	"rx discard 'cuz sta !assoc" },
7961374Sdcs#define	S_RX_NOPRIVACY		AFTER(S_RX_NOTASSOC)
8061374Sdcs	{ 6,  "rx_noprivacy",	"nopriv",	"rx w/ wep but privacy off" },
8161374Sdcs#define	S_RX_UNENCRYPTED	AFTER(S_RX_NOPRIVACY)
82138223Sscottl	{ 6,  "rx_unencrypted",	"unencr",	"rx w/o wep and privacy on" },
8361374Sdcs#define	S_RX_WEPFAIL		AFTER(S_RX_UNENCRYPTED)
8461374Sdcs	{ 7,  "rx_wepfail",	"wepfail",	"rx wep processing failed" },
8561374Sdcs#define	S_RX_DECAP		AFTER(S_RX_WEPFAIL)
8661374Sdcs	{ 5,  "rx_decap",	"decap",	"rx decapsulation failed" },
8761374Sdcs#define	S_RX_MGTDISCARD		AFTER(S_RX_DECAP)
8861374Sdcs	{ 8,  "rx_mgtdiscard",	"mgtdiscard",	"rx discard mgt frames" },
8961374Sdcs#define	S_RX_CTL		AFTER(S_RX_MGTDISCARD)
9061374Sdcs	{ 5,  "rx_ctl",		"ctl",		"rx ctrl frames" },
9161374Sdcs#define	S_RX_BEACON		AFTER(S_RX_CTL)
9261374Sdcs	{ 6,  "rx_beacon",	"beacon",	"rx beacon frames" },
9361374Sdcs#define	S_RX_RSTOOBIG		AFTER(S_RX_BEACON)
9461374Sdcs	{ 6,  "rx_rstoobig",	"rs2big",	"rx rate set truncated" },
9561374Sdcs#define	S_RX_ELEM_MISSING	AFTER(S_RX_RSTOOBIG)
9661374Sdcs	{ 6,  "rx_elem_missing","iemiss",	"rx required element missing" },
97138223Sscottl#define	S_RX_ELEM_TOOBIG	AFTER(S_RX_ELEM_MISSING)
9861374Sdcs	{ 6,  "rx_elem_toobig",	"ie2big",	"rx element too big" },
9961374Sdcs#define	S_RX_ELEM_TOOSMALL	AFTER(S_RX_ELEM_TOOBIG)
10061374Sdcs	{ 7,  "rx_elem_toosmall","ie2small","rx element too small" },
10161374Sdcs#define	S_RX_ELEM_UNKNOWN 	AFTER(S_RX_ELEM_TOOSMALL)
10261374Sdcs	{ 5,  "rx_elem_unknown","ieunk",	"rx element unknown" },
10361374Sdcs#define	S_RX_BADCHAN		AFTER(S_RX_ELEM_UNKNOWN)
10461374Sdcs	{ 6,  "rx_badchan",	"badchan",	"rx frame w/ invalid chan" },
105138223Sscottl#define	S_RX_CHANMISMATCH	AFTER(S_RX_BADCHAN)
106138223Sscottl	{ 5,  "rx_chanmismatch","chanmismatch",	"rx frame chan mismatch" },
107138223Sscottl#define	S_RX_NODEALLOC		AFTER(S_RX_CHANMISMATCH)
108138223Sscottl	{ 5,  "rx_nodealloc",	"nodealloc",	"nodes allocated (rx)" },
10961374Sdcs#define	S_RX_SSIDMISMATCH	AFTER(S_RX_NODEALLOC)
11061374Sdcs	{ 5,  "rx_ssidmismatch","ssidmismatch",	"rx frame ssid mismatch" },
11161374Sdcs#define	S_RX_AUTH_UNSUPPORTED	AFTER(S_RX_SSIDMISMATCH)
11261374Sdcs	{ 5,  "rx_auth_unsupported","auth_unsupported",
11361374Sdcs		"rx w/ unsupported auth alg" },
11461374Sdcs#define	S_RX_AUTH_FAIL		AFTER(S_RX_AUTH_UNSUPPORTED)
11561374Sdcs	{ 5,  "rx_auth_fail",	"auth_fail",	"rx sta auth failure" },
11661374Sdcs#define	S_RX_AUTH_FAIL_CODE	AFTER(S_RX_AUTH_FAIL)
11761374Sdcs	{ 5,  "rx_auth_fail_code","auth_fail_code",
11861374Sdcs		"last rx auth failure reason" },
11961374Sdcs#define	S_RX_AUTH_COUNTERMEASURES	AFTER(S_RX_AUTH_FAIL_CODE)
120138223Sscottl	{ 5,  "rx_auth_countermeasures",	"auth_countermeasures",
12161374Sdcs		"rx sta auth failure 'cuz of TKIP countermeasures" },
12261374Sdcs#define	S_RX_ASSOC_BSS		AFTER(S_RX_AUTH_COUNTERMEASURES)
12361374Sdcs	{ 5,  "rx_assoc_bss",	"assoc_bss",	"rx assoc from wrong bssid" },
12461374Sdcs#define	S_RX_ASSOC_NOTAUTH	AFTER(S_RX_ASSOC_BSS)
12561374Sdcs	{ 5,  "rx_assoc_notauth","assoc_notauth",	"rx assoc w/o auth" },
12661374Sdcs#define	S_RX_ASSOC_CAPMISMATCH	AFTER(S_RX_ASSOC_NOTAUTH)
12761374Sdcs	{ 5,  "rx_assoc_capmismatch","assoc_capmismatch",
12861374Sdcs		"rx assoc w/ cap mismatch" },
12961374Sdcs#define	S_RX_ASSOC_NORATE	AFTER(S_RX_ASSOC_CAPMISMATCH)
13061374Sdcs	{ 5,  "rx_assoc_norate","assoc_norate",	"rx assoc w/ no rate match" },
13161374Sdcs#define	S_RX_ASSOC_BADWPAIE	AFTER(S_RX_ASSOC_NORATE)
13261374Sdcs	{ 5,  "rx_assoc_badwpaie","assoc_badwpaie",
13361374Sdcs		"rx assoc w/ bad WPA IE" },
13461374Sdcs#define	S_RX_DEAUTH		AFTER(S_RX_ASSOC_BADWPAIE)
135138223Sscottl	{ 5,  "rx_deauth",	"deauth",	"rx deauthentication" },
13661374Sdcs#define	S_RX_DEAUTH_CODE	AFTER(S_RX_DEAUTH)
13761374Sdcs	{ 5,  "rx_deauth_code","deauth_code",	"last rx deauth reason" },
13861374Sdcs#define	S_RX_DISASSOC		AFTER(S_RX_DEAUTH_CODE)
13961374Sdcs	{ 5,  "rx_disassoc",	"disassoc",	"rx disassociation" },
14061374Sdcs#define	S_RX_DISASSOC_CODE	AFTER(S_RX_DISASSOC)
14161374Sdcs	{ 5,  "rx_disassoc_code","disassoc_code",
14261374Sdcs		"last rx disassoc reason" },
143138223Sscottl#define	S_BMISS			AFTER(S_RX_DISASSOC_CODE)
144253862Smarcel	{ 5,  "bmiss",		"bmiss",	"beacon miss events handled" },
145138223Sscottl#define	S_RX_BADSUBTYPE		AFTER(S_BMISS)
146253862Smarcel	{ 5,  "rx_badsubtype",	"badsubtype",	"rx frame w/ unknown subtype" },
14761374Sdcs#define	S_RX_NOBUF		AFTER(S_RX_BADSUBTYPE)
14861374Sdcs	{ 5,  "rx_nobuf",	"nobuf",	"rx failed for lack of mbuf" },
14961374Sdcs#define	S_RX_DECRYPTCRC		AFTER(S_RX_NOBUF)
15061374Sdcs	{ 5,  "rx_decryptcrc",	"decryptcrc",	"rx decrypt failed on crc" },
15161374Sdcs#define	S_RX_AHDEMO_MGT		AFTER(S_RX_DECRYPTCRC)
15261374Sdcs	{ 5,  "rx_ahdemo_mgt",	"ahdemo_mgt",
15361374Sdcs		"rx discard mgmt frame received in ahdoc demo mode" },
15461374Sdcs#define	S_RX_BAD_AUTH		AFTER(S_RX_AHDEMO_MGT)
155138223Sscottl	{ 5,  "rx_bad_auth",	"bad_auth",	"rx bad authentication request" },
15661374Sdcs#define	S_RX_UNAUTH		AFTER(S_RX_BAD_AUTH)
15761374Sdcs	{ 5,  "rx_unauth",	"unauth",
15861374Sdcs		"rx discard 'cuz port unauthorized" },
15961374Sdcs#define	S_RX_BADKEYID		AFTER(S_RX_UNAUTH)
16061374Sdcs	{ 5,  "rx_badkeyid",	"rxkid",	"rx w/ incorrect keyid" },
16161374Sdcs#define	S_RX_CCMPREPLAY		AFTER(S_RX_BADKEYID)
16261374Sdcs	{ 5,  "rx_ccmpreplay",	"ccmpreplay",	"rx seq# violation (CCMP)" },
16361374Sdcs#define	S_RX_CCMPFORMAT		AFTER(S_RX_CCMPREPLAY)
16461374Sdcs	{ 5,  "rx_ccmpformat",	"ccmpformat",	"rx format bad (CCMP)" },
16561374Sdcs#define	S_RX_CCMPMIC		AFTER(S_RX_CCMPFORMAT)
16661374Sdcs	{ 5,  "rx_ccmpmic",	"ccmpmic",	"rx MIC check failed (CCMP)" },
16761374Sdcs#define	S_RX_TKIPREPLAY		AFTER(S_RX_CCMPMIC)
16861374Sdcs	{ 5,  "rx_tkipreplay",	"tkipreplay",	"rx seq# violation (TKIP)" },
169138223Sscottl#define	S_RX_TKIPFORMAT		AFTER(S_RX_TKIPREPLAY)
17061374Sdcs	{ 5,  "rx_tkipformat",	"tkipformat",	"rx format bad (TKIP)" },
17161374Sdcs#define	S_RX_TKIPMIC		AFTER(S_RX_TKIPFORMAT)
17261374Sdcs	{ 5,  "rx_tkipmic",	"tkipmic",	"rx MIC check failed (TKIP)" },
17361374Sdcs#define	S_RX_TKIPICV		AFTER(S_RX_TKIPMIC)
17461374Sdcs	{ 5,  "rx_tkipicv",	"tkipicv",	"rx ICV check failed (TKIP)" },
17561374Sdcs#define	S_RX_BADCIPHER		AFTER(S_RX_TKIPICV)
17661374Sdcs	{ 5,  "rx_badcipher",	"badcipher",	"rx failed 'cuz bad cipher/key type" },
17761374Sdcs#define	S_RX_NOCIPHERCTX	AFTER(S_RX_BADCIPHER)
178138223Sscottl	{ 5,  "rx_nocipherctx",	"nocipherctx",	"rx failed 'cuz key/cipher ctx not setup" },
179138223Sscottl#define	S_RX_ACL		AFTER(S_RX_NOCIPHERCTX)
180138223Sscottl	{ 5,  "rx_acl",		"acl",		"rx discard 'cuz acl policy" },
181138223Sscottl#define	S_TX_NOBUF		AFTER(S_RX_ACL)
18261374Sdcs	{ 5,  "tx_nobuf",	"nobuf",	"tx failed for lack of mbuf" },
18361374Sdcs#define	S_TX_NONODE		AFTER(S_TX_NOBUF)
18461374Sdcs	{ 5,  "tx_nonode",	"nonode",	"tx failed for no node" },
18561374Sdcs#define	S_TX_UNKNOWNMGT		AFTER(S_TX_NONODE)
18661374Sdcs	{ 5,  "tx_unknownmgt",	"unknownmgt",	"tx of unknown mgt frame" },
18761374Sdcs#define	S_TX_BADCIPHER		AFTER(S_TX_UNKNOWNMGT)
18861374Sdcs	{ 5,  "tx_badcipher",	"badcipher",	"tx failed 'cuz bad ciper/key type" },
18961374Sdcs#define	S_TX_NODEFKEY		AFTER(S_TX_BADCIPHER)
190138223Sscottl	{ 5,  "tx_nodefkey",	"nodefkey",	"tx failed 'cuz no defkey" },
19161374Sdcs#define	S_TX_NOHEADROOM		AFTER(S_TX_NODEFKEY)
19261374Sdcs	{ 5,  "tx_noheadroom",	"noheadroom",	"tx failed 'cuz no space for crypto hdrs" },
19361374Sdcs#define	S_TX_FRAGFRAMES		AFTER(S_TX_NOHEADROOM)
19461374Sdcs	{ 5,  "tx_fragframes",	"fragframes",	"tx frames fragmented" },
19561374Sdcs#define	S_TX_FRAGS		AFTER(S_TX_FRAGFRAMES)
19661374Sdcs	{ 5,  "tx_frags",	"frags",		"tx frags generated" },
19761374Sdcs#define	S_SCAN_ACTIVE		AFTER(S_TX_FRAGS)
19861374Sdcs	{ 5,  "scan_active",	"ascan",	"active scans started" },
199138223Sscottl#define	S_SCAN_PASSIVE		AFTER(S_SCAN_ACTIVE)
20061374Sdcs	{ 5,  "scan_passive",	"pscan",	"passive scans started" },
20161374Sdcs#define	S_SCAN_BG		AFTER(S_SCAN_PASSIVE)
20261374Sdcs	{ 5,  "scan_bg",	"bgscn",	"background scans started" },
20361374Sdcs#define	S_NODE_TIMEOUT		AFTER(S_SCAN_BG)
20461374Sdcs	{ 5,  "node_timeout",	"node_timeout",	"nodes timed out for inactivity" },
20561374Sdcs#define	S_CRYPTO_NOMEM		AFTER(S_NODE_TIMEOUT)
20661374Sdcs	{ 5,  "crypto_nomem",	"crypto_nomem",	"cipher context malloc failed" },
20761374Sdcs#define	S_CRYPTO_TKIP		AFTER(S_CRYPTO_NOMEM)
20861374Sdcs	{ 5,  "crypto_tkip",	"crypto_tkip",	"tkip crypto done in s/w" },
20961374Sdcs#define	S_CRYPTO_TKIPENMIC	AFTER(S_CRYPTO_TKIP)
21061374Sdcs	{ 5,  "crypto_tkipenmic","crypto_tkipenmic",	"tkip tx MIC done in s/w" },
21161374Sdcs#define	S_CRYPTO_TKIPDEMIC	AFTER(S_CRYPTO_TKIPENMIC)
21261374Sdcs	{ 5,  "crypto_tkipdemic","crypto_tkipdemic",	"tkip rx MIC done in s/w" },
21361374Sdcs#define	S_CRYPTO_TKIPCM		AFTER(S_CRYPTO_TKIPDEMIC)
21461374Sdcs	{ 5,  "crypto_tkipcm",	"crypto_tkipcm",	"tkip dropped frames 'cuz of countermeasures" },
21561374Sdcs#define	S_CRYPTO_CCMP		AFTER(S_CRYPTO_TKIPCM)
21661374Sdcs	{ 5,  "crypto_ccmp",	"crypto_ccmp",	"ccmp crypto done in s/w" },
21761374Sdcs#define	S_CRYPTO_WEP		AFTER(S_CRYPTO_CCMP)
21861374Sdcs	{ 5,  "crypto_wep",	"crypto_wep",	"wep crypto done in s/w" },
219138223Sscottl#define	S_CRYPTO_SETKEY_CIPHER	AFTER(S_CRYPTO_WEP)
22061374Sdcs	{ 5,  "crypto_setkey_cipher",	"crypto_setkey_cipher","setkey failed 'cuz cipher rejected data" },
221138223Sscottl#define	S_CRYPTO_SETKEY_NOKEY	AFTER(S_CRYPTO_SETKEY_CIPHER)
22261374Sdcs	{ 5,  "crypto_setkey_nokey",	"crypto_setkey_nokey","setkey failed 'cuz no key index" },
22361374Sdcs#define	S_CRYPTO_DELKEY		AFTER(S_CRYPTO_SETKEY_NOKEY)
22461374Sdcs	{ 5,  "crypto_delkey",	"crypto_delkey",	"driver key delete failed" },
22561374Sdcs#define	S_CRYPTO_BADCIPHER	AFTER(S_CRYPTO_DELKEY)
22661374Sdcs	{ 5,  "crypto_badcipher","crypto_badcipher",	"setkey failed 'cuz unknown cipher" },
22761374Sdcs#define	S_CRYPTO_NOCIPHER	AFTER(S_CRYPTO_BADCIPHER)
22861374Sdcs	{ 5,  "crypto_nocipher","crypto_nocipher",	"setkey failed 'cuz cipher module unavailable" },
22961374Sdcs#define	S_CRYPTO_ATTACHFAIL	AFTER(S_CRYPTO_NOCIPHER)
23061374Sdcs	{ 5,  "crypto_attachfail","crypto_attachfail",	"setkey failed 'cuz cipher attach failed" },
23161374Sdcs#define	S_CRYPTO_SWFALLBACK	AFTER(S_CRYPTO_ATTACHFAIL)
23261374Sdcs	{ 5,  "crypto_swfallback","crypto_swfallback",	"crypto fell back to s/w implementation" },
23361374Sdcs#define	S_CRYPTO_KEYFAIL	AFTER(S_CRYPTO_SWFALLBACK)
23461374Sdcs	{ 5,  "crypto_keyfail",	"crypto_keyfail",	"setkey failed 'cuz driver key alloc failed" },
23561374Sdcs#define	S_CRYPTO_ENMICFAIL	AFTER(S_CRYPTO_KEYFAIL)
23661374Sdcs	{ 5,  "crypto_enmicfail","crypto_enmicfail",	"enmic failed (may be mbuf exhaustion)" },
23761374Sdcs#define	S_IBSS_CAPMISMATCH	AFTER(S_CRYPTO_ENMICFAIL)
23861374Sdcs	{ 5,  "ibss_capmismatch","ibss_capmismatch",	"ibss merge faied 'cuz capabilities mismatch" },
23961374Sdcs#define	S_IBSS_NORATE		AFTER(S_IBSS_CAPMISMATCH)
24061374Sdcs	{ 5,  "ibss_norate",	"ibss_norate",	"ibss merge faied 'cuz rate set mismatch" },
241138223Sscottl#define	S_PS_UNASSOC		AFTER(S_IBSS_NORATE)
24261374Sdcs	{ 5,  "ps_unassoc",	"ps_unassoc",	"ps-poll received for unassociated station" },
243138223Sscottl#define	S_PS_BADAID		AFTER(S_PS_UNASSOC)
24461374Sdcs	{ 5,  "ps_badaid",	"ps_badaid",	"ps-poll received with invalid association id" },
24561374Sdcs#define	S_PS_QEMPTY		AFTER(S_PS_BADAID)
24661374Sdcs	{ 5,  "ps_qempty",	"ps_qempty",	"ps-poll received with nothing to send" },
24761374Sdcs#define	S_FF_BADHDR		AFTER(S_PS_QEMPTY)
24865617Sdcs	{ 5,  "ff_badhdr",	"ff_badhdr",	"fast frame rx'd w/ bad hdr" },
24965617Sdcs#define	S_FF_TOOSHORT		AFTER(S_FF_BADHDR)
25065617Sdcs	{ 5,  "ff_tooshort",	"ff_tooshort",	"fast frame rx decap error" },
251138223Sscottl#define	S_FF_SPLIT		AFTER(S_FF_TOOSHORT)
252253862Smarcel	{ 5,  "ff_split",	"ff_split",	"fast frame rx split error" },
253138223Sscottl#define	S_FF_DECAP		AFTER(S_FF_SPLIT)
254253862Smarcel	{ 5,  "ff_decap",	"ff_decap",	"fast frames decap'd" },
25565617Sdcs#define	S_FF_ENCAP		AFTER(S_FF_DECAP)
25665617Sdcs	{ 5,  "ff_encap",	"ff_encap",	"fast frames encap'd for tx" },
25765617Sdcs#define	S_FF_ENCAPFAIL		AFTER(S_FF_ENCAP)
25865617Sdcs	{ 5,  "ff_encapfail",	"ff_encapfail",	"fast frames encap failed" },
25965617Sdcs#define	S_RX_BADBINTVAL		AFTER(S_FF_ENCAPFAIL)
26065617Sdcs	{ 5,  "rx_badbintval",	"rx_badbintval","rx frame with bogus beacon interval" },
26165617Sdcs#define	S_RX_MGMT		AFTER(S_RX_BADBINTVAL)
26265617Sdcs	{ 8,  "rx_mgmt",	"mgmt",		"rx management frames" },
26365617Sdcs#define	S_RX_DEMICFAIL		AFTER(S_RX_MGMT)
26465617Sdcs	{ 5,  "rx_demicfail",	"rx_demicfail",	"rx demic failed" },
26565617Sdcs#define	S_RX_DEFRAG		AFTER(S_RX_DEMICFAIL)
266138223Sscottl	{ 5,  "rx_defrag",	"rx_defrag",	"rx defragmentation failed" },
26765617Sdcs#define	S_RX_ACTION		AFTER(S_RX_DEFRAG)
26865617Sdcs	{ 5,  "rx_action",	"rx_action",	"rx action frames" },
26965617Sdcs#define	S_AMSDU_TOOSHORT	AFTER(S_RX_ACTION)
27065617Sdcs	{ 8,  "amsdu_tooshort",	"tooshort","A-MSDU rx decap error" },
27165617Sdcs#define	S_AMSDU_SPLIT		AFTER(S_AMSDU_TOOSHORT)
27265617Sdcs	{ 8,  "amsdu_split",	"split",	"A-MSDU rx failed on frame split" },
27365617Sdcs#define	S_AMSDU_DECAP		AFTER(S_AMSDU_SPLIT)
27465617Sdcs	{ 8,  "amsdu_decap",	"decap",	"A-MSDU frames received" },
27565617Sdcs#define	S_AMSDU_ENCAP		AFTER(S_AMSDU_DECAP)
27665617Sdcs	{ 8,  "amsdu_encap",	"encap",	"A-MSDU frames transmitted" },
27765617Sdcs#define	S_AMPDU_REORDER		AFTER(S_AMSDU_ENCAP)
27865617Sdcs	{ 8,  "ampdu_reorder",	"reorder","A-MPDU frames held in reorder q" },
279138223Sscottl#define	S_AMPDU_FLUSH		AFTER(S_AMPDU_REORDER)
280138223Sscottl	{ 8,  "ampdu_flush",	"flush",	"A-MPDU frames sent up from reorder q" },
281138223Sscottl#define	S_AMPDU_BARBAD		AFTER(S_AMPDU_FLUSH)
28265617Sdcs	{ 6,  "ampdu_barbad",	"barbad",	"A-MPDU BAR rx before ADDBA exchange (or disabled with net.link.ieee80211)" },
28365617Sdcs#define	S_AMPDU_BAROOW		AFTER(S_AMPDU_BARBAD)
28465617Sdcs	{ 6,  "ampdu_baroow",	"baroow",	"A-MPDU BAR rx out of BA window" },
28565617Sdcs#define	S_AMPDU_BARMOVE		AFTER(S_AMPDU_BAROOW)
28665617Sdcs	{ 8,  "ampdu_barmove",	"barmove","A-MPDU BAR rx moved BA window" },
287138223Sscottl#define	S_AMPDU_BAR		AFTER(S_AMPDU_BARMOVE)
28865677Sdfr	{ 8,  "ampdu_bar",	"rxbar",	"A-MPDU BAR rx successful" },
28965677Sdfr#define	S_AMPDU_MOVE		AFTER(S_AMPDU_BAR)
29065617Sdcs	{ 5,  "ampdu_move",	"move",	"A-MPDU frame moved BA window" },
29165617Sdcs#define	S_AMPDU_OOR		AFTER(S_AMPDU_MOVE)
29265617Sdcs	{ 8,  "ampdu_oor",	"oorx",	"A-MPDU frames rx out-of-order" },
29365617Sdcs#define	S_AMPDU_COPY		AFTER(S_AMPDU_OOR)
29465617Sdcs	{ 8,  "ampdu_copy",	"copy",	"A-MPDU rx window slots copied" },
29565617Sdcs#define	S_AMPDU_DROP		AFTER(S_AMPDU_COPY)
29665617Sdcs	{ 5,  "ampdu_drop",	"drop",	"A-MPDU frames discarded for out of range seqno" },
29765617Sdcs#define	S_AMPDU_AGE		AFTER(S_AMPDU_DROP)
29865617Sdcs	{ 5,  "ampdu_age",	"age",	"A-MPDU frames sent up due to old age" },
29965617Sdcs#define	S_AMPDU_STOP		AFTER(S_AMPDU_AGE)
30065617Sdcs	{ 5,  "ampdu_stop",	"stop",	"A-MPDU streams stopped" },
30165617Sdcs#define	S_AMPDU_STOP_FAILED	AFTER(S_AMPDU_STOP)
30265617Sdcs	{ 5,  "ampdu_stop_failed","!stop",	"A-MPDU stop requests failed 'cuz stream not running" },
30365617Sdcs#define	S_ADDBA_REJECT		AFTER(S_AMPDU_STOP_FAILED)
30465617Sdcs	{ 5,  "addba_reject",	"reject",	"ADDBA requests rejected 'cuz A-MPDU rx is disabled" },
30565617Sdcs#define	S_ADDBA_NOREQUEST	AFTER(S_ADDBA_REJECT)
30665617Sdcs	{ 5,  "addba_norequest","norequest","ADDBA response frames discarded because no ADDBA request was pending" },
30765617Sdcs#define	S_ADDBA_BADTOKEN	AFTER(S_ADDBA_NOREQUEST)
30865617Sdcs	{ 5,  "addba_badtoken",	"badtoken","ADDBA response frames discarded 'cuz rx'd dialog token is wrong" },
30965617Sdcs#define	S_TX_BADSTATE		AFTER(S_ADDBA_BADTOKEN)
31065617Sdcs	{ 4,  "tx_badstate",	"badstate",	"tx failed 'cuz vap not in RUN state" },
31165617Sdcs#define	S_TX_NOTASSOC		AFTER(S_TX_BADSTATE)
31265617Sdcs	{ 4,  "tx_notassoc",	"notassoc",	"tx failed 'cuz dest sta not associated" },
31365617Sdcs#define	S_TX_CLASSIFY		AFTER(S_TX_NOTASSOC)
31465617Sdcs	{ 4,  "tx_classify",	"classify",	"tx packet classification failed" },
31565617Sdcs#define	S_DWDS_MCAST		AFTER(S_TX_CLASSIFY)
31665617Sdcs	{ 8,  "dwds_mcast",	"dwds_mcast",	"mcast frame transmitted on dwds vap discarded" },
31765617Sdcs#define	S_DWDS_QDROP		AFTER(S_DWDS_MCAST)
31865617Sdcs	{ 8,  "dwds_qdrop",	"dwds_qdrop",	"4-address frame discarded because dwds pending queue is full" },
31965617Sdcs#define	S_HT_ASSOC_NOHTCAP	AFTER(S_DWDS_QDROP)
32065677Sdfr	{ 4,  "ht_nohtcap",	"ht_nohtcap",	"non-HT station rejected in HT-only BSS" },
32165677Sdfr#define	S_HT_ASSOC_DOWNGRADE	AFTER(S_HT_ASSOC_NOHTCAP)
32276116Sdcs	{ 4,  "ht_downgrade",	"ht_downgrade",	"HT station downgraded to legacy operation" },
32376116Sdcs#define	S_HT_ASSOC_NORATE	AFTER(S_HT_ASSOC_DOWNGRADE)
32465617Sdcs	{ 4,  "ht_norate",	"ht_norate",	"HT station rejected because of HT rate set" },
32565617Sdcs#define	S_MESH_WRONGMESH	AFTER(S_HT_ASSOC_NORATE)
32665617Sdcs	{ 4,  "mesh_wrong",	"mesh_wrong",	"frame discarded because sender not a mesh sta" },
32765617Sdcs#define	S_MESH_NOLINK		AFTER(S_MESH_WRONGMESH)
32865617Sdcs	{ 4,  "mesh_nolink",	"mesh_nolink",	"frame discarded because link not established" },
32965617Sdcs#define	S_MESH_FWD_TTL		AFTER(S_MESH_NOLINK)
33065617Sdcs	{ 4,  "mesh_fwd_ttl",	"mesh_fwd_ttl",	"frame not forwarded because TTL zero" },
33165617Sdcs#define	S_MESH_FWD_NOBUF	AFTER(S_MESH_FWD_TTL)
33265617Sdcs	{ 4,  "mesh_fwd_nobuf",	"mesh_fwd_nobuf",	"frame not forwarded because mbuf could not be allocated" },
33365617Sdcs#define	S_MESH_FWD_TOOSHORT	AFTER(S_MESH_FWD_NOBUF)
33465617Sdcs	{ 4,  "mesh_fwd_tooshort",	"mesh_fwd_tooshort",	"frame not forwarded because too short to have 802.11 header" },
33565617Sdcs#define	S_MESH_FWD_DISABLED	AFTER(S_MESH_FWD_TOOSHORT)
33665617Sdcs	{ 4,  "mesh_fwd_disabled",	"mesh_fwd_disabled",	"frame not forwarded because administratively disabled" },
33765617Sdcs#define	S_MESH_FWD_NOPATH	AFTER(S_MESH_FWD_DISABLED)
33865617Sdcs	{ 4,  "mesh_fwd_nopath",	"mesh_fwd_nopath",	"frame not forwarded because no path found to destination" },
33965617Sdcs#define	S_HWMP_WRONGSEQ		AFTER(S_MESH_FWD_NOPATH)
34065617Sdcs	{ 4,  "hwmp_wrongseq",	"hwmp_wrongseq",	"frame discarded because mesh sequence number is invalid" },
34165617Sdcs#define	S_HWMP_ROOTREQS		AFTER(S_HWMP_WRONGSEQ)
34265617Sdcs	{ 4,  "hwmp_rootreqs",	"hwmp_rootreqs",	"root PREQ frames sent" },
34365617Sdcs#define	S_HWMP_ROOTANN		AFTER(S_HWMP_ROOTREQS)
34465617Sdcs	{ 4,  "hwmp_rootann",	"hwmp_rootann",	"root RANN frames received" },
34565617Sdcs#define	S_MESH_BADAE		AFTER(S_HWMP_ROOTANN)
34665617Sdcs	{ 4,  "mesh_badae",	"mesh_badae",	"frame discarded for bad AddressExtension (AE)" },
34765617Sdcs#define	S_MESH_RTADDFAILED	AFTER(S_MESH_BADAE)
34865617Sdcs	{ 4,  "mesh_rtadd",	"mesh_rtadd",	"mesh route add failed" },
34965617Sdcs#define	S_MESH_NOTPROXY		AFTER(S_MESH_RTADDFAILED)
35065617Sdcs	{ 8,  "mesh_notproxy",	"mesh_notproxy","frame discarded because station not acting as a proxy" },
35165617Sdcs#define	S_RX_BADALIGN		AFTER(S_MESH_NOTPROXY)
35265617Sdcs	{ 4,  "rx_badalign",	"rx_badalign","frame discarded because payload re-alignment failed" },
35376116Sdcs#define	S_INPUT			AFTER(S_RX_BADALIGN)
35476116Sdcs	{ 8,	"input",	"input",	"total data frames received" },
35576116Sdcs#define	S_RX_UCAST		AFTER(S_INPUT)
35676116Sdcs	{ 8,	"rx_ucast",	"rx_ucast",	"unicast data frames received" },
35776116Sdcs#define	S_RX_MCAST		AFTER(S_RX_UCAST)
35876116Sdcs	{ 8,	"rx_mcast",	"rx_mcast",	"multicast data frames received" },
35976116Sdcs#define	S_OUTPUT		AFTER(S_RX_MCAST)
36076116Sdcs	{ 8,	"output",	"output",	"total data frames transmit" },
36176116Sdcs#define	S_TX_UCAST		AFTER(S_OUTPUT)
36276116Sdcs	{ 8,	"tx_ucast",	"tx_ucast",	"unicast data frames sent" },
36376116Sdcs#define	S_TX_MCAST		AFTER(S_TX_UCAST)
36476116Sdcs	{ 8,	"tx_mcast",	"tx_mcast",	"multicast data frames sent" },
36576116Sdcs#define	S_RATE			AFTER(S_TX_MCAST)
36676116Sdcs	{ 5,	"rate",		"rate",		"current transmit rate" },
36776116Sdcs#define	S_RSSI			AFTER(S_RATE)
36876116Sdcs	{ 5,	"rssi",		"rssi",		"current rssi" },
36976116Sdcs#define	S_NOISE			AFTER(S_RSSI)
37076116Sdcs	{ 5,	"noise",	"noise",	"current noise floor (dBm)" },
37176116Sdcs#define	S_SIGNAL		AFTER(S_NOISE)
37276116Sdcs	{ 5,	"signal",	"sig",		"current signal (dBm)" },
37376116Sdcs#define	S_BEACON_BAD		AFTER(S_SIGNAL)
37476116Sdcs	{ 9,	"beacon_bad",	"beaconbad",	"bad beacons received" },
37576116Sdcs#define	S_AMPDU_BARTX		AFTER(S_BEACON_BAD)
37676116Sdcs	{ 5,	"ampdu_bartx",	"bartx",	"BAR frames sent" },
37776116Sdcs#define	S_AMPDU_BARTX_FAIL	AFTER(S_AMPDU_BARTX)
37876116Sdcs	{ 9,	"ampdu_bartxfail",	"bartx_fail",	"BAR frames failed to send" },
37976116Sdcs#define	S_AMPDU_BARTX_RETRY	AFTER(S_AMPDU_BARTX_FAIL)
38076116Sdcs	{ 10,	"ampdu_bartxretry",	"bartx_retry",	"BAR frames retried" },
38176116Sdcs};
38276116Sdcs
38376116Sdcsstruct wlanstatfoo_p {
38476116Sdcs	struct wlanstatfoo base;
38576116Sdcs	int s;
38676116Sdcs	int opmode;
38776116Sdcs	uint8_t mac[IEEE80211_ADDR_LEN];
38876116Sdcs	struct ifreq ifr;
38976116Sdcs	struct ieee80211_stats cur;
39076116Sdcs	struct ieee80211_stats total;
39176116Sdcs	struct ieee80211req ireq;
39276116Sdcs	union {
39376116Sdcs		struct ieee80211req_sta_req info;
39476116Sdcs		char buf[1024];
39576116Sdcs	} u_info;
39676116Sdcs	struct ieee80211req_sta_stats ncur;
39776116Sdcs	struct ieee80211req_sta_stats ntotal;
39876116Sdcs};
39976116Sdcs
40076116Sdcsstatic void
40176116Sdcswlan_setifname(struct wlanstatfoo *wf0, const char *ifname)
40276116Sdcs{
40376116Sdcs	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
40476116Sdcs
40576116Sdcs	strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name));
40676116Sdcs	strncpy(wf->ireq.i_name, ifname, sizeof (wf->ireq.i_name));
40776116Sdcs}
40876116Sdcs
40976116Sdcsstatic const char *
41076116Sdcswlan_getifname(struct wlanstatfoo *wf0)
41176116Sdcs{
41276116Sdcs	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
413253172Smarcel
414253172Smarcel	return wf->ifr.ifr_name;
415253172Smarcel}
416253172Smarcel
417253172Smarcelstatic int
418253172Smarcelwlan_getopmode(struct wlanstatfoo *wf0)
419253172Smarcel{
420253172Smarcel	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
421253172Smarcel
422253172Smarcel	if (wf->opmode == -1) {
423253172Smarcel		struct ifmediareq ifmr;
424253172Smarcel
425253172Smarcel		memset(&ifmr, 0, sizeof(ifmr));
426253172Smarcel		strlcpy(ifmr.ifm_name, wf->ifr.ifr_name, sizeof(ifmr.ifm_name));
427253172Smarcel		if (ioctl(wf->s, SIOCGIFMEDIA, &ifmr) < 0)
428253172Smarcel			err(1, "%s (SIOCGIFMEDIA)", wf->ifr.ifr_name);
429253172Smarcel		if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
430253172Smarcel			if (ifmr.ifm_current & IFM_FLAG0)
431253172Smarcel				wf->opmode = IEEE80211_M_AHDEMO;
432253172Smarcel			else
433253172Smarcel				wf->opmode = IEEE80211_M_IBSS;
434253172Smarcel		} else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
435253172Smarcel			wf->opmode = IEEE80211_M_HOSTAP;
436253172Smarcel		else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
437253172Smarcel			wf->opmode = IEEE80211_M_MONITOR;
438253172Smarcel		else
439253172Smarcel			wf->opmode = IEEE80211_M_STA;
440253172Smarcel	}
44176116Sdcs	return wf->opmode;
44276116Sdcs}
44387636Sjhb
44476116Sdcsstatic void
44576116Sdcsgetlladdr(struct wlanstatfoo_p *wf)
44676116Sdcs{
44787636Sjhb	const struct sockaddr_dl *sdl;
44887636Sjhb	struct ifaddrs *ifp, *p;
44976116Sdcs
45076116Sdcs	if (getifaddrs(&ifp) != 0)
45187636Sjhb		err(1, "getifaddrs");
45276116Sdcs	for (p = ifp; p != NULL; p = p->ifa_next)
45387636Sjhb		if (strcmp(p->ifa_name, wf->ifr.ifr_name) == 0 &&
45487636Sjhb		    p->ifa_addr->sa_family == AF_LINK)
45587636Sjhb			break;
45687636Sjhb	if (p == NULL)
45787636Sjhb		errx(1, "did not find link layer address for interface %s",
45887636Sjhb			wf->ifr.ifr_name);
45987636Sjhb	sdl = (const struct sockaddr_dl *) p->ifa_addr;
46087636Sjhb	IEEE80211_ADDR_COPY(wf->mac, LLADDR(sdl));
46187636Sjhb	freeifaddrs(ifp);
46287636Sjhb}
46387636Sjhb
46487636Sjhbstatic int
46587636Sjhbgetbssid(struct wlanstatfoo_p *wf)
46687636Sjhb{
46787636Sjhb	wf->ireq.i_type = IEEE80211_IOC_BSSID;
46887636Sjhb	wf->ireq.i_data = wf->mac;
46987636Sjhb	wf->ireq.i_len = IEEE80211_ADDR_LEN;
47087636Sjhb	return ioctl(wf->s, SIOCG80211, &wf->ireq);
47176116Sdcs}
47276116Sdcs
47387636Sjhbstatic void
47476116Sdcswlan_setstamac(struct wlanstatfoo *wf0, const uint8_t *mac)
47576116Sdcs{
47676116Sdcs	static const uint8_t zeromac[IEEE80211_ADDR_LEN];
47776116Sdcs	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
47876116Sdcs
47976116Sdcs	if (mac == NULL) {
48076116Sdcs		switch (wlan_getopmode(wf0)) {
48176116Sdcs		case IEEE80211_M_HOSTAP:
48276116Sdcs		case IEEE80211_M_MONITOR:
48376116Sdcs			getlladdr(wf);
48476116Sdcs			break;
48576116Sdcs		case IEEE80211_M_IBSS:
48676116Sdcs		case IEEE80211_M_AHDEMO:
48776116Sdcs			/*
48876116Sdcs			 * NB: this may not work in which case the
48976116Sdcs			 * mac must be specified on the command line
49076116Sdcs			 */
49176116Sdcs			if (getbssid(wf) < 0 ||
49276116Sdcs			    IEEE80211_ADDR_EQ(wf->mac, zeromac))
49376116Sdcs				getlladdr(wf);
49476116Sdcs			break;
49576116Sdcs		case IEEE80211_M_STA:
49676116Sdcs			if (getbssid(wf) < 0)
49776116Sdcs				err(1, "%s (IEEE80211_IOC_BSSID)",
49876116Sdcs				    wf->ireq.i_name);
49976116Sdcs			break;
50076116Sdcs		}
50176116Sdcs	} else
50276116Sdcs		IEEE80211_ADDR_COPY(wf->mac, mac);
50376116Sdcs}
50476116Sdcs
50576116Sdcs/* XXX only fetch what's needed to do reports */
50676116Sdcsstatic void
50776116Sdcswlan_collect(struct wlanstatfoo_p *wf,
50876116Sdcs	struct ieee80211_stats *stats, struct ieee80211req_sta_stats *nstats)
50976116Sdcs{
51076116Sdcs
51176116Sdcs	IEEE80211_ADDR_COPY(wf->u_info.info.is_u.macaddr, wf->mac);
51276116Sdcs	wf->ireq.i_type = IEEE80211_IOC_STA_INFO;
51376116Sdcs	wf->ireq.i_data = (caddr_t) &wf->u_info;
514253172Smarcel	wf->ireq.i_len = sizeof(wf->u_info);
515253172Smarcel	if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0) {
516253172Smarcel		warn("%s:%s (IEEE80211_IOC_STA_INFO)", wf->ireq.i_name,
517253172Smarcel		    ether_ntoa((const struct ether_addr*) wf->mac));
518253172Smarcel	}
519253172Smarcel
520253862Smarcel	IEEE80211_ADDR_COPY(nstats->is_u.macaddr, wf->mac);
521254155Smarcel	wf->ireq.i_type = IEEE80211_IOC_STA_STATS;
522254155Smarcel	wf->ireq.i_data = (caddr_t) nstats;
523254155Smarcel	wf->ireq.i_len = sizeof(*nstats);
524254155Smarcel	if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0)
525254155Smarcel		warn("%s:%s (IEEE80211_IOC_STA_STATS)", wf->ireq.i_name,
526254155Smarcel		    ether_ntoa((const struct ether_addr*) wf->mac));
527253862Smarcel
528253172Smarcel	wf->ifr.ifr_data = (caddr_t) stats;
529253172Smarcel	if (ioctl(wf->s, SIOCG80211STATS, &wf->ifr) < 0)
530253172Smarcel		err(1, "%s (SIOCG80211STATS)", wf->ifr.ifr_name);
531253172Smarcel}
532253172Smarcel
533253172Smarcelstatic void
534253172Smarcelwlan_collect_cur(struct statfoo *sf)
535253172Smarcel{
536253862Smarcel	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
537253862Smarcel
538253862Smarcel	wlan_collect(wf, &wf->cur, &wf->ncur);
539253862Smarcel}
540253862Smarcel
541253862Smarcelstatic void
542254155Smarcelwlan_collect_tot(struct statfoo *sf)
543254155Smarcel{
544254155Smarcel	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
545254155Smarcel
546254155Smarcel	wlan_collect(wf, &wf->total, &wf->ntotal);
547254155Smarcel}
548254155Smarcel
549254155Smarcelstatic void
550254155Smarcelwlan_update_tot(struct statfoo *sf)
551254155Smarcel{
552254155Smarcel	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
553254155Smarcel
554254155Smarcel	wf->total = wf->cur;
555254155Smarcel	wf->ntotal = wf->ncur;
556254155Smarcel}
557254155Smarcel
558254155Smarcelvoid
559254155Smarcelsetreason(char b[], size_t bs, int v)
560254155Smarcel{
561254155Smarcel#define	N(a)	(sizeof(a)/sizeof(a[0]))
562254155Smarcel    static const char *reasons[] = {
563254155Smarcel	[IEEE80211_REASON_UNSPECIFIED]		= "unspecified",
564254155Smarcel	[IEEE80211_REASON_AUTH_EXPIRE]		= "auth expire",
565254155Smarcel	[IEEE80211_REASON_AUTH_LEAVE]		= "auth leave",
566254155Smarcel	[IEEE80211_REASON_ASSOC_EXPIRE]		= "assoc expire",
567254155Smarcel	[IEEE80211_REASON_ASSOC_TOOMANY]	= "assoc toomany",
568254155Smarcel	[IEEE80211_REASON_NOT_AUTHED]		= "not authed",
569254155Smarcel	[IEEE80211_REASON_NOT_ASSOCED]		= "not assoced",
570254155Smarcel	[IEEE80211_REASON_ASSOC_LEAVE]		= "assoc leave",
571254155Smarcel	[IEEE80211_REASON_ASSOC_NOT_AUTHED]	= "assoc not authed",
572254155Smarcel	[IEEE80211_REASON_DISASSOC_PWRCAP_BAD]	= "disassoc pwrcap bad",
573254155Smarcel	[IEEE80211_REASON_DISASSOC_SUPCHAN_BAD]	= "disassoc supchan bad",
574254155Smarcel	[IEEE80211_REASON_IE_INVALID]		= "ie invalid",
575253862Smarcel	[IEEE80211_REASON_MIC_FAILURE]		= "mic failure",
576253172Smarcel	[IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT]= "4-way handshake timeout",
577253862Smarcel	[IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT] = "group key update timeout",
578253172Smarcel	[IEEE80211_REASON_IE_IN_4WAY_DIFFERS]	= "ie in 4-way differs",
579253172Smarcel	[IEEE80211_REASON_GROUP_CIPHER_INVALID]	= "group cipher invalid",
580253172Smarcel	[IEEE80211_REASON_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid",
581253172Smarcel	[IEEE80211_REASON_AKMP_INVALID]		= "akmp invalid",
582253172Smarcel	[IEEE80211_REASON_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version",
583253172Smarcel	[IEEE80211_REASON_INVALID_RSN_IE_CAP]	= "invalid rsn ie cap",
584253172Smarcel	[IEEE80211_REASON_802_1X_AUTH_FAILED]	= "802.1x auth failed",
585253172Smarcel	[IEEE80211_REASON_CIPHER_SUITE_REJECTED]= "cipher suite rejected",
586253172Smarcel    };
58776116Sdcs    if (v < N(reasons) && reasons[v] != NULL)
58876116Sdcs	    snprintf(b, bs, "%s (%u)", reasons[v], v);
58976116Sdcs    else
59076116Sdcs	    snprintf(b, bs, "%u", v);
59176116Sdcs#undef N
59276116Sdcs}
59376116Sdcs
59476116Sdcsvoid
59576116Sdcssetstatus(char b[], size_t bs, int v)
59676116Sdcs{
59776116Sdcs#define	N(a)	(sizeof(a)/sizeof(a[0]))
59876116Sdcs    static const char *status[] = {
59976116Sdcs	[IEEE80211_STATUS_SUCCESS]		= "success",
60076116Sdcs	[IEEE80211_STATUS_UNSPECIFIED]		= "unspecified",
60176116Sdcs	[IEEE80211_STATUS_CAPINFO]		= "capinfo",
60276116Sdcs	[IEEE80211_STATUS_NOT_ASSOCED]		= "not assoced",
60376116Sdcs	[IEEE80211_STATUS_OTHER]		= "other",
60487636Sjhb	[IEEE80211_STATUS_ALG]			= "algorithm",
60587636Sjhb	[IEEE80211_STATUS_SEQUENCE]		= "sequence",
60687636Sjhb	[IEEE80211_STATUS_CHALLENGE]		= "challenge",
60787636Sjhb	[IEEE80211_STATUS_TIMEOUT]		= "timeout",
60887636Sjhb	[IEEE80211_STATUS_TOOMANY]		= "toomany",
60987636Sjhb	[IEEE80211_STATUS_BASIC_RATE]		= "basic rate",
61087636Sjhb	[IEEE80211_STATUS_SP_REQUIRED]		= "sp required",
61187636Sjhb	[IEEE80211_STATUS_PBCC_REQUIRED]	= "pbcc required",
61287636Sjhb	[IEEE80211_STATUS_CA_REQUIRED]		= "ca required",
61387636Sjhb	[IEEE80211_STATUS_SPECMGMT_REQUIRED]	= "specmgmt required",
61487636Sjhb	[IEEE80211_STATUS_PWRCAP_REQUIRED]	= "pwrcap required",
61587636Sjhb	[IEEE80211_STATUS_SUPCHAN_REQUIRED]	= "supchan required",
61687636Sjhb	[IEEE80211_STATUS_SHORTSLOT_REQUIRED]	= "shortslot required",
61787636Sjhb	[IEEE80211_STATUS_DSSSOFDM_REQUIRED]	= "dsssofdm required",
61887636Sjhb	[IEEE80211_STATUS_INVALID_IE]		= "invalid ie",
61987636Sjhb	[IEEE80211_STATUS_GROUP_CIPHER_INVALID]	= "group cipher invalid",
62087636Sjhb	[IEEE80211_STATUS_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid",
62187636Sjhb	[IEEE80211_STATUS_AKMP_INVALID]		= "akmp invalid",
62287636Sjhb	[IEEE80211_STATUS_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version",
62387636Sjhb	[IEEE80211_STATUS_INVALID_RSN_IE_CAP]	= "invalid rsn ie cap",
62487636Sjhb	[IEEE80211_STATUS_CIPHER_SUITE_REJECTED]= "cipher suite rejected",
62587636Sjhb    };
62687636Sjhb    if (v < N(status) && status[v] != NULL)
62787636Sjhb	    snprintf(b, bs, "%s (%u)", status[v], v);
62887636Sjhb    else
62987636Sjhb	    snprintf(b, bs, "%u", v);
63087636Sjhb#undef N
63187636Sjhb}
63287636Sjhb
63387636Sjhbstatic int
63487636Sjhbwlan_getinfo(struct wlanstatfoo_p *wf, int s, char b[], size_t bs)
63587636Sjhb{
63687636Sjhb	const struct ieee80211req_sta_info *si = &wf->u_info.info.info[0];
63787636Sjhb
63887636Sjhb	switch (s) {
63987636Sjhb	case S_RATE:
64087636Sjhb		snprintf(b, bs, "%uM", si->isi_txmbps/2);
64187636Sjhb		return 1;
64287636Sjhb	case S_RSSI:
64387636Sjhb		snprintf(b, bs, "%d", si->isi_rssi);
64476116Sdcs		return 1;
64576116Sdcs	case S_NOISE:
64676116Sdcs		snprintf(b, bs, "%d", si->isi_noise);
64776116Sdcs		return 1;
64876116Sdcs	case S_SIGNAL:
64976116Sdcs		snprintf(b, bs, "%d", si->isi_rssi + si->isi_noise);
65076116Sdcs		return 1;
65176116Sdcs	case S_RX_AUTH_FAIL_CODE:
65276116Sdcs		if (wf->cur.is_rx_authfail_code == 0)
65376116Sdcs			break;
65476116Sdcs		setstatus(b, bs, wf->cur.is_rx_authfail_code);
65576116Sdcs		return 1;
65676116Sdcs	case S_RX_DEAUTH_CODE:
65776116Sdcs		if (wf->cur.is_rx_deauth_code == 0)
65876116Sdcs			break;
65976116Sdcs		setreason(b, bs, wf->cur.is_rx_deauth_code);
66076116Sdcs		return 1;
66176116Sdcs	case S_RX_DISASSOC_CODE:
66276116Sdcs		if (wf->cur.is_rx_disassoc_code == 0)
66376116Sdcs			break;
66476116Sdcs		setreason(b, bs, wf->cur.is_rx_disassoc_code);
66576116Sdcs		return 1;
66676116Sdcs	}
66776116Sdcs	b[0] = '\0';
66876116Sdcs	return 0;
66976116Sdcs}
67076116Sdcs
67176116Sdcsstatic int
67276116Sdcswlan_get_curstat(struct statfoo *sf, int s, char b[], size_t bs)
67376116Sdcs{
67476116Sdcs	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
67576116Sdcs#define	STAT(x) \
67676116Sdcs	snprintf(b, bs, "%u", wf->cur.is_##x - wf->total.is_##x); return 1
67776116Sdcs#define	NSTAT(x) \
67876116Sdcs	snprintf(b, bs, "%u", \
67976116Sdcs	    wf->ncur.is_stats.ns_##x - wf->ntotal.is_stats.ns_##x); \
68076116Sdcs	    return 1
68176116Sdcs
68276116Sdcs	switch (s) {
68376116Sdcs	case S_RX_BADVERSION:	STAT(rx_badversion);
68476116Sdcs	case S_RX_TOOSHORT:	STAT(rx_tooshort);
68576116Sdcs	case S_RX_WRONGBSS:	STAT(rx_wrongbss);
68676116Sdcs	case S_RX_DUP:		STAT(rx_dup);
68776116Sdcs	case S_RX_WRONGDIR:	STAT(rx_wrongdir);
68876116Sdcs	case S_RX_MCASTECHO:	STAT(rx_mcastecho);
68976116Sdcs	case S_RX_NOTASSOC:	STAT(rx_notassoc);
69076116Sdcs	case S_RX_NOPRIVACY:	STAT(rx_noprivacy);
69176116Sdcs	case S_RX_UNENCRYPTED:	STAT(rx_unencrypted);
69276116Sdcs	case S_RX_WEPFAIL:	STAT(rx_wepfail);
69376116Sdcs	case S_RX_DECAP:	STAT(rx_decap);
69476116Sdcs	case S_RX_MGTDISCARD:	STAT(rx_mgtdiscard);
69576116Sdcs	case S_RX_CTL:		STAT(rx_ctl);
69676116Sdcs	case S_RX_BEACON:	STAT(rx_beacon);
69776116Sdcs	case S_RX_RSTOOBIG:	STAT(rx_rstoobig);
69876116Sdcs	case S_RX_ELEM_MISSING:	STAT(rx_elem_missing);
69976116Sdcs	case S_RX_ELEM_TOOBIG:	STAT(rx_elem_toobig);
70076116Sdcs	case S_RX_ELEM_TOOSMALL:	STAT(rx_elem_toosmall);
70176116Sdcs	case S_RX_ELEM_UNKNOWN:	STAT(rx_elem_unknown);
70276116Sdcs	case S_RX_BADCHAN:	STAT(rx_badchan);
70376116Sdcs	case S_RX_CHANMISMATCH:	STAT(rx_chanmismatch);
70476116Sdcs	case S_RX_NODEALLOC:	STAT(rx_nodealloc);
70576116Sdcs	case S_RX_SSIDMISMATCH:	STAT(rx_ssidmismatch);
70676116Sdcs	case S_RX_AUTH_UNSUPPORTED:	STAT(rx_auth_unsupported);
70776116Sdcs	case S_RX_AUTH_FAIL:	STAT(rx_auth_fail);
70876116Sdcs	case S_RX_AUTH_COUNTERMEASURES:	STAT(rx_auth_countermeasures);
70976116Sdcs	case S_RX_ASSOC_BSS:	STAT(rx_assoc_bss);
71076116Sdcs	case S_RX_ASSOC_NOTAUTH:	STAT(rx_assoc_notauth);
71176116Sdcs	case S_RX_ASSOC_CAPMISMATCH:	STAT(rx_assoc_capmismatch);
71276116Sdcs	case S_RX_ASSOC_NORATE:	STAT(rx_assoc_norate);
71376116Sdcs	case S_RX_ASSOC_BADWPAIE:	STAT(rx_assoc_badwpaie);
71476116Sdcs	case S_RX_DEAUTH:	STAT(rx_deauth);
71576116Sdcs	case S_RX_DISASSOC:	STAT(rx_disassoc);
71676116Sdcs	case S_BMISS:		STAT(beacon_miss);
71776116Sdcs	case S_RX_BADSUBTYPE:	STAT(rx_badsubtype);
71876116Sdcs	case S_RX_NOBUF:	STAT(rx_nobuf);
71976116Sdcs	case S_RX_DECRYPTCRC:	STAT(rx_decryptcrc);
72076116Sdcs	case S_RX_AHDEMO_MGT:	STAT(rx_ahdemo_mgt);
72176116Sdcs	case S_RX_BAD_AUTH:	STAT(rx_bad_auth);
72276116Sdcs	case S_RX_UNAUTH:	STAT(rx_unauth);
72376116Sdcs	case S_RX_BADKEYID:	STAT(rx_badkeyid);
72476116Sdcs	case S_RX_CCMPREPLAY:	STAT(rx_ccmpreplay);
72576116Sdcs	case S_RX_CCMPFORMAT:	STAT(rx_ccmpformat);
72676116Sdcs	case S_RX_CCMPMIC:	STAT(rx_ccmpmic);
72776116Sdcs	case S_RX_TKIPREPLAY:	STAT(rx_tkipreplay);
72876116Sdcs	case S_RX_TKIPFORMAT:	STAT(rx_tkipformat);
72976116Sdcs	case S_RX_TKIPMIC:	STAT(rx_tkipmic);
73076116Sdcs	case S_RX_TKIPICV:	STAT(rx_tkipicv);
73176116Sdcs	case S_RX_BADCIPHER:	STAT(rx_badcipher);
73276116Sdcs	case S_RX_NOCIPHERCTX:	STAT(rx_nocipherctx);
73376116Sdcs	case S_RX_ACL:		STAT(rx_acl);
73476116Sdcs	case S_TX_NOBUF:	STAT(tx_nobuf);
73576116Sdcs	case S_TX_NONODE:	STAT(tx_nonode);
73694290Sdcs	case S_TX_UNKNOWNMGT:	STAT(tx_unknownmgt);
73776116Sdcs	case S_TX_BADCIPHER:	STAT(tx_badcipher);
73876116Sdcs	case S_TX_NODEFKEY:	STAT(tx_nodefkey);
73976116Sdcs	case S_TX_NOHEADROOM:	STAT(tx_noheadroom);
74076116Sdcs	case S_TX_FRAGFRAMES:	STAT(tx_fragframes);
74176116Sdcs	case S_TX_FRAGS:	STAT(tx_frags);
74276116Sdcs	case S_SCAN_ACTIVE:	STAT(scan_active);
74376116Sdcs	case S_SCAN_PASSIVE:	STAT(scan_passive);
74476116Sdcs	case S_SCAN_BG:		STAT(scan_bg);
74576116Sdcs	case S_NODE_TIMEOUT:	STAT(node_timeout);
74676116Sdcs	case S_CRYPTO_NOMEM:	STAT(crypto_nomem);
74776116Sdcs	case S_CRYPTO_TKIP:	STAT(crypto_tkip);
74876116Sdcs	case S_CRYPTO_TKIPENMIC:	STAT(crypto_tkipenmic);
74976116Sdcs	case S_CRYPTO_TKIPDEMIC:	STAT(crypto_tkipdemic);
75076116Sdcs	case S_CRYPTO_TKIPCM:	STAT(crypto_tkipcm);
75176116Sdcs	case S_CRYPTO_CCMP:	STAT(crypto_ccmp);
75276116Sdcs	case S_CRYPTO_WEP:	STAT(crypto_wep);
75376116Sdcs	case S_CRYPTO_SETKEY_CIPHER:	STAT(crypto_setkey_cipher);
75476116Sdcs	case S_CRYPTO_SETKEY_NOKEY:	STAT(crypto_setkey_nokey);
75576116Sdcs	case S_CRYPTO_DELKEY:	STAT(crypto_delkey);
75676116Sdcs	case S_CRYPTO_BADCIPHER:	STAT(crypto_badcipher);
75776116Sdcs	case S_CRYPTO_NOCIPHER:	STAT(crypto_nocipher);
75876116Sdcs	case S_CRYPTO_ATTACHFAIL:	STAT(crypto_attachfail);
75976116Sdcs	case S_CRYPTO_SWFALLBACK:	STAT(crypto_swfallback);
76076116Sdcs	case S_CRYPTO_KEYFAIL:	STAT(crypto_keyfail);
76176116Sdcs	case S_CRYPTO_ENMICFAIL:	STAT(crypto_enmicfail);
76276116Sdcs	case S_IBSS_CAPMISMATCH:	STAT(ibss_capmismatch);
763253172Smarcel	case S_IBSS_NORATE:	STAT(ibss_norate);
76476116Sdcs	case S_PS_UNASSOC:	STAT(ps_unassoc);
76576116Sdcs	case S_PS_BADAID:	STAT(ps_badaid);
76676116Sdcs	case S_PS_QEMPTY:	STAT(ps_qempty);
767253172Smarcel	case S_FF_BADHDR:	STAT(ff_badhdr);
76876116Sdcs	case S_FF_TOOSHORT:	STAT(ff_tooshort);
76976116Sdcs	case S_FF_SPLIT:	STAT(ff_split);
77087636Sjhb	case S_FF_DECAP:	STAT(ff_decap);
77187636Sjhb	case S_FF_ENCAP:	STAT(ff_encap);
77276116Sdcs	case S_RX_BADBINTVAL:	STAT(rx_badbintval);
77376116Sdcs	case S_RX_MGMT:		STAT(rx_mgmt);
77476116Sdcs	case S_RX_DEMICFAIL:	STAT(rx_demicfail);
77576116Sdcs	case S_RX_DEFRAG:	STAT(rx_defrag);
77676116Sdcs	case S_RX_ACTION:	STAT(rx_action);
77776116Sdcs	case S_AMSDU_TOOSHORT:	STAT(amsdu_tooshort);
77876116Sdcs	case S_AMSDU_SPLIT:	STAT(amsdu_split);
77976116Sdcs	case S_AMSDU_DECAP:	STAT(amsdu_decap);
78076116Sdcs	case S_AMSDU_ENCAP:	STAT(amsdu_encap);
78176116Sdcs	case S_AMPDU_REORDER:	STAT(ampdu_rx_reorder);
78276116Sdcs	case S_AMPDU_FLUSH:	STAT(ampdu_rx_flush);
78376116Sdcs	case S_AMPDU_BARBAD:	STAT(ampdu_bar_bad);
78476116Sdcs	case S_AMPDU_BAROOW:	STAT(ampdu_bar_oow);
78576116Sdcs	case S_AMPDU_BARMOVE:	STAT(ampdu_bar_move);
78676116Sdcs	case S_AMPDU_BAR:	STAT(ampdu_bar_rx);
787138223Sscottl	case S_AMPDU_MOVE:	STAT(ampdu_rx_move);
788138223Sscottl	case S_AMPDU_OOR:	STAT(ampdu_rx_oor);
789138223Sscottl	case S_AMPDU_COPY:	STAT(ampdu_rx_copy);
790138223Sscottl	case S_AMPDU_DROP:	STAT(ampdu_rx_drop);
791138223Sscottl	case S_AMPDU_AGE:	STAT(ampdu_rx_age);
792138223Sscottl	case S_AMPDU_STOP:	STAT(ampdu_stop);
79376116Sdcs	case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
79476116Sdcs	case S_ADDBA_REJECT:	STAT(addba_reject);
79576116Sdcs	case S_ADDBA_NOREQUEST:	STAT(addba_norequest);
79676116Sdcs	case S_ADDBA_BADTOKEN:	STAT(addba_badtoken);
79776116Sdcs	case S_TX_BADSTATE:	STAT(tx_badstate);
79876116Sdcs	case S_TX_NOTASSOC:	STAT(tx_notassoc);
799116000Snyan	case S_TX_CLASSIFY:	STAT(tx_classify);
800116000Snyan	case S_DWDS_MCAST:	STAT(dwds_mcast);
801116000Snyan	case S_DWDS_QDROP:	STAT(dwds_qdrop);
80294290Sdcs	case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
80394290Sdcs	case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
804123373Sgrehan	case S_HT_ASSOC_NORATE:	STAT(ht_assoc_norate);
80582941Sdfr	case S_MESH_WRONGMESH:	STAT(mesh_wrongmesh);
80694290Sdcs	case S_MESH_NOLINK:	STAT(mesh_nolink);
80794290Sdcs	case S_MESH_FWD_TTL:	STAT(mesh_fwd_ttl);
808123373Sgrehan	case S_MESH_FWD_NOBUF:	STAT(mesh_fwd_nobuf);
809123373Sgrehan	case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort);
810123373Sgrehan	case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled);
811123373Sgrehan	case S_MESH_FWD_NOPATH:	STAT(mesh_fwd_nopath);
812123373Sgrehan	case S_HWMP_WRONGSEQ:	STAT(hwmp_wrongseq);
81376116Sdcs	case S_HWMP_ROOTREQS:	STAT(hwmp_rootreqs);
81476116Sdcs	case S_HWMP_ROOTANN:	STAT(hwmp_rootrann);
81576116Sdcs	case S_MESH_BADAE:	STAT(mesh_badae);
81676116Sdcs	case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed);
81776116Sdcs	case S_MESH_NOTPROXY:	STAT(mesh_notproxy);
818	case S_RX_BADALIGN:	STAT(rx_badalign);
819	case S_INPUT:		NSTAT(rx_data);
820	case S_OUTPUT:		NSTAT(tx_data);
821	case S_RX_UCAST:	NSTAT(rx_ucast);
822	case S_RX_MCAST:	NSTAT(rx_mcast);
823	case S_TX_UCAST:	NSTAT(tx_ucast);
824	case S_TX_MCAST:	NSTAT(tx_mcast);
825	case S_BEACON_BAD:	STAT(beacon_bad);
826	case S_AMPDU_BARTX:	STAT(ampdu_bar_tx);
827	case S_AMPDU_BARTX_RETRY:	STAT(ampdu_bar_tx_retry);
828	case S_AMPDU_BARTX_FAIL:	STAT(ampdu_bar_tx_fail);
829	}
830	return wlan_getinfo(wf, s, b, bs);
831#undef NSTAT
832#undef STAT
833}
834
835static int
836wlan_get_totstat(struct statfoo *sf, int s, char b[], size_t bs)
837{
838	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
839#define	STAT(x) \
840	snprintf(b, bs, "%u", wf->total.is_##x); return 1
841#define	NSTAT(x) \
842	snprintf(b, bs, "%u", wf->ntotal.is_stats.ns_##x); return 1
843
844	switch (s) {
845	case S_RX_BADVERSION:	STAT(rx_badversion);
846	case S_RX_TOOSHORT:	STAT(rx_tooshort);
847	case S_RX_WRONGBSS:	STAT(rx_wrongbss);
848	case S_RX_DUP:	STAT(rx_dup);
849	case S_RX_WRONGDIR:	STAT(rx_wrongdir);
850	case S_RX_MCASTECHO:	STAT(rx_mcastecho);
851	case S_RX_NOTASSOC:	STAT(rx_notassoc);
852	case S_RX_NOPRIVACY:	STAT(rx_noprivacy);
853	case S_RX_UNENCRYPTED:	STAT(rx_unencrypted);
854	case S_RX_WEPFAIL:	STAT(rx_wepfail);
855	case S_RX_DECAP:	STAT(rx_decap);
856	case S_RX_MGTDISCARD:	STAT(rx_mgtdiscard);
857	case S_RX_CTL:		STAT(rx_ctl);
858	case S_RX_BEACON:	STAT(rx_beacon);
859	case S_RX_RSTOOBIG:	STAT(rx_rstoobig);
860	case S_RX_ELEM_MISSING:	STAT(rx_elem_missing);
861	case S_RX_ELEM_TOOBIG:	STAT(rx_elem_toobig);
862	case S_RX_ELEM_TOOSMALL:	STAT(rx_elem_toosmall);
863	case S_RX_ELEM_UNKNOWN:	STAT(rx_elem_unknown);
864	case S_RX_BADCHAN:	STAT(rx_badchan);
865	case S_RX_CHANMISMATCH:	STAT(rx_chanmismatch);
866	case S_RX_NODEALLOC:	STAT(rx_nodealloc);
867	case S_RX_SSIDMISMATCH:	STAT(rx_ssidmismatch);
868	case S_RX_AUTH_UNSUPPORTED:	STAT(rx_auth_unsupported);
869	case S_RX_AUTH_FAIL:	STAT(rx_auth_fail);
870	case S_RX_AUTH_COUNTERMEASURES:	STAT(rx_auth_countermeasures);
871	case S_RX_ASSOC_BSS:	STAT(rx_assoc_bss);
872	case S_RX_ASSOC_NOTAUTH:	STAT(rx_assoc_notauth);
873	case S_RX_ASSOC_CAPMISMATCH:	STAT(rx_assoc_capmismatch);
874	case S_RX_ASSOC_NORATE:	STAT(rx_assoc_norate);
875	case S_RX_ASSOC_BADWPAIE:	STAT(rx_assoc_badwpaie);
876	case S_RX_DEAUTH:	STAT(rx_deauth);
877	case S_RX_DISASSOC:	STAT(rx_disassoc);
878	case S_BMISS:		STAT(beacon_miss);
879	case S_RX_BADSUBTYPE:	STAT(rx_badsubtype);
880	case S_RX_NOBUF:	STAT(rx_nobuf);
881	case S_RX_DECRYPTCRC:	STAT(rx_decryptcrc);
882	case S_RX_AHDEMO_MGT:	STAT(rx_ahdemo_mgt);
883	case S_RX_BAD_AUTH:	STAT(rx_bad_auth);
884	case S_RX_UNAUTH:	STAT(rx_unauth);
885	case S_RX_BADKEYID:	STAT(rx_badkeyid);
886	case S_RX_CCMPREPLAY:	STAT(rx_ccmpreplay);
887	case S_RX_CCMPFORMAT:	STAT(rx_ccmpformat);
888	case S_RX_CCMPMIC:	STAT(rx_ccmpmic);
889	case S_RX_TKIPREPLAY:	STAT(rx_tkipreplay);
890	case S_RX_TKIPFORMAT:	STAT(rx_tkipformat);
891	case S_RX_TKIPMIC:	STAT(rx_tkipmic);
892	case S_RX_TKIPICV:	STAT(rx_tkipicv);
893	case S_RX_BADCIPHER:	STAT(rx_badcipher);
894	case S_RX_NOCIPHERCTX:	STAT(rx_nocipherctx);
895	case S_RX_ACL:		STAT(rx_acl);
896	case S_TX_NOBUF:	STAT(tx_nobuf);
897	case S_TX_NONODE:	STAT(tx_nonode);
898	case S_TX_UNKNOWNMGT:	STAT(tx_unknownmgt);
899	case S_TX_BADCIPHER:	STAT(tx_badcipher);
900	case S_TX_NODEFKEY:	STAT(tx_nodefkey);
901	case S_TX_NOHEADROOM:	STAT(tx_noheadroom);
902	case S_TX_FRAGFRAMES:	STAT(tx_fragframes);
903	case S_TX_FRAGS:	STAT(tx_frags);
904	case S_SCAN_ACTIVE:	STAT(scan_active);
905	case S_SCAN_PASSIVE:	STAT(scan_passive);
906	case S_SCAN_BG:		STAT(scan_bg);
907	case S_NODE_TIMEOUT:	STAT(node_timeout);
908	case S_CRYPTO_NOMEM:	STAT(crypto_nomem);
909	case S_CRYPTO_TKIP:	STAT(crypto_tkip);
910	case S_CRYPTO_TKIPENMIC:	STAT(crypto_tkipenmic);
911	case S_CRYPTO_TKIPDEMIC:	STAT(crypto_tkipdemic);
912	case S_CRYPTO_TKIPCM:	STAT(crypto_tkipcm);
913	case S_CRYPTO_CCMP:	STAT(crypto_ccmp);
914	case S_CRYPTO_WEP:	STAT(crypto_wep);
915	case S_CRYPTO_SETKEY_CIPHER:	STAT(crypto_setkey_cipher);
916	case S_CRYPTO_SETKEY_NOKEY:	STAT(crypto_setkey_nokey);
917	case S_CRYPTO_DELKEY:	STAT(crypto_delkey);
918	case S_CRYPTO_BADCIPHER:	STAT(crypto_badcipher);
919	case S_CRYPTO_NOCIPHER:	STAT(crypto_nocipher);
920	case S_CRYPTO_ATTACHFAIL:	STAT(crypto_attachfail);
921	case S_CRYPTO_SWFALLBACK:	STAT(crypto_swfallback);
922	case S_CRYPTO_KEYFAIL:	STAT(crypto_keyfail);
923	case S_CRYPTO_ENMICFAIL:	STAT(crypto_enmicfail);
924	case S_IBSS_CAPMISMATCH:	STAT(ibss_capmismatch);
925	case S_IBSS_NORATE:	STAT(ibss_norate);
926	case S_PS_UNASSOC:	STAT(ps_unassoc);
927	case S_PS_BADAID:	STAT(ps_badaid);
928	case S_PS_QEMPTY:	STAT(ps_qempty);
929	case S_FF_BADHDR:	STAT(ff_badhdr);
930	case S_FF_TOOSHORT:	STAT(ff_tooshort);
931	case S_FF_SPLIT:	STAT(ff_split);
932	case S_FF_DECAP:	STAT(ff_decap);
933	case S_FF_ENCAP:	STAT(ff_encap);
934	case S_RX_BADBINTVAL:	STAT(rx_badbintval);
935	case S_RX_MGMT:		STAT(rx_mgmt);
936	case S_RX_DEMICFAIL:	STAT(rx_demicfail);
937	case S_RX_DEFRAG:	STAT(rx_defrag);
938	case S_RX_ACTION:	STAT(rx_action);
939	case S_AMSDU_TOOSHORT:	STAT(amsdu_tooshort);
940	case S_AMSDU_SPLIT:	STAT(amsdu_split);
941	case S_AMSDU_DECAP:	STAT(amsdu_decap);
942	case S_AMSDU_ENCAP:	STAT(amsdu_encap);
943	case S_AMPDU_REORDER:	STAT(ampdu_rx_reorder);
944	case S_AMPDU_FLUSH:	STAT(ampdu_rx_flush);
945	case S_AMPDU_BARBAD:	STAT(ampdu_bar_bad);
946	case S_AMPDU_BAROOW:	STAT(ampdu_bar_oow);
947	case S_AMPDU_BARMOVE:	STAT(ampdu_bar_move);
948	case S_AMPDU_BAR:	STAT(ampdu_bar_rx);
949	case S_AMPDU_MOVE:	STAT(ampdu_rx_move);
950	case S_AMPDU_OOR:	STAT(ampdu_rx_oor);
951	case S_AMPDU_COPY:	STAT(ampdu_rx_copy);
952	case S_AMPDU_DROP:	STAT(ampdu_rx_drop);
953	case S_AMPDU_AGE:	STAT(ampdu_rx_age);
954	case S_AMPDU_STOP:	STAT(ampdu_stop);
955	case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
956	case S_ADDBA_REJECT:	STAT(addba_reject);
957	case S_ADDBA_NOREQUEST:	STAT(addba_norequest);
958	case S_ADDBA_BADTOKEN:	STAT(addba_badtoken);
959	case S_TX_BADSTATE:	STAT(tx_badstate);
960	case S_TX_NOTASSOC:	STAT(tx_notassoc);
961	case S_TX_CLASSIFY:	STAT(tx_classify);
962	case S_DWDS_MCAST:	STAT(dwds_mcast);
963	case S_DWDS_QDROP:	STAT(dwds_qdrop);
964	case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
965	case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
966	case S_HT_ASSOC_NORATE:	STAT(ht_assoc_norate);
967	case S_MESH_WRONGMESH:	STAT(mesh_wrongmesh);
968	case S_MESH_NOLINK:	STAT(mesh_nolink);
969	case S_MESH_FWD_TTL:	STAT(mesh_fwd_ttl);
970	case S_MESH_FWD_NOBUF:	STAT(mesh_fwd_nobuf);
971	case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort);
972	case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled);
973	case S_MESH_FWD_NOPATH:	STAT(mesh_fwd_nopath);
974	case S_HWMP_WRONGSEQ:	STAT(hwmp_wrongseq);
975	case S_HWMP_ROOTREQS:	STAT(hwmp_rootreqs);
976	case S_HWMP_ROOTANN:	STAT(hwmp_rootrann);
977	case S_MESH_BADAE:	STAT(mesh_badae);
978	case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed);
979	case S_MESH_NOTPROXY:	STAT(mesh_notproxy);
980	case S_RX_BADALIGN:	STAT(rx_badalign);
981	case S_INPUT:		NSTAT(rx_data);
982	case S_OUTPUT:		NSTAT(tx_data);
983	case S_RX_UCAST:	NSTAT(rx_ucast);
984	case S_RX_MCAST:	NSTAT(rx_mcast);
985	case S_TX_UCAST:	NSTAT(tx_ucast);
986	case S_TX_MCAST:	NSTAT(tx_mcast);
987	case S_BEACON_BAD:	STAT(beacon_bad);
988	case S_AMPDU_BARTX:	STAT(ampdu_bar_tx);
989	case S_AMPDU_BARTX_RETRY:	STAT(ampdu_bar_tx_retry);
990	case S_AMPDU_BARTX_FAIL:	STAT(ampdu_bar_tx_fail);
991	}
992	return wlan_getinfo(wf, s, b, bs);
993#undef NSTAT
994#undef STAT
995}
996
997STATFOO_DEFINE_BOUNCE(wlanstatfoo)
998
999struct wlanstatfoo *
1000wlanstats_new(const char *ifname, const char *fmtstring)
1001{
1002#define	N(a)	(sizeof(a) / sizeof(a[0]))
1003	struct wlanstatfoo_p *wf;
1004
1005	wf = calloc(1, sizeof(struct wlanstatfoo_p));
1006	if (wf != NULL) {
1007		statfoo_init(&wf->base.base, "wlanstats", wlanstats, N(wlanstats));
1008		/* override base methods */
1009		wf->base.base.collect_cur = wlan_collect_cur;
1010		wf->base.base.collect_tot = wlan_collect_tot;
1011		wf->base.base.get_curstat = wlan_get_curstat;
1012		wf->base.base.get_totstat = wlan_get_totstat;
1013		wf->base.base.update_tot = wlan_update_tot;
1014
1015		/* setup bounce functions for public methods */
1016		STATFOO_BOUNCE(wf, wlanstatfoo);
1017
1018		/* setup our public methods */
1019		wf->base.setifname = wlan_setifname;
1020		wf->base.getifname = wlan_getifname;
1021		wf->base.getopmode = wlan_getopmode;
1022		wf->base.setstamac = wlan_setstamac;
1023		wf->opmode = -1;
1024
1025		wf->s = socket(AF_INET, SOCK_DGRAM, 0);
1026		if (wf->s < 0)
1027			err(1, "socket");
1028
1029		wlan_setifname(&wf->base, ifname);
1030		wf->base.setfmt(&wf->base, fmtstring);
1031	}
1032	return &wf->base;
1033#undef N
1034}
1035