📄 main.c
字号:
/* * main.c - Point-to-Point Protocol main module * * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The name "Carnegie Mellon University" must not be used to * endorse or promote products derived from this software without * prior written permission. For permission or any legal * details, please contact * Office of Technology Transfer * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, PA 15213-3890 * (412) 268-4387, fax: (412) 268-7395 * tech-transfer@andrew.cmu.edu * * 4. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Computing Services * at Carnegie Mellon University (http://www.cmu.edu/computing/)." * * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Copyright (c) 1999-2004 Paul Mackerras. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. The name(s) of the authors of this software must not be used to * endorse or promote products derived from this software without * prior written permission. * * 3. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Paul Mackerras * <paulus@samba.org>". * * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#define RCSID "$Id: main.c,v 1.153 2006/06/04 03:52:50 paulus Exp $"#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <errno.h>#include <fcntl.h>#include <syslog.h>#include <netdb.h>#include <utmp.h>#include <pwd.h>#include <setjmp.h>#include <sys/param.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include "pppd.h"#include "magic.h"#include "fsm.h"#include "lcp.h"#include "ipcp.h"#ifdef INET6#include "ipv6cp.h"#endif#include "upap.h"#include "chap-new.h"#include "eap.h"#include "ccp.h"#include "ecp.h"#include "pathnames.h"#ifdef USE_TDB#include "tdb.h"#endif#ifdef CBCP_SUPPORT#include "cbcp.h"#endif#ifdef IPX_CHANGE#include "ipxcp.h"#endif /* IPX_CHANGE */#ifdef AT_CHANGE#include "atcp.h"#endifstatic const char rcsid[] = RCSID;/* interface vars */char ifname[32]; /* Interface name */int ifunit; /* Interface unit number */struct channel *the_channel;char *progname; /* Name of this program */char hostname[MAXNAMELEN]; /* Our hostname */static char pidfilename[MAXPATHLEN]; /* name of pid file */static char linkpidfile[MAXPATHLEN]; /* name of linkname pid file */char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */uid_t uid; /* Our real user-id */struct notifier *pidchange = NULL;struct notifier *phasechange = NULL;struct notifier *exitnotify = NULL;struct notifier *sigreceived = NULL;struct notifier *fork_notifier = NULL;int hungup; /* terminal has been hung up */int privileged; /* we're running as real uid root */int need_holdoff; /* need holdoff period before restarting */int detached; /* have detached from terminal */volatile int status; /* exit status for pppd */int unsuccess; /* # unsuccessful connection attempts */int do_callback; /* != 0 if we should do callback next */int doing_callback; /* != 0 if we are doing callback */int ppp_session_number; /* Session number, for channels with such a concept (eg PPPoE) */int childwait_done; /* have timed out waiting for children */#ifdef USE_TDBTDB_CONTEXT *pppdb; /* database for storing status etc. */#endifchar db_key[32];int (*holdoff_hook) __P((void)) = NULL;int (*new_phase_hook) __P((int)) = NULL;void (*snoop_recv_hook) __P((unsigned char *p, int len)) = NULL;void (*snoop_send_hook) __P((unsigned char *p, int len)) = NULL;static int conn_running; /* we have a [dis]connector running */static int fd_loop; /* fd for getting demand-dial packets */int fd_devnull; /* fd for /dev/null */int devfd = -1; /* fd of underlying device */int fd_ppp = -1; /* fd for talking PPP */int phase; /* where the link is at */int kill_link;int asked_to_quit;int open_ccp_flag;int listen_time;int got_sigusr2;int got_sigterm;int got_sighup;static sigset_t signals_handled;static int waiting;static sigjmp_buf sigjmp;char **script_env; /* Env. variable values for scripts */int s_env_nalloc; /* # words avail at script_env */u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */static int n_children; /* # child processes still running */static int got_sigchld; /* set if we have received a SIGCHLD */int privopen; /* don't lock, open device as root */char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";GIDSET_TYPE groups[NGROUPS_MAX];/* groups the user is in */int ngroups; /* How many groups valid in groups */static struct timeval start_time; /* Time when link was started. */static struct pppd_stats old_link_stats;struct pppd_stats link_stats;unsigned link_connect_time;int link_stats_valid;int error_count;bool bundle_eof;bool bundle_terminating;/* * We maintain a list of child process pids and * functions to call when they exit. */struct subprocess { pid_t pid; char *prog; void (*done) __P((void *)); void *arg; struct subprocess *next;};static struct subprocess *children;/* Prototypes for procedures local to this file. */static void setup_signals __P((void));static void create_pidfile __P((int pid));static void create_linkpidfile __P((int pid));static void cleanup __P((void));static void get_input __P((void));static void calltimeout __P((void));static struct timeval *timeleft __P((struct timeval *));static void kill_my_pg __P((int));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 bad_signal __P((int));static void holdoff_end __P((void *));static void forget_child __P((int pid, int status));static int reap_kids __P((void));static void childwait_end __P((void *));#ifdef USE_TDBstatic void update_db_entry __P((void));static void add_db_key __P((const char *));static void delete_db_key __P((const char *));static void cleanup_db __P((void));#endifstatic void handle_events __P((void));void print_link_stats __P((void));extern char *ttyname __P((int));extern char *getlogin __P((void));int main __P((int, char *[]));#ifdef ultrix#undef O_NONBLOCK#define O_NONBLOCK O_NDELAY#endif#ifdef ULTRIX#define setlogmask(x)#endif/* * PPP Data Link Layer "protocol" table. * One entry per supported protocol. * The last entry must be NULL. */struct protent *protocols[] = { &lcp_protent, &pap_protent, //&chap_protent,#ifdef CBCP_SUPPORT &cbcp_protent,#endif &ipcp_protent,#ifdef INET6 &ipv6cp_protent,#endif &ccp_protent, //&ecp_protent,#ifdef IPX_CHANGE &ipxcp_protent,#endif#ifdef AT_CHANGE &atcp_protent,#endif //&eap_protent, NULL};/* * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name. */#if !defined(PPP_DRV_NAME)#define PPP_DRV_NAME "ppp"#endif /* !defined(PPP_DRV_NAME) */intmain(argc, argv) int argc; char *argv[];{ int i, t; char *p; struct passwd *pw; struct protent *protp; char numbuf[16]; link_stats_valid = 0; new_phase(PHASE_INITIALIZE); script_env = NULL; /* Initialize syslog facilities */ reopen_log(); if (gethostname(hostname, MAXNAMELEN) < 0 ) { option_error("Couldn't get hostname: %m"); exit(1); } hostname[MAXNAMELEN-1] = 0; /* make sure we don't create world or group writable files. */ umask(umask(0777) | 022); uid = getuid(); privileged = uid == 0; slprintf(numbuf, sizeof(numbuf), "%d", uid); script_setenv("ORIG_UID", numbuf, 0); ngroups = getgroups(NGROUPS_MAX, groups); /* * Initialize magic number generator now so that protocols may * use magic numbers in initialization. */ magic_init(); /* * Initialize each protocol. */ for (i = 0; (protp = protocols[i]) != NULL; ++i) (*protp->init)(0); /* * Initialize the default channel. */ tty_init(); progname = *argv; /* * Parse, in order, the system options file, the user's options file, * and the command line arguments. */ /*/if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1) || !options_from_user() || !parse_args(argc-1, argv+1)) exit(EXIT_OPTION_ERROR);*/ strncpy(user,argv[4],MAXNAMELEN); strncpy(passwd,argv[6],MAXSECRETLEN); ptycommand = malloc(strlen(argv[2])); strncpy(ptycommand,argv[2],strlen(argv[2])); devnam_fixed = 1; /* can no longer change device name */ /* * Work out the device name, if it hasn't already been specified, * and parse the tty's options file. */ if (the_channel->process_extra_options) (*the_channel->process_extra_options)(); if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); /* * 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]); exit(EXIT_NOT_ROOT); } if (!ppp_available()) { option_error("%s", no_ppp_msg); exit(EXIT_NO_KERNEL_SUPPORT); } /* * Check that the options given are valid and consistent. */ //check_options(); if (!sys_check_options()) exit(EXIT_OPTION_ERROR); //auth_check_options();#ifdef HAVE_MULTILINK mp_check_options();#endif for (i = 0; (protp = protocols[i]) != NULL; ++i) if (protp->check_options != NULL) (*protp->check_options)(); if (the_channel->check_options) (*the_channel->check_options)(); if (dump_options || dryrun) { init_pr_log(NULL, LOG_INFO); //print_options(pr_log, NULL); end_pr_log(); } if (dryrun) die(0); /* Make sure fds 0, 1, 2 are open to somewhere. */ fd_devnull = open(_PATH_DEVNULL, O_RDWR); if (fd_devnull < 0) fatal("Couldn't open %s: %m", _PATH_DEVNULL); while (fd_devnull <= 2) { i = dup(fd_devnull); if (i < 0) fatal("Critical shortage of file descriptors: dup failed: %m"); fd_devnull = i; } /* * Initialize system-dependent stuff. */ sys_init();#ifdef USE_TDB pppdb = tdb_open(_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644); if (pppdb != NULL) { slprintf(db_key, sizeof(db_key), "pppd%d", getpid()); update_db_entry(); } else { warn("Warning: couldn't open ppp database %s", _PATH_PPPDB); if (multilink) { warn("Warning: disabling multilink"); multilink = 0; } }#endif /* * Detach ourselves from the terminal, if required, * and identify who is running us. */ if (!nodetach && !updetach) detach(); p = getlogin(); 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 started by %s, uid %d", VERSION, p, uid); script_setenv("PPPLOGNAME", p, 0); if (devnam[0]) script_setenv("DEVICE", devnam, 1); slprintf(numbuf, sizeof(numbuf), "%d", getpid()); script_setenv("PPPD_PID", numbuf, 1); setup_signals(); create_linkpidfile(getpid()); waiting = 0; /* * 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. */ fd_loop = open_ppp_loopback(); set_ifunit(1); /* * Configure the interface and mark it up, etc. */ demand_conf(); } do_callback = 0; for (;;) { bundle_eof = 0; bundle_terminating = 0; listen_time = 0; need_holdoff = 1; devfd = -1; status = EXIT_OK; ++unsuccess; doing_callback = do_callback; do_callback = 0; if (demand && !doing_callback) { /* * Don't do anything until we see some activity. */ new_phase(PHASE_DORMANT); demand_unblock(); add_fd(fd_loop); for (;;) { handle_events(); if (asked_to_quit) break; if (get_loop_output()) break; } remove_fd(fd_loop); if (asked_to_quit) break; /* * Now we want to bring up the link. */ demand_block(); info("Starting link"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -