xref: /freebsd/tools/tools/net80211/wlanstats/wlanstats.c (revision 19261079b74319502c6ffa1249920079f0f69a72)
1 /*-
2  * Copyright (c) 2002-2007 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  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * net80211 statistics class.
34  */
35 
36 #include <sys/param.h>
37 #include <sys/file.h>
38 #include <sys/sockio.h>
39 #include <sys/socket.h>
40 
41 #include <net/if.h>
42 #include <net/if_dl.h>
43 #include <net/if_media.h>
44 #include <net/if_var.h>
45 #include <net/ethernet.h>
46 
47 #include <err.h>
48 #include <ifaddrs.h>
49 #include <signal.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54 
55 #include "../../../../sys/net80211/ieee80211_ioctl.h"
56 
57 #include "wlanstats.h"
58 
59 #ifndef IEEE80211_ADDR_COPY
60 #define	IEEE80211_ADDR_COPY(dst, src)	memcpy(dst, src, IEEE80211_ADDR_LEN)
61 #define	IEEE80211_ADDR_EQ(a1,a2)	(memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)
62 #endif
63 
64 #define	AFTER(prev)	((prev)+1)
65 
66 static const struct fmt wlanstats[] = {
67 #define	S_RX_BADVERSION		0
68 	{ 5,  "rx_badversion",	"bvers",	"rx frame with bad version" },
69 #define	S_RX_TOOSHORT		AFTER(S_RX_BADVERSION)
70 	{ 5,  "rx_tooshort",	"2short",	"rx frame too short" },
71 #define	S_RX_WRONGBSS		AFTER(S_RX_TOOSHORT)
72 	{ 5,  "rx_wrongbss",	"wrbss",	"rx from wrong bssid" },
73 #define	S_RX_DUP		AFTER(S_RX_WRONGBSS)
74 	{ 5,  "rx_dup",		"rxdup",	"rx discard 'cuz dup" },
75 #define	S_RX_WRONGDIR		AFTER(S_RX_DUP)
76 	{ 5,  "rx_wrongdir",	"wrdir",	"rx w/ wrong direction" },
77 #define	S_RX_MCASTECHO		AFTER(S_RX_WRONGDIR)
78 	{ 5,  "rx_mcastecho",	"mecho",	"rx discard 'cuz mcast echo" },
79 #define	S_RX_NOTASSOC		AFTER(S_RX_MCASTECHO)
80 	{ 6,  "rx_notassoc",	"!assoc",	"rx discard 'cuz sta !assoc" },
81 #define	S_RX_NOPRIVACY		AFTER(S_RX_NOTASSOC)
82 	{ 6,  "rx_noprivacy",	"nopriv",	"rx w/ wep but privacy off" },
83 #define	S_RX_UNENCRYPTED	AFTER(S_RX_NOPRIVACY)
84 	{ 6,  "rx_unencrypted",	"unencr",	"rx w/o wep and privacy on" },
85 #define	S_RX_WEPFAIL		AFTER(S_RX_UNENCRYPTED)
86 	{ 7,  "rx_wepfail",	"wepfail",	"rx wep processing failed" },
87 #define	S_RX_DECAP		AFTER(S_RX_WEPFAIL)
88 	{ 5,  "rx_decap",	"decap",	"rx decapsulation failed" },
89 #define	S_RX_MGTDISCARD		AFTER(S_RX_DECAP)
90 	{ 8,  "rx_mgtdiscard",	"mgtdiscard",	"rx discard mgt frames" },
91 #define	S_RX_CTL		AFTER(S_RX_MGTDISCARD)
92 	{ 5,  "rx_ctl",		"ctl",		"rx ctrl frames" },
93 #define	S_RX_BEACON		AFTER(S_RX_CTL)
94 	{ 6,  "rx_beacon",	"beacon",	"rx beacon frames" },
95 #define	S_RX_RSTOOBIG		AFTER(S_RX_BEACON)
96 	{ 6,  "rx_rstoobig",	"rs2big",	"rx rate set truncated" },
97 #define	S_RX_ELEM_MISSING	AFTER(S_RX_RSTOOBIG)
98 	{ 6,  "rx_elem_missing","iemiss",	"rx required element missing" },
99 #define	S_RX_ELEM_TOOBIG	AFTER(S_RX_ELEM_MISSING)
100 	{ 6,  "rx_elem_toobig",	"ie2big",	"rx element too big" },
101 #define	S_RX_ELEM_TOOSMALL	AFTER(S_RX_ELEM_TOOBIG)
102 	{ 7,  "rx_elem_toosmall","ie2small","rx element too small" },
103 #define	S_RX_ELEM_UNKNOWN 	AFTER(S_RX_ELEM_TOOSMALL)
104 	{ 5,  "rx_elem_unknown","ieunk",	"rx element unknown" },
105 #define	S_RX_BADCHAN		AFTER(S_RX_ELEM_UNKNOWN)
106 	{ 6,  "rx_badchan",	"badchan",	"rx frame w/ invalid chan" },
107 #define	S_RX_CHANMISMATCH	AFTER(S_RX_BADCHAN)
108 	{ 5,  "rx_chanmismatch","chanmismatch",	"rx frame chan mismatch" },
109 #define	S_RX_NODEALLOC		AFTER(S_RX_CHANMISMATCH)
110 	{ 5,  "rx_nodealloc",	"nodealloc",	"nodes allocated (rx)" },
111 #define	S_RX_SSIDMISMATCH	AFTER(S_RX_NODEALLOC)
112 	{ 5,  "rx_ssidmismatch","ssidmismatch",	"rx frame ssid mismatch" },
113 #define	S_RX_AUTH_UNSUPPORTED	AFTER(S_RX_SSIDMISMATCH)
114 	{ 5,  "rx_auth_unsupported","auth_unsupported",
115 		"rx w/ unsupported auth alg" },
116 #define	S_RX_AUTH_FAIL		AFTER(S_RX_AUTH_UNSUPPORTED)
117 	{ 5,  "rx_auth_fail",	"auth_fail",	"rx sta auth failure" },
118 #define	S_RX_AUTH_FAIL_CODE	AFTER(S_RX_AUTH_FAIL)
119 	{ 5,  "rx_auth_fail_code","auth_fail_code",
120 		"last rx auth failure reason" },
121 #define	S_RX_AUTH_COUNTERMEASURES	AFTER(S_RX_AUTH_FAIL_CODE)
122 	{ 5,  "rx_auth_countermeasures",	"auth_countermeasures",
123 		"rx sta auth failure 'cuz of TKIP countermeasures" },
124 #define	S_RX_ASSOC_BSS		AFTER(S_RX_AUTH_COUNTERMEASURES)
125 	{ 5,  "rx_assoc_bss",	"assoc_bss",	"rx assoc from wrong bssid" },
126 #define	S_RX_ASSOC_NOTAUTH	AFTER(S_RX_ASSOC_BSS)
127 	{ 5,  "rx_assoc_notauth","assoc_notauth",	"rx assoc w/o auth" },
128 #define	S_RX_ASSOC_CAPMISMATCH	AFTER(S_RX_ASSOC_NOTAUTH)
129 	{ 5,  "rx_assoc_capmismatch","assoc_capmismatch",
130 		"rx assoc w/ cap mismatch" },
131 #define	S_RX_ASSOC_NORATE	AFTER(S_RX_ASSOC_CAPMISMATCH)
132 	{ 5,  "rx_assoc_norate","assoc_norate",	"rx assoc w/ no rate match" },
133 #define	S_RX_ASSOC_BADWPAIE	AFTER(S_RX_ASSOC_NORATE)
134 	{ 5,  "rx_assoc_badwpaie","assoc_badwpaie",
135 		"rx assoc w/ bad WPA IE" },
136 #define	S_RX_DEAUTH		AFTER(S_RX_ASSOC_BADWPAIE)
137 	{ 5,  "rx_deauth",	"deauth",	"rx deauthentication" },
138 #define	S_RX_DEAUTH_CODE	AFTER(S_RX_DEAUTH)
139 	{ 5,  "rx_deauth_code","deauth_code",	"last rx deauth reason" },
140 #define	S_RX_DISASSOC		AFTER(S_RX_DEAUTH_CODE)
141 	{ 5,  "rx_disassoc",	"disassoc",	"rx disassociation" },
142 #define	S_RX_DISASSOC_CODE	AFTER(S_RX_DISASSOC)
143 	{ 5,  "rx_disassoc_code","disassoc_code",
144 		"last rx disassoc reason" },
145 #define	S_BMISS			AFTER(S_RX_DISASSOC_CODE)
146 	{ 5,  "bmiss",		"bmiss",	"beacon miss events handled" },
147 #define	S_RX_BADSUBTYPE		AFTER(S_BMISS)
148 	{ 5,  "rx_badsubtype",	"badsubtype",	"rx frame w/ unknown subtype" },
149 #define	S_RX_NOBUF		AFTER(S_RX_BADSUBTYPE)
150 	{ 5,  "rx_nobuf",	"nobuf",	"rx failed for lack of mbuf" },
151 #define	S_RX_DECRYPTCRC		AFTER(S_RX_NOBUF)
152 	{ 5,  "rx_decryptcrc",	"decryptcrc",	"rx decrypt failed on crc" },
153 #define	S_RX_AHDEMO_MGT		AFTER(S_RX_DECRYPTCRC)
154 	{ 5,  "rx_ahdemo_mgt",	"ahdemo_mgt",
155 		"rx discard mgmt frame received in ahdoc demo mode" },
156 #define	S_RX_BAD_AUTH		AFTER(S_RX_AHDEMO_MGT)
157 	{ 5,  "rx_bad_auth",	"bad_auth",	"rx bad authentication request" },
158 #define	S_RX_UNAUTH		AFTER(S_RX_BAD_AUTH)
159 	{ 5,  "rx_unauth",	"unauth",
160 		"rx discard 'cuz port unauthorized" },
161 #define	S_RX_BADKEYID		AFTER(S_RX_UNAUTH)
162 	{ 5,  "rx_badkeyid",	"rxkid",	"rx w/ incorrect keyid" },
163 #define	S_RX_CCMPREPLAY		AFTER(S_RX_BADKEYID)
164 	{ 5,  "rx_ccmpreplay",	"ccmpreplay",	"rx seq# violation (CCMP)" },
165 #define	S_RX_CCMPFORMAT		AFTER(S_RX_CCMPREPLAY)
166 	{ 5,  "rx_ccmpformat",	"ccmpformat",	"rx format bad (CCMP)" },
167 #define	S_RX_CCMPMIC		AFTER(S_RX_CCMPFORMAT)
168 	{ 5,  "rx_ccmpmic",	"ccmpmic",	"rx MIC check failed (CCMP)" },
169 #define	S_RX_TKIPREPLAY		AFTER(S_RX_CCMPMIC)
170 	{ 5,  "rx_tkipreplay",	"tkipreplay",	"rx seq# violation (TKIP)" },
171 #define	S_RX_TKIPFORMAT		AFTER(S_RX_TKIPREPLAY)
172 	{ 5,  "rx_tkipformat",	"tkipformat",	"rx format bad (TKIP)" },
173 #define	S_RX_TKIPMIC		AFTER(S_RX_TKIPFORMAT)
174 	{ 5,  "rx_tkipmic",	"tkipmic",	"rx MIC check failed (TKIP)" },
175 #define	S_RX_TKIPICV		AFTER(S_RX_TKIPMIC)
176 	{ 5,  "rx_tkipicv",	"tkipicv",	"rx ICV check failed (TKIP)" },
177 #define	S_RX_BADCIPHER		AFTER(S_RX_TKIPICV)
178 	{ 5,  "rx_badcipher",	"badcipher",	"rx failed 'cuz bad cipher/key type" },
179 #define	S_RX_NOCIPHERCTX	AFTER(S_RX_BADCIPHER)
180 	{ 5,  "rx_nocipherctx",	"nocipherctx",	"rx failed 'cuz key/cipher ctx not setup" },
181 #define	S_RX_ACL		AFTER(S_RX_NOCIPHERCTX)
182 	{ 5,  "rx_acl",		"acl",		"rx discard 'cuz acl policy" },
183 #define	S_TX_NOBUF		AFTER(S_RX_ACL)
184 	{ 5,  "tx_nobuf",	"nobuf",	"tx failed for lack of mbuf" },
185 #define	S_TX_NONODE		AFTER(S_TX_NOBUF)
186 	{ 5,  "tx_nonode",	"nonode",	"tx failed for no node" },
187 #define	S_TX_UNKNOWNMGT		AFTER(S_TX_NONODE)
188 	{ 5,  "tx_unknownmgt",	"unknownmgt",	"tx of unknown mgt frame" },
189 #define	S_TX_BADCIPHER		AFTER(S_TX_UNKNOWNMGT)
190 	{ 5,  "tx_badcipher",	"badcipher",	"tx failed 'cuz bad ciper/key type" },
191 #define	S_TX_NODEFKEY		AFTER(S_TX_BADCIPHER)
192 	{ 5,  "tx_nodefkey",	"nodefkey",	"tx failed 'cuz no defkey" },
193 #define	S_TX_NOHEADROOM		AFTER(S_TX_NODEFKEY)
194 	{ 5,  "tx_noheadroom",	"noheadroom",	"tx failed 'cuz no space for crypto hdrs" },
195 #define	S_TX_FRAGFRAMES		AFTER(S_TX_NOHEADROOM)
196 	{ 5,  "tx_fragframes",	"fragframes",	"tx frames fragmented" },
197 #define	S_TX_FRAGS		AFTER(S_TX_FRAGFRAMES)
198 	{ 5,  "tx_frags",	"frags",		"tx frags generated" },
199 #define	S_SCAN_ACTIVE		AFTER(S_TX_FRAGS)
200 	{ 5,  "scan_active",	"ascan",	"active scans started" },
201 #define	S_SCAN_PASSIVE		AFTER(S_SCAN_ACTIVE)
202 	{ 5,  "scan_passive",	"pscan",	"passive scans started" },
203 #define	S_SCAN_BG		AFTER(S_SCAN_PASSIVE)
204 	{ 5,  "scan_bg",	"bgscn",	"background scans started" },
205 #define	S_NODE_TIMEOUT		AFTER(S_SCAN_BG)
206 	{ 5,  "node_timeout",	"node_timeout",	"nodes timed out for inactivity" },
207 #define	S_CRYPTO_NOMEM		AFTER(S_NODE_TIMEOUT)
208 	{ 5,  "crypto_nomem",	"crypto_nomem",	"cipher context malloc failed" },
209 #define	S_CRYPTO_TKIP		AFTER(S_CRYPTO_NOMEM)
210 	{ 5,  "crypto_tkip",	"crypto_tkip",	"tkip crypto done in s/w" },
211 #define	S_CRYPTO_TKIPENMIC	AFTER(S_CRYPTO_TKIP)
212 	{ 5,  "crypto_tkipenmic","crypto_tkipenmic",	"tkip tx MIC done in s/w" },
213 #define	S_CRYPTO_TKIPDEMIC	AFTER(S_CRYPTO_TKIPENMIC)
214 	{ 5,  "crypto_tkipdemic","crypto_tkipdemic",	"tkip rx MIC done in s/w" },
215 #define	S_CRYPTO_TKIPCM		AFTER(S_CRYPTO_TKIPDEMIC)
216 	{ 5,  "crypto_tkipcm",	"crypto_tkipcm",	"tkip dropped frames 'cuz of countermeasures" },
217 #define	S_CRYPTO_CCMP		AFTER(S_CRYPTO_TKIPCM)
218 	{ 5,  "crypto_ccmp",	"crypto_ccmp",	"ccmp crypto done in s/w" },
219 #define	S_CRYPTO_WEP		AFTER(S_CRYPTO_CCMP)
220 	{ 5,  "crypto_wep",	"crypto_wep",	"wep crypto done in s/w" },
221 #define	S_CRYPTO_SETKEY_CIPHER	AFTER(S_CRYPTO_WEP)
222 	{ 5,  "crypto_setkey_cipher",	"crypto_setkey_cipher","setkey failed 'cuz cipher rejected data" },
223 #define	S_CRYPTO_SETKEY_NOKEY	AFTER(S_CRYPTO_SETKEY_CIPHER)
224 	{ 5,  "crypto_setkey_nokey",	"crypto_setkey_nokey","setkey failed 'cuz no key index" },
225 #define	S_CRYPTO_DELKEY		AFTER(S_CRYPTO_SETKEY_NOKEY)
226 	{ 5,  "crypto_delkey",	"crypto_delkey",	"driver key delete failed" },
227 #define	S_CRYPTO_BADCIPHER	AFTER(S_CRYPTO_DELKEY)
228 	{ 5,  "crypto_badcipher","crypto_badcipher",	"setkey failed 'cuz unknown cipher" },
229 #define	S_CRYPTO_NOCIPHER	AFTER(S_CRYPTO_BADCIPHER)
230 	{ 5,  "crypto_nocipher","crypto_nocipher",	"setkey failed 'cuz cipher module unavailable" },
231 #define	S_CRYPTO_ATTACHFAIL	AFTER(S_CRYPTO_NOCIPHER)
232 	{ 5,  "crypto_attachfail","crypto_attachfail",	"setkey failed 'cuz cipher attach failed" },
233 #define	S_CRYPTO_SWFALLBACK	AFTER(S_CRYPTO_ATTACHFAIL)
234 	{ 5,  "crypto_swfallback","crypto_swfallback",	"crypto fell back to s/w implementation" },
235 #define	S_CRYPTO_KEYFAIL	AFTER(S_CRYPTO_SWFALLBACK)
236 	{ 5,  "crypto_keyfail",	"crypto_keyfail",	"setkey failed 'cuz driver key alloc failed" },
237 #define	S_CRYPTO_ENMICFAIL	AFTER(S_CRYPTO_KEYFAIL)
238 	{ 5,  "crypto_enmicfail","crypto_enmicfail",	"enmic failed (may be mbuf exhaustion)" },
239 #define	S_IBSS_CAPMISMATCH	AFTER(S_CRYPTO_ENMICFAIL)
240 	{ 5,  "ibss_capmismatch","ibss_capmismatch",	"ibss merge faied 'cuz capabilities mismatch" },
241 #define	S_IBSS_NORATE		AFTER(S_IBSS_CAPMISMATCH)
242 	{ 5,  "ibss_norate",	"ibss_norate",	"ibss merge faied 'cuz rate set mismatch" },
243 #define	S_PS_UNASSOC		AFTER(S_IBSS_NORATE)
244 	{ 5,  "ps_unassoc",	"ps_unassoc",	"ps-poll received for unassociated station" },
245 #define	S_PS_BADAID		AFTER(S_PS_UNASSOC)
246 	{ 5,  "ps_badaid",	"ps_badaid",	"ps-poll received with invalid association id" },
247 #define	S_PS_QEMPTY		AFTER(S_PS_BADAID)
248 	{ 5,  "ps_qempty",	"ps_qempty",	"ps-poll received with nothing to send" },
249 #define	S_FF_BADHDR		AFTER(S_PS_QEMPTY)
250 	{ 5,  "ff_badhdr",	"ff_badhdr",	"fast frame rx'd w/ bad hdr" },
251 #define	S_FF_TOOSHORT		AFTER(S_FF_BADHDR)
252 	{ 5,  "ff_tooshort",	"ff_tooshort",	"fast frame rx decap error" },
253 #define	S_FF_SPLIT		AFTER(S_FF_TOOSHORT)
254 	{ 5,  "ff_split",	"ff_split",	"fast frame rx split error" },
255 #define	S_FF_DECAP		AFTER(S_FF_SPLIT)
256 	{ 5,  "ff_decap",	"ff_decap",	"fast frames decap'd" },
257 #define	S_FF_ENCAP		AFTER(S_FF_DECAP)
258 	{ 5,  "ff_encap",	"ff_encap",	"fast frames encap'd for tx" },
259 #define	S_FF_ENCAPFAIL		AFTER(S_FF_ENCAP)
260 	{ 5,  "ff_encapfail",	"ff_encapfail",	"fast frames encap failed" },
261 #define	S_RX_BADBINTVAL		AFTER(S_FF_ENCAPFAIL)
262 	{ 5,  "rx_badbintval",	"rx_badbintval","rx frame with bogus beacon interval" },
263 #define	S_RX_MGMT		AFTER(S_RX_BADBINTVAL)
264 	{ 8,  "rx_mgmt",	"mgmt",		"rx management frames" },
265 #define	S_RX_DEMICFAIL		AFTER(S_RX_MGMT)
266 	{ 5,  "rx_demicfail",	"rx_demicfail",	"rx demic failed" },
267 #define	S_RX_DEFRAG		AFTER(S_RX_DEMICFAIL)
268 	{ 5,  "rx_defrag",	"rx_defrag",	"rx defragmentation failed" },
269 #define	S_RX_ACTION		AFTER(S_RX_DEFRAG)
270 	{ 5,  "rx_action",	"rx_action",	"rx action frames" },
271 #define	S_AMSDU_TOOSHORT	AFTER(S_RX_ACTION)
272 	{ 8,  "amsdu_tooshort",	"tooshort","A-MSDU rx decap error" },
273 #define	S_AMSDU_SPLIT		AFTER(S_AMSDU_TOOSHORT)
274 	{ 8,  "amsdu_split",	"split",	"A-MSDU rx failed on frame split" },
275 #define	S_AMSDU_DECAP		AFTER(S_AMSDU_SPLIT)
276 	{ 8,  "amsdu_decap",	"decap",	"A-MSDU frames received" },
277 #define	S_AMSDU_ENCAP		AFTER(S_AMSDU_DECAP)
278 	{ 8,  "amsdu_encap",	"encap",	"A-MSDU frames transmitted" },
279 #define	S_AMSDU_RX_MORE		AFTER(S_AMSDU_ENCAP)
280 	{ 13,  "rx_amsdu_more",	"rx_amsdu_more",	"A-MSDU HW intermediary decap'ed received" },
281 #define	S_AMSDU_RX_MORE_END		AFTER(S_AMSDU_RX_MORE)
282 	{ 17,  "rx_amsdu_more_end",	"rx_amsdu_more_end",	"A-MSDU HW end decap'ed received" },
283 #define	S_AMPDU_REORDER		AFTER(S_AMSDU_RX_MORE_END)
284 	{ 8,  "ampdu_reorder",	"reorder","A-MPDU frames held in reorder q" },
285 #define	S_AMPDU_FLUSH		AFTER(S_AMPDU_REORDER)
286 	{ 8,  "ampdu_flush",	"flush",	"A-MPDU frames sent up from reorder q" },
287 #define	S_AMPDU_BARBAD		AFTER(S_AMPDU_FLUSH)
288 	{ 6,  "ampdu_barbad",	"barbad",	"A-MPDU BAR rx before ADDBA exchange (or disabled with net.link.ieee80211)" },
289 #define	S_AMPDU_BAROOW		AFTER(S_AMPDU_BARBAD)
290 	{ 6,  "ampdu_baroow",	"baroow",	"A-MPDU BAR rx out of BA window" },
291 #define	S_AMPDU_BARMOVE		AFTER(S_AMPDU_BAROOW)
292 	{ 8,  "ampdu_barmove",	"barmove","A-MPDU BAR rx moved BA window" },
293 #define	S_AMPDU_BAR		AFTER(S_AMPDU_BARMOVE)
294 	{ 8,  "ampdu_bar",	"rxbar",	"A-MPDU BAR rx successful" },
295 #define	S_AMPDU_MOVE		AFTER(S_AMPDU_BAR)
296 	{ 5,  "ampdu_move",	"move",	"A-MPDU frame moved BA window" },
297 #define	S_AMPDU_OOR		AFTER(S_AMPDU_MOVE)
298 	{ 8,  "ampdu_oor",	"oorx",	"A-MPDU frames rx out-of-order" },
299 #define	S_AMPDU_COPY		AFTER(S_AMPDU_OOR)
300 	{ 8,  "ampdu_copy",	"copy",	"A-MPDU rx window slots copied" },
301 #define	S_AMPDU_DROP		AFTER(S_AMPDU_COPY)
302 	{ 5,  "ampdu_drop",	"drop",	"A-MPDU frames discarded for out of range seqno" },
303 #define	S_AMPDU_AGE		AFTER(S_AMPDU_DROP)
304 	{ 5,  "ampdu_age",	"age",	"A-MPDU frames sent up due to old age" },
305 #define	S_AMPDU_STOP		AFTER(S_AMPDU_AGE)
306 	{ 5,  "ampdu_stop",	"stop",	"A-MPDU streams stopped" },
307 #define	S_AMPDU_STOP_FAILED	AFTER(S_AMPDU_STOP)
308 	{ 5,  "ampdu_stop_failed","!stop",	"A-MPDU stop requests failed 'cuz stream not running" },
309 #define	S_ADDBA_REJECT		AFTER(S_AMPDU_STOP_FAILED)
310 	{ 5,  "addba_reject",	"reject",	"ADDBA requests rejected 'cuz A-MPDU rx is disabled" },
311 #define	S_ADDBA_NOREQUEST	AFTER(S_ADDBA_REJECT)
312 	{ 5,  "addba_norequest","norequest","ADDBA response frames discarded because no ADDBA request was pending" },
313 #define	S_ADDBA_BADTOKEN	AFTER(S_ADDBA_NOREQUEST)
314 	{ 5,  "addba_badtoken",	"badtoken","ADDBA response frames discarded 'cuz rx'd dialog token is wrong" },
315 #define	S_TX_BADSTATE		AFTER(S_ADDBA_BADTOKEN)
316 	{ 4,  "tx_badstate",	"badstate",	"tx failed 'cuz vap not in RUN state" },
317 #define	S_TX_NOTASSOC		AFTER(S_TX_BADSTATE)
318 	{ 4,  "tx_notassoc",	"notassoc",	"tx failed 'cuz dest sta not associated" },
319 #define	S_TX_CLASSIFY		AFTER(S_TX_NOTASSOC)
320 	{ 4,  "tx_classify",	"classify",	"tx packet classification failed" },
321 #define	S_DWDS_MCAST		AFTER(S_TX_CLASSIFY)
322 	{ 8,  "dwds_mcast",	"dwds_mcast",	"mcast frame transmitted on dwds vap discarded" },
323 #define	S_DWDS_QDROP		AFTER(S_DWDS_MCAST)
324 	{ 8,  "dwds_qdrop",	"dwds_qdrop",	"4-address frame discarded because dwds pending queue is full" },
325 #define	S_HT_ASSOC_NOHTCAP	AFTER(S_DWDS_QDROP)
326 	{ 4,  "ht_nohtcap",	"ht_nohtcap",	"non-HT station rejected in HT-only BSS" },
327 #define	S_HT_ASSOC_DOWNGRADE	AFTER(S_HT_ASSOC_NOHTCAP)
328 	{ 4,  "ht_downgrade",	"ht_downgrade",	"HT station downgraded to legacy operation" },
329 #define	S_HT_ASSOC_NORATE	AFTER(S_HT_ASSOC_DOWNGRADE)
330 	{ 4,  "ht_norate",	"ht_norate",	"HT station rejected because of HT rate set" },
331 #define	S_MESH_WRONGMESH	AFTER(S_HT_ASSOC_NORATE)
332 	{ 4,  "mesh_wrong",	"mesh_wrong",	"frame discarded because sender not a mesh sta" },
333 #define	S_MESH_NOLINK		AFTER(S_MESH_WRONGMESH)
334 	{ 4,  "mesh_nolink",	"mesh_nolink",	"frame discarded because link not established" },
335 #define	S_MESH_FWD_TTL		AFTER(S_MESH_NOLINK)
336 	{ 4,  "mesh_fwd_ttl",	"mesh_fwd_ttl",	"frame not forwarded because TTL zero" },
337 #define	S_MESH_FWD_NOBUF	AFTER(S_MESH_FWD_TTL)
338 	{ 4,  "mesh_fwd_nobuf",	"mesh_fwd_nobuf",	"frame not forwarded because mbuf could not be allocated" },
339 #define	S_MESH_FWD_TOOSHORT	AFTER(S_MESH_FWD_NOBUF)
340 	{ 4,  "mesh_fwd_tooshort",	"mesh_fwd_tooshort",	"frame not forwarded because too short to have 802.11 header" },
341 #define	S_MESH_FWD_DISABLED	AFTER(S_MESH_FWD_TOOSHORT)
342 	{ 4,  "mesh_fwd_disabled",	"mesh_fwd_disabled",	"frame not forwarded because administratively disabled" },
343 #define	S_MESH_FWD_NOPATH	AFTER(S_MESH_FWD_DISABLED)
344 	{ 4,  "mesh_fwd_nopath",	"mesh_fwd_nopath",	"frame not forwarded because no path found to destination" },
345 #define	S_HWMP_WRONGSEQ		AFTER(S_MESH_FWD_NOPATH)
346 	{ 4,  "hwmp_wrongseq",	"hwmp_wrongseq",	"frame discarded because mesh sequence number is invalid" },
347 #define	S_HWMP_ROOTREQS		AFTER(S_HWMP_WRONGSEQ)
348 	{ 4,  "hwmp_rootreqs",	"hwmp_rootreqs",	"root PREQ frames sent" },
349 #define	S_HWMP_ROOTANN		AFTER(S_HWMP_ROOTREQS)
350 	{ 4,  "hwmp_rootann",	"hwmp_rootann",	"root RANN frames received" },
351 #define	S_MESH_BADAE		AFTER(S_HWMP_ROOTANN)
352 	{ 4,  "mesh_badae",	"mesh_badae",	"frame discarded for bad AddressExtension (AE)" },
353 #define	S_MESH_RTADDFAILED	AFTER(S_MESH_BADAE)
354 	{ 4,  "mesh_rtadd",	"mesh_rtadd",	"mesh route add failed" },
355 #define	S_MESH_NOTPROXY		AFTER(S_MESH_RTADDFAILED)
356 	{ 8,  "mesh_notproxy",	"mesh_notproxy","frame discarded because station not acting as a proxy" },
357 #define	S_RX_BADALIGN		AFTER(S_MESH_NOTPROXY)
358 	{ 4,  "rx_badalign",	"rx_badalign","frame discarded because payload re-alignment failed" },
359 #define	S_INPUT			AFTER(S_RX_BADALIGN)
360 	{ 8,	"input",	"input",	"total data frames received" },
361 #define	S_RX_UCAST		AFTER(S_INPUT)
362 	{ 8,	"rx_ucast",	"rx_ucast",	"unicast data frames received" },
363 #define	S_RX_MCAST		AFTER(S_RX_UCAST)
364 	{ 8,	"rx_mcast",	"rx_mcast",	"multicast data frames received" },
365 #define	S_OUTPUT		AFTER(S_RX_MCAST)
366 	{ 8,	"output",	"output",	"total data frames transmit" },
367 #define	S_TX_UCAST		AFTER(S_OUTPUT)
368 	{ 8,	"tx_ucast",	"tx_ucast",	"unicast data frames sent" },
369 #define	S_TX_MCAST		AFTER(S_TX_UCAST)
370 	{ 8,	"tx_mcast",	"tx_mcast",	"multicast data frames sent" },
371 #define	S_RATE			AFTER(S_TX_MCAST)
372 	{ 7,	"rate",		"rate",		"current transmit rate" },
373 #define	S_RSSI			AFTER(S_RATE)
374 	{ 6,	"rssi",		"rssi",		"current rssi" },
375 #define	S_NOISE			AFTER(S_RSSI)
376 	{ 5,	"noise",	"noise",	"current noise floor (dBm)" },
377 #define	S_SIGNAL		AFTER(S_NOISE)
378 	{ 6,	"signal",	"sig",		"current signal (dBm)" },
379 #define	S_BEACON_BAD		AFTER(S_SIGNAL)
380 	{ 9,	"beacon_bad",	"beaconbad",	"bad beacons received" },
381 #define	S_AMPDU_BARTX		AFTER(S_BEACON_BAD)
382 	{ 5,	"ampdu_bartx",	"bartx",	"BAR frames sent" },
383 #define	S_AMPDU_BARTX_FAIL	AFTER(S_AMPDU_BARTX)
384 	{ 9,	"ampdu_bartxfail",	"bartx_fail",	"BAR frames failed to send" },
385 #define	S_AMPDU_BARTX_RETRY	AFTER(S_AMPDU_BARTX_FAIL)
386 	{ 10,	"ampdu_bartxretry",	"bartx_retry",	"BAR frames retried" },
387 };
388 
389 struct wlanstatfoo_p {
390 	struct wlanstatfoo base;
391 	int s;
392 	int opmode;
393 	uint8_t mac[IEEE80211_ADDR_LEN];
394 	struct ifreq ifr;
395 	struct ieee80211_stats cur;
396 	struct ieee80211_stats total;
397 	struct ieee80211req ireq;
398 	union {
399 		struct ieee80211req_sta_req info;
400 		char buf[1024];
401 	} u_info;
402 	struct ieee80211req_sta_stats ncur;
403 	struct ieee80211req_sta_stats ntotal;
404 };
405 
406 static void
407 wlan_setifname(struct wlanstatfoo *wf0, const char *ifname)
408 {
409 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
410 
411 	strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name));
412 	strncpy(wf->ireq.i_name, ifname, sizeof (wf->ireq.i_name));
413 }
414 
415 static const char *
416 wlan_getifname(struct wlanstatfoo *wf0)
417 {
418 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
419 
420 	return wf->ifr.ifr_name;
421 }
422 
423 static int
424 wlan_getopmode(struct wlanstatfoo *wf0)
425 {
426 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
427 
428 	if (wf->opmode == -1) {
429 		struct ifmediareq ifmr;
430 
431 		memset(&ifmr, 0, sizeof(ifmr));
432 		strlcpy(ifmr.ifm_name, wf->ifr.ifr_name, sizeof(ifmr.ifm_name));
433 		if (ioctl(wf->s, SIOCGIFMEDIA, &ifmr) < 0)
434 			err(1, "%s (SIOCGIFMEDIA)", wf->ifr.ifr_name);
435 		if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
436 			if (ifmr.ifm_current & IFM_FLAG0)
437 				wf->opmode = IEEE80211_M_AHDEMO;
438 			else
439 				wf->opmode = IEEE80211_M_IBSS;
440 		} else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
441 			wf->opmode = IEEE80211_M_HOSTAP;
442 		else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
443 			wf->opmode = IEEE80211_M_MONITOR;
444 		else
445 			wf->opmode = IEEE80211_M_STA;
446 	}
447 	return wf->opmode;
448 }
449 
450 static void
451 getlladdr(struct wlanstatfoo_p *wf)
452 {
453 	const struct sockaddr_dl *sdl;
454 	struct ifaddrs *ifp, *p;
455 
456 	if (getifaddrs(&ifp) != 0)
457 		err(1, "getifaddrs");
458 	for (p = ifp; p != NULL; p = p->ifa_next)
459 		if (strcmp(p->ifa_name, wf->ifr.ifr_name) == 0 &&
460 		    p->ifa_addr->sa_family == AF_LINK)
461 			break;
462 	if (p == NULL)
463 		errx(1, "did not find link layer address for interface %s",
464 			wf->ifr.ifr_name);
465 	sdl = (const struct sockaddr_dl *) p->ifa_addr;
466 	IEEE80211_ADDR_COPY(wf->mac, CLLADDR(sdl));
467 	freeifaddrs(ifp);
468 }
469 
470 static int
471 getbssid(struct wlanstatfoo_p *wf)
472 {
473 	wf->ireq.i_type = IEEE80211_IOC_BSSID;
474 	wf->ireq.i_data = wf->mac;
475 	wf->ireq.i_len = IEEE80211_ADDR_LEN;
476 	return ioctl(wf->s, SIOCG80211, &wf->ireq);
477 }
478 
479 static void
480 wlan_setstamac(struct wlanstatfoo *wf0, const uint8_t *mac)
481 {
482 	static const uint8_t zeromac[IEEE80211_ADDR_LEN];
483 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
484 
485 	if (mac == NULL) {
486 		switch (wlan_getopmode(wf0)) {
487 		case IEEE80211_M_HOSTAP:
488 		case IEEE80211_M_MONITOR:
489 			getlladdr(wf);
490 			break;
491 		case IEEE80211_M_IBSS:
492 		case IEEE80211_M_AHDEMO:
493 			/*
494 			 * NB: this may not work in which case the
495 			 * mac must be specified on the command line
496 			 */
497 			if (getbssid(wf) < 0 ||
498 			    IEEE80211_ADDR_EQ(wf->mac, zeromac))
499 				getlladdr(wf);
500 			break;
501 		case IEEE80211_M_STA:
502 			if (getbssid(wf) < 0)
503 				err(1, "%s (IEEE80211_IOC_BSSID)",
504 				    wf->ireq.i_name);
505 			break;
506 		}
507 	} else
508 		IEEE80211_ADDR_COPY(wf->mac, mac);
509 }
510 
511 /* XXX only fetch what's needed to do reports */
512 static void
513 wlan_collect(struct wlanstatfoo_p *wf,
514 	struct ieee80211_stats *stats, struct ieee80211req_sta_stats *nstats)
515 {
516 
517 	IEEE80211_ADDR_COPY(wf->u_info.info.is_u.macaddr, wf->mac);
518 	wf->ireq.i_type = IEEE80211_IOC_STA_INFO;
519 	wf->ireq.i_data = (caddr_t) &wf->u_info;
520 	wf->ireq.i_len = sizeof(wf->u_info);
521 	if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0) {
522 		warn("%s:%s (IEEE80211_IOC_STA_INFO)", wf->ireq.i_name,
523 		    ether_ntoa((const struct ether_addr*) wf->mac));
524 	}
525 
526 	IEEE80211_ADDR_COPY(nstats->is_u.macaddr, wf->mac);
527 	wf->ireq.i_type = IEEE80211_IOC_STA_STATS;
528 	wf->ireq.i_data = (caddr_t) nstats;
529 	wf->ireq.i_len = sizeof(*nstats);
530 	if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0)
531 		warn("%s:%s (IEEE80211_IOC_STA_STATS)", wf->ireq.i_name,
532 		    ether_ntoa((const struct ether_addr*) wf->mac));
533 
534 	wf->ifr.ifr_data = (caddr_t) stats;
535 	if (ioctl(wf->s, SIOCG80211STATS, &wf->ifr) < 0)
536 		err(1, "%s (SIOCG80211STATS)", wf->ifr.ifr_name);
537 }
538 
539 static void
540 wlan_collect_cur(struct bsdstat *sf)
541 {
542 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
543 
544 	wlan_collect(wf, &wf->cur, &wf->ncur);
545 }
546 
547 static void
548 wlan_collect_tot(struct bsdstat *sf)
549 {
550 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
551 
552 	wlan_collect(wf, &wf->total, &wf->ntotal);
553 }
554 
555 static void
556 wlan_update_tot(struct bsdstat *sf)
557 {
558 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
559 
560 	wf->total = wf->cur;
561 	wf->ntotal = wf->ncur;
562 }
563 
564 static void
565 setreason(char b[], size_t bs, unsigned int v)
566 {
567     static const char *reasons[] = {
568 	[IEEE80211_REASON_UNSPECIFIED]		= "unspecified",
569 	[IEEE80211_REASON_AUTH_EXPIRE]		= "auth expire",
570 	[IEEE80211_REASON_AUTH_LEAVE]		= "auth leave",
571 	[IEEE80211_REASON_ASSOC_EXPIRE]		= "assoc expire",
572 	[IEEE80211_REASON_ASSOC_TOOMANY]	= "assoc toomany",
573 	[IEEE80211_REASON_NOT_AUTHED]		= "not authed",
574 	[IEEE80211_REASON_NOT_ASSOCED]		= "not assoced",
575 	[IEEE80211_REASON_ASSOC_LEAVE]		= "assoc leave",
576 	[IEEE80211_REASON_ASSOC_NOT_AUTHED]	= "assoc not authed",
577 	[IEEE80211_REASON_DISASSOC_PWRCAP_BAD]	= "disassoc pwrcap bad",
578 	[IEEE80211_REASON_DISASSOC_SUPCHAN_BAD]	= "disassoc supchan bad",
579 	[IEEE80211_REASON_IE_INVALID]		= "ie invalid",
580 	[IEEE80211_REASON_MIC_FAILURE]		= "mic failure",
581 	[IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT]= "4-way handshake timeout",
582 	[IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT] = "group key update timeout",
583 	[IEEE80211_REASON_IE_IN_4WAY_DIFFERS]	= "ie in 4-way differs",
584 	[IEEE80211_REASON_GROUP_CIPHER_INVALID]	= "group cipher invalid",
585 	[IEEE80211_REASON_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid",
586 	[IEEE80211_REASON_AKMP_INVALID]		= "akmp invalid",
587 	[IEEE80211_REASON_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version",
588 	[IEEE80211_REASON_INVALID_RSN_IE_CAP]	= "invalid rsn ie cap",
589 	[IEEE80211_REASON_802_1X_AUTH_FAILED]	= "802.1x auth failed",
590 	[IEEE80211_REASON_CIPHER_SUITE_REJECTED]= "cipher suite rejected",
591     };
592     if (v < nitems(reasons) && reasons[v] != NULL)
593 	    snprintf(b, bs, "%s (%u)", reasons[v], v);
594     else
595 	    snprintf(b, bs, "%u", v);
596 }
597 
598 static void
599 setstatus(char b[], size_t bs, unsigned int v)
600 {
601     static const char *status[] = {
602 	[IEEE80211_STATUS_SUCCESS]		= "success",
603 	[IEEE80211_STATUS_UNSPECIFIED]		= "unspecified",
604 	[IEEE80211_STATUS_CAPINFO]		= "capinfo",
605 	[IEEE80211_STATUS_NOT_ASSOCED]		= "not assoced",
606 	[IEEE80211_STATUS_OTHER]		= "other",
607 	[IEEE80211_STATUS_ALG]			= "algorithm",
608 	[IEEE80211_STATUS_SEQUENCE]		= "sequence",
609 	[IEEE80211_STATUS_CHALLENGE]		= "challenge",
610 	[IEEE80211_STATUS_TIMEOUT]		= "timeout",
611 	[IEEE80211_STATUS_TOOMANY]		= "toomany",
612 	[IEEE80211_STATUS_BASIC_RATE]		= "basic rate",
613 	[IEEE80211_STATUS_SP_REQUIRED]		= "sp required",
614 	[IEEE80211_STATUS_PBCC_REQUIRED]	= "pbcc required",
615 	[IEEE80211_STATUS_CA_REQUIRED]		= "ca required",
616 	[IEEE80211_STATUS_SPECMGMT_REQUIRED]	= "specmgmt required",
617 	[IEEE80211_STATUS_PWRCAP_REQUIRED]	= "pwrcap required",
618 	[IEEE80211_STATUS_SUPCHAN_REQUIRED]	= "supchan required",
619 	[IEEE80211_STATUS_SHORTSLOT_REQUIRED]	= "shortslot required",
620 	[IEEE80211_STATUS_DSSSOFDM_REQUIRED]	= "dsssofdm required",
621 	[IEEE80211_STATUS_INVALID_IE]		= "invalid ie",
622 	[IEEE80211_STATUS_GROUP_CIPHER_INVALID]	= "group cipher invalid",
623 	[IEEE80211_STATUS_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid",
624 	[IEEE80211_STATUS_AKMP_INVALID]		= "akmp invalid",
625 	[IEEE80211_STATUS_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version",
626 	[IEEE80211_STATUS_INVALID_RSN_IE_CAP]	= "invalid rsn ie cap",
627 	[IEEE80211_STATUS_CIPHER_SUITE_REJECTED]= "cipher suite rejected",
628     };
629     if (v < nitems(status) && status[v] != NULL)
630 	    snprintf(b, bs, "%s (%u)", status[v], v);
631     else
632 	    snprintf(b, bs, "%u", v);
633 }
634 
635 static int
636 wlan_getinfo(struct wlanstatfoo_p *wf, int s, char b[], size_t bs)
637 {
638 	const struct ieee80211req_sta_info *si = &wf->u_info.info.info[0];
639 
640 	switch (s) {
641 	case S_RATE:
642 		snprintf(b, bs, "%.1fM", (float) si->isi_txmbps/2.0);
643 		return 1;
644 	case S_RSSI:
645 		snprintf(b, bs, "%.1f", (float) si->isi_rssi/2.0);
646 		return 1;
647 	case S_NOISE:
648 		snprintf(b, bs, "%d", si->isi_noise);
649 		return 1;
650 	case S_SIGNAL:
651 		snprintf(b, bs, "%.1f", (float) si->isi_rssi/2.0
652 		    + (float) si->isi_noise);
653 		return 1;
654 	case S_RX_AUTH_FAIL_CODE:
655 		if (wf->cur.is_rx_authfail_code == 0)
656 			break;
657 		setstatus(b, bs, wf->cur.is_rx_authfail_code);
658 		return 1;
659 	case S_RX_DEAUTH_CODE:
660 		if (wf->cur.is_rx_deauth_code == 0)
661 			break;
662 		setreason(b, bs, wf->cur.is_rx_deauth_code);
663 		return 1;
664 	case S_RX_DISASSOC_CODE:
665 		if (wf->cur.is_rx_disassoc_code == 0)
666 			break;
667 		setreason(b, bs, wf->cur.is_rx_disassoc_code);
668 		return 1;
669 	}
670 	b[0] = '\0';
671 	return 0;
672 }
673 
674 static int
675 wlan_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs)
676 {
677 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
678 #define	STAT(x) \
679 	snprintf(b, bs, "%u", wf->cur.is_##x - wf->total.is_##x); return 1
680 #define	NSTAT(x) \
681 	snprintf(b, bs, "%u", \
682 	    wf->ncur.is_stats.ns_##x - wf->ntotal.is_stats.ns_##x); \
683 	    return 1
684 
685 	switch (s) {
686 	case S_RX_BADVERSION:	STAT(rx_badversion);
687 	case S_RX_TOOSHORT:	STAT(rx_tooshort);
688 	case S_RX_WRONGBSS:	STAT(rx_wrongbss);
689 	case S_RX_DUP:		STAT(rx_dup);
690 	case S_RX_WRONGDIR:	STAT(rx_wrongdir);
691 	case S_RX_MCASTECHO:	STAT(rx_mcastecho);
692 	case S_RX_NOTASSOC:	STAT(rx_notassoc);
693 	case S_RX_NOPRIVACY:	STAT(rx_noprivacy);
694 	case S_RX_UNENCRYPTED:	STAT(rx_unencrypted);
695 	case S_RX_WEPFAIL:	STAT(rx_wepfail);
696 	case S_RX_DECAP:	STAT(rx_decap);
697 	case S_RX_MGTDISCARD:	STAT(rx_mgtdiscard);
698 	case S_RX_CTL:		STAT(rx_ctl);
699 	case S_RX_BEACON:	STAT(rx_beacon);
700 	case S_RX_RSTOOBIG:	STAT(rx_rstoobig);
701 	case S_RX_ELEM_MISSING:	STAT(rx_elem_missing);
702 	case S_RX_ELEM_TOOBIG:	STAT(rx_elem_toobig);
703 	case S_RX_ELEM_TOOSMALL:	STAT(rx_elem_toosmall);
704 	case S_RX_ELEM_UNKNOWN:	STAT(rx_elem_unknown);
705 	case S_RX_BADCHAN:	STAT(rx_badchan);
706 	case S_RX_CHANMISMATCH:	STAT(rx_chanmismatch);
707 	case S_RX_NODEALLOC:	STAT(rx_nodealloc);
708 	case S_RX_SSIDMISMATCH:	STAT(rx_ssidmismatch);
709 	case S_RX_AUTH_UNSUPPORTED:	STAT(rx_auth_unsupported);
710 	case S_RX_AUTH_FAIL:	STAT(rx_auth_fail);
711 	case S_RX_AUTH_COUNTERMEASURES:	STAT(rx_auth_countermeasures);
712 	case S_RX_ASSOC_BSS:	STAT(rx_assoc_bss);
713 	case S_RX_ASSOC_NOTAUTH:	STAT(rx_assoc_notauth);
714 	case S_RX_ASSOC_CAPMISMATCH:	STAT(rx_assoc_capmismatch);
715 	case S_RX_ASSOC_NORATE:	STAT(rx_assoc_norate);
716 	case S_RX_ASSOC_BADWPAIE:	STAT(rx_assoc_badwpaie);
717 	case S_RX_DEAUTH:	STAT(rx_deauth);
718 	case S_RX_DISASSOC:	STAT(rx_disassoc);
719 	case S_BMISS:		STAT(beacon_miss);
720 	case S_RX_BADSUBTYPE:	STAT(rx_badsubtype);
721 	case S_RX_NOBUF:	STAT(rx_nobuf);
722 	case S_RX_DECRYPTCRC:	STAT(rx_decryptcrc);
723 	case S_RX_AHDEMO_MGT:	STAT(rx_ahdemo_mgt);
724 	case S_RX_BAD_AUTH:	STAT(rx_bad_auth);
725 	case S_RX_UNAUTH:	STAT(rx_unauth);
726 	case S_RX_BADKEYID:	STAT(rx_badkeyid);
727 	case S_RX_CCMPREPLAY:	STAT(rx_ccmpreplay);
728 	case S_RX_CCMPFORMAT:	STAT(rx_ccmpformat);
729 	case S_RX_CCMPMIC:	STAT(rx_ccmpmic);
730 	case S_RX_TKIPREPLAY:	STAT(rx_tkipreplay);
731 	case S_RX_TKIPFORMAT:	STAT(rx_tkipformat);
732 	case S_RX_TKIPMIC:	STAT(rx_tkipmic);
733 	case S_RX_TKIPICV:	STAT(rx_tkipicv);
734 	case S_RX_BADCIPHER:	STAT(rx_badcipher);
735 	case S_RX_NOCIPHERCTX:	STAT(rx_nocipherctx);
736 	case S_RX_ACL:		STAT(rx_acl);
737 	case S_TX_NOBUF:	STAT(tx_nobuf);
738 	case S_TX_NONODE:	STAT(tx_nonode);
739 	case S_TX_UNKNOWNMGT:	STAT(tx_unknownmgt);
740 	case S_TX_BADCIPHER:	STAT(tx_badcipher);
741 	case S_TX_NODEFKEY:	STAT(tx_nodefkey);
742 	case S_TX_NOHEADROOM:	STAT(tx_noheadroom);
743 	case S_TX_FRAGFRAMES:	STAT(tx_fragframes);
744 	case S_TX_FRAGS:	STAT(tx_frags);
745 	case S_SCAN_ACTIVE:	STAT(scan_active);
746 	case S_SCAN_PASSIVE:	STAT(scan_passive);
747 	case S_SCAN_BG:		STAT(scan_bg);
748 	case S_NODE_TIMEOUT:	STAT(node_timeout);
749 	case S_CRYPTO_NOMEM:	STAT(crypto_nomem);
750 	case S_CRYPTO_TKIP:	STAT(crypto_tkip);
751 	case S_CRYPTO_TKIPENMIC:	STAT(crypto_tkipenmic);
752 	case S_CRYPTO_TKIPDEMIC:	STAT(crypto_tkipdemic);
753 	case S_CRYPTO_TKIPCM:	STAT(crypto_tkipcm);
754 	case S_CRYPTO_CCMP:	STAT(crypto_ccmp);
755 	case S_CRYPTO_WEP:	STAT(crypto_wep);
756 	case S_CRYPTO_SETKEY_CIPHER:	STAT(crypto_setkey_cipher);
757 	case S_CRYPTO_SETKEY_NOKEY:	STAT(crypto_setkey_nokey);
758 	case S_CRYPTO_DELKEY:	STAT(crypto_delkey);
759 	case S_CRYPTO_BADCIPHER:	STAT(crypto_badcipher);
760 	case S_CRYPTO_NOCIPHER:	STAT(crypto_nocipher);
761 	case S_CRYPTO_ATTACHFAIL:	STAT(crypto_attachfail);
762 	case S_CRYPTO_SWFALLBACK:	STAT(crypto_swfallback);
763 	case S_CRYPTO_KEYFAIL:	STAT(crypto_keyfail);
764 	case S_CRYPTO_ENMICFAIL:	STAT(crypto_enmicfail);
765 	case S_IBSS_CAPMISMATCH:	STAT(ibss_capmismatch);
766 	case S_IBSS_NORATE:	STAT(ibss_norate);
767 	case S_PS_UNASSOC:	STAT(ps_unassoc);
768 	case S_PS_BADAID:	STAT(ps_badaid);
769 	case S_PS_QEMPTY:	STAT(ps_qempty);
770 	case S_FF_BADHDR:	STAT(ff_badhdr);
771 	case S_FF_TOOSHORT:	STAT(ff_tooshort);
772 	case S_FF_SPLIT:	STAT(ff_split);
773 	case S_FF_DECAP:	STAT(ff_decap);
774 	case S_FF_ENCAP:	STAT(ff_encap);
775 	case S_FF_ENCAPFAIL:	STAT(ff_encapfail);
776 	case S_RX_BADBINTVAL:	STAT(rx_badbintval);
777 	case S_RX_MGMT:		STAT(rx_mgmt);
778 	case S_RX_DEMICFAIL:	STAT(rx_demicfail);
779 	case S_RX_DEFRAG:	STAT(rx_defrag);
780 	case S_RX_ACTION:	STAT(rx_action);
781 	case S_AMSDU_TOOSHORT:	STAT(amsdu_tooshort);
782 	case S_AMSDU_SPLIT:	STAT(amsdu_split);
783 	case S_AMSDU_DECAP:	STAT(amsdu_decap);
784 	case S_AMSDU_ENCAP:	STAT(amsdu_encap);
785 	case S_AMSDU_RX_MORE:	NSTAT(rx_amsdu_more);
786 	case S_AMSDU_RX_MORE_END:	NSTAT(rx_amsdu_more_end);
787 	case S_AMPDU_REORDER:	STAT(ampdu_rx_reorder);
788 	case S_AMPDU_FLUSH:	STAT(ampdu_rx_flush);
789 	case S_AMPDU_BARBAD:	STAT(ampdu_bar_bad);
790 	case S_AMPDU_BAROOW:	STAT(ampdu_bar_oow);
791 	case S_AMPDU_BARMOVE:	STAT(ampdu_bar_move);
792 	case S_AMPDU_BAR:	STAT(ampdu_bar_rx);
793 	case S_AMPDU_MOVE:	STAT(ampdu_rx_move);
794 	case S_AMPDU_OOR:	STAT(ampdu_rx_oor);
795 	case S_AMPDU_COPY:	STAT(ampdu_rx_copy);
796 	case S_AMPDU_DROP:	STAT(ampdu_rx_drop);
797 	case S_AMPDU_AGE:	STAT(ampdu_rx_age);
798 	case S_AMPDU_STOP:	STAT(ampdu_stop);
799 	case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
800 	case S_ADDBA_REJECT:	STAT(addba_reject);
801 	case S_ADDBA_NOREQUEST:	STAT(addba_norequest);
802 	case S_ADDBA_BADTOKEN:	STAT(addba_badtoken);
803 	case S_TX_BADSTATE:	STAT(tx_badstate);
804 	case S_TX_NOTASSOC:	STAT(tx_notassoc);
805 	case S_TX_CLASSIFY:	STAT(tx_classify);
806 	case S_DWDS_MCAST:	STAT(dwds_mcast);
807 	case S_DWDS_QDROP:	STAT(dwds_qdrop);
808 	case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
809 	case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
810 	case S_HT_ASSOC_NORATE:	STAT(ht_assoc_norate);
811 	case S_MESH_WRONGMESH:	STAT(mesh_wrongmesh);
812 	case S_MESH_NOLINK:	STAT(mesh_nolink);
813 	case S_MESH_FWD_TTL:	STAT(mesh_fwd_ttl);
814 	case S_MESH_FWD_NOBUF:	STAT(mesh_fwd_nobuf);
815 	case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort);
816 	case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled);
817 	case S_MESH_FWD_NOPATH:	STAT(mesh_fwd_nopath);
818 	case S_HWMP_WRONGSEQ:	STAT(hwmp_wrongseq);
819 	case S_HWMP_ROOTREQS:	STAT(hwmp_rootreqs);
820 	case S_HWMP_ROOTANN:	STAT(hwmp_rootrann);
821 	case S_MESH_BADAE:	STAT(mesh_badae);
822 	case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed);
823 	case S_MESH_NOTPROXY:	STAT(mesh_notproxy);
824 	case S_RX_BADALIGN:	STAT(rx_badalign);
825 	case S_INPUT:		NSTAT(rx_data);
826 	case S_OUTPUT:		NSTAT(tx_data);
827 	case S_RX_UCAST:	NSTAT(rx_ucast);
828 	case S_RX_MCAST:	NSTAT(rx_mcast);
829 	case S_TX_UCAST:	NSTAT(tx_ucast);
830 	case S_TX_MCAST:	NSTAT(tx_mcast);
831 	case S_BEACON_BAD:	STAT(beacon_bad);
832 	case S_AMPDU_BARTX:	STAT(ampdu_bar_tx);
833 	case S_AMPDU_BARTX_RETRY:	STAT(ampdu_bar_tx_retry);
834 	case S_AMPDU_BARTX_FAIL:	STAT(ampdu_bar_tx_fail);
835 	}
836 	return wlan_getinfo(wf, s, b, bs);
837 #undef NSTAT
838 #undef STAT
839 }
840 
841 static int
842 wlan_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs)
843 {
844 	struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
845 #define	STAT(x) \
846 	snprintf(b, bs, "%u", wf->total.is_##x); return 1
847 #define	NSTAT(x) \
848 	snprintf(b, bs, "%u", wf->ntotal.is_stats.ns_##x); return 1
849 
850 	switch (s) {
851 	case S_RX_BADVERSION:	STAT(rx_badversion);
852 	case S_RX_TOOSHORT:	STAT(rx_tooshort);
853 	case S_RX_WRONGBSS:	STAT(rx_wrongbss);
854 	case S_RX_DUP:	STAT(rx_dup);
855 	case S_RX_WRONGDIR:	STAT(rx_wrongdir);
856 	case S_RX_MCASTECHO:	STAT(rx_mcastecho);
857 	case S_RX_NOTASSOC:	STAT(rx_notassoc);
858 	case S_RX_NOPRIVACY:	STAT(rx_noprivacy);
859 	case S_RX_UNENCRYPTED:	STAT(rx_unencrypted);
860 	case S_RX_WEPFAIL:	STAT(rx_wepfail);
861 	case S_RX_DECAP:	STAT(rx_decap);
862 	case S_RX_MGTDISCARD:	STAT(rx_mgtdiscard);
863 	case S_RX_CTL:		STAT(rx_ctl);
864 	case S_RX_BEACON:	STAT(rx_beacon);
865 	case S_RX_RSTOOBIG:	STAT(rx_rstoobig);
866 	case S_RX_ELEM_MISSING:	STAT(rx_elem_missing);
867 	case S_RX_ELEM_TOOBIG:	STAT(rx_elem_toobig);
868 	case S_RX_ELEM_TOOSMALL:	STAT(rx_elem_toosmall);
869 	case S_RX_ELEM_UNKNOWN:	STAT(rx_elem_unknown);
870 	case S_RX_BADCHAN:	STAT(rx_badchan);
871 	case S_RX_CHANMISMATCH:	STAT(rx_chanmismatch);
872 	case S_RX_NODEALLOC:	STAT(rx_nodealloc);
873 	case S_RX_SSIDMISMATCH:	STAT(rx_ssidmismatch);
874 	case S_RX_AUTH_UNSUPPORTED:	STAT(rx_auth_unsupported);
875 	case S_RX_AUTH_FAIL:	STAT(rx_auth_fail);
876 	case S_RX_AUTH_COUNTERMEASURES:	STAT(rx_auth_countermeasures);
877 	case S_RX_ASSOC_BSS:	STAT(rx_assoc_bss);
878 	case S_RX_ASSOC_NOTAUTH:	STAT(rx_assoc_notauth);
879 	case S_RX_ASSOC_CAPMISMATCH:	STAT(rx_assoc_capmismatch);
880 	case S_RX_ASSOC_NORATE:	STAT(rx_assoc_norate);
881 	case S_RX_ASSOC_BADWPAIE:	STAT(rx_assoc_badwpaie);
882 	case S_RX_DEAUTH:	STAT(rx_deauth);
883 	case S_RX_DISASSOC:	STAT(rx_disassoc);
884 	case S_BMISS:		STAT(beacon_miss);
885 	case S_RX_BADSUBTYPE:	STAT(rx_badsubtype);
886 	case S_RX_NOBUF:	STAT(rx_nobuf);
887 	case S_RX_DECRYPTCRC:	STAT(rx_decryptcrc);
888 	case S_RX_AHDEMO_MGT:	STAT(rx_ahdemo_mgt);
889 	case S_RX_BAD_AUTH:	STAT(rx_bad_auth);
890 	case S_RX_UNAUTH:	STAT(rx_unauth);
891 	case S_RX_BADKEYID:	STAT(rx_badkeyid);
892 	case S_RX_CCMPREPLAY:	STAT(rx_ccmpreplay);
893 	case S_RX_CCMPFORMAT:	STAT(rx_ccmpformat);
894 	case S_RX_CCMPMIC:	STAT(rx_ccmpmic);
895 	case S_RX_TKIPREPLAY:	STAT(rx_tkipreplay);
896 	case S_RX_TKIPFORMAT:	STAT(rx_tkipformat);
897 	case S_RX_TKIPMIC:	STAT(rx_tkipmic);
898 	case S_RX_TKIPICV:	STAT(rx_tkipicv);
899 	case S_RX_BADCIPHER:	STAT(rx_badcipher);
900 	case S_RX_NOCIPHERCTX:	STAT(rx_nocipherctx);
901 	case S_RX_ACL:		STAT(rx_acl);
902 	case S_TX_NOBUF:	STAT(tx_nobuf);
903 	case S_TX_NONODE:	STAT(tx_nonode);
904 	case S_TX_UNKNOWNMGT:	STAT(tx_unknownmgt);
905 	case S_TX_BADCIPHER:	STAT(tx_badcipher);
906 	case S_TX_NODEFKEY:	STAT(tx_nodefkey);
907 	case S_TX_NOHEADROOM:	STAT(tx_noheadroom);
908 	case S_TX_FRAGFRAMES:	STAT(tx_fragframes);
909 	case S_TX_FRAGS:	STAT(tx_frags);
910 	case S_SCAN_ACTIVE:	STAT(scan_active);
911 	case S_SCAN_PASSIVE:	STAT(scan_passive);
912 	case S_SCAN_BG:		STAT(scan_bg);
913 	case S_NODE_TIMEOUT:	STAT(node_timeout);
914 	case S_CRYPTO_NOMEM:	STAT(crypto_nomem);
915 	case S_CRYPTO_TKIP:	STAT(crypto_tkip);
916 	case S_CRYPTO_TKIPENMIC:	STAT(crypto_tkipenmic);
917 	case S_CRYPTO_TKIPDEMIC:	STAT(crypto_tkipdemic);
918 	case S_CRYPTO_TKIPCM:	STAT(crypto_tkipcm);
919 	case S_CRYPTO_CCMP:	STAT(crypto_ccmp);
920 	case S_CRYPTO_WEP:	STAT(crypto_wep);
921 	case S_CRYPTO_SETKEY_CIPHER:	STAT(crypto_setkey_cipher);
922 	case S_CRYPTO_SETKEY_NOKEY:	STAT(crypto_setkey_nokey);
923 	case S_CRYPTO_DELKEY:	STAT(crypto_delkey);
924 	case S_CRYPTO_BADCIPHER:	STAT(crypto_badcipher);
925 	case S_CRYPTO_NOCIPHER:	STAT(crypto_nocipher);
926 	case S_CRYPTO_ATTACHFAIL:	STAT(crypto_attachfail);
927 	case S_CRYPTO_SWFALLBACK:	STAT(crypto_swfallback);
928 	case S_CRYPTO_KEYFAIL:	STAT(crypto_keyfail);
929 	case S_CRYPTO_ENMICFAIL:	STAT(crypto_enmicfail);
930 	case S_IBSS_CAPMISMATCH:	STAT(ibss_capmismatch);
931 	case S_IBSS_NORATE:	STAT(ibss_norate);
932 	case S_PS_UNASSOC:	STAT(ps_unassoc);
933 	case S_PS_BADAID:	STAT(ps_badaid);
934 	case S_PS_QEMPTY:	STAT(ps_qempty);
935 	case S_FF_BADHDR:	STAT(ff_badhdr);
936 	case S_FF_TOOSHORT:	STAT(ff_tooshort);
937 	case S_FF_SPLIT:	STAT(ff_split);
938 	case S_FF_DECAP:	STAT(ff_decap);
939 	case S_FF_ENCAP:	STAT(ff_encap);
940 	case S_FF_ENCAPFAIL:	STAT(ff_encapfail);
941 	case S_RX_BADBINTVAL:	STAT(rx_badbintval);
942 	case S_RX_MGMT:		STAT(rx_mgmt);
943 	case S_RX_DEMICFAIL:	STAT(rx_demicfail);
944 	case S_RX_DEFRAG:	STAT(rx_defrag);
945 	case S_RX_ACTION:	STAT(rx_action);
946 	case S_AMSDU_TOOSHORT:	STAT(amsdu_tooshort);
947 	case S_AMSDU_SPLIT:	STAT(amsdu_split);
948 	case S_AMSDU_DECAP:	STAT(amsdu_decap);
949 	case S_AMSDU_ENCAP:	STAT(amsdu_encap);
950 	case S_AMSDU_RX_MORE:	NSTAT(rx_amsdu_more);
951 	case S_AMSDU_RX_MORE_END:	NSTAT(rx_amsdu_more_end);
952 	case S_AMPDU_REORDER:	STAT(ampdu_rx_reorder);
953 	case S_AMPDU_FLUSH:	STAT(ampdu_rx_flush);
954 	case S_AMPDU_BARBAD:	STAT(ampdu_bar_bad);
955 	case S_AMPDU_BAROOW:	STAT(ampdu_bar_oow);
956 	case S_AMPDU_BARMOVE:	STAT(ampdu_bar_move);
957 	case S_AMPDU_BAR:	STAT(ampdu_bar_rx);
958 	case S_AMPDU_MOVE:	STAT(ampdu_rx_move);
959 	case S_AMPDU_OOR:	STAT(ampdu_rx_oor);
960 	case S_AMPDU_COPY:	STAT(ampdu_rx_copy);
961 	case S_AMPDU_DROP:	STAT(ampdu_rx_drop);
962 	case S_AMPDU_AGE:	STAT(ampdu_rx_age);
963 	case S_AMPDU_STOP:	STAT(ampdu_stop);
964 	case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
965 	case S_ADDBA_REJECT:	STAT(addba_reject);
966 	case S_ADDBA_NOREQUEST:	STAT(addba_norequest);
967 	case S_ADDBA_BADTOKEN:	STAT(addba_badtoken);
968 	case S_TX_BADSTATE:	STAT(tx_badstate);
969 	case S_TX_NOTASSOC:	STAT(tx_notassoc);
970 	case S_TX_CLASSIFY:	STAT(tx_classify);
971 	case S_DWDS_MCAST:	STAT(dwds_mcast);
972 	case S_DWDS_QDROP:	STAT(dwds_qdrop);
973 	case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
974 	case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
975 	case S_HT_ASSOC_NORATE:	STAT(ht_assoc_norate);
976 	case S_MESH_WRONGMESH:	STAT(mesh_wrongmesh);
977 	case S_MESH_NOLINK:	STAT(mesh_nolink);
978 	case S_MESH_FWD_TTL:	STAT(mesh_fwd_ttl);
979 	case S_MESH_FWD_NOBUF:	STAT(mesh_fwd_nobuf);
980 	case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort);
981 	case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled);
982 	case S_MESH_FWD_NOPATH:	STAT(mesh_fwd_nopath);
983 	case S_HWMP_WRONGSEQ:	STAT(hwmp_wrongseq);
984 	case S_HWMP_ROOTREQS:	STAT(hwmp_rootreqs);
985 	case S_HWMP_ROOTANN:	STAT(hwmp_rootrann);
986 	case S_MESH_BADAE:	STAT(mesh_badae);
987 	case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed);
988 	case S_MESH_NOTPROXY:	STAT(mesh_notproxy);
989 	case S_RX_BADALIGN:	STAT(rx_badalign);
990 	case S_INPUT:		NSTAT(rx_data);
991 	case S_OUTPUT:		NSTAT(tx_data);
992 	case S_RX_UCAST:	NSTAT(rx_ucast);
993 	case S_RX_MCAST:	NSTAT(rx_mcast);
994 	case S_TX_UCAST:	NSTAT(tx_ucast);
995 	case S_TX_MCAST:	NSTAT(tx_mcast);
996 	case S_BEACON_BAD:	STAT(beacon_bad);
997 	case S_AMPDU_BARTX:	STAT(ampdu_bar_tx);
998 	case S_AMPDU_BARTX_RETRY:	STAT(ampdu_bar_tx_retry);
999 	case S_AMPDU_BARTX_FAIL:	STAT(ampdu_bar_tx_fail);
1000 	}
1001 	return wlan_getinfo(wf, s, b, bs);
1002 #undef NSTAT
1003 #undef STAT
1004 }
1005 
1006 BSDSTAT_DEFINE_BOUNCE(wlanstatfoo)
1007 
1008 struct wlanstatfoo *
1009 wlanstats_new(const char *ifname, const char *fmtstring)
1010 {
1011 	struct wlanstatfoo_p *wf;
1012 
1013 	wf = calloc(1, sizeof(struct wlanstatfoo_p));
1014 	if (wf != NULL) {
1015 		bsdstat_init(&wf->base.base, "wlanstats", wlanstats,
1016 		    nitems(wlanstats));
1017 		/* override base methods */
1018 		wf->base.base.collect_cur = wlan_collect_cur;
1019 		wf->base.base.collect_tot = wlan_collect_tot;
1020 		wf->base.base.get_curstat = wlan_get_curstat;
1021 		wf->base.base.get_totstat = wlan_get_totstat;
1022 		wf->base.base.update_tot = wlan_update_tot;
1023 
1024 		/* setup bounce functions for public methods */
1025 		BSDSTAT_BOUNCE(wf, wlanstatfoo);
1026 
1027 		/* setup our public methods */
1028 		wf->base.setifname = wlan_setifname;
1029 		wf->base.getifname = wlan_getifname;
1030 		wf->base.getopmode = wlan_getopmode;
1031 		wf->base.setstamac = wlan_setstamac;
1032 		wf->opmode = -1;
1033 
1034 		wf->s = socket(AF_INET, SOCK_DGRAM, 0);
1035 		if (wf->s < 0)
1036 			err(1, "socket");
1037 
1038 		wlan_setifname(&wf->base, ifname);
1039 		wf->base.setfmt(&wf->base, fmtstring);
1040 	}
1041 	return &wf->base;
1042 }
1043