options.c

来自「经典的ppp程序」· C语言 代码 · 共 1,513 行 · 第 1/3 页

C
1,513
字号
/* * options.c - handles option processing for PPP. * * 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: options.c,v 1.80 2001/03/12 22:56:12 paulus Exp $"#include <ctype.h>#include <stdio.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <syslog.h>#include <string.h>#include <pwd.h>#ifdef PLUGIN#include <dlfcn.h>#endif#ifdef PPP_FILTER#include <pcap.h>#include <pcap-int.h>	/* XXX: To get struct pcap */#endif#include "pppd.h"#include "pathnames.h"#if defined(ultrix) || defined(NeXT)char *strdup __P((char *));#endifstatic const char rcsid[] = RCSID;struct option_value {    struct option_value *next;    const char *source;    char value[1];};/* * Option variables and default values. */#ifdef PPP_FILTERint	dflag = 0;		/* Tell libpcap we want debugging */#endifint	debug = 0;		/* Debug flag */int	kdebugflag = 0;		/* Tell kernel to print debug messages */int	default_device = 1;	/* Using /dev/tty or equivalent */char	devnam[MAXPATHLEN];	/* Device name */bool	nodetach = 0;		/* Don't detach from controlling tty */bool	updetach = 0;		/* Detach once link is up */int	maxconnect = 0;		/* Maximum connect time */char	user[MAXNAMELEN];	/* Username for PAP */char	passwd[MAXSECRETLEN];	/* Password for PAP */bool	persist = 0;		/* Reopen link after it goes down */char	our_name[MAXNAMELEN];	/* Our name for authentication purposes */bool	demand = 0;		/* do dial-on-demand */char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */int	idle_time_limit = 0;	/* Disconnect if idle for this many seconds */int	holdoff = 30;		/* # seconds to pause before reconnecting */bool	holdoff_specified;	/* true if a holdoff value has been given */int	log_to_fd = 1;		/* send log messages to this fd too */bool	log_default = 1;	/* log_to_fd is default (stdout) */int	maxfail = 10;		/* max # of unsuccessful connection attempts */char	linkname[MAXPATHLEN];	/* logical name for link */bool	tune_kernel;		/* may alter kernel settings */int	connect_delay = 1000;	/* wait this many ms after connect script */int	req_unit = -1;		/* requested interface unit */bool	multilink = 0;		/* Enable multilink operation */char	*bundle_name = NULL;	/* bundle name for multilink */bool	dump_options;		/* print out option values */bool	dryrun;			/* print out option values and exit */char	*domain;		/* domain name set by domain option */extern option_t auth_options[];extern struct stat devstat;#ifdef PPP_FILTERstruct	bpf_program pass_filter;/* Filter program for packets to pass */struct	bpf_program active_filter; /* Filter program for link-active pkts */pcap_t  pc;			/* Fake struct pcap so we can compile expr */#endifchar *current_option;		/* the name of the option being parsed */int  privileged_option;		/* set iff the current option came from root */char *option_source;		/* string saying where the option came from */int  option_priority = OPRIO_CFGFILE; /* priority of the current options */bool devnam_fixed;		/* can no longer change device name */static int logfile_fd = -1;	/* fd opened for log file */static char logfile_name[MAXPATHLEN];	/* name of log file *//* * Prototypes */static int setdomain __P((char **));static int readfile __P((char **));static int callfile __P((char **));static int showversion __P((char **));static int showhelp __P((char **));static void usage __P((void));static int setlogfile __P((char **));#ifdef PLUGINstatic int loadplugin __P((char **));#endif#ifdef PPP_FILTERstatic int setpassfilter __P((char **));static int setactivefilter __P((char **));#endifstatic option_t *find_option __P((const char *name));static int process_option __P((option_t *, char *, char **));static int n_arguments __P((option_t *));static int number_option __P((char *, u_int32_t *, int));/* * Structure to store extra lists of options. */struct option_list {    option_t *options;    struct option_list *next;};static struct option_list *extra_options = NULL;/* * Valid arguments. */option_t general_options[] = {    { "debug", o_int, &debug,      "Increase debugging level", OPT_INC | OPT_NOARG | 1 },    { "-d", o_int, &debug,      "Increase debugging level",      OPT_ALIAS | OPT_INC | OPT_NOARG | 1 },    { "kdebug", o_int, &kdebugflag,      "Set kernel driver debug level", OPT_PRIO },    { "nodetach", o_bool, &nodetach,      "Don't detach from controlling tty", OPT_PRIO | 1 },    { "-detach", o_bool, &nodetach,      "Don't detach from controlling tty", OPT_ALIAS | OPT_PRIOSUB | 1 },    { "updetach", o_bool, &updetach,      "Detach from controlling tty once link is up",      OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach },    { "holdoff", o_int, &holdoff,      "Set time in seconds before retrying connection", OPT_PRIO },    { "idle", o_int, &idle_time_limit,      "Set time in seconds before disconnecting idle link", OPT_PRIO },    { "maxconnect", o_int, &maxconnect,      "Set connection time limit",      OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF },    { "domain", o_special, (void *)setdomain,      "Add given domain name to hostname",      OPT_PRIO | OPT_PRIV | OPT_A2STRVAL, &domain },    { "file", o_special, (void *)readfile,      "Take options from a file", OPT_NOPRINT },    { "call", o_special, (void *)callfile,      "Take options from a privileged file", OPT_NOPRINT },    { "persist", o_bool, &persist,      "Keep on reopening connection after close", OPT_PRIO | 1 },    { "nopersist", o_bool, &persist,      "Turn off persist option", OPT_PRIOSUB },    { "demand", o_bool, &demand,      "Dial on demand", OPT_INITONLY | 1, &persist },    { "--version", o_special_noarg, (void *)showversion,      "Show version number" },    { "--help", o_special_noarg, (void *)showhelp,      "Show brief listing of options" },    { "-h", o_special_noarg, (void *)showhelp,      "Show brief listing of options", OPT_ALIAS },    { "logfile", o_special, (void *)setlogfile,      "Append log messages to this file",      OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, &logfile_name },    { "logfd", o_int, &log_to_fd,      "Send log messages to this file descriptor",      OPT_PRIOSUB | OPT_A2CLR, &log_default },    { "nolog", o_int, &log_to_fd,      "Don't send log messages to any file",      OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) },    { "nologfd", o_int, &log_to_fd,      "Don't send log messages to any file descriptor",      OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) },    { "linkname", o_string, linkname,      "Set logical name for link",      OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN },    { "maxfail", o_int, &maxfail,      "Maximum number of unsuccessful connection attempts to allow",      OPT_PRIO },    { "ktune", o_bool, &tune_kernel,      "Alter kernel settings as necessary", OPT_PRIO | 1 },    { "noktune", o_bool, &tune_kernel,      "Don't alter kernel settings", OPT_PRIOSUB },    { "connect-delay", o_int, &connect_delay,      "Maximum time (in ms) to wait after connect script finishes",      OPT_PRIO },    { "unit", o_int, &req_unit,      "PPP interface unit number to use if possible",      OPT_PRIO | OPT_LLIMIT, 0, 0 },    { "dump", o_bool, &dump_options,      "Print out option values after parsing all options", 1 },    { "dryrun", o_bool, &dryrun,      "Stop after parsing, printing, and checking options", 1 },#ifdef HAVE_MULTILINK    { "multilink", o_bool, &multilink,      "Enable multilink operation", OPT_PRIO | 1 },    { "mp", o_bool, &multilink,      "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 },    { "nomultilink", o_bool, &multilink,      "Disable multilink operation", OPT_PRIOSUB | 0 },    { "nomp", o_bool, &multilink,      "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 },    { "bundle", o_string, &bundle_name,      "Bundle name for multilink", OPT_PRIO },#endif /* HAVE_MULTILINK */#ifdef PLUGIN    { "plugin", o_special, (void *)loadplugin,      "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST },#endif#ifdef PPP_FILTER    { "pdebug", o_int, &dflag,      "libpcap debugging", OPT_PRIO },    { "pass-filter", 1, setpassfilter,      "set filter for packets to pass", OPT_PRIO },    { "active-filter", 1, setactivefilter,      "set filter for active pkts", OPT_PRIO },#endif    { NULL }};#ifndef IMPLEMENTATION#define IMPLEMENTATION ""#endifstatic char *usage_string = "\pppd version %s\n\Usage: %s [ options ], where options are:\n\	<device>	Communicate over the named device\n\	<speed>		Set the baud rate to <speed>\n\	<loc>:<rem>	Set the local and/or remote interface IP\n\			addresses.  Either one may be omitted.\n\	asyncmap <n>	Set the desired async map to hex <n>\n\	auth		Require authentication from peer\n\        connect <p>     Invoke shell command <p> to set up the serial line\n\	crtscts		Use hardware RTS/CTS flow control\n\	defaultroute	Add default route through interface\n\	file <f>	Take options from file <f>\n\	modem		Use modem control lines\n\	mru <n>		Set MRU value to <n> for negotiation\n\See pppd(8) for more options.\n\";/* * parse_args - parse a string of arguments from the command line. */intparse_args(argc, argv)    int argc;    char **argv;{    char *arg;    option_t *opt;    int n;    privileged_option = privileged;    option_source = "command line";    option_priority = OPRIO_CMDLINE;    while (argc > 0) {	arg = *argv++;	--argc;	opt = find_option(arg);	if (opt == NULL) {	    option_error("unrecognized option '%s'", arg);	    usage();	    return 0;	}	n = n_arguments(opt);	if (argc < n) {	    option_error("too few parameters for option %s", arg);	    return 0;	}	if (!process_option(opt, arg, argv))	    return 0;	argc -= n;	argv += n;    }    return 1;}/* * options_from_file - Read a string of options from a file, * and interpret them. */intoptions_from_file(filename, must_exist, check_prot, priv)    char *filename;    int must_exist;    int check_prot;    int priv;{    FILE *f;    int i, newline, ret, err;    option_t *opt;    int oldpriv, n;    char *oldsource;    char *argv[MAXARGS];    char args[MAXARGS][MAXWORDLEN];    char cmd[MAXWORDLEN];    if (check_prot)	seteuid(getuid());    f = fopen(filename, "r");    err = errno;    if (check_prot)	seteuid(0);    if (f == NULL) {	errno = err;	if (!must_exist) {	    if (err != ENOENT && err != ENOTDIR)		warn("Warning: can't open options file %s: %m", filename);	    return 1;	}	option_error("Can't open options file %s: %m", filename);	return 0;    }    oldpriv = privileged_option;    privileged_option = priv;    oldsource = option_source;    option_source = strdup(filename);    if (option_source == NULL)	option_source = "file";    ret = 0;    while (getword(f, cmd, &newline, filename)) {	opt = find_option(cmd);	if (opt == NULL) {	    option_error("In file %s: unrecognized option '%s'",			 filename, cmd);	    goto err;	}	n = n_arguments(opt);	for (i = 0; i < n; ++i) {	    if (!getword(f, args[i], &newline, filename)) {		option_error(			"In file %s: too few parameters for option '%s'",			filename, cmd);		goto err;	    }	    argv[i] = args[i];	}	if (!process_option(opt, cmd, argv))	    goto err;    }    ret = 1;err:    fclose(f);    privileged_option = oldpriv;    option_source = oldsource;    return ret;}/* * options_from_user - See if the use has a ~/.ppprc file, * and if so, interpret options from it. */intoptions_from_user(){    char *user, *path, *file;    int ret;    struct passwd *pw;    size_t pl;    pw = getpwuid(getuid());    if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0)	return 1;    file = _PATH_USEROPT;    pl = strlen(user) + strlen(file) + 2;    path = malloc(pl);    if (path == NULL)	novm("init file name");    slprintf(path, pl, "%s/%s", user, file);    option_priority = OPRIO_CFGFILE;    ret = options_from_file(path, 0, 1, privileged);    free(path);    return ret;}/* * options_for_tty - See if an options file exists for the serial * device, and if so, interpret options from it. * We only allow the per-tty options file to override anything from * the command line if it is something that the user can't override * once it has been set by root; this is done by giving configuration * files a lower priority than the command line. */intoptions_for_tty(){    char *dev, *path, *p;    int ret;    size_t pl;    dev = devnam;    if (strncmp(dev, "/dev/", 5) == 0)	dev += 5;    if (dev[0] == 0 || strcmp(dev, "tty") == 0)	return 1;		/* don't look for /etc/ppp/options.tty */    pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1;    path = malloc(pl);    if (path == NULL)	novm("tty init file name");    slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev);    /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */    for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p)	if (*p == '/')	    *p = '.';    option_priority = OPRIO_CFGFILE;    ret = options_from_file(path, 0, 0, 1);    free(path);    return ret;}/* * options_from_list - process a string of options in a wordlist. */intoptions_from_list(w, priv)    struct wordlist *w;    int priv;{    char *argv[MAXARGS];    option_t *opt;    int i, n, ret = 0;    struct wordlist *w0;    privileged_option = priv;    option_source = "secrets file";    option_priority = OPRIO_SECFILE;    while (w != NULL) {	opt = find_option(w->word);	if (opt == NULL) {	    option_error("In secrets file: unrecognized option '%s'",			 w->word);	    goto err;	}	n = n_arguments(opt);	w0 = w;	for (i = 0; i < n; ++i) {	    w = w->next;	    if (w == NULL) {		option_error(			"In secrets file: too few parameters for option '%s'",			w0->word);		goto err;	    }	    argv[i] = w->word;	}	if (!process_option(opt, w0->word, argv))	    goto err;	w = w->next;    }    ret = 1;err:    return ret;}

⌨️ 快捷键说明

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