📄 main.c
字号:
gettimeofday(&start_time, NULL); script_unsetenv("CONNECT_TIME"); script_unsetenv("BYTES_SENT"); script_unsetenv("BYTES_RCVD"); lcp_open(0); /* Start protocol */ start_link(0); while (phase != PHASE_DEAD) { handle_events(); get_input(); if (kill_link) lcp_close(0, "User request"); if (asked_to_quit) { bundle_terminating = 1; if (phase == PHASE_MASTER) mp_bundle_terminated(); } if (open_ccp_flag) { if (phase == PHASE_NETWORK || phase == PHASE_RUNNING) { ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ (*ccp_protent.open)(0); } } } /* restore FSMs to original state */ lcp_close(0, ""); if (!persist || asked_to_quit || (maxfail > 0 && unsuccess >= maxfail)) break; 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 { handle_events(); if (kill_link) new_phase(PHASE_DORMANT); /* allow signal to end holdoff */ } while (phase == PHASE_HOLDOFF); if (!persist) break; } } /* Wait for scripts to finish */ reap_kids(); if (n_children > 0) { if (child_wait > 0) TIMEOUT(childwait_end, NULL, child_wait); if (debug) { struct subprocess *chp; dbglog("Waiting for %d child processes...", n_children); for (chp = children; chp != NULL; chp = chp->next) dbglog(" script %s, pid %d", chp->prog, chp->pid); } while (n_children > 0 && !childwait_done) { handle_events(); if (kill_link && !childwait_done) childwait_end(NULL); } } die(status); return 0;}/* * handle_events - wait for something to happen and respond to it. */static voidhandle_events(){ struct timeval timo; kill_link = open_ccp_flag = 0; if (sigsetjmp(sigjmp, 1) == 0) { sigprocmask(SIG_BLOCK, &signals_handled, NULL); if (got_sighup || got_sigterm || got_sigusr2 || got_sigchld) { sigprocmask(SIG_UNBLOCK, &signals_handled, NULL); } else { waiting = 1; sigprocmask(SIG_UNBLOCK, &signals_handled, NULL); wait_input(timeleft(&timo)); } } waiting = 0; calltimeout(); if (got_sighup) { info("Hangup (SIGHUP)"); kill_link = 1; got_sighup = 0; if (status != EXIT_HANGUP) status = EXIT_USER_REQUEST; } if (got_sigterm) { info("Terminating on signal %d", got_sigterm); kill_link = 1; asked_to_quit = 1; persist = 0; status = EXIT_USER_REQUEST; got_sigterm = 0; } if (got_sigchld) { got_sigchld = 0; reap_kids(); /* Don't leave dead kids lying around */ } if (got_sigusr2) { open_ccp_flag = 1; got_sigusr2 = 0; }}/* * setup_signals - initialize signal handling. */static voidsetup_signals(){ struct sigaction sa; /* * 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(&signals_handled); sigaddset(&signals_handled, SIGHUP); sigaddset(&signals_handled, SIGINT); sigaddset(&signals_handled, SIGTERM); sigaddset(&signals_handled, SIGCHLD); sigaddset(&signals_handled, SIGUSR2);#define SIGNAL(s, handler) do { \ sa.sa_handler = handler; \ if (sigaction(s, &sa, NULL) < 0) \ fatal("Couldn't establish signal handler (%d): %m", s); \ } while (0) sa.sa_mask = signals_handled; 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);}/* * set_ifunit - do things we need to do once we know which ppp * unit we are using. */voidset_ifunit(iskey) int iskey;{ info("Using interface %s%d", PPP_DRV_NAME, ifunit); slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit); script_setenv("IFNAME", ifname, iskey); if (iskey) { create_pidfile(getpid()); /* write pid to file */ create_linkpidfile(getpid()); }}/* * detach - detach us from the controlling terminal. */voiddetach(){ int pid; char numbuf[16]; int pipefd[2]; if (detached) return; if (pipe(pipefd) == -1) pipefd[0] = pipefd[1] = -1; if ((pid = fork()) < 0) { error("Couldn't detach (fork failed: %m)"); die(1); /* or just return? */ } if (pid != 0) { /* parent */ notify(pidchange, pid); /* update pid files if they have been written already */ if (pidfilename[0]) create_pidfile(pid); if (linkpidfile[0]) create_linkpidfile(pid); exit(0); /* parent dies */ } setsid(); chdir("/"); dup2(fd_devnull, 0); dup2(fd_devnull, 1); dup2(fd_devnull, 2); detached = 1; if (log_default) log_to_fd = -1; slprintf(numbuf, sizeof(numbuf), "%d", getpid()); script_setenv("PPPD_PID", numbuf, 1); /* wait for parent to finish updating pid & lock files and die */ close(pipefd[1]); complete_read(pipefd[0], numbuf, 1); close(pipefd[0]);}/* * reopen_log - (re)open our connection to syslog. */voidreopen_log(){ openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); setlogmask(LOG_UPTO(LOG_INFO));}/* * Create a file containing our process ID. */static voidcreate_pidfile(pid) int pid;{ FILE *pidfile; slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid", _PATH_VARRUN, ifname); if ((pidfile = fopen(pidfilename, "w")) != NULL) { fprintf(pidfile, "%d\n", pid); (void) fclose(pidfile); } else { error("Failed to create pid file %s: %m", pidfilename); pidfilename[0] = 0; }}voidcreate_linkpidfile(pid) int pid;{ FILE *pidfile; if (linkname[0] == 0) return; script_setenv("LINKNAME", linkname, 1); slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid", _PATH_VARRUN, linkname); if ((pidfile = fopen(linkpidfile, "w")) != NULL) { fprintf(pidfile, "%d\n", pid); if (ifname[0]) fprintf(pidfile, "%s\n", ifname); (void) fclose(pidfile); } else { error("Failed to create pid file %s: %m", linkpidfile); linkpidfile[0] = 0; }}/* * remove_pidfile - remove our pid files */void remove_pidfiles(){ if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) warn("unable to delete pid file %s: %m", pidfilename); pidfilename[0] = 0; if (linkpidfile[0] != 0 && unlink(linkpidfile) < 0 && errno != ENOENT) warn("unable to delete pid file %s: %m", linkpidfile); linkpidfile[0] = 0;}/* * holdoff_end - called via a timeout when the holdoff period ends. */static voidholdoff_end(arg) void *arg;{ new_phase(PHASE_DORMANT);}/* List of protocol names, to make our messages a little more informative. */struct protocol_list { u_short proto; const char *name;} protocol_list[] = { { 0x21, "IP" }, { 0x23, "OSI Network Layer" }, { 0x25, "Xerox NS IDP" }, { 0x27, "DECnet Phase IV" }, { 0x29, "Appletalk" }, { 0x2b, "Novell IPX" }, { 0x2d, "VJ compressed TCP/IP" }, { 0x2f, "VJ uncompressed TCP/IP" }, { 0x31, "Bridging PDU" }, { 0x33, "Stream Protocol ST-II" }, { 0x35, "Banyan Vines" }, { 0x39, "AppleTalk EDDP" }, { 0x3b, "AppleTalk SmartBuffered" }, { 0x3d, "Multi-Link" }, { 0x3f, "NETBIOS Framing" }, { 0x41, "Cisco Systems" }, { 0x43, "Ascom Timeplex" }, { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, { 0x47, "DCA Remote Lan" }, { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, { 0x4b, "SNA over 802.2" }, { 0x4d, "SNA" }, { 0x4f, "IP6 Header Compression" }, { 0x51, "KNX Bridging Data" }, { 0x53, "Encryption" }, { 0x55, "Individual Link Encryption" }, { 0x57, "IPv6" }, { 0x59, "PPP Muxing" }, { 0x5b, "Vendor-Specific Network Protocol" }, { 0x61, "RTP IPHC Full Header" }, { 0x63, "RTP IPHC Compressed TCP" }, { 0x65, "RTP IPHC Compressed non-TCP" }, { 0x67, "RTP IPHC Compressed UDP 8" }, { 0x69, "RTP IPHC Compressed RTP 8" }, { 0x6f, "Stampede Bridging" }, { 0x73, "MP+" }, { 0xc1, "NTCITS IPI" }, { 0xfb, "single-link compression" }, { 0xfd, "Compressed Datagram" }, { 0x0201, "802.1d Hello Packets" }, { 0x0203, "IBM Source Routing BPDU" }, { 0x0205, "DEC LANBridge100 Spanning Tree" }, { 0x0207, "Cisco Discovery Protocol" }, { 0x0209, "Netcs Twin Routing" }, { 0x020b, "STP - Scheduled Transfer Protocol" }, { 0x020d, "EDP - Extreme Discovery Protocol" }, { 0x0211, "Optical Supervisory Channel Protocol" }, { 0x0213, "Optical Supervisory Channel Protocol" }, { 0x0231, "Luxcom" }, { 0x0233, "Sigma Network Systems" }, { 0x0235, "Apple Client Server Protocol" }, { 0x0281, "MPLS Unicast" }, { 0x0283, "MPLS Multicast" }, { 0x0285, "IEEE p1284.4 standard - data packets" }, { 0x0287, "ETSI TETRA Network Protocol Type 1" }, { 0x0289, "Multichannel Flow Treatment Protocol" }, { 0x2063, "RTP IPHC Compressed TCP No Delta" }, { 0x2065, "RTP IPHC Context State" }, { 0x2067, "RTP IPHC Compressed UDP 16" }, { 0x2069, "RTP IPHC Compressed RTP 16" }, { 0x4001, "Cray Communications Control Protocol" }, { 0x4003, "CDPD Mobile Network Registration Protocol" }, { 0x4005, "Expand accelerator protocol" }, { 0x4007, "ODSICP NCP" }, { 0x4009, "DOCSIS DLL" }, { 0x400B, "Cetacean Network Detection Protocol" }, { 0x4021, "Stacker LZS" }, { 0x4023, "RefTek Protocol" }, { 0x4025, "Fibre Channel" }, { 0x4027, "EMIT Protocols" }, { 0x405b, "Vendor-Specific Protocol (VSP)" }, { 0x8021, "Internet Protocol Control Protocol" }, { 0x8023, "OSI Network Layer Control Protocol" }, { 0x8025, "Xerox NS IDP Control Protocol" }, { 0x8027, "DECnet Phase IV Control Protocol" }, { 0x8029, "Appletalk Control Protocol" }, { 0x802b, "Novell IPX Control Protocol" }, { 0x8031, "Bridging NCP" }, { 0x8033, "Stream Protocol Control Protocol" }, { 0x8035, "Banyan Vines Control Protocol" }, { 0x803d, "Multi-Link Control Protocol" }, { 0x803f, "NETBIOS Framing Control Protocol" }, { 0x8041, "Cisco Systems Control Protocol" }, { 0x8043, "Ascom Timeplex" }, { 0x8045, "Fujitsu LBLB Control Protocol" }, { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, { 0x804b, "SNA over 802.2 Control Protocol" }, { 0x804d, "SNA Control Protocol" }, { 0x804f, "IP6 Header Compression Control Protocol" }, { 0x8051, "KNX Bridging Control Protocol" }, { 0x8053, "Encryption Control Protocol" }, { 0x8055, "Individual Link Encryption Control Protocol" }, { 0x8057, "IPv6 Control Protovol" }, { 0x8059, "PPP Muxing Control Protocol" }, { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, { 0x806f, "Stampede Bridging Control Protocol" }, { 0x8073, "MP+ Control Protocol" }, { 0x80c1, "NTCITS IPI Control Protocol" }, { 0x80fb, "Single Link Compression Control Protocol" }, { 0x80fd, "Compression Control Protocol" }, { 0x8207, "Cisco Discovery Protocol Control" }, { 0x8209, "Netcs Twin Routing" }, { 0x820b, "STP - Control Protocol" }, { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, { 0x8235, "Apple Client Server Protocol Control" }, { 0x8281, "MPLSCP" }, { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, { 0x8289, "Multichannel Flow Treatment Protocol" }, { 0xc021, "Link Control Protocol" }, { 0xc023, "Password Authentication Protocol" }, { 0xc025, "Link Quality Report" }, { 0xc027, "Shiva Password Authentication Protocol" }, { 0xc029, "CallBack Control Protocol (CBCP)" }, { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, { 0xc02d, "BAP" }, { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, { 0xc081, "Container Control Protocol" }, { 0xc223, "Challenge Handshake Authentication Protocol" }, { 0xc225, "RSA Authentication Protocol" }, { 0xc227, "Extensible Authentication Protocol" }, { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, { 0xc26f, "Stampede Bridging Authorization Protocol" }, { 0xc281, "Proprietary Authentication Protocol" }, { 0xc283, "Proprietary Authentication Protocol" }, { 0xc481, "Proprietary Node ID Authentication Protocol" }, { 0, NULL },};/* * protocol_name - find a name for a PPP protocol. */const char *protocol_name(proto) int proto;{ struct protocol_list *lp; for (lp = protocol_list; lp->proto != 0; ++lp) if (proto == lp->proto) return lp->name; return NULL;}/* * get_input - called when incoming data is available. */static voidget_input(){ int len, i; u_char *p; u_short protocol; struct protent *protp; p = inpacket_buf; /* point to beginning of packet buffer */ len = read_packet(inpacket_buf); if (len < 0) return; if (len == 0) { if (bundle_eof && multilink_master) { notice("Last channel has disconnected"); mp_bundle_terminated(); return; } notice("Modem hangup"); hungup = 1; status = EXIT_HANGUP; lcp_lowerdown(0); /* serial link is no longer available */ link_terminated(0); return; } if (len < PPP_HDRLEN) { dbglog("received short packet:%.*B", len, p); return; } dump_packet("rcvd", p, len); if (snoop_recv_hook) snoop_recv_hook(p, len); 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) { dbglog("Discarded non-LCP packet when LCP not open");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -