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