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
30 /*
31 * net80211 statistics class.
32 */
33
34 #include <sys/param.h>
35 #include <sys/file.h>
36 #include <sys/sockio.h>
37 #include <sys/socket.h>
38
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 <err.h>
46 #include <ifaddrs.h>
47 #include <signal.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.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_AMSDU_RX_MORE AFTER(S_AMSDU_ENCAP)
278 { 13, "rx_amsdu_more", "rx_amsdu_more", "A-MSDU HW intermediary decap'ed received" },
279 #define S_AMSDU_RX_MORE_END AFTER(S_AMSDU_RX_MORE)
280 { 17, "rx_amsdu_more_end", "rx_amsdu_more_end", "A-MSDU HW end decap'ed received" },
281 #define S_AMPDU_REORDER AFTER(S_AMSDU_RX_MORE_END)
282 { 8, "ampdu_reorder", "reorder","A-MPDU frames held in reorder q" },
283 #define S_AMPDU_FLUSH AFTER(S_AMPDU_REORDER)
284 { 8, "ampdu_flush", "flush", "A-MPDU frames sent up from reorder q" },
285 #define S_AMPDU_BARBAD AFTER(S_AMPDU_FLUSH)
286 { 6, "ampdu_barbad", "barbad", "A-MPDU BAR rx before ADDBA exchange (or disabled with net.link.ieee80211)" },
287 #define S_AMPDU_BAROOW AFTER(S_AMPDU_BARBAD)
288 { 6, "ampdu_baroow", "baroow", "A-MPDU BAR rx out of BA window" },
289 #define S_AMPDU_BARMOVE AFTER(S_AMPDU_BAROOW)
290 { 8, "ampdu_barmove", "barmove","A-MPDU BAR rx moved BA window" },
291 #define S_AMPDU_BAR AFTER(S_AMPDU_BARMOVE)
292 { 8, "ampdu_bar", "rxbar", "A-MPDU BAR rx successful" },
293 #define S_AMPDU_MOVE AFTER(S_AMPDU_BAR)
294 { 5, "ampdu_move", "move", "A-MPDU frame moved BA window" },
295 #define S_AMPDU_OOR AFTER(S_AMPDU_MOVE)
296 { 8, "ampdu_oor", "oorx", "A-MPDU frames rx out-of-order" },
297 #define S_AMPDU_COPY AFTER(S_AMPDU_OOR)
298 { 8, "ampdu_copy", "copy", "A-MPDU rx window slots copied" },
299 #define S_AMPDU_DROP AFTER(S_AMPDU_COPY)
300 { 5, "ampdu_drop", "drop", "A-MPDU frames discarded for out of range seqno" },
301 #define S_AMPDU_AGE AFTER(S_AMPDU_DROP)
302 { 5, "ampdu_age", "age", "A-MPDU frames sent up due to old age" },
303 #define S_AMPDU_STOP AFTER(S_AMPDU_AGE)
304 { 5, "ampdu_stop", "stop", "A-MPDU streams stopped" },
305 #define S_AMPDU_STOP_FAILED AFTER(S_AMPDU_STOP)
306 { 5, "ampdu_stop_failed","!stop", "A-MPDU stop requests failed 'cuz stream not running" },
307 #define S_ADDBA_REJECT AFTER(S_AMPDU_STOP_FAILED)
308 { 5, "addba_reject", "reject", "ADDBA requests rejected 'cuz A-MPDU rx is disabled" },
309 #define S_ADDBA_NOREQUEST AFTER(S_ADDBA_REJECT)
310 { 5, "addba_norequest","norequest","ADDBA response frames discarded because no ADDBA request was pending" },
311 #define S_ADDBA_BADTOKEN AFTER(S_ADDBA_NOREQUEST)
312 { 5, "addba_badtoken", "badtoken","ADDBA response frames discarded 'cuz rx'd dialog token is wrong" },
313 #define S_TX_BADSTATE AFTER(S_ADDBA_BADTOKEN)
314 { 4, "tx_badstate", "badstate", "tx failed 'cuz vap not in RUN state" },
315 #define S_TX_NOTASSOC AFTER(S_TX_BADSTATE)
316 { 4, "tx_notassoc", "notassoc", "tx failed 'cuz dest sta not associated" },
317 #define S_TX_CLASSIFY AFTER(S_TX_NOTASSOC)
318 { 4, "tx_classify", "classify", "tx packet classification failed" },
319 #define S_DWDS_MCAST AFTER(S_TX_CLASSIFY)
320 { 8, "dwds_mcast", "dwds_mcast", "mcast frame transmitted on dwds vap discarded" },
321 #define S_DWDS_QDROP AFTER(S_DWDS_MCAST)
322 { 8, "dwds_qdrop", "dwds_qdrop", "4-address frame discarded because dwds pending queue is full" },
323 #define S_HT_ASSOC_NOHTCAP AFTER(S_DWDS_QDROP)
324 { 4, "ht_nohtcap", "ht_nohtcap", "non-HT station rejected in HT-only BSS" },
325 #define S_HT_ASSOC_DOWNGRADE AFTER(S_HT_ASSOC_NOHTCAP)
326 { 4, "ht_downgrade", "ht_downgrade", "HT station downgraded to legacy operation" },
327 #define S_HT_ASSOC_NORATE AFTER(S_HT_ASSOC_DOWNGRADE)
328 { 4, "ht_norate", "ht_norate", "HT station rejected because of HT rate set" },
329 #define S_MESH_WRONGMESH AFTER(S_HT_ASSOC_NORATE)
330 { 4, "mesh_wrong", "mesh_wrong", "frame discarded because sender not a mesh sta" },
331 #define S_MESH_NOLINK AFTER(S_MESH_WRONGMESH)
332 { 4, "mesh_nolink", "mesh_nolink", "frame discarded because link not established" },
333 #define S_MESH_FWD_TTL AFTER(S_MESH_NOLINK)
334 { 4, "mesh_fwd_ttl", "mesh_fwd_ttl", "frame not forwarded because TTL zero" },
335 #define S_MESH_FWD_NOBUF AFTER(S_MESH_FWD_TTL)
336 { 4, "mesh_fwd_nobuf", "mesh_fwd_nobuf", "frame not forwarded because mbuf could not be allocated" },
337 #define S_MESH_FWD_TOOSHORT AFTER(S_MESH_FWD_NOBUF)
338 { 4, "mesh_fwd_tooshort", "mesh_fwd_tooshort", "frame not forwarded because too short to have 802.11 header" },
339 #define S_MESH_FWD_DISABLED AFTER(S_MESH_FWD_TOOSHORT)
340 { 4, "mesh_fwd_disabled", "mesh_fwd_disabled", "frame not forwarded because administratively disabled" },
341 #define S_MESH_FWD_NOPATH AFTER(S_MESH_FWD_DISABLED)
342 { 4, "mesh_fwd_nopath", "mesh_fwd_nopath", "frame not forwarded because no path found to destination" },
343 #define S_HWMP_WRONGSEQ AFTER(S_MESH_FWD_NOPATH)
344 { 4, "hwmp_wrongseq", "hwmp_wrongseq", "frame discarded because mesh sequence number is invalid" },
345 #define S_HWMP_ROOTREQS AFTER(S_HWMP_WRONGSEQ)
346 { 4, "hwmp_rootreqs", "hwmp_rootreqs", "root PREQ frames sent" },
347 #define S_HWMP_ROOTANN AFTER(S_HWMP_ROOTREQS)
348 { 4, "hwmp_rootann", "hwmp_rootann", "root RANN frames received" },
349 #define S_MESH_BADAE AFTER(S_HWMP_ROOTANN)
350 { 4, "mesh_badae", "mesh_badae", "frame discarded for bad AddressExtension (AE)" },
351 #define S_MESH_RTADDFAILED AFTER(S_MESH_BADAE)
352 { 4, "mesh_rtadd", "mesh_rtadd", "mesh route add failed" },
353 #define S_MESH_NOTPROXY AFTER(S_MESH_RTADDFAILED)
354 { 8, "mesh_notproxy", "mesh_notproxy","frame discarded because station not acting as a proxy" },
355 #define S_RX_BADALIGN AFTER(S_MESH_NOTPROXY)
356 { 4, "rx_badalign", "rx_badalign","frame discarded because payload re-alignment failed" },
357 #define S_INPUT AFTER(S_RX_BADALIGN)
358 { 8, "input", "input", "total data frames received" },
359 #define S_RX_UCAST AFTER(S_INPUT)
360 { 8, "rx_ucast", "rx_ucast", "unicast data frames received" },
361 #define S_RX_MCAST AFTER(S_RX_UCAST)
362 { 8, "rx_mcast", "rx_mcast", "multicast data frames received" },
363 #define S_OUTPUT AFTER(S_RX_MCAST)
364 { 8, "output", "output", "total data frames transmit" },
365 #define S_TX_UCAST AFTER(S_OUTPUT)
366 { 8, "tx_ucast", "tx_ucast", "unicast data frames sent" },
367 #define S_TX_MCAST AFTER(S_TX_UCAST)
368 { 8, "tx_mcast", "tx_mcast", "multicast data frames sent" },
369 #define S_RATE AFTER(S_TX_MCAST)
370 { 7, "rate", "rate", "current transmit rate" },
371 #define S_RSSI AFTER(S_RATE)
372 { 6, "rssi", "rssi", "current rssi" },
373 #define S_NOISE AFTER(S_RSSI)
374 { 5, "noise", "noise", "current noise floor (dBm)" },
375 #define S_SIGNAL AFTER(S_NOISE)
376 { 6, "signal", "sig", "current signal (dBm)" },
377 #define S_BEACON_BAD AFTER(S_SIGNAL)
378 { 9, "beacon_bad", "beaconbad", "bad beacons received" },
379 #define S_AMPDU_BARTX AFTER(S_BEACON_BAD)
380 { 5, "ampdu_bartx", "bartx", "BAR frames sent" },
381 #define S_AMPDU_BARTX_FAIL AFTER(S_AMPDU_BARTX)
382 { 9, "ampdu_bartxfail", "bartx_fail", "BAR frames failed to send" },
383 #define S_AMPDU_BARTX_RETRY AFTER(S_AMPDU_BARTX_FAIL)
384 { 10, "ampdu_bartxretry", "bartx_retry", "BAR frames retried" },
385 #define S_CRYPTO_GCMP AFTER(S_AMPDU_BARTX_RETRY)
386 { 11, "crypto_gcmp", "crypto_gcmp", "gcmp crypto done in s/w" },
387 #define S_RX_GCMPREPLAY AFTER(S_CRYPTO_GCMP)
388 { 10, "rx_gcmpreplay", "gcmpreplay", "rx seq# violation (GCMP)" },
389 #define S_RX_GCMPFORMAT AFTER(S_RX_GCMPREPLAY)
390 { 10, "rx_gcmpformat", "gcmpformat", "rx format bad (GCMP)" },
391 #define S_RX_GCMPMIC AFTER(S_RX_GCMPFORMAT)
392 { 7, "rx_gcmpmic", "gcmpmic", "rx MIC check failed (GCMP)" },
393 #define S_RX_GCMPNOMEM AFTER(S_RX_GCMPMIC)
394 { 9, "gcmp_nomem", "gcmpnomem", "No memory available (GCMP)" },
395 #define S_RX_GCMPNOSPC AFTER(S_RX_GCMPNOMEM)
396 { 9, "gcmp_nospc", "gcmpnospc", "No mbuf space available (GCMP)" },
397 };
398
399 struct wlanstatfoo_p {
400 struct wlanstatfoo base;
401 int s;
402 int opmode;
403 uint8_t mac[IEEE80211_ADDR_LEN];
404 struct ifreq ifr;
405 struct ieee80211_stats cur;
406 struct ieee80211_stats total;
407 struct ieee80211req ireq;
408 union {
409 struct ieee80211req_sta_req info;
410 char buf[1024];
411 } u_info;
412 struct ieee80211req_sta_stats ncur;
413 struct ieee80211req_sta_stats ntotal;
414 };
415
416 static void
wlan_setifname(struct wlanstatfoo * wf0,const char * ifname)417 wlan_setifname(struct wlanstatfoo *wf0, const char *ifname)
418 {
419 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
420
421 strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name));
422 strncpy(wf->ireq.i_name, ifname, sizeof (wf->ireq.i_name));
423 }
424
425 static const char *
wlan_getifname(struct wlanstatfoo * wf0)426 wlan_getifname(struct wlanstatfoo *wf0)
427 {
428 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
429
430 return wf->ifr.ifr_name;
431 }
432
433 static int
wlan_getopmode(struct wlanstatfoo * wf0)434 wlan_getopmode(struct wlanstatfoo *wf0)
435 {
436 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
437
438 if (wf->opmode == -1) {
439 struct ifmediareq ifmr;
440
441 memset(&ifmr, 0, sizeof(ifmr));
442 strlcpy(ifmr.ifm_name, wf->ifr.ifr_name, sizeof(ifmr.ifm_name));
443 if (ioctl(wf->s, SIOCGIFMEDIA, &ifmr) < 0)
444 err(1, "%s (SIOCGIFMEDIA)", wf->ifr.ifr_name);
445 if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
446 if (ifmr.ifm_current & IFM_FLAG0)
447 wf->opmode = IEEE80211_M_AHDEMO;
448 else
449 wf->opmode = IEEE80211_M_IBSS;
450 } else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
451 wf->opmode = IEEE80211_M_HOSTAP;
452 else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
453 wf->opmode = IEEE80211_M_MONITOR;
454 else
455 wf->opmode = IEEE80211_M_STA;
456 }
457 return wf->opmode;
458 }
459
460 static void
getlladdr(struct wlanstatfoo_p * wf)461 getlladdr(struct wlanstatfoo_p *wf)
462 {
463 const struct sockaddr_dl *sdl;
464 struct ifaddrs *ifp, *p;
465
466 if (getifaddrs(&ifp) != 0)
467 err(1, "getifaddrs");
468 for (p = ifp; p != NULL; p = p->ifa_next)
469 if (strcmp(p->ifa_name, wf->ifr.ifr_name) == 0 &&
470 p->ifa_addr->sa_family == AF_LINK)
471 break;
472 if (p == NULL)
473 errx(1, "did not find link layer address for interface %s",
474 wf->ifr.ifr_name);
475 sdl = (const struct sockaddr_dl *)(const void *)p->ifa_addr;
476 IEEE80211_ADDR_COPY(wf->mac, sdl->sdl_data + sdl->sdl_nlen);
477 freeifaddrs(ifp);
478 }
479
480 static int
getbssid(struct wlanstatfoo_p * wf)481 getbssid(struct wlanstatfoo_p *wf)
482 {
483 wf->ireq.i_type = IEEE80211_IOC_BSSID;
484 wf->ireq.i_data = wf->mac;
485 wf->ireq.i_len = IEEE80211_ADDR_LEN;
486 return ioctl(wf->s, SIOCG80211, &wf->ireq);
487 }
488
489 static void
wlan_setstamac(struct wlanstatfoo * wf0,const uint8_t * mac)490 wlan_setstamac(struct wlanstatfoo *wf0, const uint8_t *mac)
491 {
492 static const uint8_t zeromac[IEEE80211_ADDR_LEN];
493 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
494
495 if (mac == NULL) {
496 switch (wlan_getopmode(wf0)) {
497 case IEEE80211_M_HOSTAP:
498 case IEEE80211_M_MONITOR:
499 getlladdr(wf);
500 break;
501 case IEEE80211_M_IBSS:
502 case IEEE80211_M_AHDEMO:
503 /*
504 * NB: this may not work in which case the
505 * mac must be specified on the command line
506 */
507 if (getbssid(wf) < 0 ||
508 IEEE80211_ADDR_EQ(wf->mac, zeromac))
509 getlladdr(wf);
510 break;
511 case IEEE80211_M_STA:
512 if (getbssid(wf) < 0)
513 err(1, "%s (IEEE80211_IOC_BSSID)",
514 wf->ireq.i_name);
515 break;
516 }
517 } else
518 IEEE80211_ADDR_COPY(wf->mac, mac);
519 }
520
521 /* XXX only fetch what's needed to do reports */
522 static void
wlan_collect(struct wlanstatfoo_p * wf,struct ieee80211_stats * stats,struct ieee80211req_sta_stats * nstats)523 wlan_collect(struct wlanstatfoo_p *wf,
524 struct ieee80211_stats *stats, struct ieee80211req_sta_stats *nstats)
525 {
526
527 IEEE80211_ADDR_COPY(wf->u_info.info.is_u.macaddr, wf->mac);
528 wf->ireq.i_type = IEEE80211_IOC_STA_INFO;
529 wf->ireq.i_data = (caddr_t) &wf->u_info;
530 wf->ireq.i_len = sizeof(wf->u_info);
531 if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0) {
532 warn("%s:%s (IEEE80211_IOC_STA_INFO)", wf->ireq.i_name,
533 ether_ntoa((const struct ether_addr*) wf->mac));
534 }
535
536 IEEE80211_ADDR_COPY(nstats->is_u.macaddr, wf->mac);
537 wf->ireq.i_type = IEEE80211_IOC_STA_STATS;
538 wf->ireq.i_data = (caddr_t) nstats;
539 wf->ireq.i_len = sizeof(*nstats);
540 if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0)
541 warn("%s:%s (IEEE80211_IOC_STA_STATS)", wf->ireq.i_name,
542 ether_ntoa((const struct ether_addr*) wf->mac));
543
544 wf->ifr.ifr_data = (caddr_t) stats;
545 if (ioctl(wf->s, SIOCG80211STATS, &wf->ifr) < 0)
546 err(1, "%s (SIOCG80211STATS)", wf->ifr.ifr_name);
547 }
548
549 static void
wlan_collect_cur(struct bsdstat * sf)550 wlan_collect_cur(struct bsdstat *sf)
551 {
552 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
553
554 wlan_collect(wf, &wf->cur, &wf->ncur);
555 }
556
557 static void
wlan_collect_tot(struct bsdstat * sf)558 wlan_collect_tot(struct bsdstat *sf)
559 {
560 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
561
562 wlan_collect(wf, &wf->total, &wf->ntotal);
563 }
564
565 static void
wlan_update_tot(struct bsdstat * sf)566 wlan_update_tot(struct bsdstat *sf)
567 {
568 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
569
570 wf->total = wf->cur;
571 wf->ntotal = wf->ncur;
572 }
573
574 static void
setreason(char b[],size_t bs,unsigned int v)575 setreason(char b[], size_t bs, unsigned int v)
576 {
577 static const char *reasons[] = {
578 [IEEE80211_REASON_UNSPECIFIED] = "unspecified",
579 [IEEE80211_REASON_AUTH_EXPIRE] = "auth expire",
580 [IEEE80211_REASON_AUTH_LEAVE] = "auth leave",
581 [IEEE80211_REASON_ASSOC_EXPIRE] = "assoc expire",
582 [IEEE80211_REASON_ASSOC_TOOMANY] = "assoc toomany",
583 [IEEE80211_REASON_NOT_AUTHED] = "not authed",
584 [IEEE80211_REASON_NOT_ASSOCED] = "not assoced",
585 [IEEE80211_REASON_ASSOC_LEAVE] = "assoc leave",
586 [IEEE80211_REASON_ASSOC_NOT_AUTHED] = "assoc not authed",
587 [IEEE80211_REASON_DISASSOC_PWRCAP_BAD] = "disassoc pwrcap bad",
588 [IEEE80211_REASON_DISASSOC_SUPCHAN_BAD] = "disassoc supchan bad",
589 [IEEE80211_REASON_IE_INVALID] = "ie invalid",
590 [IEEE80211_REASON_MIC_FAILURE] = "mic failure",
591 [IEEE80211_REASON_4WAY_HANDSHAKE_TIMEOUT]= "4-way handshake timeout",
592 [IEEE80211_REASON_GROUP_KEY_UPDATE_TIMEOUT] = "group key update timeout",
593 [IEEE80211_REASON_IE_IN_4WAY_DIFFERS] = "ie in 4-way differs",
594 [IEEE80211_REASON_GROUP_CIPHER_INVALID] = "group cipher invalid",
595 [IEEE80211_REASON_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid",
596 [IEEE80211_REASON_AKMP_INVALID] = "akmp invalid",
597 [IEEE80211_REASON_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version",
598 [IEEE80211_REASON_INVALID_RSN_IE_CAP] = "invalid rsn ie cap",
599 [IEEE80211_REASON_802_1X_AUTH_FAILED] = "802.1x auth failed",
600 [IEEE80211_REASON_CIPHER_SUITE_REJECTED]= "cipher suite rejected",
601 };
602 if (v < nitems(reasons) && reasons[v] != NULL)
603 snprintf(b, bs, "%s (%u)", reasons[v], v);
604 else
605 snprintf(b, bs, "%u", v);
606 }
607
608 static void
setstatus(char b[],size_t bs,unsigned int v)609 setstatus(char b[], size_t bs, unsigned int v)
610 {
611 static const char *status[] = {
612 [IEEE80211_STATUS_SUCCESS] = "success",
613 [IEEE80211_STATUS_UNSPECIFIED] = "unspecified",
614 [IEEE80211_STATUS_CAPINFO] = "capinfo",
615 [IEEE80211_STATUS_NOT_ASSOCED] = "not assoced",
616 [IEEE80211_STATUS_OTHER] = "other",
617 [IEEE80211_STATUS_ALG] = "algorithm",
618 [IEEE80211_STATUS_SEQUENCE] = "sequence",
619 [IEEE80211_STATUS_CHALLENGE] = "challenge",
620 [IEEE80211_STATUS_TIMEOUT] = "timeout",
621 [IEEE80211_STATUS_TOOMANY] = "toomany",
622 [IEEE80211_STATUS_BASIC_RATE] = "basic rate",
623 [IEEE80211_STATUS_SP_REQUIRED] = "sp required",
624 [IEEE80211_STATUS_PBCC_REQUIRED] = "pbcc required",
625 [IEEE80211_STATUS_CA_REQUIRED] = "ca required",
626 [IEEE80211_STATUS_SPECMGMT_REQUIRED] = "specmgmt required",
627 [IEEE80211_STATUS_PWRCAP_REQUIRED] = "pwrcap required",
628 [IEEE80211_STATUS_SUPCHAN_REQUIRED] = "supchan required",
629 [IEEE80211_STATUS_SHORTSLOT_REQUIRED] = "shortslot required",
630 [IEEE80211_STATUS_DSSSOFDM_REQUIRED] = "dsssofdm required",
631 [IEEE80211_STATUS_INVALID_IE] = "invalid ie",
632 [IEEE80211_STATUS_GROUP_CIPHER_INVALID] = "group cipher invalid",
633 [IEEE80211_STATUS_PAIRWISE_CIPHER_INVALID]= "pairwise cipher invalid",
634 [IEEE80211_STATUS_AKMP_INVALID] = "akmp invalid",
635 [IEEE80211_STATUS_UNSUPP_RSN_IE_VERSION]= "unsupported rsn ie version",
636 [IEEE80211_STATUS_INVALID_RSN_IE_CAP] = "invalid rsn ie cap",
637 [IEEE80211_STATUS_CIPHER_SUITE_REJECTED]= "cipher suite rejected",
638 };
639 if (v < nitems(status) && status[v] != NULL)
640 snprintf(b, bs, "%s (%u)", status[v], v);
641 else
642 snprintf(b, bs, "%u", v);
643 }
644
645 static int
wlan_getinfo(struct wlanstatfoo_p * wf,int s,char b[],size_t bs)646 wlan_getinfo(struct wlanstatfoo_p *wf, int s, char b[], size_t bs)
647 {
648 const struct ieee80211req_sta_info *si = &wf->u_info.info.info[0];
649
650 switch (s) {
651 case S_RATE:
652 snprintf(b, bs, "%.1fM", (float) si->isi_txmbps/2.0);
653 return 1;
654 case S_RSSI:
655 snprintf(b, bs, "%.1f", (float) si->isi_rssi/2.0);
656 return 1;
657 case S_NOISE:
658 snprintf(b, bs, "%d", si->isi_noise);
659 return 1;
660 case S_SIGNAL:
661 snprintf(b, bs, "%.1f", (float) si->isi_rssi/2.0
662 + (float) si->isi_noise);
663 return 1;
664 case S_RX_AUTH_FAIL_CODE:
665 if (wf->cur.is_rx_authfail_code == 0)
666 break;
667 setstatus(b, bs, wf->cur.is_rx_authfail_code);
668 return 1;
669 case S_RX_DEAUTH_CODE:
670 if (wf->cur.is_rx_deauth_code == 0)
671 break;
672 setreason(b, bs, wf->cur.is_rx_deauth_code);
673 return 1;
674 case S_RX_DISASSOC_CODE:
675 if (wf->cur.is_rx_disassoc_code == 0)
676 break;
677 setreason(b, bs, wf->cur.is_rx_disassoc_code);
678 return 1;
679 }
680 b[0] = '\0';
681 return 0;
682 }
683
684 static int
wlan_get_curstat(struct bsdstat * sf,int s,char b[],size_t bs)685 wlan_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs)
686 {
687 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
688 #define STAT(x) \
689 snprintf(b, bs, "%u", wf->cur.is_##x - wf->total.is_##x); return 1
690 #define NSTAT(x) \
691 snprintf(b, bs, "%u", \
692 wf->ncur.is_stats.ns_##x - wf->ntotal.is_stats.ns_##x); \
693 return 1
694
695 switch (s) {
696 case S_RX_BADVERSION: STAT(rx_badversion);
697 case S_RX_TOOSHORT: STAT(rx_tooshort);
698 case S_RX_WRONGBSS: STAT(rx_wrongbss);
699 case S_RX_DUP: STAT(rx_dup);
700 case S_RX_WRONGDIR: STAT(rx_wrongdir);
701 case S_RX_MCASTECHO: STAT(rx_mcastecho);
702 case S_RX_NOTASSOC: STAT(rx_notassoc);
703 case S_RX_NOPRIVACY: STAT(rx_noprivacy);
704 case S_RX_UNENCRYPTED: STAT(rx_unencrypted);
705 case S_RX_WEPFAIL: STAT(rx_wepfail);
706 case S_RX_DECAP: STAT(rx_decap);
707 case S_RX_MGTDISCARD: STAT(rx_mgtdiscard);
708 case S_RX_CTL: STAT(rx_ctl);
709 case S_RX_BEACON: STAT(rx_beacon);
710 case S_RX_RSTOOBIG: STAT(rx_rstoobig);
711 case S_RX_ELEM_MISSING: STAT(rx_elem_missing);
712 case S_RX_ELEM_TOOBIG: STAT(rx_elem_toobig);
713 case S_RX_ELEM_TOOSMALL: STAT(rx_elem_toosmall);
714 case S_RX_ELEM_UNKNOWN: STAT(rx_elem_unknown);
715 case S_RX_BADCHAN: STAT(rx_badchan);
716 case S_RX_CHANMISMATCH: STAT(rx_chanmismatch);
717 case S_RX_NODEALLOC: STAT(rx_nodealloc);
718 case S_RX_SSIDMISMATCH: STAT(rx_ssidmismatch);
719 case S_RX_AUTH_UNSUPPORTED: STAT(rx_auth_unsupported);
720 case S_RX_AUTH_FAIL: STAT(rx_auth_fail);
721 case S_RX_AUTH_COUNTERMEASURES: STAT(rx_auth_countermeasures);
722 case S_RX_ASSOC_BSS: STAT(rx_assoc_bss);
723 case S_RX_ASSOC_NOTAUTH: STAT(rx_assoc_notauth);
724 case S_RX_ASSOC_CAPMISMATCH: STAT(rx_assoc_capmismatch);
725 case S_RX_ASSOC_NORATE: STAT(rx_assoc_norate);
726 case S_RX_ASSOC_BADWPAIE: STAT(rx_assoc_badwpaie);
727 case S_RX_DEAUTH: STAT(rx_deauth);
728 case S_RX_DISASSOC: STAT(rx_disassoc);
729 case S_BMISS: STAT(beacon_miss);
730 case S_RX_BADSUBTYPE: STAT(rx_badsubtype);
731 case S_RX_NOBUF: STAT(rx_nobuf);
732 case S_RX_DECRYPTCRC: STAT(rx_decryptcrc);
733 case S_RX_AHDEMO_MGT: STAT(rx_ahdemo_mgt);
734 case S_RX_BAD_AUTH: STAT(rx_bad_auth);
735 case S_RX_UNAUTH: STAT(rx_unauth);
736 case S_RX_BADKEYID: STAT(rx_badkeyid);
737 case S_RX_CCMPREPLAY: STAT(rx_ccmpreplay);
738 case S_RX_CCMPFORMAT: STAT(rx_ccmpformat);
739 case S_RX_CCMPMIC: STAT(rx_ccmpmic);
740 case S_RX_TKIPREPLAY: STAT(rx_tkipreplay);
741 case S_RX_TKIPFORMAT: STAT(rx_tkipformat);
742 case S_RX_TKIPMIC: STAT(rx_tkipmic);
743 case S_RX_TKIPICV: STAT(rx_tkipicv);
744 case S_RX_BADCIPHER: STAT(rx_badcipher);
745 case S_RX_NOCIPHERCTX: STAT(rx_nocipherctx);
746 case S_RX_ACL: STAT(rx_acl);
747 case S_TX_NOBUF: STAT(tx_nobuf);
748 case S_TX_NONODE: STAT(tx_nonode);
749 case S_TX_UNKNOWNMGT: STAT(tx_unknownmgt);
750 case S_TX_BADCIPHER: STAT(tx_badcipher);
751 case S_TX_NODEFKEY: STAT(tx_nodefkey);
752 case S_TX_NOHEADROOM: STAT(tx_noheadroom);
753 case S_TX_FRAGFRAMES: STAT(tx_fragframes);
754 case S_TX_FRAGS: STAT(tx_frags);
755 case S_SCAN_ACTIVE: STAT(scan_active);
756 case S_SCAN_PASSIVE: STAT(scan_passive);
757 case S_SCAN_BG: STAT(scan_bg);
758 case S_NODE_TIMEOUT: STAT(node_timeout);
759 case S_CRYPTO_NOMEM: STAT(crypto_nomem);
760 case S_CRYPTO_TKIP: STAT(crypto_tkip);
761 case S_CRYPTO_TKIPENMIC: STAT(crypto_tkipenmic);
762 case S_CRYPTO_TKIPDEMIC: STAT(crypto_tkipdemic);
763 case S_CRYPTO_TKIPCM: STAT(crypto_tkipcm);
764 case S_CRYPTO_CCMP: STAT(crypto_ccmp);
765 case S_CRYPTO_WEP: STAT(crypto_wep);
766 case S_CRYPTO_SETKEY_CIPHER: STAT(crypto_setkey_cipher);
767 case S_CRYPTO_SETKEY_NOKEY: STAT(crypto_setkey_nokey);
768 case S_CRYPTO_DELKEY: STAT(crypto_delkey);
769 case S_CRYPTO_BADCIPHER: STAT(crypto_badcipher);
770 case S_CRYPTO_NOCIPHER: STAT(crypto_nocipher);
771 case S_CRYPTO_ATTACHFAIL: STAT(crypto_attachfail);
772 case S_CRYPTO_SWFALLBACK: STAT(crypto_swfallback);
773 case S_CRYPTO_KEYFAIL: STAT(crypto_keyfail);
774 case S_CRYPTO_ENMICFAIL: STAT(crypto_enmicfail);
775 case S_IBSS_CAPMISMATCH: STAT(ibss_capmismatch);
776 case S_IBSS_NORATE: STAT(ibss_norate);
777 case S_PS_UNASSOC: STAT(ps_unassoc);
778 case S_PS_BADAID: STAT(ps_badaid);
779 case S_PS_QEMPTY: STAT(ps_qempty);
780 case S_FF_BADHDR: STAT(ff_badhdr);
781 case S_FF_TOOSHORT: STAT(ff_tooshort);
782 case S_FF_SPLIT: STAT(ff_split);
783 case S_FF_DECAP: STAT(ff_decap);
784 case S_FF_ENCAP: STAT(ff_encap);
785 case S_FF_ENCAPFAIL: STAT(ff_encapfail);
786 case S_RX_BADBINTVAL: STAT(rx_badbintval);
787 case S_RX_MGMT: STAT(rx_mgmt);
788 case S_RX_DEMICFAIL: STAT(rx_demicfail);
789 case S_RX_DEFRAG: STAT(rx_defrag);
790 case S_RX_ACTION: STAT(rx_action);
791 case S_AMSDU_TOOSHORT: STAT(amsdu_tooshort);
792 case S_AMSDU_SPLIT: STAT(amsdu_split);
793 case S_AMSDU_DECAP: STAT(amsdu_decap);
794 case S_AMSDU_ENCAP: STAT(amsdu_encap);
795 case S_AMSDU_RX_MORE: NSTAT(rx_amsdu_more);
796 case S_AMSDU_RX_MORE_END: NSTAT(rx_amsdu_more_end);
797 case S_AMPDU_REORDER: STAT(ampdu_rx_reorder);
798 case S_AMPDU_FLUSH: STAT(ampdu_rx_flush);
799 case S_AMPDU_BARBAD: STAT(ampdu_bar_bad);
800 case S_AMPDU_BAROOW: STAT(ampdu_bar_oow);
801 case S_AMPDU_BARMOVE: STAT(ampdu_bar_move);
802 case S_AMPDU_BAR: STAT(ampdu_bar_rx);
803 case S_AMPDU_MOVE: STAT(ampdu_rx_move);
804 case S_AMPDU_OOR: STAT(ampdu_rx_oor);
805 case S_AMPDU_COPY: STAT(ampdu_rx_copy);
806 case S_AMPDU_DROP: STAT(ampdu_rx_drop);
807 case S_AMPDU_AGE: STAT(ampdu_rx_age);
808 case S_AMPDU_STOP: STAT(ampdu_stop);
809 case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
810 case S_ADDBA_REJECT: STAT(addba_reject);
811 case S_ADDBA_NOREQUEST: STAT(addba_norequest);
812 case S_ADDBA_BADTOKEN: STAT(addba_badtoken);
813 case S_TX_BADSTATE: STAT(tx_badstate);
814 case S_TX_NOTASSOC: STAT(tx_notassoc);
815 case S_TX_CLASSIFY: STAT(tx_classify);
816 case S_DWDS_MCAST: STAT(dwds_mcast);
817 case S_DWDS_QDROP: STAT(dwds_qdrop);
818 case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
819 case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
820 case S_HT_ASSOC_NORATE: STAT(ht_assoc_norate);
821 case S_MESH_WRONGMESH: STAT(mesh_wrongmesh);
822 case S_MESH_NOLINK: STAT(mesh_nolink);
823 case S_MESH_FWD_TTL: STAT(mesh_fwd_ttl);
824 case S_MESH_FWD_NOBUF: STAT(mesh_fwd_nobuf);
825 case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort);
826 case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled);
827 case S_MESH_FWD_NOPATH: STAT(mesh_fwd_nopath);
828 case S_HWMP_WRONGSEQ: STAT(hwmp_wrongseq);
829 case S_HWMP_ROOTREQS: STAT(hwmp_rootreqs);
830 case S_HWMP_ROOTANN: STAT(hwmp_rootrann);
831 case S_MESH_BADAE: STAT(mesh_badae);
832 case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed);
833 case S_MESH_NOTPROXY: STAT(mesh_notproxy);
834 case S_RX_BADALIGN: STAT(rx_badalign);
835 case S_INPUT: NSTAT(rx_data);
836 case S_OUTPUT: NSTAT(tx_data);
837 case S_RX_UCAST: NSTAT(rx_ucast);
838 case S_RX_MCAST: NSTAT(rx_mcast);
839 case S_TX_UCAST: NSTAT(tx_ucast);
840 case S_TX_MCAST: NSTAT(tx_mcast);
841 case S_BEACON_BAD: STAT(beacon_bad);
842 case S_AMPDU_BARTX: STAT(ampdu_bar_tx);
843 case S_AMPDU_BARTX_RETRY: STAT(ampdu_bar_tx_retry);
844 case S_AMPDU_BARTX_FAIL: STAT(ampdu_bar_tx_fail);
845 case S_CRYPTO_GCMP: STAT(crypto_gcmp);
846 case S_RX_GCMPREPLAY: STAT(rx_gcmpreplay);
847 case S_RX_GCMPFORMAT: STAT(rx_gcmpformat);
848 case S_RX_GCMPMIC: STAT(rx_gcmpmic);
849 case S_RX_GCMPNOMEM: STAT(crypto_gcmp_nomem);
850 case S_RX_GCMPNOSPC: STAT(crypto_gcmp_nospc);
851 }
852 return wlan_getinfo(wf, s, b, bs);
853 #undef NSTAT
854 #undef STAT
855 }
856
857 static int
wlan_get_totstat(struct bsdstat * sf,int s,char b[],size_t bs)858 wlan_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs)
859 {
860 struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
861 #define STAT(x) \
862 snprintf(b, bs, "%u", wf->total.is_##x); return 1
863 #define NSTAT(x) \
864 snprintf(b, bs, "%u", wf->ntotal.is_stats.ns_##x); return 1
865
866 switch (s) {
867 case S_RX_BADVERSION: STAT(rx_badversion);
868 case S_RX_TOOSHORT: STAT(rx_tooshort);
869 case S_RX_WRONGBSS: STAT(rx_wrongbss);
870 case S_RX_DUP: STAT(rx_dup);
871 case S_RX_WRONGDIR: STAT(rx_wrongdir);
872 case S_RX_MCASTECHO: STAT(rx_mcastecho);
873 case S_RX_NOTASSOC: STAT(rx_notassoc);
874 case S_RX_NOPRIVACY: STAT(rx_noprivacy);
875 case S_RX_UNENCRYPTED: STAT(rx_unencrypted);
876 case S_RX_WEPFAIL: STAT(rx_wepfail);
877 case S_RX_DECAP: STAT(rx_decap);
878 case S_RX_MGTDISCARD: STAT(rx_mgtdiscard);
879 case S_RX_CTL: STAT(rx_ctl);
880 case S_RX_BEACON: STAT(rx_beacon);
881 case S_RX_RSTOOBIG: STAT(rx_rstoobig);
882 case S_RX_ELEM_MISSING: STAT(rx_elem_missing);
883 case S_RX_ELEM_TOOBIG: STAT(rx_elem_toobig);
884 case S_RX_ELEM_TOOSMALL: STAT(rx_elem_toosmall);
885 case S_RX_ELEM_UNKNOWN: STAT(rx_elem_unknown);
886 case S_RX_BADCHAN: STAT(rx_badchan);
887 case S_RX_CHANMISMATCH: STAT(rx_chanmismatch);
888 case S_RX_NODEALLOC: STAT(rx_nodealloc);
889 case S_RX_SSIDMISMATCH: STAT(rx_ssidmismatch);
890 case S_RX_AUTH_UNSUPPORTED: STAT(rx_auth_unsupported);
891 case S_RX_AUTH_FAIL: STAT(rx_auth_fail);
892 case S_RX_AUTH_COUNTERMEASURES: STAT(rx_auth_countermeasures);
893 case S_RX_ASSOC_BSS: STAT(rx_assoc_bss);
894 case S_RX_ASSOC_NOTAUTH: STAT(rx_assoc_notauth);
895 case S_RX_ASSOC_CAPMISMATCH: STAT(rx_assoc_capmismatch);
896 case S_RX_ASSOC_NORATE: STAT(rx_assoc_norate);
897 case S_RX_ASSOC_BADWPAIE: STAT(rx_assoc_badwpaie);
898 case S_RX_DEAUTH: STAT(rx_deauth);
899 case S_RX_DISASSOC: STAT(rx_disassoc);
900 case S_BMISS: STAT(beacon_miss);
901 case S_RX_BADSUBTYPE: STAT(rx_badsubtype);
902 case S_RX_NOBUF: STAT(rx_nobuf);
903 case S_RX_DECRYPTCRC: STAT(rx_decryptcrc);
904 case S_RX_AHDEMO_MGT: STAT(rx_ahdemo_mgt);
905 case S_RX_BAD_AUTH: STAT(rx_bad_auth);
906 case S_RX_UNAUTH: STAT(rx_unauth);
907 case S_RX_BADKEYID: STAT(rx_badkeyid);
908 case S_RX_CCMPREPLAY: STAT(rx_ccmpreplay);
909 case S_RX_CCMPFORMAT: STAT(rx_ccmpformat);
910 case S_RX_CCMPMIC: STAT(rx_ccmpmic);
911 case S_RX_TKIPREPLAY: STAT(rx_tkipreplay);
912 case S_RX_TKIPFORMAT: STAT(rx_tkipformat);
913 case S_RX_TKIPMIC: STAT(rx_tkipmic);
914 case S_RX_TKIPICV: STAT(rx_tkipicv);
915 case S_RX_BADCIPHER: STAT(rx_badcipher);
916 case S_RX_NOCIPHERCTX: STAT(rx_nocipherctx);
917 case S_RX_ACL: STAT(rx_acl);
918 case S_TX_NOBUF: STAT(tx_nobuf);
919 case S_TX_NONODE: STAT(tx_nonode);
920 case S_TX_UNKNOWNMGT: STAT(tx_unknownmgt);
921 case S_TX_BADCIPHER: STAT(tx_badcipher);
922 case S_TX_NODEFKEY: STAT(tx_nodefkey);
923 case S_TX_NOHEADROOM: STAT(tx_noheadroom);
924 case S_TX_FRAGFRAMES: STAT(tx_fragframes);
925 case S_TX_FRAGS: STAT(tx_frags);
926 case S_SCAN_ACTIVE: STAT(scan_active);
927 case S_SCAN_PASSIVE: STAT(scan_passive);
928 case S_SCAN_BG: STAT(scan_bg);
929 case S_NODE_TIMEOUT: STAT(node_timeout);
930 case S_CRYPTO_NOMEM: STAT(crypto_nomem);
931 case S_CRYPTO_TKIP: STAT(crypto_tkip);
932 case S_CRYPTO_TKIPENMIC: STAT(crypto_tkipenmic);
933 case S_CRYPTO_TKIPDEMIC: STAT(crypto_tkipdemic);
934 case S_CRYPTO_TKIPCM: STAT(crypto_tkipcm);
935 case S_CRYPTO_CCMP: STAT(crypto_ccmp);
936 case S_CRYPTO_WEP: STAT(crypto_wep);
937 case S_CRYPTO_SETKEY_CIPHER: STAT(crypto_setkey_cipher);
938 case S_CRYPTO_SETKEY_NOKEY: STAT(crypto_setkey_nokey);
939 case S_CRYPTO_DELKEY: STAT(crypto_delkey);
940 case S_CRYPTO_BADCIPHER: STAT(crypto_badcipher);
941 case S_CRYPTO_NOCIPHER: STAT(crypto_nocipher);
942 case S_CRYPTO_ATTACHFAIL: STAT(crypto_attachfail);
943 case S_CRYPTO_SWFALLBACK: STAT(crypto_swfallback);
944 case S_CRYPTO_KEYFAIL: STAT(crypto_keyfail);
945 case S_CRYPTO_ENMICFAIL: STAT(crypto_enmicfail);
946 case S_IBSS_CAPMISMATCH: STAT(ibss_capmismatch);
947 case S_IBSS_NORATE: STAT(ibss_norate);
948 case S_PS_UNASSOC: STAT(ps_unassoc);
949 case S_PS_BADAID: STAT(ps_badaid);
950 case S_PS_QEMPTY: STAT(ps_qempty);
951 case S_FF_BADHDR: STAT(ff_badhdr);
952 case S_FF_TOOSHORT: STAT(ff_tooshort);
953 case S_FF_SPLIT: STAT(ff_split);
954 case S_FF_DECAP: STAT(ff_decap);
955 case S_FF_ENCAP: STAT(ff_encap);
956 case S_FF_ENCAPFAIL: STAT(ff_encapfail);
957 case S_RX_BADBINTVAL: STAT(rx_badbintval);
958 case S_RX_MGMT: STAT(rx_mgmt);
959 case S_RX_DEMICFAIL: STAT(rx_demicfail);
960 case S_RX_DEFRAG: STAT(rx_defrag);
961 case S_RX_ACTION: STAT(rx_action);
962 case S_AMSDU_TOOSHORT: STAT(amsdu_tooshort);
963 case S_AMSDU_SPLIT: STAT(amsdu_split);
964 case S_AMSDU_DECAP: STAT(amsdu_decap);
965 case S_AMSDU_ENCAP: STAT(amsdu_encap);
966 case S_AMSDU_RX_MORE: NSTAT(rx_amsdu_more);
967 case S_AMSDU_RX_MORE_END: NSTAT(rx_amsdu_more_end);
968 case S_AMPDU_REORDER: STAT(ampdu_rx_reorder);
969 case S_AMPDU_FLUSH: STAT(ampdu_rx_flush);
970 case S_AMPDU_BARBAD: STAT(ampdu_bar_bad);
971 case S_AMPDU_BAROOW: STAT(ampdu_bar_oow);
972 case S_AMPDU_BARMOVE: STAT(ampdu_bar_move);
973 case S_AMPDU_BAR: STAT(ampdu_bar_rx);
974 case S_AMPDU_MOVE: STAT(ampdu_rx_move);
975 case S_AMPDU_OOR: STAT(ampdu_rx_oor);
976 case S_AMPDU_COPY: STAT(ampdu_rx_copy);
977 case S_AMPDU_DROP: STAT(ampdu_rx_drop);
978 case S_AMPDU_AGE: STAT(ampdu_rx_age);
979 case S_AMPDU_STOP: STAT(ampdu_stop);
980 case S_AMPDU_STOP_FAILED:STAT(ampdu_stop_failed);
981 case S_ADDBA_REJECT: STAT(addba_reject);
982 case S_ADDBA_NOREQUEST: STAT(addba_norequest);
983 case S_ADDBA_BADTOKEN: STAT(addba_badtoken);
984 case S_TX_BADSTATE: STAT(tx_badstate);
985 case S_TX_NOTASSOC: STAT(tx_notassoc);
986 case S_TX_CLASSIFY: STAT(tx_classify);
987 case S_DWDS_MCAST: STAT(dwds_mcast);
988 case S_DWDS_QDROP: STAT(dwds_qdrop);
989 case S_HT_ASSOC_NOHTCAP:STAT(ht_assoc_nohtcap);
990 case S_HT_ASSOC_DOWNGRADE:STAT(ht_assoc_downgrade);
991 case S_HT_ASSOC_NORATE: STAT(ht_assoc_norate);
992 case S_MESH_WRONGMESH: STAT(mesh_wrongmesh);
993 case S_MESH_NOLINK: STAT(mesh_nolink);
994 case S_MESH_FWD_TTL: STAT(mesh_fwd_ttl);
995 case S_MESH_FWD_NOBUF: STAT(mesh_fwd_nobuf);
996 case S_MESH_FWD_TOOSHORT: STAT(mesh_fwd_tooshort);
997 case S_MESH_FWD_DISABLED: STAT(mesh_fwd_disabled);
998 case S_MESH_FWD_NOPATH: STAT(mesh_fwd_nopath);
999 case S_HWMP_WRONGSEQ: STAT(hwmp_wrongseq);
1000 case S_HWMP_ROOTREQS: STAT(hwmp_rootreqs);
1001 case S_HWMP_ROOTANN: STAT(hwmp_rootrann);
1002 case S_MESH_BADAE: STAT(mesh_badae);
1003 case S_MESH_RTADDFAILED:STAT(mesh_rtaddfailed);
1004 case S_MESH_NOTPROXY: STAT(mesh_notproxy);
1005 case S_RX_BADALIGN: STAT(rx_badalign);
1006 case S_INPUT: NSTAT(rx_data);
1007 case S_OUTPUT: NSTAT(tx_data);
1008 case S_RX_UCAST: NSTAT(rx_ucast);
1009 case S_RX_MCAST: NSTAT(rx_mcast);
1010 case S_TX_UCAST: NSTAT(tx_ucast);
1011 case S_TX_MCAST: NSTAT(tx_mcast);
1012 case S_BEACON_BAD: STAT(beacon_bad);
1013 case S_AMPDU_BARTX: STAT(ampdu_bar_tx);
1014 case S_AMPDU_BARTX_RETRY: STAT(ampdu_bar_tx_retry);
1015 case S_AMPDU_BARTX_FAIL: STAT(ampdu_bar_tx_fail);
1016 case S_CRYPTO_GCMP: STAT(crypto_gcmp);
1017 case S_RX_GCMPREPLAY: STAT(rx_gcmpreplay);
1018 case S_RX_GCMPFORMAT: STAT(rx_gcmpformat);
1019 case S_RX_GCMPMIC: STAT(rx_gcmpmic);
1020 case S_RX_GCMPNOMEM: STAT(crypto_gcmp_nomem);
1021 case S_RX_GCMPNOSPC: STAT(crypto_gcmp_nospc);
1022 }
1023 return wlan_getinfo(wf, s, b, bs);
1024 #undef NSTAT
1025 #undef STAT
1026 }
1027
BSDSTAT_DEFINE_BOUNCE(wlanstatfoo)1028 BSDSTAT_DEFINE_BOUNCE(wlanstatfoo)
1029
1030 struct wlanstatfoo *
1031 wlanstats_new(const char *ifname, const char *fmtstring)
1032 {
1033 struct wlanstatfoo_p *wf;
1034
1035 wf = calloc(1, sizeof(struct wlanstatfoo_p));
1036 if (wf != NULL) {
1037 bsdstat_init(&wf->base.base, "wlanstats", wlanstats,
1038 nitems(wlanstats));
1039 /* override base methods */
1040 wf->base.base.collect_cur = wlan_collect_cur;
1041 wf->base.base.collect_tot = wlan_collect_tot;
1042 wf->base.base.get_curstat = wlan_get_curstat;
1043 wf->base.base.get_totstat = wlan_get_totstat;
1044 wf->base.base.update_tot = wlan_update_tot;
1045
1046 /* setup bounce functions for public methods */
1047 BSDSTAT_BOUNCE(wf, wlanstatfoo);
1048
1049 /* setup our public methods */
1050 wf->base.setifname = wlan_setifname;
1051 wf->base.getifname = wlan_getifname;
1052 wf->base.getopmode = wlan_getopmode;
1053 wf->base.setstamac = wlan_setstamac;
1054 wf->opmode = -1;
1055
1056 wf->s = socket(AF_INET, SOCK_DGRAM, 0);
1057 if (wf->s < 0)
1058 err(1, "socket");
1059
1060 wlan_setifname(&wf->base, ifname);
1061 wf->base.setfmt(&wf->base, fmtstring);
1062 }
1063 return &wf->base;
1064 }
1065