]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - tools/tools/net80211/wlanstats/main.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / tools / tools / net80211 / wlanstats / main.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  * wlanstats [-i interface]
41  * (default interface is ath0).
42  */
43
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <net/ethernet.h>
47 #include <net80211/_ieee80211.h>
48
49 #include <stdio.h>
50 #include <signal.h>
51 #include <unistd.h>
52 #include <err.h>
53
54 #include "wlanstats.h"
55
56 #define S_DEFAULT \
57         "input,output,rx_ucast,rx_mcast,tx_ucast,tx_mcast,rssi,rate"
58 #define S_AMPDU \
59         "input,output,ampdu_reorder,ampdu_oor,rx_dup,ampdu_flush,ampdu_move,ampdu_drop,ampdu_bar,ampdu_baroow,ampdu_barmove,rssi,rate"
60
61 static int signalled;
62
63 static void
64 catchalarm(int signo __unused)
65 {
66         signalled = 1;
67 }
68
69 #if 0
70 static void
71 print_sta_stats(FILE *fd, const u_int8_t macaddr[IEEE80211_ADDR_LEN])
72 {
73 #define STAT(x,fmt) \
74         if (ns->ns_##x) { fprintf(fd, "%s" #x " " fmt, sep, ns->ns_##x); sep = " "; }
75         struct ieee80211req ireq;
76         struct ieee80211req_sta_stats stats;
77         const struct ieee80211_nodestats *ns = &stats.is_stats;
78         const char *sep;
79
80         (void) memset(&ireq, 0, sizeof(ireq));
81         (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name));
82         ireq.i_type = IEEE80211_IOC_STA_STATS;
83         ireq.i_data = &stats;
84         ireq.i_len = sizeof(stats);
85         memcpy(stats.is_u.macaddr, macaddr, IEEE80211_ADDR_LEN);
86         if (ioctl(s, SIOCG80211, &ireq) < 0)
87                 err(1, "unable to get station stats for %s",
88                         ether_ntoa((const struct ether_addr*) macaddr));
89
90         fprintf(fd, "%s:\n", ether_ntoa((const struct ether_addr*) macaddr));
91
92         sep = "\t";
93         STAT(rx_data, "%u");
94         STAT(rx_mgmt, "%u");
95         STAT(rx_ctrl, "%u");
96         STAT(rx_beacons, "%u");
97         STAT(rx_proberesp, "%u");
98         STAT(rx_ucast, "%u");
99         STAT(rx_mcast, "%u");
100         STAT(rx_bytes, "%llu");
101         STAT(rx_dup, "%u");
102         STAT(rx_noprivacy, "%u");
103         STAT(rx_wepfail, "%u");
104         STAT(rx_demicfail, "%u");
105         STAT(rx_decap, "%u");
106         STAT(rx_defrag, "%u");
107         STAT(rx_disassoc, "%u");
108         STAT(rx_deauth, "%u");
109         STAT(rx_decryptcrc, "%u");
110         STAT(rx_unauth, "%u");
111         STAT(rx_unencrypted, "%u");
112         fprintf(fd, "\n");
113
114         sep = "\t";
115         STAT(tx_data, "%u");
116         STAT(tx_mgmt, "%u");
117         STAT(tx_probereq, "%u");
118         STAT(tx_ucast, "%u");
119         STAT(tx_mcast, "%u");
120         STAT(tx_bytes, "%llu");
121         STAT(tx_novlantag, "%u");
122         STAT(tx_vlanmismatch, "%u");
123         fprintf(fd, "\n");
124
125         sep = "\t";
126         STAT(tx_assoc, "%u");
127         STAT(tx_assoc_fail, "%u");
128         STAT(tx_auth, "%u");
129         STAT(tx_auth_fail, "%u");
130         STAT(tx_deauth, "%u");
131         STAT(tx_deauth_code, "%llu");
132         STAT(tx_disassoc, "%u");
133         STAT(tx_disassoc_code, "%u");
134         fprintf(fd, "\n");
135
136 #undef STAT
137 }
138 #endif
139
140 int
141 main(int argc, char *argv[])
142 {
143         struct wlanstatfoo *wf;
144         struct ether_addr *ea;
145         const uint8_t *mac = NULL;
146         int allnodes = 0;
147         int c, mode;
148
149         wf = wlanstats_new("ath0", S_DEFAULT);
150         while ((c = getopt(argc, argv, "ai:lm:o:")) != -1) {
151                 switch (c) {
152                 case 'a':
153                         allnodes++;
154                         break;
155                 case 'i':
156                         wf->setifname(wf, optarg);
157                         break;
158                 case 'l':
159                         wf->print_fields(wf, stdout);
160                         return 0;
161                 case 'm':
162                         ea = ether_aton(optarg);
163                         if (!ea)
164                                 errx(1, "%s: invalid ethernet address", optarg);
165                         mac = ea->octet;
166                         break;
167                 case 'o':
168                         if (strcasecmp(optarg, "ampdu") == 0)
169                                 wf->setfmt(wf, S_AMPDU);
170                         else
171                                 wf->setfmt(wf, optarg);
172                         break;
173                 default:
174                         errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [interval]\n", argv[0]);
175                         /*NOTREACHED*/
176                 }
177         }
178         argc -= optind;
179         argv += optind;
180
181         mode = wf->getopmode(wf);
182         wf->setstamac(wf, mac);
183
184         if (argc > 0) {
185                 u_long interval = strtoul(argv[0], NULL, 0);
186                 int line, omask;
187
188                 if (interval < 1)
189                         interval = 1;
190                 signal(SIGALRM, catchalarm);
191                 signalled = 0;
192                 alarm(interval);
193         banner:
194                 wf->print_header(wf, stdout);
195                 line = 0;
196         loop:
197                 if (line != 0) {
198                         wf->collect_cur(wf);
199                         wf->print_current(wf, stdout);
200                         wf->update_tot(wf);
201                 } else {
202                         wf->collect_tot(wf);
203                         wf->print_total(wf, stdout);
204                 }
205                 fflush(stdout);
206                 omask = sigblock(sigmask(SIGALRM));
207                 if (!signalled)
208                         sigpause(0);
209                 sigsetmask(omask);
210                 signalled = 0;
211                 alarm(interval);
212                 line++;
213                 /* refresh every display in case sta roams */
214                 if (mac == NULL && mode == IEEE80211_M_STA)
215                         wf->setstamac(wf, NULL);
216                 if (line == 21)         /* XXX tty line count */
217                         goto banner;
218                 else
219                         goto loop;
220                 /*NOTREACHED*/
221 #if 0
222         } else if (allnodes) {
223                 struct ieee80211req_sta_info *si;
224                 union {
225                         struct ieee80211req_sta_req req;
226                         uint8_t buf[24*1024];
227                 } u;
228                 uint8_t *cp;
229                 struct ieee80211req ireq;
230                 int len;
231
232                 /*
233                  * Retrieve station/neighbor table and print stats for each.
234                  */
235                 (void) memset(&ireq, 0, sizeof(ireq));
236                 (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name));
237                 ireq.i_type = IEEE80211_IOC_STA_INFO;
238                 memset(&u.req.macaddr, 0xff, sizeof(u.req.macaddr));
239                 ireq.i_data = &u;
240                 ireq.i_len = sizeof(u);
241                 if (ioctl(s, SIOCG80211, &ireq) < 0)
242                         err(1, "unable to get station information");
243                 len = ireq.i_len;
244                 if (len >= sizeof(struct ieee80211req_sta_info)) {
245                         cp = u.req.info;
246                         do {
247                                 si = (struct ieee80211req_sta_info *) cp;
248                                 if (si->isi_len < sizeof(*si))
249                                         break;
250                                 print_sta_stats(stdout, si->isi_macaddr);
251                                 cp += si->isi_len, len -= si->isi_len;
252                         } while (len >= sizeof(struct ieee80211req_sta_info));
253                 }
254 #endif
255         } else {
256                 wf->collect_tot(wf);
257                 wf->print_verbose(wf, stdout);
258         }
259         return 0;
260 }