Multilink cleanups and fixes.
authorPaul Mackerras <paulus@samba.org>
Thu, 13 Apr 2000 12:06:00 +0000 (12:06 +0000)
committerPaul Mackerras <paulus@samba.org>
Thu, 13 Apr 2000 12:06:00 +0000 (12:06 +0000)
We don't need to include multilink.o now if HAVE_MULTILINK is
not defined.

pppd/Makefile.sol2
pppd/auth.c
pppd/lcp.c
pppd/main.c
pppd/multilink.c
pppd/sys-linux.c

index a25fd17a88ac94ff235ed7733362b3e5649951a5..835acc215091394d65e1b3bba544b7f248c7f2b7 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Makefile for pppd under Solaris 2.
-# $Id: Makefile.sol2,v 1.17 2000/04/06 23:03:28 masputra Exp $
+# $Id: Makefile.sol2,v 1.18 2000/04/13 12:05:57 paulus Exp $
 #
 
 include ../svr4/Makedefs
@@ -10,8 +10,7 @@ CFLAGS        =  -I../include -DSVR4 -DSOL2 $(COPTS)
 LIBS   = -lsocket -lnsl
 
 OBJS   =  main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o \
-       ccp.o auth.o options.o demand.o utils.o sys-svr4.o tdb.o \
-       multilink.o
+       ccp.o auth.o options.o demand.o utils.o sys-svr4.o tdb.o
 
 #
 # uncomment the following to enable plugins
index e97b48eaf439e730eed5ce80383f90e73ed282c5..023653d5d15c0036e12437bdd6524779a2496253 100644 (file)
@@ -32,7 +32,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: auth.c,v 1.63 2000/04/04 07:06:49 paulus Exp $"
+#define RCSID  "$Id: auth.c,v 1.64 2000/04/13 12:05:57 paulus Exp $"
 
 #include <stdio.h>
 #include <stddef.h>
@@ -511,9 +511,13 @@ start_networks()
     new_phase(PHASE_NETWORK);
 
 #ifdef HAVE_MULTILINK
-    if (multilink)
-       if (mp_join_bundle())
+    if (multilink) {
+       if (mp_join_bundle()) {
+           if (updetach && !nodetach)
+               detach();
            return;
+       }
+    }
 #endif /* HAVE_MULTILINK */
 
 #if 0
index 1241bfbe6a3b787ecd93382390b193a950a007c5..ff17fb0b29d2325cb7404aa0eafb99bc76bffe89 100644 (file)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: lcp.c,v 1.50 2000/04/05 00:58:28 paulus Exp $";
+#define RCSID  "$Id: lcp.c,v 1.51 2000/04/13 12:05:57 paulus Exp $";
 
 /*
  * TODO:
@@ -1955,6 +1955,7 @@ lcp_printpkt(p, plen, printer, arg)
                }
                break;
            case CI_EPDISC:
+#ifdef HAVE_MULTILINK
                if (olen >= CILEN_CHAR) {
                    struct epdisc epd;
                    p += 2;
@@ -1968,6 +1969,9 @@ lcp_printpkt(p, plen, printer, arg)
                    }
                    printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
                }
+#else
+               printer(arg, "endpoint");
+#endif
                break;
            }
            while (p < optend) {
index 5b57e99a00c6fbda3b66e7df2c5805d5b984d921..ca6e50a7be34c69228cbe115c7ef76d10a024ead 100644 (file)
@@ -17,7 +17,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
-#define RCSID  "$Id: main.c,v 1.92 2000/04/04 07:06:51 paulus Exp $"
+#define RCSID  "$Id: main.c,v 1.93 2000/04/13 12:05:59 paulus Exp $"
 
 #include <stdio.h>
 #include <ctype.h>
@@ -179,6 +179,7 @@ static void record_child __P((int, char *, void (*) (void *), void *));
 static void update_db_entry __P((void));
 static void add_db_key __P((const char *));
 static void delete_db_key __P((const char *));
+static void cleanup_db __P((void));
 static int open_socket __P((char *));
 static int start_charshunt __P((int, int));
 static void charshunt_done __P((void *));
@@ -416,7 +417,7 @@ main(argc, argv)
     if (debug)
        setlogmask(LOG_UPTO(LOG_DEBUG));
 
-    pppdb = tdb_open(_PATH_PPPDB, 0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0644);
+    pppdb = tdb_open(_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644);
     if (pppdb != NULL) {
        slprintf(db_key, sizeof(db_key), "pppd%d", getpid());
        update_db_entry();
@@ -448,6 +449,8 @@ main(argc, argv)
 
     if (devnam[0])
        script_setenv("DEVICE", devnam, 1);
+    slprintf(numbuf, sizeof(numbuf), "%d", getpid());
+    script_setenv("PPPD_PID", numbuf, 1);
 
     setup_signals();
 
@@ -462,8 +465,10 @@ main(argc, argv)
        /*
         * Open the loopback channel and set it up to be the ppp interface.
         */
