chiark / gitweb /
Pretty much works apart from some spare routes.
authorian <ian>
Sun, 19 Sep 1999 19:02:51 +0000 (19:02 +0000)
committerian <ian>
Sun, 19 Sep 1999 19:02:51 +0000 (19:02 +0000)
ipif/service.c

index 33ba2df28a362962a09a886bbc37da43d41bea95..b76c75473b04a5a1e98129c7997fc6f750beec92 100644 (file)
@@ -75,7 +75,7 @@ static struct pplace {
 } *cpplace;
 
 
-static int slpipe[2], ptmaster;
+static int slpipe[2], ptmaster, undoslattach;
 static const char *ifname;
 static const char *ptyname;
 
@@ -88,13 +88,36 @@ static union {
 sigset_t emptyset, fullset;
 
 
+static int cleantask(void) {
+  pid_t pid;
+
+  pid= fork();
+  if (!pid) return 1;
+  if (pid == (pid_t)-1)
+    perror("userv-ipif: fork for undo slattach failed - cannot clean up properly");
+  return 0;
+}
+
 static void terminate(int estatus) {
   int i, status;
   pid_t pid;
   
   for (i=0; i<NPIDS; i++)
     if (pids.bynumber[i]) kill(pids.bynumber[i], SIGTERM);
-  
+
+  if (undoslattach) {
+    if (cleantask()) {
+      execlp("slattach", "slattach", "-p", "tty", ptyname, (char*)0);
+      perror("userv-ipif: exec slattach for undo slattach failed");
+      exit(-1);
+    }
+    if (ifname && cleantask()) {
+      execlp("ifconfig", "ifconfig", ifname, "down", (char*)0);
+      perror("userv-ipif: exec ifconfig for undo ifconfig failed");
+      exit(-1);
+    }
+  }
+
   for (;;) {
     pid= waitpid(-1,&status,0);
     if (pid == (pid_t)-1) break;
@@ -124,9 +147,9 @@ static void sysfatal(const char *fmt, ...) {
   e= errno;
   va_start(al,fmt);
 
-  fputs("userv-ipif service: fatal system error",stderr);
+  fputs("userv-ipif service: fatal system error",stderr);
   vfprintf(stderr, fmt, al);
-  fprintf(stderr,"%s\n", strerror(e));
+  fprintf(stderr,"%s\n", strerror(e));
   terminate(12);
 }
 
@@ -474,6 +497,14 @@ static void dumpdebug(void) {
   exit(0);
 }
 
+
+static void setsigmask(const sigset_t *ss) {
+  int r;
+  
+  r= sigprocmask(SIG_SETMASK, ss, 0);
+  if (r) sysfatal("[un]block signals");
+}  
+
 static void setsignals(void (*handler)(int), struct sigaction *sa, int chldflags) {
   const int *signalp;
   int r, sig;
@@ -487,13 +518,6 @@ static void setsignals(void (*handler)(int), struct sigaction *sa, int 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;
 
@@ -501,6 +525,7 @@ static void infork(void) {
   sigemptyset(&sa.sa_mask);
   setsignals(SIG_DFL,&sa,0);
   setsigmask(&emptyset);
+  undoslattach= 0;
 }
 
 static pid_t makesubproc(void (*entry)(void)) {
@@ -518,28 +543,38 @@ 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; }
+  if (pid == (pid_t)-1) sysfatal("fork for task");
+  if (!pid) { infork(); return 1; }
 
   pids.byname.task= pid;
   while (pids.byname.task) sigsuspend(&emptyset);
   return 0;
 }
 
+static void mdup2(int fd1, int fd2, const char *what) {
+  int r;
+
+  for (;;) {
+    r= dup2(fd1,fd2); if (r==fd2) return;
+    if (r!=-1) fatal("dup2 in %s gave wrong answer %d instead of %d",what,r,fd2);
+    if (errno != EINTR) sysfatal("dup2 failed in %s",what);
+  }
+}
+
 static void sl_entry(void) {
-  if (dup2(slpipe[1],1) != 1) sysfatal("dup2 stdout in slattach child");
+  mdup2(slpipe[1],1,"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");
+  mdup2(ptmaster,1,"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");
+  mdup2(ptmaster,0,"cat output child");
   execlp("cat", "cat", (char*)0);
   sysfatal("cannot exec cat output");
 }
@@ -577,11 +612,22 @@ static void sighandler(int signum) {
       } else {
        continue;
       }
+      break;
     }
     if (taskfail) {
-      fprintf(stderr,
-             "userv-ipif service: %s unexpected terminated with status code %d\n",
-             taskfail, status);
+      if (WIFEXITED(status)) {
+       fprintf(stderr,
+               "userv-ipif service: %s unexpectedly exited with exit status %d\n",
+               taskfail, WEXITSTATUS(status));
+      } else if (WIFSIGNALED(status)) {
+       fprintf(stderr,
+               "userv-ipif service: %s unexpectedly killed by signal %s%s\n",
+               taskfail, strsignal(WTERMSIG(status)),
+               WCOREDUMP(status) ? " (core dumped)" : "");
+      } else {
+       fprintf(stderr, "userv-ipif service: %s unexpectedly terminated"
+               " with unknown status code %d\n", taskfail, status);
+      }
     }
   } else {
     fprintf(stderr,
@@ -603,6 +649,7 @@ static void startup(void) {
   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");
+  r= unlockpt(ptmaster);  if (r) sysfatal("unlock pty");
 
   sigfillset(&sa.sa_mask);
   setsignals(sighandler,&sa,SA_NOCLDSTOP);
@@ -610,13 +657,15 @@ static void startup(void) {
 }
 
 static void startslattach(void) {
+  static char ifnbuf[200];
+
   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");
 
+  undoslattach= 1;
   pids.byname.sl= makesubproc(sl_entry);
 
   close(slpipe[1]);
@@ -647,20 +696,20 @@ static void netconfigure(void) {
   }
 
   if (task()) {
-    execlp("route","route", "-host",localtxt, "netmask","255.255.255.255",
+    execlp("route","route", "add", "-host",localtxt,
           "dev",ifname, (char*)0);
     sysfatal("cannot exec route (for local)");
   }
 
   if (task()) {
-    execlp("route","route", "-host",peertxt, "netmask","255.255.255.255",
+    execlp("route","route", "add", "-host",peertxt,
           "dev",ifname, (char*)0);
     sysfatal("cannot exec route (for peer)");
   }
 
   for (i=0; i<nexroutes; i++) {
     if (task()) {
-      execlp("route","route", "-net",exroutes[i].prefixtxt,
+      execlp("route","route", "add", "-net",exroutes[i].prefixtxt,
             "netmask",exroutes[i].masktxt,
             "gw",peertxt, "dev",ifname, (char*)0);
       sysfatal("cannot exec route (for route)");