]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-linux.c
use strlcpy, strlcat, slprintf everywhere
[ppp.git] / pppd / sys-linux.c
index e92f6845a825b75d6fe043ef8ee52715677bab25..900e9af08336ce622f00794c558b681d2e9d7f7f 100644 (file)
@@ -25,6 +25,7 @@
 #include <sys/errno.h>
 #include <sys/file.h>
 #include <sys/stat.h>
+#include <sys/utsname.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,6 +38,8 @@
 #include <signal.h>
 #include <fcntl.h>
 #include <ctype.h>
+#include <termios.h>
+#include <unistd.h>
 
 /* This is in netdevice.h. However, this compile will fail miserably if
    you attempt to include netdevice.h because it has so many references
 #define MAX_ADDR_LEN 7
 #endif
 
-#include <linux/version.h>
+#if __GLIBC__ >= 2
+#include <asm/types.h>         /* glibc 2 conflicts with linux/types.h */
 #include <net/if.h>
-#include <linux/ppp_defs.h>
 #include <net/if_arp.h>
-#include <linux/if_ppp.h>
 #include <net/route.h>
+#include <netinet/if_ether.h>
+#else
+#include <linux/types.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/route.h>
 #include <linux/if_ether.h>
+#endif
 #include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
 
 #include "pppd.h"
 #include "fsm.h"
 #include "ipcp.h"
-
-#ifndef RTF_DEFAULT  /* Normally in <linux/route.h> from <net/route.h> */
-#define RTF_DEFAULT  0
-#endif
+#include "patchlevel.h"
 
 #ifdef IPX_CHANGE
 #include "ipxcp.h"
