ifieee80211.c revision 127831
177218Sphk/*
277218Sphk * Copyright 2001 The Aerospace Corporation.  All rights reserved.
377218Sphk *
477218Sphk * Redistribution and use in source and binary forms, with or without
577218Sphk * modification, are permitted provided that the following conditions
677218Sphk * are met:
777218Sphk * 1. Redistributions of source code must retain the above copyright
877218Sphk *    notice, this list of conditions and the following disclaimer.
977218Sphk * 2. Redistributions in binary form must reproduce the above copyright
1077218Sphk *    notice, this list of conditions and the following disclaimer in the
1177218Sphk *    documentation and/or other materials provided with the distribution.
1291454Sbrooks * 3. The name of The Aerospace Corporation may not be used to endorse or
1391454Sbrooks *    promote products derived from this software.
1477218Sphk *
1577218Sphk * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``AS IS'' AND
1677218Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1777218Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1877218Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
1977218Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2077218Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2177218Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2277218Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2377218Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2477218Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2577218Sphk * SUCH DAMAGE.
2677218Sphk *
2777218Sphk * $FreeBSD: head/sbin/ifconfig/ifieee80211.c 127831 2004-04-04 07:28:58Z phk $
2877218Sphk */
2977218Sphk
3077218Sphk/*-
3177218Sphk * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
3277218Sphk * All rights reserved.
3377218Sphk *
3477218Sphk * This code is derived from software contributed to The NetBSD Foundation
3577218Sphk * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
3677218Sphk * NASA Ames Research Center.
3777218Sphk *
3877218Sphk * Redistribution and use in source and binary forms, with or without
3977218Sphk * modification, are permitted provided that the following conditions
4077218Sphk * are met:
4177218Sphk * 1. Redistributions of source code must retain the above copyright
4277218Sphk *    notice, this list of conditions and the following disclaimer.
4377218Sphk * 2. Redistributions in binary form must reproduce the above copyright
4477218Sphk *    notice, this list of conditions and the following disclaimer in the
4577218Sphk *    documentation and/or other materials provided with the distribution.
4677218Sphk * 3. All advertising materials mentioning features or use of this software
4777218Sphk *    must display the following acknowledgement:
4877218Sphk *	This product includes software developed by the NetBSD
4977218Sphk *	Foundation, Inc. and its contributors.
5077218Sphk * 4. Neither the name of The NetBSD Foundation nor the names of its
5177218Sphk *    contributors may be used to endorse or promote products derived
5277218Sphk *    from this software without specific prior written permission.
5377218Sphk *
5477218Sphk * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
5577218Sphk * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
5677218Sphk * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
5777218Sphk * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
5877218Sphk * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5977218Sphk * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
6077218Sphk * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
6177218Sphk * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
6277218Sphk * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
6377218Sphk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
6477218Sphk * POSSIBILITY OF SUCH DAMAGE.
6577218Sphk */
6677218Sphk
6777218Sphk#include <sys/param.h>
6877218Sphk#include <sys/ioctl.h>
6977218Sphk#include <sys/socket.h>
7077218Sphk#include <sys/sysctl.h>
7177218Sphk#include <sys/time.h>
7277218Sphk
7377218Sphk#include <net/ethernet.h>
7477218Sphk#include <net/if.h>
7577218Sphk#include <net/if_dl.h>
7677218Sphk#include <net/if_types.h>
7777218Sphk#include <net/route.h>
78116957Ssam#include <net80211/ieee80211.h>
79120178Ssam#include <net80211/ieee80211_crypto.h>
80116957Ssam#include <net80211/ieee80211_ioctl.h>
8177218Sphk
8277218Sphk#include <ctype.h>
8377218Sphk#include <err.h>
8477218Sphk#include <errno.h>
8577218Sphk#include <fcntl.h>
8677218Sphk#include <stdio.h>
8777218Sphk#include <stdlib.h>
8877218Sphk#include <string.h>
8977218Sphk#include <unistd.h>
9077218Sphk
9177218Sphk#include "ifconfig.h"
9277218Sphk
9377218Sphkstatic void set80211(int s, int type, int val, int len, u_int8_t *data);
9477218Sphkstatic const char *get_string(const char *val, const char *sep,
9577218Sphk    u_int8_t *buf, int *lenp);
9677218Sphkstatic void print_string(const u_int8_t *buf, int len);
9777218Sphk
9877218Sphkvoid
9977218Sphkset80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
10077218Sphk{
10177218Sphk	int		ssid;
10277218Sphk	int		len;
10377218Sphk	u_int8_t	data[33];
10477218Sphk
10577218Sphk	ssid = 0;
106121827Sbrooks	len = strlen(val);
10788748Sambrisko	if (len > 2 && isdigit(val[0]) && val[1] == ':') {
10888748Sambrisko		ssid = atoi(val)-1;
10988748Sambrisko		val += 2;
11088748Sambrisko	}
11177218Sphk
11277218Sphk	bzero(data, sizeof(data));
11377218Sphk	len = sizeof(data);
11477218Sphk	get_string(val, NULL, data, &len);
11577218Sphk
11677218Sphk	set80211(s, IEEE80211_IOC_SSID, ssid, len, data);
11777218Sphk}
11877218Sphk
11977218Sphkvoid
12077218Sphkset80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
12177218Sphk{
12277218Sphk	int			len;
12377218Sphk	u_int8_t		data[33];
12477218Sphk
12577218Sphk	bzero(data, sizeof(data));
12677218Sphk	len = sizeof(data);
12777218Sphk	get_string(val, NULL, data, &len);
12877218Sphk
12977218Sphk	set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data);
13077218Sphk}
13177218Sphk
13277218Sphkvoid
13377218Sphkset80211channel(const char *val, int d, int s, const struct afswtch *rafp)
13477218Sphk{
135116957Ssam	if (strcmp(val, "-") == 0)
136116957Ssam		set80211(s, IEEE80211_IOC_CHANNEL, IEEE80211_CHAN_ANY, 0, NULL);
137116957Ssam	else
138116957Ssam		set80211(s, IEEE80211_IOC_CHANNEL, atoi(val), 0, NULL);
13977218Sphk}
14077218Sphk
14177218Sphkvoid
14277218Sphkset80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
14377218Sphk{
14477218Sphk	int	mode;
14577218Sphk
14691454Sbrooks	if (strcasecmp(val, "none") == 0) {
14777218Sphk		mode = IEEE80211_AUTH_NONE;
14891454Sbrooks	} else if (strcasecmp(val, "open") == 0) {
14977218Sphk		mode = IEEE80211_AUTH_OPEN;
15091454Sbrooks	} else if (strcasecmp(val, "shared") == 0) {
15177218Sphk		mode = IEEE80211_AUTH_SHARED;
15277218Sphk	} else {
15377218Sphk		err(1, "unknown authmode");
15477218Sphk	}
15577218Sphk
15677218Sphk	set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
15777218Sphk}
15877218Sphk
15977218Sphkvoid
16077218Sphkset80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp)
16177218Sphk{
16277218Sphk	int	mode;
16377218Sphk
16491454Sbrooks	if (strcasecmp(val, "off") == 0) {
16577218Sphk		mode = IEEE80211_POWERSAVE_OFF;
16691454Sbrooks	} else if (strcasecmp(val, "on") == 0) {
16777218Sphk		mode = IEEE80211_POWERSAVE_ON;
16891454Sbrooks	} else if (strcasecmp(val, "cam") == 0) {
16977218Sphk		mode = IEEE80211_POWERSAVE_CAM;
17091454Sbrooks	} else if (strcasecmp(val, "psp") == 0) {
17177218Sphk		mode = IEEE80211_POWERSAVE_PSP;
17291454Sbrooks	} else if (strcasecmp(val, "psp-cam") == 0) {
17377218Sphk		mode = IEEE80211_POWERSAVE_PSP_CAM;
17477218Sphk	} else {
17577218Sphk		err(1, "unknown powersavemode");
17677218Sphk	}
17777218Sphk
17877218Sphk	set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
17977218Sphk}
18077218Sphk
18177218Sphkvoid
18277218Sphkset80211powersave(const char *val, int d, int s, const struct afswtch *rafp)
18377218Sphk{
18477218Sphk	if (d == 0)
18577218Sphk		set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
18677218Sphk		    0, NULL);
18777218Sphk	else
18877218Sphk		set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
18977218Sphk		    0, NULL);
19077218Sphk}
19177218Sphk
19277218Sphkvoid
19377218Sphkset80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp)
19477218Sphk{
19577218Sphk	set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
19677218Sphk}
19777218Sphk
19877218Sphkvoid
19977218Sphkset80211wepmode(const char *val, int d, int s, const struct afswtch *rafp)
20077218Sphk{
20177218Sphk	int	mode;
20277218Sphk
20391454Sbrooks	if (strcasecmp(val, "off") == 0) {
20477218Sphk		mode = IEEE80211_WEP_OFF;
20591454Sbrooks	} else if (strcasecmp(val, "on") == 0) {
20677218Sphk		mode = IEEE80211_WEP_ON;
20791454Sbrooks	} else if (strcasecmp(val, "mixed") == 0) {
20877218Sphk		mode = IEEE80211_WEP_MIXED;
20977218Sphk	} else {
21077218Sphk		err(1, "unknown wep mode");
21177218Sphk	}
21277218Sphk
21377218Sphk	set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL);
21477218Sphk}
21577218Sphk
21677218Sphkvoid
21777218Sphkset80211wep(const char *val, int d, int s, const struct afswtch *rafp)
21877218Sphk{
21977218Sphk	set80211(s, IEEE80211_IOC_WEP, d, 0, NULL);
22077218Sphk}
22177218Sphk
22277218Sphkvoid
22377218Sphkset80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp)
22477218Sphk{
22577218Sphk	set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
22677218Sphk}
22777218Sphk
22877218Sphkvoid
22977218Sphkset80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
23077218Sphk{
23177218Sphk	int		key = 0;
23277218Sphk	int		len;
233120178Ssam	u_int8_t	data[IEEE80211_KEYBUF_SIZE];
23477218Sphk
23591454Sbrooks	if (isdigit(val[0]) && val[1] == ':') {
23677218Sphk		key = atoi(val)-1;
23777218Sphk		val += 2;
23877218Sphk	}
23977218Sphk
24077218Sphk	bzero(data, sizeof(data));
24177218Sphk	len = sizeof(data);
24277218Sphk	get_string(val, NULL, data, &len);
24377218Sphk
24477218Sphk	set80211(s, IEEE80211_IOC_WEPKEY, key, len, data);
24577218Sphk}
24677218Sphk
24777218Sphk/*
24877218Sphk * This function is purly a NetBSD compatability interface.  The NetBSD
24977218Sphk * iterface is too inflexable, but it's there so we'll support it since
25077218Sphk * it's not all that hard.
25177218Sphk */
25277218Sphkvoid
25377218Sphkset80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
25477218Sphk{
25577218Sphk	int		txkey;
25677218Sphk	int		i, len;
257120178Ssam	u_int8_t	data[IEEE80211_KEYBUF_SIZE];
25877218Sphk
25977218Sphk	set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
26077218Sphk
26191454Sbrooks	if (isdigit(val[0]) && val[1] == ':') {
26277218Sphk		txkey = val[0]-'0'-1;
26377218Sphk		val += 2;
26477218Sphk
26591454Sbrooks		for (i = 0; i < 4; i++) {
26677218Sphk			bzero(data, sizeof(data));
26777218Sphk			len = sizeof(data);
26877218Sphk			val = get_string(val, ",", data, &len);
26977218Sphk
27077218Sphk			set80211(s, IEEE80211_IOC_WEPKEY, i, len, data);
27177218Sphk		}
27277218Sphk	} else {
27377218Sphk		bzero(data, sizeof(data));
27477218Sphk		len = sizeof(data);
27577218Sphk		get_string(val, NULL, data, &len);
27677218Sphk		txkey = 0;
27777218Sphk
27877218Sphk		set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data);
27977218Sphk
28077218Sphk		bzero(data, sizeof(data));
28191454Sbrooks		for (i = 1; i < 4; i++)
28277218Sphk			set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data);
28377218Sphk	}
28477218Sphk
28577218Sphk	set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
28677218Sphk}
28777218Sphk
28877218Sphkvoid
289127649Ssamset80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp)
290127649Ssam{
291127649Ssam	set80211(s, IEEE80211_IOC_RTSTHRESHOLD, atoi(val), 0, NULL);
292127649Ssam}
293127649Ssam
294127649Ssamvoid
295127649Ssamset80211protmode(const char *val, int d, int s, const struct afswtch *rafp)
296127649Ssam{
297127649Ssam	int	mode;
298127649Ssam
299127649Ssam	if (strcasecmp(val, "off") == 0) {
300127649Ssam		mode = IEEE80211_PROTMODE_OFF;
301127649Ssam	} else if (strcasecmp(val, "cts") == 0) {
302127649Ssam		mode = IEEE80211_PROTMODE_CTS;
303127649Ssam	} else if (strcasecmp(val, "rtscts") == 0) {
304127649Ssam		mode = IEEE80211_PROTMODE_RTSCTS;
305127649Ssam	} else {
306127649Ssam		err(1, "unknown protection mode");
307127649Ssam	}
308127649Ssam
309127649Ssam	set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL);
310127649Ssam}
311127649Ssam
312127649Ssamvoid
313127649Ssamset80211txpower(const char *val, int d, int s, const struct afswtch *rafp)
314127649Ssam{
315127649Ssam	set80211(s, IEEE80211_IOC_TXPOWER, atoi(val), 0, NULL);
316127649Ssam}
317127649Ssam
318127649Ssamvoid
31995005Simpieee80211_status (int s, struct rt_addrinfo *info __unused)
32077218Sphk{
32177218Sphk	int			i;
32277218Sphk	int			num;
32377218Sphk	struct ieee80211req	ireq;
32477218Sphk	u_int8_t		data[32];
32577218Sphk	char			spacer;
32677218Sphk
32777218Sphk	(void) memset(&ireq, 0, sizeof(ireq));
32877218Sphk	(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
32977218Sphk	ireq.i_data = &data;
33077218Sphk
33177218Sphk	ireq.i_type = IEEE80211_IOC_SSID;
33277218Sphk	ireq.i_val = -1;
33377218Sphk	if (ioctl(s, SIOCG80211, &ireq) < 0) {
33477218Sphk		/* If we can't get the SSID, the this isn't an 802.11 device. */
33577218Sphk		return;
33677218Sphk	}
33777218Sphk	printf("\tssid ");
33877218Sphk	print_string(data, ireq.i_len);
33988748Sambrisko	num = 0;
34088748Sambrisko	ireq.i_type = IEEE80211_IOC_NUMSSIDS;
34188748Sambrisko	if (ioctl(s, SIOCG80211, &ireq) >= 0) {
34288748Sambrisko		num = ireq.i_val;
34388748Sambrisko	}
34488748Sambrisko	ireq.i_type = IEEE80211_IOC_SSID;
34588748Sambrisko	for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) {
34688748Sambrisko		if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) {
34788748Sambrisko			printf(" %d:", ireq.i_val + 1);
34888748Sambrisko			print_string(data, ireq.i_len);
34988748Sambrisko		}
35088748Sambrisko	}
35177218Sphk	printf("\n");
35277218Sphk
35377218Sphk	ireq.i_type = IEEE80211_IOC_STATIONNAME;
35477218Sphk	if (ioctl(s, SIOCG80211, &ireq) != -1) {
35577218Sphk		printf("\tstationname ");
35677218Sphk		print_string(data, ireq.i_len);
35777218Sphk		printf("\n");
35877218Sphk	}
35977218Sphk
36077218Sphk	ireq.i_type = IEEE80211_IOC_CHANNEL;
36177218Sphk	if (ioctl(s, SIOCG80211, &ireq) < 0) {
36277218Sphk		goto end;
36377218Sphk	}
36477218Sphk	printf("\tchannel %d", ireq.i_val);
36577218Sphk
36677218Sphk	ireq.i_type = IEEE80211_IOC_AUTHMODE;
36777218Sphk	if (ioctl(s, SIOCG80211, &ireq) != -1) {
36877218Sphk		printf(" authmode");
36977218Sphk		switch (ireq.i_val) {
37077218Sphk			case IEEE80211_AUTH_NONE:
37177218Sphk				printf(" NONE");
37277218Sphk				break;
37377218Sphk			case IEEE80211_AUTH_OPEN:
37477218Sphk				printf(" OPEN");
37577218Sphk				break;
37677218Sphk			case IEEE80211_AUTH_SHARED:
37777218Sphk				printf(" SHARED");
37877218Sphk				break;
37977218Sphk			default:
38077218Sphk				printf(" UNKNOWN");
38177218Sphk				break;
38277218Sphk		}
38377218Sphk	}
38477218Sphk
38577218Sphk	ireq.i_type = IEEE80211_IOC_POWERSAVE;
38677218Sphk	if (ioctl(s, SIOCG80211, &ireq) != -1 &&
38777218Sphk	    ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) {
38877218Sphk		printf(" powersavemode");
38977218Sphk		switch (ireq.i_val) {
39077218Sphk			case IEEE80211_POWERSAVE_OFF:
39177218Sphk				printf(" OFF");
39277218Sphk				break;
39377218Sphk			case IEEE80211_POWERSAVE_CAM:
39477218Sphk				printf(" CAM");
39577218Sphk				break;
39677218Sphk			case IEEE80211_POWERSAVE_PSP:
39777218Sphk				printf(" PSP");
39877218Sphk				break;
39977218Sphk			case IEEE80211_POWERSAVE_PSP_CAM:
40077218Sphk				printf(" PSP-CAM");
40177218Sphk				break;
40277218Sphk		}
40377218Sphk
40477218Sphk		ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP;
40577218Sphk		if (ioctl(s, SIOCG80211, &ireq) != -1) {
40691454Sbrooks			if (ireq.i_val)
40777218Sphk				printf(" powersavesleep %d", ireq.i_val);
40877218Sphk		}
40977218Sphk	}
41077218Sphk
41177218Sphk	printf("\n");
41277218Sphk
413127649Ssam	spacer = '\t';
414127649Ssam	ireq.i_type = IEEE80211_IOC_RTSTHRESHOLD;
415127649Ssam	if (ioctl(s, SIOCG80211, &ireq) != -1) {
416127649Ssam		printf("%crtsthreshold %d", spacer, ireq.i_val);
417127649Ssam		spacer = ' ';
418127649Ssam	}
419127649Ssam
420127649Ssam	ireq.i_type = IEEE80211_IOC_PROTMODE;
421127649Ssam	if (ioctl(s, SIOCG80211, &ireq) != -1) {
422127649Ssam		printf("%cprotmode", spacer);
423127649Ssam		switch (ireq.i_val) {
424127649Ssam			case IEEE80211_PROTMODE_OFF:
425127649Ssam				printf(" OFF");
426127649Ssam				break;
427127649Ssam			case IEEE80211_PROTMODE_CTS:
428127649Ssam				printf(" CTS");
429127649Ssam				break;
430127649Ssam			case IEEE80211_PROTMODE_RTSCTS:
431127649Ssam				printf(" RTSCTS");
432127649Ssam				break;
433127649Ssam			default:
434127649Ssam				printf(" UNKNOWN");
435127649Ssam				break;
436127649Ssam		}
437127649Ssam		spacer = ' ';
438127649Ssam	}
439127649Ssam
440127649Ssam	ireq.i_type = IEEE80211_IOC_TXPOWER;
441127649Ssam	if (ioctl(s, SIOCG80211, &ireq) != -1) {
442127649Ssam		printf("%ctxpower %d", spacer, ireq.i_val);
443127649Ssam		spacer = ' ';
444127649Ssam	}
445127649Ssam
446127649Ssam	if (spacer != '\t')
447127649Ssam		printf("\n");
448127649Ssam
44977218Sphk	ireq.i_type = IEEE80211_IOC_WEP;
45080315Sbrooks	if (ioctl(s, SIOCG80211, &ireq) != -1 &&
45180315Sbrooks	    ireq.i_val != IEEE80211_WEP_NOSUP) {
45277218Sphk		printf("\twepmode");
45377218Sphk		switch (ireq.i_val) {
45477218Sphk			case IEEE80211_WEP_OFF:
45577218Sphk				printf(" OFF");
45677218Sphk				break;
45777218Sphk			case IEEE80211_WEP_ON:
45877218Sphk				printf(" ON");
45977218Sphk				break;
46077218Sphk			case IEEE80211_WEP_MIXED:
46177218Sphk				printf(" MIXED");
46277218Sphk				break;
46377218Sphk			default:
46477218Sphk				printf(" UNKNOWN");
46577218Sphk				break;
46677218Sphk		}
46777218Sphk
46877218Sphk		/*
46977218Sphk		 * If we get here then we've got WEP support so we need
47077218Sphk		 * to print WEP status.
47191454Sbrooks		 */
47277218Sphk
47377218Sphk		ireq.i_type = IEEE80211_IOC_WEPTXKEY;
47477218Sphk		if (ioctl(s, SIOCG80211, &ireq) < 0) {
47577218Sphk			warn("WEP support, but no tx key!");
47677218Sphk			goto end;
47777218Sphk		}
47877218Sphk		printf(" weptxkey %d", ireq.i_val+1);
47977218Sphk
48077218Sphk		ireq.i_type = IEEE80211_IOC_NUMWEPKEYS;
48177218Sphk		if (ioctl(s, SIOCG80211, &ireq) < 0) {
48277218Sphk			warn("WEP support, but no NUMWEPKEYS support!");
48377218Sphk			goto end;
48477218Sphk		}
48577218Sphk		num = ireq.i_val;
48677218Sphk
48777218Sphk		printf("\n");
48877218Sphk
48977218Sphk		ireq.i_type = IEEE80211_IOC_WEPKEY;
49077218Sphk		spacer = '\t';
49191454Sbrooks		for (i = 0; i < num; i++) {
49277218Sphk			ireq.i_val = i;
49377218Sphk			if (ioctl(s, SIOCG80211, &ireq) < 0) {
49477218Sphk				warn("WEP support, but can get keys!");
49577218Sphk				goto end;
49677218Sphk			}
497120178Ssam			if (ireq.i_len == 0 ||
498120178Ssam			    ireq.i_len > IEEE80211_KEYBUF_SIZE)
49977218Sphk				continue;
50077218Sphk			printf("%cwepkey %d:%s", spacer, i+1,
501120178Ssam			    ireq.i_len <= 5 ? "40-bit" :
502120178Ssam			    ireq.i_len <= 13 ? "104-bit" : "128-bit");
50391454Sbrooks			if (spacer == '\t')
50477218Sphk				spacer = ' ';
50577218Sphk		}
50680315Sbrooks		if (spacer == ' ')
50780315Sbrooks			printf("\n");
50877218Sphk	}
50977218Sphk
51077218Sphkend:
51177218Sphk	return;
51277218Sphk}
51377218Sphk
51477218Sphkstatic void
51577218Sphkset80211(int s, int type, int val, int len, u_int8_t *data)
51677218Sphk{
51777218Sphk	struct ieee80211req	ireq;
51877218Sphk
51977218Sphk	(void) memset(&ireq, 0, sizeof(ireq));
52077218Sphk	(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
52177218Sphk	ireq.i_type = type;
52277218Sphk	ireq.i_val = val;
52377218Sphk	ireq.i_len = len;
52477218Sphk	ireq.i_data = data;
52591454Sbrooks	if (ioctl(s, SIOCS80211, &ireq) < 0)
52677218Sphk		err(1, "SIOCS80211");
52777218Sphk}
52877218Sphk
52977218Sphkstatic const char *
53077218Sphkget_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
53177218Sphk{
53277218Sphk	int len;
53377218Sphk	int hexstr;
53477218Sphk	u_int8_t *p;
53577218Sphk
53677218Sphk	len = *lenp;
53777218Sphk	p = buf;
53877218Sphk	hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
53977218Sphk	if (hexstr)
54077218Sphk		val += 2;
54177218Sphk	for (;;) {
54277218Sphk		if (*val == '\0')
54377218Sphk			break;
54477218Sphk		if (sep != NULL && strchr(sep, *val) != NULL) {
54577218Sphk			val++;
54677218Sphk			break;
54777218Sphk		}
54877218Sphk		if (hexstr) {
549127831Sphk			if (!isxdigit((u_char)val[0])) {
55077218Sphk				warnx("bad hexadecimal digits");
55177218Sphk				return NULL;
55277218Sphk			}
553127831Sphk			if (!isxdigit((u_char)val[1])) {
554127831Sphk				warnx("odd count hexadecimal digits");
555127831Sphk				return NULL;
556127831Sphk			}
55777218Sphk		}
558127831Sphk		if (p >= buf + len) {
55977218Sphk			if (hexstr)
56077218Sphk				warnx("hexadecimal digits too long");
56177218Sphk			else
562127831Sphk				warnx("string too long");
56377218Sphk			return NULL;
56477218Sphk		}
56577218Sphk		if (hexstr) {
56677218Sphk#define	tohex(x)	(isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
56777218Sphk			*p++ = (tohex((u_char)val[0]) << 4) |
56877218Sphk			    tohex((u_char)val[1]);
56977218Sphk#undef tohex
57077218Sphk			val += 2;
57177218Sphk		} else
57277218Sphk			*p++ = *val++;
57377218Sphk	}
57477218Sphk	len = p - buf;
57577218Sphk	/* The string "-" is treated as the empty string. */
57677218Sphk	if (!hexstr && len == 1 && buf[0] == '-')
57777218Sphk		len = 0;
57877218Sphk	if (len < *lenp)
57977218Sphk		memset(p, 0, *lenp - len);
58077218Sphk	*lenp = len;
58177218Sphk	return val;
58277218Sphk}
58377218Sphk
58477218Sphkstatic void
58577218Sphkprint_string(const u_int8_t *buf, int len)
58677218Sphk{
58777218Sphk	int i;
58877218Sphk	int hasspc;
58977218Sphk
59077218Sphk	i = 0;
59177218Sphk	hasspc = 0;
59291454Sbrooks	for (; i < len; i++) {
59377218Sphk		if (!isprint(buf[i]) && buf[i] != '\0')
59477218Sphk			break;
59577218Sphk		if (isspace(buf[i]))
59677218Sphk			hasspc++;
59777218Sphk	}
59877218Sphk	if (i == len) {
59977218Sphk		if (hasspc || len == 0 || buf[0] == '\0')
60077218Sphk			printf("\"%.*s\"", len, buf);
60177218Sphk		else
60277218Sphk			printf("%.*s", len, buf);
60377218Sphk	} else {
60477218Sphk		printf("0x");
60577218Sphk		for (i = 0; i < len; i++)
60677218Sphk			printf("%02x", buf[i]);
60777218Sphk	}
60877218Sphk}
60977218Sphk
610