main.c revision 174244
1/*- 2 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 * $FreeBSD: head/tools/tools/net80211/wlanstats/main.c 174244 2007-12-04 05:52:01Z sam $ 30 */ 31 32/* 33 * wlanstats [-i interface] 34 * (default interface is ath0). 35 */ 36 37#include <sys/types.h> 38#include <sys/socket.h> 39#include <net/ethernet.h> 40#include <net80211/_ieee80211.h> 41 42#include <stdio.h> 43#include <signal.h> 44#include <unistd.h> 45#include <err.h> 46 47#include "wlanstats.h" 48 49#define S_DEFAULT \ 50 "input,output,rx_ucast,rx_mcast,tx_ucast,tx_mcast,rssi,rate" 51#define S_AMPDU \ 52 "input,output,ampdu_reorder,ampdu_oor,rx_dup,ampdu_flush,ampdu_move,ampdu_drop,ampdu_bar,ampdu_baroow,ampdu_barmove,rssi,rate" 53 54static int signalled; 55 56static void 57catchalarm(int signo __unused) 58{ 59 signalled = 1; 60} 61 62#if 0 63static void 64print_sta_stats(FILE *fd, const u_int8_t macaddr[IEEE80211_ADDR_LEN]) 65{ 66#define STAT(x,fmt) \ 67 if (ns->ns_##x) { fprintf(fd, "%s" #x " " fmt, sep, ns->ns_##x); sep = " "; } 68 struct ieee80211req ireq; 69 struct ieee80211req_sta_stats stats; 70 const struct ieee80211_nodestats *ns = &stats.is_stats; 71 const char *sep; 72 73 (void) memset(&ireq, 0, sizeof(ireq)); 74 (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name)); 75 ireq.i_type = IEEE80211_IOC_STA_STATS; 76 ireq.i_data = &stats; 77 ireq.i_len = sizeof(stats); 78 memcpy(stats.is_u.macaddr, macaddr, IEEE80211_ADDR_LEN); 79 if (ioctl(s, SIOCG80211, &ireq) < 0) 80 err(1, "unable to get station stats for %s", 81 ether_ntoa((const struct ether_addr*) macaddr)); 82 83 fprintf(fd, "%s:\n", ether_ntoa((const struct ether_addr*) macaddr)); 84 85 sep = "\t"; 86 STAT(rx_data, "%u"); 87 STAT(rx_mgmt, "%u"); 88 STAT(rx_ctrl, "%u"); 89 STAT(rx_beacons, "%u"); 90 STAT(rx_proberesp, "%u"); 91 STAT(rx_ucast, "%u"); 92 STAT(rx_mcast, "%u"); 93 STAT(rx_bytes, "%llu"); 94 STAT(rx_dup, "%u"); 95 STAT(rx_noprivacy, "%u"); 96 STAT(rx_wepfail, "%u"); 97 STAT(rx_demicfail, "%u"); 98 STAT(rx_decap, "%u"); 99 STAT(rx_defrag, "%u"); 100 STAT(rx_disassoc, "%u"); 101 STAT(rx_deauth, "%u"); 102 STAT(rx_decryptcrc, "%u"); 103 STAT(rx_unauth, "%u"); 104 STAT(rx_unencrypted, "%u"); 105 fprintf(fd, "\n"); 106 107 sep = "\t"; 108 STAT(tx_data, "%u"); 109 STAT(tx_mgmt, "%u"); 110 STAT(tx_probereq, "%u"); 111 STAT(tx_ucast, "%u"); 112 STAT(tx_mcast, "%u"); 113 STAT(tx_bytes, "%llu"); 114 STAT(tx_novlantag, "%u"); 115 STAT(tx_vlanmismatch, "%u"); 116 fprintf(fd, "\n"); 117 118 sep = "\t"; 119 STAT(tx_assoc, "%u"); 120 STAT(tx_assoc_fail, "%u"); 121 STAT(tx_auth, "%u"); 122 STAT(tx_auth_fail, "%u"); 123 STAT(tx_deauth, "%u"); 124 STAT(tx_deauth_code, "%llu"); 125 STAT(tx_disassoc, "%u"); 126 STAT(tx_disassoc_code, "%u"); 127 fprintf(fd, "\n"); 128 129#undef STAT 130} 131#endif 132 133int 134main(int argc, char *argv[]) 135{ 136 struct wlanstatfoo *wf; 137 struct ether_addr *ea; 138 const uint8_t *mac = NULL; 139 int allnodes = 0; 140 int c, mode; 141 142 wf = wlanstats_new("ath0", S_DEFAULT); 143 while ((c = getopt(argc, argv, "ai:lm:o:")) != -1) { 144 switch (c) { 145 case 'a': 146 allnodes++; 147 break; 148 case 'i': 149 wf->setifname(wf, optarg); 150 break; 151 case 'l': 152 wf->print_fields(wf, stdout); 153 return 0; 154 case 'm': 155 ea = ether_aton(optarg); 156 if (!ea) 157 errx(1, "%s: invalid ethernet address", optarg); 158 mac = ea->octet; 159 break; 160 case 'o': 161 if (strcasecmp(optarg, "ampdu") == 0) 162 wf->setfmt(wf, S_AMPDU); 163 else 164 wf->setfmt(wf, optarg); 165 break; 166 default: 167 errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [interval]\n", argv[0]); 168 /*NOTREACHED*/ 169 } 170 } 171 argc -= optind; 172 argv += optind; 173 174 mode = wf->getopmode(wf); 175 wf->setstamac(wf, mac); 176 177 if (argc > 0) { 178 u_long interval = strtoul(argv[0], NULL, 0); 179 int line, omask; 180 181 if (interval < 1) 182 interval = 1; 183 signal(SIGALRM, catchalarm); 184 signalled = 0; 185 alarm(interval); 186 banner: 187 wf->print_header(wf, stdout); 188 line = 0; 189 loop: 190 if (line != 0) { 191 wf->collect_cur(wf); 192 wf->print_current(wf, stdout); 193 wf->update_tot(wf); 194 } else { 195 wf->collect_tot(wf); 196 wf->print_total(wf, stdout); 197 } 198 fflush(stdout); 199 omask = sigblock(sigmask(SIGALRM)); 200 if (!signalled) 201 sigpause(0); 202 sigsetmask(omask); 203 signalled = 0; 204 alarm(interval); 205 line++; 206 /* refresh every display in case sta roams */ 207 if (mac == NULL && mode == IEEE80211_M_STA) 208 wf->setstamac(wf, NULL); 209 if (line == 21) /* XXX tty line count */ 210 goto banner; 211 else 212 goto loop; 213 /*NOTREACHED*/ 214#if 0 215 } else if (allnodes) { 216 struct ieee80211req_sta_info *si; 217 union { 218 struct ieee80211req_sta_req req; 219 uint8_t buf[24*1024]; 220 } u; 221 uint8_t *cp; 222 struct ieee80211req ireq; 223 int len; 224 225 /* 226 * Retrieve station/neighbor table and print stats for each. 227 */ 228 (void) memset(&ireq, 0, sizeof(ireq)); 229 (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name)); 230 ireq.i_type = IEEE80211_IOC_STA_INFO; 231 memset(&u.req.macaddr, 0xff, sizeof(u.req.macaddr)); 232 ireq.i_data = &u; 233 ireq.i_len = sizeof(u); 234 if (ioctl(s, SIOCG80211, &ireq) < 0) 235 err(1, "unable to get station information"); 236 len = ireq.i_len; 237 if (len >= sizeof(struct ieee80211req_sta_info)) { 238 cp = u.req.info; 239 do { 240 si = (struct ieee80211req_sta_info *) cp; 241 if (si->isi_len < sizeof(*si)) 242 break; 243 print_sta_stats(stdout, si->isi_macaddr); 244 cp += si->isi_len, len -= si->isi_len; 245 } while (len >= sizeof(struct ieee80211req_sta_info)); 246 } 247#endif 248 } else { 249 wf->collect_tot(wf); 250 wf->print_verbose(wf, stdout); 251 } 252 return 0; 253} 254