X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fmain.c;h=51b5535b4102a8494166b779e0cd168cc1005f6a;hp=69cc5c4ee6a3fdf052ce793b3d3851f847515c57;hb=41bd52fb6047d183d77b914449006deb59425463;hpb=8ed8058b62ae72fba40f04c1dbd7f19e58ed500f diff --git a/pppd/main.c b/pppd/main.c index 69cc5c4..51b5535 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.21 1995/04/24 05:56:13 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.23.2.1 1995/06/01 07:01:31 paulus Exp $"; #endif #include @@ -65,8 +65,8 @@ 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 */ @@ -78,24 +78,28 @@ int kill_link; int open_ccp_flag; static int initfdflags = -1; /* Initial file descriptor flags */ +static int loop_fd = -1; /* fd for loopback device */ 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; +static int locked; + /* 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 holdoff_end __P((void *)); static void get_input __P((void)); -void establish_ppp __P((void)); +void establish_ppp __P((int)); void calltimeout __P((void)); struct timeval *timeleft __P((struct timeval *)); void reap_kids __P((void)); @@ -160,6 +164,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"); @@ -192,12 +197,27 @@ 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. */ sys_init(); magic_init(); + /* + * For dial-on-demand, we need to know the remote address. + */ + if (demand && ipcp_wantoptions[0].hisaddr == 0) { + fprintf(stderr, "Remote IP address must be specified for dial-on-demand\n"); + exit(1); + } + /* * Detach ourselves from the terminal, if required, * and identify who is running us. @@ -248,13 +268,72 @@ main(argc, argv) signal(SIGUSR2, open_ccp); /* Reopen CCP */ /* - * 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. + */ + loop_fd = open_loopback(); + establish_ppp(loop_fd); - do { + 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; + } + + /* + * 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; + fd = loop_fd; + 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. @@ -265,7 +344,7 @@ main(argc, argv) nonblock = (connector || !modem)? O_NONBLOCK: 0; if ((fd = open(devnam, nonblock | O_RDWR, 0)) < 0) { syslog(LOG_ERR, "Failed to open %s: %m", devnam); - die(1); + goto fail; } if ((initfdflags = fcntl(fd, F_GETFL)) == -1) { syslog(LOG_ERR, "Couldn't get device fd flags: %m"); @@ -295,32 +374,16 @@ main(argc, argv) if (device_script(connector, fd, fd) < 0) { syslog(LOG_ERR, "Connect script failed"); setdtr(fd, FALSE); - die(1); + goto fail; } - 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); - /* set up the serial device as a ppp interface */ - establish_ppp(); - - 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; - } - /* * Set device for non-blocking reads. */ @@ -329,8 +392,33 @@ main(argc, argv) die(1); } + if (!demand) { + /* set up the serial device as a ppp interface */ + establish_ppp(fd); + + 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; + } + + } else { + /* + * Transfer the PPP unit over to the real serial device. + */ + transfer_ppp(fd); + } + /* - * 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); @@ -354,36 +442,80 @@ 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) { + transfer_ppp(loop_fd); + } else { + disestablish_ppp(fd); + } + /* * 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) { + if (disconnector && !hungup) { 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..."); } + fail: close_fd(); - if (unlink(pidfilename) < 0 && errno != ENOENT) - syslog(LOG_WARNING, "unable to delete pid file: %m"); - pidfilename[0] = 0; + if (locked) { + unlock(); + locked = 0; + } - } while (persist); + if (!demand) { + if (unlink(pidfilename) < 0 && errno != ENOENT) + syslog(LOG_WARNING, "unable to delete pid file: %m"); + pidfilename[0] = 0; + } - if (lockflag && !default_device) - unlock(); + if (!persist) + break; - exit(0); + 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. @@ -402,7 +534,7 @@ get_input() return; if (len == 0) { - MAINDEBUG((LOG_DEBUG, "End of file on fd!")); + syslog(LOG_NOTICE, "Modem hangup"); hungup = 1; lcp_lowerdown(0); /* serial link is no longer available */ phase = PHASE_DEAD; @@ -513,8 +645,11 @@ cleanup(status, arg) syslog(LOG_WARNING, "unable to delete pid file: %m"); pidfilename[0] = 0; - if (lockflag && !default_device) + if (locked) unlock(); + + if (demand) + demand_reset(); } /* @@ -531,7 +666,7 @@ close_fd() syslog(LOG_WARNING, "Couldn't restore device fd flags: %m"); initfdflags = -1; - disestablish_ppp(); + disestablish_ppp(fd); restore_tty(); @@ -755,6 +890,7 @@ device_script(program, in, out) { int pid; int status; + int errfd; pid = fork(); @@ -764,10 +900,14 @@ device_script(program, in, out) } if (pid == 0) { - setuid(getuid()); - setgid(getgid()); + sys_close(); 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); @@ -816,11 +956,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 */ /* Don't pass handles to the PPP device, even by accident. */ new_fd = open (_PATH_DEVNULL, O_RDWR);