/** * Start the npppd_ppp. * Set npppd_ppp#phy_context, npppd_ppp#send_packet, npppd_ppp#phy_close and * npppd_ppp#phy_info before call this function. */ void ppp_start(npppd_ppp *_this) { char label[512]; PPP_ASSERT(_this != NULL); PPP_ASSERT(_this->recv_packet != NULL); PPP_ASSERT(_this->send_packet != NULL); PPP_ASSERT(_this->phy_close != NULL); _this->start_time = time(NULL); _this->start_monotime = get_monosec(); /* log the lower layer information */ ppp_set_tunnel_label(_this, label, sizeof(label)); ppp_log(_this, LOG_INFO, "logtype=Started tunnel=%s(%s)", _this->phy_label, label); lcp_lowerup(&_this->lcp); }
void ppp_input_task(intptr_t exinf) { T_NET_BUF *input; T_PPP_PROTENT *proto; ID tskid; int_t ix; /* ポートを初期設定する */ syscall(serial_opn_por(HDLC_PORTID)); syscall(serial_ctl_por(HDLC_PORTID, IOCTL_FCSND | IOCTL_FCRCV)); get_tid(&tskid); #ifdef PPP_CFG_MODEM init_modem(); syslog(LOG_NOTICE, "[PPP INPUT:%d] started with modem on port %d.", tskid, HDLC_PORTID); #else /* of #ifdef PPP_CFG_MODEM */ syslog(LOG_NOTICE, "[PPP INPUT:%d] started on port %d.", tskid, HDLC_PORTID); #endif /* of #ifdef PPP_CFG_MODEM */ /* ネットワークタイマタスクを起動する */ syscall(act_tsk(NET_TIMER_TASK)); /* 上位プロトコルを初期化する */ for (ix = 0; (proto = protocols[ix]) != NULL; ix ++) if (proto->init != NULL) (*proto->init)(); lcp_lowerup(); lcp_open(PPP_OPEN_PASSIVE); /* PPP 出力タスクを起動する */ syscall(act_tsk(PPP_OUTPUT_TASK)); while (true) { if (tget_net_buf(&input, IF_PDU_SIZE, TMO_PPP_GET_NET_BUF) == E_OK) { while (HDLC_read(input, IF_PDU_SIZE) != E_OK) ; if (input->len > 0) { #ifdef PPP_IDLE_TIMEOUT wai_sem(SEM_IDLE_TIMEOUT); if (idle && ntohs(*GET_PPP_HDR(input)) != PPP_LCP) { untimeout((FP)idle_timeout, NULL); idle = false; } sig_sem(SEM_IDLE_TIMEOUT); #endif /* of #ifdef PPP_IDLE_TIMEOUT */ parse_input(input); } else syscall(rel_net_buf(input)); #ifdef PPP_IDLE_TIMEOUT wai_sem(SEM_IDLE_TIMEOUT); if (!idle && ppp_phase == PPP_PHASE_NETWORK) { timeout((FP)idle_timeout, NULL, PPP_IDLE_TIMEOUT); idle = true; } else if (idle && ppp_phase != PPP_PHASE_NETWORK) { untimeout((FP)idle_timeout, NULL); idle = false; } sig_sem(SEM_IDLE_TIMEOUT); #endif /* of #ifdef PPP_IDLE_TIMEOUT */ } else { HDLC_dummy_read(); NET_COUNT_PPP(net_count_ppp.in_err_packets, 1); NET_COUNT_PPP(net_count_ppp_no_bufs, 1); } } }
int main(int argc, char *argv[]) { int i, n, fdflags; struct sigaction sa; FILE *iffile; char *p; struct passwd *pw; struct timeval timo; sigset_t mask; struct protent *protp; struct stat statbuf; int connect_attempts = 0; char numbuf[16]; phase = PHASE_INITIALIZE; p = ttyname(0); if (p) strcpy(devnam, p); strcpy(default_devnam, devnam); script_env = NULL; /* Initialize syslog facilities */ #ifdef ULTRIX openlog("pppd", LOG_PID); #else openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); setlogmask(LOG_UPTO(LOG_INFO)); #endif if (gethostname(hostname, MAXNAMELEN) < 0 ) { option_error("Couldn't get hostname: %m"); die(1); } hostname[MAXNAMELEN-1] = 0; uid = getuid(); privileged = uid == 0; sprintf(numbuf, "%d", uid); script_setenv("UID", numbuf); /* * Initialize to the standard option set, then parse, in order, * the system options file, the user's options file, * the tty's options file, and the command line arguments. */ for (i = 0; (protp = protocols[i]) != NULL; ++i) (*protp->init)(0); progname = *argv; if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1) || !options_from_user()) exit(1); scan_args(argc-1, argv+1); /* look for tty name on command line */ if (!options_for_tty() || !parse_args(argc-1, argv+1)) exit(1); /* * Check that we are running as root. */ if (geteuid() != 0) { option_error("must be root to run %s, since it is not setuid-root", argv[0]); die(1); } if (!ppp_available()) { option_error(no_ppp_msg); exit(1); } /* * 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) { option_error("connect script required for demand-dialling\n"); exit(1); } script_setenv("DEVICE", devnam); sprintf(numbuf, "%d", baud_rate); script_setenv("SPEED", numbuf); /* * 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; if (default_device) nodetach = 1; /* * Initialize system-dependent stuff and magic number package. */ sys_init(); magic_init(); if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); /* * Detach ourselves from the terminal, if required, * and identify who is running us. */ if (nodetach == 0) detach(); pid = getpid(); p = getlogin(); stime = time(NULL); if (p == NULL) { pw = getpwuid(uid); if (pw != NULL && pw->pw_name != NULL) p = pw->pw_name; else p = "(unknown)"; } syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d", VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid); /* * Compute mask of all interesting signals and install signal handlers * for each. Only one signal handler may be active at a time. Therefore, * all other signals should be masked when any handler is executing. */ sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGCHLD); #define SIGNAL(s, handler) { \ sa.sa_handler = handler; \ if (sigaction(s, &sa, NULL) < 0) { \ syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \ die(1); \ } \ } sa.sa_mask = mask; sa.sa_flags = 0; SIGNAL(SIGHUP, hup); /* Hangup */ SIGNAL(SIGINT, term); /* Interrupt */ SIGNAL(SIGTERM, term); /* Terminate */ SIGNAL(SIGCHLD, chld); 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 /* * Apparently we can get a SIGPIPE when we call syslog, if * syslogd has died and been restarted. Ignoring it seems * be sufficient. */ signal(SIGPIPE, SIG_IGN); /* * If we're doing dial-on-demand, set up the interface now. */ 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); sprintf(ifname, "ppp%d", ifunit); script_setenv("IFNAME", ifname); create_pidfile(); /* write pid to file */ /* * Configure the interface and mark it up, etc. */ demand_conf(); } for (;;) { need_holdoff = 1; 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. * First we open it in non-blocking mode so we can set the * various termios flags appropriately. If we aren't dialling * out and we want to use the modem lines, we reopen it later * in order to wait for the carrier detect signal from the modem. */ while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) { if (errno != EINTR) syslog(LOG_ERR, "Failed to open %s: %m", devnam); if (!persist || errno != EINTR) goto fail; } 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"); hungup = 0; kill_link = 0; /* * Do the equivalent of `mesg n' to stop broadcast messages. */ if (fstat(ttyfd, &statbuf) < 0 || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) { syslog(LOG_WARNING, "Couldn't restrict write permissions to %s: %m", devnam); } else tty_mode = statbuf.st_mode; /* run connection script */ if (connector && connector[0]) { MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); /* * Set line speed, flow control, etc. * On most systems we set CLOCAL for now so that we can talk * to the modem before carrier comes up. But this has the * side effect that we might miss it if CD drops before we * get to clear CLOCAL below. On systems where we can talk * successfully to the modem with CLOCAL clear and CD down, * we can clear CLOCAL at this point. */ set_up_tty(ttyfd, 1); /* drop dtr to hang up in case modem is off hook */ if (!default_device && modem) { setdtr(ttyfd, FALSE); sleep(1); setdtr(ttyfd, TRUE); } if (device_script(connector, ttyfd, ttyfd) < 0) { syslog(LOG_ERR, "Connect script failed"); setdtr(ttyfd, FALSE); connect_attempts++; goto fail; } syslog(LOG_INFO, "Serial connection established."); sleep(1); /* give it time to set up its terminal */ } connect_attempts = 0; /* we made it through ok */ /* set line speed, flow control, etc.; clear CLOCAL if modem option */ set_up_tty(ttyfd, 0); /* reopen tty if necessary to wait for carrier */ if (connector == NULL && modem) { while ((i = open(devnam, O_RDWR)) < 0) { if (errno != EINTR) syslog(LOG_ERR, "Failed to reopen %s: %m", devnam); if (!persist || errno != EINTR || hungup || kill_link) goto fail; } close(i); } /* run welcome script, if any */ if (welcomer && welcomer[0]) { if (device_script(welcomer, ttyfd, ttyfd) < 0) syslog(LOG_WARNING, "Welcome script failed"); } /* set up the serial device as a ppp interface */ establish_ppp(ttyfd); if (!demand) { syslog(LOG_INFO, "Using interface ppp%d", ifunit); sprintf(ifname, "ppp%d", ifunit); create_pidfile(); /* write pid to file */ /* write interface unit number to file */ for (n = strlen(devnam); n > 0 ; n--) if (devnam[n] == '/') { n++; break; } sprintf(iffilename, "%s%s.if", _PATH_VARRUN, &devnam[n]); if ((iffile = fopen(iffilename, "w")) != NULL) { fprintf(iffile, "ppp%d\n", ifunit); fclose(iffile); } else { syslog(LOG_ERR, "Failed to create if file %s: %m", iffilename); iffilename[0] = 0; } script_setenv("IFNAME", ifname); } /* * Start opening the connection and wait for * incoming events (reply, timeout, etc.). */ syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); stime = time(NULL); lcp_lowerup(0); lcp_open(0); /* Start protocol */ for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) { wait_input(timeleft(&timo)); calltimeout(); get_input(); if (kill_link) { lcp_close(0, "User request"); kill_link = 0; } if (open_ccp_flag) { if (phase == PHASE_NETWORK) { ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ (*ccp_protent.open)(0); } open_ccp_flag = 0; } 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! */ 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."); } } fail: if (ttyfd >= 0) close_tty(); if (locked) { unlock(); locked = 0; } if (!demand) { if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) syslog(LOG_WARNING, "unable to delete pid file: %m"); pidfilename[0] = 0; if (iffile) if (unlink(iffilename) < 0 && errno != ENOENT) syslog(LOG_WARNING, "unable to delete if file: %m"); iffilename[0] = 0; } /* limit to retries? */ if (max_con_attempts) if (connect_attempts >= max_con_attempts) break; if (!persist) die(1); if (demand) demand_discard(); if (holdoff > 0 && need_holdoff) { 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); return 0; }
externC void cyg_pppd_main(CYG_ADDRWORD arg) { int i; struct timeval timo; struct protent *protp; int connect_attempts = 0; phase = PHASE_INITIALIZE; cyg_ppp_options_install( ((struct tty *)arg)->options ); for (i = 0; (protp = protocols[i]) != NULL; ++i) (*protp->init)(0); if (!ppp_available()) { option_error(no_ppp_msg); exit(1); } /* * Initialize system-dependent stuff and magic number package. */ sys_init(); magic_init(); if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); for (;;) { need_holdoff = 1; { Cyg_ErrNo err; while ((err = cyg_io_lookup(devnam, &tty_handle)) < 0) { if (err != 0) syslog(LOG_ERR, "Failed to open %s: %d", devnam,err); } #ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS if( modem ) { cyg_uint32 len = sizeof(ppp_tty.serial_callbacks); ppp_tty.serial_callbacks.fn = cyg_ppp_serial_callback; ppp_tty.serial_callbacks.priv = (CYG_ADDRWORD)&ppp_tty; err = cyg_io_set_config( tty_handle, CYG_IO_SET_CONFIG_SERIAL_STATUS_CALLBACK, &ppp_tty.serial_callbacks, &len); if( err != 0 ) { syslog(LOG_ERR, "cyg_io_set_config(serial callbacks): %d",err); die(1); } } #endif } hungup = 0; kill_link = 0; /* set line speed, flow control, etc.; clear CLOCAL if modem option */ set_up_tty(tty_handle, 0); #ifdef CYGPKG_PPP_CHAT if( script != NULL ) { if( !cyg_ppp_chat( devnam, script ) ) { connect_attempts++; goto fail; } } #endif #ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS if( modem ) { while( !ppp_tty.carrier_detected ) cyg_thread_delay(100); } #endif connect_attempts = 0; /* we made it through ok */ /* set up the serial device as a ppp interface */ establish_ppp(tty_handle); syslog(LOG_INFO, "Using interface ppp%d", ifunit); (void) sprintf(ifname, "ppp%d", ifunit); /* * Start opening the connection and wait for * incoming events (reply, timeout, etc.). */ syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); stime = time((time_t *) NULL); lcp_lowerup(0); lcp_open(0); /* Start protocol */ for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) { wait_input(timeleft(&timo)); calltimeout(); get_input(); if (kill_link) { lcp_close(0, "User request"); kill_link = 0; } if (open_ccp_flag) { if (phase == PHASE_NETWORK) { ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ (*ccp_protent.open)(0); } open_ccp_flag = 0; } } clean_check(); disestablish_ppp(tty_handle); #ifdef CYGPKG_PPP_CHAT fail: #endif if (tty_handle != 0) close_tty(); /* limit to retries? */ if (max_con_attempts) if (connect_attempts >= max_con_attempts) break; if (!persist) die(1); #if 0 if (holdoff > 0 && need_holdoff) { 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 */ } } while (phase == PHASE_HOLDOFF); } #endif } die(0); }
int pppdmain( int argc, char *argv[]) { int i, fdflags, t; char *connector; struct timeval timo; struct protent *protp; new_phase(PHASE_INITIALIZE); script_env = NULL; hostname[MAXNAMELEN-1] = 0; privileged = 1; privileged_option = 1; /* * Initialize magic number generator now so that protocols may * use magic numbers in initialization. */ magic_init(); #ifdef XXX_XXX /* moved code the the rtems_pppd_reset_options function */ /* * Initialize to the standard option set, then parse, in order, * the system options file, the user's options file, * the tty's options file, and the command line arguments. */ for (i = 0; (protp = protocols[i]) != NULL; ++i) (*protp->init)(0); #endif if (!ppp_available()) { option_error(no_ppp_msg); return(EXIT_NO_KERNEL_SUPPORT); } /* * Check that the options given are valid and consistent. */ if (!sys_check_options()) { return(EXIT_OPTION_ERROR); } if (!auth_check_options()) { return(EXIT_OPTION_ERROR); } for (i = 0; (protp = protocols[i]) != NULL; ++i) if (protp->check_options != NULL) (*protp->check_options)(); /* default holdoff to 0 if no connect script has been given */ if (connect_script == 0 && !holdoff_specified) holdoff = 0; if (default_device) nodetach = 1; /* * Initialize system-dependent stuff. */ sys_init(); /* if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); */ do_callback = 0; for (;;) { need_holdoff = 1; pppd_ttyfd = -1; real_ttyfd = -1; pppd_status = EXIT_OK; ++unsuccess; doing_callback = do_callback; do_callback = 0; new_phase(PHASE_SERIALCONN); /* * Get a pty master/slave pair if the pty, notty, or record * options were specified. */ strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); pty_master = -1; pty_slave = -1; /* * Open the serial device and set it up to be the ppp interface. * First we open it in non-blocking mode so we can set the * various termios flags appropriately. If we aren't dialling * out and we want to use the modem lines, we reopen it later * in order to wait for the carrier detect signal from the modem. */ hungup = 0; pppd_kill_link = 0; connector = doing_callback? callback_script: connect_script; if (devnam[0] != 0) { for (;;) { /* If the user specified the device name, become the user before opening it. */ int err; pppd_ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0); err = errno; if (pppd_ttyfd >= 0) { break; } errno = err; if (err != EINTR) { error("Failed to open %s: %m", devnam); pppd_status = EXIT_OPEN_FAILED; } if (!persist || err != EINTR) goto fail; } if ((fdflags = fcntl(pppd_ttyfd, F_GETFL)) == -1 || fcntl(pppd_ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) warn("Couldn't reset non-blocking mode on device: %m"); /* * Set line speed, flow control, etc. * If we have a non-null connection or initializer script, * on most systems we set CLOCAL for now so that we can talk * to the modem before carrier comes up. But this has the * side effect that we might miss it if CD drops before we * get to clear CLOCAL below. On systems where we can talk * successfully to the modem with CLOCAL clear and CD down, * we could clear CLOCAL at this point. */ set_up_tty(pppd_ttyfd, ((connector != NULL && connector[0] != 0) || initializer != NULL)); real_ttyfd = pppd_ttyfd; } /* run connection script */ if ((connector && connector[0]) || initializer) { if (real_ttyfd != -1) { /* XXX do this if doing_callback == CALLBACK_DIALIN? */ if (!default_device && modem) { setdtr(real_ttyfd, 0); /* in case modem is off hook */ sleep(1); setdtr(real_ttyfd, 1); } } if (initializer && initializer[0]) { if (device_script(pppd_ttyfd, DIALER_INIT, initializer) < 0) { error("Initializer script failed"); pppd_status = EXIT_INIT_FAILED; goto fail; } if (pppd_kill_link) goto disconnect; info("Serial port initialized."); } if (connector && connector[0]) { if (device_script(pppd_ttyfd, DIALER_CONNECT, connector) < 0) { error("Connect script failed"); pppd_status = EXIT_CONNECT_FAILED; goto fail; } if (pppd_kill_link) goto disconnect; info("Serial connection established."); } /* set line speed, flow control, etc.; clear CLOCAL if modem option */ if (real_ttyfd != -1) set_up_tty(real_ttyfd, 0); if (doing_callback == CALLBACK_DIALIN) connector = NULL; } /* reopen tty if necessary to wait for carrier */ if (connector == NULL && modem && devnam[0] != 0) { for (;;) { if ((i = open(devnam, O_RDWR)) >= 0) break; if (errno != EINTR) { error("Failed to reopen %s: %m", devnam); pppd_status = EXIT_OPEN_FAILED; } if (!persist || errno != EINTR || hungup || pppd_kill_link) goto fail; } close(i); } info("Serial connection established."); sleep(1); /* run welcome script, if any */ if (welcomer && welcomer[0]) { if (device_script(pppd_ttyfd, DIALER_WELCOME, welcomer) < 0) warn("Welcome script failed"); } /* set up the serial device as a ppp interface */ fd_ppp = establish_ppp(pppd_ttyfd); if (fd_ppp < 0) { pppd_status = EXIT_FATAL_ERROR; goto disconnect; } if (!demand) { info("Using interface ppp%d", pppifunit); slprintf(ifname, sizeof(ifname), "ppp%d", pppifunit); } /* * Start opening the connection and wait for * incoming events (reply, timeout, etc.). */ notice("Connect: %s <--> %s", ifname, ppp_devnam); gettimeofday(&start_time, NULL); lcp_lowerup(0); lcp_open(0); /* Start protocol */ open_ccp_flag = 0; pppd_status = EXIT_NEGOTIATION_FAILED; new_phase(PHASE_ESTABLISH); while (pppd_phase != PHASE_DEAD) { wait_input(timeleft(&timo)); calltimeout(); get_input(); if (pppd_kill_link) { lcp_close(0, "User request"); pppd_kill_link = 0; } if (open_ccp_flag) { if (pppd_phase == PHASE_NETWORK || pppd_phase == PHASE_RUNNING) { ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ (*ccp_protent.open)(0); } open_ccp_flag = 0; } } /* * 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(pppd_ttyfd); fd_ppp = -1; if (!hungup) lcp_lowerdown(0); /* * Run disconnector script, if requested. * XXX we may not be able to do this if the line has hung up! */ disconnect: if (disconnect_script && !hungup) { new_phase(PHASE_DISCONNECT); if (real_ttyfd >= 0) set_up_tty(real_ttyfd, 1); if (device_script(pppd_ttyfd, DIALER_DISCONNECT, disconnect_script) < 0) { warn("disconnect script failed"); } else { info("Serial link disconnected."); } } fail: if (pty_master >= 0) close(pty_master); if (pty_slave >= 0) close(pty_slave); if (real_ttyfd >= 0) close_tty(); if (!persist || (maxfail > 0 && unsuccess >= maxfail)) break; pppd_kill_link = 0; if (demand) demand_discard(); t = need_holdoff? holdoff: 0; if (holdoff_hook) t = (*holdoff_hook)(); if (t > 0) { new_phase(PHASE_HOLDOFF); TIMEOUT(holdoff_end, NULL, t); do { wait_input(timeleft(&timo)); calltimeout(); if (pppd_kill_link) { pppd_kill_link = 0; new_phase(PHASE_DORMANT); /* allow signal to end holdoff */ } } while (pppd_phase == PHASE_HOLDOFF); if (!persist) break; } } die(pppd_status); return pppd_status; }