X-Git-Url: https://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Foptions.c;h=07dd6d02d3b0d255d4424b9e8416990dcbe6dd9e;hp=2571774974c05668e858be67ea02eae2e2a44fb5;hb=0b3acd3a1122d542e2994d7791cc9127e91778f1;hpb=43980349e8e0c4119d58aa4d53c414864991b276 diff --git a/pppd/options.c b/pppd/options.c index 2571774..07dd6d0 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -17,9 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#ifndef lint -static const char rcsid[] = "$Id: options.c,v 1.62 1999/08/12 04:25:10 paulus Exp $"; -#endif +#define RCSID "$Id: options.c,v 1.72 2000/04/04 07:06:52 paulus Exp $" #include #include @@ -36,6 +34,9 @@ static const char rcsid[] = "$Id: options.c,v 1.62 1999/08/12 04:25:10 paulus Ex #include #include #include +#ifdef PLUGIN +#include +#endif #ifdef PPP_FILTER #include #include /* XXX: To get struct pcap */ @@ -57,6 +58,8 @@ static const char rcsid[] = "$Id: options.c,v 1.62 1999/08/12 04:25:10 paulus Ex char *strdup __P((char *)); #endif +static const char rcsid[] = RCSID; + /* * Option variables and default values. */ @@ -75,8 +78,8 @@ 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 *connector = NULL; /* Script to establish physical link */ -char *disconnector = NULL; /* Script to disestablish 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 */ @@ -88,20 +91,29 @@ 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 *pty_socket = NULL; /* Socket to connect to pty */ 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 */ +int max_data_rate; /* max bytes/sec through charshunt */ +int req_unit = -1; /* requested interface unit */ +bool multilink = 0; /* Enable multilink operation */ +char *bundle_name = NULL; /* bundle name for multilink */ 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 connector_info; -struct option_info disconnector_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; @@ -133,18 +145,30 @@ static int showversion __P((char **)); static int showhelp __P((char **)); static void usage __P((void)); static int setlogfile __P((char **)); +#ifdef PLUGIN +static int loadplugin __P((char **)); +#endif #ifdef PPP_FILTER static int setpassfilter __P((char **)); static int setactivefilter __P((char **)); #endif - static 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. */ @@ -172,12 +196,12 @@ option_t general_options[] = { { "init", o_string, &initializer, "A program to initialize the device", OPT_A2INFO | OPT_PRIVFIX, &initializer_info }, - { "connect", o_string, &connector, + { "connect", o_string, &connect_script, "A program to set up a connection", - OPT_A2INFO | OPT_PRIVFIX, &connector_info }, - { "disconnect", o_string, &disconnector, + OPT_A2INFO | OPT_PRIVFIX, &connect_script_info }, + { "disconnect", o_string, &disconnect_script, "Program to disconnect serial device", - OPT_A2INFO | OPT_PRIVFIX, &disconnector_info }, + OPT_A2INFO | OPT_PRIVFIX, &disconnect_script_info }, { "welcome", o_string, &welcomer, "Script to welcome client", OPT_A2INFO | OPT_PRIVFIX, &welcomer_info }, @@ -186,6 +210,8 @@ option_t general_options[] = { OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info }, { "notty", o_bool, ¬ty, "Input/output is not a tty", OPT_DEVNAM | 1 }, + { "socket", o_string, &pty_socket, + "Send and receive over socket, arg is host:port", OPT_DEVNAM }, { "record", o_string, &record_file, "Record characters sent/received to file" }, { "maxconnect", o_int, &maxconnect, @@ -240,8 +266,37 @@ option_t general_options[] = { { "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" }, + { "datarate", o_int, &max_data_rate, + "Maximum data rate in bytes/sec (with pty, notty or record option)" }, + { "unit", o_int, &req_unit, + "PPP interface unit number to use if possible", OPT_LLIMIT, 0, 0 }, +#ifdef HAVE_MULTILINK + { "multilink", o_bool, &multilink, + "Enable multilink operation", 1 }, + { "nomultilink", o_bool, &multilink, + "Disable multilink operation", 0 }, + { "mp", o_bool, &multilink, + "Enable multilink operation", 1 }, + { "nomp", o_bool, &multilink, + "Disable multilink operation", 0 }, + { "bundle", o_string, &bundle_name, + "Bundle name for multilink" }, +#endif /* HAVE_MULTILINK */ +#ifdef PLUGIN + { "plugin", o_special, loadplugin, + "Load a plug-in module into pppd", OPT_PRIV }, +#endif #ifdef PPP_FILTER { "pdebug", o_int, &dflag, @@ -320,7 +375,8 @@ parse_args(argc, argv) */ if ((ret = setdevname(arg)) == 0 && (ret = setspeed(arg)) == 0 - && (ret = setipaddr(arg)) == 0) { + && (ret = setipaddr(arg)) == 0 + && !prepass) { option_error("unrecognized option '%s'", arg); usage(); return 0; @@ -581,8 +637,13 @@ find_option(name) char *name; { option_t *opt; + struct option_list *list; int i; + for (list = extra_options; list != NULL; list = list->next) + for (opt = list->options; opt->name != NULL; ++opt) + if (strcmp(name, opt->name) == 0) + return opt; for (opt = general_options; opt->name != NULL; ++opt) if (strcmp(name, opt->name) == 0) return opt; @@ -739,6 +800,23 @@ n_arguments(opt) || (opt->flags & OPT_NOARG))? 0: 1; } +/* + * add_options - add a list of options to the set we grok. + */ +void +add_options(opt) + option_t *opt; +{ + struct option_list *list; + + list = malloc(sizeof(*list)); + if (list == 0) + novm("option list entry"); + list->options = opt; + list->next = extra_options; + extra_options = list; +} + /* * usage - print out a message telling how to use the program. */ @@ -790,7 +868,7 @@ option_error __V((char *fmt, ...)) va_list args; char buf[256]; -#if __STDC__ +#if defined(__STDC__) va_start(args, fmt); #else char *fmt; @@ -1270,6 +1348,8 @@ setspeed(arg) char *ptr; int spd; + if (prepass) + return 1; spd = strtol(arg, &ptr, 0); if (ptr == arg || *ptr != 0 || spd == 0) return 0; @@ -1359,7 +1439,7 @@ setipaddr(arg) */ if (colon != arg) { *colon = '\0'; - if ((local = inet_addr(arg)) == -1) { + if ((local = inet_addr(arg)) == (u_int32_t) -1) { if ((hp = gethostbyname(arg)) == NULL) { option_error("unknown host: %s", arg); return -1; @@ -1380,7 +1460,7 @@ setipaddr(arg) * If colon last character, then no remote addr. */ if (*++colon != '\0') { - if ((remote = inet_addr(colon)) == -1) { + if ((remote = inet_addr(colon)) == (u_int32_t) -1) { if ((hp = gethostbyname(colon)) == NULL) { option_error("unknown host: %s", colon); return -1; @@ -1409,39 +1489,20 @@ static int setnetmask(argv) char **argv; { - u_int32_t mask, b; - int n, ok; - char *p, *endp; + u_int32_t mask; + int n; + char *p; /* * Unfortunately, if we use inet_addr, we can't tell whether * a result of all 1s is an error or a valid 255.255.255.255. */ p = *argv; - ok = 0; - mask = 0; - for (n = 3;; --n) { - b = strtoul(p, &endp, 0); - if (endp == p) - break; - if (b < 0 || b > 255) { - if (n == 3) { - /* accept e.g. 0xffffff00 */ - p = endp; - mask = b; - } - break; - } - mask |= b << (n * 8); - p = endp; - if (*p != '.' || n == 0) - break; - ++p; - } + n = parse_dotted_ip(p, &mask); mask = htonl(mask); - if (*p != 0 || (netmask & ~mask) != 0) { + if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) { option_error("invalid netmask value '%s'", *argv); return 0; } @@ -1450,6 +1511,39 @@ setnetmask(argv) return (1); } +int +parse_dotted_ip(p, vp) + char *p; + u_int32_t *vp; +{ + int n; + u_int32_t v, b; + char *endp, *p0 = p; + + v = 0; + for (n = 3;; --n) { + b = strtoul(p, &endp, 0); + if (endp == p) + return 0; + if (b > 255) { + if (n < 3) + return 0; + /* accept e.g. 0xffffff00 */ + *vp = b; + return endp - p0; + } + v |= b << (n * 8); + p = endp; + if (n == 0) + break; + if (*p != '.') + return 0; + ++p; + } + *vp = v; + return p - p0; +} + static int setxonxoff(argv) char **argv; @@ -1469,7 +1563,9 @@ setlogfile(argv) if (!privileged_option) seteuid(getuid()); - fd = open(*argv, O_WRONLY | O_APPEND); + fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644); + if (fd < 0 && errno == EEXIST) + fd = open(*argv, O_WRONLY | O_APPEND); err = errno; if (!privileged_option) seteuid(0); @@ -1484,3 +1580,33 @@ setlogfile(argv) log_to_file = 1; return 1; } + +#ifdef PLUGIN +static int +loadplugin(argv) + char **argv; +{ + char *arg = *argv; + void *handle; + const char *err; + void (*init) __P((void)); + + handle = dlopen(arg, RTLD_GLOBAL | RTLD_NOW); + if (handle == 0) { + err = dlerror(); + if (err != 0) + option_error("%s", err); + option_error("Couldn't load plugin %s", arg); + return 0; + } + init = dlsym(handle, "plugin_init"); + if (init == 0) { + option_error("%s has no initialization entry point", arg); + dlclose(handle); + return 0; + } + info("Plugin %s loaded.", arg); + (*init)(); + return 1; +} +#endif /* PLUGIN */