+       tdb_writelock(pppdb);
        fd_loop = open_ppp_loopback();
        set_ifunit(1);
+       tdb_writeunlock(pppdb);
 
        /*
         * Configure the interface and mark it up, etc.
@@ -720,14 +725,17 @@ main(argc, argv)
        }
 
        /* set up the serial device as a ppp interface */
+       tdb_writelock(pppdb);
        fd_ppp = establish_ppp(ttyfd);
        if (fd_ppp < 0) {
+           tdb_writeunlock(pppdb);
            status = EXIT_FATAL_ERROR;
            goto disconnect;
        }
 
        if (!demand && ifunit >= 0)
            set_ifunit(1);
+       tdb_writeunlock(pppdb);
 
        /*
         * Start opening the connection and wait for
@@ -822,6 +830,8 @@ main(argc, argv)
        fd_ppp = -1;
        if (!hungup)
            lcp_lowerdown(0);
+       if (!demand)
+           script_unsetenv("IFNAME");
 
        /*
         * Run disconnector script, if requested.
@@ -1018,6 +1028,7 @@ void
 detach()
 {
     int pid;
+    char numbuf[16];
 
     if (detached)
        return;
@@ -1037,12 +1048,15 @@ detach()
     close(1);
     close(2);
     detached = 1;
-    log_to_fd = -1;
+    if (!log_to_file && !log_to_specific_fd)
+       log_to_fd = -1;
     /* update pid files if they have been written already */
     if (pidfilename[0])
        create_pidfile();
     if (linkpidfile[0])
        create_linkpidfile();
