📄 main.c
字号:
return; } /* * Until we get past the authentication phase, toss all packets * except LCP, LQR and authentication packets. */ if (phase <= PHASE_AUTHENTICATE && !(protocol == PPP_LCP || protocol == PPP_LQR || protocol == PPP_PAP || protocol == PPP_CHAP || protocol == PPP_EAP)) { dbglog("discarding proto 0x%x in phase %d", protocol, phase); return; } /* * Upcall the proper protocol input routine. */ for (i = 0; (protp = protocols[i]) != NULL; ++i) { if (protp->protocol == protocol && protp->enabled_flag) { (*protp->input)(0, p, len); return; } if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag && protp->datainput != NULL) { (*protp->datainput)(0, p, len); return; } } if (debug) { const char *pname = protocol_name(protocol); if (pname != NULL) warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); else warn("Unsupported protocol 0x%x received", protocol); } lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);}/* * ppp_send_config - configure the transmit-side characteristics of * the ppp interface. Returns -1, indicating an error, if the channel * send_config procedure called error() (or incremented error_count * itself), otherwise 0. */intppp_send_config(unit, mtu, accm, pcomp, accomp) int unit, mtu; u_int32_t accm; int pcomp, accomp;{ int errs; if (the_channel->send_config == NULL) return 0; errs = error_count; (*the_channel->send_config)(mtu, accm, pcomp, accomp); return (error_count != errs)? -1: 0;}/* * ppp_recv_config - configure the receive-side characteristics of * the ppp interface. Returns -1, indicating an error, if the channel * recv_config procedure called error() (or incremented error_count * itself), otherwise 0. */intppp_recv_config(unit, mru, accm, pcomp, accomp) int unit, mru; u_int32_t accm; int pcomp, accomp;{ int errs; if (the_channel->recv_config == NULL) return 0; errs = error_count; (*the_channel->recv_config)(mru, accm, pcomp, accomp); return (error_count != errs)? -1: 0;}/* * new_phase - signal the start of a new phase of pppd's operation. */voidnew_phase(p) int p;{ phase = p; if (new_phase_hook) (*new_phase_hook)(p); notify(phasechange, p);}/* * die - clean up state and exit with the specified status. */voiddie(status) int status;{ if (!doing_multilink || multilink_master) print_link_stats(); cleanup(); notify(exitnotify, status); syslog(LOG_INFO, "Exit."); exit(status);}/* * cleanup - restore anything which needs to be restored before we exit *//* ARGSUSED */static voidcleanup(){ sys_cleanup(); if (fd_ppp >= 0) the_channel->disestablish_ppp(devfd); if (the_channel->cleanup) (*the_channel->cleanup)(); remove_pidfiles();#ifdef USE_TDB if (pppdb != NULL) cleanup_db();#endif}voidprint_link_stats(){ /* * Print connect time and statistics. */ if (link_stats_valid) { int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ info("Connect time %d.%d minutes.", t/10, t%10); info("Sent %u bytes, received %u bytes.", link_stats.bytes_out, link_stats.bytes_in); link_stats_valid = 0; }}/* * reset_link_stats - "reset" stats when link goes up. */voidreset_link_stats(u) int u;{ if (!get_ppp_stats(u, &old_link_stats)) return; gettimeofday(&start_time, NULL);}/* * update_link_stats - get stats at link termination. */voidupdate_link_stats(u) int u;{ struct timeval now; char numbuf[32]; if (!get_ppp_stats(u, &link_stats) || gettimeofday(&now, NULL) < 0) return; link_connect_time = now.tv_sec - start_time.tv_sec; link_stats_valid = 1; link_stats.bytes_in -= old_link_stats.bytes_in; link_stats.bytes_out -= old_link_stats.bytes_out; link_stats.pkts_in -= old_link_stats.pkts_in; link_stats.pkts_out -= old_link_stats.pkts_out; slprintf(numbuf, sizeof(numbuf), "%u", link_connect_time); script_setenv("CONNECT_TIME", numbuf, 0); slprintf(numbuf, sizeof(numbuf), "%u", link_stats.bytes_out); script_setenv("BYTES_SENT", numbuf, 0); slprintf(numbuf, sizeof(numbuf), "%u", link_stats.bytes_in); script_setenv("BYTES_RCVD", numbuf, 0);}struct callout { struct timeval c_time; /* time at which to call routine */ void *c_arg; /* argument to routine */ void (*c_func) __P((void *)); /* routine */ struct callout *c_next;};static struct callout *callout = NULL; /* Callout list */static struct timeval timenow; /* Current time *//* * timeout - Schedule a timeout. */voidtimeout(func, arg, secs, usecs) void (*func) __P((void *)); void *arg; int secs, usecs;{ struct callout *newp, *p, **pp; /* * Allocate timeout. */ if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) fatal("Out of memory in timeout()!"); newp->c_arg = arg; newp->c_func = func; gettimeofday(&timenow, NULL); newp->c_time.tv_sec = timenow.tv_sec + secs; newp->c_time.tv_usec = timenow.tv_usec + usecs; if (newp->c_time.tv_usec >= 1000000) { newp->c_time.tv_sec += newp->c_time.tv_usec / 1000000; newp->c_time.tv_usec %= 1000000; } /* * Find correct place and link it in. */ for (pp = &callout; (p = *pp); pp = &p->c_next) 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_usec)) break; newp->c_next = p; *pp = newp;}/* * untimeout - Unschedule a timeout. */voiduntimeout(func, arg) void (*func) __P((void *)); void *arg;{ struct callout **copp, *freep; /* * Find first matching timeout and remove it from the list. */ for (copp = &callout; (freep = *copp); copp = &freep->c_next) if (freep->c_func == func && freep->c_arg == arg) { *copp = freep->c_next; free((char *) freep); break; }}/* * calltimeout - Call any timeout routines which are now due. */static voidcalltimeout(){ struct callout *p; while (callout != NULL) { p = callout; if (gettimeofday(&timenow, NULL) < 0) fatal("Failed to get time of day: %m"); if (!(p->c_time.tv_sec < timenow.tv_sec || (p->c_time.tv_sec == timenow.tv_sec && p->c_time.tv_usec <= timenow.tv_usec))) break; /* no, it's not time yet */ callout = p->c_next; (*p->c_func)(p->c_arg); free((char *) p); }}/* * timeleft - return the length of time until the next timeout is due. */static struct timeval *timeleft(tvp) struct timeval *tvp;{ if (callout == NULL) return NULL; gettimeofday(&timenow, NULL); tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec; tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec; if (tvp->tv_usec < 0) { tvp->tv_usec += 1000000; tvp->tv_sec -= 1; } if (tvp->tv_sec < 0) tvp->tv_sec = tvp->tv_usec = 0; return tvp;}/* * kill_my_pg - send a signal to our process group, and ignore it ourselves. * We assume that sig is currently blocked. */static voidkill_my_pg(sig) int sig;{ struct sigaction act, oldact; sigemptyset(&act.sa_mask); /* unnecessary in fact */ act.sa_handler = SIG_IGN; act.sa_flags = 0; kill(0, sig); /* * The kill() above made the signal pending for us, as well as * the rest of our process group, but we don't want it delivered * to us. It is blocked at the moment. Setting it to be ignored * will cause the pending signal to be discarded. If we did the * kill() after setting the signal to be ignored, it is unspecified * (by POSIX) whether the signal is immediately discarded or left * pending, and in fact Linux would leave it pending, and so it * would be delivered after the current signal handler exits, * leading to an infinite loop. */ sigaction(sig, &act, &oldact); sigaction(sig, &oldact, NULL);}/* * hup - Catch SIGHUP signal. * * Indicates that the physical layer has been disconnected. * We don't rely on this indication; if the user has sent this * signal, we just take the link down. */static voidhup(sig) int sig;{ /* can't log a message here, it can deadlock */ got_sighup = 1; if (conn_running) /* Send the signal to the [dis]connector process(es) also */ kill_my_pg(sig); notify(sigreceived, sig); if (waiting) siglongjmp(sigjmp, 1);}/* * term - Catch SIGTERM signal and SIGINT signal (^C/del). * * Indicates that we should initiate a graceful disconnect and exit. *//*ARGSUSED*/static voidterm(sig) int sig;{ /* can't log a message here, it can deadlock */ got_sigterm = sig; if (conn_running) /* Send the signal to the [dis]connector process(es) also */ kill_my_pg(sig); notify(sigreceived, sig); if (waiting) siglongjmp(sigjmp, 1);}/* * chld - Catch SIGCHLD signal. * Sets a flag so we will call reap_kids in the mainline. */static voidchld(sig) int sig;{ got_sigchld = 1; if (waiting) siglongjmp(sigjmp, 1);}/* * toggle_debug - Catch SIGUSR1 signal. * * Toggle debug flag. *//*ARGSUSED*/static voidtoggle_debug(sig) int sig;{ debug = !debug; if (debug) { setlogmask(LOG_UPTO(LOG_DEBUG)); } else { setlogmask(LOG_UPTO(LOG_WARNING)); }}/* * open_ccp - Catch SIGUSR2 signal. * * Try to (re)negotiate compression. *//*ARGSUSED*/static voidopen_ccp(sig) int sig;{ got_sigusr2 = 1; if (waiting) siglongjmp(sigjmp, 1);}/* * bad_signal - We've caught a fatal signal. Clean up state and exit. */static voidbad_signal(sig) int sig;{ static int crashed = 0; if (crashed) _exit(127); crashed = 1; error("Fatal signal %d", sig); if (conn_running) kill_my_pg(SIGTERM); notify(sigreceived, sig); die(127);}/* * safe_fork - Create a child process. The child closes all the * file descriptors that we don't want to leak to a script. * The parent waits for the child to do this before returning. * This also arranges for the specified fds to be dup'd to * fds 0, 1, 2 in the child. */pid_tsafe_fork(int infd, int outfd, int errfd){ pid_t pid; int fd, pipefd[2]; char buf[1]; /* make sure fds 0, 1, 2 are occupied (probably not necessary) */ while ((fd = dup(fd_devnull)) >= 0) { if (fd > 2) { close(fd); break; } } if (pipe(pipefd) == -1) pipefd[0] = pipefd[1] = -1; pid = fork(); if (pid < 0) { error("fork failed: %m"); return -1; } if (pid > 0) { /* parent */ close(pipefd[1]); /* this read() blocks until the close(pipefd[1]) below */ complete_read(pipefd[0], buf, 1); close(pipefd[0]); return pid; } /* Executing in the child */ sys_close();#ifdef USE_TDB tdb_close(pppdb);#endif /* make sure infd, outfd and errfd won't get tromped on below */ if (infd == 1 || infd == 2) infd = dup(infd); if (outfd == 0 || outfd == 2) outfd = dup(outfd); if (errfd == 0 || errfd == 1) errfd = dup(errfd); /* dup the in, out, err fds to 0, 1, 2 */ if (infd != 0) dup2(infd, 0); if (outfd != 1) dup2(outfd, 1); if (errfd != 2) dup2(errfd, 2); closelog(); if (log_to_fd > 2) close(log_to_fd); if (the_channel->close) (*the_channel->close)(); else close(devfd); /* some plugins don't have a close function */ close(fd_ppp); close(fd_devnull); if (infd != 0) close(infd); if (outfd != 1) close(outfd); if (errfd != 2) close(errfd); notify(fork_notifier, 0); close(pipefd[0]); /* this close unblocks the read() call above in the parent */ close(pipefd[1]); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -