]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-linux.c
make it compile under sunos
[ppp.git] / pppd / sys-linux.c
index 0ed73fd81dc0ccda2a9388207ae64ae4eb22c6d2..43855a932afaff000fc419412e873aca7ce17612 100644 (file)
@@ -120,6 +120,7 @@ static unsigned char inbuf[512]; /* buffer for chars read from loopback */
 static int     if_is_up;       /* Interface has been marked up */
 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;
 
@@ -144,8 +145,10 @@ static int open_route_table (void);
 static int read_route_table (struct rtentry *rt);
 static int defaultroute_exists (struct rtentry *rt);
 static int get_ether_addr (u_int32_t ipaddr, struct sockaddr *hwaddr,
-                          char *name);
+                          char *name, int namelen);
 static void decode_version (char *buf, int *version, int *mod, int *patch);
+static int set_kdebugflag(int level);
+static int ppp_registered(void);
 
 extern u_char  inpacket_buf[]; /* borrowed from main.c */
 
@@ -251,7 +254,7 @@ void sys_init(void)
  *
  * sys_cleanup - restore any system state we modified before exiting:
  * mark the interface down, delete default route and/or proxy arp entry.
- * This should call die() because it's called from die().
+ * This shouldn't call die() because it's called from die().
  */
 
 void sys_cleanup(void)
@@ -278,33 +281,21 @@ void sys_cleanup(void)
 void
 sys_close(void)
 {
-    close(sock_fd);
-    sock_fd = -1;
+    if (sock_fd >= 0)
+       close(sock_fd);
+    if (slave_fd >= 0)
+       close(slave_fd);
+    if (master_fd >= 0)
+       close(master_fd);
     closelog();
 }
 
-/********************************************************************
- *
- * note_debug_level - note a change in the debug level.
- */
-
-void note_debug_level (void)
-{
-    if (debug) {
-       SYSDEBUG ((LOG_INFO, "Debug turned ON, Level %d", debug));
-       setlogmask(LOG_UPTO(LOG_DEBUG));
-    }
-    else {
-       setlogmask(LOG_UPTO(LOG_WARNING));
-    }
-}
-
 /********************************************************************
  *
  * set_kdebugflag - Define the debugging level for the kernel
  */
 
-int set_kdebugflag (int requested_level)
+static int set_kdebugflag (int requested_level)
 {
     if (ioctl(ppp_fd, PPPIOCSDEBUG, &requested_level) < 0) {
        if ( ! ok_error (errno) )
@@ -660,7 +651,7 @@ void set_up_tty(int tty_fd, int local)
            fatal("tcsetattr: %m");
     
     baud_rate    = baud_rate_of(speed);
-    restore_term = TRUE;
+    restore_term = 1;
 }
 
 /********************************************************************
@@ -859,7 +850,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));
-    strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
     ifr.ifr_mtu = mtu;
        
     if (ioctl(sock_fd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
@@ -875,6 +866,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);
 }
 
@@ -978,6 +970,30 @@ get_idle_time(u, ip)
     return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
 } 
 
+/********************************************************************
+ *
+ * get_ppp_stats - return statistics for the link.
+ */
+int
+get_ppp_stats(u, stats)
+    int u;
+    struct pppd_stats *stats;
+{
+    struct ifpppstatsreq req;
+
+    memset (&req, 0, sizeof (req));
+
+    req.stats_ptr = (caddr_t) &req.stats;
+    strlcpy(req.ifr__name, ifname, sizeof(req.ifr__name));
+    if (ioctl(sock_fd, SIOCGPPPSTATS, &req) < 0) {
+       error("Couldn't get PPP statistics: %m");
+       return 0;
+    }
+    stats->bytes_in = req.stats.p.ppp_ibytes;
+    stats->bytes_out = req.stats.p.ppp_obytes;
+    return 1;
+}
+
 /********************************************************************
  *
  * ccp_fatal_error - returns 1 if decompression was disabled as a
@@ -1020,7 +1036,7 @@ static int path_to_procfs (void)
     fp = fopen(MOUNTED, "r");
     if (fp == NULL) {
        /* Default the mount location of /proc */
-       strlcpy (route_buffer, sizeof (route_buffer), "/proc");
+       strlcpy (route_buffer, "/proc", sizeof (route_buffer));
        return 1;
     }
 
