Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add IPv4 address flags IN_IFF_TENTATIVE, IN_IFF_DUPLICAT...
details: https://anonhg.NetBSD.org/src/rev/f40cac8e8ae3
branches: trunk
changeset: 337878:f40cac8e8ae3
user: roy <roy%NetBSD.org@localhost>
date: Sat May 02 14:41:32 2015 +0000
description:
Add IPv4 address flags IN_IFF_TENTATIVE, IN_IFF_DUPLICATED and
IN_IFF_DETATCHED to mimic the IPv6 address behaviour.
Add SIOCGIFAFLAG_IN ioctl to retrieve the address flag via the
ifreq structure.
Add IPv4 DAD detection via the ARP methods described in RFC 5227.
Add sysctls net.inet.ip.dad_count and net.inet.arp.debug.
Discussed on tech-net@
diffstat:
sys/net/if.h | 4 +-
sys/net/if_spppsubr.c | 19 +-
sys/netinet/if_arp.c | 395 +++++++++++++++++++++++++++++++++++++++++++++--
sys/netinet/if_inarp.h | 21 ++-
sys/netinet/in.c | 163 +++++++++++++++++--
sys/netinet/in.h | 12 +-
sys/netinet/in_pcb.c | 6 +-
sys/netinet/in_proto.c | 7 +-
sys/netinet/in_selsrc.c | 15 +-
sys/netinet/in_var.h | 15 +-
sys/netinet/ip_icmp.c | 10 +-
sys/netinet/ip_input.c | 18 +-
sys/netinet/raw_ip.c | 17 +-
sys/sys/sockio.h | 3 +-
14 files changed, 637 insertions(+), 68 deletions(-)
diffs (truncated from 1292 to 300 lines):
diff -r 651070b5cda0 -r f40cac8e8ae3 sys/net/if.h
--- a/sys/net/if.h Sat May 02 14:30:27 2015 +0000
+++ b/sys/net/if.h Sat May 02 14:41:32 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if.h,v 1.188 2015/04/20 10:19:54 roy Exp $ */
+/* $NetBSD: if.h,v 1.189 2015/05/02 14:41:32 roy Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -594,6 +594,7 @@
struct sockaddr ifru_broadaddr;
struct sockaddr_storage ifru_space;
short ifru_flags;
+ int ifru_addrflags;
int ifru_metric;
int ifru_mtu;
int ifru_dlt;
@@ -609,6 +610,7 @@
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_space ifr_ifru.ifru_space /* sockaddr_storage */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_addrflags ifr_ifru.ifru_addrflags /* addr flags */
#define ifr_metric ifr_ifru.ifru_metric /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define ifr_dlt ifr_ifru.ifru_dlt /* data link type (DLT_*) */
diff -r 651070b5cda0 -r f40cac8e8ae3 sys/net/if_spppsubr.c
--- a/sys/net/if_spppsubr.c Sat May 02 14:30:27 2015 +0000
+++ b/sys/net/if_spppsubr.c Sat May 02 14:41:32 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_spppsubr.c,v 1.132 2015/04/20 10:19:54 roy Exp $ */
+/* $NetBSD: if_spppsubr.c,v 1.133 2015/05/02 14:41:32 roy Exp $ */
/*
* Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.132 2015/04/20 10:19:54 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.133 2015/05/02 14:41:32 roy Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@@ -4875,7 +4875,7 @@
found:
{
- int error;
+ int error, hostIsNew;
struct sockaddr_in new_sin = *si;
struct sockaddr_in new_dst = *dest;
@@ -4886,8 +4886,13 @@
*/
in_ifscrub(ifp, ifatoia(ifa));
- if (myaddr != 0)
- new_sin.sin_addr.s_addr = htonl(myaddr);
+ hostIsNew = 0;
+ if (myaddr != 0) {
+ if (new_sin.sin_addr.s_addr != htonl(myaddr)) {
+ new_sin.sin_addr.s_addr = htonl(myaddr);
+ hostIsNew = 1;
+ }
+ }
if (hisaddr != 0) {
new_dst.sin_addr.s_addr = htonl(hisaddr);
if (new_dst.sin_addr.s_addr != dest->sin_addr.s_addr) {
@@ -4895,7 +4900,7 @@
*dest = new_dst; /* fix dstaddr in place */
}
}
- error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 0);
+ error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 0, hostIsNew);
if (debug && error)
{
log(LOG_DEBUG, "%s: sppp_set_ip_addrs: in_ifinit "
@@ -4948,7 +4953,7 @@
if (sp->ipcp.flags & IPCP_HISADDR_DYN)
/* replace peer addr in place */
dest->sin_addr.s_addr = sp->ipcp.saved_hisaddr;
- in_ifinit(ifp, ifatoia(ifa), &new_sin, 0);
+ in_ifinit(ifp, ifatoia(ifa), &new_sin, 0, 0);
(void)pfil_run_hooks(if_pfil,
(struct mbuf **)SIOCDIFADDR, ifp, PFIL_IFADDR);
}
diff -r 651070b5cda0 -r f40cac8e8ae3 sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c Sat May 02 14:30:27 2015 +0000
+++ b/sys/netinet/if_arp.c Sat May 02 14:41:32 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_arp.c,v 1.162 2015/03/23 18:33:17 roy Exp $ */
+/* $NetBSD: if_arp.c,v 1.163 2015/05/02 14:41:32 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.162 2015/03/23 18:33:17 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.163 2015/05/02 14:41:32 roy Exp $");
#include "opt_ddb.h"
#include "opt_inet.h"
@@ -95,6 +95,7 @@
#include <sys/sysctl.h>
#include <sys/socketvar.h>
#include <sys/percpu.h>
+#include <sys/cprng.h>
#include <net/ethertypes.h>
#include <net/if.h>
@@ -102,6 +103,7 @@
#include <net/if_token.h>
#include <net/if_types.h>
#include <net/if_ether.h>
+#include <net/net_osdep.h>
#include <net/route.h>
#include <net/net_stats.h>
@@ -142,6 +144,14 @@
#define rt_expire rt_rmx.rmx_expire
#define rt_pksent rt_rmx.rmx_pksent
+int ip_dad_count = PROBE_NUM;
+#ifdef ARP_DEBUG
+static int arp_debug = 1;
+#else
+static int arp_debug = 0;
+#endif
+#define arplog(x) do { if (arp_debug) log x; } while (/*CONSTCOND*/ 0)
+
static struct sockaddr *arp_setgate(struct rtentry *, struct sockaddr *,
const struct sockaddr *);
static void arptfree(struct llinfo_arp *);
@@ -153,6 +163,9 @@
static void in_arpinput(struct mbuf *);
static void arp_drainstub(void);
+static void arp_dad_timer(struct ifaddr *);
+static void arp_dad_duplicated(struct ifaddr *);
+
LIST_HEAD(llinfo_arpq, llinfo_arp) llinfo_arp;
struct ifqueue arpintrq = {
.ifq_head = NULL,
@@ -511,6 +524,14 @@
in = &ifatoia(ifa)->ia_addr.sin_addr;
+ if (ifatoia(ifa)->ia4_flags &
+ (IN_IFF_NOTREADY | IN_IFF_DETACHED))
+ {
+ arplog((LOG_DEBUG, "arp_request: %s not ready\n",
+ in_fmtaddr(*in)));
+ return;
+ }
+
arprequest(ifa->ifa_ifp, in, in,
CLLADDR(ifa->ifa_ifp->if_sadl));
return;
@@ -601,10 +622,17 @@
}
/* Announce a new entry if requested. */
if (rt->rt_flags & RTF_ANNOUNCE) {
- arprequest(ifp,
- &satocsin(rt_getkey(rt))->sin_addr,
- &satocsin(rt_getkey(rt))->sin_addr,
- CLLADDR(satocsdl(gate)));
+ INADDR_TO_IA(satocsin(rt_getkey(rt))->sin_addr, ia);
+ while (ia && ia->ia_ifp != ifp)
+ NEXT_IA_WITH_SAME_ADDR(ia);
+ if (ia == NULL ||
+ ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED))
+ ;
+ else
+ arprequest(ifp,
+ &satocsin(rt_getkey(rt))->sin_addr,
+ &satocsin(rt_getkey(rt))->sin_addr,
+ CLLADDR(satocsdl(gate)));
}
/*FALLTHROUGH*/
case RTM_RESOLVE:
@@ -999,16 +1027,6 @@
if (m->m_flags & (M_BCAST|M_MCAST))
ARP_STATINC(ARP_STAT_RCVMCAST);
- /*
- * If the target IP address is zero, ignore the packet.
- * This prevents the code below from tring to answer
- * when we are using IP address zero (booting).
- */
- if (in_nullhost(itaddr)) {
- ARP_STATINC(ARP_STAT_RCVZEROTPA);
- goto out;
- }
-
/*
* Search for a matching interface address
@@ -1089,13 +1107,38 @@
/*
* If the source IP address is zero, this is an RFC 5227 ARP probe
*/
- if (in_nullhost(isaddr)) {
+ if (in_nullhost(isaddr))
ARP_STATINC(ARP_STAT_RCVZEROSPA);
- goto reply;
+ else if (in_hosteq(isaddr, myaddr))
+ ARP_STATINC(ARP_STAT_RCVLOCALSPA);
+
+ if (in_nullhost(itaddr))
+ ARP_STATINC(ARP_STAT_RCVZEROTPA);
+
+ /* DAD check, RFC 5227 2.1.1, Probe Details */
+ if (in_hosteq(isaddr, myaddr) ||
+ (in_nullhost(isaddr) && in_hosteq(itaddr, myaddr)))
+ {
+ /* If our address is tentative, mark it as duplicated */
+ if (ia->ia4_flags & IN_IFF_TENTATIVE)
+ arp_dad_duplicated((struct ifaddr *)ia);
+ /* If our address is unuseable, don't reply */
+ if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED))
+ goto out;
}
+ /*
+ * If the target IP address is zero, ignore the packet.
+ * This prevents the code below from tring to answer
+ * when we are using IP address zero (booting).
+ */
+ if (in_nullhost(itaddr))
+ goto out;
+
+ if (in_nullhost(isaddr))
+ goto reply;
+
if (in_hosteq(isaddr, myaddr)) {
- ARP_STATINC(ARP_STAT_RCVLOCALSPA);
log(LOG_ERR,
"duplicate IP address %s sent from link address %s\n",
in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln));
@@ -1211,6 +1254,9 @@
}
ARP_STATINC(ARP_STAT_RCVREQUEST);
if (in_hosteq(itaddr, myaddr)) {
+ /* If our address is unuseable, don't reply */
+ if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED))
+ goto out;
/* I am the target */
tha = ar_tha(ah);
if (tha)
@@ -1358,19 +1404,321 @@
arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
{
struct in_addr *ip;
+ struct in_ifaddr *ia = (struct in_ifaddr *)ifa;
/*
* Warn the user if another station has this IP address,
* but only if the interface IP address is not zero.
*/
ip = &IA_SIN(ifa)->sin_addr;
- if (!in_nullhost(*ip))
+ if (!in_nullhost(*ip) &&
+ (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) == 0)
arprequest(ifp, ip, ip, CLLADDR(ifp->if_sadl));
ifa->ifa_rtrequest = arp_rtrequest;
ifa->ifa_flags |= RTF_CLONING;
}
+TAILQ_HEAD(dadq_head, dadq);
+struct dadq {
+ TAILQ_ENTRY(dadq) dad_list;
+ struct ifaddr *dad_ifa;
+ int dad_count; /* max ARP to send */
+ int dad_arp_tcount; /* # of trials to send ARP */
+ int dad_arp_ocount; /* ARP sent so far */
+ int dad_arp_announce; /* max ARP announcements */
+ int dad_arp_acount; /* # of announcements */
+ struct callout dad_timer_ch;
+};
+MALLOC_JUSTDEFINE(M_IPARP, "ARP DAD", "ARP DAD Structure");
+
+static struct dadq_head dadq;
+static int dad_init = 0;
+static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
+
+static struct dadq *
+arp_dad_find(struct ifaddr *ifa)
+{
+ struct dadq *dp;
+
+ TAILQ_FOREACH(dp, &dadq, dad_list) {
+ if (dp->dad_ifa == ifa)
+ return dp;
+ }
+ return NULL;
+}
+
Home |
Main Index |
Thread Index |
Old Index