Added -vjccid and vj-max-slots options, and reorganized in
[ppp.git] / pppd / sys-aix4.c
index 29e2dd3c04f8360c8ddfa1022ed92349dac2694c..ca9cebc94c446fcfd353ae91f0759d6456a550b1 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * sys-str.c - System-dependent procedures for setting up
- * PPP interfaces on systems which use the STREAMS ppp interface.
+ * sys-aix4.c - System-dependent procedures for setting up
+ * PPP interfaces on AIX systems which use the STREAMS ppp interface.
  *
  * Copyright (c) 1989 Carnegie Mellon University.
  * All rights reserved.
@@ -19,7 +19,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-aix4.c,v 1.1 1994/11/29 02:36:45 paulus Exp $";
+static char rcsid[] = "$Id: sys-aix4.c,v 1.6 1995/05/01 00:26:11 paulus Exp $";
 #endif
 
 /*
@@ -27,6 +27,9 @@ static char rcsid[] = "$Id: sys-aix4.c,v 1.1 1994/11/29 02:36:45 paulus Exp $";
  */
 
 #include <stdio.h>
+/*
+#include <stdlib.h>
+*/
 #include <errno.h>
 #include <syslog.h>
 #include <termios.h>
@@ -66,6 +69,8 @@ static int    closed_stdio;
 static int     restore_term;   /* 1 => we've munged the terminal */
 static struct termios inittermios; /* Initial TTY termios */
 
+int sockfd;                    /* socket for doing interface ioctls */
+
 /*
  * sys_init - System-dependent initialization.
  */
@@ -76,6 +81,12 @@ sys_init()
     setlogmask(LOG_UPTO(LOG_INFO));
     if (debug)
        setlogmask(LOG_UPTO(LOG_DEBUG));
+
+    /* Get an internet socket for doing socket ioctl's on. */
+    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+       syslog(LOG_ERR, "Couldn't create IP socket: %m");
+       die(1);
+    }
 }
 
 /*
@@ -191,7 +202,7 @@ establish_ppp()
        int i;
 
        for (i = 0; i <= 2; ++i)
-           if (i != fd && i != s)
+           if (i != fd && i != sockfd)
                close(i);
        closed_stdio = 1;
     }
@@ -452,6 +463,15 @@ void
 restore_tty()
 {
     if (restore_term) {
+       if (!default_device) {
+           /*
+            * Turn off echoing, because otherwise we can get into
+            * a loop with the tty and the modem echoing to each other.
+            * We presume we are the sole user of this tty device, so
+            * when we close it, it will revert to its defaults anyway.
+            */
+           inittermios.c_lflag &= ~(ECHO | ECHONL);
+       }
        if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
            if (errno != ENXIO)
                syslog(LOG_WARNING, "tcsetattr: %m");
@@ -570,7 +590,7 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
 
     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
     ifr.ifr_mtu = mtu;
-    if (ioctl(s, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
+    if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
        syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
        quit();
     }
@@ -716,12 +736,12 @@ sifup(u)
     struct npioctl npi;
 
     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
-    if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
        syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
        return 0;
     }
     ifr.ifr_flags |= IFF_UP;
-    if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+    if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
        syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
        return 0;
     }
@@ -759,12 +779,12 @@ sifdown(u)
     }
 
     strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
-    if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+    if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
         syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
         rv = 0;
     } else {
         ifr.ifr_flags &= ~IFF_UP;
-        if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+        if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
             syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
             rv = 0;
         }
