]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/options.c
create log file safely, don't create world-writable files
[ppp.git] / pppd / options.c
index cb9c2d4a1638f868bdbf130530a8d1f106baeb58..66770a5918606578c9e7b6e10cb4d19b7dc9d13d 100644 (file)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: options.c,v 1.64 1999/08/13 06:46:16 paulus Exp $"
+#define RCSID  "$Id: options.c,v 1.68 1999/11/15 03:55:37 paulus Exp $"
 
 #include <ctype.h>
 #include <stdio.h>
@@ -34,6 +34,9 @@
 #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 */
@@ -88,6 +91,7 @@ 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;
@@ -95,6 +99,7 @@ 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 */
 
 extern option_t auth_options[];
 extern struct stat devstat;
@@ -134,18 +139,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.
  */
@@ -246,6 +263,14 @@ option_t general_options[] = {
       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 },
+#ifdef PLUGIN
+    { "plugin", o_special, loadplugin,
+      "Load a plug-in module into pppd", OPT_PRIV },
+#endif
 
 #ifdef PPP_FILTER
     { "pdebug", o_int, &dflag,
@@ -324,7 +349,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;
@@ -585,8 +611,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;
@@ -743,6 +774,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.
  */
@@ -794,7 +842,7 @@ option_error __V((char *fmt, ...))
     va_list args;
     char buf[256];
 
-#if __STDC__
+#if defined(__STDC__)
     va_start(args, fmt);
 #else
     char *fmt;
@@ -1274,6 +1322,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;
@@ -1363,7 +1413,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;
@@ -1384,7 +1434,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;
@@ -1428,7 +1478,7 @@ setnetmask(argv)
        b = strtoul(p, &endp, 0);
        if (endp == p)
            break;
-       if (b < 0 || b > 255) {
+       if (b > 255) {
            if (n == 3) {
                /* accept e.g. 0xffffff00 */
                p = endp;
@@ -1473,7 +1523,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);
@@ -1488,3 +1540,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 */