⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * main.c - Point-to-Point Protocol main module * * Copyright (c) 1989 Carnegie Mellon University. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by Carnegie Mellon University.  The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#define RCSID	"$Id: main.c,v 1.88 1999/12/23 01:28:27 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 "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.h"#include "ccp.h"#include "pathnames.h"#include "patchlevel.h"#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 */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 */static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */static uid_t uid;		/* Our real user-id */static int conn_running;	/* we have a [dis]connector running */int ttyfd;			/* Serial port file descriptor */mode_t tty_mode = -1;		/* Original access permissions to tty */int baud_rate;			/* Actual bits/second for serial device */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 */struct stat devstat;		/* result of stat() on devnam */int prepass = 0;		/* doing prepass to find device name */int devnam_fixed;		/* set while in options.ttyxx file */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 */char *callback_script;		/* script for doing callback */int (*holdoff_hook) __P((void)) = NULL;int (*new_phase_hook) __P((int)) = NULL;static int fd_ppp = -1;		/* fd for talking PPP */static int fd_loop;		/* fd for getting demand-dial packets */static int pty_master;		/* fd for master side of pty */static int pty_slave;		/* fd for slave side of pty */static int real_ttyfd;		/* fd for actual serial port (not pty) */int phase;			/* where the link is at */int kill_link;int open_ccp_flag;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 */static int locked;		/* lock() has succeeded */static 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. */struct pppd_stats link_stats;int link_connect_time;int link_stats_valid;static int charshunt_pid;	/* Process ID for charshunt *//* * 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 create_pidfile __P((void));static void create_linkpidfile __P((void));static void cleanup __P((void));static void close_tty __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 int device_script __P((char *, int, int, int));static int reap_kids __P((int waitfor));static void record_child __P((int, char *, void (*) (void *), void *));static int start_charshunt __P((int, int));static void charshunt_done __P((void *));static void charshunt __P((int, int, char *));static int record_write __P((FILE *, int code, u_char *buf, int nb,			     struct timeval *));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,#ifdef IPX_CHANGE    &ipxcp_protent,#endif#ifdef AT_CHANGE    &atcp_protent,#endif    NULL};intmain(argc, argv)    int argc;    char *argv[];{    int i, fdflags, t;    struct sigaction sa;    char *p, *connector;    struct passwd *pw;    struct timeval timo;    sigset_t mask;    struct protent *protp;    struct stat statbuf;    char numbuf[16];    new_phase(PHASE_INITIALIZE);    /*     * Ensure that fds 0, 1, 2 are open, to /dev/null if nowhere else.     * This way we can close 0, 1, 2 in detach() without clobbering     * a fd that we are using.     */    if ((i = open("/dev/null", O_RDWR)) >= 0) {	while (0 <= i && i <= 2)	    i = dup(i);	if (i >= 0)	    close(i);    }    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);    ngroups = getgroups(NGROUPS_MAX, groups);    /*     * Initialize magic number generator now so that protocols may     * use magic numbers in initialization.     */    magic_init();    /*     * 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;    prepass = 0;    if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)	|| !options_from_user())	exit(EXIT_OPTION_ERROR);    /* scan command line and options files to find device name */    prepass = 1;    parse_args(argc-1, argv+1);    prepass = 0;    /*     * Work out the device name, if it hasn't already been specified.     */    using_pty = notty || ptycommand != NULL;    if (!using_pty && default_device) {	char *p;	if (!isatty(0) || (p = ttyname(0)) == NULL) {	    option_error("no device specified and stdin is not a tty");	    exit(EXIT_OPTION_ERROR);	}	strlcpy(devnam, p, sizeof(devnam));	if (stat(devnam, &devstat) < 0)	    fatal("Couldn't stat default device %s: %m", devnam);    }    /*     * Parse the tty options file and the command line.     * The per-tty options file should not change     * ptycommand, notty or devnam.     */    devnam_fixed = 1;    if (!using_pty) {	if (!options_for_tty())	    exit(EXIT_OPTION_ERROR);    }    devnam_fixed = 0;    if (!parse_args(argc-1, argv+1))	exit(EXIT_OPTION_ERROR);    /*     * 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(no_ppp_msg);	exit(EXIT_NO_KERNEL_SUPPORT);    }    /*     * Check that the options given are valid and consistent.     */    if (!sys_check_options())	exit(EXIT_OPTION_ERROR);    auth_check_options();    for (i = 0; (protp = protocols[i]) != NULL; ++i)	if (protp->check_options != NULL)	    (*protp->check_options)();    if (demand && connect_script == 0) {	option_error("connect script is required for demand-dialling\n");	exit(EXIT_OPTION_ERROR);    }    /* default holdoff to 0 if no connect script has been given */    if (connect_script == 0 && !holdoff_specified)	holdoff = 0;    if (using_pty) {	if (!default_device) {	    option_error("%s option precludes specifying device name",			 notty? "notty": "pty");	    exit(EXIT_OPTION_ERROR);	}	if (ptycommand != NULL && notty) {	    option_error("pty option is incompatible with notty option");	    exit(EXIT_OPTION_ERROR);	}	default_device = notty;	lockflag = 0;	modem = 0;	if (notty && log_to_fd <= 1)	    log_to_fd = -1;    } else {	/*	 * If the user has specified a device which is the same as	 * the one on stdin, pretend they didn't specify any.	 * If the device is already open read/write on stdin,	 * we assume we don't need to lock it, and we can open it as root.	 */	if (fstat(0, &statbuf) >= 0 && S_ISCHR(statbuf.st_mode)	    && statbuf.st_rdev == devstat.st_rdev) {	    default_device = 1;	    fdflags = fcntl(0, F_GETFL);	    if (fdflags != -1 && (fdflags & O_ACCMODE) == O_RDWR)		privopen = 1;	}    }    if (default_device)	nodetach = 1;    /*     * Don't send log messages to the serial port, it tends to     * confuse the peer. :-)     */    if (log_to_fd >= 0 && fstat(log_to_fd, &statbuf) >= 0	&& S_ISCHR(statbuf.st_mode) && statbuf.st_rdev == devstat.st_rdev)	log_to_fd = -1;    script_setenv("DEVICE", devnam);    /*     * Initialize system-dependent stuff.     */    sys_init();    if (debug)	setlogmask(LOG_UPTO(LOG_DEBUG));    /*     * 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.%d%s started by %s, uid %d",	   VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);    script_setenv("PPPLOGNAME", p);    /*     * 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);    sigaddset(&mask, 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 = 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);    waiting = 0;    create_linkpidfile();    /*     * 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();	syslog(LOG_INFO, "Using interface ppp%d", ifunit);	slprintf(ifname, sizeof(ifname), "ppp%d", ifunit);	script_setenv("IFNAME", ifname);	create_pidfile();	/* write pid to file */	/*	 * Configure the interface and mark it up, etc.	 */	demand_conf();    }    do_callback = 0;    for (;;) {	need_holdoff = 1;	ttyfd = -1;	real_ttyfd = -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.	     */	    kill_link = 0;	    new_phase(PHASE_DORMANT);	    demand_unblock();	    add_fd(fd_loop);	    for (;;) {		if (sigsetjmp(sigjmp, 1) == 0) {		    sigprocmask(SIG_BLOCK, &mask, NULL);		    if (kill_link || got_sigchld) {			sigprocmask(SIG_UNBLOCK, &mask, NULL);		    } else {			waiting = 1;			sigprocmask(SIG_UNBLOCK, &mask, NULL);			wait_input(timeleft(&timo));		    }		}		waiting = 0;		calltimeout();		if (kill_link) {		    if (!persist)			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -