]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-linux.c
fix strtok loop
[ppp.git] / pppd / sys-linux.c
index e85988665924545ac1887d1b22d5c9570b8894aa..4cc8987cc57b84cce67e167de7b4779379da14e5 100644 (file)
@@ -122,8 +122,6 @@ static u_int32_t default_route_gateway;     /* Gateway for default route added */
 static u_int32_t proxy_arp_addr;       /* Addr for proxy arp entry added */
 static char proxy_arp_dev[16];         /* Device for proxy arp entry */
 
-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))
@@ -167,10 +165,6 @@ extern u_char      inpacket_buf[]; /* borrowed from main.c */
 
 extern int hungup;
 
-#ifndef LOCK_PREFIX
-#define LOCK_PREFIX    "/var/lock/LCK.."
-#endif
-
 static void set_ppp_fd (int new_fd)
 {
        SYSDEBUG ((LOG_DEBUG, "setting ppp_fd to %d\n", new_fd));
@@ -387,10 +381,12 @@ int establish_ppp (int tty_fd)
 
 void disestablish_ppp(int tty_fd)
 {
+    if (!hungup) {
 /*
- * Attempt to restore the previous tty settings
+ * Flush the tty output buffer so that the TIOCSETD doesn't hang.
  */
-    if (!hungup) {
+       if (tcflush(tty_fd, TCIOFLUSH) < 0)
+           warn("tcflush failed: %m");
 /*
  * Restore the previous line discipline
  */
@@ -866,6 +862,7 @@ void ppp_send_config (int unit,int mtu,u_int32_t asyncmap,int pcomp,int accomp)
     x = get_flags();
     x = pcomp  ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
     x = accomp ? x | SC_COMP_AC   : x & ~SC_COMP_AC;
+    x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC;
     set_flags(x);
 }
 
@@ -1027,7 +1024,7 @@ static int read_route_table (struct rtentry *rt);
  * path_to_procfs - find the path to the proc file system mount point
  */
 
-static int path_to_procfs (void)
+static int path_to_procfs (const char *tail)
 {
     struct mntent *mntent;
     FILE *fp;
@@ -1036,6 +1033,7 @@ static int path_to_procfs (void)
     if (fp == NULL) {
        /* Default the mount location of /proc */
        strlcpy (route_buffer, "/proc", sizeof (route_buffer));
+       strlcat (route_buffer, tail, sizeof(route_buffer));
        return 1;
     }
 
@@ -1050,6 +1048,7 @@ static int path_to_procfs (void)
        return 0;
 
     strlcpy(route_buffer, mntent->mnt_dir, sizeof (route_buffer));
+    strlcat (route_buffer, tail, sizeof(route_buffer));
     return 1;
 }
 
@@ -1060,11 +1059,10 @@ static int path_to_procfs (void)
 
 static char *path_to_route (void)
 {
-    if (!path_to_procfs()) {
+    if (!path_to_procfs("/net/route")) {
        error("proc file system not mounted");
        return 0;
     }
-    strlcat (route_buffer, "/net/route", sizeof(route_buffer));
     return (route_buffer);
 }
 
@@ -1159,6 +1157,7 @@ static int read_route_table(struct rtentry *rt)
        cols[col] = strtok(p, route_delims);
        if (cols[col] == NULL)
            return 0;           /* didn't get enough columns */
+       p = NULL;
     }
 
     ((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
@@ -1569,48 +1568,33 @@ static int
 ppp_registered(void)
 {
     int local_fd;
-    int init_disc = -1;
-    int initfdflags;
-
-    local_fd = open(devnam, O_NONBLOCK | O_RDWR, 0);
-    if (local_fd < 0) {
-       error("Failed to open %s: %m(%d)", devnam, errno);
-       return 0;
-    }
-
-    initfdflags = fcntl(local_fd, F_GETFL);
-    if (initfdflags == -1) {
-       error("Couldn't get device fd flags: %m(%d)", errno);
-       close (local_fd);
+    int mfd = -1;
+    int ret = 0;
+    char slave[16];
+
+    /*
+     * We used to open the serial device and set it to the ppp line
+     * discipline here, in order to create a ppp unit.  But that is
+     * not a good idea - the user might have specified a device that
+     * they can't open (permission, or maybe it doesn't really exist).
+     * So we grab a pty master/slave pair and use that.
+     */
+    if (!get_pty(&mfd, &local_fd, slave, 0)) {
+       no_ppp_msg = "Couldn't determine if PPP is supported (no free ptys)";
        return 0;
     }
 
-    initfdflags &= ~O_NONBLOCK;
-    fcntl(local_fd, F_SETFL, initfdflags);
-/*
- * Read the initial line dicipline and try to put the device into the
- * PPP dicipline.
- */
-    if (ioctl(local_fd, TIOCGETD, &init_disc) < 0) {
-       error("ioctl(TIOCGETD): %m(%d)", errno);
-       close (local_fd);
-       return 0;
-    }
-    
+    /*
+     * Try to put the device into the PPP discipline.
+     */
     if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
-       error("ioctl(TIOCSETD): %m(%d)", errno);
-       close (local_fd);
-       return 0;
-    }
-    
-    if (ioctl(local_fd, TIOCSETD, &init_disc) < 0) {
-       error("ioctl(TIOCSETD): %m(%d)", errno);
-       close (local_fd);
-       return 0;
-    }
+       error("ioctl(TIOCSETD(PPP)): %m(%d)", errno);
+    } else
+       ret = 1;
     
-    close (local_fd);
-    return 1;
+    close(local_fd);
+    close(mfd);
+    return ret;
 }
 
 /********************************************************************
@@ -1625,7 +1609,15 @@ int ppp_available(void)
     struct ifreq ifr;
     int    size;
     int    my_version, my_modification, my_patch;
-    extern char *no_ppp_msg;
+
+    no_ppp_msg = 
+       "This system lacks kernel support for PPP.  This could be because\n"
+       "the PPP kernel module could not be loaded, or because PPP was not\n"
+       "included in the kernel configuration.  If PPP was included as a\n"
+       "module, try `/sbin/modprobe -v ppp'.  If that fails, check that\n"
+       "ppp.o exists in /lib/modules/`uname -r`/net.\n"
+       "See README.linux file in the ppp distribution for more details.\n";
+
 /*
  * Open a socket for doing the ioctl operations.
  */    
@@ -1655,18 +1647,11 @@ int ppp_available(void)
     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.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 {
+    if (ok) {
        char   abBuffer [1024];
 
        ifr.ifr_data = abBuffer;
@@ -1745,10 +1730,10 @@ void logwtmp (const char *line, const char *name, const char *host)
        memset(&ut, 0, sizeof(ut));
 
     if (ut.ut_id[0] == 0)
-       strlcpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
+       strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
        
-    strlcpy(ut.ut_user, name, sizeof(ut.ut_user));
-    strlcpy(ut.ut_line, line, sizeof(ut.ut_line));
+    strncpy(ut.ut_user, name, sizeof(ut.ut_user));
+    strncpy(ut.ut_line, line, sizeof(ut.ut_line));
 
     time(&ut.ut_time);
 
@@ -1757,7 +1742,7 @@ void logwtmp (const char *line, const char *name, const char *host)
 
     /* Insert the host name if one is supplied */
     if (*host)
-       strlcpy (ut.ut_host, host, sizeof(ut.ut_host));
+       strncpy (ut.ut_host, host, sizeof(ut.ut_host));
 
     /* Insert the IP address of the remote system if IP is enabled */
     if (ipcp_protent.enabled_flag && ipcp_hisoptions[0].neg_addr)
@@ -1785,11 +1770,18 @@ void logwtmp (const char *line, const char *name, const char *host)
     }
 }
 
+#if 0
 /********************************************************************
  * Code for locking/unlocking the serial device.
  * This code is derived from chat.c.
  */
 
+#ifndef LOCK_PREFIX
+#define LOCK_PREFIX    "/var/lock/LCK.."
+#endif
+
+static char *lock_file;
+
 /*
  * lock - create a lock file for the named device
  */
@@ -1922,6 +1914,7 @@ void unlock(void)
        lock_file = NULL;
     }
 }
+#endif
 
 /********************************************************************
  *
@@ -2125,7 +2118,7 @@ int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
 
 /*
  * get_pty - get a pty master/slave pair and chown the slave side
- * to the uid given.  Assumes slave_name points to >= 12 bytes of space.
+ * to the uid given.  Assumes slave_name points to >= 16 bytes of space.
  */
 int
 get_pty(master_fdp, slave_fdp, slave_name, uid)
@@ -2134,31 +2127,56 @@ get_pty(master_fdp, slave_fdp, slave_name, uid)
     char *slave_name;
     int uid;
 {
-    int i, mfd, sfd;
-    char pty_name[12];
+    int i, mfd, sfd = -1;
+    char pty_name[16];
     struct termios tios;
 
-    sfd = -1;
-    for (i = 0; i < 64; ++i) {
-       slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
-                'p' + i / 16, i % 16);
-       mfd = open(pty_name, O_RDWR, 0);
-       if (mfd >= 0) {
-           pty_name[5] = 't';
-           sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
-           if (sfd >= 0)
-               break;
-           close(mfd);
+#ifdef TIOCGPTN
+    /*
+     * Try the unix98 way first.
+     */
+    mfd = open("/dev/ptmx", O_RDWR);
+    if (mfd >= 0) {
+       int ptn;
+       if (ioctl(mfd, TIOCGPTN, &ptn) >= 0) {
+           slprintf(pty_name, sizeof(pty_name), "/dev/pts/%d", ptn);
+           chmod(pty_name, S_IRUSR | S_IWUSR);
+#ifdef TIOCSPTLCK
+           ptn = 0;
+           if (ioctl(mfd, TIOCSPTLCK, &ptn) < 0)
+               warn("Couldn't unlock pty slave %s: %m", pty_name);
+#endif
+           if ((sfd = open(pty_name, O_RDWR)) < 0)
+               warn("Couldn't open pty slave %s: %m", pty_name);
+       }
+    }
+#endif /* TIOCGPTN */
+
+    if (sfd < 0) {
+       /* the old way - scan through the pty name space */
+       for (i = 0; i < 64; ++i) {
+           slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
+                    'p' + i / 16, i % 16);
+           mfd = open(pty_name, O_RDWR, 0);
+           if (mfd >= 0) {
+               pty_name[5] = 't';
+               sfd = open(pty_name, O_RDWR | O_NOCTTY, 0);
+               if (sfd >= 0) {
+                   fchown(sfd, uid, -1);
+                   fchmod(sfd, S_IRUSR | S_IWUSR);
+                   break;
+               }
+               close(mfd);
+           }
        }
     }
+
     if (sfd < 0)
        return 0;
 
-    strlcpy(slave_name, pty_name, 12);
+    strlcpy(slave_name, pty_name, 16);
     *master_fdp = mfd;
     *slave_fdp = sfd;
-    fchown(sfd, uid, -1);
-    fchmod(sfd, S_IRUSR | S_IWUSR);
     if (tcgetattr(sfd, &tios) == 0) {
        tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
        tios.c_cflag |= CS8 | CREAD;
@@ -2355,6 +2373,7 @@ int cipxfaddr (int unit)
     return result;
 }
 
+#if 0
 /*
  * daemon - Detach us from controlling terminal session.
  */
@@ -2378,6 +2397,7 @@ daemon(nochdir, noclose)
     }
     return 0;
 }
+#endif
 
 /*
  * Use the hostname as part of the random number seed.
@@ -2403,21 +2423,16 @@ int
 sys_check_options(void)
 {
 #ifdef IPX_CHANGE
-    struct stat stat_buf;
 /*
  * Disable the IPX protocol if the support is not present in the kernel.
- * If we disable it then ensure that IP support is enabled.
  */
-    while (ipxcp_protent.enabled_flag) {
-        if (path_to_procfs()) {
-           strlcat (route_buffer, "/net/ipx_interface", sizeof(route_buffer));
-           if (lstat (route_buffer, &stat_buf) >= 0)
-               break;
+    if (ipxcp_protent.enabled_flag) {
+       struct stat stat_buf;
+        if (!path_to_procfs("/net/ipx_interface")
+           || lstat (route_buffer, &stat_buf) < 0) {
+           error("IPX support is not present in the kernel\n");
+           ipxcp_protent.enabled_flag = 0;
        }
-       error("IPX support is not present in the kernel\n");
-       ipxcp_protent.enabled_flag = 0;
-       ipcp_protent.enabled_flag  = 1;
-       break;
     }
 #endif
     if (demand && driver_is_old) {