/* * Configure X.25 interface * * Copyright (c) 1986 University of British Columbia * * Frank Pronk * February 1986 */ #include #include #include #include #include #include #include #define IFFBITS \ "\020\1UP\2BROADCAST\3DEBUG\4ROUTE\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP" int setifflags (), setdefault (), setnet (), setntn (); int setlproto (), sethdlc (), setlwsize (), setltrace (); 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, "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 x25config x25conf = { AF_CCITT }; 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 (ifr.ifr_name, ifname); if (ioctl (s, SIOCGIFADDR, (char *)&ifr) == 0) bcopy ((char *)&ifr.ifr_addr, (char *)&x25conf, sizeof (x25conf)); 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 (ifr.ifr_name, ifname); bcopy ((char *)&x25conf, (char *)&ifr.ifr_addr, sizeof (x25conf)); if (ioctl (s, SIOCSIFADDR, (char *)&ifr) < 0) syserr ("ioctl (SIOCSIFADDR)"); 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[sizeof (x25conf.xc_ntn) * 2 + 1]; 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"); from_bcd (x25conf.xc_ntn, addr, x25conf.xc_ntnlen); printf ("\taddress: %04d %s\n", x25conf.xc_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_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_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); } else for (l = 0, p = arg; *p; p++) { l++; if (*p < '0' || *p > '9') abort ("invalid character in ntn address"); } if (l > sizeof (x25conf.xc_ntn) * 2 || l == 0) abort ("invalid ntn address"); x25conf.xc_ntnlen = l; to_bcd (arg, x25conf.xc_ntn); } 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; } 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'); } }