]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-svr4.c
use strlcpy, strlcat, slprintf everywhere
[ppp.git] / pppd / sys-svr4.c
index 01a377723cbc69d752681f8ff5b5815b3ffc065f..4173e4d2f4c246e81431403960c3929ad0689d80 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-svr4.c,v 1.17 1998/03/25 02:19:31 paulus Exp $";
+static char rcsid[] = "$Id: sys-svr4.c,v 1.24 1999/03/12 06:07:23 paulus Exp $";
 #endif
 
 #include <limits.h>
@@ -61,6 +61,10 @@ static char rcsid[] = "$Id: sys-svr4.c,v 1.17 1998/03/25 02:19:31 paulus Exp $";
 #include <net/ppp_defs.h>
 #include <net/pppio.h>
 #include <netinet/in.h>
+#include <sys/tihdr.h>
+#include <sys/tiuser.h>
+#include <inet/common.h>
+#include <inet/mib2.h>
 
 #include "pppd.h"
 
@@ -87,6 +91,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 remote_addr;          /* IP address of peer */
 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,7 +99,7 @@ static u_int32_t proxy_arp_addr;      /* Addr for proxy arp entry added */
 static int translate_speed __P((int));
 static int baud_rate_of __P((int));
 static int get_ether_addr __P((u_int32_t, struct sockaddr *));
-static int get_hw_addr __P((char *, struct sockaddr *));
+static int get_hw_addr __P((char *, u_int32_t, struct sockaddr *));
 static int dlpi_attach __P((int, int));
 static int dlpi_info_req __P((int));
 static int dlpi_get_reply __P((int, union DL_primitives *, int, int));
@@ -219,9 +224,10 @@ sys_close()
 /*
  * sys_check_options - check the options that the user specified
  */
-void
+int
 sys_check_options()
 {
+    return 1;
 }
 
 
@@ -747,7 +753,7 @@ read_packet(buf)
        flags = 0;
        len = getmsg(pppfd, &ctrl, &data, &flags);
        if (len < 0) {
-           if (errno = EAGAIN || errno == EINTR)
+           if (errno == EAGAIN || errno == EINTR)
                return -1;
            syslog(LOG_ERR, "Error reading packet: %m");
            die(1);
@@ -818,7 +824,7 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
 
     /* set the MTU for IP as well */
     memset(&ifr, 0, sizeof(ifr));
-    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    strlcpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
     ifr.ifr_metric = link_mtu;
     if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
        syslog(LOG_ERR, "Couldn't set IP MTU: %m");
@@ -1000,7 +1006,7 @@ sifup(u)
 {
     struct ifreq ifr;
 
-    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    strlcpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
        syslog(LOG_ERR, "Couldn't mark interface up (get): %m");
        return 0;
@@ -1025,7 +1031,7 @@ sifdown(u)
 
     if (ipmuxid < 0)
        return 1;
-    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    strlcpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
     if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
        syslog(LOG_ERR, "Couldn't mark interface down (get): %m");
        return 0;
@@ -1073,7 +1079,7 @@ sifaddr(u, o, h, m)
     int ret = 1;
 
     memset(&ifr, 0, sizeof(ifr));
-    strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+    strlcpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);
     ifr.ifr_addr.sa_family = AF_INET;
     INET_ADDR(ifr.ifr_addr) = m;
     if (ioctl(ipfd, SIOCSIFNETMASK, &ifr) < 0) {
@@ -1112,6 +1118,7 @@ sifaddr(u, o, h, m)
     }
 #endif
 
+    remote_addr = h;
     return ret;
 }
 
@@ -1135,6 +1142,7 @@ cifaddr(u, o, h)
        ipmuxid = -1;
     }
 #endif
+    remote_addr = 0;
     return 1;
 }
 
@@ -1283,7 +1291,7 @@ get_ether_addr(ipaddr, hwaddr)
        /*
         * Check that the interface is up, and not point-to-point or loopback.
         */
