Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet arp: find source address then target address whe...



details:   https://anonhg.NetBSD.org/src/rev/fbde5af77a62
branches:  trunk
changeset: 968655:fbde5af77a62
user:      roy <roy%NetBSD.org@localhost>
date:      Thu Jan 23 17:27:35 2020 +0000

description:
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.

diffstat:

 sys/netinet/if_arp.c |  32 +++++++++++++++++++++++++-------
 1 files changed, 25 insertions(+), 7 deletions(-)

diffs (76 lines):

diff -r e18fc8a3c0be -r fbde5af77a62 sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c      Thu Jan 23 17:23:03 2020 +0000
+++ b/sys/netinet/if_arp.c      Thu Jan 23 17:27:35 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_arp.c,v 1.291 2020/01/20 18:38:22 thorpej Exp $     */
+/*     $NetBSD: if_arp.c,v 1.292 2020/01/23 17:27:35 roy 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.291 2020/01/20 18:38:22 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.292 2020/01/23 17:27:35 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -988,7 +988,7 @@
        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;
@@ -1023,11 +1023,20 @@
         * 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;
@@ -1069,6 +1078,15 @@
                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);
@@ -1722,7 +1740,7 @@
 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;



Home | Main Index | Thread Index | Old Index