ifieee80211.c revision 121827
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 121827 2003-11-01 00:03:20Z brooks $
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
28995005Simpieee80211_status (int s, struct rt_addrinfo *info __unused)
29077218Sphk{
29177218Sphk	int			i;
29277218Sphk	int			num;
29377218Sphk	struct ieee80211req	ireq;
29477218Sphk	u_int8_t		data[32];
29577218Sphk	char			spacer;
29677218Sphk
29777218Sphk	(void) memset(&ireq, 0, sizeof(ireq));
29877218Sphk	(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
29977218Sphk	ireq.i_data = &data;
30077218Sphk
30177218Sphk	ireq.i_type = IEEE80211_IOC_SSID;
30277218Sphk	ireq.i_val = -1;
30377218Sphk	if (ioctl(s, SIOCG80211, &ireq) < 0) {
30477218Sphk		/* If we can't get the SSID, the this isn't an 802.11 device. */
30577218Sphk		return;
30677218Sphk	}
30777218Sphk	printf("\tssid ");
30877218Sphk	print_string(data, ireq.i_len);
30988748Sambrisko	num = 0;
31088748Sambrisko	ireq.i_type = IEEE80211_IOC_NUMSSIDS;
31188748Sambrisko	if (ioctl(s, SIOCG80211, &ireq) >= 0) {
31288748Sambrisko		num = ireq.i_val;
31388748Sambrisko	}
31488748Sambrisko	ireq.i_type = IEEE80211_IOC_SSID;
31588748Sambrisko	for (ireq.i_val = 0; ireq.i_val < num; ireq.i_val++) {
31688748Sambrisko		if (ioctl(s, SIOCG80211, &ireq) >= 0 && ireq.i_len > 0) {
31788748Sambrisko			printf(" %d:", ireq.i_val + 1);
31888748Sambrisko			print_string(data, ireq.i_len);
31988748Sambrisko		}
32088748Sambrisko	}
32177218Sphk	printf("\n");
32277218Sphk
32377218Sphk	ireq.i_type = IEEE80211_IOC_STATIONNAME;
32477218Sphk	if (ioctl(s, SIOCG80211, &ireq) != -1) {
32577218Sphk		printf("\tstationname ");
32677218Sphk		print_string(data, ireq.i_len);
32777218Sphk		printf("\n");
32877218Sphk	}
32977218Sphk
33077218Sphk	ireq.i_type = IEEE80211_IOC_CHANNEL;
33177218Sphk	if (ioctl(s, SIOCG80211, &ireq) < 0) {
33277218Sphk		goto end;
33377218Sphk	}
33477218Sphk	printf("\tchannel %d", ireq.i_val);
33577218Sphk
33677218Sphk	ireq.i_type = IEEE80211_IOC_AUTHMODE;
33777218Sphk	if (ioctl(s, SIOCG80211, &ireq) != -1) {
33877218Sphk		printf(" authmode");
33977218Sphk		switch (ireq.i_val) {
34077218Sphk			case IEEE80211_AUTH_NONE:
34177218Sphk				printf(" NONE");
34277218Sphk				break;
34377218Sphk			case IEEE80211_AUTH_OPEN:
34477218Sphk				printf(" OPEN");
34577218Sphk				break;
34677218Sphk			case IEEE80211_AUTH_SHARED:
34777218Sphk				printf(" SHARED");
34877218Sphk				break;
34977218Sphk			default:
35077218Sphk				printf(" UNKNOWN");
35177218Sphk				break;
35277218Sphk		}
35377218Sphk	}
35477218Sphk
35577218Sphk	ireq.i_type = IEEE80211_IOC_POWERSAVE;
35677218Sphk	if (ioctl(s, SIOCG80211, &ireq) != -1 &&
35777218Sphk	    ireq.i_val != IEEE80211_POWERSAVE_NOSUP ) {
35877218Sphk		printf(" powersavemode");
35977218Sphk		switch (ireq.i_val) {
36077218Sphk			case IEEE80211_POWERSAVE_OFF:
36177218Sphk				printf(" OFF");
36277218Sphk				break;
36377218Sphk			case IEEE80211_POWERSAVE_CAM:
36477218Sphk				printf(" CAM");
36577218Sphk				break;
36677218Sphk			case IEEE80211_POWERSAVE_PSP:
36777218Sphk				printf(" PSP");
36877218Sphk				break;
36977218Sphk			case IEEE80211_POWERSAVE_PSP_CAM:
37077218Sphk				printf(" PSP-CAM");
37177218Sphk				break;
37277218Sphk		}
37377218Sphk
37477218Sphk		ireq.i_type = IEEE80211_IOC_POWERSAVESLEEP;
37577218Sphk		if (ioctl(s, SIOCG80211, &ireq) != -1) {
37691454Sbrooks			if (ireq.i_val)
37777218Sphk				printf(" powersavesleep %d", ireq.i_val);
37877218Sphk		}
37977218Sphk	}
38077218Sphk
38177218Sphk	printf("\n");
38277218Sphk
38377218Sphk	ireq.i_type = IEEE80211_IOC_WEP;
38480315Sbrooks	if (ioctl(s, SIOCG80211, &ireq) != -1 &&
38580315Sbrooks	    ireq.i_val != IEEE80211_WEP_NOSUP) {
38677218Sphk		printf("\twepmode");
38777218Sphk		switch (ireq.i_val) {
38877218Sphk			case IEEE80211_WEP_OFF:
38977218Sphk				printf(" OFF");
39077218Sphk				break;
39177218Sphk			case IEEE80211_WEP_ON:
39277218Sphk				printf(" ON");
39377218Sphk				break;
39477218Sphk			case IEEE80211_WEP_MIXED:
39577218Sphk				printf(" MIXED");
39677218Sphk				break;
39777218Sphk			default:
39877218Sphk				printf(" UNKNOWN");
39977218Sphk				break;
40077218Sphk		}
40177218Sphk
40277218Sphk		/*
40377218Sphk		 * If we get here then we've got WEP support so we need
40477218Sphk		 * to print WEP status.
40591454Sbrooks		 */
40677218Sphk
40777218Sphk		ireq.i_type = IEEE80211_IOC_WEPTXKEY;
40877218Sphk		if (ioctl(s, SIOCG80211, &ireq) < 0) {
40977218Sphk			warn("WEP support, but no tx key!");
41077218Sphk			goto end;
41177218Sphk		}
41277218Sphk		printf(" weptxkey %d", ireq.i_val+1);
41377218Sphk
41477218Sphk		ireq.i_type = IEEE80211_IOC_NUMWEPKEYS;
41577218Sphk		if (ioctl(s, SIOCG80211, &ireq) < 0) {
41677218Sphk			warn("WEP support, but no NUMWEPKEYS support!");
41777218Sphk			goto end;
41877218Sphk		}
41977218Sphk		num = ireq.i_val;
42077218Sphk
42177218Sphk		printf("\n");
42277218Sphk
42377218Sphk		ireq.i_type = IEEE80211_IOC_WEPKEY;
42477218Sphk		spacer = '\t';
42591454Sbrooks		for (i = 0; i < num; i++) {
42677218Sphk			ireq.i_val = i;
42777218Sphk			if (ioctl(s, SIOCG80211, &ireq) < 0) {
42877218Sphk				warn("WEP support, but can get keys!");
42977218Sphk				goto end;
43077218Sphk			}
431120178Ssam			if (ireq.i_len == 0 ||
432120178Ssam			    ireq.i_len > IEEE80211_KEYBUF_SIZE)
43377218Sphk				continue;
43477218Sphk			printf("%cwepkey %d:%s", spacer, i+1,
435120178Ssam			    ireq.i_len <= 5 ? "40-bit" :
436120178Ssam			    ireq.i_len <= 13 ? "104-bit" : "128-bit");
43791454Sbrooks			if (spacer == '\t')
43877218Sphk				spacer = ' ';
43977218Sphk		}
44080315Sbrooks		if (spacer == ' ')
44180315Sbrooks			printf("\n");
44277218Sphk	}
44377218Sphk
44477218Sphkend:
44577218Sphk	return;
44677218Sphk}
44777218Sphk
44877218Sphkstatic void
44977218Sphkset80211(int s, int type, int val, int len, u_int8_t *data)
45077218Sphk{
45177218Sphk	struct ieee80211req	ireq;
45277218Sphk
45377218Sphk	(void) memset(&ireq, 0, sizeof(ireq));
45477218Sphk	(void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
45577218Sphk	ireq.i_type = type;
45677218Sphk	ireq.i_val = val;
45777218Sphk	ireq.i_len = len;
45877218Sphk	ireq.i_data = data;
45991454Sbrooks	if (ioctl(s, SIOCS80211, &ireq) < 0)
46077218Sphk		err(1, "SIOCS80211");
46177218Sphk}
46277218Sphk
46377218Sphkstatic const char *
46477218Sphkget_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
46577218Sphk{
46677218Sphk	int len;
46777218Sphk	int hexstr;
46877218Sphk	u_int8_t *p;
46977218Sphk
47077218Sphk	len = *lenp;
47177218Sphk	p = buf;
47277218Sphk	hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
47377218Sphk	if (hexstr)
47477218Sphk		val += 2;
47577218Sphk	for (;;) {
47677218Sphk		if (*val == '\0')
47777218Sphk			break;
47877218Sphk		if (sep != NULL && strchr(sep, *val) != NULL) {
47977218Sphk			val++;
48077218Sphk			break;
48177218Sphk		}
48277218Sphk		if (hexstr) {
48377218Sphk			if (!isxdigit((u_char)val[0]) ||
48477218Sphk			    !isxdigit((u_char)val[1])) {
48577218Sphk				warnx("bad hexadecimal digits");
48677218Sphk				return NULL;
48777218Sphk			}
48877218Sphk		}
48977218Sphk		if (p > buf + len) {
49077218Sphk			if (hexstr)
49177218Sphk				warnx("hexadecimal digits too long");
49277218Sphk			else
49377218Sphk				warnx("strings too long");
49477218Sphk			return NULL;
49577218Sphk		}
49677218Sphk		if (hexstr) {
49777218Sphk#define	tohex(x)	(isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
49877218Sphk			*p++ = (tohex((u_char)val[0]) << 4) |
49977218Sphk			    tohex((u_char)val[1]);
50077218Sphk#undef tohex
50177218Sphk			val += 2;
50277218Sphk		} else
50377218Sphk			*p++ = *val++;
50477218Sphk	}
50577218Sphk	len = p - buf;
50677218Sphk	/* The string "-" is treated as the empty string. */
50777218Sphk	if (!hexstr && len == 1 && buf[0] == '-')
50877218Sphk		len = 0;
50977218Sphk	if (len < *lenp)
51077218Sphk		memset(p, 0, *lenp - len);
51177218Sphk	*lenp = len;
51277218Sphk	return val;
51377218Sphk}
51477218Sphk
51577218Sphkstatic void
51677218Sphkprint_string(const u_int8_t *buf, int len)
51777218Sphk{
51877218Sphk	int i;
51977218Sphk	int hasspc;
52077218Sphk
52177218Sphk	i = 0;
52277218Sphk	hasspc = 0;
52391454Sbrooks	for (; i < len; i++) {
52477218Sphk		if (!isprint(buf[i]) && buf[i] != '\0')
52577218Sphk			break;
52677218Sphk		if (isspace(buf[i]))
52777218Sphk			hasspc++;
52877218Sphk	}
52977218Sphk	if (i == len) {
53077218Sphk		if (hasspc || len == 0 || buf[0] == '\0')
53177218Sphk			printf("\"%.*s\"", len, buf);
53277218Sphk		else
53377218Sphk			printf("%.*s", len, buf);
53477218Sphk	} else {
53577218Sphk		printf("0x");
53677218Sphk		for (i = 0; i < len; i++)
53777218Sphk			printf("%02x", buf[i]);
53877218Sphk	}
53977218Sphk}
54077218Sphk
541