X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fsys-svr4.c;h=d525064e10dd54f3ba6094dbb7cb183ee6f19b07;hp=d2bc489dd991797211b087d1fcaccaf1c679e5a2;hb=f0a6c417e65393d127a9f0fe0ba668ec2d2fdf3b;hpb=3fba081c6e1607ab349fc3237d1d519f1dc14e4d diff --git a/pppd/sys-svr4.c b/pppd/sys-svr4.c index d2bc489..d525064 100644 --- a/pppd/sys-svr4.c +++ b/pppd/sys-svr4.c @@ -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 @@ -61,6 +61,10 @@ static char rcsid[] = "$Id: sys-svr4.c,v 1.19 1999/01/20 00:01:53 paulus Exp $"; #include #include #include +#include +#include +#include +#include #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; +}