diff --git a/usr.sbin/wlconfig/Makefile b/usr.sbin/wlconfig/Makefile new file mode 100644 index 000000000000..21fd7cc4165d --- /dev/null +++ b/usr.sbin/wlconfig/Makefile @@ -0,0 +1,7 @@ +# $Id$ +PROG= wlconfig +SRCS= wlconfig.c +CFLAGS+= Wall +MAN8= wlconfig.8 + +.include diff --git a/usr.sbin/wlconfig/wlconfig.8 b/usr.sbin/wlconfig/wlconfig.8 new file mode 100644 index 000000000000..6267c182318c --- /dev/null +++ b/usr.sbin/wlconfig/wlconfig.8 @@ -0,0 +1,103 @@ +.Dd December 26 1996 +.Os +.Dt WLCONFIG 8 +.Sh NAME +.Nm wlconfig +.Nd read/write wavelan config parameters +.Sh SYNOPSIS +.Nm wlconfig +.Ar ifname +.Op Ar param value ... +.Sh DESCRIPTION +The +.Nm wlconfig +command can be used to read and set parameters for the NCR/AT&T Wavelan +radio LAN card. Various parameters stored in the nonvolatile Parameter +Storage Area (PSA) on the card can be modified with this program, which +obviates the need for the DOS-based +.Nm instconf.exe +program. +.Pp +The +.Ar ifname +parameter specifies the wavelan interface name (eg. +.Pa wl0 +). If no other arguments are supplied, the current contents of the PSA +are interpreted and displayed. +.Pp +The +.Ar param +and +.Ar value +arguments can be used to change the value of several of the parameters. +Any number of +.Ar param value +pairs may be supplied. +.Bl -tag -width 15n -compat -offset indent +.It Va param +.Va value +.It irq +IRQ value (used at next reset), may be one of 3,4,5,6,10,11,12,15 +.It mac +Local MAC value (ethernet address) +.It macsel +.Sq soft +(as set by the +.Sq mac +parameter) or +.Sq default +(as set at the factory). +.It nwid +The NWID is a 2-byte parameter passed to the card's radio modem. +NWIDs allow multiple logically discrete networks to operate +independantly whilse occupying the same airspace. +Packets with a different NWID are simply ignored by the modem. +In the hardware, NWIDs are stored long-term in non-volative memory +(called the PSA or programmable storage area), and are loaded by +software into the radio modem when the driver is +initialized. This sets the default NWID loaded at startup. +.It curnwid +This sets the current operating NWID (but does not save it to the +PSA). +.El +.Pp +Note that if the IRQ on the Wavelan card is incorrect, the interface +will be configured, but will not function. The +.Nm wlconfig +program should then be used to reconfigure the card to a sensible +value. +.Sh EXAMPLES +Set the NWID to 0x1234 : +.Bd -literal -offset +# wlconfig wl0 nwid 0x1234 +.Ed +.Pp +Show the current settings : +.Bd -literal -offset +# wlconfig wl0 +Board type : ISA +Base address options : 0x300, 0x390, 0x3c0, 0x3e0 +Waitstates : 0 +Bus mode : ISA +IRQ : 10 +Default MAC address : 08:00:0e:20:3d:4b +Soft MAC address : 00:00:00:00:00:00 +Current MAC address : Default +Adapter compatability : PC-AT 2.4GHz +Threshold preset : 1 +Call code required : NO +Subband : 2425MHz +Quality threshold : 3 +Hardware version : 0 (Rel1/Rel2) +Network ID enable : YES +NWID : 0xdead +Datalink security : NO +Databus width : 16 (variable) +Configuration state : unconfigured +CRC-16 : 0x3c26 +CRC status : OK +.Ed +.Sh HISTORY +This implementation of the +.Nm wlconfig +command is completely new, written for Hilink Internet by Michael Smith. diff --git a/usr.sbin/wlconfig/wlconfig.c b/usr.sbin/wlconfig/wlconfig.c new file mode 100644 index 000000000000..10771c957033 --- /dev/null +++ b/usr.sbin/wlconfig/wlconfig.c @@ -0,0 +1,325 @@ +/* + * Copyright (C) 1996 + * Michael Smith. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY Michael Smith AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Michael Smith OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + * + */ +/* + * wlconfig.c + * + * utility to read out and change various WAVELAN parameters. + * Currently supports NWID and IRQ values. + * + * The NWID is used by 2 or more wavelan controllers to determine + * if packets should be received or not. It is a filter that + * is roughly analogous to the "channel" setting with a garage + * door controller. Two companies side by side with wavelan devices + * that could actually hear each other can use different NWIDs + * and ignore packets. In truth however, the air space is shared, + * and the NWID is a virtual filter. + * + * In the current set of wavelan drivers, ioctls changed only + * the runtime radio modem registers which act in a manner analogous + * to an ethernet transceiver. The ioctls do not change the + * stored nvram PSA (or parameter storage area). At boot, the PSA + * values are stored in the radio modem. Thus when the + * system reboots it will restore the wavelan NWID to the value + * stored in the PSA. The NCR/ATT dos utilities must be used to + * change the initial NWID values in the PSA. The wlconfig utility + * may be used to set a different NWID at runtime; this is only + * permitted while the interface is up and running. + * + * By contrast, the IRQ value can only be changed while the + * Wavelan card is down and unconfigured, and it will remain + * disabled after an IRQ change until reboot. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +extern struct ether_addr *ether_aton(char *a); + +#include +#include +#include +#include +#include +#include + +/* translate IRQ bit to number */ +/* array for maping irq numbers to values for the irq parameter register */ +static int irqvals[16] = { + 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80 +}; + +int +wlirq(int irqval) +{ + int irq; + + for(irq = 0; irq < 16; irq++) + if(irqvals[irq] == irqval) + return(irq); + return 0; +} + +char *compat_type[] = { + "PC-AT 915MHz", + "PC-MC 915MHz", + "PC-AT 2.4GHz", + "PC-MC 2.4GHz", + "PCCARD or 1/2 size AT, 915MHz or 2.4GHz" +}; + +char *subband[] = { + "915MHz/see WaveModem", + "2425MHz", + "2460MHz", + "2484MHz", + "2430.5MHz" +}; + + +/* +** print_psa +** +** Given a pointer to a PSA structure, print it out +*/ +void +print_psa(u_char *psa, int currnwid) +{ + int nwid; + + /* + ** Work out what sort of board we have + */ + if (psa[0] == 0x14) { + printf("Board type : Microchannel\n"); + } else { + if (psa[1] == 0) { + printf("Board type : PCCARD\n"); + } else { + printf("Board type : ISA"); + if ((psa[4] == 0) && + (psa[5] == 0) && + (psa[6] == 0)) + printf(" (DEC OEM)"); + printf("\n"); + printf("Base address options : 0x300, 0x%02x0, 0x%02x0, 0x%02x0\n", + (int)psa[1], (int)psa[2], (int)psa[3]); + printf("Waitstates : %d\n",psa[7] & 0xf); + printf("Bus mode : %s\n",(psa[7] & 0x10) ? "EISA" : "ISA"); + printf("IRQ : %d\n",wlirq(psa[8])); + } + } + printf("Default MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n", + psa[0x10],psa[0x11],psa[0x12],psa[0x13],psa[0x14],psa[0x15]); + printf("Soft MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n", + psa[0x16],psa[0x17],psa[0x18],psa[0x19],psa[0x1a],psa[0x1b]); + printf("Current MAC address : %s\n",(psa[0x1c] & 0x1) ? "Soft" : "Default"); + printf("Adapter compatability : "); + if (psa[0x1d] < 5) { + printf("%s\n",compat_type[psa[0x1d]]); + } else { + printf("unknown\n"); + } + printf("Threshold preset : %d\n",psa[0x1e]); + printf("Call code required : %s\n",(psa[0x1f] & 0x1) ? "YES" : "NO"); + if (psa[0x1f] & 0x1) + printf("Call code : 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + psa[0x30],psa[0x31],psa[0x32],psa[0x33],psa[0x34],psa[0x35],psa[0x36],psa[0x37]); + printf("Subband : %s\n",subband[psa[0x20] & 0xf]); + printf("Quality threshold : %d\n",psa[0x21]); + printf("Hardware version : %d (%s)\n",psa[0x22],psa[0x22] ? "Rel3" : "Rel1/Rel2"); + printf("Network ID enable : %s\n",(psa[0x25] & 0x1) ? "YES" : "NO"); + if (psa[0x25] & 0x1) { + nwid = (psa[0x23] << 8) + psa[0x24]; + printf("NWID : 0x%04x\n",nwid); + if (nwid != currnwid) { + printf("Current NWID : 0x%04x\n",currnwid); + } + } + printf("Datalink security : %s\n",(psa[0x26] & 0x1) ? "YES" : "NO"); + if (psa[0x26] & 0x1) { + printf("Encryption key : "); + if (psa[0x27] == 0) { + printf("DENIED\n"); + } else { + printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + psa[0x27],psa[0x28],psa[0x29],psa[0x2a],psa[0x2b],psa[0x2c],psa[0x2d],psa[0x2e]); + } + } + printf("Databus width : %d (%s)\n", + (psa[0x2f] & 0x1) ? 16 : 8, (psa[0x2f] & 0x80) ? "fixed" : "variable"); + printf("Configuration state : %sconfigured\n",(psa[0x38] & 0x1) ? "" : "un"); + printf("CRC-16 : 0x%02x%02x\n",psa[0x3e],psa[0x3d]); + printf("CRC status : "); + switch(psa[0x3f]) { + case 0xaa: + printf("OK\n"); + break; + case 0x55: + printf("BAD\n"); + break; + default: + printf("Error\n"); + break; + } +} + + +void +syntax(char *pname) +{ + fprintf(stderr,"Usage: %s [ ...]\n",pname); + fprintf(stderr," Wavelan interface name.\n"); + fprintf(stderr," Parameter name (see below)\n"); + fprintf(stderr," New value for parameter.\n"); + fprintf(stderr," Parameter name: Value:\n"); + fprintf(stderr," irq 3,4,5,6,10,11,12,15\n"); + fprintf(stderr," mac soft ethernet address\n"); + fprintf(stderr," macsel soft or default\n"); + fprintf(stderr," nwid default NWID (0x0-0xffff)\n"); + fprintf(stderr," currnwid current NWID (0x0-0xffff) or 'get'\n"); + exit(1); +} + +void +main(int argc, char *argv[]) +{ + int sd; + struct ifreq ifr; + u_char psabuf[0x40]; + int val, argind, i; + char *cp, *param, *value; + struct ether_addr *ea; + int work = 0; + int currnwid; + + if ((argc < 2) || (argc % 2)) + syntax(argv[0]); + + /* get a socket */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0) + err(1,"socket"); + strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)); + ifr.ifr_addr.sa_family = AF_INET; + + /* get the PSA */ + ifr.ifr_data = (caddr_t)psabuf; + if (ioctl(sd, SIOCGWLPSA, (caddr_t)&ifr)) + err(1,"Get PSA"); + + /* get the current NWID */ + if (ioctl(sd, SIOCGWLCNWID, (caddr_t)&ifr)) + err(1,"Get NWID"); + currnwid = (int)ifr.ifr_data; + + /* just dump and exit? */ + if (argc == 2) { + print_psa(psabuf, currnwid); + exit(0); + } + + /* loop reading arg pairs */ + for (argind = 2; argind < argc; argind += 2) { + + param = argv[argind]; + value = argv[argind+1]; + + /* What to do? */ + + if (!strcasecmp(param,"currnwid")) { /* set current NWID */ + val = strtol(value,&cp,0); + if ((val < 0) || (val > 0xffff) || (cp == value)) + errx(1,"Bad NWID '%s'",value); + + ifr.ifr_data = (caddr_t)val; + if (ioctl(sd, SIOCSWLCNWID, (caddr_t)&ifr)) + err(1,"Set NWID (interface not up?)"); + continue ; + } + + if (!strcasecmp(param,"irq")) { + val = strtol(value,&cp,0); + val = irqvals[val]; + if ((val == 0) || (cp == value)) + errx(1,"Bad IRQ '%s'",value); + psabuf[WLPSA_IRQNO] = (u_char)val; + work = 1; + continue; + } + + if (!strcasecmp(param,"mac")) { + if ((ea = ether_aton(value)) == NULL) + errx(1,"Bad ethernet address '%s'",value); + for (i = 0; i < 6; i++) + psabuf[WLPSA_LOCALMAC + i] = ea->octet[i]; + work = 1; + continue; + } + + if (!strcasecmp(param,"macsel")) { + if (!strcasecmp(value,"local")) { + psabuf[WLPSA_MACSEL] |= 0x1; + work = 1; + continue; + } + if (!strcasecmp(value,"universal")) { + psabuf[WLPSA_MACSEL] &= ~0x1; + work = 1; + continue; + } + errx(1,"Bad macsel value '%s'",value); + } + + if (!strcasecmp(param,"nwid")) { + val = strtol(value,&cp,0); + if ((val < 0) || (val > 0xffff) || (cp == value)) + errx(1,"Bad NWID '%s'",value); + psabuf[WLPSA_NWID] = (val >> 8) & 0xff; + psabuf[WLPSA_NWID+1] = val & 0xff; + work = 1; + continue; + } + errx(1,"Unknown parameter '%s'",param); + } + if (work) { + ifr.ifr_data = (caddr_t)psabuf; + if (ioctl(sd, SIOCSWLPSA, (caddr_t)&ifr)) + err(1,"Set PSA"); + } +} + + + +