@@ -1034,7 +1050,7 @@ static int path_to_procfs (void)
     if (mntent == 0)
        return 0;
 
-    strlcpy(route_buffer, sizeof (route_buffer), mntent->mnt_dir);
+    strlcpy(route_buffer, mntent->mnt_dir, sizeof (route_buffer));
     return 1;
 }
 
@@ -1049,7 +1065,7 @@ static char *path_to_route (void)
        error("proc file system not mounted");
        return 0;
     }
-    strlcat (route_buffer, sizeof(route_buffer), "/net/route");
+    strlcat (route_buffer, "/net/route", sizeof(route_buffer));
     return (route_buffer);
 }
 
@@ -1310,11 +1326,13 @@ int sifproxyarp (int unit, u_int32_t his_adr)
  * Get the hardware address of an interface on the same subnet
  * as our local address.
  */
-       if (!get_ether_addr(his_adr, &arpreq.arp_ha, arpreq.arp_dev)) {
+       if (!get_ether_addr(his_adr, &arpreq.arp_ha, proxy_arp_dev,
+                           sizeof(proxy_arp_dev))) {
            error("Cannot determine ethernet address for proxy ARP");
            return 0;
        }
-       
+       strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
+
        if (ioctl(sock_fd, SIOCSARP, (caddr_t)&arpreq) < 0) {
            if ( ! ok_error ( errno ))
                error("ioctl(SIOCSARP): %m(%d)", errno);
@@ -1342,6 +1360,7 @@ int cifproxyarp (int unit, u_int32_t his_adr)
        SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
        ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
        arpreq.arp_flags = ATF_PERM | ATF_PUBL;
+       strlcpy(arpreq.arp_dev, proxy_arp_dev, sizeof(arpreq.arp_dev));
 
        if (ioctl(sock_fd, SIOCDARP, (caddr_t)&arpreq) < 0) {
            if ( ! ok_error ( errno ))
@@ -1360,7 +1379,7 @@ int cifproxyarp (int unit, u_int32_t his_adr)
 
 static int get_ether_addr (u_int32_t ipaddr,
                           struct sockaddr *hwaddr,
-                          char *name)
+                          char *name, int namelen)
 {
     struct ifreq *ifr, *ifend;
     u_int32_t ina, mask;
@@ -1386,7 +1405,7 @@ static int get_ether_addr (u_int32_t ipaddr,
     for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
        if (ifr->ifr_addr.sa_family == AF_INET) {
            ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
-           strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
+           strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
             SYSDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
                        ifreq.ifr_name));
 /*
@@ -1417,7 +1436,7 @@ static int get_ether_addr (u_int32_t ipaddr,
     if (ifr >= ifend)
         return 0;
 
-    memcpy (name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
+    strlcpy(name, ifreq.ifr_name, namelen);
     info("found interface %s for proxy arp", name);
 /*
  * Now get the hardware address.
@@ -1497,7 +1516,7 @@ u_int32_t GetMask (u_int32_t addr)
 /*
  * Check that the interface is up, and not point-to-point nor loopback.
  */
-       strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
+       strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
        if (ioctl(sock_fd, SIOCGIFFLAGS, &ifreq) < 0)
            continue;
        
@@ -1547,52 +1566,44 @@ static void decode_version (char *buf, int *version,
  * Procedure to determine if the PPP line discipline is registered.
  */
 
-int
+static int
 ppp_registered(void)
 {
     int local_fd;
     int init_disc = -1;
-    int initfdflags;
+    int mfd = -1;
+    int ret = 0;
 
-    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);
-       return 0;
+    if (devnam[0] == 0) {
+       /* running with notty or pty option */
+       char slave[16];
+       if (!get_pty(&mfd, &local_fd, slave, 0))
+           return 0;
+    } else {
+       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 &= ~O_NONBLOCK;
-    fcntl(local_fd, F_SETFL, initfdflags);
 /*
- * Read the initial line dicipline and try to put the device into the
+ * Read the initial line discipline 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;
-    }
-    
-    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;
-    }
+    } else if (ioctl(local_fd, TIOCSETD, &ppp_disc) < 0) {
+       error("ioctl(TIOCSETD(PPP)): %m(%d)", errno);
+    } else if (ioctl(local_fd, TIOCSETD, &init_disc) < 0) {
+       error("ioctl(TIOCSETD(%d)): %m(%d)", init_disc, errno);
+    } else
+       ret = 1;
     
     close (local_fd);
-    return 1;
+    if (mfd >= 0)
+       close(mfd);
+    return ret;
 }
 
 /********************************************************************
@@ -1615,7 +1626,7 @@ int ppp_available(void)
     if (s < 0)
        return 0;
     
-    strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), "ppp0");
+    strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
     ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
 /*
  * If the device did not exist then attempt to create one by putting the
@@ -1624,7 +1635,7 @@ int ppp_available(void)
  */
     if (!ok) {
        if (ppp_registered()) {
-           strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), "ppp0");
+           strlcpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
            ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
        }
     }
@@ -1642,7 +1653,7 @@ int ppp_available(void)
          "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";
+         "ppp-2.3.7 distribution.\n";
 
 /*
  *  This is the PPP device. Validate the version of the driver at this
@@ -1727,10 +1738,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, sizeof(ut.ut_id), line + 3);
+       strlcpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
        
-    strlcpy(ut.ut_user, sizeof(ut.ut_user), name);
-    strlcpy(ut.ut_line, sizeof(ut.ut_line), line);
+    strlcpy(ut.ut_user, name, sizeof(ut.ut_user));
+    strlcpy(ut.ut_line, line, sizeof(ut.ut_line));
 
     time(&ut.ut_time);
 
@@ -1739,7 +1750,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, sizeof(ut.ut_host), host);
+       strlcpy (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)
@@ -1939,7 +1950,7 @@ int sifup (int u)
     struct ifreq ifr;
 
     memset (&ifr, '\0', sizeof (ifr));
-    strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
        if (! ok_error (errno))
            error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
@@ -1968,7 +1979,7 @@ int sifdown (int u)
     if_is_up = 0;
 
     memset (&ifr, '\0', sizeof (ifr));
-    strlcpy(ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+    strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
     if (ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
        if (! ok_error (errno))
            error("ioctl (SIOCGIFFLAGS): %m(%d)", errno);
@@ -2003,7 +2014,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); 
 
-    strlcpy (ifr.ifr_name, sizeof (ifr.ifr_name), ifname);
+    strlcpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
 /*
  *  Set our IP address
  */
@@ -2011,10 +2022,10 @@ int sifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr,
     if (ioctl(sock_fd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
        if (errno != EEXIST) {
            if (! ok_error (errno))
-               error("ioctl(SIOCAIFADDR): %m(%d)", errno);
+               error("ioctl(SIOCSIFADDR): %m(%d)", errno);
        }
         else {
-           warn("ioctl(SIOCAIFADDR): Address already exists");
+           warn("ioctl(SIOCSIFADDR): Address already exists");
        }
         return (0);
     }
@@ -2105,44 +2116,71 @@ int cifaddr (int unit, u_int32_t our_adr, u_int32_t his_adr)
     return 1;
 }
 
-/********************************************************************
- *
- * open_loopback - open the device we use for getting packets
- * in demand mode.  Under Linux, we use a pty master/slave pair.
+/*
+ * 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.
  */
 int
-open_ppp_loopback(void)
+get_pty(master_fdp, slave_fdp, slave_name, uid)
+    int *master_fdp;
+    int *slave_fdp;
+    char *slave_name;
+    int uid;
 {
-    int flags, i;
+    int i, mfd, sfd;
+    char pty_name[12];
     struct termios tios;
 
-    master_fd = -1;
+    sfd = -1;
     for (i = 0; i < 64; ++i) {
-       slprintf(loop_name, sizeof(loop_name), "/dev/pty%c%x",
+       slprintf(pty_name, sizeof(pty_name), "/dev/pty%c%x",
                 'p' + i / 16, i % 16);
-       master_fd = open(loop_name, O_RDWR | O_NOCTTY, 0);
-       if (master_fd >= 0)
-           break;
+       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);
+       }
     }
-    if (master_fd < 0)
-       fatal("No free pty for loopback");
-    SYSDEBUG(("using %s for loopback", loop_name));
-    loop_name[5] = 't';
-    slave_fd = open(loop_name, O_RDWR | O_NOCTTY, 0);
-    if (slave_fd < 0)
-       fatal("Couldn't open %s for loopback: %m", loop_name);
-
-    set_ppp_fd(slave_fd);
+    if (sfd < 0)
+       return 0;
 
-    if (tcgetattr(ppp_fd, &tios) == 0) {
+    strlcpy(slave_name, pty_name, 12);
+    *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;
        tios.c_iflag  = IGNPAR | CLOCAL;
        tios.c_oflag  = 0;
        tios.c_lflag  = 0;
-       if (tcsetattr(ppp_fd, TCSAFLUSH, &tios) < 0)
-           warn("couldn't set attributes on loopback: %m(%d)", errno);
-    }
+       if (tcsetattr(sfd, TCSAFLUSH, &tios) < 0)
+           warn("couldn't set attributes on pty: %m");
+    } else
+       warn("couldn't get attributes on pty: %m");
+
+    return 1;
+}
+
+/********************************************************************
+ *
+ * open_loopback - open the device we use for getting packets
+ * in demand mode.  Under Linux, we use a pty master/slave pair.
+ */
+int
+open_ppp_loopback(void)
+{
+    int flags;
+
+    if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
+       fatal("No free pty for loopback");
+    SYSDEBUG(("using %s for loopback", loop_name));
+
+    set_ppp_fd(slave_fd);
 
     flags = fcntl(master_fd, F_GETFL);
     if (flags == -1 ||
@@ -2240,7 +2278,7 @@ int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
     }
     else {
        memset (&ifr, '\0', sizeof (ifr));
-       strlcpy (ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
+       strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 
        memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
        sipx->sipx_family  = AF_IPX;
@@ -2255,10 +2293,10 @@ int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
            result = 0;
            if (errno != EEXIST) {
                if (! ok_error (errno))
-                   dbglog("ioctl(SIOCAIFADDR, CRTITF): %m (%d)", errno);
+                   dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (%d)", errno);
            }
            else {
-               warn("ioctl(SIOCAIFADDR, CRTITF): Address already exists");
+               warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists");
            }
        }
        close (skfd);
@@ -2291,7 +2329,7 @@ int cipxfaddr (int unit)
     }
     else {
        memset (&ifr, '\0', sizeof (ifr));
-       strlcpy (ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
+       strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 
        sipx->sipx_type    = IPX_FRAME_ETHERII;
        sipx->sipx_action  = IPX_DLTITF;
@@ -2301,7 +2339,7 @@ int cipxfaddr (int unit)
  */
        if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
            if (! ok_error (errno))
-               info("ioctl(SIOCAIFADDR, IPX_DLTITF): %m (%d)", errno);
+               info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (%d)", errno);
            result = 0;
        }
        close (skfd);
@@ -2365,7 +2403,7 @@ sys_check_options(void)
  */
     while (ipxcp_protent.enabled_flag) {
         if (path_to_procfs()) {
-           strlcat (route_buffer, sizeof(route_buffer), "/net/ipx_interface");
+           strlcat (route_buffer, "/net/ipx_interface", sizeof(route_buffer));
            if (lstat (route_buffer, &stat_buf) >= 0)
                break;
        }