@@ -796,26 +816,26 @@ sifaddr(u, o, h, m)
     if (m != 0) {
         syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
         ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
-        if (ioctl(s, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
+        if (ioctl(sockfd, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
             syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
             ret = 0;
         }
     }
 
     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
-    if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
+    if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
         ret = 0;
     }
 
     SET_SA_FAMILY(ifr.ifr_dstaddr, AF_INET);
     ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
-    if (ioctl(s, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
+    if (ioctl(sockfd, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
         syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
         ret = 0;
     }
     ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
-    if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
+    if (ioctl(sockfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
         syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
         ret = 0;
     }
@@ -838,7 +858,7 @@ cifaddr(u, o, h)
     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
     rt.rt_flags = RTF_HOST;
-    if (ioctl(s, SIOCDELRT, (caddr_t) &rt) < 0) {
+    if (ioctl(sockfd, SIOCDELRT, (caddr_t) &rt) < 0) {
        syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
        return 0;
     }
@@ -859,7 +879,7 @@ sifdefaultroute(u, g)
     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
     rt.rt_flags = RTF_GATEWAY;
-    if (ioctl(s, SIOCADDRT, &rt) < 0) {
+    if (ioctl(sockfd, SIOCADDRT, &rt) < 0) {
        syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
        return 0;
     }
@@ -880,7 +900,7 @@ cifdefaultroute(u, g)
     SET_SA_FAMILY(rt.rt_gateway, AF_INET);
     ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
     rt.rt_flags = RTF_GATEWAY;
-    if (ioctl(s, SIOCDELRT, &rt) < 0) {
+    if (ioctl(sockfd, SIOCDELRT, &rt) < 0) {
        syslog(LOG_ERR, "default route ioctl(SIOCDELRT): %m");
        return 0;
     }
@@ -911,7 +931,7 @@ sifproxyarp(unit, hisaddr)
     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
     arpreq.arp_flags = ATF_PERM | ATF_PUBL;
-    if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) {
+    if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
        syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
        return 0;
     }
@@ -932,7 +952,7 @@ cifproxyarp(unit, hisaddr)
     BZERO(&arpreq, sizeof(arpreq));
     SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
     ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
-    if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) < 0) {
+    if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
        syslog(LOG_ERR, "ioctl(SIOCDARP): %m");
        return 0;
     }
@@ -1095,6 +1115,74 @@ get_ether_addr(ipaddr, hwaddr)
     return(found);
 }
 
+/*
+ * Return user specified netmask, modified by any mask we might determine
+ * for address `addr' (in network byte order).
+ * Here we scan through the system's list of interfaces, looking for
+ * any non-point-to-point interfaces which might appear to be on the same
+ * network as `addr'.  If we find any, we OR in their netmask to the
+ * user-specified netmask.
+ */
+#define MAX_IFS                32
+
+u_int32_t
+GetMask(addr)
+    u_int32_t addr;
+{
+    u_int32_t mask, nmask, ina;
+    struct ifreq *ifr, *ifend, ifreq;
+    struct ifconf ifc;
+    struct ifreq ifs[MAX_IFS];
+
+    addr = ntohl(addr);
+    if (IN_CLASSA(addr))       /* determine network mask for address class */
+       nmask = IN_CLASSA_NET;
+    else if (IN_CLASSB(addr))
+       nmask = IN_CLASSB_NET;
+    else
+       nmask = IN_CLASSC_NET;
+    /* class D nets are disallowed by bad_ip_adrs */
+    mask = netmask | htonl(nmask);
+
+    /*
+     * Scan through the system's network interfaces.
+     */
+    ifc.ifc_len = sizeof(ifs);
+    ifc.ifc_req = ifs;
+    if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
+       syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
+       return mask;
+    }
+    ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+    for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) {
+       /*
+        * Check the interface's internet address.
+        */
+       if (ifr->ifr_addr.sa_family != AF_INET)
+           continue;
+       ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+       if ((ntohl(ina) & nmask) != (addr & nmask))
+           continue;
+       /*
+        * Check that the interface is up, and not point-to-point or loopback.
+        */
+       strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+       if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
+           continue;
+       if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
+           != IFF_UP)
+           continue;
+       /*
+        * Get its netmask and OR it into our mask.
+        */
+       if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
+           continue;
+       mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
+    }
+
+    return mask;
+}
+
 #define        WTMPFILE        "/var/adm/wtmp"
 
 int
@@ -1117,3 +1205,41 @@ logwtmp(line, name, host)
     }
     close(fd);
 }
+
+/*
+ * Code for locking/unlocking the serial device.
+ */
+
+static char *devlocked = (char *) 0;
+
+int lock(char *device)
+{
+    char       *devname;
+    int                rc;
+
+    if (devname = strrchr(device,'/'))
+       ++devname;
+    else
+       devname = device;
+
+    if ((rc = ttylock(devname)) == 0) {
+       devlocked = (char *) malloc(strlen(devname) + 1);
+       sprintf(devlocked,"%s",devname);
+    } else
+       devlocked = (char *) 0;
+
+    return(rc);
+}
+
+int unlock()
+{
+    int rc = 0;
+
+    if (devlocked) {
+       rc = ttyunlock(devlocked);
+       free(devlocked);
+       devlocked = (char *) 0;
+    }
+    return(rc);
+}
+