X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fmain.c;h=f4913ff28e7798c9b813640d092cfebde21f3a09;hp=c580f7c6e23d618e0ff7544b2083a25d5c3683d4;hb=79b0b24a753bc3f560ba85893cb51bbbecc429be;hpb=a3396b002507d72b3e1f1169bd02ae018539654b diff --git a/pppd/main.c b/pppd/main.c index c580f7c..f4913ff 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -18,10 +18,11 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.19 1994/09/21 06:47:37 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.27 1995/08/16 01:39:08 paulus Exp $"; #endif #include +#include #include #include #include @@ -64,14 +65,13 @@ int ifunit; /* Interface unit number */ char *progname; /* Name of this program */ char hostname[MAXNAMELEN]; /* Our hostname */ -static char pidfilename[MAXPATHLEN]; - +static char pidfilename[MAXPATHLEN]; /* name of pid file */ +static char default_devnam[MAXPATHLEN]; /* name of default device */ static pid_t pid; /* Our pid */ static pid_t pgrpid; /* Process Group ID */ static uid_t uid; /* Our real user-id */ int fd = -1; /* Device file descriptor */ -int s; /* Socket file descriptor */ int phase; /* where the link is at */ int kill_link; @@ -87,12 +87,15 @@ static int n_children; /* # child processes still running */ int baud_rate; +char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n"; + /* prototypes */ static void hup __P((int)); static void term __P((int)); static void chld __P((int)); static void toggle_debug __P((int)); static void open_ccp __P((int)); +static void bad_signal __P((int)); static void get_input __P((void)); void establish_ppp __P((void)); @@ -112,6 +115,11 @@ void pr_log __P((void *, char *, ...)); extern char *ttyname __P((int)); extern char *getlogin __P((void)); +#ifdef ultrix +#undef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif + /* * PPP Data Link Layer "protocol" table. * One entry per supported protocol. @@ -155,6 +163,7 @@ main(argc, argv) p = ttyname(0); if (p) strcpy(devnam, p); + strcpy(default_devnam, devnam); if (gethostname(hostname, MAXNAMELEN) < 0 ) { perror("couldn't get hostname"); @@ -165,7 +174,7 @@ main(argc, argv) uid = getuid(); if (!ppp_available()) { - fprintf(stderr, "Sorry - PPP is not available on this system\n"); + fprintf(stderr, no_ppp_msg); exit(1); } @@ -187,6 +196,13 @@ main(argc, argv) check_auth_options(); setipdefault(); + /* + * If the user has specified the default device name explicitly, + * pretend they hadn't. + */ + if (!default_device && strcmp(devnam, default_devnam) == 0) + default_device = 1; + /* * Initialize system-dependent stuff and magic number package. */ @@ -212,12 +228,6 @@ main(argc, argv) } syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d", VERSION, PATCHLEVEL, p, uid); - - /* Get an internet socket for doing socket ioctl's on. */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "Couldn't create IP socket: %m"); - die(1); - } /* * Compute mask of all interesting signals and install signal handlers @@ -245,8 +255,47 @@ main(argc, argv) SIGNAL(SIGTERM, term); /* Terminate */ SIGNAL(SIGCHLD, chld); - signal(SIGUSR1, toggle_debug); /* Toggle debug flag */ - signal(SIGUSR2, open_ccp); /* Reopen CCP */ + SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */ + SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */ + + /* + * Install a handler for other signals which would otherwise + * cause pppd to exit without cleaning up. + */ + SIGNAL(SIGABRT, bad_signal); + SIGNAL(SIGALRM, bad_signal); + SIGNAL(SIGFPE, bad_signal); + SIGNAL(SIGILL, bad_signal); + SIGNAL(SIGPIPE, bad_signal); + SIGNAL(SIGQUIT, bad_signal); + SIGNAL(SIGSEGV, bad_signal); +#ifdef SIGBUS + SIGNAL(SIGBUS, bad_signal); +#endif +#ifdef SIGEMT + SIGNAL(SIGEMT, bad_signal); +#endif +#ifdef SIGPOLL + SIGNAL(SIGPOLL, bad_signal); +#endif +#ifdef SIGPROF + SIGNAL(SIGPROF, bad_signal); +#endif +#ifdef SIGSYS + SIGNAL(SIGSYS, bad_signal); +#endif +#ifdef SIGTRAP + SIGNAL(SIGTRAP, bad_signal); +#endif +#ifdef SIGVTALRM + SIGNAL(SIGVTALRM, bad_signal); +#endif +#ifdef SIGXCPU + SIGNAL(SIGXCPU, bad_signal); +#endif +#ifdef SIGXFSZ + SIGNAL(SIGXFSZ, bad_signal); +#endif /* * Lock the device if we've been asked to. @@ -299,10 +348,10 @@ main(argc, argv) die(1); } - syslog(LOG_INFO, "Connected..."); + syslog(LOG_INFO, "Serial connection established."); sleep(1); /* give it time to set up its terminal */ } - + /* set line speed, flow control, etc.; clear CLOCAL if modem option */ set_up_tty(fd, 0); @@ -340,6 +389,7 @@ main(argc, argv) for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) { wait_input(timeleft(&timo)); calltimeout(); + get_input(); if (kill_link) { lcp_close(0); kill_link = 0; @@ -351,20 +401,24 @@ main(argc, argv) } open_ccp_flag = 0; } - get_input(); reap_kids(); /* Don't leave dead kids lying around */ } /* - * Run disconnector script, if requested + * Run disconnector script, if requested. + * First we need to reset non-blocking mode. + * XXX we may not be able to do this if the line has hung up! */ + if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) >= 0) + initfdflags = -1; + disestablish_ppp(); if (disconnector) { + set_up_tty(fd, 1); if (device_script(disconnector, fd, fd) < 0) { syslog(LOG_WARNING, "disconnect script failed"); - die(1); + } else { + syslog(LOG_INFO, "Serial link disconnected."); } - - syslog(LOG_INFO, "Disconnected..."); } close_fd(); @@ -374,10 +428,7 @@ main(argc, argv) } while (persist); - if (lockflag && !default_device) - unlock(); - - exit(0); + die(0); } @@ -391,62 +442,59 @@ get_input() u_char *p; u_short protocol; - for (;;) { /* Read all available packets */ - p = inpacket_buf; /* point to beginning of packet buffer */ + p = inpacket_buf; /* point to beginning of packet buffer */ - len = read_packet(inpacket_buf); - if (len < 0) - return; + len = read_packet(inpacket_buf); + if (len < 0) + return; - if (len == 0) { - MAINDEBUG((LOG_DEBUG, "End of file on fd!")); - hungup = 1; - lcp_lowerdown(0); /* serial link is no longer available */ - phase = PHASE_DEAD; - return; - } + if (len == 0) { + syslog(LOG_NOTICE, "Modem hangup"); + hungup = 1; + lcp_lowerdown(0); /* serial link is no longer available */ + phase = PHASE_DEAD; + return; + } - if (debug /*&& (debugflags & DBG_INPACKET)*/) - log_packet(p, len, "rcvd "); + if (debug /*&& (debugflags & DBG_INPACKET)*/) + log_packet(p, len, "rcvd "); - if (len < PPP_HDRLEN) { - MAINDEBUG((LOG_INFO, "io(): Received short packet.")); - return; - } + if (len < PPP_HDRLEN) { + MAINDEBUG((LOG_INFO, "io(): Received short packet.")); + return; + } - p += 2; /* Skip address and control */ - GETSHORT(protocol, p); - len -= PPP_HDRLEN; + p += 2; /* Skip address and control */ + GETSHORT(protocol, p); + len -= PPP_HDRLEN; - /* - * Toss all non-LCP packets unless LCP is OPEN. - */ - if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) { - MAINDEBUG((LOG_INFO, - "io(): Received non-LCP packet when LCP not open.")); + /* + * Toss all non-LCP packets unless LCP is OPEN. + */ + if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) { + MAINDEBUG((LOG_INFO, + "io(): Received non-LCP packet when LCP not open.")); + return; + } + + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) { + if (prottbl[i].protocol == protocol) { + (*prottbl[i].input)(0, p, len); return; } - - /* - * Upcall the proper protocol input routine. - */ - for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) - if (prottbl[i].protocol == protocol) { - (*prottbl[i].input)(0, p, len); - break; - } else if (protocol == (prottbl[i].protocol & ~0x8000) - && prottbl[i].datainput != NULL) { - (*prottbl[i].datainput)(0, p, len); - break; - } - - if (i == sizeof (prottbl) / sizeof (struct protent)) { - if (debug) - syslog(LOG_WARNING, "Unknown protocol (0x%x) received", - protocol); - lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); + if (protocol == (prottbl[i].protocol & ~0x8000) + && prottbl[i].datainput != NULL) { + (*prottbl[i].datainput)(0, p, len); + return; } } + + if (debug) + syslog(LOG_WARNING, "Unknown protocol (0x%x) received", protocol); + lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); } @@ -476,12 +524,23 @@ demuxprotrej(unit, protocol) /* - * quit - Clean up state and exit. + * bad_signal - We've caught a fatal signal. Clean up state and exit. + */ +static void +bad_signal(sig) + int sig; +{ + syslog(LOG_ERR, "Fatal signal %d", sig); + die(1); +} + +/* + * quit - Clean up state and exit (with an error indication). */ void quit() { - die(0); + die(1); } /* @@ -522,6 +581,8 @@ cleanup(status, arg) void close_fd() { + disestablish_ppp(); + /* drop dtr to hang up */ if (modem) setdtr(fd, FALSE); @@ -530,8 +591,6 @@ close_fd() syslog(LOG_WARNING, "Couldn't restore device fd flags: %m"); initfdflags = -1; - disestablish_ppp(); - restore_tty(); close(fd); @@ -563,8 +622,8 @@ timeout(func, arg, time) { struct callout *newp, *p, **pp; - MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.", - (int) func, (int) arg, time)); + MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.", + (long) func, (long) arg, time)); /* * Allocate timeout. @@ -583,9 +642,9 @@ timeout(func, arg, time) * Find correct place and link it in. */ for (pp = &callout; (p = *pp); pp = &p->c_next) - if (p->c_time.tv_sec < newp->c_time.tv_sec - || (p->c_time.tv_sec == newp->c_time.tv_sec - && p->c_time.tv_usec <= newp->c_time.tv_sec)) + if (newp->c_time.tv_sec < p->c_time.tv_sec + || (newp->c_time.tv_sec == p->c_time.tv_sec + && newp->c_time.tv_usec < p->c_time.tv_sec)) break; newp->c_next = p; *pp = newp; @@ -604,7 +663,7 @@ untimeout(func, arg) struct callout **copp, *freep; int reschedule = 0; - MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg)); + MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); /* * Find first matching timeout and remove it from the list. @@ -754,12 +813,7 @@ device_script(program, in, out) { int pid; int status; - sigset_t mask; - - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &mask); + int errfd; pid = fork(); @@ -769,11 +823,13 @@ device_script(program, in, out) } if (pid == 0) { - setreuid(getuid(), getuid()); - setregid(getgid(), getgid()); - sigprocmask(SIG_SETMASK, &mask, NULL); dup2(in, 0); dup2(out, 1); + errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644); + if (errfd >= 0) + dup2(errfd, 2); + setuid(getuid()); + setgid(getgid()); execl("/bin/sh", "sh", "-c", program, (char *)0); syslog(LOG_ERR, "could not exec /bin/sh: %m"); _exit(99); @@ -786,7 +842,6 @@ device_script(program, in, out) syslog(LOG_ERR, "error waiting for (dis)connection process: %m"); die(1); } - sigprocmask(SIG_SETMASK, &mask, NULL); return (status == 0 ? 0 : -1); } @@ -805,6 +860,7 @@ run_program(prog, args, must_exist) int must_exist; { int pid; + char *nullenv[1]; pid = fork(); if (pid == -1) { @@ -812,20 +868,22 @@ run_program(prog, args, must_exist) return -1; } if (pid == 0) { - int new_fd; + int new_fd; /* Leave the current location */ (void) setsid(); /* No controlling tty. */ - (void) umask (0); /* no umask. Must change in script. */ + (void) umask (S_IRWXG|S_IRWXO); (void) chdir ("/"); /* no current directory. */ + setuid(geteuid()); + setgid(getegid()); /* Ensure that nothing of our device environment is inherited. */ close (0); close (1); close (2); - close (s); /* Socket interface to the ppp device */ close (fd); /* tty interface to the ppp device */ - + /* XXX should call sysdep cleanup procedure here */ + /* Don't pass handles to the PPP device, even by accident. */ new_fd = open (_PATH_DEVNULL, O_RDWR); if (new_fd >= 0) { @@ -837,14 +895,17 @@ run_program(prog, args, must_exist) dup2 (0, 2); /* stderr -> /dev/null */ } +#ifdef BSD /* Force the priority back to zero if pppd is running higher. */ if (setpriority (PRIO_PROCESS, 0, 0) < 0) syslog (LOG_WARNING, "can't reset priority to 0: %m"); +#endif /* SysV recommends a second fork at this point. */ - /* run the program */ - execv(prog, args); + /* run the program; give it a null environment */ + nullenv[0] = NULL; + execve(prog, args, nullenv); if (must_exist || errno != ENOENT) syslog(LOG_WARNING, "Can't execute %s: %m", prog); _exit(-1);