Module Name: src Committed By: martin Date: Fri Jan 24 18:57:02 UTC 2020
Modified Files: src/sys/netinet [netbsd-9]: if_arp.c Log Message: Pull up following revision(s) (requested by roy in ticket #645): sys/netinet/if_arp.c: revision 1.292 arp: find source address then target address when processing input This fixes the case where another host having a duplicate ip address starts using it right away without probing for it's availability. While here, prefer ifatoia over a strict cast. To generate a diff of this commit: cvs rdiff -u -r1.282.2.5 -r1.282.2.6 src/sys/netinet/if_arp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet/if_arp.c diff -u src/sys/netinet/if_arp.c:1.282.2.5 src/sys/netinet/if_arp.c:1.282.2.6 --- src/sys/netinet/if_arp.c:1.282.2.5 Fri Oct 11 18:22:14 2019 +++ src/sys/netinet/if_arp.c Fri Jan 24 18:57:02 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_arp.c,v 1.282.2.5 2019/10/11 18:22:14 martin Exp $ */ +/* $NetBSD: if_arp.c,v 1.282.2.6 2020/01/24 18:57:02 martin Exp $ */ /* * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.282.2.5 2019/10/11 18:22:14 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.282.2.6 2020/01/24 18:57:02 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -1025,7 +1025,7 @@ in_arpinput(struct mbuf *m) struct psref psref, psref_ia; int s; char ipbuf[INET_ADDRSTRLEN]; - bool do_dad; + bool find_source, do_dad; if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT))) goto out; @@ -1060,11 +1060,20 @@ in_arpinput(struct mbuf *m) * or any address on the interface to use * as a dummy address in the rest of this function. * - * If the target IP address is zero then try and find - * the sender address for DAD. + * First try and find the source address for early + * duplicate address detection. */ - myaddr = in_nullhost(itaddr) ? isaddr : itaddr; + if (in_nullhost(isaddr)) { + if (in_nullhost(itaddr)) /* very bogus ARP */ + goto out; + find_source = false; + myaddr = itaddr; + } else { + find_source = true; + myaddr = isaddr; + } s = pserialize_read_enter(); +again: IN_ADDRHASH_READER_FOREACH(ia, myaddr.s_addr) { if (!in_hosteq(ia->ia_addr.sin_addr, myaddr)) continue; @@ -1106,6 +1115,15 @@ in_arpinput(struct mbuf *m) ifp = bridge_ia->ia_ifp; } #endif + + /* If we failed to find the source address then find + * the target address. */ + if (ia == NULL && find_source && !in_nullhost(itaddr)) { + find_source = false; + myaddr = itaddr; + goto again; + } + if (ia != NULL) ia4_acquire(ia, &psref_ia); pserialize_read_exit(s); @@ -1787,7 +1805,7 @@ done: static void arp_dad_duplicated(struct ifaddr *ifa, const struct sockaddr_dl *from) { - struct in_ifaddr *ia = (struct in_ifaddr *)ifa; + struct in_ifaddr *ia = ifatoia(ifa); struct ifnet *ifp = ifa->ifa_ifp; char ipbuf[INET_ADDRSTRLEN], llabuf[LLA_ADDRSTRLEN]; const char *iastr, *llastr;