+#if __GLIBC__ >= 2 && \
+    !(defined(__powerpc__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+#include <netipx/ipx.h>
+#else
+#include <linux/ipx.h>
 #endif
+#endif /* IPX_CHANGE */
 
 #ifdef LOCKLIB
 #include <sys/locks.h>
 #endif
 
+#ifndef RTF_DEFAULT  /* Normally in <linux/route.h> from <net/route.h> */
+#define RTF_DEFAULT  0
+#endif
+
 #define ok_error(num) ((num)==EIO)
 
 static int tty_disc = N_TTY;   /* The TTY discipline */
@@ -99,6 +119,10 @@ static u_int32_t proxy_arp_addr;    /* Addr for proxy arp entry added */
 
 static char *lock_file;
 
+static struct utsname utsname; /* for the kernel version */
+static int kernel_version;
+#define KVERSION(j,n,p)        ((j)*1000000 + (n)*1000 + (p))
+
 #define MAX_IFS                100
 
 #define FLAGS_GOOD (IFF_UP          | IFF_BROADCAST)
@@ -135,22 +159,27 @@ extern u_char     inpacket_buf[]; /* borrowed from main.c */
  */
 
 extern int hungup;
-#define still_ppp() (hungup == 0)
 
 #ifndef LOCK_PREFIX
 #define LOCK_PREFIX    "/var/lock/LCK.."
 #endif
 
-/********************************************************************
- *
- * Functions to read and set the flags value in the device driver
- */
-
 static void set_ppp_fd (int new_fd)
-  {    
-    SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", ppp_fd));
-    ppp_fd = new_fd;
-  }
+{
+       SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", new_fd));
+       ppp_fd = new_fd;
+}
+
+static int still_ppp(void)
+{
+       if (!hungup || ppp_fd == slave_fd)
+               return 1;
+       if (slave_fd >= 0) {
+               set_ppp_fd(slave_fd);
+               return 1;
+       }
+       return 0;
+}
 
 /********************************************************************
  *
@@ -201,6 +230,8 @@ static void set_flags (int flags)
 
 void sys_init(void)
   {
+    int osmaj, osmin, ospatch;
+
     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
     setlogmask(LOG_UPTO(LOG_INFO));
     if (debug)
@@ -218,6 +249,11 @@ void sys_init(void)
            die(1);
          }
       }
+
+    uname(&utsname);
+    osmaj = osmin = ospatch = 0;
+    sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch);
+    kernel_version = KVERSION(osmaj, osmin, ospatch);
   }
 
 /********************************************************************
@@ -229,7 +265,6 @@ void sys_init(void)
 
 void sys_cleanup(void)
   {
-    struct ifreq ifr;
 /*
  * Take down the device
  */
@@ -402,9 +437,6 @@ void establish_ppp (int tty_fd)
 
 void disestablish_ppp(int tty_fd)
   {
-    int x;
-    char *s;
-
 /*
  * Attempt to restore the previous tty settings
  */
@@ -565,6 +597,12 @@ struct speed {
 #endif
 #ifdef EXTB
     { 38400, EXTB },
+#endif
+#ifdef B230400
+    { 230400, B230400 },
+#endif
+#ifdef B460800
+    { 460800, B460800 },
 #endif
     { 0, 0 }
 };
@@ -621,11 +659,12 @@ static int baud_rate_of (int speed)
  * regardless of whether the modem option was specified.
  */
 
-void set_up_tty (int tty_fd, int local)
+void set_up_tty(int tty_fd, int local)
   {
-    int speed, x;
+    int speed;
     struct termios tios;
-    
+
+    setdtr(tty_fd, 1);
     if (tcgetattr(tty_fd, &tios) < 0)
       {
        syslog(LOG_ERR, "tcgetattr: %m(%d)", errno);
@@ -761,14 +800,13 @@ void output (int unit, unsigned char *p, int len)
     if (write(ppp_fd, p, len) < 0)
       {
        if (errno == EWOULDBLOCK || errno == ENOBUFS
-           || errno == ENXIO || errno == EIO)
+           || errno == ENXIO || errno == EIO || errno == EINTR)
          {
-           syslog(LOG_WARNING, "write: warning: %m(%d)", errno);
+           syslog(LOG_WARNING, "write: warning: %m (%d)", errno);
          } 
        else
          {
-           syslog(LOG_ERR, "write: %m(%d)", errno);
-           die(1);
+           syslog(LOG_ERR, "write: %m (%d)", errno);
          }
       }
   }
@@ -915,7 +953,7 @@ void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
  * Set the MTU and other parameters for the ppp device
  */
        memset (&ifr, '\0', sizeof (ifr));
-       strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+       strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
        ifr.ifr_mtu = mtu;
        
        if (ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
@@ -1058,18 +1096,21 @@ get_idle_time(u, ip)
  */
 
 int ccp_fatal_error (int unit)
-  {
+{
     int x = get_flags();
 
     return x & SC_DC_FERROR;
-  }
+}
 
 /*
  * path_to_route - determine the path to the proc file system data
  */
-
+#define ROUTE_MAX_COLS 12
 FILE *route_fd = (FILE *) 0;
 static char route_buffer [512];
+static int route_dev_col, route_dest_col, route_gw_col;
+static int route_flags_col, route_mask_col;
+static int route_num_cols;
 
 static char *path_to_route (void);
 static int open_route_table (void);
@@ -1082,33 +1123,30 @@ static int read_route_table (struct rtentry *rt);
  */
 
 static int path_to_procfs (void)
-  {
+{
     struct mntent *mntent;
     FILE *fp;
 
-    fp = fopen (MOUNTED, "r");
-    if (fp != 0)
-      {
-       mntent = getmntent (fp);
-        while (mntent != (struct mntent *) 0)
-         {
-           if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) != 0)
-             {
-               if (strcmp (mntent->mnt_type, "proc") == 0)
-                 {
-                   strncpy (route_buffer, mntent->mnt_dir,
-                            sizeof (route_buffer)-10);
-                   route_buffer [sizeof (route_buffer)-10] = '\0';
-                   fclose (fp);
-                   return 1;
-                 }
-             }
-           mntent = getmntent (fp);
-         }
-       fclose (fp);
-      }
-    return 0;
-  }
+    fp = fopen(MOUNTED, "r");
+    if (fp == NULL) {
+       /* Default the mount location of /proc */
+       strlcpy (route_buffer, sizeof (route_buffer), "/proc");
+       return 1;
+    }
+
+    while ((mntent = getmntent(fp)) != NULL) {
+       if (strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0)
+           continue;
+       if (strcmp(mntent->mnt_type, "proc") == 0)
+           break;
+    }
+    fclose (fp);
+    if (mntent == 0)
+       return 0;
+
+    strlcpy(route_buffer, sizeof (route_buffer), mntent->mnt_dir);
+    return 1;
+}
 
 /********************************************************************
  *
@@ -1116,15 +1154,14 @@ static int path_to_procfs (void)
  */
 
 static char *path_to_route (void)
-  {
-    if (! path_to_procfs())
-      {
+{
+    if (!path_to_procfs()) {
        syslog (LOG_ERR, "proc file system not mounted");
        return 0;
-      }
-    strcat (route_buffer, "/net/route");
+    }
+    strlcat (route_buffer, sizeof(route_buffer), "/net/route");
     return (route_buffer);
-  }
+}
 
 /********************************************************************
  *
@@ -1132,89 +1169,107 @@ static char *path_to_route (void)
  */
 
 static void close_route_table (void)
-  {
-    if (route_fd != (FILE *) 0)
-      {
+{
+    if (route_fd != (FILE *) 0) {
         fclose (route_fd);
         route_fd = (FILE *) 0;
-      }
-  }
+    }
+}
 
 /********************************************************************
  *
  * open_route_table - open the interface to the route table
  */
+static char route_delims[] = " \t\n";
 
 static int open_route_table (void)
-  {
+{
     char *path;
 
     close_route_table();
 
     path = path_to_route();
     if (path == NULL)
-      {
         return 0;
-      }
 
     route_fd = fopen (path, "r");
-    if (route_fd == (FILE *) 0)
-      {
-        syslog (LOG_ERR, "can not open %s: %m(%d)", path, errno);
+    if (route_fd == NULL) {
+        syslog (LOG_ERR, "can't open %s: %m (%d)", path, errno);
         return 0;
-      }
+    }
+
+    route_dev_col = 0;         /* default to usual columns */
+    route_dest_col = 1;
+    route_gw_col = 2;
+    route_flags_col = 3;
+    route_mask_col = 7;
+    route_num_cols = 8;
+
+    /* parse header line */
+    if (fgets(route_buffer, sizeof(route_buffer), route_fd) != 0) {
+       char *p = route_buffer, *q;
+       int col;
+       for (col = 0; col < ROUTE_MAX_COLS; ++col) {
+           int used = 1;
+           if ((q = strtok(p, route_delims)) == 0)
+               break;
+           if (strcasecmp(q, "iface") == 0)
+               route_dev_col = col;
+           else if (strcasecmp(q, "destination") == 0)
+               route_dest_col = col;
+           else if (strcasecmp(q, "gateway") == 0)
+               route_gw_col = col;
+           else if (strcasecmp(q, "flags") == 0)
+               route_flags_col = col;
+           else if (strcasecmp(q, "mask") == 0)
+               route_mask_col = col;
+           else
+               used = 0;
+           if (used && col >= route_num_cols)
+               route_num_cols = col + 1;
+           p = NULL;
+       }
+    }
+
     return 1;
-  }
+}
 
 /********************************************************************
  *
  * read_route_table - read the next entry from the route table
  */
 
-static int read_route_table (struct rtentry *rt)
-  {
-    static char delims[] = " \t\n";
-    char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
+static int read_route_table(struct rtentry *rt)
+{
+    char *cols[ROUTE_MAX_COLS], *p;
+    int col;
        
     memset (rt, '\0', sizeof (struct rtentry));
 
-    for (;;)
-      {
-       if (fgets (route_buffer, sizeof (route_buffer), route_fd) ==
-           (char *) 0)
-         {
-           return 0;
-         }
+    if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
+       return 0;
 
-       dev_ptr  = strtok (route_buffer, delims); /* interface name */
-       dst_ptr  = strtok (NULL,         delims); /* destination address */
-       gw_ptr   = strtok (NULL,         delims); /* gateway */
-       flag_ptr = strtok (NULL,         delims); /* flags */
-    
-       if (flag_ptr == (char *) 0) /* assume that we failed, somewhere. */
-         {
-           return 0;
-         }
-       
-       /* Discard that stupid header line which should never
-        * have been there in the first place !! */
-       if (isxdigit (*dst_ptr) && isxdigit (*gw_ptr) && isxdigit (*flag_ptr))
-         {
-           break;
-         }
-      }
+    p = route_buffer;
+    for (col = 0; col < route_num_cols; ++col) {
+       cols[col] = strtok(p, route_delims);
+       if (cols[col] == NULL)
+           return 0;           /* didn't get enough columns */
+    }
 
     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
-      strtoul (dst_ptr, NULL, 16);
+       strtoul(cols[route_dest_col], NULL, 16);
 
     ((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
-      strtoul (gw_ptr, NULL, 16);
+       strtoul(cols[route_gw_col], NULL, 16);
+
+    ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr =
+       strtoul(cols[route_mask_col], NULL, 16);
 
-    rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
-    rt->rt_dev   = dev_ptr;
+    rt->rt_flags = (short) strtoul(cols[route_flags_col], NULL, 16);
+    rt->rt_dev   = cols[route_dev_col];
 
     return 1;
-  }
+}
 
 /********************************************************************
  *
@@ -1222,31 +1277,54 @@ static int read_route_table (struct rtentry *rt)
  */
 
 static int defaultroute_exists (struct rtentry *rt)
-  {
-    int    result = 0;
+{
+    int result = 0;
 
     if (!open_route_table())
-      {
         return 0;
-      }
 
-    while (read_route_table(rt) != 0)
-      {
+    while (read_route_table(rt) != 0) {
         if ((rt->rt_flags & RTF_UP) == 0)
-         {
            continue;
-         }
 
-        if (((struct sockaddr_in *) (&rt->rt_dst))->sin_addr.s_addr == 0L)
-         {
+        if (((struct sockaddr_in *) (&rt->rt_dst))->sin_addr.s_addr == 0L) {
            result = 1;
            break;
-         }
-      }
+       }
+    }
 
     close_route_table();
     return result;
-  }
+}
+
+/*
+ * have_route_to - determine if the system has any route to
+ * a given IP address.  `addr' is in network byte order.
+ * Return value is 1 if yes, 0 if no, -1 if don't know.
+ * For demand mode to work properly, we have to ignore routes
+ * through our own interface.
+ */
+int have_route_to(u_int32_t addr)
+{
+    struct rtentry rt;
+    int result = 0;
+
+    if (!open_route_table())
+       return -1;              /* don't know */
+
+    while (read_route_table(&rt)) {
+       if ((rt.rt_flags & RTF_UP) == 0 || strcmp(rt.rt_dev, ifname) == 0)
+           continue;
+       if ((addr & ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr)
+           == ((struct sockaddr_in *)&rt.rt_dst)->sin_addr.s_addr) {
+           result = 1;
+           break;
+       }
+    }
+
+    close_route_table();
+    return result;
+}
 
 /********************************************************************
  *
@@ -1257,7 +1335,7 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
   {
     struct rtentry rt;
 
-    if (defaultroute_exists(&rt))
+    if (defaultroute_exists(&rt) && strcmp(rt.rt_dev, ifname) != 0)
       {
        struct in_addr old_gateway =
          ((struct sockaddr_in *) (&rt.rt_gateway))-> sin_addr;
@@ -1266,8 +1344,7 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
          {
            syslog (LOG_ERR,
                    "not replacing existing default route to %s [%s]",
-                   rt.rt_dev,
-                   inet_ntoa (old_gateway));
+                   rt.rt_dev, inet_ntoa (old_gateway));
          }
        return 0;
       }
@@ -1276,10 +1353,10 @@ int sifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
 
-#if LINUX_VERSION_CODE > 0x020100
-    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
-    ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L;
-#endif
+    if (kernel_version > KVERSION(2,1,0)) {
+      SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+      ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L;
+    }
 
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
     
@@ -1312,10 +1389,10 @@ int cifdefaultroute (int unit, u_int32_t ouraddr, u_int32_t gateway)
     SET_SA_FAMILY (rt.rt_dst,     AF_INET);
     SET_SA_FAMILY (rt.rt_gateway, AF_INET);
 
-#if LINUX_VERSION_CODE > 0x020100
-    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
-    ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L;
-#endif
+    if (kernel_version > KVERSION(2,1,0)) {
+      SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+      ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = 0L;
+    }
 
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
     
@@ -1416,8 +1493,7 @@ static int get_ether_addr (u_int32_t ipaddr,
                           struct sockaddr *hwaddr,
                           char *name)
   {
-    struct ifreq *ifr, *ifend, *ifp;
-    int i;
+    struct ifreq *ifr, *ifend;
     u_int32_t ina, mask;
     struct ifreq ifreq;
     struct ifconf ifc;
@@ -1446,7 +1522,7 @@ static int get_ether_addr (u_int32_t ipaddr,
        if (ifr->ifr_addr.sa_family == AF_INET)
          {
            ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
-           strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+           strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
             SYSDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
                        ifreq.ifr_name));
 /*
@@ -1585,7 +1661,7 @@ u_int32_t GetMask (u_int32_t addr)
 /*
  * Check that the interface is up, and not point-to-point nor loopback.
  */
-       strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+       strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
        if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
          {
            continue;
@@ -1641,7 +1717,7 @@ static void decode_version (char *buf, int *version,
 
 /********************************************************************
  *
- * Procedure to determine if the PPP line dicipline is registered.
+ * Procedure to determine if the PPP line discipline is registered.
  */
 
 int
@@ -1704,7 +1780,7 @@ ppp_registered(void)
  */
 
 int ppp_available(void)
-  {
+{
     int s, ok;
     struct ifreq ifr;
     int    size;
@@ -1715,11 +1791,11 @@ int ppp_available(void)
  */    
     s = socket(AF_INET, SOCK_DGRAM, 0);
     if (s < 0)
-      {
+    {
        return 0;
-      }
+    }
     
-    strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
+    strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), "ppp0");
     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
 /*
  * If the device did not exist then attempt to create one by putting the
@@ -1727,97 +1803,92 @@ int ppp_available(void)
  * flags for the device again.
  */
     if (!ok)
-      {
+    {
        if (ppp_registered())
-         {
-           strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
+       {
+           strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), "ppp0");
            ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
-         }
-      }
+       }
+    }
 /*
  * Ensure that the hardware address is for PPP and not something else
  */
     if (ok)
-      {
+    {
         ok = ioctl (s, SIOCGIFHWADDR, (caddr_t) &ifr) >= 0;
-      }
+    }
 
     if (ok && ((ifr.ifr_hwaddr.sa_family & ~0xFF) != ARPHRD_PPP))
-      {
+    {
         ok = 0;
-      }
+    }
 
     if (!ok)
-      {
+    {
        no_ppp_msg = 
          "This system lacks kernel support for PPP.  This could be because\n"
          "the PPP kernel module is not loaded, or because the kernel is\n"
          "not configured for PPP.  See the README.linux file in the\n"
-         "ppp-2.3.1 distribution.\n";
-      }
+         "ppp-2.3.6 distribution.\n";
+    }
 /*
  *  This is the PPP device. Validate the version of the driver at this
  *  point to ensure that this program will work with the driver.
  */
     else
-      {
+    {
        char   abBuffer [1024];
 
        ifr.ifr_data = abBuffer;
        size = ioctl (s, SIOCGPPPVER, (caddr_t) &ifr);
-       ok   = size >= 0;
+       if (size < 0) {
+           syslog(LOG_ERR, "Couldn't read driver version: %m");
+           ok = 0;
+           no_ppp_msg = "Sorry, couldn't verify kernel driver version\n";
 
-       if (ok)
-         {
-           decode_version (abBuffer,
-                           &driver_version,
-                           &driver_modification,
-                           &driver_patch);
-         }
-    
-       if (!ok)
-         {
-           driver_version      =
-           driver_modification =
-           driver_patch        = 0;
-         }
+       } else {
+           decode_version(abBuffer,
+                          &driver_version,
+                          &driver_modification,
+                          &driver_patch);
 /*
  * Validate the version of the driver against the version that we used.
  */
-       decode_version (PPP_VERSION,
-                       &my_version,
-                       &my_modification,
-                       &my_patch);
+           decode_version(VERSION,
+                          &my_version,
+                          &my_modification,
+                          &my_patch);
 
-       /* The version numbers must match */
-       if (driver_version != my_version)
-         {
-           ok = 0;
-         }
+           /* The version numbers must match */
+           if (driver_version != my_version)
+           {
+               ok = 0;
+           }
       
-       /* The modification levels must be legal */
-       if (driver_modification < my_modification)
-         {
-           if (driver_modification >= 2) {
-             /* we can cope with 2.2.0 and above */
-             driver_is_old = 1;
-           } else {
-             ok = 0;
+           /* The modification levels must be legal */
+           if (driver_modification < 3)
+           {
+               if (driver_modification >= 2) {
+                   /* we can cope with 2.2.0 and above */
+                   driver_is_old = 1;
+               } else {
+                   ok = 0;
+               }
            }
-         }
 
-       close (s);
-       if (!ok)
-         {
-           sprintf (route_buffer,
-                    "Sorry - PPP driver version %d.%d.%d is out of date\n",
-                    driver_version, driver_modification, driver_patch);
+           close (s);
+           if (!ok)
+           {
+               sprintf (route_buffer,
+                        "Sorry - PPP driver version %d.%d.%d is out of date\n",
+                        driver_version, driver_modification, driver_patch);
 
-           no_ppp_msg = route_buffer;
-         }
-      }
+               no_ppp_msg = route_buffer;
+           }
+       }
+    }
     return ok;
-  }
+}
 
 /********************************************************************
  *
@@ -1853,11 +1924,11 @@ void logwtmp (const char *line, const char *name, const char *host)
 
     if (ut.ut_id[0] == 0)
       {
-       strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
+       strlcpy(ut.ut_id, sizeof(ut.ut_id), line + 3);
       }
        
-    strncpy(ut.ut_user, name, sizeof(ut.ut_user));
-    strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+    strlcpy(ut.ut_user, sizeof(ut.ut_user), name);
+    strlcpy(ut.ut_line, sizeof(ut.ut_line), line);
 
     time(&ut.ut_time);
 
@@ -1867,7 +1938,7 @@ void logwtmp (const char *line, const char *name, const char *host)
     /* Insert the host name if one is supplied */
     if (*host)
       {
-       strncpy (ut.ut_host, host, sizeof(ut.ut_host));
+       strlcpy (ut.ut_host, sizeof(ut.ut_host), host);
       }
 
     /* Insert the IP address of the remote system if IP is enabled */
@@ -1911,63 +1982,52 @@ void logwtmp (const char *line, const char *name, const char *host)
  */
 
 int lock (char *dev)
-  {
+{
 #ifdef LOCKLIB
     int result;
-    lock_file = malloc(strlen(dev) + 1);
+    lock_file = strdup(dev);
     if (lock_file == NULL)
-      {
        novm("lock file name");
-      }
-    strcpy (lock_file, dev);
     result = mklock (dev, (void *) 0);
 
-    if (result > 0)
-      {
+    if (result > 0) {
         syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, result);
        free (lock_file);
        lock_file = NULL;
        result = -1;
-      }
-    else
-      {
-        if (result < 0)
-         {
+    }
+    else {
+        if (result < 0) {
            syslog (LOG_ERR, "Can't create lock file %s", lock_file);
            free (lock_file);
            lock_file = NULL;
            result = -1;
-         }
-      }
+       }
+    }
     return (result);
 #else
     char hdb_lock_buffer[12];
     int fd, n;
     int pid = getpid();
     char *p;
+    size_t l;
 
     p = strrchr(dev, '/');
     if (p != NULL)
-      {
        dev = ++p;
-      }
 
-    lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
+    l = strlen(LOCK_PREFIX) + strlen(dev) + 1;
+    lock_file = malloc(l);
     if (lock_file == NULL)
-      {
        novm("lock file name");
-      }
 
-    strcpy (lock_file, LOCK_PREFIX);
-    strcat (lock_file, dev);
+    slprintf(lock_file, l, "%s%s", LOCK_PREFIX, dev);
 /*
  * Attempt to create the lock file at this point.
  */
-    while (1)
-      {
+    while (1) {
        fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644);
-       if (fd >= 0)
-         {
+       if (fd >= 0) {
            pid = getpid();
 #ifndef PID_BINARY
            sprintf (hdb_lock_buffer, "%010d\n", pid);
@@ -1977,34 +2037,28 @@ int lock (char *dev)
 #endif
            close(fd);
            return 0;
-         }
+       }
 /*
  * If the file exists then check to see if the pid is stale
  */
-       if (errno == EEXIST)
-         {
+       if (errno == EEXIST) {
            fd = open(lock_file, O_RDONLY, 0);
-           if (fd < 0)
-             {
+           if (fd < 0) {
                if (errno == ENOENT) /* This is just a timing problem. */
-                 {
                    continue;
-                 }
                break;
-             }
+           }
 
            /* Read the lock file to find out who has the device locked */
            n = read (fd, hdb_lock_buffer, 11);
            close (fd);
-           if (n < 0)
-             {
+           if (n < 0) {
                syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
                break;
-             }
+           }
 
            /* See the process still exists. */
-           if (n > 0)
-             {
+           if (n > 0) {
 #ifndef PID_BINARY
                hdb_lock_buffer[n] = '\0';
                sscanf (hdb_lock_buffer, " %d", &pid);
@@ -2013,26 +2067,23 @@ int lock (char *dev)
 #endif
                if (pid == 0 || pid == getpid()
                    || (kill(pid, 0) == -1 && errno == ESRCH))
-                 {
                    n = 0;
-                 }
-             }
+           }
 
            /* If the process does not exist then try to remove the lock */
-           if (n == 0 && unlink (lock_file) == 0)
-             {
+           if (n == 0 && unlink (lock_file) == 0) {
                syslog (LOG_NOTICE, "Removed stale lock on %s (pid %d)",
                        dev, pid);
                continue;
-             }
+           }
 
            syslog (LOG_NOTICE, "Device %s is locked by pid %d", dev, pid);
            break;
-         }
+       }
 
        syslog(LOG_ERR, "Can't create lock file %s: %m(%d)", lock_file, errno);
        break;
-      }
+    }
 
     free(lock_file);
     lock_file = NULL;
@@ -2075,7 +2126,7 @@ int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
          {
            if (! ok_error (errno))
              {
-               syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m(%d)", errno);
+               syslog (LOG_ERR, "ioctl(PPPIOCSMAXCID): %m(%d)", errno);
              }
            vjcomp = 0;
          }
@@ -2098,7 +2149,7 @@ int sifup (int u)
     struct ifreq ifr;
 
     memset (&ifr, '\0', sizeof (ifr));
-    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+    strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
       {
        if (! ok_error (errno))
@@ -2133,7 +2184,7 @@ int sifdown (int u)
     if_is_up = 0;
 
     memset (&ifr, '\0', sizeof (ifr));
-    strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+    strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0)
       {
        if (! ok_error (errno))
@@ -2174,7 +2225,7 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
     SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET); 
     SET_SA_FAMILY (ifr.ifr_netmask, AF_INET); 
 
-    strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+    strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
 /*
  *  Set our IP address
  */
@@ -2207,8 +2258,11 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
        return (0);
       } 
 /*
- *  Set the netmask
+ *  Set the netmask.
+ *  For recent kernels, force the netmask to 255.255.255.255.
  */
+    if (kernel_version >= KVERSION(2,1,16))
+      net_mask = ~0L;
     if (net_mask != 0)
       {
        ((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
@@ -2224,29 +2278,29 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
 /*
  *  Add the device route
  */
-#if LINUX_VERSION_CODE < 0x020100+16           /* 2.1.16 */
-    SET_SA_FAMILY (rt.rt_dst,     AF_INET);
-    SET_SA_FAMILY (rt.rt_gateway, AF_INET);
-    rt.rt_dev = ifname;
+    if (kernel_version < KVERSION(2,1,16)) {
+      SET_SA_FAMILY (rt.rt_dst,     AF_INET);
+      SET_SA_FAMILY (rt.rt_gateway, AF_INET);
+      rt.rt_dev = ifname;
 
-    ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0L;
-    ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
-    rt.rt_flags = RTF_UP | RTF_HOST;
-
-#if LINUX_VERSION_CODE > 0x020100
-    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
-    ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L;
-#endif
+      ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0L;
+      ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
+      rt.rt_flags = RTF_UP | RTF_HOST;
 
-    if (ioctl(sock_fd, SIOCADDRT, &rt) < 0)
-      {
-       if (! ok_error (errno))
-         {
-           syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m(%d)", errno);
-         }
-        return (0);
+      if (kernel_version > KVERSION(2,1,0)) {
+       SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+       ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L;
       }
-#endif
+
+      if (ioctl(sock_fd, SIOCADDRT, &rt) < 0)
+       {
+         if (! ok_error (errno))
+           {
+             syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m(%d)", errno);
+           }
+         return (0);
+       }
+    }
     return 1;
   }
 
@@ -2258,35 +2312,36 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
 
 int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
   {
-#if LINUX_VERSION_CODE < 0x020100+16           /* 2.1.16 */
     struct rtentry rt;
+
+    if (kernel_version < KVERSION(2,1,16)) {
 /*
  *  Delete the route through the device
  */
-    memset (&rt, '\0', sizeof (rt));
+      memset (&rt, '\0', sizeof (rt));
 
-    SET_SA_FAMILY (rt.rt_dst,     AF_INET);
-    SET_SA_FAMILY (rt.rt_gateway, AF_INET);
-    rt.rt_dev = ifname;
-
-    ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
-    ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
-    rt.rt_flags = RTF_UP | RTF_HOST;
+      SET_SA_FAMILY (rt.rt_dst,     AF_INET);
+      SET_SA_FAMILY (rt.rt_gateway, AF_INET);
+      rt.rt_dev = ifname;
 
-#if LINUX_VERSION_CODE > 0x020100
-    SET_SA_FAMILY (rt.rt_genmask, AF_INET);
-    ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L;
-#endif
+      ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
+      ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr     = his_adr;
+      rt.rt_flags = RTF_UP | RTF_HOST;
 
-    if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH)
-      {
-       if (still_ppp() && ! ok_error (errno))
-         {
-           syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m(%d)", errno);
-         }
-       return (0);
+      if (kernel_version > KVERSION(2,1,0)) {
+       SET_SA_FAMILY (rt.rt_genmask, AF_INET);
+       ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = -1L;
       }
-#endif
+
+      if (ioctl(sock_fd, SIOCDELRT, &rt) < 0 && errno != ESRCH)
+       {
+         if (still_ppp() && ! ok_error (errno))
+           {
+             syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m(%d)", errno);
+           }
+         return (0);
+       }
+    }
     return 1;
   }
 
@@ -2305,7 +2360,7 @@ open_ppp_loopback(void)
     master_fd = -1;
     for (i = 0; i < 64; ++i) {
       sprintf(loop_name, "/dev/pty%c%x", 'p' + i / 16, i % 16);
-      master_fd = open(loop_name, O_RDWR, 0);
+      master_fd = open(loop_name, O_RDWR | O_NOCTTY, 0);
       if (master_fd >= 0)
        break;
     }
@@ -2315,7 +2370,7 @@ open_ppp_loopback(void)
     }
     SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
     loop_name[5] = 't';
-    slave_fd = open(loop_name, O_RDWR, 0);
+    slave_fd = open(loop_name, O_RDWR | O_NOCTTY, 0);
     if (slave_fd < 0) {
       syslog(LOG_ERR, "Couldn't open %s for loopback: %m", loop_name);
       die(1);
@@ -2421,8 +2476,6 @@ sifnpmode(u, proto, mode)
   }
 
 \f
-#include <linux/ipx.h>
-
 /********************************************************************
  *
  * sipxfaddr - Config the interface IPX networknumber
@@ -2434,7 +2487,6 @@ int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
 
 #ifdef IPX_CHANGE
     int    skfd; 
-    struct sockaddr_ipx  ipx_addr;
     struct ifreq         ifr;
     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
 
@@ -2450,7 +2502,7 @@ int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
     else
       {
        memset (&ifr, '\0', sizeof (ifr));
-       strcpy (ifr.ifr_name, ifname);
+       strlcpy (ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
 
        memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
        sipx->sipx_family  = AF_IPX;
@@ -2497,7 +2549,6 @@ int cipxfaddr (int unit)
 
 #ifdef IPX_CHANGE
     int    skfd; 
-    struct sockaddr_ipx  ipx_addr;
     struct ifreq         ifr;
     struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
 
@@ -2513,7 +2564,7 @@ int cipxfaddr (int unit)
     else
       {
        memset (&ifr, '\0', sizeof (ifr));
-       strcpy (ifr.ifr_name, ifname);
+       strlcpy (ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
 
        sipx->sipx_type    = IPX_FRAME_ETHERII;
        sipx->sipx_action  = IPX_DLTITF;
@@ -2560,12 +2611,27 @@ daemon(nochdir, noclose)
     return 0;
 }
 
+/*
+ * Use the hostname as part of the random number seed.
+ */
+int
+get_host_seed()
+{
+    int h;
+    char *p = hostname;
+
+    h = 407;
+    for (p = hostname; *p != 0; ++p)
+       h = h * 37 + *p;
+    return h;
+}
+
 /********************************************************************
  *
  * sys_check_options - check the options that the user specified
  */
 
-void
+int
 sys_check_options(void)
   {
 #ifdef IPX_CHANGE
@@ -2578,7 +2644,7 @@ sys_check_options(void)
       {
         if (path_to_procfs())
          {
-           strcat (route_buffer, "/net/ipx_interface");
+           strlcat (route_buffer, sizeof(route_buffer), "/net/ipx_interface");
            if (lstat (route_buffer, &stat_buf) >= 0)
              {
                break;
@@ -2594,6 +2660,7 @@ sys_check_options(void)
       option_error("demand dialling is not supported by kernel driver version "
                   "%d.%d.%d", driver_version, driver_modification,
                   driver_patch);
-      demand = 0;
+      return 0;
     }
+    return 1;
   }