add a few defs
[ppp.git] / pppd / sys-sunos4.c
index d2f83f7239d94081fea2a6502b6031f6837424a3..74c0217ef2908d7c5ae160164b53dc0a42fec180 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-sunos4.c,v 1.1 1995/10/27 03:54:02 paulus Exp $";
+static char rcsid[] = "$Id: sys-sunos4.c,v 1.8 1997/04/30 05:58:52 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -61,6 +61,13 @@ static char rcsid[] = "$Id: sys-sunos4.c,v 1.1 1995/10/27 03:54:02 paulus Exp $"
 
 #include "pppd.h"
 
+#if defined(sun) && defined(sparc)
+#include <alloca.h>
+#ifndef __GNUC__
+extern void *alloca();
+#endif
+#endif /*sparc*/
+
 static int     pppfd;
 static int     fdmuxid = -1;
 static int     iffd;
@@ -71,6 +78,8 @@ static struct termios inittermios;
 static struct winsize wsinfo;  /* Initial window size info */
 static pid_t   parent_pid;     /* PID of our parent */
 
+extern u_char  inpacket_buf[]; /* borrowed from main.c */
+
 static int     link_mtu, link_mru;
 
 #define NMODULES       32
@@ -78,6 +87,7 @@ static int    tty_nmodules;
 static char    tty_modules[NMODULES][FMNAMESZ+1];
 
 static int     if_is_up;       /* Interface has been marked up */
+static u_int32_t ifaddrs[2];   /* local and remote addresses */
 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 */
 
@@ -94,10 +104,7 @@ static int strioctl __P((int, int, void *, int, int));
 void
 sys_init()
 {
-    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
-    setlogmask(LOG_UPTO(LOG_INFO));
-    if (debug)
-       setlogmask(LOG_UPTO(LOG_DEBUG));
+    int x;
 
     /* Get an internet socket for doing socket ioctl's on. */
     if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
@@ -112,26 +119,99 @@ sys_init()
      * parent process.
      */
     parent_pid = getppid();
+
+    /*
+     * Open the ppp device.
+     */
+    pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
+    if (pppfd < 0) {
+       syslog(LOG_ERR, "Can't open /dev/ppp: %m");
+       die(1);
+    }
+    if (kdebugflag) {
+       x = PPPDBG_LOG + PPPDBG_DRIVER;
+       strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
+    }
+
+    /* Assign a new PPA and get its unit number. */
+    if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
+       syslog(LOG_ERR, "Can't create new PPP interface: %m");
+       die(1);
+    }
+
+    /*
+     * Open the ppp device again and push the if_ppp module on it.
+     */
+    iffd = open("/dev/ppp", O_RDWR, 0);
+    if (iffd < 0) {
+       syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
+       die(1);
+    }
+    if (kdebugflag) {
+       x = PPPDBG_LOG + PPPDBG_DRIVER;
+       strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
+    }
+    if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) {
+       syslog(LOG_ERR, "Couldn't attach ppp interface to device: %m");
+       die(1);
+    }
+    if (ioctl(iffd, I_PUSH, "if_ppp") < 0) {
+       syslog(LOG_ERR, "Can't push ppp interface module: %m");
+       die(1);
+    }
+    if (kdebugflag) {
+       x = PPPDBG_LOG + PPPDBG_IF;
+       strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
+    }
+    if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) {
+       syslog(LOG_ERR, "Couldn't create ppp interface unit: %m");
+       die(1);
+    }
+    x = PPP_IP;
+    if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) {
+       syslog(LOG_ERR, "Couldn't bind ppp interface to IP SAP: %m");
+       die(1);
+    }
 }
 
 /*
  * 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()
 {
-    struct ifreq ifr;
-
     if (if_is_up)
        sifdown(0);
+    if (ifaddrs[0])
+       cifaddr(0, ifaddrs[0], ifaddrs[1]);
     if (default_route_gateway)
-       cifdefaultroute(0, default_route_gateway);
+       cifdefaultroute(0, 0, default_route_gateway);
     if (proxy_arp_addr)
        cifproxyarp(0, proxy_arp_addr);
 }
 
+/*
+ * sys_close - Clean up in a child process before execing.
+ */
+void
+sys_close()
+{
+    close(iffd);
+    close(pppfd);
+    close(sockfd);
+}
+
+/*
+ * sys_check_options - check the options that the user specified
+ */
+void
+sys_check_options()
+{
+}
+
+
 /*
  * daemon - Detach us from controlling terminal session.
  */
@@ -156,20 +236,6 @@ daemon(nochdir, noclose)
     return 0;
 }
 
-/*
- * note_debug_level - note a change in the debug level.
- */
-void
-note_debug_level()
-{
-    if (debug) {
-       syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
-       setlogmask(LOG_UPTO(LOG_DEBUG));
-    } else {
-       setlogmask(LOG_UPTO(LOG_WARNING));
-    }
-}
-
 /*
  * ppp_available - check whether the system has any ppp interfaces
  */
@@ -185,60 +251,10 @@ ppp_available()
  * establish_ppp - Turn the serial port into a ppp interface.
  */
 void
-establish_ppp()
+establish_ppp(fd)
+    int fd;
 {
-    int i, x;
-    struct ifreq ifr;
-
-    pppfd = open("/dev/ppp", O_RDWR | O_NONBLOCK, 0);
-    if (pppfd < 0) {
-       syslog(LOG_ERR, "Can't open /dev/ppp: %m");
-       die(1);
-    }
-    if (kdebugflag) {
-       x = PPPDBG_LOG + PPPDBG_DRIVER;
-       strioctl(pppfd, PPPIO_DEBUG, &x, sizeof(int), 0);
-    }
-
-    /* Assign a new PPA and get its unit number. */
-    if (strioctl(pppfd, PPPIO_NEWPPA, &ifunit, 0, sizeof(int)) < 0) {
-       syslog(LOG_ERR, "Can't create new PPP interface: %m");
-       die(1);
-    }
-
-    /*
-     * Open the ppp device again and push the if_ppp module on it.
-     */
-    iffd = open("/dev/ppp", O_RDWR, 0);
-    if (iffd < 0) {
-       syslog(LOG_ERR, "Can't open /dev/ppp (2): %m");
-       die(1);
-    }
-    if (kdebugflag) {
-       x = PPPDBG_LOG + PPPDBG_DRIVER;
-       strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
-    }
-    if (strioctl(iffd, PPPIO_ATTACH, &ifunit, sizeof(int), 0) < 0) {
-       syslog(LOG_ERR, "Couldn't attach ppp interface to device: %m");
-       die(1);
-    }
-    if (ioctl(iffd, I_PUSH, "if_ppp") < 0) {
-       syslog(LOG_ERR, "Can't push ppp interface module: %m");
-       die(1);
-    }
-    if (kdebugflag) {
-       x = PPPDBG_LOG + PPPDBG_IF;
-       strioctl(iffd, PPPIO_DEBUG, &x, sizeof(int), 0);
-    }
-    if (strioctl(iffd, PPPIO_NEWPPA, &ifunit, sizeof(int), 0) < 0) {
-       syslog(LOG_ERR, "Couldn't create ppp interface unit: %m");
-       die(1);
-    }
-    x = PPP_IP;
-    if (strioctl(iffd, PPPIO_BIND, &x, sizeof(int), 0) < 0) {
-       syslog(LOG_ERR, "Couldn't bind ppp interface to IP SAP: %m");
-       die(1);
-    }
+    int i;
 
     /* Pop any existing modules off the tty stream. */
     for (i = 0;; ++i)
@@ -262,21 +278,25 @@ establish_ppp()
        syslog(LOG_ERR, "Can't link tty to PPP mux: %m");
        die(1);
     }
+}
 
-    do {
-       char buf[PPP_MRU];
-
-       i = read(fd, buf, PPP_MRU);
-       syslog(LOG_DEBUG, "read %d bytes from fd", i);
-    } while (i > 0);
+/*
+ * restore_loop - reattach the ppp unit to the loopback.
+ * This doesn't need to do anything because disestablish_ppp does it.
+ */
+void
+restore_loop()
+{
 }
 
 /*
  * disestablish_ppp - Restore the serial port to normal operation.
- * This shouldn't call die() because it's called from die().
+ * It attempts to reconstruct the stream with the previously popped
+ * modules.  This shouldn't call die() because it's called from die().
  */
 void
-disestablish_ppp()
+disestablish_ppp(fd)
+    int fd;
 {
     int i;
 
@@ -310,6 +330,38 @@ disestablish_ppp()
     }
 }
 
+/*
+ * Check whether the link seems not to be 8-bit clean.
+ */
+void
+clean_check()
+{
+    int x;
+    char *s;
+
+    if (strioctl(pppfd, PPPIO_GCLEAN, &x, 0, sizeof(x)) < 0)
+       return;
+    s = NULL;
+    switch (~x) {
+    case RCV_B7_0:
+       s = "bit 7 set to 1";
+       break;
+    case RCV_B7_1:
+       s = "bit 7 set to 0";
+       break;
+    case RCV_EVNP:
+       s = "odd parity";
+       break;
+    case RCV_ODDP:
+       s = "even parity";
+       break;
+    }
+    if (s != NULL) {
+       syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
+       syslog(LOG_WARNING, "All received characters had %s", s);
+    }
+}
+
 /*
  * List of valid speeds.
  */
@@ -493,7 +545,8 @@ set_up_tty(fd, local)
  * restore_tty - restore the terminal to the saved settings.
  */
 void
-restore_tty()
+restore_tty(fd)
+    int fd;
 {
     if (restore_term) {
        if (!default_device) {
@@ -526,6 +579,16 @@ int fd, on;
     ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
 }
 
+/*
+ * open_loopback - open the device we use for getting packets
+ * in demand mode.  Under Solaris 2, we use our existing fd
+ * to the ppp driver.
+ */
+void
+open_ppp_loopback()
+{
+}
+
 /*
  * output - Output PPP packet.
  */
@@ -540,22 +603,24 @@ output(unit, p, len)
     struct pollfd pfd;
 
     if (debug)
-       log_packet(p, len, "sent ");
+       log_packet(p, len, "sent ", LOG_DEBUG);
 
     data.len = len;
     data.buf = (caddr_t) p;
+    retries = 4;
     while (putmsg(pppfd, NULL, &data, 0) < 0) {
        if (--retries < 0 || (errno != EWOULDBLOCK && errno != EAGAIN)) {
            if (errno != ENXIO)
                syslog(LOG_ERR, "Couldn't send packet: %m");
            break;
        }
-       pfd.fd = fd;
+       pfd.fd = pppfd;
        pfd.events = POLLOUT;
        poll(&pfd, 1, 250);     /* wait for up to 0.25 seconds */
     }
 }
 
+
 /*
  * wait_input - wait until there is data available on fd,
  * for the length of time specified by *timo (indefinite
@@ -577,6 +642,36 @@ wait_input(timo)
     }
 }
 
+/*
+ * wait_loop_output - wait until there is data available on the
+ * loopback, for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+void
+wait_loop_output(timo)
+    struct timeval *timo;
+{
+    wait_input(timo);
+}
+
+/*
+ * wait_time - wait for a given length of time or until a
+ * signal is received.
+ */
+void
+wait_time(timo)
+    struct timeval *timo;
+{
+    int n;
+
+    n = select(0, NULL, NULL, NULL, timo);
+    if (n < 0 && errno != EINTR) {
+       syslog(LOG_ERR, "select: %m");
+       die(1);
+    }
+}
+
+
 /*
  * read_packet - get a PPP packet from the serial device.
  */
@@ -614,6 +709,24 @@ read_packet(buf)
     }
 }
 
+/*
+ * get_loop_output - get outgoing packets from the ppp device,
+ * and detect when we want to bring the real link up.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ */
+int
+get_loop_output()
+{
+    int len;
+    int rv = 0;
+
+    while ((len = read_packet(inpacket_buf)) > 0) {
+       if (loop_frame(inpacket_buf, len))
+           rv = 1;
+    }
+    return rv;
+}
+
 /*
  * ppp_send_config - configure the transmit characteristics of
  * the ppp interface.
@@ -625,6 +738,7 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
     int pcomp, accomp;
 {
     int cf[2];
+    struct ifreq ifr;
 
     link_mtu = mtu;
     if (strioctl(pppfd, PPPIO_MTU, &mtu, sizeof(mtu), 0) < 0) {
@@ -640,6 +754,14 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
     if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
        syslog(LOG_ERR, "Couldn't set prot/AC compression: %m");
     }
+
+    /* set mtu for ip as well */
+    memset(&ifr, 0, sizeof(ifr));
+    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    ifr.ifr_metric = link_mtu;
+    if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
+       syslog(LOG_ERR, "Couldn't set IP MTU: %m");
+    }
 }
 
 /*
@@ -716,6 +838,18 @@ ccp_flags_set(unit, isopen, isup)
     }
 }
 
+/*
+ * get_idle_time - return how long the link has been idle.
+ */
+int
+get_idle_time(u, ip)
+    int u;
+    struct ppp_idle *ip;
+{
+    return strioctl(pppfd, PPPIO_GIDLE, ip, 0, sizeof(struct ppp_idle)) >= 0;
+}
+
+
 /*
  * ccp_fatal_error - returns 1 if decompression was disabled as a
  * result of an error detected after decompression of a packet,
@@ -813,6 +947,26 @@ sifdown(u)
     return 1;
 }
 
+/*
+ * sifnpmode - Set the mode for handling packets for a given NP.
+ */
+int
+sifnpmode(u, proto, mode)
+    int u;
+    int proto;
+    enum NPmode mode;
+{
+    int npi[2];
+
+    npi[0] = proto;
+    npi[1] = (int) mode;
+    if (strioctl(pppfd, PPPIO_NPMODE, npi, 2 * sizeof(int), 0) < 0) {
+       syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
+       return 0;
+    }
+    return 1;
+}
+
 #define INET_ADDR(x)   (((struct sockaddr_in *) &(x))->sin_addr.s_addr)
 
 /*
@@ -828,6 +982,11 @@ sifaddr(u, o, h, m)
     memset(&ifr, 0, sizeof(ifr));
     strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
     ifr.ifr_addr.sa_family = AF_INET;
+    INET_ADDR(ifr.ifr_addr) = m;
+    if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
+       syslog(LOG_ERR, "Couldn't set IP netmask: %m");
+    }
+    ifr.ifr_addr.sa_family = AF_INET;
     INET_ADDR(ifr.ifr_addr) = o;
     if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) {
        syslog(LOG_ERR, "Couldn't set local IP address: %m");
@@ -837,15 +996,14 @@ sifaddr(u, o, h, m)
     if (ioctl(sockfd, SIOCSIFDSTADDR, &ifr) < 0) {
        syslog(LOG_ERR, "Couldn't set remote IP address: %m");
     }
-    ifr.ifr_addr.sa_family = AF_INET;
-    INET_ADDR(ifr.ifr_addr) = m;
-    if (ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) {
-       syslog(LOG_ERR, "Couldn't set IP netmask: %m");
-    }
+#if 0  /* now done in ppp_send_config */
     ifr.ifr_metric = link_mtu;
     if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
        syslog(LOG_ERR, "Couldn't set IP MTU: %m");
     }
