Source-Changes-HG archive

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

[src/trunk]: src/sys arp: Validate ARP source hardware address matches Ethern...



details:   https://anonhg.NetBSD.org/src/rev/e4b5d4c706ff
branches:  trunk
changeset: 372325:e4b5d4c706ff
user:      roy <roy%NetBSD.org@localhost>
date:      Tue Nov 15 10:47:39 2022 +0000

description:
arp: Validate ARP source hardware address matches Ethernet source

RFC 5227 section 1.1 states that for a DaD ARP probe the sender hardware
address must match the hardware address of the interface sending the
packet.

We can now verify this by checking the mbuf tag PACKET_TAG_ETHERNET_SRC.

This fixes an obsure issue where an old router was sending out bogus
ARP probes.

Thanks to Ryo Shimizu <ryo%nerv.org@localhost> for the re-implementation.

diffstat:

 sys/net/if_ethersubr.c |  17 +++++++++++++++--
 sys/netinet/if_arp.c   |  24 ++++++++++++++++--------
 sys/sys/mbuf.h         |   3 ++-
 3 files changed, 33 insertions(+), 11 deletions(-)

diffs (108 lines):

diff -r a80b0f18d8a5 -r e4b5d4c706ff sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c    Tue Nov 15 10:29:56 2022 +0000
+++ b/sys/net/if_ethersubr.c    Tue Nov 15 10:47:39 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ethersubr.c,v 1.322 2022/11/15 09:14:28 roy Exp $   */
+/*     $NetBSD: if_ethersubr.c,v 1.323 2022/11/15 10:47:39 roy Exp $   */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.322 2022/11/15 09:14:28 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.323 2022/11/15 10:47:39 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -886,6 +886,19 @@
 #endif
        }
 
+       /* For ARP packets, store the source address so that
+        * ARP DAD probes can be validated. */
+       if (etype == ETHERTYPE_ARP) {
+               struct m_tag *mtag;
+
+               mtag = m_tag_get(PACKET_TAG_ETHERNET_SRC, ETHER_ADDR_LEN,
+                   M_NOWAIT);
+               if (mtag != NULL) {
+                       memcpy(mtag + 1, &eh->ether_shost, ETHER_ADDR_LEN);
+                       m_tag_prepend(m, mtag);
+               }
+       }
+
        /* Strip off the Ethernet header. */
        m_adj(m, ehlen);
 
diff -r a80b0f18d8a5 -r e4b5d4c706ff sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c      Tue Nov 15 10:29:56 2022 +0000
+++ b/sys/netinet/if_arp.c      Tue Nov 15 10:47:39 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_arp.c,v 1.310 2022/11/15 09:15:43 roy Exp $ */
+/*     $NetBSD: if_arp.c,v 1.311 2022/11/15 10:47:39 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.310 2022/11/15 09:15:43 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.311 2022/11/15 10:47:39 roy Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -932,6 +932,8 @@
 
        /*
         * DAD check, RFC 5227.
+        * ARP sender hardware address must match the interface
+        * address of the interface sending the packet.
         * Collision on sender address is always a duplicate.
         * Collision on target address is only a duplicate
         * IF the sender address is the null host (ie a DAD probe)
@@ -945,13 +947,19 @@
             m->m_flags & M_BCAST &&
             ia->ia4_flags & (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED))))
        {
-               struct sockaddr_dl sdl, *sdlp;
+               struct m_tag *mtag;
+
+               mtag = m_tag_find(m, PACKET_TAG_ETHERNET_SRC);
+               if (mtag == NULL || (ah->ar_hln == ETHER_ADDR_LEN &&
+                   memcmp(mtag + 1, ar_sha(ah), ah->ar_hln) == 0)) {
+                       struct sockaddr_dl sdl, *sdlp;
 
-               sdlp = sockaddr_dl_init(&sdl, sizeof(sdl),
-                   ifp->if_index, ifp->if_type,
-                   NULL, 0, ar_sha(ah), ah->ar_hln);
-               arp_dad_duplicated((struct ifaddr *)ia, sdlp);
-               goto out;
+                       sdlp = sockaddr_dl_init(&sdl, sizeof(sdl),
+                           ifp->if_index, ifp->if_type,
+                           NULL, 0, ar_sha(ah), ah->ar_hln);
+                       arp_dad_duplicated((struct ifaddr *)ia, sdlp);
+                       goto out;
+               }
        }
 
        /*
diff -r a80b0f18d8a5 -r e4b5d4c706ff sys/sys/mbuf.h
--- a/sys/sys/mbuf.h    Tue Nov 15 10:29:56 2022 +0000
+++ b/sys/sys/mbuf.h    Tue Nov 15 10:47:39 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mbuf.h,v 1.235 2022/11/15 09:13:43 roy Exp $   */
+/*     $NetBSD: mbuf.h,v 1.236 2022/11/15 10:47:39 roy Exp $   */
 
 /*
  * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc.
@@ -800,6 +800,7 @@
                                            */
 #define PACKET_TAG_MPLS                        29 /* Indicate it's for MPLS */
 #define PACKET_TAG_SRCROUTE            30 /* IPv4 source routing */
+#define PACKET_TAG_ETHERNET_SRC                31 /* Ethernet source address */
 
 /*
  * Return the number of bytes in the mbuf chain, m.



Home | Main Index | Thread Index | Old Index