|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T U
Length: 26550 (0x67b6) Types: TextFile Notes: Uncompressed file
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦f3431f052⟧ »EurOpenD3/network/uucp-x25.shar.Z« └─⟦this⟧
#!/bin/sh echo 'Start of UUCP over native X.25, part 01 of 01:' echo 'x - README' sed 's/^X//' > README << '/' XUUCP on top of native X.25 1.2 89/10/23 X========================== X X XThis is a collection of programs that I hacked together to make uucp run Xon top of a packet level X.25 interface. The idea was to make it as Xindependent as possible from the actual interface. It is not a finished Xdistribution! I am not planning to make one. X X XLimitations X XThe whole stuff does incoming calls only at this point. XFor outgoing calls one needs to either hack uucico or do Xdirty tricks. I am considering the latter by making a Xspecial version of uucpd that can recognise being Xcalled from a local client and then offer to call Xout via X.25. This could be done buy dialogue from L.sys Xso no changes in uucico are needed. X XIt's tested only with Sunlink X.25 but i expect to get Xthe "opportunity" to make it run on HP-UX soon. X X XYou need X X1) a working X.25 implementation with a documented X packet level interface X X2) a version of uucico that can work with stdin and stdout X not being terminals (most of them nowadays can) X X3) some will to experiment, this is not a well thought out X distribution but rather sharing of code built for a X specific use X X X X"Design" X XThere are two programs: uucp-x25d and uucp-x25. Xuucp-x25d is a daemon like inetd which listens for incoming Xconnections and forks off uucp-x25 for each one. XThe idea was to have all knowledge of the particular X.25 Ximplementations reside in uucp-x25d. This did not work out. XAnother idea was to make uucp-x25d into an x25d much like inetd Xwhich is table driven and forks off different servers according Xto subaddess and userdata. Maybe I'll do this sometime. X Xuucp-x25 will remain copying data between uucico and the x25 socket. XThis needs to be done because uucico can read/write arbitrary chunks of Xdata which most x25 interfaces don't like. I have reduced the link Xbetween uucico and uucp-x25 to a pipe which is less overhead Xthan a pty. X XThe copying is done with nonblocking io and polling. XIt could be done with select() but too many broken implementations Xmake this look unwise. Performance isn't suffering too badly, Xsee below. X X XPerformance X XPretty good. Takes about .3% of a SUN4/260 for a 10kbit/s Xlink flat out. With SUnlink X.25 it's certainly less of Xa CPU drain than a hardware pad via a serial connection. X X XBugs X Xuucp-x25 still sometimes dies without cleaning up Xafter it and killing uucico properly. This happens Xwhen the X.25 link is broken in the middle of a Xsession. It;s hard to reproduce and diagnose. X X XInstallation X X o configure in uucp-x25.h X X o make X X o make install X (make sure you have DESTDIR consistent with what X you configured in uucp-x25.h) X X o create files /dev/<UUCPTTY>0 ... /dev/<UUCPTTY>n X depending on the max. number of parallel sessions X you estimate X X X X X o start uucp-x25d with the subaddress you want to listen X on as argument X X o connect from a pad and try to login X verify that you can't login on a normal user account X X o try a uucico session X X X XSend flames and suggestions to dfk@cwi.nl. If you change the code Xplease mark the changed sections as yours and send me the changes. X X XDaniel Karrenberg Future Net: <dfk@cwi.nl> XCWI, Amsterdam Oldie Net: mcvax!dfk XThe Netherlands Because It's There Net: DFK@MCVAX / echo 'x - Makefile' sed 's/^X//' > Makefile << '/' X# 1.2 89/12/19 X XCFLAGS = -O XDESTDIR = /usr/lib/uucp X Xall: uucp-x25 uucp-x25d X Xuucp-x25: uucp-x25.c uucp-x25.h X cc $(CFLAGS) -o uucp-x25 uucp-x25.c X Xuucp-x25d: uucp-x25d.c uucp-x25.h X cc $(CFLAGS) -o uucp-x25d uucp-x25d.c X Xclean: X rm -f *.o tmp uucp-x25 uucp-x25d distrib core X Xinstall: uucp-x25 uucp-x25d X cp uucp-x25 uucp-x25d $(DESTDIR) X chown root $(DESTDIR)/uucp-x25 $(DESTDIR)/uucp-x25d X chgrp uucp $(DESTDIR)/uucp-x25 $(DESTDIR)/uucp-x25d X chmod 510 $(DESTDIR)/uucp-x25 $(DESTDIR)/uucp-x25d X Xdistrib: README Makefile uucp-x25.h uucp-x25.c uucp-x25d.c X packmail -odistrib -t"UUCP over native X.25" README Makefile *.h *.c / echo 'x - uucp-x25.h' sed 's/^X//' > uucp-x25.h << '/' X /* 1.2 89/12/19 uucp-x25.h (CWI) */ X X#define RECSIZE 1024 /* the size of the transfer buffers X * X * This parameter controls a timeout, X * overhead tradeoff. Make its smaller and X * CPU usage will increase. Make it bigger and X * low thruput links are liable to time out X * unnecessarily. It also has to be a multiple X * of the X25 windowsizes used on your connection!!! X */ X X#define SUNLINK /* define this if you use Sunlink X.25 */ X X /* the welcome message, %s will be the domain name */ X#define BANNER "\r\n%s - authorised uucp access only!" X X /* will allow login on users with CICO or UUTCP X * shells in /etc/paswd only! X */ X#define UUCICO "/usr/lib/uucp/uucico" X#define UUTCP "/usr/lib/uucp/uutcp" X X#define UUCPTTY "xuucp" /* prefix of the ttytab entries to be used */ X X#define NOUTMP /* define this if you don't want utmp entries */ X X/* #define UNAMEUP /* uppercase the usernames in utmp and log files X * X * This is a gross hack to prevent finger from X * bailing out if it can't stat the login tty. X * The best idea is to make normal files by touching X * /dev/<UUCPTTY>. X */ X X /* the server program */ X#define UUCPX25 "/usr/lib/uucp/uucp-x25" X X /* X.3 parameters that will be set in X * the caller's PAD. X */ Xchar x3parms[] = { /* this array is the actual set parameter message */ X 02, /* set parameters! */ X 1, 0, X 2, 0, X 3, 2, X 4, 20, X 5, 1, X 6, 0, X 9, 0, X 10, 0, X 12, 1, X 13, 0, X 14, 0, X 15, 0 X}; / echo 'x - uucp-x25.c' sed 's/^X//' > uucp-x25.c << '/' X /* uucp-x25.c 1.1 89/09/13 (CWI) */ X X/* X * BSD server for uucico via X.25 (preferably f-protocol) X * geared towards SUNLINK but generally adaptable X * X * For tailoring see uucp-x25.h. X * X * blame dfk@cwi.nl but if *you* cchange it, please mark it prominently X * and send changes back! X * X * State: Fairly well tested. New DEBUG macros not tested. X */ X X#include "uucp-x25.h" X X#include <sys/types.h> X#include <netdb.h> X#include <signal.h> X#include <strings.h> X#include <errno.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <sys/wait.h> X#include <sys/ioctl.h> X#include <pwd.h> X#include <lastlog.h> X#ifdef SUNLINK X#include <sys/mbuf.h> X#include <sundev/syncstat.h> X#include <netx25/x25_ioctl.h> X#include <netx25/x25_ctl.h> X#include <netx25/x25_pk.h> X#endif X#include <utmp.h> X#include <ttyent.h> X#include <fcntl.h> X#include <ctype.h> X#include <stdio.h> X X#define SCPYN(a, b) strncpy(a, b, sizeof (a)) X#define EXIT(msg) {perror(msg); dologout();} X Xchar lastlog[] = "/usr/adm/lastlog"; Xchar wtmpfile[] = "/usr/adm/wtmp"; Xchar utmpfile[] = "/etc/utmp"; X Xchar Username[64]; /* uucico environment stuff */ Xchar *nenv[] = { X Username, X NULL, X}; Xextern char **environ; X Xchar domainname[256]; /* domain name of this host */ Xchar calling_dte[32]; /* calling DTE X.121 address */ Xchar called_dte[32]; /* called DTE X.121 address */ X Xchar cicobuf[RECSIZE]; /* buffer uucico -> x25 */ X X#ifdef SUNLINK Xchar x25buf[RECSIZE+1]; /* buffer x25 -> uucico */ X#else Xchar x25buf[RECSIZE]; X#endif X Xint to[2], from[2]; /* pipes */ X Xint pid = 0; /* pid of cico process */ Xint slot = 0; /* utmp slot number of "tty" */ Xchar line[32]; /* "tty" name */ Xstruct utmp utmp; /* utmp entry */ X X X#undef DEBUG X#ifdef DEBUG Xchar sbuf[RECSIZE+256]; Xint debug = 1; Xint debugf; Xchar debugfile[100] = ""; X#define DEBUGPR(msg, arg) {if(debug){ sprintf(sbuf, msg, (arg)); \ X write(debugf, sbuf, strlen(sbuf));}} X#define DEBUGCMD(cmd) {if(debug){cmd}} X#else X#define DEBUGPR(msg, arg) ; X#define DEBUGCMD(cmd) ; X#endif DEBUG X X X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X register int i; X extern int errno; X extern void dologout(); X X X /* paranoia strikes again .... */ X signal(SIGHUP, SIG_IGN); X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGIO, SIG_IGN); X signal(SIGURG, SIG_IGN); X X /* clean up our process */ X environ = nenv; X errno=0; X for (i=3; i<32; i++) X close(i); X X if (argc !=3) { X fprintf(stderr, "usage: uucp-x25 calling_dte called_dte"); X exit(1); X } X X getdomainname(domainname, sizeof(domainname)); X SCPYN(calling_dte, argv[1]); X SCPYN(called_dte, argv[2]); X slot = utmpslot(); X X DEBUGCMD(strcpy(debugfile, "/spare/x25log/");) X DEBUGCMD(strcat(debugfile, line);) X DEBUGCMD(debugf = creat(debugfile, 0666);) X X if (setpgrp(0, getpid()) < 0) X { X perror("setpgrp()"); X exit(1); X } X X if (pipe(from)<0 || pipe(to)<0) { X perror("uucpc-x25: pipes"); X exit(1); X } X X if ((pid=fork()) > 0) { /* copy process */ X signal(SIGCHLD, dologout); X docopy(0, 1, to[1], from[0]); X perror("docopy returned"); X exit(1); X } X else if (pid == 0) { /* uucp process */ X if (dup2(to[0], 0)<0 || dup2(from[1], 1)<0) { X perror("uucpc-x25: dup2s"); X exit(1); X } X close (to[1]); close(from[0]); X doit(); X exit(1); X } X else { X perror("uucpc-x25: fork"); X exit(1); X } X} X X X Xdoit() /* do login dialogue and exec uucico */ X{ X char prgn[256]; X char user[64], passwd[64]; X char *xpasswd, *crypt(); X struct passwd *pw, *getpwnam(); X register char failed = 0; X X sleep(1); X alarm(60); X fflush(stdout); X printf(BANNER, domainname); X X /* login dialogue loop */ X *user = 0; X while (*user == 0) X { X /* X * Ask for username and note if user doesn't exist X * or has the wrong shell. Don't tell it failed now X * because it gives away too much. X */ X failed = 0; X printf("\r\nlogin: "); X fflush(stdout); X if (readline(user, sizeof user, 1) < 0) X return; X if (*user == 0) X continue; X user[8] = '\0'; X pw = getpwnam(user); X if (pw == NULL) X failed++; X else if (strcmp(pw->pw_shell, UUCICO) == 0) X SCPYN(prgn, UUCICO); X#ifdef UUTCP X else if (strcmp(pw->pw_shell, UUTCP) == 0) X SCPYN(prgn, UUTCP); X#endif X else X failed++; X X /* X * Ask for a password in all cases except if we have X * a valid user without password. X */ X if (failed || pw->pw_passwd && *pw->pw_passwd != '\0') { X printf("\rPassword: "); fflush(stdout); X if (readline(passwd, sizeof passwd, 0) < 0) { X return; X } X xpasswd = crypt(passwd, failed?"*":pw->pw_passwd); X if (failed || strcmp(xpasswd, pw->pw_passwd)) { X fprintf(stderr, "\r\nLogin incorrect.\r\n"); X *user = 0; X } X } X } /* login dialogue loop */ X X /* valid user: log in logfiles, create environment, exec uucico */ X alarm(0); X sprintf(Username, "USER=%s", user); X dologin(pw); X setgid(pw->pw_gid); X initgroups(pw->pw_name, pw->pw_gid); X chdir(pw->pw_dir); X setuid(pw->pw_uid); X execl(prgn, rindex(prgn, '/')?rindex(prgn, '/')+1:prgn, (char *)0); X perror("uucico server: execl"); X} X X Xreadline(p, n, echo) /* get a line from stdin for login dialogue */ Xregister char *p; Xregister int n; Xregister int echo; X{ X char c; X register int nc = n; X X while (nc-- > 0) { X if (read(0, &c, 1) <= 0) X return(-1); X c &= 0177; X if (c == 004) X return(-1); X if (c == '\n' || c == '\r') { X *p = '\0'; X write(1, "\r\n", 2); X return(0); X } X if (echo) X write(1, &c, 1); X *p++ = c; X } X return(-1); X} X X X Xdologin(pw) /* record login in various files */ Xstruct passwd *pw; X{ X int wtmp, f; X X SCPYN(utmp.ut_line, line); X SCPYN(utmp.ut_name, pw->pw_name); X X#ifdef UNAMEUP X for (p=utmp.ut_name; *p && p-utmp.ut_name < sizeof(utmp); p++) { X if (islower(*p)) X *p = toupper(*p); X } X#endif UNAMEUP X X SCPYN(utmp.ut_host, calling_dte); X time(&utmp.ut_time); X X#ifndef NOUTMP X /* log in utmp file for who and friends */ X if (slot <=999 && (f=open(utmpfile, O_WRONLY)) >= 0) { X lseek(f, (long)(slot*sizeof(utmp)), 0); X (void) write(f, utmp, sizeof(utmp)); X (void) close(f); X } X#endif NOUTMP X X /* log in wtmp file the standard session log */ X wtmp = open(wtmpfile, O_WRONLY|O_APPEND); X if (wtmp >= 0) { X (void) write(wtmp, (char *)&utmp, sizeof (utmp)); X (void) close(wtmp); X } X X /* log in lastlog for finger and friends */ X if ((f = open(lastlog, 2)) >= 0) { X struct lastlog ll; X X time(&ll.ll_time); X lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0); X X if (strlen(called_dte) > sizeof(ll.ll_line)) X SCPYN(ll.ll_line, called_dte+strlen(called_dte)-2); X else X SCPYN(ll.ll_line, called_dte); X SCPYN(ll.ll_host, calling_dte); X (void) write(f, (char *) &ll, sizeof ll); X (void) close(f); X } X} X Xvoid Xdologout() /* clean up, log session end and delete from utmp */ X{ X int i; X int fd; X X DEBUGPR("dologout called, pid=%d\n", pid); X /* give the whole process group a hangup */ X if (pid) X { X signal(SIGCHLD, SIG_IGN); X signal(SIGHUP, SIG_IGN); X kill(0, SIGHUP); X wait(0); X } X DEBUGPR("dologout after wait\n", 0); X X /* close all fds and hence also the X25 circuit */ X for (i=0; i<32; i++) X close(i); X X /* X * This runs a small chance of writing a logout record even if X * we aren't logged in yet. There is no way to know since X * login is done in the other process. But it's a second degree X * error. Better write one too many. X */ X fd = open(wtmpfile, O_WRONLY|O_APPEND); X if (fd >= 0) { X DEBUGPR("dologout wtmp line=%s\n", line); X SCPYN(utmp.ut_line, line); X SCPYN(utmp.ut_name, ""); X SCPYN(utmp.ut_host, ""); X (void) time(&utmp.ut_time); X (void) write(fd, (char *)&utmp, sizeof (utmp)); X (void) close(fd); X } X X#ifndef NOUTMP X if (slot<=999 && (fd=open(utmpfile, O_WRONLY)) >= 0) { X lseek(fd, (long)(slot*sizeof(utmp)), 0); X (void) write(fd, utmp, sizeof(utmp)); X (void) close(fd); X } X#endif NOUTMP X DEBUGPR("dologout exit(0)\n", 0); X exit(0); X} X Xdocopy(x25in, x25out, to, from) Xint x25in, x25out, to, from; X{ X register int idlecnt=0; /* idle counter */ X register int tox25=0; /* bytes to be written to x25 */ X register int tocico=0; /* bytes to be written to uucico */ X int fromcico = 0; /* bytes readable from uucico */ X int fromx25 = 0; /* bytes readable from x25 */ X int tmp; X X X X /* make x25 input and all output nonblocking */ X tmp=1; X if (ioctl(x25in, FIONBIO, &tmp)<0) X EXIT("docopy x25in FIONBIO"); X if (ioctl(x25out, FIONBIO, &tmp)<0) X EXIT("docopy x25out FIONBIO"); X if (ioctl(to, FIONBIO, &tmp)<0) X EXIT("docopy to FIONBIO"); X#ifdef SUNLINK X tmp=1; X if (ioctl(x25in, X25_HEADER, &tmp)<0) X EXIT("docopy x25in X25_HEADER"); X#endif X X /* server loop */ X for (;;) X { X /* input pending from x25 ? */ X if (fromx25==0 && ioctl(x25in, FIONREAD, &fromx25)<0) X EXIT("docopy x25in FIONREAD"); X DEBUGPR("fromx25 = %d\n", fromx25); X X /* input pending from uucico ? */ X if (fromcico==0 && ioctl(from, FIONREAD, &fromcico)<0) X EXIT("docopy from FIONREAD"); X DEBUGPR("fromcico = %d\n", fromcico); X X /* X * If there is no input pending or output is blocked X * to one side we presume ourselves idle and wait X * a little before we poll again. X */ X if (fromx25==0 && fromcico==0 || tox25 || tocico) X { X sleep(1); X if (idlecnt++ > 600) X dologout; X X /* check now and then whether x25 has gone away */ X if (idlecnt%15 == 0 && !tocico) { X DEBUGPR("check x25, count=%d\n", idlecnt); X tmp=read(x25in, x25buf, sizeof(x25buf)); X DEBUGPR("check x25, read=%d\n", tmp); X if (tmp<0) { X DEBUGPR("check x25, errno=%d\n", errno); X if (errno!=EWOULDBLOCK) { X /* X.25 connection broken */ X dologout(); X } X } X else if (tmp>0) { X /* read something! */ X tocico=tmp; X fromx25=0; X } X else { X /* "can't happen" */ X dologout(); X } X } X } X else { X idlecnt=0; X } X X if (fromcico) { /* input pending from uucico */ X /* if output is not blocked, we read */ X if (!tox25) { X if (fromcico > sizeof(cicobuf)) X fromcico = sizeof(cicobuf); X if ((tox25=read(from, cicobuf, fromcico))<=0) X EXIT("docopy from read"); X DEBUGPR("from read=%d\n", tox25); X fromcico=0; X } X } X if (tox25) { /* data to be written to x25 */ X /* we write to x25 */ X if ((tmp=write(x25out, cicobuf, tox25)) < 0) { X if (errno != EWOULDBLOCK) X EXIT("docopy x25out write error"); X /* output blocked, we try again later */ X DEBUGPR("x25 write blocks\n", (char*)0); X } X else if (tmp != tox25) { X EXIT("docopy x25out write short"); X } else { X DEBUGPR("x25 write=%d\n", tmp); X tox25=0; X } X } X X if (fromx25) { /* input ready from x25 */ X if (!tocico) { X if (fromx25 > sizeof(x25buf)) X fromx25 = sizeof(x25buf); X if ((tocico=read(x25in, x25buf, fromx25))<=0) X EXIT("docopy x25in read"); X DEBUGPR("x25 read=%d\n", tocico); X#ifdef SUNLINK X if (*x25buf & 1<<Q_BIT) X tocico = qualified(x25buf+1, tocico-1, x25out); X#endif X fromx25=0; X } X } X if (tocico) { /* output to uucico */ X#ifdef SUNLINK X if ((tmp=write(to, x25buf+1, tocico-1)) < 0) { X#else X if ((tmp=write(to, x25buf, tocico)) < 0) { X#endif X if (errno != EWOULDBLOCK) X EXIT("docopy to write"); X DEBUGPR("to write blocks\n", (char*)0); X } X#ifdef SUNLINK X else if (tmp != tocico-1) { X#else X else if (tmp != tocico) { X#endif SUNLINK X EXIT("docopy to write short"); X } X else { X DEBUGPR("to write=%d\n", tmp); X tocico=0; X } X } X } X} X X#ifdef SUNLINK X X /* X * This handles packets with the Q bit on. X * As a "host" we shouldn't get any of those X * but there are a lot of reverse PADs out there.... X * X * Since we (EUnet) started the reverse PAD business X * we now have to suffer from it! X * X * This is not a complete implementation of a PAD X * since it *is no* PAD. Especially the parameter X * indication responses are bogus to say the least. X */ X Xint Xqualified(buf, count, x25out) Xchar *buf; int count; int x25out; X{ X int tmp; X X if (count<=0) X return(0); X X switch (*buf) X { X case 1: X /* invitation to clear */ X dologout(); X /* doesn't return */ X X case 2: X /* set PAD parameters */ X case 3: X /* indication of break */ X case 5: X /* PAD error */ X return(0); X X case 4: X /* read PAD parameters */ X case 6: X /* set and read PAD parameters */ X *buf = 0; /* parameter indication message code */ X tmp = (1 << Q_BIT); X if (ioctl(x25out, X25_SEND_TYPE, &tmp)<0) X EXIT("ioctl(X25_SEND_TYPE)"); X write(x25out, buf, count); X tmp = 0; X if (ioctl(x25out, X25_SEND_TYPE, &tmp)<0) X EXIT("ioctl(X25_SEND_TYPE)"); X return(0); X X default: X /* send an "unrecognized message" error */ X buf[2] = buf[0]; X buf[1] = 1; X buf[0] = 5; X tmp = (1 << Q_BIT); X if (ioctl(x25out, X25_SEND_TYPE, &tmp)<0) X EXIT("ioctl(X25_SEND_TYPE)"); X write(x25out, buf, 3); X tmp = 0; X if (ioctl(x25out, X25_SEND_TYPE, &tmp)<0) X EXIT("ioctl(X25_SEND_TYPE)"); X return(0); X } X} X#endif SUNLINK X Xint Xutmpslot() /* reserve an utmp slot, and return slot number */ X /* hack, but line must be unique and no tty line */ X{ X register struct ttyent *t; X register int utmpfd; X register int n = 0; X struct utmp ut; X long now; X X#ifndef NOUTMP X if ((utmpfd=open(utmpfile, O_RDWR)) < 0) X goto pseudo; X X while ((t=getttyent()) != (struct ttyent*) 0) X { X n++; X if (strncmp(t->ty_name, UUCPTTY, strlen(UUCPTTY)) == 0) { X lseek(utmpfd, (long)(n*sizeof(utmp)), 0); X if (read(utmpfd, (char*)&ut, sizeof(utmp)) X ==sizeof(utmp)) X { X if (*ut.ut_name==0) X goto found; X if (strncmp(ut.ut_name, "X25LOGIN", 8) == 0) { X time(&now); X if (now-ut.ut_time > 120) X goto found; X } X } X else /* new entry ! */ X goto found; X } X } X#endif NOUTMP X Xpseudo: X /* generate a pseudo unique slot number: 999<slot<=9999 */ X n = getpid(); X while(n>9999) X n -= 9999; X if (n<=999) X n+=999; X sprintf(line, "uucp%.4d", n); X#ifndef NOUTMP X endttyent(); X close(utmpfd); X#endif NOUTMP X return (n); X X#ifndef NOUTMP Xfound: X SCPYN(line, t->ty_name); X lseek(utmpfd, (long)(n*sizeof(utmp)), 0); X SCPYN(ut.ut_name, "X25LOGIN"); X SCPYN(ut.ut_line, line); X SCPYN(ut.ut_host, calling_dte); X (void) time(&ut.ut_time); X (void) write(utmpfd, (char*) &ut, sizeof(utmp)); X endttyent(); X close(utmpfd); X return (n); X#endif NOUTMP X} / echo 'x - uucp-x25d.c' sed 's/^X//' > uucp-x25d.c << '/' X /* uucp-x25d.c 1.3 89/11/14 (CWI) */ X X X /* uucp-x25 daemon */ X X#include "uucp-x25.h" X#include <stdio.h> X#include <fcntl.h> X#include <sys/types.h> X#include <sys/ioctl.h> X#include <sys/wait.h> X#include <sys/param.h> X#include <sys/systm.h> X#include <sys/mbuf.h> X#include <sys/socket.h> X#include <sys/protosw.h> X#include <sys/domain.h> X#include <sys/socketvar.h> X#include <sys/errno.h> X#include <sys/signal.h> X#include <net/if.h> X#include <sundev/syncstat.h> X#include <netx25/x25_pk.h> X#include <netx25/x25_ctl.h> X#include <netx25/x25_ioctl.h> X#include <syslog.h> X X Xextern int errno; X Xint ls; /* listen socket */ Xint s; /* socket returned by accept */ X Xchar rmtaddr[MAXHOSTADR + 1] = ""; X /* remote DTE address, unpacked form */ Xchar localaddr[MAXHOSTADR + 1] = ""; X /* local DTE address, unpacked form */ XCONN_DB bind_addr; X /* local address */ XCONN_DB remote; /* remote address and user data */ Xint remote_len = sizeof(CONN_DB); X XFACILITY_DB facilities; XCONN_ADR loc; X X Xextern int cleanchild(); X Xint send_type; X Xmain(argc, argv) X int argc; X char *argv[]; X{ X int pgrp = getpid(); /* process id */ X int temp; X register int pid; X X if (fork() > 0) X exit(0); X for (temp=3; temp<10; temp++) X close(temp); X setpgrp(0, getpid); X X openlog("uucp-x25d", LOG_PID, LOG_DAEMON); X X /* paranoia strikes again .... */ X signal(SIGHUP, SIG_IGN); X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X signal(SIGIO, SIG_IGN); X signal(SIGURG, SIG_IGN); X signal (SIGCHLD, cleanchild); X X bzero(&bind_addr, sizeof(bind_addr)); X X /* Create listen socket X */ X if ((ls = socket(AF_X25, SOCK_STREAM, 0)) < 0) { X perror("socket"); X exit(1); X } X X /* Set process group id for socket, and signal handler. Socket X * returned by accept() will inherit process group id. X */ X if (ioctl(ls, SIOCSPGRP, &pgrp)) { X perror("ioctl(SIOCSPGRP)"); X exit(1); X } X X if ((bind_addr.hostlen=pack(argv[1], bind_addr.host)) < 0) { X printf("Error: invalid subaddress\n"); X exit(1); X } X bind_addr.hostlen |= ANY_LINK; X X /* Bind socket to bind_addr X */ X if (bind(ls, &bind_addr, sizeof(bind_addr)) < 0) { X perror("bind"); X exit(1); X } X X /* Mark socket as listening. X */ X if (listen(ls, 5) < 0) { X perror("listen"); X exit(1); X } X X for(;;) /* daemon loop */ X { X /* Wait to accept X */ X for (;;) { X if ((s = accept(ls, &remote, &remote_len)) < 0) { X if (errno == EINTR) { X /* X * Got signal. X */ X continue; X } X perror("accept"); X exit(1); X } X break; X } X X /* Get calling and called addresses. X */ X X if (ioctl(s, X25_RD_LOCAL_ADR, &loc)) { X perror("ioctl(X25_RD_LOCAL_ADR)"); X exit(1); X } X X /* get dte-addresses */ X (void) unpack(loc.host, loc.hostlen, localaddr); X (void) unpack(remote.host, remote.hostlen, rmtaddr); X X /* set record size */ X if (ioctl(s, X25_RD_FACILITY, &facilities)) { X perror("ioctl(X25_RD_FACILITY)"); X exit(1); X } X if (facilities.recvpktsize > RECSIZE) { X perror("RECSIZE to small"); X exit(1); X } X temp = RECSIZE/facilities.recvpktsize; X if (ioctl(s, X25_RECORD_SIZE, &temp)) { X perror("ioctl(X25_RECORD_SIZE)"); X exit(1); X } X X /* set remote x3 parameters */ X sleep(1); X send_type = (1 << Q_BIT); X if (ioctl(s, X25_SEND_TYPE, &send_type)<0) { X perror("ioctl(X25_SEND_TYPE)"); X exit(1); X } X write(s, x3parms, sizeof(x3parms)); X send_type = 0; X if (ioctl(s, X25_SEND_TYPE, &send_type)<0) { X perror("ioctl(X25_SEND_TYPE)"); X exit(1); X } X X if ((pid=fork()) == 0) { X X close(0); close(1); close (2); X dup(s); dup(s); dup(s); X#ifdef LOGINFO X syslog(LOG_INFO, "call from %s", rmtaddr); X#endif LOGINFO X execl(UUCPX25 ,"uucp-x25",rmtaddr,localaddr,(char*)0); X perror("uucpd-x25: exec "); X exit(1); X } X else if (pid > 0) { X close(s); X } X else { X perror("uucpd-x25: fork "); X exit(1); X } X } X} X X X/* X * pack() takes as input a null-terminated ASCII string str X * representing an X.121 address, and converts it to packed BCD form. X * bcd points to the array containing the packed BCD output. If the X * address has invalid characters, -1 is returned. Otherwise, the X * length of the address (in BCD digits) is returned. X */ Xint Xpack(str, bcd) X char *str; X u_char *bcd; X{ X int i, j; X u_char c; X X i = j = 0; X while (str[i]) { X if (i >= 15 || str[i] < '0' || str[i] > '9') X return(-1); X c = str[i] - '0'; X if (i & 1) X bcd[j++] |= c; X else X bcd[j] = c << 4; X i++; X } X return(i); X} X X X/* X * unpack() takes as input a packed BCD string (bcd) and X * its length in BCD digits (len), and converts it to a null-terminated X * ASCII string. If the address is invalid, -1 is returned, otherwise X * its length in BCD digits is returned. X */ Xint Xunpack(bcd, len, str) X u_char *bcd; X int len; X char *str; X{ X int i, j; X u_char c; X X if (len > 15) X return(-1); X i = j = 0; X while (i < len) { X if (i & 1) X c = bcd[j++] & 0x0f; X else X c = bcd[j] >> 4; X if (c > 9) X return(-1); X str[i++] = '0' + c; X } X str[i] = '\0'; X return(i); X} X Xcleanchild() X{ X signal(SIGCHLD, SIG_IGN); X X while (wait3(NULL, WNOHANG, NULL)>0) X ; X X signal(SIGCHLD, cleanchild); X} X Xperror(msg) Xchar *msg; X{ X syslog(LOG_CRIT, msg); X} / echo 'Part 01 of UUCP over native X.25 complete.' exit