]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/tools/tools/net80211/wlanstats/wlanstats.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / 6 / 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 <signal.h>
54 #include <string.h>
55 #include <unistd.h>
56 #include <err.h>
57 #include <ifaddrs.h>
58
59 #include "../../../../sys/net80211/ieee80211_ioctl.h"
60
61 #include "wlanstats.h"
62
63 #ifndef IEEE80211_ADDR_COPY
64 #define IEEE80211_ADDR_COPY(dst, src)   memcpy(dst, src, IEEE80211_ADDR_LEN)
65 #define IEEE80211_ADDR_EQ(a1,a2)        (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0)
66 #endif
67
68 static const struct fmt wlanstats[] = {
69 #define S_RX_BADVERSION 0
70         { 5,  "rx_badversion",  "badversion",   "rx frame with bad version" },
71 #define S_RX_TOOSHORT   1
72         { 5,  "rx_tooshort",    "tooshort",     "rx frame too short" },
73 #define S_RX_WRONGBSS   2
74         { 5,  "rx_wrongbss",    "wrongbss",     "rx from wrong bssid" },
75 #define S_RX_DUP        3
76         { 5,  "rx_dup", "rx_dup",               "rx discard 'cuz dup" },
77 #define S_RX_WRONGDIR   4
78         { 5,  "rx_wrongdir",    "wrongdir",     "rx w/ wrong direction" },
79 #define S_RX_MCASTECHO  5
80         { 5,  "rx_mcastecho",   "mcastecho",    "rx discard 'cuz mcast echo" },
81 #define S_RX_NOTASSOC   6
82         { 5,  "rx_notassoc",    "notassoc",     "rx discard 'cuz sta !assoc" },
83 #define S_RX_NOPRIVACY  7
84         { 5,  "rx_noprivacy",   "noprivacy",    "rx w/ wep but privacy off" },
85 #define S_RX_UNENCRYPTED        8
86         { 5,  "rx_unencrypted", "unencrypted",  "rx w/o wep and privacy on" },
87 #define S_RX_WEPFAIL    9
88         { 5,  "rx_wepfail",     "wepfail",      "rx wep processing failed" },
89 #define S_RX_DECAP      10
90         { 5,  "rx_decap",       "decap",        "rx decapsulation failed" },
91 #define S_RX_MGTDISCARD 11
92         { 5,  "rx_mgtdiscard",  "mgtdiscard",   "rx discard mgt frames" },
93 #define S_RX_CTL        12
94         { 5,  "rx_ctl",         "ctl",          "rx discard ctrl frames" },
95 #define S_RX_BEACON     13
96         { 5,  "rx_beacon",      "beacon",       "rx beacon frames" },
97 #define S_RX_RSTOOBIG   14
98         { 5,  "rx_rstoobig",    "rstoobig",     "rx rate set truncated" },
99 #define S_RX_ELEM_MISSING       15
100         { 5,  "rx_elem_missing","elem_missing", "rx required element missing" },
101 #define S_RX_ELEM_TOOBIG        16
102         { 5,  "rx_elem_toobig", "elem_toobig",  "rx element too big" },
103 #define S_RX_ELEM_TOOSMALL      17
104         { 5,  "rx_elem_toosmall","elem_toosmall","rx element too small" },
105 #define S_RX_ELEM_UNKNOWN       18
106         { 5,  "rx_elem_unknown","elem_unknown", "rx element unknown" },
107 #define S_RX_BADCHAN    19
108         { 5,  "rx_badchan",     "badchan",      "rx frame w/ invalid chan" },
109 #define S_RX_CHANMISMATCH       20
110         { 5,  "rx_chanmismatch","chanmismatch", "rx frame chan mismatch" },
111 #define S_RX_NODEALLOC  21
112         { 5,  "rx_nodealloc",   "nodealloc",    "nodes allocated (rx)" },
113 #define S_RX_SSIDMISMATCH       22
114         { 5,  "rx_ssidmismatch","ssidmismatch", "rx frame ssid mismatch" },
115 #define S_RX_AUTH_UNSUPPORTED   23
116         { 5,  "rx_auth_unsupported","auth_unsupported",
117                 "rx w/ unsupported auth alg" },
118 #define S_RX_AUTH_FAIL  24
119         { 5,  "rx_auth_fail",   "auth_fail",    "rx sta auth failure" },
120 #define S_RX_AUTH_COUNTERMEASURES       25
121         { 5,  "rx_auth_countermeasures",        "auth_countermeasures",
122                 "rx sta auth failure 'cuz of TKIP countermeasures" },
123 #define S_RX_ASSOC_BSS  26
124         { 5,  "rx_assoc_bss",   "assoc_bss",    "rx assoc from wrong bssid" },
125 #define S_RX_ASSOC_NOTAUTH      27
126         { 5,  "rx_assoc_notauth","assoc_notauth",       "rx assoc w/o auth" },
127 #define S_RX_ASSOC_CAPMISMATCH  28
128         { 5,  "rx_assoc_capmismatch","assoc_capmismatch",
129                 "rx assoc w/ cap mismatch" },
130 #define S_RX_ASSOC_NORATE       29
131         { 5,  "rx_assoc_norate","assoc_norate", "rx assoc w/ no rate match" },
132 #define S_RX_ASSOC_BADWPAIE     30
133         { 5,  "rx_assoc_badwpaie","assoc_badwpaie",
134                 "rx assoc w/ bad WPA IE" },
135 #define S_RX_DEAUTH     31
136         { 5,  "rx_deauth",      "deauth",       "rx deauthentication" },
137 #define S_RX_DISASSOC   32
138         { 5,  "rx_disassoc",    "disassoc",     "rx disassociation" },
139 #define S_RX_BADSUBTYPE 33
140         { 5,  "rx_badsubtype",  "badsubtype",   "rx frame w/ unknown subtype" },
141 #define S_RX_NOBUF      34
142         { 5,  "rx_nobuf",       "nobuf",        "rx failed for lack of mbuf" },
143 #define S_RX_DECRYPTCRC 35
144         { 5,  "rx_decryptcrc",  "decryptcrc",   "rx decrypt failed on crc" },
145 #define S_RX_AHDEMO_MGT 36
146         { 5,  "rx_ahdemo_mgt",  "ahdemo_mgt",
147                 "rx discard mgmt frame received in ahdoc demo mode" },
148 #define S_RX_BAD_AUTH   37
149         { 5,  "rx_bad_auth",    "bad_auth",     "rx bad authentication request" },
150 #define S_RX_UNAUTH     38
151         { 5,  "rx_unauth",      "unauth",
152                 "rx discard 'cuz port unauthorized" },
153 #define S_RX_BADKEYID   39
154         { 5,  "rx_badkeyid",    "badkeyid",     "rx w/ incorrect keyid" },
155 #define S_RX_CCMPREPLAY 40
156         { 5,  "rx_ccmpreplay",  "ccmpreplay",   "rx seq# violation (CCMP)" },
157 #define S_RX_CCMPFORMAT 41
158         { 5,  "rx_ccmpformat",  "ccmpformat",   "rx format bad (CCMP)" },
159 #define S_RX_CCMPMIC    42
160         { 5,  "rx_ccmpmic",     "ccmpmic",      "rx MIC check failed (CCMP)" },
161 #define S_RX_TKIPREPLAY 43
162         { 5,  "rx_tkipreplay",  "tkipreplay",   "rx seq# violation (TKIP)" },
163 #define S_RX_TKIPFORMAT 44
164         { 5,  "rx_tkipformat",  "tkipformat",   "rx format bad (TKIP)" },
165 #define S_RX_TKIPMIC    45
166         { 5,  "rx_tkipmic",     "tkipmic",      "rx MIC check failed (TKIP)" },
167 #define S_RX_TKIPICV    46
168         { 5,  "rx_tkipicv",     "tkipicv",      "rx ICV check failed (TKIP)" },
169 #define S_RX_BADCIPHER  47
170         { 5,  "rx_badcipher",   "badcipher",    "rx failed 'cuz bad cipher/key type" },
171 #define S_RX_NOCIPHERCTX        48
172         { 5,  "rx_nocipherctx", "nocipherctx",  "rx failed 'cuz key/cipher ctx not setup" },
173 #define S_RX_ACL        49
174         { 5,  "rx_acl",         "acl",          "rx discard 'cuz acl policy" },
175 #define S_TX_NOBUF      50
176         { 5,  "tx_nobuf",       "nobuf",        "tx failed for lack of mbuf" },
177 #define S_TX_NONODE     51
178         { 5,  "tx_nonode",      "nonode",       "tx failed for no node" },
179 #define S_TX_UNKNOWNMGT 52
180         { 5,  "tx_unknownmgt",  "unknownmgt",   "tx of unknown mgt frame" },
181 #define S_TX_BADCIPHER  53
182         { 5,  "tx_badcipher",   "badcipher",    "tx failed 'cuz bad ciper/key type" },
183 #define S_TX_NODEFKEY   54
184         { 5,  "tx_nodefkey",    "nodefkey",     "tx failed 'cuz no defkey" },
185 #define S_TX_NOHEADROOM 55
186         { 5,  "tx_noheadroom",  "noheadroom",   "tx failed 'cuz no space for crypto hdrs" },
187 #define S_TX_FRAGFRAMES 56
188         { 5,  "tx_fragframes",  "fragframes",   "tx frames fragmented" },
189 #define S_TX_FRAGS      57
190         { 5,  "tx_frags",       "frags",                "tx frags generated" },
191 #define S_SCAN_ACTIVE   58
192         { 5,  "scan_active",    "scan_active",  "active scans started" },
193 #define S_SCAN_PASSIVE  59
194         { 5,  "scan_passive",   "scan_passive", "passive scans started" },
195 #define S_NODE_TIMEOUT  60
196         { 5,  "node_timeout",   "node_timeout", "nodes timed out inactivity" },
197 #define S_CRYPTO_NOMEM  61
198         { 5,  "crypto_nomem",   "crypto_nomem", "cipher context malloc failed" },
199 #define S_CRYPTO_TKIP   62
200         { 5,  "crypto_tkip",    "crypto_tkip",  "tkip crypto done in s/w" },
201 #define S_CRYPTO_TKIPENMIC      63
202         { 5,  "crypto_tkipenmic","crypto_tkipenmic",    "tkip tx MIC done in s/w" },
203 #define S_CRYPTO_TKIPDEMIC      64
204         { 5,  "crypto_tkipdemic","crypto_tkipdemic",    "tkip rx MIC done in s/w" },
205 #define S_CRYPTO_TKIPCM 65
206         { 5,  "crypto_tkipcm",  "crypto_tkipcm",        "tkip dropped frames 'cuz of countermeasures" },
207 #define S_CRYPTO_CCMP   66
208         { 5,  "crypto_ccmp",    "crypto_ccmp",  "ccmp crypto done in s/w" },
209 #define S_CRYPTO_WEP    67
210         { 5,  "crypto_wep",     "crypto_wep",   "wep crypto done in s/w" },
211 #define S_CRYPTO_SETKEY_CIPHER  68
212         { 5,  "crypto_setkey_cipher",   "crypto_setkey_cipher","setkey failed 'cuz cipher rejected data" },
213 #define S_CRYPTO_SETKEY_NOKEY   69
214         { 5,  "crypto_setkey_nokey",    "crypto_setkey_nokey","setkey failed 'cuz no key index" },
215 #define S_CRYPTO_DELKEY 70
216         { 5,  "crypto_delkey",  "crypto_delkey",        "driver key delete failed" },
217 #define S_CRYPTO_BADCIPHER      71
218         { 5,  "crypto_badcipher","crypto_badcipher",    "setkey failed 'cuz unknown cipher" },
219 #define S_CRYPTO_NOCIPHER       72
220         { 5,  "crypto_nocipher","crypto_nocipher",      "setkey failed 'cuz cipher module unavailable" },
221 #define S_CRYPTO_ATTACHFAIL     73
222         { 5,  "crypto_attachfail","crypto_attachfail",  "setkey failed 'cuz cipher attach failed" },
223 #define S_CRYPTO_SWFALLBACK     74
224         { 5,  "crypto_swfallback","crypto_swfallback",  "crypto fell back to s/w implementation" },
225 #define S_CRYPTO_KEYFAIL        75
226         { 5,  "crypto_keyfail", "crypto_keyfail",       "setkey failed 'cuz driver key alloc failed" },
227 #define S_CRYPTO_ENMICFAIL      76
228         { 5,  "crypto_enmicfail","crypto_enmicfail",    "enmic failed (may be mbuf exhaustion)" },
229 #define S_IBSS_CAPMISMATCH      77
230         { 5,  "ibss_capmismatch","ibss_capmismatch",    "ibss merge faied 'cuz capabilities mismatch" },
231 #define S_IBSS_NORATE   78
232         { 5,  "ibss_norate",    "ibss_norate",  "ibss merge faied 'cuz rate set mismatch" },
233 #define S_PS_UNASSOC    79
234         { 5,  "ps_unassoc",     "ps_unassoc",   "ps-poll received for unassociated station" },
235 #define S_PS_BADAID     80
236         { 5,  "ps_badaid",      "ps_badaid",    "ps-poll received with invalid association id" },
237 #define S_PS_QEMPTY     81
238         { 5,  "ps_qempty",      "ps_qempty",    "ps-poll received with nothing to send" },
239 #define S_FF_BADHDR     82
240         { 5,  "ff_badhdr",      "ff_badhdr",    "fast frame rx'd w/ bad hdr" },
241 #define S_FF_TOOSHORT   83
242         { 5,  "ff_tooshort",    "ff_tooshort",  "fast frame rx decap error" },
243 #define S_FF_SPLIT      84
244         { 5,  "ff_split",       "ff_split",     "fast frame rx split error" },
245 #define S_FF_DECAP      85
246         { 5,  "ff_decap",       "ff_decap",     "fast frames decap'd" },
247 #define S_FF_ENCAP      86
248         { 5,  "ff_encap",       "ff_encap",     "fast frames encap'd for tx" },
249 #define S_FF_ENCAPFAIL  87
250         { 5,  "ff_encapfail",   "ff_encapfail", "fast frames encap failed" },
251 #define S_RX_BADBINTVAL 88
252         { 5,  "rx_badbintval",  "rx_badbintval","rx frame with bogus beacon interval" },
253 #define S_RX_MGMT       89
254         { 5,  "rx_mgmt",        "rx_mgmt",      "rx management frames" },
255 #define S_RX_DEMICFAIL  90
256         { 5,  "rx_demicfail",   "rx_demicfail", "rx demic failed" },
257 #define S_RX_DEFRAG     91
258         { 5,  "rx_defrag",      "rx_defrag",    "rx defragmentation failed" },
259 #define S_INPUT         92
260         { 8,    "input",        "input",        "data frames received" },
261 #define S_OUTPUT        93
262         { 8,    "output",       "output",       "data frames transmit" },
263 #define S_RATE          94
264         { 4,    "rate",         "rate",         "current transmit rate" },
265 #define S_RSSI          95
266         { 4,    "rssi",         "rssi",         "current rssi" },
267 #define S_NOISE         96
268         { 4,    "noise",        "noise",        "current noise floor (dBm)" },
269 #define S_RX_UCAST      97
270         { 8,    "rx_ucast",     "rx_ucast",     "unicast data frames received" },
271 #define S_RX_MCAST      98
272         { 8,    "rx_mcast",     "rx_mcast",     "multicast data frames received" },
273 #define S_TX_UCAST      99
274         { 8,    "tx_ucast",     "tx_ucast",     "unicast data frames sent" },
275 #define S_TX_MCAST      100
276         { 8,    "tx_mcast",     "tx_mcast",     "multicast data frames sent" },
277 #define S_SIGNAL        101
278         { 4,    "signal",       "sig",          "current signal (dBm)" },
279 };
280 #define S_LAST  S_RX_DEFRAG
281 #define S_MAX   S_LAST+1
282
283 struct wlanstatfoo_p {
284         struct wlanstatfoo base;
285         int s;
286         int opmode;
287         uint8_t mac[IEEE80211_ADDR_LEN];
288         struct ifreq ifr;
289         struct ieee80211_stats cur;
290         struct ieee80211_stats total;
291         struct ieee80211req ireq;
292         union {
293                 struct ieee80211req_sta_req info;
294                 char buf[1024];
295         } u_info;
296         struct ieee80211req_sta_stats ncur;
297         struct ieee80211req_sta_stats ntotal;
298 };
299
300 static void
301 wlan_setifname(struct wlanstatfoo *wf0, const char *ifname)
302 {
303         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
304
305         strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name));
306         strncpy(wf->ireq.i_name, ifname, sizeof (wf->ireq.i_name));
307 }
308
309 static const char *
310 wlan_getifname(struct wlanstatfoo *wf0)
311 {
312         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
313
314         return wf->ifr.ifr_name;
315 }
316
317 static int
318 wlan_getopmode(struct wlanstatfoo *wf0)
319 {
320         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
321
322         if (wf->opmode == -1) {
323                 struct ifmediareq ifmr;
324
325                 memset(&ifmr, 0, sizeof(ifmr));
326                 strlcpy(ifmr.ifm_name, wf->ifr.ifr_name, sizeof(ifmr.ifm_name));
327                 if (ioctl(wf->s, SIOCGIFMEDIA, &ifmr) < 0)
328                         err(1, "%s (SIOCGIFMEDIA)", wf->ifr.ifr_name);
329                 if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
330                         wf->opmode = IEEE80211_M_IBSS;  /* XXX ahdemo */
331                 else if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
332                         wf->opmode = IEEE80211_M_HOSTAP;
333                 else if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
334                         wf->opmode = IEEE80211_M_MONITOR;
335                 else
336                         wf->opmode = IEEE80211_M_STA;
337         }
338         return wf->opmode;
339 }
340
341 static void
342 getlladdr(struct wlanstatfoo_p *wf)
343 {
344         const struct sockaddr_dl *sdl;
345         struct ifaddrs *ifp, *p;
346
347         if (getifaddrs(&ifp) != 0)
348                 err(1, "getifaddrs");
349         for (p = ifp; p != NULL; p = p->ifa_next)
350                 if (strcmp(p->ifa_name, wf->ifr.ifr_name) == 0 &&
351                     p->ifa_addr->sa_family == AF_LINK)
352                         break;
353         if (p == NULL)
354                 errx(1, "did not find link layer address for interface %s",
355                         wf->ifr.ifr_name);
356         sdl = (const struct sockaddr_dl *) p->ifa_addr;
357         IEEE80211_ADDR_COPY(wf->mac, LLADDR(sdl));
358         freeifaddrs(ifp);
359 }
360
361 static void
362 wlan_setstamac(struct wlanstatfoo *wf0, const uint8_t *mac)
363 {
364         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) wf0;
365
366         if (mac == NULL) {
367                 switch (wlan_getopmode(wf0)) {
368                 case IEEE80211_M_HOSTAP:
369                 case IEEE80211_M_MONITOR:
370                 case IEEE80211_M_IBSS:
371                 case IEEE80211_M_AHDEMO:
372                         getlladdr(wf);
373                         break;
374                 case IEEE80211_M_STA:
375                         wf->ireq.i_type = IEEE80211_IOC_BSSID;
376                         wf->ireq.i_data = wf->mac;
377                         wf->ireq.i_len = IEEE80211_ADDR_LEN;
378                         if (ioctl(wf->s, SIOCG80211, &wf->ireq) <0)
379                                 err(1, wf->ireq.i_name);
380                         break;
381                 }
382         } else
383                 IEEE80211_ADDR_COPY(wf->mac, mac);
384 }
385
386 /* XXX only fetch what's needed to do reports */
387 static void
388 wlan_collect(struct wlanstatfoo_p *wf,
389         struct ieee80211_stats *stats, struct ieee80211req_sta_stats *nstats)
390 {
391
392         IEEE80211_ADDR_COPY(wf->u_info.info.is_u.macaddr, wf->mac);
393         wf->ireq.i_type = IEEE80211_IOC_STA_INFO;
394         wf->ireq.i_data = (caddr_t) &wf->u_info;
395         wf->ireq.i_len = sizeof(wf->u_info);
396         if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0)
397                 err(1, wf->ireq.i_name);
398
399         IEEE80211_ADDR_COPY(nstats->is_u.macaddr, wf->mac);
400         wf->ireq.i_type = IEEE80211_IOC_STA_STATS;
401         wf->ireq.i_data = (caddr_t) nstats;
402         wf->ireq.i_len = sizeof(*nstats);
403         if (ioctl(wf->s, SIOCG80211, &wf->ireq) < 0)
404                 err(1, wf->ireq.i_name);
405
406         wf->ifr.ifr_data = (caddr_t) stats;
407         if (ioctl(wf->s, SIOCG80211STATS, &wf->ifr) < 0)
408                 err(1, wf->ifr.ifr_name);
409 }
410
411 static void
412 wlan_collect_cur(struct statfoo *sf)
413 {
414         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
415
416         wlan_collect(wf, &wf->cur, &wf->ncur);
417 }
418
419 static void
420 wlan_collect_tot(struct statfoo *sf)
421 {
422         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
423
424         wlan_collect(wf, &wf->total, &wf->ntotal);
425 }
426
427 static void
428 wlan_update_tot(struct statfoo *sf)
429 {
430         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
431
432         wf->total = wf->cur;
433         wf->ntotal = wf->ncur;
434 }
435
436 static int
437 wlan_getinfo(struct wlanstatfoo_p *wf, int s, char b[], size_t bs)
438 {
439         const struct ieee80211req_sta_info *si = &wf->u_info.info.info[0];
440         uint8_t r;
441
442         switch (s) {
443         case S_RATE:
444                 r = si->isi_rates[si->isi_txrate];
445                 snprintf(b, bs, "%uM", (r &~ 0x80) / 2);
446                 return 1;
447         case S_RSSI:
448                 snprintf(b, bs, "%d", si->isi_rssi);
449                 return 1;
450         case S_NOISE:
451                 snprintf(b, bs, "%d", si->isi_noise);
452                 return 1;
453         case S_SIGNAL:
454                 snprintf(b, bs, "%d", si->isi_rssi + si->isi_noise);
455                 return 1;
456         }
457         b[0] = '\0';
458         return 0;
459 }
460
461 static int
462 wlan_get_curstat(struct statfoo *sf, int s, char b[], size_t bs)
463 {
464         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
465 #define STAT(x) \
466         snprintf(b, bs, "%u", wf->cur.is_##x - wf->total.is_##x); return 1
467 #define NSTAT(x) \
468         snprintf(b, bs, "%u", \
469             wf->ncur.is_stats.ns_##x - wf->ntotal.is_stats.ns_##x); \
470             return 1
471
472         switch (s) {
473         case S_RX_BADVERSION:   STAT(rx_badversion);
474         case S_RX_TOOSHORT:     STAT(rx_tooshort);
475         case S_RX_WRONGBSS:     STAT(rx_wrongbss);
476         case S_RX_DUP:          STAT(rx_dup);
477         case S_RX_WRONGDIR:     STAT(rx_wrongdir);
478         case S_RX_MCASTECHO:    STAT(rx_mcastecho);
479         case S_RX_NOTASSOC:     STAT(rx_notassoc);
480         case S_RX_NOPRIVACY:    STAT(rx_noprivacy);
481         case S_RX_UNENCRYPTED:  STAT(rx_unencrypted);
482         case S_RX_WEPFAIL:      STAT(rx_wepfail);
483         case S_RX_DECAP:        STAT(rx_decap);
484         case S_RX_MGTDISCARD:   STAT(rx_mgtdiscard);
485         case S_RX_CTL:          STAT(rx_ctl);
486         case S_RX_BEACON:       STAT(rx_beacon);
487         case S_RX_RSTOOBIG:     STAT(rx_rstoobig);
488         case S_RX_ELEM_MISSING: STAT(rx_elem_missing);
489         case S_RX_ELEM_TOOBIG:  STAT(rx_elem_toobig);
490         case S_RX_ELEM_TOOSMALL:        STAT(rx_elem_toosmall);
491         case S_RX_ELEM_UNKNOWN: STAT(rx_elem_unknown);
492         case S_RX_BADCHAN:      STAT(rx_badchan);
493         case S_RX_CHANMISMATCH: STAT(rx_chanmismatch);
494         case S_RX_NODEALLOC:    STAT(rx_nodealloc);
495         case S_RX_SSIDMISMATCH: STAT(rx_ssidmismatch);
496         case S_RX_AUTH_UNSUPPORTED:     STAT(rx_auth_unsupported);
497         case S_RX_AUTH_FAIL:    STAT(rx_auth_fail);
498         case S_RX_AUTH_COUNTERMEASURES: STAT(rx_auth_countermeasures);
499         case S_RX_ASSOC_BSS:    STAT(rx_assoc_bss);
500         case S_RX_ASSOC_NOTAUTH:        STAT(rx_assoc_notauth);
501         case S_RX_ASSOC_CAPMISMATCH:    STAT(rx_assoc_capmismatch);
502         case S_RX_ASSOC_NORATE: STAT(rx_assoc_norate);
503         case S_RX_ASSOC_BADWPAIE:       STAT(rx_assoc_badwpaie);
504         case S_RX_DEAUTH:       STAT(rx_deauth);
505         case S_RX_DISASSOC:     STAT(rx_disassoc);
506         case S_RX_BADSUBTYPE:   STAT(rx_badsubtype);
507         case S_RX_NOBUF:        STAT(rx_nobuf);
508         case S_RX_DECRYPTCRC:   STAT(rx_decryptcrc);
509         case S_RX_AHDEMO_MGT:   STAT(rx_ahdemo_mgt);
510         case S_RX_BAD_AUTH:     STAT(rx_bad_auth);
511         case S_RX_UNAUTH:       STAT(rx_unauth);
512         case S_RX_BADKEYID:     STAT(rx_badkeyid);
513         case S_RX_CCMPREPLAY:   STAT(rx_ccmpreplay);
514         case S_RX_CCMPFORMAT:   STAT(rx_ccmpformat);
515         case S_RX_CCMPMIC:      STAT(rx_ccmpmic);
516         case S_RX_TKIPREPLAY:   STAT(rx_tkipreplay);
517         case S_RX_TKIPFORMAT:   STAT(rx_tkipformat);
518         case S_RX_TKIPMIC:      STAT(rx_tkipmic);
519         case S_RX_TKIPICV:      STAT(rx_tkipicv);
520         case S_RX_BADCIPHER:    STAT(rx_badcipher);
521         case S_RX_NOCIPHERCTX:  STAT(rx_nocipherctx);
522         case S_RX_ACL:          STAT(rx_acl);
523         case S_TX_NOBUF:        STAT(tx_nobuf);
524         case S_TX_NONODE:       STAT(tx_nonode);
525         case S_TX_UNKNOWNMGT:   STAT(tx_unknownmgt);
526         case S_TX_BADCIPHER:    STAT(tx_badcipher);
527         case S_TX_NODEFKEY:     STAT(tx_nodefkey);
528         case S_TX_NOHEADROOM:   STAT(tx_noheadroom);
529         case S_TX_FRAGFRAMES:   STAT(tx_fragframes);
530         case S_TX_FRAGS:        STAT(tx_frags);
531         case S_SCAN_ACTIVE:     STAT(scan_active);
532         case S_SCAN_PASSIVE:    STAT(scan_passive);
533         case S_NODE_TIMEOUT:    STAT(node_timeout);
534         case S_CRYPTO_NOMEM:    STAT(crypto_nomem);
535         case S_CRYPTO_TKIP:     STAT(crypto_tkip);
536         case S_CRYPTO_TKIPENMIC:        STAT(crypto_tkipenmic);
537         case S_CRYPTO_TKIPDEMIC:        STAT(crypto_tkipdemic);
538         case S_CRYPTO_TKIPCM:   STAT(crypto_tkipcm);
539         case S_CRYPTO_CCMP:     STAT(crypto_ccmp);
540         case S_CRYPTO_WEP:      STAT(crypto_wep);
541         case S_CRYPTO_SETKEY_CIPHER:    STAT(crypto_setkey_cipher);
542         case S_CRYPTO_SETKEY_NOKEY:     STAT(crypto_setkey_nokey);
543         case S_CRYPTO_DELKEY:   STAT(crypto_delkey);
544         case S_CRYPTO_BADCIPHER:        STAT(crypto_badcipher);
545         case S_CRYPTO_NOCIPHER: STAT(crypto_nocipher);
546         case S_CRYPTO_ATTACHFAIL:       STAT(crypto_attachfail);
547         case S_CRYPTO_SWFALLBACK:       STAT(crypto_swfallback);
548         case S_CRYPTO_KEYFAIL:  STAT(crypto_keyfail);
549         case S_CRYPTO_ENMICFAIL:        STAT(crypto_enmicfail);
550         case S_IBSS_CAPMISMATCH:        STAT(ibss_capmismatch);
551         case S_IBSS_NORATE:     STAT(ibss_norate);
552         case S_PS_UNASSOC:      STAT(ps_unassoc);
553         case S_PS_BADAID:       STAT(ps_badaid);
554         case S_PS_QEMPTY:       STAT(ps_qempty);
555         case S_FF_BADHDR:       STAT(ff_badhdr);
556         case S_FF_TOOSHORT:     STAT(ff_tooshort);
557         case S_FF_SPLIT:        STAT(ff_split);
558         case S_FF_DECAP:        STAT(ff_decap);
559         case S_FF_ENCAP:        STAT(ff_encap);
560         case S_RX_BADBINTVAL:   STAT(rx_badbintval);
561         case S_RX_MGMT:         STAT(rx_mgmt);
562         case S_RX_DEMICFAIL:    STAT(rx_demicfail);
563         case S_RX_DEFRAG:       STAT(rx_defrag);
564         case S_INPUT:           NSTAT(rx_data);
565         case S_OUTPUT:          NSTAT(tx_data);
566         case S_RX_UCAST:        NSTAT(rx_ucast);
567         case S_RX_MCAST:        NSTAT(rx_mcast);
568         case S_TX_UCAST:        NSTAT(tx_ucast);
569         case S_TX_MCAST:        NSTAT(tx_mcast);
570         }
571         return wlan_getinfo(wf, s, b, bs);
572 #undef NSTAT
573 #undef STAT
574 }
575
576 static int
577 wlan_get_totstat(struct statfoo *sf, int s, char b[], size_t bs)
578 {
579         struct wlanstatfoo_p *wf = (struct wlanstatfoo_p *) sf;
580 #define STAT(x) \
581         snprintf(b, bs, "%u", wf->total.is_##x); return 1
582 #define NSTAT(x) \
583         snprintf(b, bs, "%u", wf->ntotal.is_stats.ns_##x); return 1
584
585         switch (s) {
586         case S_RX_BADVERSION:   STAT(rx_badversion);
587         case S_RX_TOOSHORT:     STAT(rx_tooshort);
588         case S_RX_WRONGBSS:     STAT(rx_wrongbss);
589         case S_RX_DUP:  STAT(rx_dup);
590         case S_RX_WRONGDIR:     STAT(rx_wrongdir);
591         case S_RX_MCASTECHO:    STAT(rx_mcastecho);
592         case S_RX_NOTASSOC:     STAT(rx_notassoc);
593         case S_RX_NOPRIVACY:    STAT(rx_noprivacy);
594         case S_RX_UNENCRYPTED:  STAT(rx_unencrypted);
595         case S_RX_WEPFAIL:      STAT(rx_wepfail);
596         case S_RX_DECAP:        STAT(rx_decap);
597         case S_RX_MGTDISCARD:   STAT(rx_mgtdiscard);
598         case S_RX_CTL:          STAT(rx_ctl);
599         case S_RX_BEACON:       STAT(rx_beacon);
600         case S_RX_RSTOOBIG:     STAT(rx_rstoobig);
601         case S_RX_ELEM_MISSING: STAT(rx_elem_missing);
602         case S_RX_ELEM_TOOBIG:  STAT(rx_elem_toobig);
603         case S_RX_ELEM_TOOSMALL:        STAT(rx_elem_toosmall);
604         case S_RX_ELEM_UNKNOWN: STAT(rx_elem_unknown);
605         case S_RX_BADCHAN:      STAT(rx_badchan);
606         case S_RX_CHANMISMATCH: STAT(rx_chanmismatch);
607         case S_RX_NODEALLOC:    STAT(rx_nodealloc);
608         case S_RX_SSIDMISMATCH: STAT(rx_ssidmismatch);
609         case S_RX_AUTH_UNSUPPORTED:     STAT(rx_auth_unsupported);
610         case S_RX_AUTH_FAIL:    STAT(rx_auth_fail);
611         case S_RX_AUTH_COUNTERMEASURES: STAT(rx_auth_countermeasures);
612         case S_RX_ASSOC_BSS:    STAT(rx_assoc_bss);
613         case S_RX_ASSOC_NOTAUTH:        STAT(rx_assoc_notauth);
614         case S_RX_ASSOC_CAPMISMATCH:    STAT(rx_assoc_capmismatch);
615         case S_RX_ASSOC_NORATE: STAT(rx_assoc_norate);
616         case S_RX_ASSOC_BADWPAIE:       STAT(rx_assoc_badwpaie);
617         case S_RX_DEAUTH:       STAT(rx_deauth);
618         case S_RX_DISASSOC:     STAT(rx_disassoc);
619         case S_RX_BADSUBTYPE:   STAT(rx_badsubtype);
620         case S_RX_NOBUF:        STAT(rx_nobuf);
621         case S_RX_DECRYPTCRC:   STAT(rx_decryptcrc);
622         case S_RX_AHDEMO_MGT:   STAT(rx_ahdemo_mgt);
623         case S_RX_BAD_AUTH:     STAT(rx_bad_auth);
624         case S_RX_UNAUTH:       STAT(rx_unauth);
625         case S_RX_BADKEYID:     STAT(rx_badkeyid);
626         case S_RX_CCMPREPLAY:   STAT(rx_ccmpreplay);
627         case S_RX_CCMPFORMAT:   STAT(rx_ccmpformat);
628         case S_RX_CCMPMIC:      STAT(rx_ccmpmic);
629         case S_RX_TKIPREPLAY:   STAT(rx_tkipreplay);
630         case S_RX_TKIPFORMAT:   STAT(rx_tkipformat);
631         case S_RX_TKIPMIC:      STAT(rx_tkipmic);
632         case S_RX_TKIPICV:      STAT(rx_tkipicv);
633         case S_RX_BADCIPHER:    STAT(rx_badcipher);
634         case S_RX_NOCIPHERCTX:  STAT(rx_nocipherctx);
635         case S_RX_ACL:          STAT(rx_acl);
636         case S_TX_NOBUF:        STAT(tx_nobuf);
637         case S_TX_NONODE:       STAT(tx_nonode);
638         case S_TX_UNKNOWNMGT:   STAT(tx_unknownmgt);
639         case S_TX_BADCIPHER:    STAT(tx_badcipher);
640         case S_TX_NODEFKEY:     STAT(tx_nodefkey);
641         case S_TX_NOHEADROOM:   STAT(tx_noheadroom);
642         case S_TX_FRAGFRAMES:   STAT(tx_fragframes);
643         case S_TX_FRAGS:        STAT(tx_frags);
644         case S_SCAN_ACTIVE:     STAT(scan_active);
645         case S_SCAN_PASSIVE:    STAT(scan_passive);
646         case S_NODE_TIMEOUT:    STAT(node_timeout);
647         case S_CRYPTO_NOMEM:    STAT(crypto_nomem);
648         case S_CRYPTO_TKIP:     STAT(crypto_tkip);
649         case S_CRYPTO_TKIPENMIC:        STAT(crypto_tkipenmic);
650         case S_CRYPTO_TKIPDEMIC:        STAT(crypto_tkipdemic);
651         case S_CRYPTO_TKIPCM:   STAT(crypto_tkipcm);
652         case S_CRYPTO_CCMP:     STAT(crypto_ccmp);
653         case S_CRYPTO_WEP:      STAT(crypto_wep);
654         case S_CRYPTO_SETKEY_CIPHER:    STAT(crypto_setkey_cipher);
655         case S_CRYPTO_SETKEY_NOKEY:     STAT(crypto_setkey_nokey);
656         case S_CRYPTO_DELKEY:   STAT(crypto_delkey);
657         case S_CRYPTO_BADCIPHER:        STAT(crypto_badcipher);
658         case S_CRYPTO_NOCIPHER: STAT(crypto_nocipher);
659         case S_CRYPTO_ATTACHFAIL:       STAT(crypto_attachfail);
660         case S_CRYPTO_SWFALLBACK:       STAT(crypto_swfallback);
661         case S_CRYPTO_KEYFAIL:  STAT(crypto_keyfail);
662         case S_CRYPTO_ENMICFAIL:        STAT(crypto_enmicfail);
663         case S_IBSS_CAPMISMATCH:        STAT(ibss_capmismatch);
664         case S_IBSS_NORATE:     STAT(ibss_norate);
665         case S_PS_UNASSOC:      STAT(ps_unassoc);
666         case S_PS_BADAID:       STAT(ps_badaid);
667         case S_PS_QEMPTY:       STAT(ps_qempty);
668         case S_FF_BADHDR:       STAT(ff_badhdr);
669         case S_FF_TOOSHORT:     STAT(ff_tooshort);
670         case S_FF_SPLIT:        STAT(ff_split);
671         case S_FF_DECAP:        STAT(ff_decap);
672         case S_FF_ENCAP:        STAT(ff_encap);
673         case S_RX_BADBINTVAL:   STAT(rx_badbintval);
674         case S_RX_MGMT:         STAT(rx_mgmt);
675         case S_RX_DEMICFAIL:    STAT(rx_demicfail);
676         case S_RX_DEFRAG:       STAT(rx_defrag);
677         case S_INPUT:           NSTAT(rx_data);
678         case S_OUTPUT:          NSTAT(tx_data);
679         case S_RX_UCAST:        NSTAT(rx_ucast);
680         case S_RX_MCAST:        NSTAT(rx_mcast);
681         case S_TX_UCAST:        NSTAT(tx_ucast);
682         case S_TX_MCAST:        NSTAT(tx_mcast);
683         }
684         return wlan_getinfo(wf, s, b, bs);
685 #undef NSTAT
686 #undef STAT
687 }
688
689 STATFOO_DEFINE_BOUNCE(wlanstatfoo)
690
691 struct wlanstatfoo *
692 wlanstats_new(const char *ifname, const char *fmtstring)
693 {
694 #define N(a)    (sizeof(a) / sizeof(a[0]))
695         struct wlanstatfoo_p *wf;
696
697         wf = calloc(1, sizeof(struct wlanstatfoo_p));
698         if (wf != NULL) {
699                 statfoo_init(&wf->base.base, "wlanstats", wlanstats, N(wlanstats));
700                 /* override base methods */
701                 wf->base.base.collect_cur = wlan_collect_cur;
702                 wf->base.base.collect_tot = wlan_collect_tot;
703                 wf->base.base.get_curstat = wlan_get_curstat;
704                 wf->base.base.get_totstat = wlan_get_totstat;
705                 wf->base.base.update_tot = wlan_update_tot;
706
707                 /* setup bounce functions for public methods */
708                 STATFOO_BOUNCE(wf, wlanstatfoo);
709
710                 /* setup our public methods */
711                 wf->base.setifname = wlan_setifname;
712                 wf->base.getifname = wlan_getifname;
713                 wf->base.getopmode = wlan_getopmode;
714                 wf->base.setstamac = wlan_setstamac;
715                 wf->opmode = -1;
716
717                 wf->s = socket(AF_INET, SOCK_DGRAM, 0);
718                 if (wf->s < 0)
719                         err(1, "socket");
720
721                 wlan_setifname(&wf->base, ifname);
722                 wf->base.setfmt(&wf->base, fmtstring);
723         }
724         return &wf->base;
725 #undef N
726 }