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