-       strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+       strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
        if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
            continue;
        if ((ifreq.ifr_flags &
@@ -1308,7 +1316,7 @@ get_ether_addr(ipaddr, hwaddr)
     }
 
     syslog(LOG_INFO, "found interface %s for proxy ARP", ifr->ifr_name);
-    if (!get_hw_addr(ifr->ifr_name, hwaddr)) {
+    if (!get_hw_addr(ifr->ifr_name, ina, hwaddr)) {
        syslog(LOG_ERR, "Couldn't get hardware address for %s", ifr->ifr_name);
        free(ifc.ifc_buf);
        return 0;
@@ -1322,10 +1330,30 @@ get_ether_addr(ipaddr, hwaddr)
  * get_hw_addr - obtain the hardware address for a named interface.
  */
 static int
-get_hw_addr(name, hwaddr)
+get_hw_addr(name, ina, hwaddr)
     char *name;
+    u_int32_t ina;
     struct sockaddr *hwaddr;
 {
+#if 1
+    /* New way - get the address by doing an arp request. */
+    int s;
+    struct arpreq req;
+
+    s = socket(AF_INET, SOCK_DGRAM, 0);
+    if (s < 0)
+       return 0;
+    memset(&req, 0, sizeof(req));
+    req.arp_pa.sa_family = AF_INET;
+    INET_ADDR(req.arp_pa) = ina;
+    if (ioctl(s, SIOCGARP, &req) < 0) {
+       syslog(LOG_ERR, "Couldn't get ARP entry for %s: %m", ip_ntoa(ina));
+       return 0;
+    }
+    *hwaddr = req.arp_ha;
+    hwaddr->sa_family = AF_UNSPEC;
+
+#else /* 0 */
     char *p, *q;
     int unit, iffd, adrlen;
     unsigned char *adrp;
@@ -1339,12 +1367,12 @@ get_hw_addr(name, hwaddr)
      * We have to open the device and ask it for its hardware address.
      * First split apart the device name and unit.
      */
-    strcpy(ifdev, "/dev/");
-    q = ifdev + 5;             /* strlen("/dev/") */
-    while (*name != 0 && !isdigit(*name))
-       *q++ = *name++;
-    *q = 0;
-    unit = atoi(name);
+    slprintf(ifdev, sizeof(ifdev), "/dev/%s", name);
+    for (q = ifdev + strlen(ifdev); --q >= ifdev; )
+       if (!isdigit(*q))
+           break;
+    unit = atoi(q+1);
+    q[1] = 0;
 
     /*
      * Open the device and do a DLPI attach and phys_addr_req.
@@ -1372,6 +1400,7 @@ get_hw_addr(name, hwaddr)
 #endif
     hwaddr->sa_family = AF_UNSPEC;
     memcpy(hwaddr->sa_data, adrp, adrlen);
+#endif /* 0 */
 
     return 1;
 }
@@ -1511,7 +1540,7 @@ GetMask(addr)
        /*
         * Check that the interface is up, and not point-to-point or loopback.
         */
-       strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+       strlcpy(ifreq.ifr_name, sizeof(ifreq.ifr_name), ifr->ifr_name);
        if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0)
            continue;
        if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
@@ -1540,9 +1569,9 @@ logwtmp(line, name, host)
 
     if (name[0] != 0) {
        /* logging in */
-       strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user));
-       strncpy(utmpx.ut_id, ifname, sizeof(utmpx.ut_id));
-       strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
+       strlcpy(utmpx.ut_user, sizeof(utmpx.ut_user), name);
+       strlcpy(utmpx.ut_id, sizeof(utmpx.ut_id), ifname);
+       strlcpy(utmpx.ut_line, sizeof(utmpx.ut_line), line);
        utmpx.ut_pid = getpid();
        utmpx.ut_type = USER_PROCESS;
     } else {
@@ -1688,3 +1717,110 @@ cifroute(u, our, his)
 
     return 1;
 }
