diff options
author | Henric Jungheim <henric@cvs.openbsd.org> | 2003-03-17 23:26:22 +0000 |
---|---|---|
committer | Henric Jungheim <henric@cvs.openbsd.org> | 2003-03-17 23:26:22 +0000 |
commit | 751d2933016216b057959af5869762c7d898f0a1 (patch) | |
tree | 95e9c25376dd32c61541c6fa8b350100ec2d42b3 /usr.sbin | |
parent | d5316210dc9e14015fa84f0358d2e1296776dc0a (diff) |
arp did not long-align sockaddrs in routing messages. This led to
garbage being sent to the kernel on sparc64.
Problem reported and fix tested by Doug Winter (thanks).
ok jason@ and millert@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/arp/arp.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c index 22fbd38c61f..21fe43f5f1f 100644 --- a/usr.sbin/arp/arp.c +++ b/usr.sbin/arp/arp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: arp.c,v 1.25 2002/12/03 22:33:50 fgsch Exp $ */ +/* $OpenBSD: arp.c,v 1.26 2003/03/17 23:26:21 henric Exp $ */ /* $NetBSD: arp.c,v 1.12 1995/04/24 13:25:18 cgd Exp $ */ /* @@ -45,7 +45,7 @@ static char copyright[] = #ifndef lint /*static char sccsid[] = "from: @(#)arp.c 8.2 (Berkeley) 1/2/94";*/ -static char *rcsid = "$OpenBSD: arp.c,v 1.25 2002/12/03 22:33:50 fgsch Exp $"; +static char *rcsid = "$OpenBSD: arp.c,v 1.26 2003/03/17 23:26:21 henric Exp $"; #endif /* not lint */ /* @@ -96,6 +96,10 @@ static int nflag; /* no reverse dns lookups */ static int aflag; /* do it for all entries */ static int s = -1; +/* ROUNDUP() is nasty, but it is identical to what's in the kernel. */ +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) + /* which function we're supposed to do */ #define F_GET 1 #define F_SET 2 @@ -299,7 +303,7 @@ tryagain: return (1); } sin = (struct sockaddr_inarp *)(rtm + 1); - sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); + sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin_len) + (char *)sin); if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { if (sdl->sdl_family == AF_LINK && (rtm->rtm_flags & RTF_LLINFO) && @@ -383,7 +387,7 @@ tryagain: return (1); } sin = (struct sockaddr_inarp *)(rtm + 1); - sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); + sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin_len) + (char *)sin); if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { if (sdl->sdl_family == AF_LINK && (rtm->rtm_flags & RTF_LLINFO) && @@ -500,11 +504,11 @@ print_entry(sdl, sin, rtm) (void)printf(" published (proxy only)"); if (rtm->rtm_addrs & RTA_NETMASK) { sin = (struct sockaddr_inarp *) - (sdl->sdl_len + (char *)sdl); + (ROUNDUP(sdl->sdl_len) + (char *)sdl); if (sin->sin_addr.s_addr == 0xffffffff) (void)printf(" published"); if (sin->sin_len != 8) - (void)printf("(weird)"); + (void)printf("(weird %d)", sin->sin_len); } printf("\n"); } @@ -588,9 +592,12 @@ rtmsg(cmd) case RTM_GET: rtm->rtm_addrs |= RTA_DST; } -#define NEXTADDR(w, s) \ - if (rtm->rtm_addrs & (w)) { \ - (void)memcpy(cp, &s, sizeof(s)); cp += sizeof(s);} + +#define NEXTADDR(w, s) \ + if (rtm->rtm_addrs & (w)) { \ + (void)memcpy(cp, &s, sizeof(s)); \ + cp += ROUNDUP(sizeof(s)); \ + } NEXTADDR(RTA_DST, sin_m); NEXTADDR(RTA_GATEWAY, sdl_m); |