📄 options.c
字号:
/* * 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.4.4.1 2003/04/10 13:09:09 joel Exp $"#include <ctype.h>#include <stdio.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <termios.h>#include <string.h>#include <netdb.h>#include <pwd.h>#include <sys/types.h>#include <sys/stat.h>#include <netinet/in.h>#include <arpa/inet.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"#include "patchlevel.h"#include "fsm.h"#include "lcp.h"#include "ipcp.h"#include "upap.h"#include "chap.h"#include "ccp.h"#include <net/ppp-comp.h>#if defined(ultrix) || defined(NeXT)char *strdup __P((char *));#endifstatic const char rcsid[] = RCSID;/* * 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 */int crtscts = 0; /* Use hardware flow control */bool modem = 1; /* Use modem control lines */int inspeed = 0; /* Input/Output speed requested */u_int32_t netmask = 0; /* IP netmask to set on interface */bool lockflag = 0; /* Create lock file to lock the serial dev */bool nodetach = 0; /* Don't detach from controlling tty */bool updetach = 0; /* Detach once link is up */char *initializer = NULL; /* Script to initialize physical link */char *connect_script = NULL; /* Script to establish physical link */char *disconnect_script = NULL; /* Script to disestablish physical link */char *welcomer = NULL; /* Script to run after phys link estab. */char *ptycommand = NULL; /* Command to run on other side of pty */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 */bool notty = 0; /* Stdin/out is not a tty */char *record_file = NULL; /* File to record chars sent/received */int using_pty = 0;bool sync_serial = 0; /* Device is synchronous serial device */int log_to_fd = 1; /* send log messages to this fd too */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 */extern option_t auth_options[];extern struct stat devstat;extern int prepass; /* Doing pre-pass to find device name */struct option_info initializer_info;struct option_info connect_script_info;struct option_info disconnect_script_info;struct option_info welcomer_info;struct option_info devnam_info;struct option_info ptycommand_info;#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 */bool log_to_file; /* log_to_fd is a file opened by us *//* * Prototypes */static int setdevname __P((char *));static int setipaddr __P((char *));static int setspeed __P((char *));static int noopt __P((char **));static int setdomain __P((char **));static int setnetmask __P((char **));static int setxonxoff __P((char **));static int readfile __P((char **));static int callfile __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((char *name));static int process_option __P((option_t *, 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_INC|OPT_NOARG|1 }, { "kdebug", o_int, &kdebugflag, "Set kernel driver debug level" }, { "nodetach", o_bool, &nodetach, "Don't detach from controlling tty", 1 }, { "-detach", o_bool, &nodetach, "Don't detach from controlling tty", 1 }, { "updetach", o_bool, &updetach, "Detach from controlling tty once link is up", 1 }, { "holdoff", o_int, &holdoff, "Set time in seconds before retrying connection" }, { "idle", o_int, &idle_time_limit, "Set time in seconds before disconnecting idle link" }, { "lock", o_bool, &lockflag, "Lock serial device with UUCP-style lock file", 1 }, { "-all", o_special_noarg, noopt, "Don't request/allow any LCP or IPCP options (useless)" }, { "init", o_string, &initializer, "A program to initialize the device", OPT_A2INFO | OPT_PRIVFIX, &initializer_info }, { "connect", o_string, &connect_script, "A program to set up a connection", OPT_A2INFO | OPT_PRIVFIX, &connect_script_info }, { "disconnect", o_string, &disconnect_script, "Program to disconnect serial device", OPT_A2INFO | OPT_PRIVFIX, &disconnect_script_info }, { "welcome", o_string, &welcomer, "Script to welcome client", OPT_A2INFO | OPT_PRIVFIX, &welcomer_info }, { "pty", o_string, &ptycommand, "Script to run on pseudo-tty master side", OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info }, { "notty", o_bool, ¬ty, "Input/output is not a tty", OPT_DEVNAM | 1 }, { "record", o_string, &record_file, "Record characters sent/received to file" }, { "maxconnect", o_int, &maxconnect, "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF }, { "crtscts", o_int, &crtscts, "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) }, { "nocrtscts", o_int, &crtscts, "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, { "-crtscts", o_int, &crtscts, "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, { "cdtrcts", o_int, &crtscts, "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) }, { "nocdtrcts", o_int, &crtscts, "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, { "xonxoff", o_special_noarg, setxonxoff, "Set software (XON/XOFF) flow control" }, { "domain", o_special, setdomain, "Add given domain name to hostname" }, { "mtu", o_int, &lcp_allowoptions[0].mru, "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, { "netmask", o_special, setnetmask, "set netmask" }, { "modem", o_bool, &modem, "Use modem control lines", 1 }, { "local", o_bool, &modem, "Don't use modem control lines" }, { "file", o_special, readfile, "Take options from a file", OPT_PREPASS }, { "call", o_special, callfile, "Take options from a privileged file", OPT_PREPASS }, { "persist", o_bool, &persist, "Keep on reopening connection after close", 1 }, { "nopersist", o_bool, &persist, "Turn off persist option" }, { "demand", o_bool, &demand, "Dial on demand", OPT_INITONLY | 1, &persist }, { "sync", o_bool, &sync_serial, "Use synchronous HDLC serial encoding", 1 }, { "logfd", o_int, &log_to_fd, "Send log messages to this file descriptor" }, { "logfile", o_special, setlogfile, "Append log messages to this file" }, { "nolog", o_int, &log_to_fd, "Don't send log messages to any file", OPT_NOARG | OPT_VAL(-1) }, { "nologfd", o_int, &log_to_fd, "Don't send log messages to any file descriptor", OPT_NOARG | OPT_VAL(-1) }, { "linkname", o_string, linkname, "Set logical name for link", OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, { "maxfail", o_int, &maxfail, "Maximum number of unsuccessful connection attempts to allow" }, { "ktune", o_bool, &tune_kernel, "Alter kernel settings as necessary", 1 }, { "noktune", o_bool, &tune_kernel, "Don't alter kernel settings", 0 }, { "connect-delay", o_int, &connect_delay, "Maximum time (in ms) to wait after connect script finishes" },#ifdef PLUGIN { "plugin", o_special, loadplugin, "Load a plug-in module into pppd", OPT_PRIV },#endif#ifdef PPP_FILTER { "pdebug", o_int, &dflag, "libpcap debugging" }, { "pass-filter", 1, setpassfilter, "set filter for packets to pass" }, { "active-filter", 1, setactivefilter, "set filter for active pkts" },#endif { NULL }};#ifndef IMPLEMENTATION#define IMPLEMENTATION ""#endifstatic char *usage_string = "\pppd version %s.%d%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. * If prepass is true, we are scanning for the device name and only * processing a few options, so error messages are suppressed. */intparse_args(argc, argv) int argc; char **argv;{ char *arg; option_t *opt; int ret; privileged_option = privileged; option_source = "command line"; while (argc > 0) { arg = *argv++; --argc; /* * First see if it's an option in the new option list. */ opt = find_option(arg); if (opt != NULL) { int n = n_arguments(opt); if (argc < n) { option_error("too few parameters for option %s", arg); return 0; } current_option = arg; if (!process_option(opt, argv)) return 0; argc -= n; argv += n; continue; } /* * Maybe a tty name, speed or IP address? */ if ((ret = setdevname(arg)) == 0 && (ret = setspeed(arg)) == 0 && (ret = setipaddr(arg)) == 0 && !prepass) { option_error("unrecognized option '%s'", arg); usage(); return 0; } if (ret < 0) /* error */ return 0; } return 1;}#if 0/* * scan_args - scan the command line arguments to get the tty name, * if specified. Also checks whether the notty or pty option was given. */voidscan_args(argc, argv) int argc; char **argv;{ char *arg; option_t *opt; privileged_option = privileged; while (argc > 0) { arg = *argv++; --argc; if (strcmp(arg, "notty") == 0 || strcmp(arg, "pty") == 0) using_pty = 1; /* Skip options and their arguments */ opt = find_option(arg); if (opt != NULL) { int n = n_arguments(opt); argc -= n; argv += n; continue; } /* Check if it's a tty name and copy it if so */ (void) setdevname(arg, 1); }}#endif/* * 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; char *oldsource; char *argv[MAXARGS]; char args[MAXARGS][MAXWORDLEN]; char cmd[MAXWORDLEN]; f = fopen(filename, "r"); err = errno; if (f == NULL) { if (!must_exist && err == ENOENT) return 1; errno = err; 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)) { /* * First see if it's a command. */ opt = find_option(cmd); if (opt != NULL) { int 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]; } current_option = cmd; if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) { option_error("the %s option may not be used in the %s file", cmd, filename); goto err; } if (!process_option(opt, argv)) goto err; continue; } /* * Maybe a tty name, speed or IP address? */ if ((i = setdevname(cmd)) == 0 && (i = setspeed(cmd)) == 0 && (i = setipaddr(cmd)) == 0) { option_error("In file %s: unrecognized option '%s'", filename, cmd); goto err; } if (i < 0) /* error */ 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(){ return 0;}/* * options_for_tty - See if an options file exists for the serial * device, and if so, interpret options from it. */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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -