X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fsys-svr4.c;h=4173e4d2f4c246e81431403960c3929ad0689d80;hp=246712d7c8740d55cc18984b13fde67f5c4a97ba;hb=1fae28ce79350b03f0cf8a69ad06dd68637cd6b1;hpb=bfa20ccde2a70b1252dbb614132f1a4cbee815d4 diff --git a/pppd/sys-svr4.c b/pppd/sys-svr4.c index 246712d..4173e4d 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.18 1998/11/07 06:59:31 paulus Exp $"; +static char rcsid[] = "$Id: sys-svr4.c,v 1.24 1999/03/12 06:07:23 paulus Exp $"; #endif #include @@ -61,6 +61,10 @@ static char rcsid[] = "$Id: sys-svr4.c,v 1.18 1998/11/07 06:59:31 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 */ @@ -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)); @@ -748,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); @@ -819,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"); @@ -1001,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; @@ -1026,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; @@ -1074,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) { @@ -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; } @@ -1284,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 & @@ -1309,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; @@ -1323,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; @@ -1340,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. @@ -1373,6 +1400,7 @@ get_hw_addr(name, hwaddr) #endif hwaddr->sa_family = AF_UNSPEC; memcpy(hwaddr->sa_data, adrp, adrlen); +#endif /* 0 */ return 1; } @@ -1512,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)) @@ -1541,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 { @@ -1689,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; +}