BSD 4_3_Net_2 release
[unix-history] / usr / src / contrib / usr.x25 / x25config.c
/*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* %sccs.include.redist.c%
*
* %W% (Berkeley) %G%
*/
/*
* Configure X.25 interface
*
* Copyright (c) 1986 University of British Columbia
*
* Frank Pronk
* February 1986
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netccitt/x25.h>
#include <stdio.h>
#include <netdb.h>
#define IFFBITS \
"\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP"
int setifflags (), setdefault (), setnet (), setntn (), setprepnd0 ();
int setlproto (), sethdlc (), setlwsize (), setltrace (), setnodnic ();
int setyear (), setpwsize (), setpacketsize (), setmaxlcn (), setptrace ();
struct cmd {
char *c_name;
int c_arg;
int (*c_func) ();
} cmds[] = {
"up", IFF_UP, setifflags,
"-up", -IFF_UP, setifflags,
"down", -IFF_UP, setifflags,
"debug", IFF_DEBUG, setifflags,
"-debug", -IFF_DEBUG, setifflags,
"default", 0, setdefault,
"hdlc", CCITTPROTO_HDLC, setlproto,
"ieee802llc", IEEEPROTO_802LLC, setlproto,
"lap", HDLCPROTO_LAP, sethdlc,
"lapb", HDLCPROTO_LAPB, sethdlc,
"lapd", HDLCPROTO_LAPD, sethdlc,
"unset", HDLCPROTO_UNSET, sethdlc,
"-ltrace", 0, setltrace,
"ltrace", 1, setltrace,
"-prepnd0", 0, setprepnd0,
"prepnd0", 1, setprepnd0,
"-nodnic", 0, setnodnic,
"nodnic", 1, setnodnic,
"1976", X25_1976, setyear,
"1980", X25_1980, setyear,
"1984", X25_1984, setyear,
"-ptrace", 0, setptrace,
"ptrace", 1, setptrace,
"-net", 0, setnet,
"-ntn", 0, setntn,
"-lwsize", 0, setlwsize,
"-pwsize", 0, setpwsize,
"-psize", 0, setpacketsize,
"-maxlcn", 0, setmaxlcn,
0, 0, 0
};
struct ifreq ifr;
struct ifreq_x25 ifrx25;
#define x25conf ifrx25.ifr_xc
char *myname;
char *ifname; /* interface name */
short ifflags; /* local copy of interface flags */
main (argc, argv)
register char **argv;
int argc;
{
register int s;
myname = *argv;
if (argc < 2)
abort ("usage: x25ifconfig interface [default] [-net net] [-ntn ntn] [-maxlcn maxlcn] [up] [down] [zillions of other options]");
if ((s = socket (AF_CCITT, SOCK_STREAM, 0)) < 0)
syserr ("socket");
argv[argc] = 0;
argv++;
ifname = *argv;
strcpy (ifr.ifr_name, ifname);
if (ioctl (s, SIOCGIFFLAGS, (char *)&ifr) < 0)
syserr ("ioctl (SIOCGIFFLAGS)");
ifflags = ifr.ifr_flags;
strcpy (ifrx25.ifr_name, ifname);
if (ioctl (s, SIOCGIFCONF_X25, (char *)&ifrx25) < 0) {
x25conf.xc_addr.x25_len = sizeof(x25conf);
x25conf.xc_addr.x25_family = AF_CCITT;
}
if (argc == 2) {
status ();
exit (0);
}
argv++;
while (*argv) {
register struct cmd *cp;
register int argneeded;
argneeded = 0;
for (cp = cmds; ; cp++) {
if (cp->c_name == 0)
abort ("invalid argument: %s", *argv);
if (cp->c_func == setnet)
argneeded++;
if (strcmp (cp->c_name, *argv) == 0) {
if (argneeded) {
if (argv[1]) {
argv++;
(*cp->c_func) (*argv);
} else
abort ("argument expect after %s", *argv);
} else
(*cp->c_func) (cp->c_arg);
break;
}
}
argv++;
}
ifr.ifr_flags = ifflags;
strcpy (ifr.ifr_name, ifname);
if (ioctl (s, SIOCSIFFLAGS, (char *)&ifr) < 0)
syserr ("ioctl (SIOCSIFFLAGS)");
strcpy (ifrx25.ifr_name, ifname);
if (ioctl (s, SIOCSIFCONF_X25, (char *)&ifrx25) < 0)
syserr ("ioctl (SIOCSIFCONF_X25)");
exit (0);
}
/* VARARGS */
abort (fmt, a1, a2, a3, a4, a5)
char *fmt;
{
char buf[128];
sprintf (buf, "%s: %s\n", myname, fmt);
fprintf (stderr, buf, a1, a2, a3, a4, a5);
exit (1);
}
/* VARARGS */
syserr (fmt, a1, a2, a3, a4, a5)
char *fmt;
{
char buf[128];
extern int errno;
extern char *sys_errlist[];
sprintf (buf, "%s: %s: %s\n", myname, fmt, sys_errlist[errno]);
fprintf (stderr, buf, a1, a2, a3, a4, a5);
exit (1);
}
status ()
{
char *addr = x25conf.xc_addr.x25_addr;
printf ("%s: ", ifname);
printb ("interface flags", ifflags, IFFBITS);
printf ("link level:\n");
printf ("\twindow size: %d\n", x25conf.xc_lwsize);
if (x25conf.xc_ltrace)
printf ("\ttracing: on\n");
printf ("\npacket level:\n");
printf ("\taddress: %04d %s\n", x25conf.xc_addr.x25_net, addr);
printf ("\twindow size: %d\n", x25conf.xc_pwsize);
printf ("\tpacket size: %d\n", 1 << x25conf.xc_psize);
printf ("\tmax lcn: %d\n", x25conf.xc_maxlcn);
if (x25conf.xc_ptrace)
printf ("\ttracing: on\n");
}
setifflags (value)
{
if (value < 0) {
value = -value;
ifflags &= ~value;
} else
ifflags |= value;
}
/* VARARGS */
setdefault (arg)
{
x25conf.xc_addr.x25_family = AF_CCITT;
x25conf.xc_lproto = CCITTPROTO_HDLC;
x25conf.xc_lptype = HDLCPROTO_LAPB;
x25conf.xc_lwsize = 7;
x25conf.xc_pwsize = 2;
x25conf.xc_psize = X25_PS128;
x25conf.xc_type = X25_1976;
}
setnet (arg)
char *arg;
{
register int net;
register struct netent *np;
if (*arg < '0' || *arg > '9') { /* lookup name in /etc/networks */
if ((np = getnetbyname (arg)) == 0)
abort ("unknown network (%s)", arg);
net = np->n_net;
} else
net = atoi (arg);
x25conf.xc_addr.x25_net = net;
}
setntn (arg)
register char *arg;
{
register int l;
register char *p;
register struct hostent *hp;
struct hostent *getx25hostbyname ();
if (*arg < '0' || *arg > '9') { /* lookup in /etc/x25hosts */
if ((hp = getx25hostbyname (arg)) == 0)
abort ("can't find '%s' in /etc/x25hosts", arg);
arg = ((struct sockaddr_x25 *)hp->h_addr)->x25_addr;
l = strlen (arg) + 1;
} else
for (l = 1, p = arg; *p; p++) {
l++;
if (*p < '0' || *p > '9')
abort ("invalid character in ntn address");
}
if (l > sizeof (x25conf.xc_addr.x25_addr))
abort ("invalid ntn address");
bcopy(arg, x25conf.xc_addr.x25_addr, l);
}
to_bcd (src, dest)
register char *src, *dest;
{
register int i;
for(i = 0; *src; i++)
if (i & 0x01 )
*dest++ |= *src++ & 0x0F;
else
*dest = *src++ << 4;
}
from_bcd (src, dest, len)
char *src, *dest;
{
register int i;
for (i = 0; i < len/2; i++) {
*dest++ = ((*src & 0xf0) >> 4) + '0';
*dest++ = (*src++ & 0xf) + '0';
}
*dest = 0;
}
setlproto (arg)
{
x25conf.xc_lproto = arg;
}
sethdlc (arg)
{
x25conf.xc_lptype = arg;
}
setlwsize (arg)
char *arg;
{
register int ws;
if ((ws = atoi (arg)) <= 0 || ws > 31)
abort ("invalid link level window size");
x25conf.xc_lwsize = ws;
}
setprepnd0 (arg)
{
x25conf.xc_prepnd0 = arg;
}
setnodnic (arg)
{
x25conf.xc_nodnic = arg;
}
setltrace (arg)
{
x25conf.xc_ltrace = arg;
}
setyear (arg)
{
x25conf.xc_type = arg;
switch (arg) {
case X25_1976:
return;
case X25_1980:
case X25_1984:
x25conf.xc_pwsize = 7;
x25conf.xc_psize = 12; /* 4096 bytes */
}
}
setpwsize (arg)
char *arg;
{
register int ws;
if ((ws = atoi (arg)) <= 0 || ws > 7)
abort ("invalid packet level window size");
x25conf.xc_pwsize = ws;
}
setpacketsize (arg)
char *arg;
{
register int psize, logpsize = 0;
if ((psize = atoi (arg)) < 64 || psize > 4096)
abort ("invalid packet size");
while (psize > 1) {
psize >>= 1;
logpsize++;
}
x25conf.xc_psize = logpsize;
}
setmaxlcn (arg)
char *arg;
{
register int lcn;
if ((lcn = atoi (arg)) <= 0)
abort ("invalid maximum lcn");
x25conf.xc_maxlcn = lcn;
}
setptrace (arg)
{
x25conf.xc_ptrace = arg;
}
/*
* Print a value a la the %b format of the kernel's printf
*/
printb(s, v, bits)
char *s;
register char *bits;
register unsigned short v;
{
register int i, any = 0;
register char c;
if (bits && *bits == 8)
printf("%s=%o", s, v);
else
printf("%s=%x", s, v);
bits++;
if (bits) {
putchar('<');
while (i = *bits++) {
if (v & (1 << (i-1))) {
if (any)
putchar(',');
any = 1;
for (; (c = *bits) > 32; bits++)
putchar(c);
} else
for (; *bits > 32; bits++)
;
}
putchar('>');
putchar('\n');
}
}