wlanstats.c revision 173306
1/*-
2 * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer,
10 *    without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 *    redistribution must be conditioned upon including a substantially
14 *    similar Disclaimer requirement for further binary redistribution.
15 * 3. Neither the names of the above-listed copyright holders nor the names
16 *    of any contributors may be used to endorse or promote products derived
17 *    from this software without specific prior written permission.
18 *
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
22 *
23 * NO WARRANTY
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGES.
35 *
36 * $FreeBSD: head/tools/tools/net80211/wlanstats/wlanstats.c 173306 2007-11-03 18:14:12Z sam $
37 */
38
39/*
40 * net80211 statistics class.
41 */
42#include <sys/types.h>
43#include <sys/file.h>
44#include <sys/sockio.h>
45#include <sys/socket.h>
46#include <net/if.h>
47#include <net/if_dl.h>
48#include <net/if_media.h>
49#include <net/if_var.h>
50#include <net/ethernet.h>
51
52#include <stdio.h>
53#include <stdlib.h>
54#include <signal.h>
55#include <string.h>
56#include <unistd.h>
57#include <err.h>
58#include <ifaddrs.h>
59
60#include "../../../../sys/net80211/ieee80211_ioctl.h"
61
62#include "wlanstats.h"
63
64#ifndef IEEE80211_ADDR_COPY
65#define	IEEE80211_ADDR_COPY(dst, src)	memcpy(dst, src, IEEE80211_ADDR_LEN)
66#define	IEEE80211_ADDR_EQ(a1,a2)	(memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)
67#endif
68
69#define	AFTER(prev)	((prev)+1)
70
71static const struct fmt wlanstats[] = {
72#define	S_RX_BADVERSION		0
73	{ 5,  "rx_badversion",	"bvers",	"rx frame with bad version" },
74#define	S_RX_TOOSHORT		AFTER(S_RX_BADVERSION)
75	{ 5,  "rx_tooshort",	"2short",	"rx frame too short" },
76#define	S_RX_WRONGBSS		AFTER(S_RX_TOOSHORT)
77	{ 5,  "rx_wrongbss",	"wrbss",	"rx from wrong bssid" },
78#define	S_RX_DUP		AFTER(S_RX_WRONGBSS)
79	{ 5,  "rx_dup",		"rxdup",	"rx discard 'cuz dup" },
80#define	S_RX_WRONGDIR		AFTER(S_RX_DUP)
81	{ 5,  "rx_wrongdir",	"wrdir",	"rx w/ wrong direction" },
82#define	S_RX_MCASTECHO		AFTER(S_RX_WRONGDIR)
83	{ 5,  "rx_mcastecho",	"mecho",	"rx discard 'cuz mcast echo" },
84#define	S_RX_NOTASSOC		AFTER(S_RX_MCASTECHO)
85	{ 6,  "rx_notassoc",	"!assoc",	"rx discard 'cuz sta !assoc" },
86#define	S_RX_NOPRIVACY		AFTER(S_RX_NOTASSOC)
87	{ 6,  "rx_noprivacy",	"nopriv",	"rx w/ wep but privacy off" },
88#define	S_RX_UNENCRYPTED	AFTER(S_RX_NOPRIVACY)
89	{ 6,  "rx_unencrypted",	"unencr",	"rx w/o wep and privacy on" },
90#define	S_RX_WEPFAIL		AFTER(S_RX_UNENCRYPTED)
91	{ 7,  "rx_wepfail",	"wepfail",	"rx wep processing failed" },
92#define	S_RX_DECAP		AFTER(S_RX_WEPFAIL)
93	{ 5,  "rx_decap",	"decap",	"rx decapsulation failed" },
94#define	S_RX_MGTDISCARD		AFTER(S_RX_DECAP)
95	{ 8,  "rx_mgtdiscard",	"mgtdiscard",	"rx discard mgt frames" },
96#define	S_RX_CTL		AFTER(S_RX_MGTDISCARD)
97	{ 5,  "rx_ctl",		"ctl",		"rx ctrl frames" },
98#define	S_RX_BEACON		AFTER(S_RX_CTL)
99	{ 6,  "rx_beacon",	"beacon",	"rx beacon frames" },
100#define	S_RX_RSTOOBIG		AFTER(S_RX_BEACON)
101	{ 6,  "rx_rstoobig",	"rs2big",	"rx rate set truncated" },
102#define	S_RX_ELEM_MISSING	AFTER(S_RX_RSTOOBIG)
103	{ 6,  "rx_elem_missing","iemiss",	"rx required element missing" },
104#define	S_RX_ELEM_TOOBIG	AFTER(S_RX_ELEM_MISSING)
105	{ 6,  "rx_elem_toobig",	"ie2big",	"rx element too big" },
106#define	S_RX_ELEM_TOOSMALL	AFTER(S_RX_ELEM_TOOBIG)
107	{ 7,  "rx_elem_toosmall","ie2small","rx element too small" },
108#define	S_RX_ELEM_UNKNOWN 	AFTER(S_RX_ELEM_TOOSMALL)
109	{ 5,  "rx_elem_unknown","ieunk",	"rx element unknown" },
110#define	S_RX_BADCHAN		AFTER(S_RX_ELEM_UNKNOWN)
111	{ 6,  "rx_badchan",	"badchan",	"rx frame w/ invalid chan" },
112#define	S_RX_CHANMISMATCH	AFTER(S_RX_BADCHAN)
113	{ 5,  "rx_chanmismatch","chanmismatch",	"rx frame chan mismatch" },
114#define	S_RX_NODEALLOC		AFTER(S_RX_CHANMISMATCH)
115	{ 5,  "rx_nodealloc",	"nodealloc",	"nodes allocated (rx)" },
116#define	S_RX_SSIDMISMATCH	AFTER(S_RX_NODEALLOC)
117	{ 5,  "rx_ssidmismatch","ssidmismatch",	"rx frame ssid mismatch" },
118#define	S_RX_AUTH_UNSUPPORTED	AFTER(S_RX_SSIDMISMATCH)
119	{ 5,  "rx_auth_unsupported","auth_unsupported",
120		"rx w/ unsupported auth alg" },
121#define	S_RX_AUTH_FAIL		AFTER(S_RX_AUTH_UNSUPPORTED)
122	{ 5,  "rx_auth_fail",	"auth_fail",	"rx sta auth failure" },
123#define	S_RX_AUTH_COUNTERMEASURES	AFTER(S_RX_AUTH_FAIL)
124	{ 5,  "rx_auth_countermeasures",	"auth_countermeasures",
125		"rx sta auth failure 'cuz of TKIP countermeasures" },
126#define	S_RX_ASSOC_BSS		AFTER(S_RX_AUTH_COUNTERMEASURES)
127	{ 5,  "rx_assoc_bss",	"assoc_bss",	"rx assoc from wrong bssid" },
128#define	S_RX_ASSOC_NOTAUTH	AFTER(S_RX_ASSOC_BSS)
129	{ 5,  "rx_assoc_notauth","assoc_notauth",	"rx assoc w/o auth" },
130#define	S_RX_ASSOC_CAPMISMATCH	AFTER(S_RX_ASSOC_NOTAUTH)
131	{ 5,  "rx_assoc_capmismatch","assoc_capmismatch",
132		"rx assoc w/ cap mismatch" },
133#define	S_RX_ASSOC_NORATE	AFTER(S_RX_ASSOC_CAPMISMATCH)
134	{ 5,  "rx_assoc_norate","assoc_norate",	"rx assoc w/ no rate match" },
135#define	S_RX_ASSOC_BADWPAIE	AFTER(S_RX_ASSOC_NORATE)
136	{ 5,  "rx_assoc_badwpaie","assoc_badwpaie",
137		"rx assoc w/ bad WPA IE" },
138#define	S_RX_DEAUTH		AFTER(S_RX_ASSOC_BADWPAIE)
139	{ 5,  "rx_deauth",	"deauth",	"rx deauthentication" },
140#define	S_RX_DISASSOC		AFTER(S_RX_DEAUTH)
141	{ 5,  "rx_disassoc",	"disassoc",	"rx disassociation" },
142#define	S_RX_BADSUBTYPE		AFTER(S_RX_DISASSOC)
143	{ 5,  "rx_badsubtype",	"badsubtype",	"rx frame w/ unknown subtype" },
144#define	S_RX_NOBUF		AFTER(S_RX_BADSUBTYPE)
145	{ 5,  "rx_nobuf",	"nobuf",	"rx failed for lack of mbuf" },
146#define	S_RX_DECRYPTCRC		AFTER(S_RX_NOBUF)
147	{ 5,  "rx_decryptcrc",	"decryptcrc",	"rx decrypt failed on crc" },
148#define	S_RX_AHDEMO_MGT		AFTER(S_RX_DECRYPTCRC)
149	{ 5,  "rx_ahdemo_mgt",	"ahdemo_mgt",
150		"rx discard mgmt frame received in ahdoc demo mode" },
151#define	S_RX_BAD_AUTH		AFTER(S_RX_AHDEMO_MGT)
152	{ 5,  "rx_bad_auth",	"bad_auth",	"rx bad authentication request" },
153#define	S_RX_UNAUTH		AFTER(S_RX_BAD_AUTH)
154	{ 5,  "rx_unauth",	"unauth",
155		"rx discard 'cuz port unauthorized" },
156#define	S_RX_BADKEYID		AFTER(S_RX_UNAUTH)
157	{ 5,  "rx_badkeyid",	"badkeyid",	"rx w/ incorrect keyid" },
158#define	S_RX_CCMPREPLAY		AFTER(S_RX_BADKEYID)
159	{ 5,  "rx_ccmpreplay",	"ccmpreplay",	"rx seq# violation (CCMP)" },
160#define	S_RX_CCMPFORMAT		AFTER(S_RX_CCMPREPLAY)
161	{ 5,  "rx_ccmpformat",	"ccmpformat",	"rx format bad (CCMP)" },
162#define	S_RX_CCMPMIC		AFTER(S_RX_CCMPFORMAT)
163	{ 5,  "rx_ccmpmic",	"ccmpmic",	"rx MIC check failed (CCMP)" },
164#define	S_RX_TKIPREPLAY		AFTER(S_RX_CCMPMIC)
165	{ 5,  "rx_tkipreplay",	"tkipreplay",	"rx seq# violation (TKIP)" },
166#define	S_RX_TKIPFORMAT		AFTER(S_RX_TKIPREPLAY)
167	{ 5,  "rx_tkipformat",	"tkipformat",	"rx format bad (TKIP)" },
168#define	S_RX_TKIPMIC		AFTER(S_RX_TKIPFORMAT)
169	{ 5,  "rx_tkipmic",	"tkipmic",	"rx MIC check failed (TKIP)" },
170#define	S_RX_TKIPICV		AFTER(S_RX_TKIPMIC)
171	{ 5,  "rx_tkipicv",	"tkipicv",	"rx ICV check failed (TKIP)" },
172#define	S_RX_BADCIPHER		AFTER(S_RX_TKIPICV)
173	{ 5,  "rx_badcipher",	"badcipher",	"rx failed 'cuz bad cipher/key type" },
174#define	S_RX_NOCIPHERCTX	AFTER(S_RX_BADCIPHER)
175	{ 5,  "rx_nocipherctx",	"nocipherctx",	"rx failed 'cuz key/cipher ctx not setup" },
176#define	S_RX_ACL		AFTER(S_RX_NOCIPHERCTX)
177	{ 5,  "rx_acl",		"acl",		"rx discard 'cuz acl policy" },
178#define	S_TX_NOBUF		AFTER(S_RX_ACL)
179	{ 5,  "tx_nobuf",	"nobuf",	"tx failed for lack of mbuf" },
180#define	S_TX_NONODE		AFTER(S_TX_NOBUF)
181	{ 5,  "tx_nonode",	"nonode",	"tx failed for no node" },
182#define	S_TX_UNKNOWNMGT		AFTER(S_TX_NONODE)
183	{ 5,  "tx_unknownmgt",	"unknownmgt",	"tx of unknown mgt frame" },
184#define	S_TX_BADCIPHER		AFTER(S_TX_UNKNOWNMGT)
185	{ 5,  "tx_badcipher",	"badcipher",	"tx failed 'cuz bad ciper/key type" },
186#define	S_TX_NODEFKEY		AFTER(S_TX_BADCIPHER)
187	{ 5,  "tx_nodefkey",	"nodefkey",	"tx failed 'cuz no defkey" },
188#define	S_TX_NOHEADROOM		AFTER(S_TX_NODEFKEY)
189	{ 5,  "tx_noheadroom",	"noheadroom",	"tx failed 'cuz no space for crypto hdrs" },
190#define	S_TX_FRAGFRAMES		AFTER(S_TX_NOHEADROOM)
191	{ 5,  "tx_fragframes",	"fragframes",	"tx frames fragmented" },
192#define	S_TX_FRAGS		AFTER(S_TX_FRAGFRAMES)
193	{ 5,  "tx_frags",	"frags",		"tx frags generated" },
194#define	S_SCAN_ACTIVE		AFTER(S_TX_FRAGS)
195	{ 5,  "scan_active",	"scan_active",	"active scans started" },
196#define	S_SCAN_PASSIVE		AFTER(S_SCAN_ACTIVE)
197	{ 5,  "scan_passive",	"scan_passive",	"passive scans started" },
198#define	S_NODE_TIMEOUT		AFTER(S_SCAN_PASSIVE)
199	{ 5,  "node_timeout",	"node_timeout",	"nodes timed out for inactivity" },
200#define	S_CRYPTO_NOMEM		AFTER(S_NODE_TIMEOUT)
201	{ 5,  "crypto_nomem",	"crypto_nomem",	"cipher context malloc failed" },
202#define	S_CRYPTO_TKIP		AFTER(S_CRYPTO_NOMEM)
203	{ 5,  "crypto_tkip",	"crypto_tkip",	"tkip crypto done in s/w" },
204#define	S_CRYPTO_TKIPENMIC	AFTER(S_CRYPTO_TKIP)
205	{ 5,  "crypto_tkipenmic","crypto_tkipenmic",	"tkip tx MIC done in s/w" },
206#define	S_CRYPTO_TKIPDEMIC	AFTER(S_CRYPTO_TKIPENMIC)
207	{ 5,  "crypto_tkipdemic","crypto_tkipdemic",	"tkip rx MIC done in s/w" },
208#define	S_CRYPTO_TKIPCM		AFTER(S_CRYPTO_TKIPDEMIC)
209	{ 5,  "crypto_tkipcm",	"crypto_tkipcm",	"tkip dropped frames 'cuz of countermeasures" },
210#define	S_CRYPTO_CCMP		AFTER(S_CRYPTO_TKIPCM)
211	{ 5,  "crypto_ccmp",	"crypto_ccmp",	"ccmp crypto done in s/w" },
212#define	S_CRYPTO_WEP		AFTER(S_CRYPTO_CCMP)
213	{ 5,  "crypto_wep",	"crypto_wep",	"wep crypto done in s/w" },
214#define	S_CRYPTO_SETKEY_CIPHER	AFTER(S_CRYPTO_WEP)
215	{ 5,  "crypto_setkey_cipher",	"crypto_setkey_cipher","setkey failed 'cuz cipher rejected data" },
216#define	S_CRYPTO_SETKEY_NOKEY	AFTER(S_CRYPTO_SETKEY_CIPHER)
217	{ 5,  "crypto_setkey_nokey",	"crypto_setkey_nokey","setkey failed 'cuz no key index" },
218#define	S_CRYPTO_DELKEY		AFTER(S_CRYPTO_SETKEY_NOKEY)
219	{ 5,  "crypto_delkey",	"crypto_delkey",	"driver key delete failed" },
220#define	S_CRYPTO_BADCIPHER	AFTER(S_CRYPTO_DELKEY)
221	{ 5,  "crypto_badcipher","crypto_badcipher",	"setkey failed 'cuz unknown cipher" },
222#define	S_CRYPTO_NOCIPHER	AFTER(S_CRYPTO_BADCIPHER)
223	{ 5,  "crypto_nocipher","crypto_nocipher",	"setkey failed 'cuz cipher module unavailable" },
224#define	S_CRYPTO_ATTACHFAIL	AFTER(S_CRYPTO_NOCIPHER)
225	{ 5,  "crypto_attachfail","crypto_attachfail",	"setkey failed 'cuz cipher attach failed" },
226#define	S_CRYPTO_SWFALLBACK	AFTER(S_CRYPTO_ATTACHFAIL)
227	{ 5,  "crypto_swfallback","crypto_swfallback",	"crypto fell back to s/w implementation" },
228#define	S_CRYPTO_KEYFAIL	AFTER(S_CRYPTO_SWFALLBACK)
229	{ 5,  "crypto_keyfail",	"crypto_keyfail",	"setkey failed 'cuz driver key alloc failed" },
230#define	S_CRYPTO_ENMICFAIL	AFTER(S_CRYPTO_KEYFAIL)
231	{ 5,  "crypto_enmicfail","crypto_enmicfail",	"enmic failed (may be mbuf exhaustion)" },
232#define	S_IBSS_CAPMISMATCH	AFTER(S_CRYPTO_ENMICFAIL)
233	{ 5,  "ibss_capmismatch","ibss_capmismatch",	"ibss merge faied 'cuz capabilities mismatch" },
234#define	S_IBSS_NORATE		AFTER(S_IBSS_CAPMISMATCH)
235	{ 5,  "ibss_norate",	"ibss_norate",	"ibss merge faied 'cuz rate set mismatch" },
236#define	S_PS_UNASSOC		AFTER(S_IBSS_NORATE)
237	{ 5,  "ps_unassoc",	"ps_unassoc",	"ps-poll received for unassociated station" },
238#define	S_PS_BADAID		AFTER(S_PS_UNASSOC)
239	{ 5,  "ps_badaid",	"ps_badaid",	"ps-poll received with invalid association id" },
240#define	S_PS_QEMPTY		AFTER(S_PS_BADAID)
241	{ 5,  "ps_qempty",	"ps_qempty",	"ps-poll received with nothing to send" },
242#define	S_FF_BADHDR		AFTER(S_PS_QEMPTY)
243	{ 5,  "ff_badhdr",	"ff_badhdr",	"fast frame rx'd w/ bad hdr" },
244#define	S_FF_TOOSHORT		AFTER(S_FF_BADHDR)
245	{ 5,  "ff_tooshort",	"ff_tooshort",	"fast frame rx decap error" },
246#define	S_FF_SPLIT		AFTER(S_FF_TOOSHORT)
247	{ 5,  "ff_split",	"ff_split",	"fast frame rx split error" },
248#define	S_FF_DECAP		AFTER(S_FF_SPLIT)
249	{ 5,  "ff_decap",	"ff_decap",	"fast frames decap'd" },
250#define	S_FF_ENCAP		AFTER(S_FF_DECAP)
251	{ 5,  "ff_encap",	"ff_encap",	"fast frames encap'd for tx" },
252#define	S_FF_ENCAPFAIL		AFTER(S_FF_ENCAP)
253	{ 5,  "ff_encapfail",	"ff_encapfail",	"fast frames encap failed" },
254#define	S_RX_BADBINTVAL		AFTER(S_FF_ENCAPFAIL)
255	{ 5,  "rx_badbintval",	"rx_badbintval","rx frame with bogus beacon interval" },
256#define	S_RX_MGMT		AFTER(S_RX_BADBINTVAL)
257	{ 5,  "rx_mgmt",	"rx_mgmt",	"rx management frames" },
258#define	S_RX_DEMICFAIL		AFTER(S_RX_MGMT)
259	{ 5,  "rx_demicfail",	"rx_demicfail",	"rx demic failed" },
260#define	S_RX_DEFRAG		AFTER(S_RX_DEMICFAIL)
261	{ 5,  "rx_defrag",	"rx_defrag",	"rx defragmentation failed" },
262#define	S_RX_ACTION		AFTER(S_RX_DEFRAG)
263	{ 5,  "rx_action",	"rx_action",	"rx action frames" },
264#define	S_AMSDU_TOOSHORT	AFTER(S_RX_ACTION)
265	{ 8,  "amsdu_tooshort",	"tooshort","A-MSDU rx decap error" },
266#define	S_AMSDU_SPLIT		AFTER(S_AMSDU_TOOSHORT)
267	{ 8,  "amsdu_split",	"split",	"A-MSDU rx failed on frame split" },
268#define	S_AMSDU_DECAP		AFTER(S_AMSDU_SPLIT)
269	{ 8,  "amsdu_decap",	"decap",	"A-MSDU frames received" },
270#define	S_AMSDU_ENCAP		AFTER(S_AMSDU_DECAP)
271	{ 8,  "amsdu_encap",	"encap",	"A-MSDU frames transmitted" },
272#define	S_AMPDU_REORDER		AFTER(S_AMSDU_ENCAP)
273	{ 8,  "ampdu_reorder",	"reorder","A-MPDU frames held in reorder q" },
274#define	S_AMPDU_FLUSH		AFTER(S_AMPDU_REORDER)
275	{ 8,  "ampdu_flush",	"flush",	"A-MPDU frames sent up from reorder q" },
276#define	S_AMPDU_BARBAD		AFTER(S_AMPDU_FLUSH)
277	{ 6,  "ampdu_barbad",	"barbad",	"A-MPDU BAR rx before ADDBA exchange (or disabled with net.link.ieee80211)" },
278#define	S_AMPDU_BAROOW		AFTER(S_AMPDU_BARBAD)
279	{ 6,  "ampdu_baroow",	"baroow",	"A-MPDU BAR rx out of BA window" },
280#define	S_AMPDU_BARMOVE		AFTER(S_AMPDU_BAROOW)
281	{ 8,  "ampdu_barmove",	"barmove","A-MPDU BAR rx moved BA window" },
282#define	S_AMPDU_BAR		AFTER(S_AMPDU_BARMOVE)
283	{ 8,  "ampdu_bar",	"rxbar",	"A-MPDU BAR rx successful" },
284#define	S_AMPDU_MOVE		AFTER(S_AMPDU_BAR)
285	{ 5,  "ampdu_move",	"move",	"A-MPDU frame moved BA window" },
286#define	S_AMPDU_OOR		AFTER(S_AMPDU_MOVE)
287	{ 8,  "ampdu_oor",	"oorx",	"A-MPDU frames rx out-of-order" },
288#define	S_AMPDU_COPY		AFTER(S_AMPDU_OOR)
289	{ 8,  "ampdu_copy",	"copy",	"A-MPDU rx window slots copied" },
290#define	S_AMPDU_DROP		AFTER(S_AMPDU_COPY)
291	{ 5,  "ampdu_drop",	"drop",	"A-MPDU frames discarded for out of range seqno" },
292#define	S_AMPDU_AGE		AFTER(S_AMPDU_DROP)
293	{ 5,  "ampdu_age",	"age",	"A-MPDU frames sent up due to old age" },
294#define	S_AMPDU_STOP		AFTER(S_AMPDU_AGE)
295	{ 5,  "ampdu_stop",	"stop",	"A-MPDU streams stopped" },
296#define	S_AMPDU_STOP_FAILED	AFTER(S_AMPDU_STOP)
297	{ 5,  "ampdu_stop_failed","!stop",	"A-MPDU stop requests failed 'cuz stream not running" },
298#define	S_ADDBA_REJECT		AFTER(S_AMPDU_STOP_FAILED)
299	{ 5,  "addba_reject",	"reject",	"ADDBA requests rejected 'cuz A-MPDU rx is disabled" },
300#define	S_ADDBA_NOREQUEST	AFTER(S_ADDBA_REJECT)
301	{ 5,  "addba_norequest","norequest","ADDBA response frames discarded because no ADDBA request was pending" },
302#define	S_ADDBA_BADTOKEN	AFTER(S_ADDBA_NOREQUEST)
303	{ 5,  "addba_badtoken",	"badtoken","ADDBA response frames discarded 'cuz rx'd dialog token is wrong" },
304#define	S_TX_BADSTATE		AFTER(S_ADDBA_BADTOKEN)
305	{ 4,  "tx_badstate",	"badstate",	"tx failed 'cuz vap not in RUN state" },
306#define	S_TX_NOTASSOC		AFTER(S_TX_BADSTATE)
307	{ 4,  "tx_notassoc",	"notassoc",	"tx failed 'cuz dest sta not associated" },
308#define	S_TX_CLASSIFY		AFTER(S_TX_NOTASSOC)
309	{ 4,  "tx_classify",	"classify",	"tx packet classification failed" },
310#define	S_DWDS_MCAST		AFTER(S_TX_CLASSIFY)
311	{ 8,  "dwds_mcast",	"dwds_mcast",	"mcast frame transmitted on dwds vap discarded" },
312#define	S_DWDS_QDROP		AFTER(S_DWDS_MCAST)
313	{ 8,  "dwds_qdrop",	"dwds_qdrop",	"4-address frame discarded because dwds pending queue is full" },
314#define	S_HT_ASSOC_NOHTCAP	AFTER(S_DWDS_QDROP)
315	{ 4,  "ht_nohtcap",	"ht_nohtcap",	"non-HT station rejected in HT-only BSS" },
316#define	S_HT_ASSOC_DOWNGRADE	AFTER(S_HT_ASSOC_NOHTCAP)
317	{ 4,  "ht_downgrade",	"ht_downgrade",	"HT station downgraded to legacy operation" },
318#define	S_HT_ASSOC_NORATE	AFTER(S_HT_ASSOC_DOWNGRADE)
319	{ 4,  "ht_norate",	"ht_norate",	"HT station rejected because of HT rate set" },
320#define	S_INPUT			AFTER(S_HT_ASSOC_NORATE)
321	{ 8,	"input",	"input",	"total data frames received" },
322#define	S_RX_UCAST		AFTER(S_INPUT)
323	{ 8,	"rx_ucast",	"rx_ucast",	"unicast data frames received" },
324#define	S_RX_MCAST		AFTER(S_RX_UCAST)
325	{ 8,	"rx_mcast",	"rx_mcast",	"multicast data frames received" },
326#define	S_OUTPUT		AFTER(S_RX_MCAST)
327	{ 8,	"output",	"output",	"total data frames transmit" },
328#define	S_TX_UCAST		AFTER(S_OUTPUT)
329	{ 8,	"tx_ucast",	"tx_ucast",	"unicast data frames sent" },
330#define	S_TX_MCAST		AFTER(S_TX_UCAST)
331	{ 8,	"tx_mcast",	"tx_mcast",	"multicast data frames sent" },
332#define	S_RATE			AFTER(S_TX_MCAST)
333	{ 4,	"rate",		"rate",		"current transmit rate" },
334#define	S_RSSI			AFTER(S_RATE)
335	{ 4,	"rssi",		"rssi",		"current rssi" },
336#define	S_NOISE			AFTER(S_RSSI)
337	{ 4,	"noise",	"noise",	"current noise floor (dBm)" },
338#define	S_SIGNAL		AFTER(S_NOISE)
339	{ 4,	"signal",	"sig",		"current signal (dBm)" },
340};
341
342struct wlanstatfoo_p {
343	struct wlanstatfoo base;
344	int s;
345	int opmode;
346	uint8_t mac[IEEE80211_ADDR_LEN];
347	struct ifreq ifr;
348	struct ieee80211_stats cur;
349	struct ieee80211_stats total;
350	struct ieee80211req ireq;
351	union {
352		struct ieee80211req_sta_req info;
353		char buf[1024];
354	} u_info;
355	struct ieee80211req_sta_stats ncur;
356	struct ieee80211req_sta_stats ntotal;
357};
358
359static void
360wlan_setifname(struct wlanstatfoo *wf0, const char *ifname)
361{
362	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
363
364	strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name));
365	strncpy(wf->ireq.i_name, ifname, sizeof (wf->ireq.i_name));
366}
367
368static const char *
369wlan_getifname(struct wlanstatfoo *wf0)
370{
371	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
372
373	return wf->ifr.ifr_name;
374}
375
376static int
377wlan_getopmode(struct wlanstatfoo *wf0)
378{
379	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
380
381	if (wf->opmode == -1) {
382		struct ifmediareq ifmr;
383
384		memset(&ifmr, 0, sizeof(ifmr));
385		strlcpy(ifmr.ifm_name, wf->ifr.ifr_name, sizeof(ifmr.ifm_name));
386		if (ioctl(wf->s, SIOCGIFMEDIA, &ifmr) < 0)
387			err(1, "%s (SIOCGIFMEDIA)", wf->ifr.ifr_name);
388		if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
389			wf->opmode = IEEE80211_M_IBSS;	/* XXX ahdemo */
390		else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
391			wf->opmode = IEEE80211_M_HOSTAP;
392		else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
393			wf->opmode = IEEE80211_M_MONITOR;
394		else
395			wf->opmode = IEEE80211_M_STA;
396	}
397	return wf->opmode;
398}
399
400static void
401getlladdr(struct wlanstatfoo_p *wf)
402{
403	const struct sockaddr_dl *sdl;
404	struct ifaddrs *ifp, *p;
405
406	if (getifaddrs(&ifp) != 0)
407		err(1, "getifaddrs");
408	for (p = ifp; p != NULL; p = p->ifa_next)
409		if (strcmp(p->ifa_name, wf->ifr.ifr_name) == 0 &&
410		    p->ifa_addr->sa_family == AF_LINK)
411			break;
412	if (p == NULL)
413		errx(1, "did not find link layer address for interface %s",
414			wf->ifr.ifr_name);
415	sdl = (const struct sockaddr_dl *) p->ifa_addr;
416	IEEE80211_ADDR_COPY(wf->mac, LLADDR(sdl));
417	freeifaddrs(ifp);
418}
419
420static void
421wlan_setstamac(struct wlanstatfoo *wf0, const uint8_t *mac)
422{
423	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
424
425	if (mac == NULL) {
426		switch (wlan_getopmode(wf0)) {
427		case IEEE80211_M_HOSTAP:
428		case IEEE80211_M_MONITOR:
429		case IEEE80211_M_IBSS:
430		case IEEE80211_M_AHDEMO:
431			getlladdr(wf);
432			break;
433		case IEEE80211_M_STA:
434			wf->ireq.i_type = IEEE80211_IOC_BSSID;
435			wf->ireq.i_data = wf->mac;
436			wf->ireq.i_len = IEEE80211_ADDR_LEN;
437			if (ioctl(wf->s, SIOCG80211, &wf->ireq) <0)
438				err(1, "%s (IEEE80211_IOC_BSSID)", wf->ireq.i_name);
439			break;
440		}
441	} else
442		IEEE80211_ADDR_COPY(wf->mac, mac);
443}
444
445/* XXX only fetch what's needed to do reports */
446static void
447wlan_collect(struct wlanstatfoo_p *wf,
448	struct ieee80211_stats *stats, struct ieee80211req_sta_stats *nstats)
449{
450
451	IEEE80211_ADDR_COPY(wf->u_info.info.is_u.macaddr, wf->mac);
452	wf->ireq.i_type = IEEE80211_IOC_STA_INFO;
453	wf->ireq.i_data = (caddr_t) &wf->u_info;
454	wf->ireq.i_len = sizeof(wf->u_info);
455	if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0)
456		err(1, "%s (IEEE80211_IOC_STA_INFO)", wf->ireq.i_name);
457
458	IEEE80211_ADDR_COPY(nstats->is_u.macaddr, wf->mac);
459	wf->ireq.i_type = IEEE80211_IOC_STA_STATS;
460	wf->ireq.i_data = (caddr_t) nstats;
461	wf->ireq.i_len = sizeof(*nstats);
462	if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0)
463		err(1, "%s (IEEE80211_IOC_STA_STATS)", wf->ireq.i_name);
464
465	wf->ifr.ifr_data = (caddr_t) stats;
466	if (ioctl(wf->s, SIOCG80211STATS, &wf->ifr) < 0)
467		err(1, "%s (SIOCG80211STATS)", wf->ifr.ifr_name);
468}
469
470static void
471wlan_collect_cur(struct statfoo *sf)
472{
473	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
474
475	wlan_collect(wf, &wf->cur, &wf->ncur);
476}
477
478static void
479wlan_collect_tot(struct statfoo *sf)
480{
481	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
482
483	wlan_collect(wf, &wf->total, &wf->ntotal);
484}
485
486static void
487wlan_update_tot(struct statfoo *sf)
488{
489	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
490
491	wf->total = wf->cur;
492	wf->ntotal = wf->ncur;
493}
494
495static int
496wlan_getinfo(struct wlanstatfoo_p *wf, int s, char b[], size_t bs)
497{
498	const struct ieee80211req_sta_info *si = &wf->u_info.info.info[0];
499	uint8_t r;
500
501	switch (s) {
502	case S_RATE:
503		r = si->isi_rates[si->isi_txrate];
504		snprintf(b, bs, "%uM", (r &~ 0x80) / 2);
505		return 1;
506	case S_RSSI:
507		snprintf(b, bs, "%d", si->isi_rssi);
508		return 1;
509	case S_NOISE:
510		snprintf(b, bs, "%d", si->isi_noise);
511		return 1;
512	case S_SIGNAL:
513		snprintf(b, bs, "%d", si->isi_rssi + si->isi_noise);
514		return 1;
515	}
516	b[0] = '\0';
517	return 0;
518}
519
520static int
521wlan_get_curstat(struct statfoo *sf, int s, char b[], size_t bs)
522{
523	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
524#define	STAT(x) \
525	snprintf(b, bs, "%u", wf->cur.is_##x - wf->total.is_##x); return 1
526#define	NSTAT(x) \
527	snprintf(b, bs, "%u", \
528	    wf->ncur.is_stats.ns_##x - wf->ntotal.is_stats.ns_##x); \
529	    return 1
530
531	switch (s) {
532	case S_RX_BADVERSION:	STAT(rx_badversion);
533	case S_RX_TOOSHORT:	STAT(rx_tooshort);
534	case S_RX_WRONGBSS:	STAT(rx_wrongbss);
535	case S_RX_DUP:		STAT(rx_dup);
536	case S_RX_WRONGDIR:	STAT(rx_wrongdir);
537	case S_RX_MCASTECHO:	STAT(rx_mcastecho);
538	case S_RX_NOTASSOC:	STAT(rx_notassoc);
539	case S_RX_NOPRIVACY:	STAT(rx_noprivacy);
540	case S_RX_UNENCRYPTED:	STAT(rx_unencrypted);
541	case S_RX_WEPFAIL:	STAT(rx_wepfail);
542	case S_RX_DECAP:	STAT(rx_decap);
543	case S_RX_MGTDISCARD:	STAT(rx_mgtdiscard);
544	case S_RX_CTL:		STAT(rx_ctl);
545	case S_RX_BEACON:	STAT(rx_beacon);
546	case S_RX_RSTOOBIG:	STAT(rx_rstoobig);
547	case S_RX_ELEM_MISSING:	STAT(rx_elem_missing);
548	case S_RX_ELEM_TOOBIG:	STAT(rx_elem_toobig);
549	case S_RX_ELEM_TOOSMALL:	STAT(rx_elem_toosmall);
550	case S_RX_ELEM_UNKNOWN:	STAT(rx_elem_unknown);
551	case S_RX_BADCHAN:	STAT(rx_badchan);
552	case S_RX_CHANMISMATCH:	STAT(rx_chanmismatch);
553	case S_RX_NODEALLOC:	STAT(rx_nodealloc);
554	case S_RX_SSIDMISMATCH:	STAT(rx_ssidmismatch);
555	case S_RX_AUTH_UNSUPPORTED:	STAT(rx_auth_unsupported);
556	case S_RX_AUTH_FAIL:	STAT(rx_auth_fail);
557	case S_RX_AUTH_COUNTERMEASURES:	STAT(rx_auth_countermeasures);
558	case S_RX_ASSOC_BSS:	STAT(rx_assoc_bss);
559	case S_RX_ASSOC_NOTAUTH:	STAT(rx_assoc_notauth);
560	case S_RX_ASSOC_CAPMISMATCH:	STAT(rx_assoc_capmismatch);
561	case S_RX_ASSOC_NORATE:	STAT(rx_assoc_norate);
562	case S_RX_ASSOC_BADWPAIE:	STAT(rx_assoc_badwpaie);
563	case S_RX_DEAUTH:	STAT(rx_deauth);
564	case S_RX_DISASSOC:	STAT(rx_disassoc);
565	case S_RX_BADSUBTYPE:	STAT(rx_badsubtype);
566	case S_RX_NOBUF:	STAT(rx_nobuf);
567	case S_RX_DECRYPTCRC:	STAT(rx_decryptcrc);
568	case S_RX_AHDEMO_MGT:	STAT(rx_ahdemo_mgt);
569	case S_RX_BAD_AUTH:	STAT(rx_bad_auth);
570	case S_RX_UNAUTH:	STAT(rx_unauth);
571	case S_RX_BADKEYID:	STAT(rx_badkeyid);
572	case S_RX_CCMPREPLAY:	STAT(rx_ccmpreplay);
573	case S_RX_CCMPFORMAT:	STAT(rx_ccmpformat);
574	case S_RX_CCMPMIC:	STAT(rx_ccmpmic);
575	case S_RX_TKIPREPLAY:	STAT(rx_tkipreplay);
576	case S_RX_TKIPFORMAT:	STAT(rx_tkipformat);
577	case S_RX_TKIPMIC:	STAT(rx_tkipmic);
578	case S_RX_TKIPICV:	STAT(rx_tkipicv);
579	case S_RX_BADCIPHER:	STAT(rx_badcipher);
580	case S_RX_NOCIPHERCTX:	STAT(rx_nocipherctx);
581	case S_RX_ACL:		STAT(rx_acl);
582	case S_TX_NOBUF:	STAT(tx_nobuf);
583	case S_TX_NONODE:	STAT(tx_nonode);
584	case S_TX_UNKNOWNMGT:	STAT(tx_unknownmgt);
585	case S_TX_BADCIPHER:	STAT(tx_badcipher);
586	case S_TX_NODEFKEY:	STAT(tx_nodefkey);
587	case S_TX_NOHEADROOM:	STAT(tx_noheadroom);
588	case S_TX_FRAGFRAMES:	STAT(tx_fragframes);
589	case S_TX_FRAGS:	STAT(tx_frags);
590	case S_SCAN_ACTIVE:	STAT(scan_active);
591	case S_SCAN_PASSIVE:	STAT(scan_passive);
592	case S_NODE_TIMEOUT:	STAT(node_timeout);
593	case S_CRYPTO_NOMEM:	STAT(crypto_nomem);
594	case S_CRYPTO_TKIP:	STAT(crypto_tkip);
595	case S_CRYPTO_TKIPENMIC:	STAT(crypto_tkipenmic);
596	case S_CRYPTO_TKIPDEMIC:	STAT(crypto_tkipdemic);
597	case S_CRYPTO_TKIPCM:	STAT(crypto_tkipcm);
598	case S_CRYPTO_CCMP:	STAT(crypto_ccmp);
599	case S_CRYPTO_WEP:	STAT(crypto_wep);
600	case S_CRYPTO_SETKEY_CIPHER:	STAT(crypto_setkey_cipher);
601	case S_CRYPTO_SETKEY_NOKEY:	STAT(crypto_setkey_nokey);
602	case S_CRYPTO_DELKEY:	STAT(crypto_delkey);
603	case S_CRYPTO_BADCIPHER:	STAT(crypto_badcipher);
604	case S_CRYPTO_NOCIPHER:	STAT(crypto_nocipher);
605	case S_CRYPTO_ATTACHFAIL:	STAT(crypto_attachfail);
606	case S_CRYPTO_SWFALLBACK:	STAT(crypto_swfallback);
607	case S_CRYPTO_KEYFAIL:	STAT(crypto_keyfail);
608	case S_CRYPTO_ENMICFAIL:	STAT(crypto_enmicfail);
609	case S_IBSS_CAPMISMATCH:	STAT(ibss_capmismatch);
610	case S_IBSS_NORATE:	STAT(ibss_norate);
611	case S_PS_UNASSOC:	STAT(ps_unassoc);
612	case S_PS_BADAID:	STAT(ps_badaid);
613	case S_PS_QEMPTY:	STAT(ps_qempty);
614	case S_FF_BADHDR:	STAT(ff_badhdr);
615	case S_FF_TOOSHORT:	STAT(ff_tooshort);
616	case S_FF_SPLIT:	STAT(ff_split);
617	case S_FF_DECAP:	STAT(ff_decap);
618	case S_FF_ENCAP:	STAT(ff_encap);
619	case S_RX_BADBINTVAL:	STAT(rx_badbintval);
620	case S_RX_MGMT:		STAT(rx_mgmt);
621	case S_RX_DEMICFAIL:	STAT(rx_demicfail);
622	case S_RX_DEFRAG:	STAT(rx_defrag);
623	case S_RX_ACTION:	STAT(rx_action);
624	case S_AMSDU_TOOSHORT:	STAT(amsdu_tooshort);
625	case S_AMSDU_SPLIT:	STAT(amsdu_split);
626	case S_AMSDU_DECAP:	STAT(amsdu_decap);
627	case S_AMSDU_ENCAP:	STAT(amsdu_encap);
628	case S_AMPDU_REORDER:	STAT(ampdu_rx_reorder);
629	case S_AMPDU_FLUSH:	STAT(ampdu_rx_flush);
630	case S_AMPDU_BARBAD:	STAT(ampdu_bar_bad);
631	case S_AMPDU_BAROOW:	STAT(ampdu_bar_oow);
632	case S_AMPDU_BARMOVE:	STAT(ampdu_bar_move);
633	case S_AMPDU_BAR:	STAT(ampdu_bar_rx);
634	case S_AMPDU_MOVE:	STAT(ampdu_rx_move);
635	case S_AMPDU_OOR:	STAT(ampdu_rx_oor);
636	case S_AMPDU_COPY:	STAT(ampdu_rx_copy);
637	case S_AMPDU_DROP:	STAT(ampdu_rx_drop);
638	case S_AMPDU_AGE:	STAT(ampdu_rx_age);
639	case S_AMPDU_STOP:	STAT(ampdu_stop);
640	case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
641	case S_ADDBA_REJECT:	STAT(addba_reject);
642	case S_ADDBA_NOREQUEST:	STAT(addba_norequest);
643	case S_ADDBA_BADTOKEN:	STAT(addba_badtoken);
644	case S_TX_BADSTATE:	STAT(tx_badstate);
645	case S_TX_NOTASSOC:	STAT(tx_notassoc);
646	case S_TX_CLASSIFY:	STAT(tx_classify);
647	case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
648	case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
649	case S_HT_ASSOC_NORATE:	STAT(ht_assoc_norate);
650	case S_INPUT:		NSTAT(rx_data);
651	case S_OUTPUT:		NSTAT(tx_data);
652	case S_RX_UCAST:	NSTAT(rx_ucast);
653	case S_RX_MCAST:	NSTAT(rx_mcast);
654	case S_TX_UCAST:	NSTAT(tx_ucast);
655	case S_TX_MCAST:	NSTAT(tx_mcast);
656	}
657	return wlan_getinfo(wf, s, b, bs);
658#undef NSTAT
659#undef STAT
660}
661
662static int
663wlan_get_totstat(struct statfoo *sf, int s, char b[], size_t bs)
664{
665	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
666#define	STAT(x) \
667	snprintf(b, bs, "%u", wf->total.is_##x); return 1
668#define	NSTAT(x) \
669	snprintf(b, bs, "%u", wf->ntotal.is_stats.ns_##x); return 1
670
671	switch (s) {
672	case S_RX_BADVERSION:	STAT(rx_badversion);
673	case S_RX_TOOSHORT:	STAT(rx_tooshort);
674	case S_RX_WRONGBSS:	STAT(rx_wrongbss);
675	case S_RX_DUP:	STAT(rx_dup);
676	case S_RX_WRONGDIR:	STAT(rx_wrongdir);
677	case S_RX_MCASTECHO:	STAT(rx_mcastecho);
678	case S_RX_NOTASSOC:	STAT(rx_notassoc);
679	case S_RX_NOPRIVACY:	STAT(rx_noprivacy);
680	case S_RX_UNENCRYPTED:	STAT(rx_unencrypted);
681	case S_RX_WEPFAIL:	STAT(rx_wepfail);
682	case S_RX_DECAP:	STAT(rx_decap);
683	case S_RX_MGTDISCARD:	STAT(rx_mgtdiscard);
684	case S_RX_CTL:		STAT(rx_ctl);
685	case S_RX_BEACON:	STAT(rx_beacon);
686	case S_RX_RSTOOBIG:	STAT(rx_rstoobig);
687	case S_RX_ELEM_MISSING:	STAT(rx_elem_missing);
688	case S_RX_ELEM_TOOBIG:	STAT(rx_elem_toobig);
689	case S_RX_ELEM_TOOSMALL:	STAT(rx_elem_toosmall);
690	case S_RX_ELEM_UNKNOWN:	STAT(rx_elem_unknown);
691	case S_RX_BADCHAN:	STAT(rx_badchan);
692	case S_RX_CHANMISMATCH:	STAT(rx_chanmismatch);
693	case S_RX_NODEALLOC:	STAT(rx_nodealloc);
694	case S_RX_SSIDMISMATCH:	STAT(rx_ssidmismatch);
695	case S_RX_AUTH_UNSUPPORTED:	STAT(rx_auth_unsupported);
696	case S_RX_AUTH_FAIL:	STAT(rx_auth_fail);
697	case S_RX_AUTH_COUNTERMEASURES:	STAT(rx_auth_countermeasures);
698	case S_RX_ASSOC_BSS:	STAT(rx_assoc_bss);
699	case S_RX_ASSOC_NOTAUTH:	STAT(rx_assoc_notauth);
700	case S_RX_ASSOC_CAPMISMATCH:	STAT(rx_assoc_capmismatch);
701	case S_RX_ASSOC_NORATE:	STAT(rx_assoc_norate);
702	case S_RX_ASSOC_BADWPAIE:	STAT(rx_assoc_badwpaie);
703	case S_RX_DEAUTH:	STAT(rx_deauth);
704	case S_RX_DISASSOC:	STAT(rx_disassoc);
705	case S_RX_BADSUBTYPE:	STAT(rx_badsubtype);
706	case S_RX_NOBUF:	STAT(rx_nobuf);
707	case S_RX_DECRYPTCRC:	STAT(rx_decryptcrc);
708	case S_RX_AHDEMO_MGT:	STAT(rx_ahdemo_mgt);
709	case S_RX_BAD_AUTH:	STAT(rx_bad_auth);
710	case S_RX_UNAUTH:	STAT(rx_unauth);
711	case S_RX_BADKEYID:	STAT(rx_badkeyid);
712	case S_RX_CCMPREPLAY:	STAT(rx_ccmpreplay);
713	case S_RX_CCMPFORMAT:	STAT(rx_ccmpformat);
714	case S_RX_CCMPMIC:	STAT(rx_ccmpmic);
715	case S_RX_TKIPREPLAY:	STAT(rx_tkipreplay);
716	case S_RX_TKIPFORMAT:	STAT(rx_tkipformat);
717	case S_RX_TKIPMIC:	STAT(rx_tkipmic);
718	case S_RX_TKIPICV:	STAT(rx_tkipicv);
719	case S_RX_BADCIPHER:	STAT(rx_badcipher);
720	case S_RX_NOCIPHERCTX:	STAT(rx_nocipherctx);
721	case S_RX_ACL:		STAT(rx_acl);
722	case S_TX_NOBUF:	STAT(tx_nobuf);
723	case S_TX_NONODE:	STAT(tx_nonode);
724	case S_TX_UNKNOWNMGT:	STAT(tx_unknownmgt);
725	case S_TX_BADCIPHER:	STAT(tx_badcipher);
726	case S_TX_NODEFKEY:	STAT(tx_nodefkey);
727	case S_TX_NOHEADROOM:	STAT(tx_noheadroom);
728	case S_TX_FRAGFRAMES:	STAT(tx_fragframes);
729	case S_TX_FRAGS:	STAT(tx_frags);
730	case S_SCAN_ACTIVE:	STAT(scan_active);
731	case S_SCAN_PASSIVE:	STAT(scan_passive);
732	case S_NODE_TIMEOUT:	STAT(node_timeout);
733	case S_CRYPTO_NOMEM:	STAT(crypto_nomem);
734	case S_CRYPTO_TKIP:	STAT(crypto_tkip);
735	case S_CRYPTO_TKIPENMIC:	STAT(crypto_tkipenmic);
736	case S_CRYPTO_TKIPDEMIC:	STAT(crypto_tkipdemic);
737	case S_CRYPTO_TKIPCM:	STAT(crypto_tkipcm);
738	case S_CRYPTO_CCMP:	STAT(crypto_ccmp);
739	case S_CRYPTO_WEP:	STAT(crypto_wep);
740	case S_CRYPTO_SETKEY_CIPHER:	STAT(crypto_setkey_cipher);
741	case S_CRYPTO_SETKEY_NOKEY:	STAT(crypto_setkey_nokey);
742	case S_CRYPTO_DELKEY:	STAT(crypto_delkey);
743	case S_CRYPTO_BADCIPHER:	STAT(crypto_badcipher);
744	case S_CRYPTO_NOCIPHER:	STAT(crypto_nocipher);
745	case S_CRYPTO_ATTACHFAIL:	STAT(crypto_attachfail);
746	case S_CRYPTO_SWFALLBACK:	STAT(crypto_swfallback);
747	case S_CRYPTO_KEYFAIL:	STAT(crypto_keyfail);
748	case S_CRYPTO_ENMICFAIL:	STAT(crypto_enmicfail);
749	case S_IBSS_CAPMISMATCH:	STAT(ibss_capmismatch);
750	case S_IBSS_NORATE:	STAT(ibss_norate);
751	case S_PS_UNASSOC:	STAT(ps_unassoc);
752	case S_PS_BADAID:	STAT(ps_badaid);
753	case S_PS_QEMPTY:	STAT(ps_qempty);
754	case S_FF_BADHDR:	STAT(ff_badhdr);
755	case S_FF_TOOSHORT:	STAT(ff_tooshort);
756	case S_FF_SPLIT:	STAT(ff_split);
757	case S_FF_DECAP:	STAT(ff_decap);
758	case S_FF_ENCAP:	STAT(ff_encap);
759	case S_RX_BADBINTVAL:	STAT(rx_badbintval);
760	case S_RX_MGMT:		STAT(rx_mgmt);
761	case S_RX_DEMICFAIL:	STAT(rx_demicfail);
762	case S_RX_DEFRAG:	STAT(rx_defrag);
763	case S_RX_ACTION:	STAT(rx_action);
764	case S_AMSDU_TOOSHORT:	STAT(amsdu_tooshort);
765	case S_AMSDU_SPLIT:	STAT(amsdu_split);
766	case S_AMSDU_DECAP:	STAT(amsdu_decap);
767	case S_AMSDU_ENCAP:	STAT(amsdu_encap);
768	case S_AMPDU_REORDER:	STAT(ampdu_rx_reorder);
769	case S_AMPDU_FLUSH:	STAT(ampdu_rx_flush);
770	case S_AMPDU_BARBAD:	STAT(ampdu_bar_bad);
771	case S_AMPDU_BAROOW:	STAT(ampdu_bar_oow);
772	case S_AMPDU_BARMOVE:	STAT(ampdu_bar_move);
773	case S_AMPDU_BAR:	STAT(ampdu_bar_rx);
774	case S_AMPDU_MOVE:	STAT(ampdu_rx_move);
775	case S_AMPDU_OOR:	STAT(ampdu_rx_oor);
776	case S_AMPDU_COPY:	STAT(ampdu_rx_copy);
777	case S_AMPDU_DROP:	STAT(ampdu_rx_drop);
778	case S_AMPDU_AGE:	STAT(ampdu_rx_age);
779	case S_AMPDU_STOP:	STAT(ampdu_stop);
780	case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
781	case S_ADDBA_REJECT:	STAT(addba_reject);
782	case S_ADDBA_NOREQUEST:	STAT(addba_norequest);
783	case S_ADDBA_BADTOKEN:	STAT(addba_badtoken);
784	case S_TX_BADSTATE:	STAT(tx_badstate);
785	case S_TX_NOTASSOC:	STAT(tx_notassoc);
786	case S_TX_CLASSIFY:	STAT(tx_classify);
787	case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
788	case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
789	case S_HT_ASSOC_NORATE:	STAT(ht_assoc_norate);
790	case S_INPUT:		NSTAT(rx_data);
791	case S_OUTPUT:		NSTAT(tx_data);
792	case S_RX_UCAST:	NSTAT(rx_ucast);
793	case S_RX_MCAST:	NSTAT(rx_mcast);
794	case S_TX_UCAST:	NSTAT(tx_ucast);
795	case S_TX_MCAST:	NSTAT(tx_mcast);
796	}
797	return wlan_getinfo(wf, s, b, bs);
798#undef NSTAT
799#undef STAT
800}
801
802STATFOO_DEFINE_BOUNCE(wlanstatfoo)
803
804struct wlanstatfoo *
805wlanstats_new(const char *ifname, const char *fmtstring)
806{
807#define	N(a)	(sizeof(a) / sizeof(a[0]))
808	struct wlanstatfoo_p *wf;
809
810	wf = calloc(1, sizeof(struct wlanstatfoo_p));
811	if (wf != NULL) {
812		statfoo_init(&wf->base.base, "wlanstats", wlanstats, N(wlanstats));
813		/* override base methods */
814		wf->base.base.collect_cur = wlan_collect_cur;
815		wf->base.base.collect_tot = wlan_collect_tot;
816		wf->base.base.get_curstat = wlan_get_curstat;
817		wf->base.base.get_totstat = wlan_get_totstat;
818		wf->base.base.update_tot = wlan_update_tot;
819
820		/* setup bounce functions for public methods */
821		STATFOO_BOUNCE(wf, wlanstatfoo);
822
823		/* setup our public methods */
824		wf->base.setifname = wlan_setifname;
825		wf->base.getifname = wlan_getifname;
826		wf->base.getopmode = wlan_getopmode;
827		wf->base.setstamac = wlan_setstamac;
828		wf->opmode = -1;
829
830		wf->s = socket(AF_INET, SOCK_DGRAM, 0);
831		if (wf->s < 0)
832			err(1, "socket");
833
834		wlan_setifname(&wf->base, ifname);
835		wf->base.setfmt(&wf->base, fmtstring);
836	}
837	return &wf->base;
838#undef N
839}
840