]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-svr4.c
clock32_t is clock_t (long)
[ppp.git] / pppd / sys-svr4.c
index 5357aebfeb91bcb45aac7f6c7abc069068534cb9..0743da189060271b1194ff54726f242d9dc3e1b9 100644 (file)
@@ -25,7 +25,7 @@
  * OR MODIFICATIONS.
  */
 
-#define RCSID  "$Id: sys-svr4.c,v 1.35 1999/09/30 19:59:06 masputra Exp $"
+#define RCSID  "$Id: sys-svr4.c,v 1.41 2000/02/11 03:09:19 masputra Exp $"
 
 #include <limits.h>
 #include <stdio.h>
 #endif
 
 #include "pppd.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+#include "ccp.h"
+
+#if !defined(PPP_DEV_NAME)
+#define PPP_DEV_NAME   "/dev/ppp"
+#endif /* !defined(PPP_DEV_NAME) */
+
+#if !defined(AHDLC_MOD_NAME)
+#define AHDLC_MOD_NAME "ppp_ahdl"
+#endif /* !defined(AHDLC_MOD_NAME) */
+
+#if !defined(COMP_MOD_NAME)
+#define COMP_MOD_NAME  "ppp_comp"
+#endif /* !defined(COMP_MOD_NAME) */
+
+#if !defined(IP_DEV_NAME)
+#define        IP_DEV_NAME     "/dev/ip"
+#endif /* !defined(IP_DEV_NAME) */
+
+#if !defined(IP_MOD_NAME)
+#define        IP_MOD_NAME     "ip"
+#endif /* !defined(IP_MOD_NAME) */
+
+#if !defined(UDP_DEV_NAME) && defined(SOL2)
+#define        UDP_DEV_NAME    "/dev/udp"
+#endif /* !defined(UDP_DEV_NAME) && defined(SOL2) */
+
+#if !defined(UDP6_DEV_NAME) && defined(SOL2)
+#define        UDP6_DEV_NAME   "/dev/udp6"
+#endif /* !defined(UDP6_DEV_NAME) && defined(SOL2) */
 
 static const char rcsid[] = RCSID;
 
+#if defined(SOL2)
+/*
+ * "/dev/udp" is used as a multiplexor to PLINK the interface stream
+ * under. It is used in place of "/dev/ip" since STREAMS will not let
+ * a driver be PLINK'ed under itself, and "/dev/ip" is typically the
+ * driver at the bottom of the tunneling interfaces stream.
+ */
+static char *mux_dev_name = UDP_DEV_NAME;
+#else
+static char *mux_dev_name = IP_DEV_NAME;
+#endif
 static int     pppfd;
 static int     fdmuxid = -1;
 static int     ipfd;
@@ -156,8 +199,8 @@ static int strioctl __P((int, int, void *, int, int));
  */
 static int
 sifppa(fd, ppa)
-        int fd;
-        int ppa;
+    int fd;
+    int ppa;
 {
     return (int)ioctl(fd, IF_UNITSEL, (char *)&ppa);
 }
@@ -172,8 +215,8 @@ sifppa(fd, ppa)
  */
 static int
 slifname(fd, ppa)
