wlanstats.c revision 153392
1153317Ssam/*- 2153317Ssam * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting 3153317Ssam * All rights reserved. 4153317Ssam * 5153317Ssam * Redistribution and use in source and binary forms, with or without 6153317Ssam * modification, are permitted provided that the following conditions 7153317Ssam * are met: 8153317Ssam * 1. Redistributions of source code must retain the above copyright 9153317Ssam * notice, this list of conditions and the following disclaimer, 10153317Ssam * without modification. 11153317Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12153317Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13153317Ssam * redistribution must be conditioned upon including a substantially 14153317Ssam * similar Disclaimer requirement for further binary redistribution. 15153317Ssam * 3. Neither the names of the above-listed copyright holders nor the names 16153317Ssam * of any contributors may be used to endorse or promote products derived 17153317Ssam * from this software without specific prior written permission. 18153317Ssam * 19153317Ssam * Alternatively, this software may be distributed under the terms of the 20153317Ssam * GNU General Public License ("GPL") version 2 as published by the Free 21153317Ssam * Software Foundation. 22153317Ssam * 23153317Ssam * NO WARRANTY 24153317Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25153317Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26153317Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 27153317Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 28153317Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 29153317Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30153317Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31153317Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 32153317Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33153317Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 34153317Ssam * THE POSSIBILITY OF SUCH DAMAGES. 35153317Ssam * 36153317Ssam * $FreeBSD: head/tools/tools/net80211/wlanstats/wlanstats.c 153392 2005-12-13 22:15:09Z sam $ 37153317Ssam */ 38153317Ssam 39153317Ssam/* 40153317Ssam * wlanstats [-i interface] 41153317Ssam * (default interface is ath0). 42153317Ssam */ 43153317Ssam#include <sys/types.h> 44153317Ssam#include <sys/file.h> 45153317Ssam#include <sys/sockio.h> 46153317Ssam#include <sys/socket.h> 47153317Ssam#include <net/if.h> 48153317Ssam#include <net/if_media.h> 49153317Ssam#include <net/if_var.h> 50153317Ssam#include <net/ethernet.h> 51153317Ssam 52153317Ssam#include <stdio.h> 53153317Ssam#include <signal.h> 54153317Ssam#include <unistd.h> 55153317Ssam#include <err.h> 56153317Ssam 57153392Ssam#include "../../../../sys/net80211/ieee80211_ioctl.h" 58153317Ssam 59153317Ssamconst char *progname; 60153317Ssam 61153317Ssamstatic void 62153317Ssamprintstats(FILE *fd, const struct ieee80211_stats *stats) 63153317Ssam{ 64153317Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 65153317Ssam#define STAT(x,fmt) \ 66153317Ssam if (stats->is_##x) fprintf(fd, "%u " fmt "\n", stats->is_##x) 67153317Ssam STAT(rx_badversion, "rx frame with bad version"); 68153317Ssam STAT(rx_tooshort, "rx frame too short"); 69153317Ssam STAT(rx_wrongbss, "rx from wrong bssid"); 70153317Ssam STAT(rx_dup, "rx discard 'cuz dup"); 71153317Ssam STAT(rx_wrongdir, "rx w/ wrong direction"); 72153317Ssam STAT(rx_mcastecho, "rx discard 'cuz mcast echo"); 73153317Ssam STAT(rx_notassoc, "rx discard 'cuz sta !assoc"); 74153317Ssam STAT(rx_noprivacy, "rx w/ wep but privacy off"); 75153317Ssam STAT(rx_unencrypted, "rx w/o wep and privacy on"); 76153317Ssam STAT(rx_wepfail, "rx wep processing failed"); 77153317Ssam STAT(rx_decap, "rx decapsulation failed"); 78153317Ssam STAT(rx_mgtdiscard, "rx discard mgt frames"); 79153317Ssam STAT(rx_ctl, "rx discard ctrl frames"); 80153317Ssam STAT(rx_beacon, "rx beacon frames"); 81153317Ssam STAT(rx_rstoobig, "rx rate set truncated"); 82153317Ssam STAT(rx_elem_missing, "rx required element missing"); 83153317Ssam STAT(rx_elem_toobig, "rx element too big"); 84153317Ssam STAT(rx_elem_toosmall, "rx element too small"); 85153317Ssam STAT(rx_elem_unknown, "rx element unknown"); 86153317Ssam STAT(rx_badchan, "rx frame w/ invalid chan"); 87153317Ssam STAT(rx_chanmismatch, "rx frame chan mismatch"); 88153317Ssam STAT(rx_nodealloc, "nodes allocated (rx)"); 89153317Ssam STAT(rx_ssidmismatch, "rx frame ssid mismatch"); 90153317Ssam STAT(rx_auth_unsupported,"rx w/ unsupported auth alg"); 91153317Ssam STAT(rx_auth_fail, "rx sta auth failure"); 92153317Ssam STAT(rx_auth_countermeasures, 93153317Ssam "rx sta auth failure 'cuz of TKIP countermeasures"); 94153317Ssam STAT(rx_assoc_bss, "rx assoc from wrong bssid"); 95153317Ssam STAT(rx_assoc_notauth, "rx assoc w/o auth"); 96153317Ssam STAT(rx_assoc_capmismatch,"rx assoc w/ cap mismatch"); 97153317Ssam STAT(rx_assoc_norate, "rx assoc w/ no rate match"); 98153317Ssam STAT(rx_assoc_badwpaie, "rx assoc w/ bad WPA IE"); 99153317Ssam STAT(rx_deauth, "rx deauthentication"); 100153317Ssam STAT(rx_disassoc, "rx disassociation"); 101153317Ssam STAT(rx_badsubtype, "rx frame w/ unknown subtype"); 102153317Ssam STAT(rx_nobuf, "rx failed for lack of sk_buffer"); 103153317Ssam STAT(rx_decryptcrc, "rx decrypt failed on crc"); 104153317Ssam STAT(rx_ahdemo_mgt, 105153317Ssam "rx discard mgmt frame received in ahdoc demo mode"); 106153317Ssam STAT(rx_bad_auth, "rx bad authentication request"); 107153317Ssam STAT(rx_unauth, "rx discard 'cuz port unauthorized"); 108153317Ssam STAT(rx_badkeyid, "rx w/ incorrect keyid"); 109153317Ssam STAT(rx_ccmpreplay, "rx seq# violation (CCMP)"); 110153317Ssam STAT(rx_ccmpformat, "rx format bad (CCMP)"); 111153317Ssam STAT(rx_ccmpmic, "rx MIC check failed (CCMP)"); 112153317Ssam STAT(rx_tkipreplay, "rx seq# violation (TKIP)"); 113153317Ssam STAT(rx_tkipformat, "rx format bad (TKIP)"); 114153317Ssam STAT(rx_tkipmic, "rx MIC check failed (TKIP)"); 115153317Ssam STAT(rx_tkipicv, "rx ICV check failed (TKIP)"); 116153317Ssam STAT(rx_badcipher, "rx failed 'cuz bad cipher/key type"); 117153317Ssam STAT(rx_nocipherctx, "rx failed 'cuz key/cipher ctx not setup"); 118153317Ssam STAT(rx_acl, "rx discard 'cuz acl policy"); 119153317Ssam STAT(tx_nobuf, "tx failed for lack of sk_buffer"); 120153317Ssam STAT(tx_nonode, "tx failed for no node"); 121153317Ssam STAT(tx_unknownmgt, "tx of unknown mgt frame"); 122153317Ssam STAT(tx_badcipher, "tx failed 'cuz bad ciper/key type"); 123153317Ssam STAT(tx_nodefkey, "tx failed 'cuz no defkey"); 124153317Ssam STAT(tx_noheadroom, "tx failed 'cuz no space for crypto hdrs"); 125153317Ssam STAT(tx_fragframes, "tx frames fragmented"); 126153317Ssam STAT(tx_frags, "tx frags generated"); 127153317Ssam STAT(scan_active, "active scans started"); 128153317Ssam STAT(scan_passive, "passive scans started"); 129153317Ssam STAT(node_timeout, "nodes timed out inactivity"); 130153317Ssam STAT(crypto_nomem, "cipher context malloc failed"); 131153317Ssam STAT(crypto_tkip, "tkip crypto done in s/w"); 132153317Ssam STAT(crypto_tkipenmic, "tkip tx MIC done in s/w"); 133153317Ssam STAT(crypto_tkipdemic, "tkip rx MIC done in s/w"); 134153317Ssam STAT(crypto_tkipcm, "tkip dropped frames 'cuz of countermeasures"); 135153317Ssam STAT(crypto_ccmp, "ccmp crypto done in s/w"); 136153317Ssam STAT(crypto_wep, "wep crypto done in s/w"); 137153317Ssam STAT(crypto_setkey_cipher,"setkey failed 'cuz cipher rejected data"); 138153317Ssam STAT(crypto_setkey_nokey,"setkey failed 'cuz no key index"); 139153317Ssam STAT(crypto_delkey, "driver key delete failed"); 140153317Ssam STAT(crypto_badcipher, "setkey failed 'cuz unknown cipher"); 141153317Ssam STAT(crypto_nocipher, "setkey failed 'cuz cipher module unavailable"); 142153317Ssam STAT(crypto_attachfail, "setkey failed 'cuz cipher attach failed"); 143153317Ssam STAT(crypto_swfallback, "crypto fell back to s/w implementation"); 144153317Ssam STAT(crypto_keyfail, "setkey failed 'cuz driver key alloc failed"); 145153317Ssam STAT(crypto_enmicfail, "enmic failed (may be mbuf exhaustion)"); 146153317Ssam STAT(ibss_capmismatch, "ibss merge faied 'cuz capabilities mismatch"); 147153317Ssam STAT(ibss_norate, "ibss merge faied 'cuz rate set mismatch"); 148153317Ssam STAT(ps_unassoc, "ps-poll received for unassociated station"); 149153317Ssam STAT(ps_badaid, "ps-poll received with invalid association id"); 150153317Ssam STAT(ps_qempty, "ps-poll received with nothing to send"); 151153317Ssam STAT(ff_badhdr, "fast frame rx'd w/ bad hdr"); 152153317Ssam STAT(ff_tooshort, "fast frame rx decap error"); 153153317Ssam STAT(ff_split, "fast frame rx split error"); 154153317Ssam STAT(ff_decap, "fast frames decap'd"); 155153317Ssam STAT(ff_encap, "fast frames encap'd for tx"); 156153317Ssam#undef STAT 157153317Ssam#undef N 158153317Ssam} 159153317Ssam 160153317Ssamstruct ifreq ifr; 161153317Ssamint s; 162153317Ssam 163153317Ssamstatic void 164153317Ssamprint_sta_stats(FILE *fd, const u_int8_t macaddr[IEEE80211_ADDR_LEN]) 165153317Ssam{ 166153317Ssam#define STAT(x,fmt) \ 167153317Ssam if (ns->ns_##x) { fprintf(fd, "%s" #x " " fmt, sep, ns->ns_##x); sep = " "; } 168153317Ssam struct ieee80211req ireq; 169153317Ssam struct ieee80211req_sta_stats stats; 170153317Ssam const struct ieee80211_nodestats *ns = &stats.is_stats; 171153317Ssam const char *sep; 172153317Ssam 173153317Ssam (void) memset(&ireq, 0, sizeof(ireq)); 174153317Ssam (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name)); 175153317Ssam ireq.i_type = IEEE80211_IOC_STA_STATS; 176153317Ssam ireq.i_data = &stats; 177153317Ssam ireq.i_len = sizeof(stats); 178153317Ssam memcpy(stats.is_u.macaddr, macaddr, IEEE80211_ADDR_LEN); 179153317Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 180153317Ssam err(1, "unable to get station stats for %s", 181153317Ssam ether_ntoa((const struct ether_addr*) macaddr)); 182153317Ssam 183153317Ssam fprintf(fd, "%s:\n", ether_ntoa((const struct ether_addr*) macaddr)); 184153317Ssam 185153317Ssam sep = "\t"; 186153317Ssam STAT(rx_data, "%u"); 187153317Ssam STAT(rx_mgmt, "%u"); 188153317Ssam STAT(rx_ctrl, "%u"); 189153317Ssam STAT(rx_beacons, "%u"); 190153317Ssam STAT(rx_proberesp, "%u"); 191153317Ssam STAT(rx_ucast, "%u"); 192153317Ssam STAT(rx_mcast, "%u"); 193153317Ssam STAT(rx_bytes, "%llu"); 194153317Ssam STAT(rx_dup, "%u"); 195153317Ssam STAT(rx_noprivacy, "%u"); 196153317Ssam STAT(rx_wepfail, "%u"); 197153317Ssam STAT(rx_demicfail, "%u"); 198153317Ssam STAT(rx_decap, "%u"); 199153317Ssam STAT(rx_defrag, "%u"); 200153317Ssam STAT(rx_disassoc, "%u"); 201153317Ssam STAT(rx_deauth, "%u"); 202153317Ssam STAT(rx_decryptcrc, "%u"); 203153317Ssam STAT(rx_unauth, "%u"); 204153317Ssam STAT(rx_unencrypted, "%u"); 205153317Ssam fprintf(fd, "\n"); 206153317Ssam 207153317Ssam sep = "\t"; 208153317Ssam STAT(tx_data, "%u"); 209153317Ssam STAT(tx_mgmt, "%u"); 210153317Ssam STAT(tx_probereq, "%u"); 211153317Ssam STAT(tx_ucast, "%u"); 212153317Ssam STAT(tx_mcast, "%u"); 213153317Ssam STAT(tx_bytes, "%llu"); 214153317Ssam STAT(tx_novlantag, "%u"); 215153317Ssam STAT(tx_vlanmismatch, "%u"); 216153317Ssam fprintf(fd, "\n"); 217153317Ssam 218153317Ssam sep = "\t"; 219153317Ssam STAT(tx_assoc, "%u"); 220153317Ssam STAT(tx_assoc_fail, "%u"); 221153317Ssam STAT(tx_auth, "%u"); 222153317Ssam STAT(tx_auth_fail, "%u"); 223153317Ssam STAT(tx_deauth, "%u"); 224153317Ssam STAT(tx_deauth_code, "%llu"); 225153317Ssam STAT(tx_disassoc, "%u"); 226153317Ssam STAT(tx_disassoc_code, "%u"); 227153317Ssam fprintf(fd, "\n"); 228153317Ssam 229153317Ssam#undef STAT 230153317Ssam} 231153317Ssam 232153317Ssamint 233153317Ssammain(int argc, char *argv[]) 234153317Ssam{ 235153317Ssam int c, len; 236153317Ssam struct ieee80211req_sta_info *si; 237153317Ssam uint8_t buf[24*1024], *cp; 238153317Ssam struct ieee80211req ireq; 239153317Ssam int allnodes = 0; 240153317Ssam 241153317Ssam progname = argv[0]; 242153317Ssam 243153317Ssam s = socket(AF_INET, SOCK_DGRAM, 0); 244153317Ssam if (s < 0) 245153317Ssam err(1, "socket"); 246153317Ssam strncpy(ifr.ifr_name, "ath0", sizeof (ifr.ifr_name)); 247153317Ssam while ((c = getopt(argc, argv, "ai:")) != -1) 248153317Ssam switch (c) { 249153317Ssam case 'a': 250153317Ssam allnodes++; 251153317Ssam break; 252153317Ssam case 'i': 253153317Ssam strncpy(ifr.ifr_name, optarg, sizeof (ifr.ifr_name)); 254153317Ssam break; 255153317Ssam default: 256153317Ssam errx(1, "usage: %s [-a] [-i device] [mac...]\n", progname); 257153317Ssam /*NOTREACHED*/ 258153317Ssam } 259153317Ssam 260153317Ssam if (argc == optind && !allnodes) { 261153317Ssam struct ieee80211_stats stats; 262153317Ssam 263153317Ssam /* no args, just show global stats */ 264153317Ssam ifr.ifr_data = (caddr_t) &stats; 265153317Ssam if (ioctl(s, SIOCG80211STATS, &ifr) < 0) 266153317Ssam err(1, ifr.ifr_name); 267153317Ssam printstats(stdout, &stats); 268153317Ssam return 0; 269153317Ssam } 270153317Ssam if (allnodes) { 271153317Ssam /* 272153317Ssam * Retrieve station/neighbor table and print stats for each. 273153317Ssam */ 274153317Ssam (void) memset(&ireq, 0, sizeof(ireq)); 275153317Ssam (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name)); 276153317Ssam ireq.i_type = IEEE80211_IOC_STA_INFO; 277153317Ssam ireq.i_data = buf; 278153317Ssam ireq.i_len = sizeof(buf); 279153317Ssam if (ioctl(s, SIOCG80211, &ireq) < 0) 280153317Ssam err(1, "unable to get station information"); 281153317Ssam len = ireq.i_len; 282153317Ssam if (len >= sizeof(struct ieee80211req_sta_info)) { 283153317Ssam cp = buf; 284153317Ssam do { 285153317Ssam si = (struct ieee80211req_sta_info *) cp; 286153317Ssam print_sta_stats(stdout, si->isi_macaddr); 287153317Ssam cp += si->isi_len, len -= si->isi_len; 288153317Ssam } while (len >= sizeof(struct ieee80211req_sta_info)); 289153317Ssam } 290153317Ssam } else { 291153317Ssam /* 292153317Ssam * Print stats for specified stations. 293153317Ssam */ 294153317Ssam for (c = optind; c < argc; c++) { 295153317Ssam const struct ether_addr *ea = ether_aton(argv[c]); 296153317Ssam if (ea != NULL) 297153317Ssam print_sta_stats(stdout, ea->octet); 298153317Ssam } 299153317Ssam } 300153317Ssam} 301