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