+    slprintf(numbuf, sizeof(numbuf), "%d", getpid());
+    script_setenv("PPPD_PID", numbuf, 1);
 }
 
 /*
@@ -1066,7 +1080,6 @@ static void
 create_pidfile()
 {
     FILE *pidfile;
-    char numbuf[16];
 
     slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",
             _PATH_VARRUN, ifname);
@@ -1077,8 +1090,6 @@ create_pidfile()
        error("Failed to create pid file %s: %m", pidfilename);
        pidfilename[0] = 0;
     }
-    slprintf(numbuf, sizeof(numbuf), "%d", getpid());
-    script_setenv("PPPD_PID", numbuf, 1);
 }
 
 static void
@@ -1088,6 +1099,7 @@ create_linkpidfile()
 
     if (linkname[0] == 0)
        return;
+    script_setenv("LINKNAME", linkname, 1);
     slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid",
             _PATH_VARRUN, linkname);
     if ((pidfile = fopen(linkpidfile, "w")) != NULL) {
@@ -1099,7 +1111,6 @@ create_linkpidfile()
        error("Failed to create pid file %s: %m", linkpidfile);
        linkpidfile[0] = 0;
     }
-    script_setenv("LINKNAME", linkname, 1);
 }
 
 /*
@@ -1327,13 +1338,8 @@ cleanup()
     if (locked)
        unlock();
 
-    if (pppdb != NULL) {
-       TDB_DATA key;
-
-       key.dptr = db_key;
-       key.dsize = strlen(db_key);
-       tdb_delete(pppdb, key);
-    }
+    if (pppdb != NULL)
+       cleanup_db();
 }
 
 /*
@@ -1934,21 +1940,23 @@ script_setenv(var, value, iskey)
     int i;
     char *p, *newstring;
 
-    newstring = (char *) malloc(vl);
+    newstring = (char *) malloc(vl+1);
     if (newstring == 0)
        return;
+    *newstring++ = iskey;
     slprintf(newstring, vl, "%s=%s", var, value);
 
     /* check if this variable is already set */
     if (script_env != 0) {
        for (i = 0; (p = script_env[i]) != 0; ++i) {
            if (strncmp(p, var, varl) == 0 && p[varl] == '=') {
-               if (iskey && pppdb != NULL) {
+               if (p[-1] && pppdb != NULL)
                    delete_db_key(p);
-                   add_db_key(newstring);
-               }
-               free(p);
+               free(p-1);
                script_env[i] = newstring;
+               if (iskey && pppdb != NULL)
+                   add_db_key(newstring);
+               update_db_entry();
                return;
            }
        }
@@ -1998,7 +2006,9 @@ script_unsetenv(var)
        return;
     for (i = 0; (p = script_env[i]) != 0; ++i) {
        if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
-           free(p);
+           if (p[-1] && pppdb != NULL)
+               delete_db_key(p);
+           free(p-1);
            while ((script_env[i] = script_env[i+1]) != 0)
                ++i;
            break;
@@ -2070,6 +2080,24 @@ delete_db_key(str)
     tdb_delete(pppdb, key);
 }
 
+/*
+ * cleanup_db - delete all the entries we put in the database.
+ */
+static void
+cleanup_db()
+{
+    TDB_DATA key;
+    int i;
+    char *p;
+
+    key.dptr = db_key;
+    key.dsize = strlen(db_key);
+    tdb_delete(pppdb, key);
+    for (i = 0; (p = script_env[i]) != 0; ++i)
+       if (p[-1])
+           delete_db_key(p);
+}
+
 /*
  * open_socket - establish a stream socket connection to the nominated
  * host and port.
index 596fd816d24e5332989db20388e5e36dd88a4ca1..546fcaea64004d0d2df991705975de6d90a4761d 100644 (file)
@@ -17,6 +17,8 @@
 #include <ctype.h>
 #include <stdlib.h>
 #include <netdb.h>
+#include <errno.h>
+#include <signal.h>
 #include <netinet/in.h>
 
 #include "pppd.h"
@@ -31,6 +33,8 @@ extern TDB_CONTEXT *pppdb;
 extern char db_key[];
 
 static int get_default_epdisc __P((struct epdisc *));
+static int parse_num __P((char *str, const char *key, int *valp));
+static int owns_unit __P((TDB_DATA pid, int unit));
 
 #define set_ip_epdisc(ep, addr) do {   \
        ep->length = 4;                 \
@@ -45,7 +49,8 @@ static int get_default_epdisc __P((struct epdisc *));
         || ((addr) & 0xfff00000) == 0xac100000         /* 172.16.x.x */  \
         || ((addr) & 0xffff0000) == 0xc0a80000)        /* 192.168.x.x */
 
-#ifdef HAVE_MULTILINK
+#define process_exists(n)      (kill(0, (n)) == 0 || errno != ESRCH)
+
 void
 mp_check_options()
 {
@@ -67,13 +72,11 @@ mp_check_options()
                /* get a default endpoint value */
                wo->neg_endpoint = get_default_epdisc(&wo->endpoint);
                if (wo->neg_endpoint)
-                       info("using default endpoint %s",
-                            epdisc_to_str(&wo->endpoint));
+                       dbglog("using default endpoint %s",
+                              epdisc_to_str(&wo->endpoint));
        }
 }
-#endif /* HAVE_MULTILINK */
 
