diff options
author | brian <brian@FreeBSD.org> | 1998-01-19 02:59:34 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 1998-01-19 02:59:34 +0000 |
commit | a4acc2b6f976579bebc0c80d90760486a832f261 (patch) | |
tree | 477af83ef0de4914fc1dd987f702873c9eb2f7c4 | |
parent | 3ef8b0b8d77df5d4f852819e42dab40f2665ce13 (diff) | |
download | FreeBSD-src-a4acc2b6f976579bebc0c80d90760486a832f261.zip FreeBSD-src-a4acc2b6f976579bebc0c80d90760486a832f261.tar.gz |
Reimplement proxy-arp address stuff using sysctl().
-rw-r--r-- | usr.sbin/ppp/arp.c | 200 | ||||
-rw-r--r-- | usr.sbin/ppp/arp.h | 6 | ||||
-rw-r--r-- | usr.sbin/ppp/os.c | 6 | ||||
-rw-r--r-- | usr.sbin/ppp/route.c | 5 | ||||
-rw-r--r-- | usr.sbin/ppp/route.h | 3 |
5 files changed, 127 insertions, 93 deletions
diff --git a/usr.sbin/ppp/arp.c b/usr.sbin/ppp/arp.c index b54ebca..0287b2e 100644 --- a/usr.sbin/ppp/arp.c +++ b/usr.sbin/ppp/arp.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: arp.c,v 1.20 1997/12/24 09:28:49 brian Exp $ + * $Id: arp.c,v 1.21 1998/01/11 04:02:57 brian Exp $ * */ @@ -37,9 +37,11 @@ #include <fcntl.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <sys/errno.h> #include <sys/ioctl.h> +#include <sys/sysctl.h> #include <sys/uio.h> #include <unistd.h> @@ -47,11 +49,37 @@ #include "mbuf.h" #include "log.h" #include "id.h" +#include "route.h" #include "arp.h" +#ifdef DEBUG +/* + * To test the proxy arp stuff, put the following in your Makefile: + * + * arp-test: arp.c + * cp ${.CURDIR}/arp.c arp-test.c + * echo 'const char *' >>arp-test.c + * awk '/^Index2Nam/,/^}/' ${.CURDIR}/route.c >>arp-test.c + * cc -I${.CURDIR} -DDEBUG arp-test.c -o arp-test + * + * and type ``make arp-test''. + * + */ +#define LogIsKept(x) 0 +#define LogPrintf fprintf +#undef LogDEBUG +#define LogDEBUG stderr +#undef LogERROR +#define LogERROR stderr +#undef LogPHASE +#define LogPHASE stdout +#define ID0socket socket +#define ID0ioctl ioctl +#endif + static int rtm_seq; -static int get_ether_addr(int, u_long, struct sockaddr_dl *); +static int get_ether_addr(int, struct in_addr, struct sockaddr_dl *); /* * SET_SA_FAMILY - set the sa_family field of a struct sockaddr, @@ -78,7 +106,7 @@ static struct { static int arpmsg_valid; int -sifproxyarp(int unit, u_long hisaddr) +sifproxyarp(int unit, struct in_addr hisaddr) { int routes; @@ -105,7 +133,7 @@ sifproxyarp(int unit, u_long hisaddr) arpmsg.hdr.rtm_inits = RTV_EXPIRE; arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp); arpmsg.dst.sin_family = AF_INET; - arpmsg.dst.sin_addr.s_addr = hisaddr; + arpmsg.dst.sin_addr.s_addr = hisaddr.s_addr; arpmsg.dst.sin_other = SIN_PROXY; arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg @@ -124,7 +152,7 @@ sifproxyarp(int unit, u_long hisaddr) * cifproxyarp - Delete the proxy ARP entry for the peer. */ int -cifproxyarp(int unit, u_long hisaddr) +cifproxyarp(int unit, struct in_addr hisaddr) { int routes; @@ -156,7 +184,7 @@ cifproxyarp(int unit, u_long hisaddr) * sifproxyarp - Make a proxy ARP entry for the peer. */ int -sifproxyarp(int unit, u_long hisaddr) +sifproxyarp(int unit, struct in_addr hisaddr) { struct arpreq arpreq; struct { @@ -178,7 +206,7 @@ sifproxyarp(int unit, u_long hisaddr) arpreq.arp_ha.sa_family = AF_UNSPEC; memcpy(arpreq.arp_ha.sa_data, LLADDR(&dls.sdl), dls.sdl.sdl_alen); SET_SA_FAMILY(arpreq.arp_pa, AF_INET); - ((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr; + ((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr.s_addr; arpreq.arp_flags = ATF_PERM | ATF_PUBL; if (ID0ioctl(unit, SIOCSARP, (caddr_t) & arpreq) < 0) { LogPrintf(LogERROR, "sifproxyarp: ioctl(SIOCSARP): %s\n", strerror(errno)); @@ -191,13 +219,13 @@ sifproxyarp(int unit, u_long hisaddr) * cifproxyarp - Delete the proxy ARP entry for the peer. */ int -cifproxyarp(int unit, u_long hisaddr) +cifproxyarp(int unit, struct in_addr hisaddr) { struct arpreq arpreq; memset(&arpreq, '\0', sizeof arpreq); SET_SA_FAMILY(arpreq.arp_pa, AF_INET); - ((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr; + ((struct sockaddr_in *) & arpreq.arp_pa)->sin_addr.s_addr = hisaddr.s_addr; if (ID0ioctl(unit, SIOCDARP, (caddr_t) & arpreq) < 0) { LogPrintf(LogERROR, "cifproxyarp: ioctl(SIOCDARP): %s\n", strerror(errno)); return 0; @@ -215,96 +243,102 @@ cifproxyarp(int unit, u_long hisaddr) #define MAX_IFS 32 static int -get_ether_addr(int s, u_long ipaddr, struct sockaddr_dl *hwaddr) +get_ether_addr(int s, struct in_addr ipaddr, struct sockaddr_dl *hwaddr) { - struct ifreq *ifr, *ifend, *ifp; - u_long ina, mask; - struct sockaddr_dl *dla; - struct ifreq ifreq; - struct ifconf ifc; - struct ifreq ifs[MAX_IFS]; - - ifc.ifc_len = sizeof ifs; - ifc.ifc_req = ifs; - if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { - LogPrintf(LogERROR, "get_ether_addr: ioctl(SIOCGIFCONF): %s\n", - strerror(errno)); - return 0; - } - - /* - * Scan through looking for an interface with an Internet address on the - * same subnet as `ipaddr'. - */ - ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); - for (ifr = ifc.ifc_req; ifr < ifend;) { - if (ifr->ifr_addr.sa_family == AF_INET) { - ina = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr.s_addr; - strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof ifreq.ifr_name - 1); - ifreq.ifr_name[sizeof ifreq.ifr_name - 1] = '\0'; - - /* - * Check that the interface is up, and not point-to-point or loopback. - */ - if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) - continue; - if ((ifreq.ifr_flags & - (IFF_UP | IFF_BROADCAST | IFF_POINTOPOINT | IFF_LOOPBACK | IFF_NOARP)) - != (IFF_UP | IFF_BROADCAST)) - goto nextif; - - /* - * Get its netmask and check that it's on the right subnet. - */ - if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) - continue; - mask = ((struct sockaddr_in *) & ifreq.ifr_addr)->sin_addr.s_addr; - if ((ipaddr & mask) != (ina & mask)) - goto nextif; - - break; + int idx; + const char *got; + char *sp, *ep, *cp, *wp; + struct ifreq ifrq; + struct in_addr addr, mask; + struct rt_msghdr *rtm; + struct sockaddr *sa_dst, *sa_gw; + struct sockaddr_dl *dl; + size_t needed; + int mib[6]; + + idx = 1; + while (strcmp(got = Index2Nam(idx), "???")) { + strncpy(ifrq.ifr_name, got, sizeof ifrq.ifr_name - 1); + ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; + if (ID0ioctl(s, SIOCGIFADDR, &ifrq) == 0 && + ifrq.ifr_addr.sa_family == AF_INET) { + addr = ((struct sockaddr_in *)&ifrq.ifr_addr)->sin_addr; + if (ID0ioctl(s, SIOCGIFNETMASK, &ifrq) == 0) { + mask = ((struct sockaddr_in *)&ifrq.ifr_broadaddr)->sin_addr; + if ((ipaddr.s_addr & mask.s_addr) == (addr.s_addr & mask.s_addr)) + break; + } } -nextif: - ifr = (struct ifreq *) ((char *) &ifr->ifr_addr + ifr->ifr_addr.sa_len); + idx++; } - if (ifr >= ifend) + if (!strcmp(got, "???")) return 0; - LogPrintf(LogPHASE, "Found interface %s for proxy arp\n", ifr->ifr_name); - /* - * Now scan through again looking for a link-level address for this - * interface. - */ - ifp = ifr; - for (ifr = ifc.ifc_req; ifr < ifend;) { - if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 - && ifr->ifr_addr.sa_family == AF_LINK) { - - /* - * Found the link-level address - copy it out - */ - dla = (struct sockaddr_dl *) & ifr->ifr_addr; - memcpy(hwaddr, dla, dla->sdl_len); - return 1; + LogPrintf(LogPHASE, "Found interface %s for proxy arp\n", got); + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_DUMP; + mib[5] = 0; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { + LogPrintf(LogERROR, "get_ether_addr: sysctl: estimate: %s\n", + strerror(errno)); + return 0; + } + if (needed < 0) + return 0; + if ((sp = malloc(needed)) == NULL) + return 0; + if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { + LogPrintf(LogERROR, "ShowRoute: sysctl: getroute: %s\n", strerror(errno)); + free(sp); + return (1); + } + ep = sp + needed; + + for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *) cp; + if (rtm->rtm_index == idx) { + wp = (char *)(rtm+1); + + if (rtm->rtm_addrs & RTA_DST) { + sa_dst = (struct sockaddr *)wp; + wp += sa_dst->sa_len; + } else + sa_dst = NULL; + + if (rtm->rtm_addrs & RTA_GATEWAY) { + sa_gw = (struct sockaddr *)wp; + if (sa_gw->sa_family == AF_LINK) { + dl = (struct sockaddr_dl *)wp; + if (dl->sdl_alen && dl->sdl_type == IFT_ETHER) { + memcpy(hwaddr, dl, dl->sdl_len); + free(sp); + return 1; + } + } + } } - ifr = (struct ifreq *) ((char *) &ifr->ifr_addr + ifr->ifr_addr.sa_len); } - + free(sp); return 0; } - #ifdef DEBUG int -main() +main(int argc, char **argv) { - u_long ipaddr; - int s; + struct in_addr ipaddr; + int s, f; s = socket(AF_INET, SOCK_DGRAM, 0); - ipaddr = inet_addr("192.168.1.32"); - sifproxyarp(s, ipaddr); + for (f = 1; f < argc; f++) { + if (inet_aton(argv[f], &ipaddr)) + sifproxyarp(s, ipaddr); + } close(s); } #endif diff --git a/usr.sbin/ppp/arp.h b/usr.sbin/ppp/arp.h index 8c54720..8d419d1 100644 --- a/usr.sbin/ppp/arp.h +++ b/usr.sbin/ppp/arp.h @@ -17,9 +17,9 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: arp.h,v 1.5 1997/08/25 00:29:04 brian Exp $ + * $Id: arp.h,v 1.6 1997/10/26 01:02:04 brian Exp $ * */ -extern int cifproxyarp(int, u_long); -extern int sifproxyarp(int, u_long); +extern int cifproxyarp(int, struct in_addr); +extern int sifproxyarp(int, struct in_addr); diff --git a/usr.sbin/ppp/os.c b/usr.sbin/ppp/os.c index 541aace..b2b268e 100644 --- a/usr.sbin/ppp/os.c +++ b/usr.sbin/ppp/os.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: os.c,v 1.39 1998/01/08 23:47:55 brian Exp $ + * $Id: os.c,v 1.40 1998/01/11 17:53:25 brian Exp $ * */ #include <sys/param.h> @@ -82,7 +82,7 @@ SetIpDevice(struct in_addr myaddr, } if (how == SET_DOWN) { if (Enabled(ConfProxy)) - cifproxyarp(s, oldhis.s_addr); + cifproxyarp(s, oldhis); if (oldmine.s_addr == 0 && oldhis.s_addr == 0) { close(s); return (0); @@ -161,7 +161,7 @@ SetIpDevice(struct in_addr myaddr, oldhis.s_addr = hisaddr.s_addr; oldmine.s_addr = myaddr.s_addr; if (Enabled(ConfProxy)) - sifproxyarp(s, hisaddr.s_addr); + sifproxyarp(s, hisaddr); } close(s); return (0); diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c index 16c3a9e..2aa2709 100644 --- a/usr.sbin/ppp/route.c +++ b/usr.sbin/ppp/route.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: route.c,v 1.39 1998/01/11 02:59:22 brian Exp $ + * $Id: route.c,v 1.40 1998/01/11 04:45:36 brian Exp $ * */ @@ -54,7 +54,6 @@ #include "route.h" static int IfIndex; -static const char *Index2Nam(int); struct rtmsg { struct rt_msghdr m_rtm; @@ -308,7 +307,7 @@ p_flags(u_long f, int max) } } -static const char * +const char * Index2Nam(int idx) { static char **ifs; diff --git a/usr.sbin/ppp/route.h b/usr.sbin/ppp/route.h index 9ccf95b..1338487 100644 --- a/usr.sbin/ppp/route.h +++ b/usr.sbin/ppp/route.h @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: route.h,v 1.8 1997/12/13 02:37:32 brian Exp $ + * $Id: route.h,v 1.9 1997/12/30 02:45:48 brian Exp $ * */ @@ -26,3 +26,4 @@ extern int ShowRoute(struct cmdargs const *); extern void OsSetRoute(int, struct in_addr, struct in_addr, struct in_addr,int); extern void DeleteIfRoutes(int); extern struct in_addr ChooseHisAddr(const struct in_addr); +extern const char *Index2Nam(int); |