From 02b2392d025937ea5a1108b07b0dcd2a52cd957e Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 19 Sep 1999 18:15:50 +0000 Subject: [PATCH] Compiles and getting there for full use. --- ipif/Makefile | 2 +- ipif/service.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 246 insertions(+), 5 deletions(-) diff --git a/ipif/Makefile b/ipif/Makefile index fd69b4a..2bcea8c 100644 --- a/ipif/Makefile +++ b/ipif/Makefile @@ -1,6 +1,6 @@ # CFLAGS= -Wall -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith \ - -Wwrite-strings -g + -Wwrite-strings -g -D_GNU_SOURCE all: service diff --git a/ipif/service.c b/ipif/service.c index b770623..33ba2df 100644 --- a/ipif/service.c +++ b/ipif/service.c @@ -40,6 +40,12 @@ #include #include #include +#include +#include + +#include +#include +#include #define NARGS 4 #define MAXEXROUTES 5 @@ -47,6 +53,7 @@ static const unsigned long gidmaxval= (unsigned long)((gid_t)-2); static const char *const protos_ok[]= { "slip", "cslip", "adaptive", 0 }; +static const int signals[]= { SIGHUP, SIGINT, SIGTERM, 0 }; static const char *configstr, *proto; static unsigned long localaddr, peeraddr, mtu; @@ -67,6 +74,35 @@ static struct pplace { int lineno; } *cpplace; + +static int slpipe[2], ptmaster; +static const char *ifname; +static const char *ptyname; + +#define NPIDS 4 + +static union { + struct { pid_t sl, cout, cin, task; } byname; + pid_t bynumber[NPIDS]; +} pids; +sigset_t emptyset, fullset; + + +static void terminate(int estatus) { + int i, status; + pid_t pid; + + for (i=0; ifilename, cpp->lineno); } } - exit(16); + terminate(16); } static char *ip2txt(unsigned long addr, char *buf) { @@ -438,11 +474,216 @@ static void dumpdebug(void) { exit(0); } +static void setsignals(void (*handler)(int), struct sigaction *sa, int chldflags) { + const int *signalp; + int r, sig; + + sa->sa_handler= handler; + sa->sa_flags= 0; + for (signalp=signals; (sig=*signalp); signalp++) { + r= sigaction(sig, sa, 0); if (r) sysfatal("uncatch signal"); + } + sa->sa_flags= chldflags; + r= sigaction(SIGCHLD, sa, 0); if (r) sysfatal("uncatch children"); +} + +static void setsigmask(const sigset_t *ss) { + int r; + + r= sigprocmask(SIG_SETMASK, ss, 0); + if (r) sysfatal("[un]block signals"); +} + +static void infork(void) { + struct sigaction sa; + + memset(&pids,0,sizeof(pids)); + sigemptyset(&sa.sa_mask); + setsignals(SIG_DFL,&sa,0); + setsigmask(&emptyset); +} + +static pid_t makesubproc(void (*entry)(void)) { + pid_t pid; + + pid= fork(); if (pid == (pid_t)-1) sysfatal("fork for subprocess"); + if (pid) return pid; + + infork(); + entry(); + abort(); +} + +static int task(void) { + pid_t pid; + + pid= fork(); + if (pids.byname.task == (pid_t)-1) sysfatal("fork for task"); + if (!pids.byname.task) { infork(); return 1; } + + pids.byname.task= pid; + while (pids.byname.task) sigsuspend(&emptyset); + return 0; +} + +static void sl_entry(void) { + if (dup2(slpipe[1],1) != 1) sysfatal("dup2 stdout in slattach child"); + execlp("slattach", "slattach", "-v", "-L", "-p",proto, ptyname, (char*)0); + sysfatal("cannot exec slattach"); +} + +static void cin_entry(void) { + if (dup2(ptmaster,1) != 1) sysfatal("dup2 stdout in cat input child"); + execlp("cat", "cat", (char*)0); + sysfatal("cannot exec cat input"); +} + +static void cout_entry(void) { + if (dup2(ptmaster,0) != 1) sysfatal("dup2 stdin in cat output child"); + execlp("cat", "cat", (char*)0); + sysfatal("cannot exec cat output"); +} + +static void sighandler(int signum) { + pid_t pid; + int estatus, status; + const char *taskfail; + + estatus= 4; + + if (signum == SIGCHLD) { + for (;;) { + pid= waitpid(-1,&status,WNOHANG); + if (!pid || pid == (pid_t)-1) return; + + if (pid == pids.byname.task) { + pids.byname.task= 0; + if (!status) return; + taskfail= "task"; + } else if (pid == pids.byname.cin) { + pids.byname.cin= 0; + if (status) { + taskfail= "input cat"; + } else { + taskfail= 0; + estatus= 0; + } + } else if (pid == pids.byname.cout) { + pids.byname.cout= 0; + taskfail= "output cat"; + } else if (pid == pids.byname.sl) { + pids.byname.sl= 0; + taskfail= "slattach"; + } else { + continue; + } + } + if (taskfail) { + fprintf(stderr, + "userv-ipif service: %s unexpected terminated with status code %d\n", + taskfail, status); + } + } else { + fprintf(stderr, + "userv-ipif service: received signal %d, terminating\n", + signum); + } + + terminate(estatus); +} + +static void startup(void) { + int r; + struct sigaction sa; + + sigfillset(&fullset); + sigemptyset(&emptyset); + + ptmaster= getpt(); if (ptmaster==-1) sysfatal("allocate pty master"); + r= grantpt(ptmaster); if (r) sysfatal("grab/grant pty slave"); + ptyname= ptsname(ptmaster); if (!ptyname) sysfatal("get pty slave name"); + r= chmod(ptyname,0600); if (r) sysfatal("chmod pty slave"); + + sigfillset(&sa.sa_mask); + setsignals(sighandler,&sa,SA_NOCLDSTOP); + setsigmask(&fullset); +} + +static void startslattach(void) { + FILE *piper; + char ifnbuf[200]; + int r, l, k; + + r= pipe(slpipe); if (r) sysfatal("create pipe"); + piper= fdopen(slpipe[0],"r"); if (!piper) sysfatal("fdopen pipe"); + + pids.byname.sl= makesubproc(sl_entry); + + close(slpipe[1]); + setsigmask(&emptyset); + if (!fgets(ifnbuf,sizeof(ifnbuf),piper)) { + if (ferror(piper)) sysfatal("cannot read ifname from slattach"); + else fatal("cannot read ifname from slattach"); + } + setsigmask(&fullset); + l= strlen(ifnbuf); + if (l<0 || ifnbuf[l-1] != '\n') fatal("slattach gave strange output `%s'",ifnbuf); + ifnbuf[l-1]= 0; + for (k=l; k>0 && ifnbuf[k-1]!=' '; k--); + ifname= ifnbuf+k; +} + +static void netconfigure(void) { + char mtutxt[100]; + int i; + + if (task()) { + sprintf(mtutxt,"%lu",mtu); + + execlp("ifconfig", "ifconfig", ifname, localtxt, + "netmask","255.255.255.255", "-broadcast", "pointopoint",peertxt, + "mtu",mtutxt, "up", (char*)0); + sysfatal("cannot exec ifconfig"); + } + + if (task()) { + execlp("route","route", "-host",localtxt, "netmask","255.255.255.255", + "dev",ifname, (char*)0); + sysfatal("cannot exec route (for local)"); + } + + if (task()) { + execlp("route","route", "-host",peertxt, "netmask","255.255.255.255", + "dev",ifname, (char*)0); + sysfatal("cannot exec route (for peer)"); + } + + for (i=0; i