-#ifdef HAVE_MULTILINK
 /*
  * Make a new bundle or join us to an existing bundle
  * if we are doing multilink.
@@ -83,9 +86,9 @@ mp_join_bundle()
 {
        lcp_options *go = &lcp_gotoptions[0];
        lcp_options *ho = &lcp_hisoptions[0];
-       int unit;
-       int i, l;
-       char *p, *endp;
+       int unit, pppd_pid;
+       int l;
+       char *p;
        TDB_DATA key, pid, rec;
 
        if (!go->neg_mrru || !ho->neg_mrru) {
@@ -122,38 +125,39 @@ mp_join_bundle()
                              epdisc_to_str(&ho->endpoint));
        if (bundle_name)
                p += slprintf(p, bundle_id+l-p, "/%v", bundle_name);
-       info("bundle_id = %s", bundle_id+7);
+       dbglog("bundle_id = %s", bundle_id+7);
 
        /*
         * Check if the bundle ID is already in the database.
         */
        unit = -1;
+       pppd_pid = -1;
        key.dptr = bundle_id;
        key.dsize = p - bundle_id;
+       tdb_writelock(pppdb);
        pid = tdb_fetch(pppdb, key);
        if (pid.dptr != NULL) {
                /* bundle ID exists, see if the pppd record still exists */
                rec = tdb_fetch(pppdb, pid);
                if (rec.dptr != NULL) {
                        /* it is, parse the interface number */
-                       p = strstr(rec.dptr, "IFNAME=ppp");
-                       if (p != 0) {
-                               p += 10;        /* skip to unit number */
-                               i = strtol(p, &endp, 10);
-                               if (endp != p && (*endp == 0 || *endp == ';'))
-                                       unit = i;
-                       }
+                       parse_num(rec.dptr, "IFNAME=ppp", &unit);
+                       /* check the pid value */
+                       parse_num(rec.dptr, "PPPD_PID=", &pppd_pid);
+                       if (!process_exists(pppd_pid) || !owns_unit(pid, unit))
+                               unit = -1;
                        free(rec.dptr);
                }
                free(pid.dptr);
        }
 
        if (unit >= 0) {
-               /* attach to existing unit */
+               /* attach to existing unit, if the pid still exists */
                if (bundle_attach(unit)) {
-                       info("attached link to interface %d", ifunit);
+                       dbglog("attached link to interface %d", ifunit);
                        set_ifunit(0);
                        script_setenv("BUNDLE", bundle_id + 7, 0);
+                       tdb_writeunlock(pppdb);
                        return 1;
                }
                /* attach failed because bundle doesn't exist */
@@ -163,11 +167,55 @@ mp_join_bundle()
        make_new_bundle(go->mrru, ho->mrru, go->neg_ssnhf, ho->neg_ssnhf);
        set_ifunit(1);
        script_setenv("BUNDLE", bundle_id + 7, 1);
+       tdb_writeunlock(pppdb);
+       return 0;
+}
+
+static int
+parse_num(str, key, valp)
+     char *str;
+     const char *key;
+     int *valp;
+{
+       char *p, *endp;
+       int i;
+
+       p = strstr(str, key);
+       if (p != 0) {
+               p += strlen(key);
+               i = strtol(p, &endp, 10);
+               if (endp != p && (*endp == 0 || *endp == ';')) {
+                       *valp = i;
+                       return 1;
+               }
+       }
        return 0;
 }
-#endif /* HAVE_MULTILINK */
 
-#ifdef /* HAVE_MULTILINK */
+/*
+ * Check whether the pppd identified by `key' still owns ppp unit `unit'.
+ */
+static int
+owns_unit(key, unit)
+     TDB_DATA key;
+     int unit;
+{
+       char ifkey[32];
+       TDB_DATA kd, vd;
+       int ret = 0;
+
+       slprintf(ifkey, sizeof(ifkey), "IFNAME=ppp%d", unit);
+       kd.dptr = ifkey;
+       kd.dsize = strlen(ifkey);
+       vd = tdb_fetch(pppdb, kd);
+       if (vd.dptr != NULL) {
+               ret = vd.dsize == key.dsize
+                       && memcmp(vd.dptr, key.dptr, vd.dsize) == 0;
+               free(vd.dptr);
+       }
+       return ret;
+}
+
 static int
 get_default_epdisc(ep)
      struct epdisc *ep;
