} *cpplace;
-static int slpipe[2], ptmaster;
+static int slpipe[2], ptmaster, undoslattach;
static const char *ifname;
static const char *ptyname;
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;
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);
}
char *ep;
int endchar;
- if (!*argp) { badusage("missing number %s\n",what); }
+ if (!*argp) { badusage("missing number %s",what); }
rv= strtoul(*argp,&ep,0);
if ((endchar= *ep)) {
- if (!endchars) badusage("junk after number %s\n",what);
+ if (!endchars) badusage("junk after number %s",what);
if (!strchr(endchars,endchar))
badusage("invalid character or delimiter `%c' in or after number, %s:"
- " expected %s (or none?)\n", endchar,what,endchars);
+ " expected %s (or none?)", endchar,what,endchars);
*argp= ep+1;
} else {
*argp= 0;
len= eat_number(argp,whatbuf, 0,32, endchars,endchar_r);
mask= (~0UL << (32-len));
- if (prefix & ~mask) badusage("%s prefix %08lx not fully contained in mask %08lx\n",
+ if (prefix & ~mask) badusage("%s prefix %08lx not fully contained in mask %08lx",
what,prefix,mask);
*prefix_r= prefix;
if (mask_r) *mask_r= mask;
carg= *++argv;
for (nexroutes=0;
- carg;
+ carg && *carg;
nexroutes++) {
if (nexroutes == MAXEXROUTES)
fatal("too many extra routes (only %d allowed)",MAXEXROUTES);
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;
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;
sigemptyset(&sa.sa_mask);
setsignals(SIG_DFL,&sa,0);
setsigmask(&emptyset);
+ undoslattach= 0;
}
static pid_t makesubproc(void (*entry)(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");
}
} 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,
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);
}
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]);
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<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)");
}
static void copydata(void) __attribute__((noreturn));
-static void copydata(void) {
+static void copydata(void) {
+ int r;
+
pids.byname.cin= makesubproc(cin_entry);
+ for (;;) {
+ r= write(1, "\300", 1); if (r==1) break;
+ assert(r==-1); if (errno != EINTR) sysfatal("send initial delim to confirm");
+ }
pids.byname.cout= makesubproc(cout_entry);
for (;;) sigsuspend(&emptyset);