diff options
author | brian <brian@FreeBSD.org> | 1998-05-28 23:17:51 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1998-05-28 23:17:51 +0000 |
commit | e0d8cc391d650e6b69d5d77af50a002041522151 (patch) | |
tree | e3cc3229d89e0fd28c03dea90790a87b1f1bcfe6 /usr.sbin | |
parent | f320a1dcb71e3195a3a9ab924dd4f60db4c3ac53 (diff) | |
download | FreeBSD-src-e0d8cc391d650e6b69d5d77af50a002041522151.zip FreeBSD-src-e0d8cc391d650e6b69d5d77af50a002041522151.tar.gz |
o #define the name "tun" in defs.h against the future possibility
of supporting architectures with different device names.
o Close /dev/tunX when destroying the bundle.
o Don't forget to close the parent end of the pipe in the child
process when exec'ing a program from a chat script.
o If we close our controlling terminal, ditch the current session
with it, allowing getty(8) (or whatever) to regain control.
o After transferring our controlling terminal descriptor to another
ppp instance, we now fork a new ppp to continue where we left off,
transferring ownership of all uucp locks and the /var/run/tunX.pid
file. Meanwhile the parent closes all file descriptors, defaults
all signals and does a pause() to wait for a HUP after the
transferred descriptor is finally closed.
We don't run /bin/cat any more (again!).
Suggested by: bde
TODO: It seems clocal devices need their pause()d session leader
to be given a manual HUP, as closing the last open descriptor
doesn't do the job.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ppp/bundle.c | 235 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.h | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/chat.c | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/defs.h | 6 | ||||
-rw-r--r-- | usr.sbin/ppp/log.c | 7 | ||||
-rw-r--r-- | usr.sbin/ppp/main.c | 21 | ||||
-rw-r--r-- | usr.sbin/ppp/modem.c | 11 |
7 files changed, 170 insertions, 117 deletions
diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index 15e0cfe..474e895 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -23,10 +23,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bundle.c,v 1.8 1998/05/25 10:37:00 brian Exp $ + * $Id: bundle.c,v 1.9 1998/05/28 23:15:29 brian Exp $ */ -#include <sys/types.h> +#include <sys/param.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/if.h> @@ -515,7 +515,7 @@ bundle_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) FD_SET(bundle->dev.fd, r); if (*n < bundle->dev.fd + 1) *n = bundle->dev.fd + 1; - log_Printf(LogTIMER, "tun: fdset(r) %d\n", bundle->dev.fd); + log_Printf(LogTIMER, "%s: fdset(r) %d\n", TUN_NAME, bundle->dev.fd); result++; } } @@ -567,12 +567,12 @@ bundle_DescriptorRead(struct descriptor *d, struct bundle *bundle, /* something to read from tun */ n = read(bundle->dev.fd, &tun, sizeof tun); if (n < 0) { - log_Printf(LogERROR, "read from tun: %s\n", strerror(errno)); + log_Printf(LogERROR, "read from %s: %s\n", TUN_NAME, strerror(errno)); return; } n -= sizeof tun - sizeof tun.data; if (n <= 0) { - log_Printf(LogERROR, "read from tun: Only %d bytes read\n", n); + log_Printf(LogERROR, "read from %s: Only %d bytes read\n", TUN_NAME, n); return; } if (!tun_check_header(tun, AF_INET)) @@ -653,6 +653,33 @@ bundle_DescriptorWrite(struct descriptor *d, struct bundle *bundle, descriptor_Write(&dl->desc, bundle, fdset); } +static void +bundle_LockTun(struct bundle *bundle) +{ + FILE *lockfile; + char pidfile[MAXPATHLEN]; + + snprintf(pidfile, sizeof pidfile, "%stun%d.pid", _PATH_VARRUN, bundle->unit); + lockfile = ID0fopen(pidfile, "w"); + if (lockfile != NULL) { + fprintf(lockfile, "%d\n", (int)getpid()); + fclose(lockfile); + } +#ifndef RELEASE_CRUNCH + else + log_Printf(LogERROR, "Warning: Can't create %s: %s\n", + pidfile, strerror(errno)); +#endif +} + +static void +bundle_UnlockTun(struct bundle *bundle) +{ + char pidfile[MAXPATHLEN]; + + snprintf(pidfile, sizeof pidfile, "%stun%d.pid", _PATH_VARRUN, bundle->unit); + ID0unlink(pidfile); +} struct bundle * bundle_Create(const char *prefix, int type) @@ -803,6 +830,8 @@ bundle_Create(const char *prefix, int type) /* Clean out any leftover crud */ bundle_CleanInterface(&bundle); + bundle_LockTun(&bundle); + return &bundle; } @@ -854,12 +883,15 @@ bundle_Destroy(struct bundle *bundle) mp_Down(&bundle->ncp.mp); ipcp_CleanInterface(&bundle->ncp.ipcp); bundle_DownInterface(bundle); - + /* Again, these are all DATALINK_CLOSED unless we're abending */ dl = bundle->links; while (dl) dl = datalink_Destroy(dl); + close(bundle->dev.fd); + bundle_UnlockTun(bundle); + /* In case we never made PHASE_NETWORK */ bundle_Notify(bundle, EX_ERRDEAD); @@ -1432,7 +1464,7 @@ bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf; struct msghdr msg; struct iovec iov[SCATTER_SEGMENTS]; - int niov, link_fd, f, expect; + int niov, link_fd, f, expect, newsid; pid_t newpid; log_Printf(LogPHASE, "Transmitting datalink %s\n", dl->name); @@ -1456,23 +1488,12 @@ bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) msg.msg_iov = iov; msg.msg_iovlen = niov; - if (tcgetpgrp(link_fd) == getpgrp()) { - /* - * We can't transfer this tty descriptor. If we do, then once the - * session leader exits, the descriptor becomes unusable by the - * other ppp process. Instead, we'll fork() two `/bin/cat' - * processes..... - */ - msg.msg_control = NULL; - msg.msg_controllen = 0; - } else { - cmsg->cmsg_len = sizeof cmsgbuf; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = link_fd; - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof cmsgbuf; - } + cmsg->cmsg_len = sizeof cmsgbuf; + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = link_fd; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof cmsgbuf; for (f = expect = 0; f < niov; f++) expect += iov[f].iov_len; @@ -1486,69 +1507,10 @@ bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) /* We must get the ACK before closing the descriptor ! */ read(s, &ack, 1); - if (tcgetpgrp(link_fd) == getpgrp()) { - /* We use `/bin/cat' to keep the tty session id */ - pid_t pid; - int status, len, fd; - char name[50], *tname; - - tname = ttyname(link_fd); - len = strlen(_PATH_DEV); - if (!strncmp(tname, _PATH_DEV, len)) - tname += len; - - log_Printf(LogPHASE, "%s: Using twin %s invocations\n", tname, CATPROG); - - switch ((pid = fork())) { - case -1: - log_Printf(LogERROR, "fork: %s\n", strerror(errno)); - break; - case 0: - if (fork()) /* Don't want to belong to the parent any more */ - exit(0); - setsid(); - log_Printf(LogPHASE, "%d: Continuing without controlling terminal\n", - (int)getpid()); - break; - default: - /* Parent does the execs .... */ - timer_TermService(); - waitpid(pid, &status, 0); - - fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ - fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) & ~O_NONBLOCK); - fcntl(link_fd, F_SETFL, fcntl(link_fd, F_GETFL, 0) & ~O_NONBLOCK); - s = fcntl(s, F_DUPFD, 3); - link_fd = fcntl(link_fd, F_DUPFD, 3); - dup2(open(_PATH_DEVNULL, O_WRONLY|O_APPEND), STDERR_FILENO); - - setuid(geteuid()); - - switch (fork()) { - case -1: - _exit(0); - break; - case 0: - dup2(link_fd, STDIN_FILENO); - dup2(s, STDOUT_FILENO); - snprintf(name, sizeof name, "%s <- %s", dl->name, tname); - break; - default: - dup2(s, STDIN_FILENO); - dup2(link_fd, STDOUT_FILENO); - snprintf(name, sizeof name, "%s -> %s", dl->name, tname); - break; - } - signal(SIGPIPE, SIG_DFL); - signal(SIGALRM, SIG_DFL); - for (fd = getdtablesize(); fd > 2; fd--) - close(fd); - execl(CATPROG, name, NULL); - _exit(0); - break; - } - } + newsid = tcgetpgrp(link_fd) == getpgrp(); close(link_fd); + if (newsid) + bundle_setsid(dl->bundle, 1); } close(s); @@ -1605,3 +1567,104 @@ bundle_SetMode(struct bundle *bundle, struct datalink *dl, int mode) return 1; } + +void +bundle_setsid(struct bundle *bundle, int holdsession) +{ + /* + * Lose the current session. This means getting rid of our pid + * too so that the tty device will really go away, and any getty + * etc will be allowed to restart. + */ + pid_t pid, orig; + int fds[2]; + char done; + struct datalink *dl; + + orig = getpid(); + if (pipe(fds) == -1) { + log_Printf(LogERROR, "pipe: %s\n", strerror(errno)); + return; + } + switch ((pid = fork())) { + case -1: + log_Printf(LogERROR, "fork: %s\n", strerror(errno)); + close(fds[0]); + close(fds[1]); + return; + case 0: + close(fds[0]); + read(fds[1], &done, 1); /* uu_locks are mine ! */ + close(fds[1]); + if (pipe(fds) == -1) { + log_Printf(LogERROR, "pipe(2): %s\n", strerror(errno)); + return; + } + switch ((pid = fork())) { + case -1: + log_Printf(LogERROR, "fork: %s\n", strerror(errno)); + close(fds[0]); + close(fds[1]); + return; + case 0: + close(fds[0]); + bundle_LockTun(bundle); /* update pid */ + read(fds[1], &done, 1); /* uu_locks are mine ! */ + close(fds[1]); + setsid(); + log_Printf(LogPHASE, "%d -> %d: %s session control\n", + (int)orig, (int)getpid(), + holdsession ? "Passed" : "Dropped"); + break; + default: + close(fds[1]); + /* Give away all our modem locks (to the final process) */ + for (dl = bundle->links; dl; dl = dl->next) + if (dl->state != DATALINK_CLOSED) + modem_ChangedPid(dl->physical, pid); + write(fds[0], "!", 1); /* done */ + close(fds[0]); + exit(0); + break; + } + break; + default: + close(fds[1]); + /* Give away all our modem locks (to the intermediate process) */ + for (dl = bundle->links; dl; dl = dl->next) + if (dl->state != DATALINK_CLOSED) + modem_ChangedPid(dl->physical, pid); + write(fds[0], "!", 1); /* done */ + close(fds[0]); + if (holdsession) { + int fd, status; + + timer_TermService(); + signal(SIGPIPE, SIG_DFL); + signal(SIGALRM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + for (fd = getdtablesize(); fd >= 0; fd--) + close(fd); + setuid(geteuid()); + /* + * Reap the intermediate process. As we're not exiting but the + * intermediate is, we don't want it to become defunct. + */ + waitpid(pid, &status, 0); + /* + * Hang around for a HUP. This should happen as soon as the + * ppp that we passed our ctty descriptor to closes it. + * NOTE: If this process dies, the passed descriptor becomes + * invalid and will give a select() error by setting one + * of the error fds, aborting the other ppp. We don't + * want that to happen ! + */ + pause(); + } + exit(0); + break; + } +} diff --git a/usr.sbin/ppp/bundle.h b/usr.sbin/ppp/bundle.h index 974563a..a903fa2 100644 --- a/usr.sbin/ppp/bundle.h +++ b/usr.sbin/ppp/bundle.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bundle.h,v 1.2 1998/05/21 21:44:14 brian Exp $ + * $Id: bundle.h,v 1.3 1998/05/23 22:24:30 brian Exp $ */ #define PHASE_DEAD 0 /* Link is dead */ @@ -164,3 +164,4 @@ extern void bundle_ReceiveDatalink(struct bundle *, int, struct sockaddr_un *); extern int bundle_SetMode(struct bundle *, struct datalink *, int); extern int bundle_RenameDatalink(struct bundle *, struct datalink *, const char *); +extern void bundle_setsid(struct bundle *, int); diff --git a/usr.sbin/ppp/chat.c b/usr.sbin/ppp/chat.c index c9e099f..db7356f 100644 --- a/usr.sbin/ppp/chat.c +++ b/usr.sbin/ppp/chat.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: chat.c,v 1.45 1998/05/21 21:44:37 brian Exp $ + * $Id: chat.c,v 1.46 1998/05/23 22:24:32 brian Exp $ */ #include <sys/types.h> @@ -727,8 +727,8 @@ ExecStr(struct physical *physical, char *command, char *out, int olen) return; } if ((pid = fork()) == 0) { + close(fids[0]); timer_TermService(); - fids[1] = fcntl(fids[1], F_DUPFD, 4); dup2(physical_GetFD(physical), STDIN_FILENO); dup2(STDIN_FILENO, STDOUT_FILENO); diff --git a/usr.sbin/ppp/defs.h b/usr.sbin/ppp/defs.h index 6f39ad6..877b7dd 100644 --- a/usr.sbin/ppp/defs.h +++ b/usr.sbin/ppp/defs.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: defs.h,v 1.29.2.18 1998/05/15 23:58:22 brian Exp $ + * $Id: defs.h,v 1.30 1998/05/21 21:45:05 brian Exp $ * * TODO: */ @@ -33,8 +33,8 @@ #define _PATH_PPP "/etc/ppp" -#define TUN_PREFIX "/dev/tun" /* tunnel device prefix */ -#define CATPROG "/bin/cat" /* Multilink pipe program name */ +#define TUN_NAME "tun" +#define TUN_PREFIX (_PATH_DEV TUN_NAME) /* /dev/tun */ #define MODEM_SPEED B38400 /* tty speed */ #define SERVER_PORT 3000 /* Base server port no. */ diff --git a/usr.sbin/ppp/log.c b/usr.sbin/ppp/log.c index 61a3b29..c530dae 100644 --- a/usr.sbin/ppp/log.c +++ b/usr.sbin/ppp/log.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: log.c,v 1.27 1998/05/21 21:46:25 brian Exp $ + * $Id: log.c,v 1.28 1998/05/23 22:24:40 brian Exp $ */ #include <sys/types.h> @@ -39,6 +39,7 @@ #include "log.h" #include "descriptor.h" #include "prompt.h" +#include "defs.h" static const char *LogNames[] = { "Async", @@ -293,7 +294,7 @@ log_Printf(int lev, const char *fmt,...) if ((log_IsKept(lev) & LOG_KEPT_LOCAL) && promptlist) { if ((log_IsKept(LogTUN) & LOG_KEPT_LOCAL) && LogTunno != -1) - snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s", + snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME, LogTunno, log_Name(lev), fmt); else snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt); @@ -306,7 +307,7 @@ log_Printf(int lev, const char *fmt,...) if ((log_IsKept(lev) & LOG_KEPT_SYSLOG) && (lev != LogWARN || !promptlist)) { if ((log_IsKept(LogTUN) & LOG_KEPT_SYSLOG) && LogTunno != -1) - snprintf(nfmt, sizeof nfmt, "tun%d: %s: %s", + snprintf(nfmt, sizeof nfmt, "%s%d: %s: %s", TUN_NAME, LogTunno, log_Name(lev), fmt); else snprintf(nfmt, sizeof nfmt, "%s: %s", log_Name(lev), fmt); diff --git a/usr.sbin/ppp/main.c b/usr.sbin/ppp/main.c index 73945a5..e794a15 100644 --- a/usr.sbin/ppp/main.c +++ b/usr.sbin/ppp/main.c @@ -17,12 +17,12 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: main.c,v 1.125 1998/05/25 02:22:36 brian Exp $ + * $Id: main.c,v 1.126 1998/05/27 22:43:31 brian Exp $ * * TODO: */ -#include <sys/param.h> +#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -78,8 +78,6 @@ #endif #endif -static char pid_filename[MAXPATHLEN]; - static void DoLoop(struct bundle *); static void TerminalStop(int); static const char *ex_desc(int); @@ -99,7 +97,6 @@ void AbortProgram(int excode) { server_Close(SignalBundle); - ID0unlink(pid_filename); log_Printf(LogPHASE, "PPP Terminated (%s).\n", ex_desc(excode)); bundle_Close(SignalBundle, NULL, 1); bundle_Destroy(SignalBundle); @@ -239,7 +236,6 @@ ProcessArgs(int argc, char **argv, int *mode) int main(int argc, char **argv) { - FILE *lockfile; char *name, *label; int nfds, mode; struct bundle *bundle; @@ -444,19 +440,6 @@ main(int argc, char **argv) prompt_Required(prompt); } - snprintf(pid_filename, sizeof pid_filename, "%stun%d.pid", - _PATH_VARRUN, bundle->unit); - lockfile = ID0fopen(pid_filename, "w"); - if (lockfile != NULL) { - fprintf(lockfile, "%d\n", (int) getpid()); - fclose(lockfile); - } -#ifndef RELEASE_CRUNCH - else - log_Printf(LogALERT, "Warning: Can't create %s: %s\n", - pid_filename, strerror(errno)); -#endif - log_Printf(LogPHASE, "PPP Started (%s mode).\n", mode2Nam(mode)); DoLoop(bundle); AbortProgram(EX_NORMAL); diff --git a/usr.sbin/ppp/modem.c b/usr.sbin/ppp/modem.c index f8bf5f4..8e3c705 100644 --- a/usr.sbin/ppp/modem.c +++ b/usr.sbin/ppp/modem.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: modem.c,v 1.85 1998/05/25 10:37:02 brian Exp $ + * $Id: modem.c,v 1.86 1998/05/28 23:15:38 brian Exp $ * * TODO: */ @@ -431,7 +431,7 @@ modem_lock(struct physical *modem, int tunno) snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, modem->name.base); lockfile = ID0fopen(fn, "w"); if (lockfile != NULL) { - fprintf(lockfile, "tun%d\n", tunno); + fprintf(lockfile, "%s%d\n", TUN_NAME, tunno); fclose(lockfile); } #ifndef RELEASE_CRUNCH @@ -750,13 +750,18 @@ modem_Unraw(struct physical *modem) static void modem_PhysicalClose(struct physical *modem) { + int newsid; + log_Printf(LogDEBUG, "%s: Physical Close\n", modem->link.name); + newsid = tcgetpgrp(modem->fd) == getpgrp(); close(modem->fd); modem->fd = -1; timer_Stop(&modem->Timer); log_SetTtyCommandMode(modem->dl); throughput_stop(&modem->link.throughput); throughput_log(&modem->link.throughput, LogPHASE, modem->link.name); + if (newsid) + bundle_setsid(modem->dl->bundle, 0); } void @@ -1072,7 +1077,7 @@ modem2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, void modem_ChangedPid(struct physical *p, pid_t newpid) { - if (p->type != PHYS_DIRECT) { + if (p->fd >= 0 && p->type != PHYS_DIRECT) { int res; if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) |