+#endif
+    ifaddrs[0] = o;
+    ifaddrs[1] = h;
 
     return 1;
 }
@@ -861,12 +1019,15 @@ cifaddr(u, o, h)
 {
     struct rtentry rt;
 
+    bzero(&rt, sizeof(rt));
     rt.rt_dst.sa_family = AF_INET;
     INET_ADDR(rt.rt_dst) = h;
     rt.rt_gateway.sa_family = AF_INET;
     INET_ADDR(rt.rt_gateway) = o;
     rt.rt_flags = RTF_HOST;
-    ioctl(sockfd, SIOCDELRT, &rt);
+    if (ioctl(sockfd, SIOCDELRT, &rt) < 0)
+       syslog(LOG_ERR, "Couldn't delete route through interface: %m");
+    ifaddrs[0] = 0;
     return 1;
 }
 
@@ -874,12 +1035,13 @@ cifaddr(u, o, h)
  * sifdefaultroute - assign a default route through the address given.
  */
 int
-sifdefaultroute(u, g)
+sifdefaultroute(u, l, g)
     int u;
-    u_int32_t g;
+    u_int32_t l, g;
 {
     struct rtentry rt;
 
+    bzero(&rt, sizeof(rt));
     rt.rt_dst.sa_family = AF_INET;
     INET_ADDR(rt.rt_dst) = 0;
     rt.rt_gateway.sa_family = AF_INET;
@@ -899,12 +1061,13 @@ sifdefaultroute(u, g)
  * cifdefaultroute - delete a default route through the address given.
  */
 int
-cifdefaultroute(u, g)
+cifdefaultroute(u, l, g)
     int u;
-    u_int32_t g;
+    u_int32_t l, g;
 {
     struct rtentry rt;
 
+    bzero(&rt, sizeof(rt));
     rt.rt_dst.sa_family = AF_INET;
     INET_ADDR(rt.rt_dst) = 0;
     rt.rt_gateway.sa_family = AF_INET;
@@ -1056,9 +1219,9 @@ get_ether_addr(ipaddr, hwaddr)
 
 #define        WTMPFILE        "/usr/adm/wtmp"
 
-int
+void
 logwtmp(line, name, host)
-    char *line, *name, *host;
+    const char *line, *name, *host;
 {
     int fd;
     struct stat buf;
@@ -1275,3 +1438,21 @@ strtoul(str, ptr, base)
 {
     return (unsigned long) strtol(str, ptr, base);
 }
+
+/*
+ * Or strerror :-(
+ */
+extern char *sys_errlist[];
+extern int sys_nerr;
+
+char *
+strerror(n)
+    int n;
+{
+    static char unknown[32];
+
+    if (n > 0 && n < sys_nerr)
+       return sys_errlist[n];
+    sprintf(unknown, "Error %d", n);
+    return unknown;
+}