]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-svr4.c
fix compile problems on OSF/1
[ppp.git] / pppd / sys-svr4.c
index d2bc489dd991797211b087d1fcaccaf1c679e5a2..d525064e10dd54f3ba6094dbb7cb183ee6f19b07 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: sys-svr4.c,v 1.19 1999/01/20 00:01:53 paulus Exp $";
+static char rcsid[] = "$Id: sys-svr4.c,v 1.23 1999/03/08 05:34:46 paulus Exp $";
 #endif
 
 #include <limits.h>
@@ -61,6 +61,10 @@ static char rcsid[] = "$Id: sys-svr4.c,v 1.19 1999/01/20 00:01:53 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 */
 
@@ -1113,6 +1118,7 @@ sifaddr(u, o, h, m)
     }
 #endif
 
+    remote_addr = h;
     return ret;
 }
 
@@ -1136,6 +1142,7 @@ cifaddr(u, o, h)
        ipmuxid = -1;
     }
 #endif
+    remote_addr = 0;
     return 1;
 }
 
@@ -1337,10 +1344,10 @@ get_hw_addr(name, ina, hwaddr)
     if (s < 0)
        return 0;
     memset(&req, 0, sizeof(req));
-    req.arp_pa.sin_family = AF_INET;
+    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", inet_itoa(ina));
+       syslog(LOG_ERR, "Couldn't get ARP entry for %s: %m", ip_ntoa(ina));
        return 0;
     }
     *hwaddr = req.arp_ha;
@@ -1710,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;
+}