-       int fd;
-       int ppa;
+    int fd;
+    int ppa;
 {
     struct  lifreq lifr;
     int            ret;
@@ -323,23 +366,24 @@ void
 sys_init()
 {
     int ifd, x;
+    struct ifreq ifr;
 #if defined(INET6) && defined(SOL2)
     int i6fd;
+    struct lifreq lifr;
 #endif /* defined(INET6) && defined(SOL2) */
 #if !defined(SOL2)
-    struct ifreq ifr;
     struct {
        union DL_primitives prim;
        char space[64];
     } reply;
 #endif /* !defined(SOL2) */
 
-    ipfd = open("/dev/ip", O_RDWR, 0);
+    ipfd = open(mux_dev_name, O_RDWR, 0);
     if (ipfd < 0)
        fatal("Couldn't open IP device: %m");
 
 #if defined(INET6) && defined(SOL2)
-    ip6fd = open("/dev/ip", O_RDWR, 0);
+    ip6fd = open(UDP6_DEV_NAME, O_RDWR, 0);
     if (ip6fd < 0)
        fatal("Couldn't open IP device (2): %m");
 #endif /* defined(INET6) && defined(SOL2) */
@@ -347,9 +391,9 @@ sys_init()
     if (default_device && !notty)
        tty_sid = getsid((pid_t)0);
 
-    pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
+    pppfd = open(PPP_DEV_NAME, O_RDWR | O_NONBLOCK, 0);
     if (pppfd < 0)
-       fatal("Can't open /dev/ppp: %m");
+       fatal("Can't open %s: %m", PPP_DEV_NAME);
     if (kdebugflag & 1) {
        x = PPPDBG_LOG + PPPDBG_DRIVER;
        strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
@@ -359,31 +403,33 @@ sys_init()
     if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0)
        fatal("Can't create new PPP interface: %m");
 
+#if defined(SOL2)
+    /*
+     * Since sys_init() is called prior to ifname being set in main(),
+     * we need to get the ifname now, otherwise slifname(), and others,
+     * will fail, or maybe, I should move them to a later point ?
+     * <adi.masputra@sun.com>
+     */
+    sprintf(ifname, "ppp%d", ifunit);
+#endif /* defined(SOL2) */
     /*
      * Open the ppp device again and link it under the ip multiplexor.
      * IP will assign a unit number which hopefully is the same as ifunit.
      * I don't know any way to be certain they will be the same. :-(
      */
-    ifd = open("/dev/ppp", O_RDWR, 0);
+    ifd = open(PPP_DEV_NAME, O_RDWR, 0);
     if (ifd < 0)
-       fatal("Can't open /dev/ppp (2): %m");
+       fatal("Can't open %s (2): %m", PPP_DEV_NAME);
     if (kdebugflag & 1) {
        x = PPPDBG_LOG + PPPDBG_DRIVER;
        strioctl(ifd, PPPIO_DEBUG, &x, sizeof(int), 0);
     }
 
 #if defined(INET6) && defined(SOL2)
-    /*
-     * Since sys_init() is called prior to ifname being set in main(),
-     * we need to get the ifname now, otherwise slifname() will fail,
-     * or maybe, I should move slifname() to a later point ?
-     */
-    sprintf(ifname, "ppp%d", ifunit);
-
-    i6fd = open("/dev/ppp", O_RDWR, 0);
+    i6fd = open(PPP_DEV_NAME, O_RDWR, 0);
     if (i6fd < 0) {
        close(ifd);
-       fatal("Can't open /dev/ppp (3): %m");
+       fatal("Can't open %s (3): %m", PPP_DEV_NAME);
     }
     if (kdebugflag & 1) {
        x = PPPDBG_LOG + PPPDBG_DRIVER;
@@ -392,7 +438,7 @@ sys_init()
 #endif /* defined(INET6) && defined(SOL2) */
 
 #if defined(SOL2)
-    if (ioctl(ifd, I_PUSH, "ip") < 0) {
+    if (ioctl(ifd, I_PUSH, IP_MOD_NAME) < 0) {
        close(ifd);
 #if defined(INET6)
        close(i6fd);
@@ -418,7 +464,7 @@ sys_init()
      * explicitly enable it. Note that the interface will be marked
      * IPv6 during slifname().
      */
-    if (ioctl(i6fd, I_PUSH, "ip") < 0) {
+    if (ioctl(i6fd, I_PUSH, IP_MOD_NAME) < 0) {
        close(ifd);
        close(i6fd);
        fatal("Can't push IP module (2): %m");
@@ -436,6 +482,34 @@ sys_init()
     }
 #endif /* defined(INET6) */
 
+    ipmuxid = ioctl(ipfd, I_PLINK, ifd);
+    close(ifd);
+    if (ipmuxid < 0) {
+#if defined(INET6)
+       close(i6fd);
+#endif /* defined(INET6) */
+       fatal("Can't I_PLINK PPP device to IP: %m");
+    }
+
+    memset(&ifr, 0, sizeof(ifr));
+    sprintf(ifr.ifr_name, "%s", ifname);
+    ifr.ifr_ip_muxid = ipmuxid;
+
+    /*
+     * In Sol 8 and later, STREAMS dynamic module plumbing feature exists.
+     * This is so that an arbitrary module can be inserted, or deleted, 
+     * between ip module and the device driver without tearing down the 
+     * existing stream. Such feature requires the mux ids, which is set 
+     * by SIOCSIFMUXID (or SIOCLSIFMUXID).
+     */
+    if (ioctl(ipfd, SIOCSIFMUXID, &ifr) < 0) {
+       ioctl(ipfd, I_PUNLINK, ipmuxid);
+#if defined(INET6)
+       close(i6fd);
+#endif /* defined(INET6) */
+       fatal("SIOCSIFMUXID: %m");
+    }
+
 #else /* else if !defined(SOL2) */
 
     if (dlpi_attach(ifd, ifunit) < 0 ||
@@ -443,18 +517,33 @@ sys_init()
        close(ifd);
        fatal("Can't attach to ppp%d: %m", ifunit);
     }
-#endif /* defined(SOL2) */
 
     ipmuxid = ioctl(ipfd, I_LINK, ifd);
     close(ifd);
     if (ipmuxid < 0)
        fatal("Can't link PPP device to IP: %m");
+#endif /* defined(SOL2) */
 
 #if defined(INET6) && defined(SOL2)
-    ip6muxid = ioctl(ip6fd, I_LINK, i6fd);
+    ip6muxid = ioctl(ip6fd, I_PLINK, i6fd);
     close(i6fd);
-    if (ip6muxid < 0) 
+    if (ip6muxid < 0) {
+       ioctl(ipfd, I_PUNLINK, ipmuxid);
+       fatal("Can't I_PLINK PPP device to IP (2): %m");
+    }
+
+    memset(&lifr, 0, sizeof(lifr));
+    sprintf(lifr.lifr_name, "%s", ifname);
+    lifr.lifr_ip_muxid = ip6muxid;
+
+    /*
+     * Let IP know of the mux id [see comment for SIOCSIFMUXID above]
+     */
+    if (ioctl(ip6fd, SIOCSLIFMUXID, &lifr) < 0) {
+       ioctl(ipfd, I_PUNLINK, ipmuxid);
+       ioctl(ip6fd, I_PUNLINK, ip6muxid);
        fatal("Can't link PPP device to IP (2): %m");
+    }
 #endif /* defined(INET6) && defined(SOL2) */
 
 #if !defined(SOL2)
@@ -476,7 +565,12 @@ sys_init()
 void
 sys_cleanup()
 {
+#if defined(SOL2)
     struct ifreq ifr;
+#if defined(INET6)
+    struct lifreq lifr;
+#endif /* defined(INET6) */
+#endif /* defined(SOL2) */
 
 #if defined(SOL2) && defined(INET6)
     if (if6_is_up)
@@ -488,6 +582,53 @@ sys_cleanup()
        cifdefaultroute(0, default_route_gateway, default_route_gateway);
     if (proxy_arp_addr)
        cifproxyarp(0, proxy_arp_addr);
+#if defined(SOL2)
+    /*
+     * Make sure we ask ip what the muxid, because 'ifconfig modlist' will
+     * unlink and re-link the modules, causing the muxid to change.
+     */
+    memset(&ifr, 0, sizeof(ifr));
+    sprintf(ifr.ifr_name, "%s", ifname);
+    if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
+       error("SIOCGIFFLAGS: %m");
+       return;
+    }
+
+    if (ioctl(ipfd, SIOCGIFMUXID, &ifr) < 0) {
+       error("SIOCGIFMUXID: %m");
+       return;
+    }
+
+    ipmuxid = ifr.ifr_ip_muxid;
+     
+    if (ioctl(ipfd, I_PUNLINK, ipmuxid) < 0) {
+       error("Can't I_PUNLINK PPP from IP: %m");
+       return;
+    }
+#if defined(INET6)
+    /*
+     * Make sure we ask ip what the muxid, because 'ifconfig modlist' will
+     * unlink and re-link the modules, causing the muxid to change.
+     */
+    memset(&lifr, 0, sizeof(lifr));
+    sprintf(lifr.lifr_name, "%s", ifname);
+    if (ioctl(ip6fd, SIOCGLIFFLAGS, &lifr) < 0) {
+       error("SIOCGLIFFLAGS: %m");
+       return;
+    }
+
+    if (ioctl(ip6fd, SIOCGLIFMUXID, &lifr) < 0) {
+       error("SIOCGLIFMUXID: %m");
+       return;
+    }
+
+    ip6muxid = lifr.lifr_ip_muxid;
+
+    if (ioctl(ip6fd, I_PUNLINK, ip6muxid) < 0) {
+       error("Can't I_PUNLINK PPP from IP (2): %m");
+    }
+#endif /* defined(INET6) */
+#endif /* defined(SOL2) */
 }
 
 /*
@@ -547,7 +688,28 @@ ppp_available()
 {
     struct stat buf;
 
-    return stat("/dev/ppp", &buf) >= 0;
+    return stat(PPP_DEV_NAME, &buf) >= 0;
+}
+
+/*
+ * any_compressions - see if compression is enabled or not
+ *
+ * In the STREAMS implementation of kernel-portion pppd,
+ * the comp STREAMS module performs the ACFC, PFC, as well
+ * CCP and VJ compressions. However, if the user has explicitly
+ * declare to not enable them from the command line, there is
+ * no point of having the comp module be pushed on the stream.
+ */
+static int
+any_compressions()
+{
+    if ((!lcp_wantoptions[0].neg_accompression) &&
+       (!lcp_wantoptions[0].neg_pcompression) &&
+       (!ccp_protent.enabled_flag) &&
+       (!ipcp_wantoptions[0].neg_vj)) {
+           return 0;
+    }
+    return 1;
 }
 
 /*
@@ -571,7 +733,7 @@ establish_ppp(fd)
     tty_npushed = 0;
 
     if(!sync_serial) {
-        if (ioctl(fd, I_PUSH, "ppp_ahdl") < 0) {
+        if (ioctl(fd, I_PUSH, AHDLC_MOD_NAME) < 0) {
             error("Couldn't push PPP Async HDLC module: %m");
            return -1;
         }
@@ -581,12 +743,21 @@ establish_ppp(fd)
        i = PPPDBG_LOG + PPPDBG_AHDLC;
        strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
     }
-    if (ioctl(fd, I_PUSH, "ppp_comp") < 0)
-       error("Couldn't push PPP compression module: %m");
-    else
-       ++tty_npushed;
+    /*
+     * There's no need to push comp module if we don't intend
+     * to compress anything
+     */
+    if (any_compressions()) { 
+        if (ioctl(fd, I_PUSH, COMP_MOD_NAME) < 0)
+           error("Couldn't push PPP compression module: %m");
+       else
+           ++tty_npushed;
+    }
+
     if (kdebugflag & 2) {
-       i = PPPDBG_LOG + PPPDBG_COMP;
+       i = PPPDBG_LOG; 
+       if (any_compressions())
+           i += PPPDBG_COMP;
        strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
     }
 
@@ -753,6 +924,18 @@ struct speed {
 #endif
 #ifdef B115200
     { 115200, B115200 },
+#endif
+#ifdef B153600
+    { 153600, B153600 },
+#endif
+#ifdef B230400
+    { 230400, B230400 },
+#endif
+#ifdef B307200
+    { 307200, B307200 },
+#endif
+#ifdef B460800
+    { 460800, B460800 },
 #endif
     { 0, 0 }
 };
@@ -812,7 +995,7 @@ set_up_tty(fd, local)
 
 #ifndef CRTSCTS
     termiox_ok = 1;
-    if (ioctl (fd, TCGETX, &tiox) < 0) {
+    if (!sync_serial && ioctl (fd, TCGETX, &tiox) < 0) {
        termiox_ok = 0;
        if (errno != ENOTTY)
            error("TCGETX: %m");
@@ -824,7 +1007,8 @@ set_up_tty(fd, local)
 #ifndef CRTSCTS
        inittermiox = tiox;
 #endif
-       ioctl(fd, TIOCGWINSZ, &wsinfo);
+       if (!sync_serial)
+           ioctl(fd, TIOCGWINSZ, &wsinfo);
     }
 
     tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
@@ -868,7 +1052,7 @@ set_up_tty(fd, local)
         * We can't proceed if the serial port speed is 0,
         * since that implies that the serial port is disabled.
         */
-       if (speed == B0)
+       if ((speed == B0) && !sync_serial)
            fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
     }
 
@@ -876,13 +1060,14 @@ set_up_tty(fd, local)
        fatal("tcsetattr: %m");
 
 #ifndef CRTSCTS
-    if (termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){
+    if (!sync_serial && termiox_ok && ioctl (fd, TCSETXF, &tiox) < 0){
        error("TCSETXF: %m");
     }
 #endif
 
     baud_rate = inspeed = baud_rate_of(speed);
-    restore_term = 1;
+    if (!sync_serial)
+       restore_term = 1;
 }
 
 /*
@@ -902,16 +1087,17 @@ restore_tty(fd)
             */
            inittermios.c_lflag &= ~(ECHO | ECHONL);
        }
-       if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
+       if (!sync_serial && tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
            if (!hungup && errno != ENXIO)
                warn("tcsetattr: %m");
 #ifndef CRTSCTS
-       if (ioctl (fd, TCSETXF, &inittermiox) < 0){
+       if (!sync_serial && ioctl (fd, TCSETXF, &inittermiox) < 0){
            if (!hungup && errno != ENXIO)
                error("TCSETXF: %m");
        }
 #endif
-       ioctl(fd, TIOCSWINSZ, &wsinfo);
+       if (!sync_serial)
+           ioctl(fd, TIOCSWINSZ, &wsinfo);
        restore_term = 0;
     }
 }
@@ -1135,13 +1321,15 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
        error("Couldn't set MTU: %m");
     }
     if (fdmuxid >= 0) {
-       /* can't set these if we don't have a stream attached below /dev/ppp */
-       if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
-           error("Couldn't set transmit ACCM: %m");
+       if (!sync_serial) {
+           if (strioctl(pppfd, PPPIO_XACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
+               error("Couldn't set transmit ACCM: %m");
+           }
        }
        cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
        cf[1] = COMP_PROT | COMP_AC;
-       if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
+       if (any_compressions() &&
+           strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
            error("Couldn't set prot/AC compression: %m");
        }
     }
@@ -1178,6 +1366,9 @@ ppp_set_xaccm(unit, accm)
     int unit;
     ext_accm accm;
 {
+    if (sync_serial)
+       return;
+
     if (fdmuxid >= 0
        && strioctl(pppfd, PPPIO_XACCM, accm, sizeof(ext_accm), 0) < 0) {
        if (!hungup || errno != ENXIO)
@@ -1204,13 +1395,15 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
        error("Couldn't set MRU: %m");
     }
     if (fdmuxid >= 0) {
-       /* can't set these if we don't have a stream attached below /dev/ppp */
-       if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
-           error("Couldn't set receive ACCM: %m");
+       if (!sync_serial) {
+           if (strioctl(pppfd, PPPIO_RACCM, &asyncmap, sizeof(asyncmap), 0) < 0) {
+               error("Couldn't set receive ACCM: %m");
+           }
        }
        cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
        cf[1] = DECOMP_PROT | DECOMP_AC;
-       if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
+       if (any_compressions() &&
+           strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
            error("Couldn't set prot/AC decompression: %m");
        }
     }
@@ -1269,7 +1462,8 @@ get_ppp_stats(u, stats)
 {
     struct ppp_stats s;
 
-    if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
+    if (!sync_serial && 
+       strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
        error("Couldn't get link statistics: %m");
        return 0;
     }
@@ -2251,9 +2445,9 @@ have_route_to(addr)
     mib2_ipRouteEntry_t routes[8];
     mib2_ipRouteEntry_t *rp;
 
-    fd = open("/dev/ip", O_RDWR);
+    fd = open(mux_dev_name, O_RDWR);
     if (fd < 0) {
-       warn("have_route_to: couldn't open /dev/ip: %m");
+       warn("have_route_to: couldn't open %s: %m", mux_dev_name);
        return -1;
     }