X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fmain.c;h=2b25753214ba0fdbecc86be80c884707c5c45727;hp=159ecfb983985e8e9a56e3f23d207afecf5026ce;hb=4b66bba66f111bdd72ae3f9ac99b88e023090ffa;hpb=1b024cb02056cc81b5e8a4eb3d02f50fc0bb4f5a diff --git a/pppd/main.c b/pppd/main.c index 159ecfb..2b25753 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -18,12 +18,13 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.29 1995/12/18 03:50:17 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.32 1996/04/04 03:59:33 paulus Exp $"; #endif #include #include #include +#include #include #include #include @@ -71,30 +72,31 @@ char *progname; /* Name of this program */ char hostname[MAXNAMELEN]; /* Our hostname */ 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 pid_t pid; /* Our pid */ static uid_t uid; /* Our real user-id */ -int fd = -1; /* Device file descriptor */ +int ttyfd = -1; /* Serial port file descriptor */ int phase; /* where the link is at */ int kill_link; int open_ccp_flag; u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */ -static u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ +u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ int hungup; /* terminal has been hung up */ static int n_children; /* # child processes still running */ int baud_rate; /* Actual bits/second for serial device */ +static int locked; /* lock() has succeeded */ + char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n"; /* Prototypes for procedures local to this file. */ static void cleanup __P((void)); -static void close_fd __P((void)); +static void close_tty __P((void)); static void get_input __P((void)); static void connect_time_expired __P((caddr_t)); static void calltimeout __P((void)); @@ -105,6 +107,7 @@ 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 holdoff_end __P((void *)); static int device_script __P((char *, int, int)); static void reap_kids __P((void)); static void pr_log __P((void *, char *, ...)); @@ -134,13 +137,13 @@ struct protent *protocols[] = { NULL }; +int main(argc, argv) int argc; char *argv[]; { int i, nonblock, fdflags; struct sigaction sa; - struct cmd *cmdp; FILE *pidfile; char *p; struct passwd *pw; @@ -172,21 +175,29 @@ main(argc, argv) progname = *argv; if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) || + !options_for_tty() || !options_from_user() || - !parse_args(argc-1, argv+1) || - !options_for_tty()) - die(1); + !parse_args(argc-1, argv+1)) + exit(1); if (!ppp_available()) { fprintf(stderr, no_ppp_msg); exit(1); } -#ifdef IPX_CHANGE - remove_sys_options(); -#endif /* IPX_CHANGE */ - check_auth_options(); - setipdefault(); + /* + * Check that the options given are valid and consistent. + */ + sys_check_options(); + auth_check_options(); + for (i = 0; (protp = protocols[i]) != NULL; ++i) + if (protp->check_options != NULL) + (*protp->check_options)(); + if (demand && connector == 0) { + fprintf(stderr, "%s: connect script required for demand-dialling\n", + progname); + exit(1); + } /* * If the user has specified the default device name explicitly, @@ -290,13 +301,70 @@ main(argc, argv) #endif /* - * Lock the device if we've been asked to. + * If we're doing dial-on-demand, set up the interface now. */ - if (lockflag && !default_device) - if (lock(devnam) < 0) - die(1); + if (demand) { + /* + * Open the loopback channel and set it up to be the ppp interface. + */ + open_ppp_loopback(); + + syslog(LOG_INFO, "Using interface ppp%d", ifunit); + (void) sprintf(ifname, "ppp%d", ifunit); - do { + /* write pid to file */ + (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); + if ((pidfile = fopen(pidfilename, "w")) != NULL) { + fprintf(pidfile, "%d\n", pid); + (void) fclose(pidfile); + } else { + syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename); + pidfilename[0] = 0; + } + + /* + * Configure the interface and mark it up, etc. + */ + demand_conf(); + } + + for (;;) { + + if (demand) { + /* + * Don't do anything until we see some activity. + */ + phase = PHASE_DORMANT; + kill_link = 0; + demand_unblock(); + for (;;) { + wait_loop_output(timeleft(&timo)); + calltimeout(); + if (kill_link) { + if (!persist) + die(0); + kill_link = 0; + } + if (get_loop_output()) + break; + reap_kids(); + } + + /* + * Now we want to bring up the link. + */ + demand_block(); + syslog(LOG_INFO, "Starting link"); + } + + /* + * Lock the device if we've been asked to. + */ + if (lockflag && !default_device) { + if (lock(devnam) < 0) + goto fail; + locked = 1; + } /* * Open the serial device and set it up to be the ppp interface. @@ -305,13 +373,13 @@ main(argc, argv) * the non-blocking I/O bit. */ nonblock = (connector || !modem)? O_NONBLOCK: 0; - if ((fd = open(devnam, nonblock | O_RDWR, 0)) < 0) { + if ((ttyfd = open(devnam, nonblock | O_RDWR, 0)) < 0) { syslog(LOG_ERR, "Failed to open %s: %m", devnam); - die(1); + goto fail; } if (nonblock) { - if ((fdflags = fcntl(fd, F_GETFL)) == -1 - || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) + if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 + || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) syslog(LOG_WARNING, "Couldn't reset non-blocking mode on device: %m"); } @@ -323,19 +391,19 @@ main(argc, argv) MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); /* set line speed, flow control, etc.; set CLOCAL for now */ - set_up_tty(fd, 1); + set_up_tty(ttyfd, 1); /* drop dtr to hang up in case modem is off hook */ if (!default_device && modem) { - setdtr(fd, FALSE); + setdtr(ttyfd, FALSE); sleep(1); - setdtr(fd, TRUE); + setdtr(ttyfd, TRUE); } - if (device_script(connector, fd, fd) < 0) { + if (device_script(connector, ttyfd, ttyfd) < 0) { syslog(LOG_ERR, "Connect script failed"); - setdtr(fd, FALSE); - die(1); + setdtr(ttyfd, FALSE); + goto fail; } syslog(LOG_INFO, "Serial connection established."); @@ -343,22 +411,32 @@ main(argc, argv) } /* set line speed, flow control, etc.; clear CLOCAL if modem option */ - set_up_tty(fd, 0); - - /* set up the serial device as a ppp interface */ - establish_ppp(); + set_up_tty(ttyfd, 0); - syslog(LOG_INFO, "Using interface ppp%d", ifunit); - (void) sprintf(ifname, "ppp%d", ifunit); + /* run welcome script, if any */ + if (welcomer && welcomer[0]) { + if (device_script(welcomer, ttyfd, ttyfd) < 0) + syslog(LOG_WARNING, "Welcome script failed"); + } - /* write pid to file */ - (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); - if ((pidfile = fopen(pidfilename, "w")) != NULL) { - fprintf(pidfile, "%d\n", pid); - (void) fclose(pidfile); - } else { - syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename); - pidfilename[0] = 0; + /* set up the serial device as a ppp interface */ + establish_ppp(ttyfd); + + if (!demand) { + + syslog(LOG_INFO, "Using interface ppp%d", ifunit); + (void) sprintf(ifname, "ppp%d", ifunit); + + /* write pid to file */ + (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); + if ((pidfile = fopen(pidfilename, "w")) != NULL) { + fprintf(pidfile, "%d\n", pid); + (void) fclose(pidfile); + } else { + syslog(LOG_ERR, "Failed to create pid file %s: %m", + pidfilename); + pidfilename[0] = 0; + } } /* @@ -369,7 +447,7 @@ main(argc, argv) TIMEOUT(connect_time_expired, 0, maxconnect); /* - * Block all signals, start opening the connection, and wait for + * Start opening the connection and wait for * incoming events (reply, timeout, etc.). */ syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); @@ -394,30 +472,76 @@ main(argc, argv) reap_kids(); /* Don't leave dead kids lying around */ } + /* + * If we may want to bring the link up again, transfer + * the ppp unit back to the loopback. Set the + * real serial device back to its normal mode of operation. + */ + clean_check(); + if (demand) + restore_loop(); + disestablish_ppp(ttyfd); + /* * Run disconnector script, if requested. * XXX we may not be able to do this if the line has hung up! */ - disestablish_ppp(); - if (disconnector) { - set_up_tty(fd, 1); - if (device_script(disconnector, fd, fd) < 0) { + if (disconnector && !hungup) { + set_up_tty(ttyfd, 1); + if (device_script(disconnector, ttyfd, ttyfd) < 0) { syslog(LOG_WARNING, "disconnect script failed"); } else { syslog(LOG_INFO, "Serial link disconnected."); } } - close_fd(); - if (unlink(pidfilename) < 0 && errno != ENOENT) - syslog(LOG_WARNING, "unable to delete pid file: %m"); - pidfilename[0] = 0; + fail: + close_tty(); + if (locked) { + unlock(); + locked = 0; + } + + if (!demand) { + if (unlink(pidfilename) < 0 && errno != ENOENT) + syslog(LOG_WARNING, "unable to delete pid file: %m"); + pidfilename[0] = 0; + } + + if (!persist) + break; - } while (persist); + if (demand) + demand_discard(); + if (holdoff > 0) { + phase = PHASE_HOLDOFF; + TIMEOUT(holdoff_end, NULL, holdoff); + do { + wait_time(timeleft(&timo)); + calltimeout(); + if (kill_link) { + if (!persist) + die(0); + kill_link = 0; + phase = PHASE_DORMANT; /* allow signal to end holdoff */ + } + reap_kids(); + } while (phase == PHASE_HOLDOFF); + } + } die(0); } +/* + * holdoff_end - called via a timeout when the holdoff period ends. + */ +static void +holdoff_end(arg) + void *arg; +{ + phase = PHASE_DORMANT; +} /* * get_input - called when incoming data is available. @@ -529,33 +653,39 @@ cleanup() { sys_cleanup(); - if (fd >= 0) - close_fd(); + if (ttyfd >= 0) + close_tty(); if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) syslog(LOG_WARNING, "unable to delete pid file: %m"); pidfilename[0] = 0; - if (lockflag && !default_device) + if (locked) unlock(); } /* - * close_fd - restore the terminal device and close it. + * close_tty - restore the terminal device and close it. */ static void -close_fd() +close_tty() { - disestablish_ppp(); + disestablish_ppp(ttyfd); /* drop dtr to hang up */ - if (modem) - setdtr(fd, FALSE); + if (modem) { + setdtr(ttyfd, FALSE); + /* + * This sleep is in case the serial port has CLOCAL set by default, + * and consequently will reassert DTR when we close the device. + */ + sleep(1); + } - restore_tty(); + restore_tty(ttyfd); - close(fd); - fd = -1; + close(ttyfd); + ttyfd = -1; } @@ -620,9 +750,7 @@ untimeout(func, arg) void (*func)(); caddr_t arg; { - struct itimerval itv; struct callout **copp, *freep; - int reschedule = 0; MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); @@ -796,6 +924,7 @@ device_script(program, in, out) } if (pid == 0) { + sys_close(); dup2(in, 0); dup2(out, 1); errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644); @@ -851,11 +980,11 @@ run_program(prog, args, must_exist) setgid(getegid()); /* Ensure that nothing of our device environment is inherited. */ + sys_close(); close (0); close (1); close (2); - close (fd); /* tty interface to the ppp device */ - /* XXX should call sysdep cleanup procedure here */ + close (ttyfd); /* tty interface to the ppp device */ /* Don't pass handles to the PPP device, even by accident. */ new_fd = open (_PATH_DEVNULL, O_RDWR);