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