+
+/*
+ * have_route_to - determine if the system has a route to the specified
+ * IP address.  Returns 0 if not, 1 if so, -1 if we can't tell.
+ * `addr' is in network byte order.
+ * For demand mode to work properly, we have to ignore routes
+ * through our own interface.
+ */
+#ifndef T_CURRENT              /* needed for Solaris 2.5 */
+#define T_CURRENT      MI_T_CURRENT
+#endif
+
+int
+have_route_to(addr)
+    u_int32_t addr;
+{
+    int fd, r, flags, i;
+    struct {
+       struct T_optmgmt_req req;
+       struct opthdr hdr;
+    } req;
+    union {
+       struct T_optmgmt_ack ack;
+       unsigned char space[64];
+    } ack;
+    struct opthdr *rh;
+    struct strbuf cbuf, dbuf;
+    int nroutes;
+    mib2_ipRouteEntry_t routes[8];
+    mib2_ipRouteEntry_t *rp;
+
+    fd = open("/dev/ip", O_RDWR);
+    if (fd < 0) {
+       syslog(LOG_WARNING, "have_route_to: couldn't open /dev/ip: %m");
+       return -1;
+    }
+
+    req.req.PRIM_type = T_OPTMGMT_REQ;
+    req.req.OPT_offset = (char *) &req.hdr - (char *) &req;
+    req.req.OPT_length = sizeof(req.hdr);
+    req.req.MGMT_flags = T_CURRENT;
+
+    req.hdr.level = MIB2_IP;
+    req.hdr.name = 0;
+    req.hdr.len = 0;
+
+    cbuf.buf = (char *) &req;
+    cbuf.len = sizeof(req);
+
+    if (putmsg(fd, &cbuf, NULL, 0) == -1) {
+       syslog(LOG_WARNING, "have_route_to: putmsg: %m");
+       close(fd);
+       return -1;
+    }
+
+    for (;;) {
+       cbuf.buf = (char *) &ack;
+       cbuf.maxlen = sizeof(ack);
+       dbuf.buf = (char *) routes;
+       dbuf.maxlen = sizeof(routes);
+       flags = 0;
+       r = getmsg(fd, &cbuf, &dbuf, &flags);
+       if (r == -1) {
+           syslog(LOG_WARNING, "have_route_to: getmsg: %m");
+           close(fd);
+           return -1;
+       }
+
+       if (cbuf.len < sizeof(struct T_optmgmt_ack)
+           || ack.ack.PRIM_type != T_OPTMGMT_ACK
+           || ack.ack.MGMT_flags != T_SUCCESS
+           || ack.ack.OPT_length < sizeof(struct opthdr)) {
+           syslog(LOG_DEBUG, "have_route_to: bad message len=%d prim=%d",
+                  cbuf.len, ack.ack.PRIM_type);
+           close(fd);
+           return -1;
+       }
+
+       rh = (struct opthdr *) ((char *)&ack + ack.ack.OPT_offset);
+       if (rh->level == 0 && rh->name == 0)
+           break;
+       if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) {
+           while (r == MOREDATA)
+               r = getmsg(fd, NULL, &dbuf, &flags);
+           continue;
+       }
+
+       for (;;) {
+           nroutes = dbuf.len / sizeof(mib2_ipRouteEntry_t);
+           for (rp = routes, i = 0; i < nroutes; ++i, ++rp) {
+               if (rp->ipRouteMask != ~0) {
+                   syslog(LOG_DEBUG, "have_route_to: dest=%x gw=%x mask=%x\n",
+                          rp->ipRouteDest, rp->ipRouteNextHop,
+                          rp->ipRouteMask);
+                   if (((addr ^ rp->ipRouteDest) & rp->ipRouteMask) == 0
+                       && rp->ipRouteNextHop != remote_addr)
+                       return 1;
+               }
+           }
+           if (r == 0)
+               break;
+           r = getmsg(fd, NULL, &dbuf, &flags);
+       }
+    }
+    close(fd);
+    return 0;
+}