Tue Nov 15 10:47:39 2022 UTC ()
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> for the re-implementation.


(roy)
diff -r1.322 -r1.323 src/sys/net/if_ethersubr.c
diff -r1.310 -r1.311 src/sys/netinet/if_arp.c
diff -r1.235 -r1.236 src/sys/sys/mbuf.h

cvs diff -r1.322 -r1.323 src/sys/net/if_ethersubr.c (expand / switch to unified diff)

--- src/sys/net/if_ethersubr.c 2022/11/15 09:14:28 1.322
+++ src/sys/net/if_ethersubr.c 2022/11/15 10:47:39 1.323
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_ethersubr.c,v 1.322 2022/11/15 09:14:28 roy Exp $ */ 1/* $NetBSD: if_ethersubr.c,v 1.323 2022/11/15 10:47:39 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -51,27 +51,27 @@ @@ -51,27 +51,27 @@
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96 60 * @(#)if_ethersubr.c 8.2 (Berkeley) 4/4/96
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.322 2022/11/15 09:14:28 roy Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.323 2022/11/15 10:47:39 roy Exp $");
65 65
66#ifdef _KERNEL_OPT 66#ifdef _KERNEL_OPT
67#include "opt_inet.h" 67#include "opt_inet.h"
68#include "opt_atalk.h" 68#include "opt_atalk.h"
69#include "opt_mbuftrace.h" 69#include "opt_mbuftrace.h"
70#include "opt_mpls.h" 70#include "opt_mpls.h"
71#include "opt_gateway.h" 71#include "opt_gateway.h"
72#include "opt_pppoe.h" 72#include "opt_pppoe.h"
73#include "opt_net_mpsafe.h" 73#include "opt_net_mpsafe.h"
74#endif 74#endif
75 75
76#include "vlan.h" 76#include "vlan.h"
77#include "pppoe.h" 77#include "pppoe.h"
@@ -876,26 +876,39 @@ ether_input(struct ifnet *ifp, struct mb @@ -876,26 +876,39 @@ ether_input(struct ifnet *ifp, struct mb
876 876
877 /* etype represents the size of the payload in this case */ 877 /* etype represents the size of the payload in this case */
878 if (etype <= ETHERMTU + sizeof(struct ether_header)) { 878 if (etype <= ETHERMTU + sizeof(struct ether_header)) {
879 KASSERT(ehlen == sizeof(*eh)); 879 KASSERT(ehlen == sizeof(*eh));
880#if defined (LLC) || defined (NETATALK) 880#if defined (LLC) || defined (NETATALK)
881 ether_input_llc(ifp, m, eh); 881 ether_input_llc(ifp, m, eh);
882 return; 882 return;
883#else 883#else
884 /* ethertype of 0-1500 is regarded as noproto */ 884 /* ethertype of 0-1500 is regarded as noproto */
885 goto noproto; 885 goto noproto;
886#endif 886#endif
887 } 887 }
888 888
 889 /* For ARP packets, store the source address so that
 890 * ARP DAD probes can be validated. */
 891 if (etype == ETHERTYPE_ARP) {
 892 struct m_tag *mtag;
 893
 894 mtag = m_tag_get(PACKET_TAG_ETHERNET_SRC, ETHER_ADDR_LEN,
 895 M_NOWAIT);
 896 if (mtag != NULL) {
 897 memcpy(mtag + 1, &eh->ether_shost, ETHER_ADDR_LEN);
 898 m_tag_prepend(m, mtag);
 899 }
 900 }
 901
