Synopsis: Problems with ARP
NetBSD versions: NetBSD 1.3*, NetBSD-current to 19990505.
Thanks to: Olaf "Rhialto" Seibert, Zdenek Salvet and Ignatios Souvatzis.
Reported in NetBSD Security Advisory: SA1999-010

--- sys/netinet/if_arp.c.orig	Thu Oct  1 19:56:11 1998
+++ sys/netinet/if_arp.c	Wed May  5 17:04:31 1999
@@ -576,10 +576,30 @@
 	la = arplookup(&isaddr, in_hosteq(itaddr, myaddr), 0);
 	if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
 		if (sdl->sdl_alen &&
-		    bcmp((caddr_t)ar_sha(ah), LLADDR(sdl), sdl->sdl_alen))
-			log(LOG_INFO, "arp info overwritten for %08x by %s\n",
-			    ntohl(isaddr.s_addr),
-			    lla_snprintf(ar_sha(ah), ah->ar_hln));
+		    bcmp((caddr_t)ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) {
+			if (rt->rt_flags & RTF_STATIC) {
+				log(LOG_INFO,
+				    "%s tried to overwrite permanent arp info"
+				    " for %08x\n",
+				    lla_snprintf(ar_sha(ah), ah->ar_hln),
+				    ntohl(isaddr.s_addr));
+				goto out;
+			} else if (rt->rt_ifp != ifp) {
+				log(LOG_INFO,
+				    "%s on %s tried to overwrite "
+				    "arp info for %08x on %s\n",
+				    lla_snprintf(ar_sha(ah), ah->ar_hln),
+				    ifp->if_xname, ntohl(isaddr.s_addr),
+				    rt->rt_ifp->if_xname);
+				    goto out;
+			} else {
+				log(LOG_INFO,
+				    "arp info overwritten for %08x by %s\n",
+				    ntohl(isaddr.s_addr),
+				    lla_snprintf(ar_sha(ah), ah->ar_hln));
+			}
+		}
+
 		/* 
 		 * sanity check for the address length.
 		 * XXX this does not work for protocols with variable address