]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/options.c
Get the repository a bit closer to what will be released
[ppp.git] / pppd / options.c
index 09a2db17bab52a8f2a7d82f84ea343372e7a1eb3..482eab99e3274086d7c6b13aac4b7c1254045c27 100644 (file)
@@ -1,23 +1,46 @@
 /*
  * options.c - handles option processing for PPP.
  *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
+ * Copyright (c) 1984-2000 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The name "Carnegie Mellon University" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For permission or any legal
+ *    details, please contact
+ *      Office of Technology Transfer
+ *      Carnegie Mellon University
+ *      5000 Forbes Avenue
+ *      Pittsburgh, PA  15213-3890
+ *      (412) 268-4387, fax: (412) 268-7395
+ *      tech-transfer@andrew.cmu.edu
+ *
+ * 4. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Computing Services
+ *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
+ *
+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define RCSID  "$Id: options.c,v 1.87 2002/09/14 08:05:27 etbe Exp $"
+#define RCSID  "$Id: options.c,v 1.102 2008/06/15 06:53:06 paulus Exp $"
 
 #include <ctype.h>
 #include <stdio.h>
 #ifdef PLUGIN
 #include <dlfcn.h>
 #endif
+
 #ifdef PPP_FILTER
 #include <pcap.h>
-#include <pcap-int.h>  /* XXX: To get struct pcap */
+/*
+ * There have been 3 or 4 different names for this in libpcap CVS, but
+ * this seems to be what they have settled on...
+ * For older versions of libpcap, use DLT_PPP - but that means
+ * we lose the inbound and outbound qualifiers.
+ */
+#ifndef DLT_PPP_PPPD
+#ifdef DLT_PPP_WITHDIRECTION
+#define DLT_PPP_PPPD   DLT_PPP_WITHDIRECTION
+#else
+#define DLT_PPP_PPPD   DLT_PPP
 #endif
+#endif
+#endif /* PPP_FILTER */
 
 #include "pppd.h"
 #include "pathnames.h"
@@ -54,9 +90,6 @@ struct option_value {
 /*
  * Option variables and default values.
  */
-#ifdef PPP_FILTER
-int    dflag = 0;              /* Tell libpcap we want debugging */
-#endif
 int    debug = 0;              /* Debug flag */
 int    kdebugflag = 0;         /* Tell kernel to print debug messages */
 int    default_device = 1;     /* Using /dev/tty or equivalent */
@@ -85,6 +118,7 @@ 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 */
+int    child_wait = 5;         /* # seconds to wait for children at exit */
 
 #ifdef MAXOCTETS
 unsigned int  maxoctets = 0;    /* default - no limit */
@@ -99,7 +133,6 @@ extern struct stat devstat;
 #ifdef PPP_FILTER
 struct 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 */
 #endif
 
 char *current_option;          /* the name of the option being parsed */
@@ -171,7 +204,8 @@ option_t general_options[] = {
       OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach },
 
     { "holdoff", o_int, &holdoff,
-      "Set time in seconds before retrying connection", OPT_PRIO },
+      "Set time in seconds before retrying connection",
+      OPT_PRIO, &holdoff_specified },
 
     { "idle", o_int, &idle_time_limit,
       "Set time in seconds before disconnecting idle link", OPT_PRIO },
