Home | History | Annotate | Line # | Download | only in ifconfig
ieee80211.c revision 1.8
      1  1.8    dyoung /*	$NetBSD: ieee80211.c,v 1.8 2007/01/09 09:19:02 dyoung Exp $	*/
      2  1.1   thorpej 
      3  1.1   thorpej /*
      4  1.1   thorpej  * Copyright (c) 1983, 1993
      5  1.1   thorpej  *      The Regents of the University of California.  All rights reserved.
      6  1.1   thorpej  *
      7  1.1   thorpej  * Redistribution and use in source and binary forms, with or without
      8  1.1   thorpej  * modification, are permitted provided that the following conditions
      9  1.1   thorpej  * are met:
     10  1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     11  1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     12  1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     14  1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     15  1.1   thorpej  * 3. Neither the name of the University nor the names of its contributors
     16  1.1   thorpej  *    may be used to endorse or promote products derived from this software
     17  1.1   thorpej  *    without specific prior written permission.
     18  1.1   thorpej  *
     19  1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  1.1   thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  1.1   thorpej  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  1.1   thorpej  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  1.1   thorpej  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  1.1   thorpej  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  1.1   thorpej  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  1.1   thorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  1.1   thorpej  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  1.1   thorpej  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  1.1   thorpej  * SUCH DAMAGE.
     30  1.1   thorpej  */
     31  1.1   thorpej 
     32  1.1   thorpej #include <sys/cdefs.h>
     33  1.1   thorpej #ifndef lint
     34  1.8    dyoung __RCSID("$NetBSD: ieee80211.c,v 1.8 2007/01/09 09:19:02 dyoung Exp $");
     35  1.1   thorpej #endif /* not lint */
     36  1.1   thorpej 
     37  1.1   thorpej #include <sys/param.h>
     38  1.1   thorpej #include <sys/ioctl.h>
     39  1.1   thorpej #include <sys/socket.h>
     40  1.1   thorpej 
     41  1.1   thorpej #include <net/if.h>
     42  1.1   thorpej #include <net/if_ether.h>
     43  1.5    rpaulo #include <net/if_media.h>
     44  1.1   thorpej #include <net80211/ieee80211.h>
     45  1.1   thorpej #include <net80211/ieee80211_ioctl.h>
     46  1.1   thorpej 
     47  1.1   thorpej #include <ctype.h>
     48  1.1   thorpej #include <err.h>
     49  1.1   thorpej #include <netdb.h>
     50  1.1   thorpej #include <string.h>
     51  1.1   thorpej #include <stdlib.h>
     52  1.1   thorpej #include <stdio.h>
     53  1.7  christos #include <util.h>
     54  1.1   thorpej 
     55  1.1   thorpej #include "extern.h"
     56  1.1   thorpej #include "ieee80211.h"
     57  1.1   thorpej 
     58  1.5    rpaulo static void set80211(int, int, int, uint8_t *);
     59  1.5    rpaulo 
     60  1.5    rpaulo static void
     61  1.5    rpaulo set80211(int type, int val, int len, u_int8_t *data)
     62  1.5    rpaulo {
     63  1.5    rpaulo 	struct ieee80211req	ireq;
     64  1.5    rpaulo 
     65  1.5    rpaulo 	(void) memset(&ireq, 0, sizeof(ireq));
     66  1.6      elad 	estrlcpy(ireq.i_name, name, sizeof(ireq.i_name));
     67  1.5    rpaulo 	ireq.i_type = type;
     68  1.5    rpaulo 	ireq.i_val = val;
     69  1.5    rpaulo 	ireq.i_len = len;
     70  1.5    rpaulo 	ireq.i_data = data;
     71  1.5    rpaulo 	if (ioctl(s, SIOCS80211, &ireq) < 0)
     72  1.5    rpaulo 		err(1, "SIOCS80211");
     73  1.5    rpaulo }
     74  1.5    rpaulo 
     75  1.5    rpaulo void
     76  1.5    rpaulo sethidessid(const char *val, int d)
     77  1.5    rpaulo {
     78  1.5    rpaulo 	set80211(IEEE80211_IOC_HIDESSID, d, 0, NULL);
     79  1.5    rpaulo }
     80  1.5    rpaulo 
     81  1.5    rpaulo void
     82  1.5    rpaulo setapbridge(const char *val, int d)
     83  1.5    rpaulo {
     84  1.5    rpaulo 	set80211(IEEE80211_IOC_APBRIDGE, d, 0, NULL);
     85  1.5    rpaulo }
     86  1.5    rpaulo 
     87  1.5    rpaulo static enum ieee80211_opmode
     88  1.5    rpaulo get80211opmode(void)
     89  1.5    rpaulo {
     90  1.5    rpaulo 	struct ifmediareq ifmr;
     91  1.5    rpaulo 
     92  1.5    rpaulo 	(void) memset(&ifmr, 0, sizeof(ifmr));
     93  1.6      elad 	estrlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
     94  1.5    rpaulo 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
     95  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
     96  1.5    rpaulo 			return IEEE80211_M_IBSS;        /* XXX ahdemo */
     97  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
     98  1.5    rpaulo 			return IEEE80211_M_HOSTAP;
     99  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
    100  1.5    rpaulo 			return IEEE80211_M_MONITOR;
    101  1.5    rpaulo 	}
    102  1.5    rpaulo 
    103  1.5    rpaulo 	return IEEE80211_M_STA;
    104  1.5    rpaulo }
    105  1.5    rpaulo 
    106  1.1   thorpej void
    107  1.1   thorpej setifnwid(const char *val, int d)
    108  1.1   thorpej {
    109  1.1   thorpej 	struct ieee80211_nwid nwid;
    110  1.1   thorpej 	int len;
    111  1.1   thorpej 
    112  1.1   thorpej 	len = sizeof(nwid.i_nwid);
    113  1.1   thorpej 	if (get_string(val, NULL, nwid.i_nwid, &len) == NULL)
    114  1.1   thorpej 		return;
    115  1.1   thorpej 	nwid.i_len = len;
    116  1.6      elad 	estrlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    117  1.1   thorpej 	ifr.ifr_data = (void *)&nwid;
    118  1.1   thorpej 	if (ioctl(s, SIOCS80211NWID, &ifr) == -1)
    119  1.1   thorpej 		warn("SIOCS80211NWID");
    120  1.1   thorpej }
    121  1.1   thorpej 
    122  1.1   thorpej void
    123  1.1   thorpej setifbssid(const char *val, int d)
    124  1.1   thorpej {
    125  1.1   thorpej 	struct ieee80211_bssid bssid;
    126  1.1   thorpej 	struct ether_addr *ea;
    127  1.1   thorpej 
    128  1.1   thorpej 	if (d != 0) {
    129  1.1   thorpej 		/* no BSSID is especially desired */
    130  1.1   thorpej 		memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid));
    131  1.1   thorpej 	} else {
    132  1.1   thorpej 		ea = ether_aton(val);
    133  1.1   thorpej 		if (ea == NULL) {
    134  1.1   thorpej 			warnx("malformed BSSID: %s", val);
    135  1.1   thorpej 			return;
    136  1.1   thorpej 		}
    137  1.1   thorpej 		memcpy(&bssid.i_bssid, ea->ether_addr_octet,
    138  1.1   thorpej 		    sizeof(bssid.i_bssid));
    139  1.1   thorpej 	}
    140  1.6      elad 	estrlcpy(bssid.i_name, name, sizeof(bssid.i_name));
    141  1.1   thorpej 	if (ioctl(s, SIOCS80211BSSID, &bssid) == -1)
    142  1.1   thorpej 		warn("SIOCS80211BSSID");
    143  1.1   thorpej }
    144  1.1   thorpej 
    145  1.1   thorpej void
    146  1.8    dyoung setiffrag(const char *val, int d)
    147  1.8    dyoung {
    148  1.8    dyoung 	struct ieee80211req ireq;
    149  1.8    dyoung 	int thr;
    150  1.8    dyoung 
    151  1.8    dyoung 	if (d != 0)
    152  1.8    dyoung 		thr = IEEE80211_FRAG_MAX;
    153  1.8    dyoung 	else {
    154  1.8    dyoung 		thr = atoi(val);
    155  1.8    dyoung 		if (thr < IEEE80211_FRAG_MIN || thr > IEEE80211_FRAG_MAX) {
    156  1.8    dyoung 			errx(EXIT_FAILURE, "invalid fragmentation threshold: %s", val);
    157  1.8    dyoung 			return;
    158  1.8    dyoung 		}
    159  1.8    dyoung 	}
    160  1.8    dyoung 
    161  1.8    dyoung 	(void)strncpy(ireq.i_name, name, sizeof(ireq.i_name));
    162  1.8    dyoung 	ireq.i_type = IEEE80211_IOC_FRAGTHRESHOLD;
    163  1.8    dyoung 	ireq.i_val = thr;
    164  1.8    dyoung 	if (ioctl(s, SIOCS80211, &ireq) == -1)
    165  1.8    dyoung 		err(EXIT_FAILURE, "IEEE80211_IOC_FRAGTHRESHOLD");
    166  1.8    dyoung }
    167  1.8    dyoung 
    168  1.8    dyoung void
    169  1.1   thorpej setifchan(const char *val, int d)
    170  1.1   thorpej {
    171  1.1   thorpej 	struct ieee80211chanreq channel;
    172  1.1   thorpej 	int chan;
    173  1.1   thorpej 
    174  1.1   thorpej 	if (d != 0)
    175  1.1   thorpej 		chan = IEEE80211_CHAN_ANY;
    176  1.1   thorpej 	else {
    177  1.1   thorpej 		chan = atoi(val);
    178  1.1   thorpej 		if (chan < 0 || chan > 0xffff) {
    179  1.1   thorpej 			warnx("invalid channel: %s", val);
    180  1.1   thorpej 			return;
    181  1.1   thorpej 		}
    182  1.1   thorpej 	}
    183  1.1   thorpej 
    184  1.6      elad 	estrlcpy(channel.i_name, name, sizeof(channel.i_name));
    185  1.1   thorpej 	channel.i_channel = (u_int16_t) chan;
    186  1.1   thorpej 	if (ioctl(s, SIOCS80211CHANNEL, &channel) == -1)
    187  1.1   thorpej 		warn("SIOCS80211CHANNEL");
    188  1.1   thorpej }
    189  1.1   thorpej 
    190  1.1   thorpej void
    191  1.1   thorpej setifnwkey(const char *val, int d)
    192  1.1   thorpej {
    193  1.1   thorpej 	struct ieee80211_nwkey nwkey;
    194  1.1   thorpej 	int i;
    195  1.1   thorpej 	u_int8_t keybuf[IEEE80211_WEP_NKID][16];
    196  1.1   thorpej 
    197  1.1   thorpej 	nwkey.i_wepon = IEEE80211_NWKEY_WEP;
    198  1.1   thorpej 	nwkey.i_defkid = 1;
    199  1.1   thorpej 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    200  1.1   thorpej 		nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
    201  1.1   thorpej 		nwkey.i_key[i].i_keydat = keybuf[i];
    202  1.1   thorpej 	}
    203  1.1   thorpej 	if (d != 0) {
    204  1.1   thorpej 		/* disable WEP encryption */
    205  1.1   thorpej 		nwkey.i_wepon = 0;
    206  1.1   thorpej 		i = 0;
    207  1.1   thorpej 	} else if (strcasecmp("persist", val) == 0) {
    208  1.1   thorpej 		/* use all values from persistent memory */
    209  1.1   thorpej 		nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
    210  1.1   thorpej 		nwkey.i_defkid = 0;
    211  1.1   thorpej 		for (i = 0; i < IEEE80211_WEP_NKID; i++)
    212  1.1   thorpej 			nwkey.i_key[i].i_keylen = -1;
    213  1.1   thorpej 	} else if (strncasecmp("persist:", val, 8) == 0) {
    214  1.1   thorpej 		val += 8;
    215  1.1   thorpej 		/* program keys in persistent memory */
    216  1.1   thorpej 		nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
    217  1.1   thorpej 		goto set_nwkey;
    218  1.1   thorpej 	} else {
    219  1.1   thorpej   set_nwkey:
    220  1.1   thorpej 		if (isdigit((unsigned char)val[0]) && val[1] == ':') {
    221  1.1   thorpej 			/* specifying a full set of four keys */
    222  1.1   thorpej 			nwkey.i_defkid = val[0] - '0';
    223  1.1   thorpej 			val += 2;
    224  1.1   thorpej 			for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    225  1.1   thorpej 				val = get_string(val, ",", keybuf[i],
    226  1.1   thorpej 				    &nwkey.i_key[i].i_keylen);
    227  1.1   thorpej 				if (val == NULL)
    228  1.1   thorpej 					return;
    229  1.1   thorpej 			}
    230  1.1   thorpej 			if (*val != '\0') {
    231  1.1   thorpej 				warnx("SIOCS80211NWKEY: too many keys.");
    232  1.1   thorpej 				return;
    233  1.1   thorpej 			}
    234  1.1   thorpej 		} else {
    235  1.1   thorpej 			val = get_string(val, NULL, keybuf[0],
    236  1.1   thorpej 			    &nwkey.i_key[0].i_keylen);
    237  1.1   thorpej 			if (val == NULL)
    238  1.1   thorpej 				return;
    239  1.1   thorpej 			i = 1;
    240  1.1   thorpej 		}
    241  1.1   thorpej 	}
    242  1.1   thorpej 	for (; i < IEEE80211_WEP_NKID; i++)
    243  1.1   thorpej 		nwkey.i_key[i].i_keylen = 0;
    244  1.6      elad 	estrlcpy(nwkey.i_name, name, sizeof(nwkey.i_name));
    245  1.1   thorpej 	if (ioctl(s, SIOCS80211NWKEY, &nwkey) == -1)
    246  1.1   thorpej 		warn("SIOCS80211NWKEY");
    247  1.1   thorpej }
    248  1.1   thorpej 
    249  1.1   thorpej void
    250  1.1   thorpej setifpowersave(const char *val, int d)
    251  1.1   thorpej {
    252  1.1   thorpej 	struct ieee80211_power power;
    253  1.1   thorpej 
    254  1.6      elad 	estrlcpy(power.i_name, name, sizeof(power.i_name));
    255  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1) {
    256  1.1   thorpej 		warn("SIOCG80211POWER");
    257  1.1   thorpej 		return;
    258  1.1   thorpej 	}
    259  1.1   thorpej 
    260  1.1   thorpej 	power.i_enabled = d;
    261  1.1   thorpej 	if (ioctl(s, SIOCS80211POWER, &power) == -1)
    262  1.1   thorpej 		warn("SIOCS80211POWER");
    263  1.1   thorpej }
    264  1.1   thorpej 
    265  1.1   thorpej void
    266  1.1   thorpej setifpowersavesleep(const char *val, int d)
    267  1.1   thorpej {
    268  1.1   thorpej 	struct ieee80211_power power;
    269  1.1   thorpej 
    270  1.6      elad 	estrlcpy(power.i_name, name, sizeof(power.i_name));
    271  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1) {
    272  1.1   thorpej 		warn("SIOCG80211POWER");
    273  1.1   thorpej 		return;
    274  1.1   thorpej 	}
    275  1.1   thorpej 
    276  1.1   thorpej 	power.i_maxsleep = atoi(val);
    277  1.1   thorpej 	if (ioctl(s, SIOCS80211POWER, &power) == -1)
    278  1.1   thorpej 		warn("SIOCS80211POWER");
    279  1.1   thorpej }
    280  1.1   thorpej 
    281  1.1   thorpej void
    282  1.1   thorpej ieee80211_statistics(void)
    283  1.1   thorpej {
    284  1.1   thorpej 	struct ieee80211_stats stats;
    285  1.1   thorpej 
    286  1.1   thorpej 	memset(&ifr, 0, sizeof(ifr));
    287  1.3    dyoung 	ifr.ifr_buflen = sizeof(stats);
    288  1.3    dyoung 	ifr.ifr_buf = (caddr_t)&stats;
    289  1.6      elad 	estrlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    290  1.1   thorpej 	if (ioctl(s, (zflag) ? SIOCG80211ZSTATS : SIOCG80211STATS,
    291  1.1   thorpej 	    (caddr_t)&ifr) == -1)
    292  1.1   thorpej 		return;
    293  1.2    dyoung #define	STAT_PRINT(_member, _desc)	\
    294  1.2    dyoung 	printf("\t" _desc ": %" PRIu32 "\n", stats._member)
    295  1.1   thorpej 
    296  1.2    dyoung 	STAT_PRINT(is_rx_badversion, "rx frame with bad version");
    297  1.2    dyoung 	STAT_PRINT(is_rx_tooshort, "rx frame too short");
    298  1.2    dyoung 	STAT_PRINT(is_rx_wrongbss, "rx from wrong bssid");
    299  1.2    dyoung 	STAT_PRINT(is_rx_dup, "rx discard 'cuz dup");
    300  1.2    dyoung 	STAT_PRINT(is_rx_wrongdir, "rx w/ wrong direction");
    301  1.2    dyoung 	STAT_PRINT(is_rx_mcastecho, "rx discard 'cuz mcast echo");
    302  1.2    dyoung 	STAT_PRINT(is_rx_notassoc, "rx discard 'cuz sta !assoc");
    303  1.2    dyoung 	STAT_PRINT(is_rx_noprivacy, "rx w/ wep but privacy off");
    304  1.2    dyoung 	STAT_PRINT(is_rx_unencrypted, "rx w/o wep and privacy on");
    305  1.2    dyoung 	STAT_PRINT(is_rx_wepfail, "rx wep processing failed");
    306  1.2    dyoung 	STAT_PRINT(is_rx_decap, "rx decapsulation failed");
    307  1.2    dyoung 	STAT_PRINT(is_rx_mgtdiscard, "rx discard mgt frames");
    308  1.2    dyoung 	STAT_PRINT(is_rx_ctl, "rx discard ctrl frames");
    309  1.2    dyoung 	STAT_PRINT(is_rx_beacon, "rx beacon frames");
    310  1.2    dyoung 	STAT_PRINT(is_rx_rstoobig, "rx rate set truncated");
    311  1.2    dyoung 	STAT_PRINT(is_rx_elem_missing, "rx required element missin");
    312  1.2    dyoung 	STAT_PRINT(is_rx_elem_toobig, "rx element too big");
    313  1.2    dyoung 	STAT_PRINT(is_rx_elem_toosmall, "rx element too small");
    314  1.2    dyoung 	STAT_PRINT(is_rx_elem_unknown, "rx element unknown");
    315  1.2    dyoung 	STAT_PRINT(is_rx_badchan, "rx frame w/ invalid chan");
    316  1.2    dyoung 	STAT_PRINT(is_rx_chanmismatch, "rx frame chan mismatch");
    317  1.2    dyoung 	STAT_PRINT(is_rx_nodealloc, "rx frame dropped");
    318  1.2    dyoung 	STAT_PRINT(is_rx_ssidmismatch, "rx frame ssid mismatch ");
    319  1.2    dyoung 	STAT_PRINT(is_rx_auth_unsupported, "rx w/ unsupported auth alg");
    320  1.2    dyoung 	STAT_PRINT(is_rx_auth_fail, "rx sta auth failure");
    321  1.2    dyoung 	STAT_PRINT(is_rx_auth_countermeasures, "rx auth discard 'cuz CM");
    322  1.2    dyoung 	STAT_PRINT(is_rx_assoc_bss, "rx assoc from wrong bssid");
    323  1.2    dyoung 	STAT_PRINT(is_rx_assoc_notauth, "rx assoc w/o auth");
    324  1.2    dyoung 	STAT_PRINT(is_rx_assoc_capmismatch, "rx assoc w/ cap mismatch");
    325  1.2    dyoung 	STAT_PRINT(is_rx_assoc_norate, "rx assoc w/ no rate match");
    326  1.2    dyoung 	STAT_PRINT(is_rx_assoc_badwpaie, "rx assoc w/ bad WPA IE");
    327  1.2    dyoung 	STAT_PRINT(is_rx_deauth, "rx deauthentication");
    328  1.2    dyoung 	STAT_PRINT(is_rx_disassoc, "rx disassociation");
    329  1.2    dyoung 	STAT_PRINT(is_rx_badsubtype, "rx frame w/ unknown subtyp");
    330  1.2    dyoung 	STAT_PRINT(is_rx_nobuf, "rx failed for lack of buf");
    331  1.2    dyoung 	STAT_PRINT(is_rx_decryptcrc, "rx decrypt failed on crc");
    332  1.2    dyoung 	STAT_PRINT(is_rx_ahdemo_mgt, "rx discard ahdemo mgt fram");
    333  1.2    dyoung 	STAT_PRINT(is_rx_bad_auth, "rx bad auth request");
    334  1.2    dyoung 	STAT_PRINT(is_rx_unauth, "rx on unauthorized port");
    335  1.2    dyoung 	STAT_PRINT(is_rx_badkeyid, "rx w/ incorrect keyid");
    336  1.2    dyoung 	STAT_PRINT(is_rx_ccmpreplay, "rx seq# violation (CCMP)");
    337  1.2    dyoung 	STAT_PRINT(is_rx_ccmpformat, "rx format bad (CCMP)");
    338  1.2    dyoung 	STAT_PRINT(is_rx_ccmpmic, "rx MIC check failed (CCMP)");
    339  1.2    dyoung 	STAT_PRINT(is_rx_tkipreplay, "rx seq# violation (TKIP)");
    340  1.2    dyoung 	STAT_PRINT(is_rx_tkipformat, "rx format bad (TKIP)");
    341  1.2    dyoung 	STAT_PRINT(is_rx_tkipmic, "rx MIC check failed (TKIP)");
    342  1.2    dyoung 	STAT_PRINT(is_rx_tkipicv, "rx ICV check failed (TKIP)");
    343  1.2    dyoung 	STAT_PRINT(is_rx_badcipher, "rx failed 'cuz key type");
    344  1.2    dyoung 	STAT_PRINT(is_rx_nocipherctx, "rx failed 'cuz key !setup");
    345  1.2    dyoung 	STAT_PRINT(is_rx_acl, "rx discard 'cuz acl policy");
    346  1.2    dyoung 
    347  1.2    dyoung 	STAT_PRINT(is_tx_nobuf, "tx failed for lack of buf");
    348  1.2    dyoung 	STAT_PRINT(is_tx_nonode, "tx failed for no node");
    349  1.2    dyoung 	STAT_PRINT(is_tx_unknownmgt, "tx of unknown mgt frame");
    350  1.2    dyoung 	STAT_PRINT(is_tx_badcipher, "tx failed 'cuz key type");
    351  1.2    dyoung 	STAT_PRINT(is_tx_nodefkey, "tx failed 'cuz no defkey");
    352  1.2    dyoung 	STAT_PRINT(is_tx_noheadroom, "tx failed 'cuz no space");
    353  1.2    dyoung 
    354  1.2    dyoung 	STAT_PRINT(is_scan_active, "active scans started");
    355  1.2    dyoung 	STAT_PRINT(is_scan_passive, "passive scans started");
    356  1.2    dyoung 	STAT_PRINT(is_node_timeout, "nodes timed out inactivity");
    357  1.2    dyoung 	STAT_PRINT(is_crypto_nomem, "no memory for crypto ctx");
    358  1.2    dyoung 	STAT_PRINT(is_crypto_tkip, "tkip crypto done in s/w");
    359  1.2    dyoung 	STAT_PRINT(is_crypto_tkipenmic, "tkip en-MIC done in s/w");
    360  1.2    dyoung 	STAT_PRINT(is_crypto_tkipdemic, "tkip de-MIC done in s/w");
    361  1.2    dyoung 	STAT_PRINT(is_crypto_tkipcm, "tkip counter measures");
    362  1.2    dyoung 	STAT_PRINT(is_crypto_ccmp, "ccmp crypto done in s/w");
    363  1.2    dyoung 	STAT_PRINT(is_crypto_wep, "wep crypto done in s/w");
    364  1.2    dyoung 	STAT_PRINT(is_crypto_setkey_cipher, "cipher rejected key");
    365  1.2    dyoung 	STAT_PRINT(is_crypto_setkey_nokey, "no key index for setkey");
    366  1.2    dyoung 	STAT_PRINT(is_crypto_delkey, "driver key delete failed");
    367  1.2    dyoung 	STAT_PRINT(is_crypto_badcipher, "unknown cipher");
    368  1.2    dyoung 	STAT_PRINT(is_crypto_nocipher, "cipher not available");
    369  1.2    dyoung 	STAT_PRINT(is_crypto_attachfail, "cipher attach failed");
    370  1.2    dyoung 	STAT_PRINT(is_crypto_swfallback, "cipher fallback to s/w");
    371  1.2    dyoung 	STAT_PRINT(is_crypto_keyfail, "driver key alloc failed");
    372  1.2    dyoung 	STAT_PRINT(is_crypto_enmicfail, "en-MIC failed");
    373  1.2    dyoung 	STAT_PRINT(is_ibss_capmismatch, "merge failed-cap mismatch");
    374  1.2    dyoung 	STAT_PRINT(is_ibss_norate, "merge failed-rate mismatch");
    375  1.2    dyoung 	STAT_PRINT(is_ps_unassoc, "ps-poll for unassoc. sta");
    376  1.2    dyoung 	STAT_PRINT(is_ps_badaid, "ps-poll w/ incorrect aid");
    377  1.2    dyoung 	STAT_PRINT(is_ps_qempty, "ps-poll w/ nothing to send");
    378  1.1   thorpej }
    379  1.1   thorpej 
    380  1.1   thorpej void
    381  1.1   thorpej ieee80211_status(void)
    382  1.1   thorpej {
    383  1.1   thorpej 	int i, nwkey_verbose;
    384  1.1   thorpej 	struct ieee80211_nwid nwid;
    385  1.1   thorpej 	struct ieee80211_nwkey nwkey;
    386  1.1   thorpej 	struct ieee80211_power power;
    387  1.1   thorpej 	u_int8_t keybuf[IEEE80211_WEP_NKID][16];
    388  1.1   thorpej 	struct ieee80211_bssid bssid;
    389  1.1   thorpej 	struct ieee80211chanreq channel;
    390  1.5    rpaulo 	struct ieee80211req ireq;
    391  1.1   thorpej 	struct ether_addr ea;
    392  1.1   thorpej 	static const u_int8_t zero_macaddr[IEEE80211_ADDR_LEN];
    393  1.5    rpaulo 	enum ieee80211_opmode opmode = get80211opmode();
    394  1.5    rpaulo 	extern int vflag;
    395  1.1   thorpej 
    396  1.1   thorpej 	memset(&ifr, 0, sizeof(ifr));
    397  1.1   thorpej 	ifr.ifr_data = (void *)&nwid;
    398  1.6      elad 	estrlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    399  1.1   thorpej 	if (ioctl(s, SIOCG80211NWID, &ifr) == -1)
    400  1.1   thorpej 		return;
    401  1.1   thorpej 	if (nwid.i_len > IEEE80211_NWID_LEN) {
    402  1.1   thorpej 		warnx("SIOCG80211NWID: wrong length of nwid (%d)", nwid.i_len);
    403  1.1   thorpej 		return;
    404  1.1   thorpej 	}
    405  1.1   thorpej 	printf("\tssid ");
    406  1.1   thorpej 	print_string(nwid.i_nwid, nwid.i_len);
    407  1.5    rpaulo 
    408  1.5    rpaulo 	if (opmode == IEEE80211_M_HOSTAP) {
    409  1.6      elad 		estrlcpy(ireq.i_name, name, sizeof(ireq.i_name));
    410  1.5    rpaulo 		ireq.i_type = IEEE80211_IOC_HIDESSID;
    411  1.5    rpaulo 		if (ioctl(s, SIOCG80211, &ireq) != -1) {
    412  1.5    rpaulo                         if (ireq.i_val)
    413  1.5    rpaulo                                 printf(" [hidden]");
    414  1.5    rpaulo                         else if (vflag)
    415  1.5    rpaulo                                 printf(" [shown]");
    416  1.5    rpaulo                 }
    417  1.5    rpaulo 
    418  1.5    rpaulo 		ireq.i_type = IEEE80211_IOC_APBRIDGE;
    419  1.5    rpaulo 		if (ioctl(s, SIOCG80211, &ireq) != -1) {
    420  1.5    rpaulo 			if (ireq.i_val)
    421  1.5    rpaulo 				printf(" apbridge");
    422  1.5    rpaulo 			else if (vflag)
    423  1.5    rpaulo 				printf(" -apbridge");
    424  1.5    rpaulo 		}
    425  1.5    rpaulo         }
    426  1.5    rpaulo 
    427  1.8    dyoung 	estrlcpy(ireq.i_name, name, sizeof(ireq.i_name));
    428  1.8    dyoung 	ireq.i_type = IEEE80211_IOC_FRAGTHRESHOLD;
    429  1.8    dyoung 	if (ioctl(s, SIOCG80211, &ireq) == -1)
    430  1.8    dyoung 		;
    431  1.8    dyoung 	else if (ireq.i_val < IEEE80211_FRAG_MAX)
    432  1.8    dyoung 		printf(" frag %d", ireq.i_val);
    433  1.8    dyoung 	else if (vflag)
    434  1.8    dyoung 		printf(" -frag");
    435  1.8    dyoung 
    436  1.1   thorpej 	memset(&nwkey, 0, sizeof(nwkey));
    437  1.6      elad 	estrlcpy(nwkey.i_name, name, sizeof(nwkey.i_name));
    438  1.1   thorpej 	/* show nwkey only when WEP is enabled */
    439  1.1   thorpej 	if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1 ||
    440  1.1   thorpej 	    nwkey.i_wepon == 0) {
    441  1.1   thorpej 		printf("\n");
    442  1.1   thorpej 		goto skip_wep;
    443  1.1   thorpej 	}
    444  1.1   thorpej 
    445  1.1   thorpej 	printf(" nwkey ");
    446  1.1   thorpej 	/* try to retrieve WEP keys */
    447  1.1   thorpej 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    448  1.1   thorpej 		nwkey.i_key[i].i_keydat = keybuf[i];
    449  1.1   thorpej 		nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
    450  1.1   thorpej 	}
    451  1.1   thorpej 	if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1) {
    452  1.1   thorpej 		printf("*****");
    453  1.1   thorpej 	} else {
    454  1.1   thorpej 		nwkey_verbose = 0;
    455  1.1   thorpej 		/* check to see non default key or multiple keys defined */
    456  1.1   thorpej 		if (nwkey.i_defkid != 1) {
    457  1.1   thorpej 			nwkey_verbose = 1;
    458  1.1   thorpej 		} else {
    459  1.1   thorpej 			for (i = 1; i < IEEE80211_WEP_NKID; i++) {
    460  1.1   thorpej 				if (nwkey.i_key[i].i_keylen != 0) {
    461  1.1   thorpej 					nwkey_verbose = 1;
    462  1.1   thorpej 					break;
    463  1.1   thorpej 				}
    464  1.1   thorpej 			}
    465  1.1   thorpej 		}
    466  1.1   thorpej 		/* check extra ambiguity with keywords */
    467  1.1   thorpej 		if (!nwkey_verbose) {
    468  1.1   thorpej 			if (nwkey.i_key[0].i_keylen >= 2 &&
    469  1.1   thorpej 			    isdigit(nwkey.i_key[0].i_keydat[0]) &&
    470  1.1   thorpej 			    nwkey.i_key[0].i_keydat[1] == ':')
    471  1.1   thorpej 				nwkey_verbose = 1;
    472  1.1   thorpej 			else if (nwkey.i_key[0].i_keylen >= 7 &&
    473  1.4  christos 			    strncasecmp("persist",
    474  1.4  christos 			    (const char *)nwkey.i_key[0].i_keydat, 7) == 0)
    475  1.1   thorpej 				nwkey_verbose = 1;
    476  1.1   thorpej 		}
    477  1.1   thorpej 		if (nwkey_verbose)
    478  1.1   thorpej 			printf("%d:", nwkey.i_defkid);
    479  1.1   thorpej 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    480  1.1   thorpej 			if (i > 0)
    481  1.1   thorpej 				printf(",");
    482  1.1   thorpej 			if (nwkey.i_key[i].i_keylen < 0)
    483  1.1   thorpej 				printf("persist");
    484  1.1   thorpej 			else
    485  1.1   thorpej 				print_string(nwkey.i_key[i].i_keydat,
    486  1.1   thorpej 				    nwkey.i_key[i].i_keylen);
    487  1.1   thorpej 			if (!nwkey_verbose)
    488  1.1   thorpej 				break;
    489  1.1   thorpej 		}
    490  1.1   thorpej 	}
    491  1.1   thorpej 	printf("\n");
    492  1.1   thorpej 
    493  1.1   thorpej  skip_wep:
    494  1.6      elad 	estrlcpy(power.i_name, name, sizeof(power.i_name));
    495  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1)
    496  1.1   thorpej 		goto skip_power;
    497  1.1   thorpej 	printf("\tpowersave ");
    498  1.1   thorpej 	if (power.i_enabled)
    499  1.1   thorpej 		printf("on (%dms sleep)", power.i_maxsleep);
    500  1.1   thorpej 	else
    501  1.1   thorpej 		printf("off");
    502  1.1   thorpej 	printf("\n");
    503  1.1   thorpej 
    504  1.1   thorpej  skip_power:
    505  1.6      elad 	estrlcpy(bssid.i_name, name, sizeof(bssid.i_name));
    506  1.1   thorpej 	if (ioctl(s, SIOCG80211BSSID, &bssid) == -1)
    507  1.1   thorpej 		return;
    508  1.6      elad 	estrlcpy(channel.i_name, name, sizeof(channel.i_name));
    509  1.1   thorpej 	if (ioctl(s, SIOCG80211CHANNEL, &channel) == -1)
    510  1.1   thorpej 		return;
    511  1.1   thorpej 	if (memcmp(bssid.i_bssid, zero_macaddr, IEEE80211_ADDR_LEN) == 0) {
    512  1.1   thorpej 		if (channel.i_channel != (u_int16_t)-1)
    513  1.1   thorpej 			printf("\tchan %d\n", channel.i_channel);
    514  1.1   thorpej 	} else {
    515  1.1   thorpej 		memcpy(ea.ether_addr_octet, bssid.i_bssid,
    516  1.1   thorpej 		    sizeof(ea.ether_addr_octet));
    517  1.1   thorpej 		printf("\tbssid %s", ether_ntoa(&ea));
    518  1.1   thorpej 		if (channel.i_channel != IEEE80211_CHAN_ANY)
    519  1.1   thorpej 			printf(" chan %d", channel.i_channel);
    520  1.1   thorpej 		printf("\n");
    521  1.1   thorpej 	}
    522  1.1   thorpej }
    523