| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_arp.c,v 1.229 2016/10/11 12:32:30 roy Exp $ */ | | 1 | /* $NetBSD: if_arp.c,v 1.230 2016/10/11 13:59:30 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.229 2016/10/11 12:32:30 roy Exp $"); | | 71 | __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.230 2016/10/11 13:59:30 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 | #endif | | 76 | #endif |
77 | | | 77 | |
78 | #ifdef INET | | 78 | #ifdef INET |
79 | | | 79 | |
80 | #include "arp.h" | | 80 | #include "arp.h" |
81 | #include "bridge.h" | | 81 | #include "bridge.h" |
82 | | | 82 | |
83 | #include <sys/param.h> | | 83 | #include <sys/param.h> |
84 | #include <sys/systm.h> | | 84 | #include <sys/systm.h> |
| @@ -168,27 +168,27 @@ static void arp_settimer(struct llentry | | | @@ -168,27 +168,27 @@ static void arp_settimer(struct llentry |
168 | static struct llentry *arplookup(struct ifnet *, struct mbuf *, | | 168 | static struct llentry *arplookup(struct ifnet *, struct mbuf *, |
169 | const struct in_addr *, const struct sockaddr *, int); | | 169 | const struct in_addr *, const struct sockaddr *, int); |
170 | static struct llentry *arpcreate(struct ifnet *, struct mbuf *, | | 170 | static struct llentry *arpcreate(struct ifnet *, struct mbuf *, |
171 | const struct in_addr *, const struct sockaddr *, int); | | 171 | const struct in_addr *, const struct sockaddr *, int); |
172 | static void in_arpinput(struct mbuf *); | | 172 | static void in_arpinput(struct mbuf *); |
173 | static void in_revarpinput(struct mbuf *); | | 173 | static void in_revarpinput(struct mbuf *); |
174 | static void revarprequest(struct ifnet *); | | 174 | static void revarprequest(struct ifnet *); |
175 | | | 175 | |
176 | static void arp_drainstub(void); | | 176 | static void arp_drainstub(void); |
177 | | | 177 | |
178 | static void arp_dad_timer(struct ifaddr *); | | 178 | static void arp_dad_timer(struct ifaddr *); |
179 | static void arp_dad_start(struct ifaddr *); | | 179 | static void arp_dad_start(struct ifaddr *); |
180 | static void arp_dad_stop(struct ifaddr *); | | 180 | static void arp_dad_stop(struct ifaddr *); |
181 | static void arp_dad_duplicated(struct ifaddr *); | | 181 | static void arp_dad_duplicated(struct ifaddr *, const char *); |
182 | | | 182 | |
183 | static void arp_init_llentry(struct ifnet *, struct llentry *); | | 183 | static void arp_init_llentry(struct ifnet *, struct llentry *); |
184 | #if NTOKEN > 0 | | 184 | #if NTOKEN > 0 |
185 | static void arp_free_llentry_tokenring(struct llentry *); | | 185 | static void arp_free_llentry_tokenring(struct llentry *); |
186 | #endif | | 186 | #endif |
187 | | | 187 | |
188 | struct ifqueue arpintrq = { | | 188 | struct ifqueue arpintrq = { |
189 | .ifq_head = NULL, | | 189 | .ifq_head = NULL, |
190 | .ifq_tail = NULL, | | 190 | .ifq_tail = NULL, |
191 | .ifq_len = 0, | | 191 | .ifq_len = 0, |
192 | .ifq_maxlen = 50, | | 192 | .ifq_maxlen = 50, |
193 | .ifq_drops = 0, | | 193 | .ifq_drops = 0, |
194 | }; | | 194 | }; |
| @@ -1123,57 +1123,46 @@ in_arpinput(struct mbuf *m) | | | @@ -1123,57 +1123,46 @@ in_arpinput(struct mbuf *m) |
1123 | } | | 1123 | } |
1124 | | | 1124 | |
1125 | /* | | 1125 | /* |
1126 | * If the source IP address is zero, this is an RFC 5227 ARP probe | | 1126 | * If the source IP address is zero, this is an RFC 5227 ARP probe |
1127 | */ | | 1127 | */ |
1128 | if (in_nullhost(isaddr)) | | 1128 | if (in_nullhost(isaddr)) |
1129 | ARP_STATINC(ARP_STAT_RCVZEROSPA); | | 1129 | ARP_STATINC(ARP_STAT_RCVZEROSPA); |
1130 | else if (in_hosteq(isaddr, myaddr)) | | 1130 | else if (in_hosteq(isaddr, myaddr)) |
1131 | ARP_STATINC(ARP_STAT_RCVLOCALSPA); | | 1131 | ARP_STATINC(ARP_STAT_RCVLOCALSPA); |
1132 | | | 1132 | |
1133 | if (in_nullhost(itaddr)) | | 1133 | if (in_nullhost(itaddr)) |
1134 | ARP_STATINC(ARP_STAT_RCVZEROTPA); | | 1134 | ARP_STATINC(ARP_STAT_RCVZEROTPA); |
1135 | | | 1135 | |
1136 | /* DAD check, RFC 5227 2.1.1, Probe Details */ | | 1136 | /* DAD check, RFC 5227 */ |
1137 | if (in_hosteq(isaddr, myaddr) || | | 1137 | if (in_hosteq(isaddr, myaddr) || |
1138 | (in_nullhost(isaddr) && in_hosteq(itaddr, myaddr))) | | 1138 | (in_nullhost(isaddr) && in_hosteq(itaddr, myaddr))) |
1139 | { | | 1139 | { |
1140 | /* If our address is tentative, mark it as duplicated */ | | 1140 | arp_dad_duplicated((struct ifaddr *)ia, |
1141 | if (ia->ia4_flags & IN_IFF_TENTATIVE) | | 1141 | lla_snprintf(ar_sha(ah), ah->ar_hln)); |
1142 | arp_dad_duplicated((struct ifaddr *)ia); | | 1142 | goto out; |
1143 | /* If our address is unuseable, don't reply */ | | | |
1144 | if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) | | | |
1145 | goto out; | | | |
1146 | } | | 1143 | } |
1147 | | | 1144 | |
1148 | /* | | 1145 | /* |
1149 | * If the target IP address is zero, ignore the packet. | | 1146 | * If the target IP address is zero, ignore the packet. |
1150 | * This prevents the code below from tring to answer | | 1147 | * This prevents the code below from tring to answer |
1151 | * when we are using IP address zero (booting). | | 1148 | * when we are using IP address zero (booting). |
1152 | */ | | 1149 | */ |
1153 | if (in_nullhost(itaddr)) | | 1150 | if (in_nullhost(itaddr)) |
1154 | goto out; | | 1151 | goto out; |
1155 | | | 1152 | |
1156 | if (in_nullhost(isaddr)) | | 1153 | if (in_nullhost(isaddr)) |
1157 | goto reply; | | 1154 | goto reply; |
1158 | | | 1155 | |
1159 | if (in_hosteq(isaddr, myaddr)) { | | | |
1160 | log(LOG_ERR, | | | |
1161 | "duplicate IP address %s sent from link address %s\n", | | | |
1162 | in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln)); | | | |
1163 | itaddr = myaddr; | | | |
1164 | goto reply; | | | |
1165 | } | | | |
1166 | | | | |
1167 | if (in_hosteq(itaddr, myaddr)) | | 1156 | if (in_hosteq(itaddr, myaddr)) |
1168 | la = arpcreate(ifp, m, &isaddr, NULL, 1); | | 1157 | la = arpcreate(ifp, m, &isaddr, NULL, 1); |
1169 | else | | 1158 | else |
1170 | la = arplookup(ifp, m, &isaddr, NULL, 1); | | 1159 | la = arplookup(ifp, m, &isaddr, NULL, 1); |
1171 | if (la == NULL) | | 1160 | if (la == NULL) |
1172 | goto reply; | | 1161 | goto reply; |
1173 | | | 1162 | |
1174 | if ((la->la_flags & LLE_VALID) && | | 1163 | if ((la->la_flags & LLE_VALID) && |
1175 | memcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { | | 1164 | memcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { |
1176 | if (la->la_flags & LLE_STATIC) { | | 1165 | if (la->la_flags & LLE_STATIC) { |
1177 | ARP_STATINC(ARP_STAT_RCVOVERPERM); | | 1166 | ARP_STATINC(ARP_STAT_RCVOVERPERM); |
1178 | if (!log_permanent_modify) | | 1167 | if (!log_permanent_modify) |
1179 | goto out; | | 1168 | goto out; |
| @@ -1764,61 +1753,65 @@ announce: | | | @@ -1764,61 +1753,65 @@ announce: |
1764 | | | 1753 | |
1765 | TAILQ_REMOVE(&dadq, dp, dad_list); | | 1754 | TAILQ_REMOVE(&dadq, dp, dad_list); |
1766 | free(dp, M_IPARP); | | 1755 | free(dp, M_IPARP); |
1767 | dp = NULL; | | 1756 | dp = NULL; |
1768 | ifafree(ifa); | | 1757 | ifafree(ifa); |
1769 | | | 1758 | |
1770 | done: | | 1759 | done: |
1771 | mutex_exit(&arp_dad_lock); | | 1760 | mutex_exit(&arp_dad_lock); |
1772 | KERNEL_UNLOCK_ONE(NULL); | | 1761 | KERNEL_UNLOCK_ONE(NULL); |
1773 | mutex_exit(softnet_lock); | | 1762 | mutex_exit(softnet_lock); |
1774 | } | | 1763 | } |
1775 | | | 1764 | |
1776 | static void | | 1765 | static void |
1777 | arp_dad_duplicated(struct ifaddr *ifa) | | 1766 | arp_dad_duplicated(struct ifaddr *ifa, const char *sha) |
1778 | { | | 1767 | { |
1779 | struct in_ifaddr *ia = (struct in_ifaddr *)ifa; | | 1768 | struct in_ifaddr *ia = (struct in_ifaddr *)ifa; |
1780 | struct ifnet *ifp; | | 1769 | struct ifnet *ifp = ifa->ifa_ifp; |
1781 | struct dadq *dp; | | 1770 | const char *iastr = in_fmtaddr(ia->ia_addr.sin_addr); |
1782 | | | 1771 | |
1783 | mutex_enter(&arp_dad_lock); | | 1772 | if (ia->ia4_flags & (IN_IFF_TENTATIVE|IN_IFF_DUPLICATED)) { |
1784 | dp = arp_dad_find(ifa); | | 1773 | log(LOG_ERR, |
1785 | if (dp == NULL) { | | 1774 | "%s: DAD duplicate address %s from %s\n", |
1786 | mutex_exit(&arp_dad_lock); | | 1775 | if_name(ifp), iastr, sha); |
1787 | /* DAD seems to be stopping, so do nothing. */ | | 1776 | } else if (ia->ia_dad_defended == 0 || |
| | | 1777 | ia->ia_dad_defended < time_uptime - DEFEND_INTERVAL) { |
| | | 1778 | ia->ia_dad_defended = time_uptime; |
| | | 1779 | arpannounce1(ifa); |
| | | 1780 | log(LOG_ERR, |
| | | 1781 | "%s: DAD defended address %s from %s\n", |
| | | 1782 | if_name(ifp), iastr, sha); |
1788 | return; | | 1783 | return; |
| | | 1784 | } else { |
| | | 1785 | /* If DAD is disabled, just report the duplicate. */ |
| | | 1786 | if (ip_dad_count == 0) { |
| | | 1787 | log(LOG_ERR, |
| | | 1788 | "%s: DAD ignoring duplicate address %s from %s\n", |
| | | 1789 | if_name(ifp), iastr, sha); |
| | | 1790 | return; |
| | | 1791 | } |
| | | 1792 | log(LOG_ERR, |
| | | 1793 | "%s: DAD defence failed for %s from %s\n", |
| | | 1794 | if_name(ifp), iastr, sha); |
1789 | } | | 1795 | } |
1790 | | | 1796 | |
1791 | ifp = ifa->ifa_ifp; | | 1797 | arp_dad_stop(ifa); |
1792 | log(LOG_ERR, | | | |
1793 | "%s: DAD detected duplicate IPv4 address %s: ARP out=%d\n", | | | |
1794 | if_name(ifp), in_fmtaddr(ia->ia_addr.sin_addr), | | | |
1795 | dp->dad_arp_ocount); | | | |
1796 | | | 1798 | |
1797 | ia->ia4_flags &= ~IN_IFF_TENTATIVE; | | 1799 | ia->ia4_flags &= ~IN_IFF_TENTATIVE; |
1798 | ia->ia4_flags |= IN_IFF_DUPLICATED; | | 1800 | if ((ia->ia4_flags & IN_IFF_DUPLICATED) == 0) { |
1799 | | | 1801 | ia->ia4_flags |= IN_IFF_DUPLICATED; |
1800 | /* We are done with DAD, with duplicated address found. (failure) */ | | 1802 | /* Inform the routing socket of the duplicate address */ |
1801 | arp_dad_stoptimer(dp); | | 1803 | rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); |
1802 | | | 1804 | } |
1803 | /* Inform the routing socket that DAD has completed */ | | | |
1804 | rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); | | | |
1805 | | | | |
1806 | TAILQ_REMOVE(&dadq, dp, dad_list); | | | |
1807 | mutex_exit(&arp_dad_lock); | | | |
1808 | | | | |
1809 | free(dp, M_IPARP); | | | |
1810 | dp = NULL; | | | |
1811 | ifafree(ifa); | | | |
1812 | } | | 1805 | } |
1813 | | | 1806 | |
1814 | /* | | 1807 | /* |
1815 | * Called from 10 Mb/s Ethernet interrupt handlers | | 1808 | * Called from 10 Mb/s Ethernet interrupt handlers |
1816 | * when ether packet type ETHERTYPE_REVARP | | 1809 | * when ether packet type ETHERTYPE_REVARP |
1817 | * is received. Common length and type checks are done here, | | 1810 | * is received. Common length and type checks are done here, |
1818 | * then the protocol-specific routine is called. | | 1811 | * then the protocol-specific routine is called. |
1819 | */ | | 1812 | */ |
1820 | void | | 1813 | void |
1821 | revarpinput(struct mbuf *m) | | 1814 | revarpinput(struct mbuf *m) |
1822 | { | | 1815 | { |
1823 | struct arphdr *ar; | | 1816 | struct arphdr *ar; |
1824 | | | 1817 | |