@@ -243,6 +277,10 @@ option_t general_options[] = {
     { "dryrun", o_bool, &dryrun,
       "Stop after parsing, printing, and checking options", 1 },
 
+    { "child-timeout", o_int, &child_wait,
+      "Number of seconds to wait for child processes at exit",
+      OPT_PRIO },
+
 #ifdef HAVE_MULTILINK
     { "multilink", o_bool, &multilink,
       "Enable multilink operation", OPT_PRIO | 1 },
@@ -263,13 +301,10 @@ option_t general_options[] = {
 #endif
 
 #ifdef PPP_FILTER
-    { "pdebug", o_int, &dflag,
-      "libpcap debugging", OPT_PRIO },
-
-    { "pass-filter", 1, setpassfilter,
+    { "pass-filter", o_special, setpassfilter,
       "set filter for packets to pass", OPT_PRIO },
 
-    { "active-filter", 1, setactivefilter,
+    { "active-filter", o_special, setactivefilter,
       "set filter for active pkts", OPT_PRIO },
 #endif
 
@@ -364,16 +399,20 @@ options_from_file(filename, must_exist, check_prot, priv)
     option_t *opt;
     int oldpriv, n;
     char *oldsource;
+    uid_t euid;
     char *argv[MAXARGS];
     char args[MAXARGS][MAXWORDLEN];
     char cmd[MAXWORDLEN];
 
-    if (check_prot)
-       seteuid(getuid());
+    euid = geteuid();
+    if (check_prot && seteuid(getuid()) == -1) {
+       option_error("unable to drop privileges to open %s: %m", filename);
+       return 0;
+    }
     f = fopen(filename, "r");
     err = errno;
-    if (check_prot)
-       seteuid(0);
+    if (check_prot && seteuid(euid) == -1)
+       fatal("unable to regain privileges");
     if (f == NULL) {
        errno = err;
        if (!must_exist) {
@@ -464,8 +503,8 @@ options_for_tty()
     size_t pl;
 
     dev = devnam;
-    if (strncmp(dev, "/dev/", 5) == 0)
-       dev += 5;
+    if ((p = strstr(dev, "/dev/")) != NULL)
+       dev = p + 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;
@@ -602,6 +641,7 @@ process_option(opt, cmd, argv)
     int prio = option_priority;
     option_t *mainopt = opt;
 
+    current_option = opt->name;
     if ((opt->flags & OPT_PRIVFIX) && privileged_option)
        prio += OPRIO_ROOT;
     while (mainopt->flags & OPT_PRIOSUB)
@@ -653,8 +693,6 @@ process_option(opt, cmd, argv)
            *(u_char *)(opt->addr2) &= ~v;
        else if (opt->addr2 && (opt->flags & OPT_A2OR))
            *(u_char *)(opt->addr2) |= v;
-       if (opt->addr3 && (opt->flags & OPT_A3OR))
-           *(u_char *)(opt->addr3) |= v;
        break;
 
     case o_int:
@@ -733,17 +771,20 @@ process_option(opt, cmd, argv)
        if (!(*parser)(argv))
            return 0;
        if (opt->flags & OPT_A2LIST) {
-           struct option_value *ovp, **pp;
+           struct option_value *ovp, *pp;
 
            ovp = malloc(sizeof(*ovp) + strlen(*argv));
            if (ovp != 0) {
                strcpy(ovp->value, *argv);
                ovp->source = option_source;
                ovp->next = NULL;
-               pp = (struct option_value **) &opt->addr2;
-               while (*pp != 0)
-                   pp = &(*pp)->next;
-               *pp = ovp;
+               if (opt->addr2 == NULL) {
+                   opt->addr2 = ovp;
+               } else {
+                   for (pp = opt->addr2; pp->next != NULL; pp = pp->next)
+                       ;
+                   pp->next = ovp;
+               }
            }
        }
        break;
@@ -755,6 +796,10 @@ process_option(opt, cmd, argv)
        break;
     }
 
+    /*
+     * If addr2 wasn't used by any flag (OPT_A2COPY, etc.) but is set,
+     * treat it as a bool and set/clear it based on the OPT_A2CLR bit.
+     */
     if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE
                |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST|OPT_A2OR)) == 0)
        *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR);
@@ -1417,13 +1462,18 @@ static int
 setpassfilter(argv)
     char **argv;
 {
-    pc.linktype = DLT_PPP;
-    pc.snapshot = PPP_HDRLEN;
-    if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
-       return 1;
-    option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
-    return 0;
+    pcap_t *pc;
+    int ret = 1;
+
+    pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
+    if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) {
+       option_error("error in pass-filter expression: %s\n",
+                    pcap_geterr(pc));
+       ret = 0;
+    }
+    pcap_close(pc);
+
+    return ret;
 }
 
 /*
@@ -1433,13 +1483,18 @@ static int
 setactivefilter(argv)
     char **argv;
 {
-    pc.linktype = DLT_PPP;
-    pc.snapshot = PPP_HDRLEN;
-    if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
-       return 1;
-    option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
-    return 0;
+    pcap_t *pc;
+    int ret = 1;
+
+    pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
+    if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) {
+       option_error("error in active-filter expression: %s\n",
+                    pcap_geterr(pc));
+       ret = 0;
+    }
+    pcap_close(pc);
+
+    return ret;
 }
 #endif
 
@@ -1461,21 +1516,24 @@ setdomain(argv)
     return (1);
 }
 
-
 static int
 setlogfile(argv)
     char **argv;
 {
     int fd, err;
+    uid_t euid;
 
-    if (!privileged_option)
-       seteuid(getuid());
+    euid = geteuid();
+    if (!privileged_option && seteuid(getuid()) == -1) {
+       option_error("unable to drop permissions to open %s: %m", *argv);
+       return 0;
+    }
     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);
+    if (!privileged_option && seteuid(euid) == -1)
+       fatal("unable to regain privileges: %m");
     if (fd < 0) {
        errno = err;
        option_error("Can't open log file %s: %m", *argv);
@@ -1489,6 +1547,7 @@ setlogfile(argv)
     log_default = 0;
     return 1;
 }
+
 #ifdef MAXOCTETS
 static int
 setmodir(argv)