@@ -200,7 +248,6 @@ get_default_epdisc(ep)
 
        return 0;
 }
-#endif /* HAVE_MULTILINK */
 
 /*
  * epdisc_to_str - make a printable string from an endpoint discriminator.
@@ -252,7 +299,6 @@ epdisc_to_str(ep)
        return str;
 }
 
-#ifdef HAVE_MULTILINK
 static int hexc_val(int c)
 {
        if (c >= 'a')
@@ -261,9 +307,7 @@ static int hexc_val(int c)
                return c - 'A' + 10;
        return c - '0';
 }
-#endif /* HAVE_MULTILINK */
 
-#ifdef HAVE_MULTILINK
 int
 str_to_epdisc(ep, str)
      struct epdisc *ep;
@@ -332,5 +376,4 @@ str_to_epdisc(ep, str)
        dbglog("str_to_epdisc -> %s", epdisc_to_str(ep));
        return 1;
 }
-#endif /* HAVE_MULTILINK */
 
index 532fb130fd82b0d5a123d2a0ce749094acfb3de3..88ab9ddba54b50a0bd2e31175844611e299f87f6 100644 (file)
@@ -1846,35 +1846,34 @@ int ppp_available(void)
     sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
     kernel_version = KVERSION(osmaj, osmin, ospatch);
 
-    if (kernel_version >= KVERSION(2,3,13)) {
-       fd = open("/dev/ppp", O_RDWR);
+    fd = open("/dev/ppp", O_RDWR);
 #if 0
-       if (fd < 0 && errno == ENOENT) {
-           /* try making it and see if that helps. */
-           if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR,
-                     makedev(108, 0)) >= 0) {
-               fd = open("/dev/ppp", O_RDWR);
-               if (fd >= 0)
-                   info("Created /dev/ppp device node");
-               else
-                   unlink("/dev/ppp"); /* didn't work, undo the mknod */
-           } else if (errno == EEXIST) {
-               fd = open("/dev/ppp", O_RDWR);
-           }
+    if (fd < 0 && errno == ENOENT) {
+       /* try making it and see if that helps. */
+       if (mknod("/dev/ppp", S_IFCHR | S_IRUSR | S_IWUSR,
+                 makedev(108, 0)) >= 0) {
+           fd = open("/dev/ppp", O_RDWR);
+           if (fd >= 0)
+               info("Created /dev/ppp device node");
+           else
+               unlink("/dev/ppp");     /* didn't work, undo the mknod */
+       } else if (errno == EEXIST) {
+           fd = open("/dev/ppp", O_RDWR);
        }
+    }
 #endif /* 0 */
-       if (fd >= 0) {
-           new_style_driver = 1;
-
-           /* XXX should get from driver */
-           driver_version = 2;
-           driver_modification = 4;
-           driver_patch = 0;
-           close(fd);
-           return 1;
-       }
-       return 0;
+    if (fd >= 0) {
+       new_style_driver = 1;
+
+       /* XXX should get from driver */
+       driver_version = 2;
+       driver_modification = 4;
+       driver_patch = 0;
+       close(fd);
+       return 1;
     }
+    if (kernel_version >= KVERSION(2,3,13))
+       return 0;
 
 /*
  * Open a socket for doing the ioctl operations.
@@ -2671,8 +2670,8 @@ sys_check_options(void)
        return 0;
     }
     if (multilink && !new_style_driver) {
-       option_error("multilink is not supported by the kernel driver");
-       return 0;
+       warn("Warning: multilink is not supported by the kernel driver");
+       multilink = 0;
     }
     return 1;
 }