889 /* Strip off the Ethernet header. */ 902 /* Strip off the Ethernet header. */
890 m_adj(m, ehlen); 903 m_adj(m, ehlen);
891 904
892 switch (etype) { 905 switch (etype) {
893#ifdef INET 906#ifdef INET
894 case ETHERTYPE_IP: 907 case ETHERTYPE_IP:
895#ifdef GATEWAY 908#ifdef GATEWAY
896 if (ipflow_fastforward(m)) 909 if (ipflow_fastforward(m))
897 return; 910 return;
898#endif 911#endif
899 pktq = ip_pktq; 912 pktq = ip_pktq;
900 rps_hash = atomic_load_relaxed(&ether_pktq_rps_hash_p); 913 rps_hash = atomic_load_relaxed(&ether_pktq_rps_hash_p);
901 break; 914 break;

cvs diff -r1.310 -r1.311 src/sys/netinet/if_arp.c (expand / switch to unified diff)

--- src/sys/netinet/if_arp.c 2022/11/15 09:15:43 1.310
+++ src/sys/netinet/if_arp.c 2022/11/15 10:47:39 1.311
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_arp.c,v 1.310 2022/11/15 09:15:43 roy Exp $ */ 1/* $NetBSD: if_arp.c,v 1.311 2022/11/15 10:47:39 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Public Access Networks Corporation ("Panix"). It was developed under 8 * by Public Access Networks Corporation ("Panix"). It was developed under
9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. 9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -58,27 +58,27 @@ @@ -58,27 +58,27 @@
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE. 59 * SUCH DAMAGE.
60 * 60 *
61 * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 61 * @(#)if_ether.c 8.2 (Berkeley) 9/26/94
62 */ 62 */
63 63
64/* 64/*
65 * Ethernet address resolution protocol. 65 * Ethernet address resolution protocol.
66 * TODO: 66 * TODO:
67 * add "inuse/lock" bit (or ref. count) along with valid bit 67 * add "inuse/lock" bit (or ref. count) along with valid bit
68 */ 68 */
69 69
70#include <sys/cdefs.h> 70#include <sys/cdefs.h>
71__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.310 2022/11/15 09:15:43 roy Exp $"); 71__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.311 2022/11/15 10:47:39 roy Exp $");
72 72
73#ifdef _KERNEL_OPT 73#ifdef _KERNEL_OPT
74#include "opt_ddb.h" 74#include "opt_ddb.h"
75#include "opt_inet.h" 75#include "opt_inet.h"
76#include "opt_net_mpsafe.h" 76#include "opt_net_mpsafe.h"
77#endif 77#endif
78 78
79#ifdef INET 79#ifdef INET
80 80
81#include "arp.h" 81#include "arp.h"
82#include "bridge.h" 82#include "bridge.h"
83 83
84#include <sys/param.h> 84#include <sys/param.h>
@@ -922,46 +922,54 @@ again: @@ -922,46 +922,54 @@ again:
922 /* 922 /*
923 * If the source IP address is zero, this is an RFC 5227 ARP probe 923 * If the source IP address is zero, this is an RFC 5227 ARP probe
924 */ 924 */
925 if (in_nullhost(isaddr)) 925 if (in_nullhost(isaddr))
926 ARP_STATINC(ARP_STAT_RCVZEROSPA); 926 ARP_STATINC(ARP_STAT_RCVZEROSPA);
927 else if (in_hosteq(isaddr, myaddr)) 927 else if (in_hosteq(isaddr, myaddr))
928 ARP_STATINC(ARP_STAT_RCVLOCALSPA); 928 ARP_STATINC(ARP_STAT_RCVLOCALSPA);
929 929
930 if (in_nullhost(itaddr)) 930 if (in_nullhost(itaddr))
931 ARP_STATINC(ARP_STAT_RCVZEROTPA); 931 ARP_STATINC(ARP_STAT_RCVZEROTPA);
932 932
933 /* 933 /*
934 * DAD check, RFC 5227. 934 * DAD check, RFC 5227.
 935 * ARP sender hardware address must match the interface
 936 * address of the interface sending the packet.
935 * Collision on sender address is always a duplicate. 937 * Collision on sender address is always a duplicate.
936 * Collision on target address is only a duplicate 938 * Collision on target address is only a duplicate
937 * IF the sender address is the null host (ie a DAD probe) 939 * IF the sender address is the null host (ie a DAD probe)
938 * AND the message was broadcast 940 * AND the message was broadcast
939 * AND our address is either tentative or duplicated 941 * AND our address is either tentative or duplicated
940 * If it was unicast then it's a valid Unicast Poll from RFC 1122. 942 * If it was unicast then it's a valid Unicast Poll from RFC 1122.
941 */ 943 */
942 if (do_dad && 944 if (do_dad &&
943 (in_hosteq(isaddr, myaddr) || 945 (in_hosteq(isaddr, myaddr) ||
944 (in_nullhost(isaddr) && in_hosteq(itaddr, myaddr) && 946 (in_nullhost(isaddr) && in_hosteq(itaddr, myaddr) &&
945 m->m_flags & M_BCAST && 947 m->m_flags & M_BCAST &&
946 ia->ia4_flags & (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED)))) 948 ia->ia4_flags & (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED))))
947 { 949 {
948 struct sockaddr_dl sdl, *sdlp; 950 struct m_tag *mtag;
949 951
950 sdlp = sockaddr_dl_init(&sdl, sizeof(sdl), 952 mtag = m_tag_find(m, PACKET_TAG_ETHERNET_SRC);
951 ifp->if_index, ifp->if_type, 953 if (mtag == NULL || (ah->ar_hln == ETHER_ADDR_LEN &&
952 NULL, 0, ar_sha(ah), ah->ar_hln); 954 memcmp(mtag + 1, ar_sha(ah), ah->ar_hln) == 0)) {
953 arp_dad_duplicated((struct ifaddr *)ia, sdlp); 955 struct sockaddr_dl sdl, *sdlp;
954 goto out; 956
 957 sdlp = sockaddr_dl_init(&sdl, sizeof(sdl),
 958 ifp->if_index, ifp->if_type,
 959 NULL, 0, ar_sha(ah), ah->ar_hln);
 960 arp_dad_duplicated((struct ifaddr *)ia, sdlp);
 961 goto out;
 962 }
955 } 963 }
956 964
957 /* 965 /*
958 * If the target IP address is zero, ignore the packet. 966 * If the target IP address is zero, ignore the packet.
959 * This prevents the code below from trying to answer 967 * This prevents the code below from trying to answer
960 * when we are using IP address zero (booting). 968 * when we are using IP address zero (booting).
961 */ 969 */
962 if (in_nullhost(itaddr)) 970 if (in_nullhost(itaddr))
963 goto out; 971 goto out;
964 972
965 if (in_nullhost(isaddr)) 973 if (in_nullhost(isaddr))
966 goto reply; 974 goto reply;
967 975

cvs diff -r1.235 -r1.236 src/sys/sys/mbuf.h (expand / switch to unified diff)

--- src/sys/sys/mbuf.h 2022/11/15 09:13:43 1.235
+++ src/sys/sys/mbuf.h 2022/11/15 10:47:39 1.236
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: mbuf.h,v 1.235 2022/11/15 09:13:43 roy Exp $ */ 1/* $NetBSD: mbuf.h,v 1.236 2022/11/15 10:47:39 roy Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc. 4 * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and Matt Thomas of 3am Software Foundry. 9 * NASA Ames Research Center and Matt Thomas of 3am Software Foundry.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -790,26 +790,27 @@ int m_tag_copy_chain(struct mbuf *, stru @@ -790,26 +790,27 @@ int m_tag_copy_chain(struct mbuf *, stru
790#define PACKET_TAG_SO 4 /* sending socket pointer */ 790#define PACKET_TAG_SO 4 /* sending socket pointer */
791#define PACKET_TAG_NPF 10 /* packet filter */ 791#define PACKET_TAG_NPF 10 /* packet filter */
792#define PACKET_TAG_PF 11 /* packet filter */ 792#define PACKET_TAG_PF 11 /* packet filter */
793#define PACKET_TAG_ALTQ_QID 12 /* ALTQ queue id */ 793#define PACKET_TAG_ALTQ_QID 12 /* ALTQ queue id */
794#define PACKET_TAG_IPSEC_OUT_DONE 18 794#define PACKET_TAG_IPSEC_OUT_DONE 18
795#define PACKET_TAG_IPSEC_NAT_T_PORTS 25 /* two uint16_t */ 795#define PACKET_TAG_IPSEC_NAT_T_PORTS 25 /* two uint16_t */
796#define PACKET_TAG_INET6 26 /* IPv6 info */ 796#define PACKET_TAG_INET6 26 /* IPv6 info */
797#define PACKET_TAG_TUNNEL_INFO 28 /* tunnel identification and 797#define PACKET_TAG_TUNNEL_INFO 28 /* tunnel identification and
798 * protocol callback, for loop 798 * protocol callback, for loop
799 * detection/recovery 799 * detection/recovery
800 */ 800 */
801#define PACKET_TAG_MPLS 29 /* Indicate it's for MPLS */ 801#define PACKET_TAG_MPLS 29 /* Indicate it's for MPLS */
802#define PACKET_TAG_SRCROUTE 30 /* IPv4 source routing */ 802#define PACKET_TAG_SRCROUTE 30 /* IPv4 source routing */
 803#define PACKET_TAG_ETHERNET_SRC 31 /* Ethernet source address */
803 804
804/* 805/*
805 * Return the number of bytes in the mbuf chain, m. 806 * Return the number of bytes in the mbuf chain, m.
806 */ 807 */
807static __inline u_int 808static __inline u_int
808m_length(const struct mbuf *m) 809m_length(const struct mbuf *m)
809{ 810{
810 const struct mbuf *m0; 811 const struct mbuf *m0;
811 u_int pktlen; 812 u_int pktlen;
812 813
813 if ((m->m_flags & M_PKTHDR) != 0) 814 if ((m->m_flags & M_PKTHDR) != 0)
814 return m->m_pkthdr.len; 815 return m->m_pkthdr.len;
815 816