Home | History | Annotate | Line # | Download | only in ifconfig
ieee80211.c revision 1.5
      1  1.5    rpaulo /*	$NetBSD: ieee80211.c,v 1.5 2006/04/29 21:32:29 rpaulo 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.5    rpaulo __RCSID("$NetBSD: ieee80211.c,v 1.5 2006/04/29 21:32:29 rpaulo 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.1   thorpej 
     54  1.1   thorpej #include "extern.h"
     55  1.1   thorpej #include "ieee80211.h"
     56  1.1   thorpej 
     57  1.5    rpaulo static void set80211(int, int, int, uint8_t *);
     58  1.5    rpaulo 
     59  1.5    rpaulo static void
     60  1.5    rpaulo set80211(int type, int val, int len, u_int8_t *data)
     61  1.5    rpaulo {
     62  1.5    rpaulo 	struct ieee80211req	ireq;
     63  1.5    rpaulo 
     64  1.5    rpaulo 	(void) memset(&ireq, 0, sizeof(ireq));
     65  1.5    rpaulo 	(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
     66  1.5    rpaulo 	ireq.i_type = type;
     67  1.5    rpaulo 	ireq.i_val = val;
     68  1.5    rpaulo 	ireq.i_len = len;
     69  1.5    rpaulo 	ireq.i_data = data;
     70  1.5    rpaulo 	if (ioctl(s, SIOCS80211, &ireq) < 0)
     71  1.5    rpaulo 		err(1, "SIOCS80211");
     72  1.5    rpaulo }
     73  1.5    rpaulo 
     74  1.5    rpaulo void
     75  1.5    rpaulo sethidessid(const char *val, int d)
     76  1.5    rpaulo {
     77  1.5    rpaulo 	set80211(IEEE80211_IOC_HIDESSID, d, 0, NULL);
     78  1.5    rpaulo }
     79  1.5    rpaulo 
     80  1.5    rpaulo void
     81  1.5    rpaulo setapbridge(const char *val, int d)
     82  1.5    rpaulo {
     83  1.5    rpaulo 	set80211(IEEE80211_IOC_APBRIDGE, d, 0, NULL);
     84  1.5    rpaulo }
     85  1.5    rpaulo 
     86  1.5    rpaulo static enum ieee80211_opmode
     87  1.5    rpaulo get80211opmode(void)
     88  1.5    rpaulo {
     89  1.5    rpaulo 	struct ifmediareq ifmr;
     90  1.5    rpaulo 
     91  1.5    rpaulo 	(void) memset(&ifmr, 0, sizeof(ifmr));
     92  1.5    rpaulo 	(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
     93  1.5    rpaulo 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
     94  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
     95  1.5    rpaulo 			return IEEE80211_M_IBSS;        /* XXX ahdemo */
     96  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
     97  1.5    rpaulo 			return IEEE80211_M_HOSTAP;
     98  1.5    rpaulo 		if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
     99  1.5    rpaulo 			return IEEE80211_M_MONITOR;
    100  1.5    rpaulo 	}
    101  1.5    rpaulo 
    102  1.5    rpaulo 	return IEEE80211_M_STA;
    103  1.5    rpaulo }
    104  1.5    rpaulo 
    105  1.1   thorpej void
    106  1.1   thorpej setifnwid(const char *val, int d)
    107  1.1   thorpej {
    108  1.1   thorpej 	struct ieee80211_nwid nwid;
    109  1.1   thorpej 	int len;
    110  1.1   thorpej 
    111  1.1   thorpej 	len = sizeof(nwid.i_nwid);
    112  1.1   thorpej 	if (get_string(val, NULL, nwid.i_nwid, &len) == NULL)
    113  1.1   thorpej 		return;
    114  1.1   thorpej 	nwid.i_len = len;
    115  1.1   thorpej 	(void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    116  1.1   thorpej 	ifr.ifr_data = (void *)&nwid;
    117  1.1   thorpej 	if (ioctl(s, SIOCS80211NWID, &ifr) == -1)
    118  1.1   thorpej 		warn("SIOCS80211NWID");
    119  1.1   thorpej }
    120  1.1   thorpej 
    121  1.1   thorpej void
    122  1.1   thorpej setifbssid(const char *val, int d)
    123  1.1   thorpej {
    124  1.1   thorpej 	struct ieee80211_bssid bssid;
    125  1.1   thorpej 	struct ether_addr *ea;
    126  1.1   thorpej 
    127  1.1   thorpej 	if (d != 0) {
    128  1.1   thorpej 		/* no BSSID is especially desired */
    129  1.1   thorpej 		memset(&bssid.i_bssid, 0, sizeof(bssid.i_bssid));
    130  1.1   thorpej 	} else {
    131  1.1   thorpej 		ea = ether_aton(val);
    132  1.1   thorpej 		if (ea == NULL) {
    133  1.1   thorpej 			warnx("malformed BSSID: %s", val);
    134  1.1   thorpej 			return;
    135  1.1   thorpej 		}
    136  1.1   thorpej 		memcpy(&bssid.i_bssid, ea->ether_addr_octet,
    137  1.1   thorpej 		    sizeof(bssid.i_bssid));
    138  1.1   thorpej 	}
    139  1.1   thorpej 	(void)strncpy(bssid.i_name, name, sizeof(bssid.i_name));
    140  1.1   thorpej 	if (ioctl(s, SIOCS80211BSSID, &bssid) == -1)
    141  1.1   thorpej 		warn("SIOCS80211BSSID");
    142  1.1   thorpej }
    143  1.1   thorpej 
    144  1.1   thorpej void
    145  1.1   thorpej setifchan(const char *val, int d)
    146  1.1   thorpej {
    147  1.1   thorpej 	struct ieee80211chanreq channel;
    148  1.1   thorpej 	int chan;
    149  1.1   thorpej 
    150  1.1   thorpej 	if (d != 0)
    151  1.1   thorpej 		chan = IEEE80211_CHAN_ANY;
    152  1.1   thorpej 	else {
    153  1.1   thorpej 		chan = atoi(val);
    154  1.1   thorpej 		if (chan < 0 || chan > 0xffff) {
    155  1.1   thorpej 			warnx("invalid channel: %s", val);
    156  1.1   thorpej 			return;
    157  1.1   thorpej 		}
    158  1.1   thorpej 	}
    159  1.1   thorpej 
    160  1.1   thorpej 	(void)strncpy(channel.i_name, name, sizeof(channel.i_name));
    161  1.1   thorpej 	channel.i_channel = (u_int16_t) chan;
    162  1.1   thorpej 	if (ioctl(s, SIOCS80211CHANNEL, &channel) == -1)
    163  1.1   thorpej 		warn("SIOCS80211CHANNEL");
    164  1.1   thorpej }
    165  1.1   thorpej 
    166  1.1   thorpej void
    167  1.1   thorpej setifnwkey(const char *val, int d)
    168  1.1   thorpej {
    169  1.1   thorpej 	struct ieee80211_nwkey nwkey;
    170  1.1   thorpej 	int i;
    171  1.1   thorpej 	u_int8_t keybuf[IEEE80211_WEP_NKID][16];
    172  1.1   thorpej 
    173  1.1   thorpej 	nwkey.i_wepon = IEEE80211_NWKEY_WEP;
    174  1.1   thorpej 	nwkey.i_defkid = 1;
    175  1.1   thorpej 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    176  1.1   thorpej 		nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
    177  1.1   thorpej 		nwkey.i_key[i].i_keydat = keybuf[i];
    178  1.1   thorpej 	}
    179  1.1   thorpej 	if (d != 0) {
    180  1.1   thorpej 		/* disable WEP encryption */
    181  1.1   thorpej 		nwkey.i_wepon = 0;
    182  1.1   thorpej 		i = 0;
    183  1.1   thorpej 	} else if (strcasecmp("persist", val) == 0) {
    184  1.1   thorpej 		/* use all values from persistent memory */
    185  1.1   thorpej 		nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
    186  1.1   thorpej 		nwkey.i_defkid = 0;
    187  1.1   thorpej 		for (i = 0; i < IEEE80211_WEP_NKID; i++)
    188  1.1   thorpej 			nwkey.i_key[i].i_keylen = -1;
    189  1.1   thorpej 	} else if (strncasecmp("persist:", val, 8) == 0) {
    190  1.1   thorpej 		val += 8;
    191  1.1   thorpej 		/* program keys in persistent memory */
    192  1.1   thorpej 		nwkey.i_wepon |= IEEE80211_NWKEY_PERSIST;
    193  1.1   thorpej 		goto set_nwkey;
    194  1.1   thorpej 	} else {
    195  1.1   thorpej   set_nwkey:
    196  1.1   thorpej 		if (isdigit((unsigned char)val[0]) && val[1] == ':') {
    197  1.1   thorpej 			/* specifying a full set of four keys */
    198  1.1   thorpej 			nwkey.i_defkid = val[0] - '0';
    199  1.1   thorpej 			val += 2;
    200  1.1   thorpej 			for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    201  1.1   thorpej 				val = get_string(val, ",", keybuf[i],
    202  1.1   thorpej 				    &nwkey.i_key[i].i_keylen);
    203  1.1   thorpej 				if (val == NULL)
    204  1.1   thorpej 					return;
    205  1.1   thorpej 			}
    206  1.1   thorpej 			if (*val != '\0') {
    207  1.1   thorpej 				warnx("SIOCS80211NWKEY: too many keys.");
    208  1.1   thorpej 				return;
    209  1.1   thorpej 			}
    210  1.1   thorpej 		} else {
    211  1.1   thorpej 			val = get_string(val, NULL, keybuf[0],
    212  1.1   thorpej 			    &nwkey.i_key[0].i_keylen);
    213  1.1   thorpej 			if (val == NULL)
    214  1.1   thorpej 				return;
    215  1.1   thorpej 			i = 1;
    216  1.1   thorpej 		}
    217  1.1   thorpej 	}
    218  1.1   thorpej 	for (; i < IEEE80211_WEP_NKID; i++)
    219  1.1   thorpej 		nwkey.i_key[i].i_keylen = 0;
    220  1.1   thorpej 	(void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name));
    221  1.1   thorpej 	if (ioctl(s, SIOCS80211NWKEY, &nwkey) == -1)
    222  1.1   thorpej 		warn("SIOCS80211NWKEY");
    223  1.1   thorpej }
    224  1.1   thorpej 
    225  1.1   thorpej void
    226  1.1   thorpej setifpowersave(const char *val, int d)
    227  1.1   thorpej {
    228  1.1   thorpej 	struct ieee80211_power power;
    229  1.1   thorpej 
    230  1.1   thorpej 	(void)strncpy(power.i_name, name, sizeof(power.i_name));
    231  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1) {
    232  1.1   thorpej 		warn("SIOCG80211POWER");
    233  1.1   thorpej 		return;
    234  1.1   thorpej 	}
    235  1.1   thorpej 
    236  1.1   thorpej 	power.i_enabled = d;
    237  1.1   thorpej 	if (ioctl(s, SIOCS80211POWER, &power) == -1)
    238  1.1   thorpej 		warn("SIOCS80211POWER");
    239  1.1   thorpej }
    240  1.1   thorpej 
    241  1.1   thorpej void
    242  1.1   thorpej setifpowersavesleep(const char *val, int d)
    243  1.1   thorpej {
    244  1.1   thorpej 	struct ieee80211_power power;
    245  1.1   thorpej 
    246  1.1   thorpej 	(void)strncpy(power.i_name, name, sizeof(power.i_name));
    247  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1) {
    248  1.1   thorpej 		warn("SIOCG80211POWER");
    249  1.1   thorpej 		return;
    250  1.1   thorpej 	}
    251  1.1   thorpej 
    252  1.1   thorpej 	power.i_maxsleep = atoi(val);
    253  1.1   thorpej 	if (ioctl(s, SIOCS80211POWER, &power) == -1)
    254  1.1   thorpej 		warn("SIOCS80211POWER");
    255  1.1   thorpej }
    256  1.1   thorpej 
    257  1.1   thorpej void
    258  1.1   thorpej ieee80211_statistics(void)
    259  1.1   thorpej {
    260  1.1   thorpej 	struct ieee80211_stats stats;
    261  1.1   thorpej 
    262  1.1   thorpej 	memset(&ifr, 0, sizeof(ifr));
    263  1.3    dyoung 	ifr.ifr_buflen = sizeof(stats);
    264  1.3    dyoung 	ifr.ifr_buf = (caddr_t)&stats;
    265  1.1   thorpej 	(void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    266  1.1   thorpej 	if (ioctl(s, (zflag) ? SIOCG80211ZSTATS : SIOCG80211STATS,
    267  1.1   thorpej 	    (caddr_t)&ifr) == -1)
    268  1.1   thorpej 		return;
    269  1.2    dyoung #define	STAT_PRINT(_member, _desc)	\
    270  1.2    dyoung 	printf("\t" _desc ": %" PRIu32 "\n", stats._member)
    271  1.1   thorpej 
    272  1.2    dyoung 	STAT_PRINT(is_rx_badversion, "rx frame with bad version");
    273  1.2    dyoung 	STAT_PRINT(is_rx_tooshort, "rx frame too short");
    274  1.2    dyoung 	STAT_PRINT(is_rx_wrongbss, "rx from wrong bssid");
    275  1.2    dyoung 	STAT_PRINT(is_rx_dup, "rx discard 'cuz dup");
    276  1.2    dyoung 	STAT_PRINT(is_rx_wrongdir, "rx w/ wrong direction");
    277  1.2    dyoung 	STAT_PRINT(is_rx_mcastecho, "rx discard 'cuz mcast echo");
    278  1.2    dyoung 	STAT_PRINT(is_rx_notassoc, "rx discard 'cuz sta !assoc");
    279  1.2    dyoung 	STAT_PRINT(is_rx_noprivacy, "rx w/ wep but privacy off");
    280  1.2    dyoung 	STAT_PRINT(is_rx_unencrypted, "rx w/o wep and privacy on");
    281  1.2    dyoung 	STAT_PRINT(is_rx_wepfail, "rx wep processing failed");
    282  1.2    dyoung 	STAT_PRINT(is_rx_decap, "rx decapsulation failed");
    283  1.2    dyoung 	STAT_PRINT(is_rx_mgtdiscard, "rx discard mgt frames");
    284  1.2    dyoung 	STAT_PRINT(is_rx_ctl, "rx discard ctrl frames");
    285  1.2    dyoung 	STAT_PRINT(is_rx_beacon, "rx beacon frames");
    286  1.2    dyoung 	STAT_PRINT(is_rx_rstoobig, "rx rate set truncated");
    287  1.2    dyoung 	STAT_PRINT(is_rx_elem_missing, "rx required element missin");
    288  1.2    dyoung 	STAT_PRINT(is_rx_elem_toobig, "rx element too big");
    289  1.2    dyoung 	STAT_PRINT(is_rx_elem_toosmall, "rx element too small");
    290  1.2    dyoung 	STAT_PRINT(is_rx_elem_unknown, "rx element unknown");
    291  1.2    dyoung 	STAT_PRINT(is_rx_badchan, "rx frame w/ invalid chan");
    292  1.2    dyoung 	STAT_PRINT(is_rx_chanmismatch, "rx frame chan mismatch");
    293  1.2    dyoung 	STAT_PRINT(is_rx_nodealloc, "rx frame dropped");
    294  1.2    dyoung 	STAT_PRINT(is_rx_ssidmismatch, "rx frame ssid mismatch ");
    295  1.2    dyoung 	STAT_PRINT(is_rx_auth_unsupported, "rx w/ unsupported auth alg");
    296  1.2    dyoung 	STAT_PRINT(is_rx_auth_fail, "rx sta auth failure");
    297  1.2    dyoung 	STAT_PRINT(is_rx_auth_countermeasures, "rx auth discard 'cuz CM");
    298  1.2    dyoung 	STAT_PRINT(is_rx_assoc_bss, "rx assoc from wrong bssid");
    299  1.2    dyoung 	STAT_PRINT(is_rx_assoc_notauth, "rx assoc w/o auth");
    300  1.2    dyoung 	STAT_PRINT(is_rx_assoc_capmismatch, "rx assoc w/ cap mismatch");
    301  1.2    dyoung 	STAT_PRINT(is_rx_assoc_norate, "rx assoc w/ no rate match");
    302  1.2    dyoung 	STAT_PRINT(is_rx_assoc_badwpaie, "rx assoc w/ bad WPA IE");
    303  1.2    dyoung 	STAT_PRINT(is_rx_deauth, "rx deauthentication");
    304  1.2    dyoung 	STAT_PRINT(is_rx_disassoc, "rx disassociation");
    305  1.2    dyoung 	STAT_PRINT(is_rx_badsubtype, "rx frame w/ unknown subtyp");
    306  1.2    dyoung 	STAT_PRINT(is_rx_nobuf, "rx failed for lack of buf");
    307  1.2    dyoung 	STAT_PRINT(is_rx_decryptcrc, "rx decrypt failed on crc");
    308  1.2    dyoung 	STAT_PRINT(is_rx_ahdemo_mgt, "rx discard ahdemo mgt fram");
    309  1.2    dyoung 	STAT_PRINT(is_rx_bad_auth, "rx bad auth request");
    310  1.2    dyoung 	STAT_PRINT(is_rx_unauth, "rx on unauthorized port");
    311  1.2    dyoung 	STAT_PRINT(is_rx_badkeyid, "rx w/ incorrect keyid");
    312  1.2    dyoung 	STAT_PRINT(is_rx_ccmpreplay, "rx seq# violation (CCMP)");
    313  1.2    dyoung 	STAT_PRINT(is_rx_ccmpformat, "rx format bad (CCMP)");
    314  1.2    dyoung 	STAT_PRINT(is_rx_ccmpmic, "rx MIC check failed (CCMP)");
    315  1.2    dyoung 	STAT_PRINT(is_rx_tkipreplay, "rx seq# violation (TKIP)");
    316  1.2    dyoung 	STAT_PRINT(is_rx_tkipformat, "rx format bad (TKIP)");
    317  1.2    dyoung 	STAT_PRINT(is_rx_tkipmic, "rx MIC check failed (TKIP)");
    318  1.2    dyoung 	STAT_PRINT(is_rx_tkipicv, "rx ICV check failed (TKIP)");
    319  1.2    dyoung 	STAT_PRINT(is_rx_badcipher, "rx failed 'cuz key type");
    320  1.2    dyoung 	STAT_PRINT(is_rx_nocipherctx, "rx failed 'cuz key !setup");
    321  1.2    dyoung 	STAT_PRINT(is_rx_acl, "rx discard 'cuz acl policy");
    322  1.2    dyoung 
    323  1.2    dyoung 	STAT_PRINT(is_tx_nobuf, "tx failed for lack of buf");
    324  1.2    dyoung 	STAT_PRINT(is_tx_nonode, "tx failed for no node");
    325  1.2    dyoung 	STAT_PRINT(is_tx_unknownmgt, "tx of unknown mgt frame");
    326  1.2    dyoung 	STAT_PRINT(is_tx_badcipher, "tx failed 'cuz key type");
    327  1.2    dyoung 	STAT_PRINT(is_tx_nodefkey, "tx failed 'cuz no defkey");
    328  1.2    dyoung 	STAT_PRINT(is_tx_noheadroom, "tx failed 'cuz no space");
    329  1.2    dyoung 
    330  1.2    dyoung 	STAT_PRINT(is_scan_active, "active scans started");
    331  1.2    dyoung 	STAT_PRINT(is_scan_passive, "passive scans started");
    332  1.2    dyoung 	STAT_PRINT(is_node_timeout, "nodes timed out inactivity");
    333  1.2    dyoung 	STAT_PRINT(is_crypto_nomem, "no memory for crypto ctx");
    334  1.2    dyoung 	STAT_PRINT(is_crypto_tkip, "tkip crypto done in s/w");
    335  1.2    dyoung 	STAT_PRINT(is_crypto_tkipenmic, "tkip en-MIC done in s/w");
    336  1.2    dyoung 	STAT_PRINT(is_crypto_tkipdemic, "tkip de-MIC done in s/w");
    337  1.2    dyoung 	STAT_PRINT(is_crypto_tkipcm, "tkip counter measures");
    338  1.2    dyoung 	STAT_PRINT(is_crypto_ccmp, "ccmp crypto done in s/w");
    339  1.2    dyoung 	STAT_PRINT(is_crypto_wep, "wep crypto done in s/w");
    340  1.2    dyoung 	STAT_PRINT(is_crypto_setkey_cipher, "cipher rejected key");
    341  1.2    dyoung 	STAT_PRINT(is_crypto_setkey_nokey, "no key index for setkey");
    342  1.2    dyoung 	STAT_PRINT(is_crypto_delkey, "driver key delete failed");
    343  1.2    dyoung 	STAT_PRINT(is_crypto_badcipher, "unknown cipher");
    344  1.2    dyoung 	STAT_PRINT(is_crypto_nocipher, "cipher not available");
    345  1.2    dyoung 	STAT_PRINT(is_crypto_attachfail, "cipher attach failed");
    346  1.2    dyoung 	STAT_PRINT(is_crypto_swfallback, "cipher fallback to s/w");
    347  1.2    dyoung 	STAT_PRINT(is_crypto_keyfail, "driver key alloc failed");
    348  1.2    dyoung 	STAT_PRINT(is_crypto_enmicfail, "en-MIC failed");
    349  1.2    dyoung 	STAT_PRINT(is_ibss_capmismatch, "merge failed-cap mismatch");
    350  1.2    dyoung 	STAT_PRINT(is_ibss_norate, "merge failed-rate mismatch");
    351  1.2    dyoung 	STAT_PRINT(is_ps_unassoc, "ps-poll for unassoc. sta");
    352  1.2    dyoung 	STAT_PRINT(is_ps_badaid, "ps-poll w/ incorrect aid");
    353  1.2    dyoung 	STAT_PRINT(is_ps_qempty, "ps-poll w/ nothing to send");
    354  1.1   thorpej }
    355  1.1   thorpej 
    356  1.1   thorpej void
    357  1.1   thorpej ieee80211_status(void)
    358  1.1   thorpej {
    359  1.1   thorpej 	int i, nwkey_verbose;
    360  1.1   thorpej 	struct ieee80211_nwid nwid;
    361  1.1   thorpej 	struct ieee80211_nwkey nwkey;
    362  1.1   thorpej 	struct ieee80211_power power;
    363  1.1   thorpej 	u_int8_t keybuf[IEEE80211_WEP_NKID][16];
    364  1.1   thorpej 	struct ieee80211_bssid bssid;
    365  1.1   thorpej 	struct ieee80211chanreq channel;
    366  1.5    rpaulo 	struct ieee80211req ireq;
    367  1.1   thorpej 	struct ether_addr ea;
    368  1.1   thorpej 	static const u_int8_t zero_macaddr[IEEE80211_ADDR_LEN];
    369  1.5    rpaulo 	enum ieee80211_opmode opmode = get80211opmode();
    370  1.5    rpaulo 	extern int vflag;
    371  1.1   thorpej 
    372  1.1   thorpej 	memset(&ifr, 0, sizeof(ifr));
    373  1.1   thorpej 	ifr.ifr_data = (void *)&nwid;
    374  1.1   thorpej 	(void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
    375  1.1   thorpej 	if (ioctl(s, SIOCG80211NWID, &ifr) == -1)
    376  1.1   thorpej 		return;
    377  1.1   thorpej 	if (nwid.i_len > IEEE80211_NWID_LEN) {
    378  1.1   thorpej 		warnx("SIOCG80211NWID: wrong length of nwid (%d)", nwid.i_len);
    379  1.1   thorpej 		return;
    380  1.1   thorpej 	}
    381  1.1   thorpej 	printf("\tssid ");
    382  1.1   thorpej 	print_string(nwid.i_nwid, nwid.i_len);
    383  1.5    rpaulo 
    384  1.5    rpaulo 	if (opmode == IEEE80211_M_HOSTAP) {
    385  1.5    rpaulo 		(void)strncpy(ireq.i_name, name, sizeof(ireq.i_name));
    386  1.5    rpaulo 		ireq.i_type = IEEE80211_IOC_HIDESSID;
    387  1.5    rpaulo 		if (ioctl(s, SIOCG80211, &ireq) != -1) {
    388  1.5    rpaulo                         if (ireq.i_val)
    389  1.5    rpaulo                                 printf(" [hidden]");
    390  1.5    rpaulo                         else if (vflag)
    391  1.5    rpaulo                                 printf(" [shown]");
    392  1.5    rpaulo                 }
    393  1.5    rpaulo 
    394  1.5    rpaulo 		ireq.i_type = IEEE80211_IOC_APBRIDGE;
    395  1.5    rpaulo 		if (ioctl(s, SIOCG80211, &ireq) != -1) {
    396  1.5    rpaulo 			if (ireq.i_val)
    397  1.5    rpaulo 				printf(" apbridge");
    398  1.5    rpaulo 			else if (vflag)
    399  1.5    rpaulo 				printf(" -apbridge");
    400  1.5    rpaulo 		}
    401  1.5    rpaulo         }
    402  1.5    rpaulo 
    403  1.1   thorpej 	memset(&nwkey, 0, sizeof(nwkey));
    404  1.1   thorpej 	(void)strncpy(nwkey.i_name, name, sizeof(nwkey.i_name));
    405  1.1   thorpej 	/* show nwkey only when WEP is enabled */
    406  1.1   thorpej 	if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1 ||
    407  1.1   thorpej 	    nwkey.i_wepon == 0) {
    408  1.1   thorpej 		printf("\n");
    409  1.1   thorpej 		goto skip_wep;
    410  1.1   thorpej 	}
    411  1.1   thorpej 
    412  1.1   thorpej 	printf(" nwkey ");
    413  1.1   thorpej 	/* try to retrieve WEP keys */
    414  1.1   thorpej 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    415  1.1   thorpej 		nwkey.i_key[i].i_keydat = keybuf[i];
    416  1.1   thorpej 		nwkey.i_key[i].i_keylen = sizeof(keybuf[i]);
    417  1.1   thorpej 	}
    418  1.1   thorpej 	if (ioctl(s, SIOCG80211NWKEY, &nwkey) == -1) {
    419  1.1   thorpej 		printf("*****");
    420  1.1   thorpej 	} else {
    421  1.1   thorpej 		nwkey_verbose = 0;
    422  1.1   thorpej 		/* check to see non default key or multiple keys defined */
    423  1.1   thorpej 		if (nwkey.i_defkid != 1) {
    424  1.1   thorpej 			nwkey_verbose = 1;
    425  1.1   thorpej 		} else {
    426  1.1   thorpej 			for (i = 1; i < IEEE80211_WEP_NKID; i++) {
    427  1.1   thorpej 				if (nwkey.i_key[i].i_keylen != 0) {
    428  1.1   thorpej 					nwkey_verbose = 1;
    429  1.1   thorpej 					break;
    430  1.1   thorpej 				}
    431  1.1   thorpej 			}
    432  1.1   thorpej 		}
    433  1.1   thorpej 		/* check extra ambiguity with keywords */
    434  1.1   thorpej 		if (!nwkey_verbose) {
    435  1.1   thorpej 			if (nwkey.i_key[0].i_keylen >= 2 &&
    436  1.1   thorpej 			    isdigit(nwkey.i_key[0].i_keydat[0]) &&
    437  1.1   thorpej 			    nwkey.i_key[0].i_keydat[1] == ':')
    438  1.1   thorpej 				nwkey_verbose = 1;
    439  1.1   thorpej 			else if (nwkey.i_key[0].i_keylen >= 7 &&
    440  1.4  christos 			    strncasecmp("persist",
    441  1.4  christos 			    (const char *)nwkey.i_key[0].i_keydat, 7) == 0)
    442  1.1   thorpej 				nwkey_verbose = 1;
    443  1.1   thorpej 		}
    444  1.1   thorpej 		if (nwkey_verbose)
    445  1.1   thorpej 			printf("%d:", nwkey.i_defkid);
    446  1.1   thorpej 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
    447  1.1   thorpej 			if (i > 0)
    448  1.1   thorpej 				printf(",");
    449  1.1   thorpej 			if (nwkey.i_key[i].i_keylen < 0)
    450  1.1   thorpej 				printf("persist");
    451  1.1   thorpej 			else
    452  1.1   thorpej 				print_string(nwkey.i_key[i].i_keydat,
    453  1.1   thorpej 				    nwkey.i_key[i].i_keylen);
    454  1.1   thorpej 			if (!nwkey_verbose)
    455  1.1   thorpej 				break;
    456  1.1   thorpej 		}
    457  1.1   thorpej 	}
    458  1.1   thorpej 	printf("\n");
    459  1.1   thorpej 
    460  1.1   thorpej  skip_wep:
    461  1.1   thorpej 	(void)strncpy(power.i_name, name, sizeof(power.i_name));
    462  1.1   thorpej 	if (ioctl(s, SIOCG80211POWER, &power) == -1)
    463  1.1   thorpej 		goto skip_power;
    464  1.1   thorpej 	printf("\tpowersave ");
    465  1.1   thorpej 	if (power.i_enabled)
    466  1.1   thorpej 		printf("on (%dms sleep)", power.i_maxsleep);
    467  1.1   thorpej 	else
    468  1.1   thorpej 		printf("off");
    469  1.1   thorpej 	printf("\n");
    470  1.1   thorpej 
    471  1.1   thorpej  skip_power:
    472  1.1   thorpej 	(void)strncpy(bssid.i_name, name, sizeof(bssid.i_name));
    473  1.1   thorpej 	if (ioctl(s, SIOCG80211BSSID, &bssid) == -1)
    474  1.1   thorpej 		return;
    475  1.1   thorpej 	(void)strncpy(channel.i_name, name, sizeof(channel.i_name));
    476  1.1   thorpej 	if (ioctl(s, SIOCG80211CHANNEL, &channel) == -1)
    477  1.1   thorpej 		return;
    478  1.1   thorpej 	if (memcmp(bssid.i_bssid, zero_macaddr, IEEE80211_ADDR_LEN) == 0) {
    479  1.1   thorpej 		if (channel.i_channel != (u_int16_t)-1)
    480  1.1   thorpej 			printf("\tchan %d\n", channel.i_channel);
    481  1.1   thorpej 	} else {
    482  1.1   thorpej 		memcpy(ea.ether_addr_octet, bssid.i_bssid,
    483  1.1   thorpej 		    sizeof(ea.ether_addr_octet));
    484  1.1   thorpej 		printf("\tbssid %s", ether_ntoa(&ea));
    485  1.1   thorpej 		if (channel.i_channel != IEEE80211_CHAN_ANY)
    486  1.1   thorpej 			printf(" chan %d", channel.i_channel);
    487  1.1   thorpej 		printf("\n");
    488  1.1   thorpej 	}
    489  1.1   thorpej }
    490