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.diff -r1.322 -r1.323 src/sys/net/if_ethersubr.c
(roy)
--- 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(ðer_pktq_rps_hash_p); | 913 | rps_hash = atomic_load_relaxed(ðer_pktq_rps_hash_p); | |
901 | break; | 914 | break; |
--- 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 |
--- 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 | */ | |
807 | static __inline u_int | 808 | static __inline u_int | |
808 | m_length(const struct mbuf *m) | 809 | m_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 |