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;

Reply via email to