Separate ARP handling DAD from inet.
This is done by signalling the intent to try tentative addresses and then clearing the intent once the address is setup. When the ARP handler is installed (arp_ifinit) then it adds dad start and stop functions to the address which are used instead of calling ARP directly.
This commit is contained in:
parent
3333c4c041
commit
f45d868787
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_arp.c,v 1.164 2015/05/03 10:44:04 justin Exp $ */
|
||||
/* $NetBSD: if_arp.c,v 1.165 2015/05/16 12:12:46 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.164 2015/05/03 10:44:04 justin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.165 2015/05/16 12:12:46 roy Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_inet.h"
|
||||
|
@ -164,6 +164,8 @@ static void in_arpinput(struct mbuf *);
|
|||
static void arp_drainstub(void);
|
||||
|
||||
static void arp_dad_timer(struct ifaddr *);
|
||||
static void arp_dad_start(struct ifaddr *);
|
||||
static void arp_dad_stop(struct ifaddr *);
|
||||
static void arp_dad_duplicated(struct ifaddr *);
|
||||
|
||||
LIST_HEAD(llinfo_arpq, llinfo_arp) llinfo_arp;
|
||||
|
@ -1417,6 +1419,13 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
|
|||
|
||||
ifa->ifa_rtrequest = arp_rtrequest;
|
||||
ifa->ifa_flags |= RTF_CLONING;
|
||||
|
||||
/* ARP will handle DAD for this address. */
|
||||
if (ia->ia4_flags & IN_IFF_TRYTENTATIVE) {
|
||||
ia->ia4_flags |= IN_IFF_TENTATIVE;
|
||||
ia->ia_dad_start = arp_dad_start;
|
||||
ia->ia_dad_stop = arp_dad_stop;
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_HEAD(dadq_head, dadq);
|
||||
|
@ -1487,7 +1496,7 @@ arp_dad_output(struct dadq *dp, struct ifaddr *ifa)
|
|||
/*
|
||||
* Start Duplicate Address Detection (DAD) for specified interface address.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
arp_dad_start(struct ifaddr *ifa)
|
||||
{
|
||||
struct in_ifaddr *ia = (struct in_ifaddr *)ifa;
|
||||
|
@ -1559,7 +1568,7 @@ arp_dad_start(struct ifaddr *ifa)
|
|||
/*
|
||||
* terminate DAD unconditionally. used for address removals.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
arp_dad_stop(struct ifaddr *ifa)
|
||||
{
|
||||
struct dadq *dp;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_inarp.h,v 1.45 2015/05/02 14:41:32 roy Exp $ */
|
||||
/* $NetBSD: if_inarp.h,v 1.46 2015/05/16 12:12:46 roy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1993
|
||||
|
@ -85,9 +85,6 @@ void arp_drain(void);
|
|||
int arpioctl(u_long, void *);
|
||||
void arpwhohas(struct ifnet *, struct in_addr *);
|
||||
|
||||
void arp_dad_start(struct ifaddr *);
|
||||
void arp_dad_stop(struct ifaddr *);
|
||||
|
||||
void revarpinput(struct mbuf *);
|
||||
void in_revarpinput(struct mbuf *);
|
||||
void revarprequest(struct ifnet *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in.c,v 1.155 2015/05/05 08:52:51 roy Exp $ */
|
||||
/* $NetBSD: in.c,v 1.156 2015/05/16 12:12:46 roy Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -91,7 +91,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.155 2015/05/05 08:52:51 roy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.156 2015/05/16 12:12:46 roy Exp $");
|
||||
|
||||
#include "arp.h"
|
||||
#include "opt_inet.h"
|
||||
|
@ -664,10 +664,9 @@ in_purgeaddr(struct ifaddr *ifa)
|
|||
struct ifnet *ifp = ifa->ifa_ifp;
|
||||
struct in_ifaddr *ia = (void *) ifa;
|
||||
|
||||
#if NARP
|
||||
/* stop DAD processing */
|
||||
arp_dad_stop(ifa);
|
||||
#endif
|
||||
if (ia->ia_dad_stop != NULL)
|
||||
ia->ia_dad_stop(ifa);
|
||||
|
||||
in_ifscrub(ifp, ia);
|
||||
in_ifremlocal(ifa);
|
||||
|
@ -905,14 +904,13 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
|
|||
ia->ia_addr = *sin;
|
||||
LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
|
||||
|
||||
/* Set IN_IFF flags early for arp_ifinit() */
|
||||
/* Set IN_IFF flags early for if_addr_init() */
|
||||
if (hostIsNew && if_do_dad(ifp) && !in_nullhost(ia->ia_addr.sin_addr)) {
|
||||
if (ifp->if_link_state == LINK_STATE_DOWN)
|
||||
ia->ia4_flags |= IN_IFF_DETACHED;
|
||||
#if NARP
|
||||
else
|
||||
ia->ia4_flags |= IN_IFF_TENTATIVE;
|
||||
#endif
|
||||
/* State the intent to try DAD if possible */
|
||||
ia->ia4_flags |= IN_IFF_TRYTENTATIVE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -922,7 +920,10 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
|
|||
*/
|
||||
if ((error = if_addr_init(ifp, &ia->ia_ifa, true)) != 0)
|
||||
goto bad;
|
||||
/* Now clear the try tentative flag, it's job is done. */
|
||||
ia->ia4_flags &= ~IN_IFF_TRYTENTATIVE;
|
||||
splx(s);
|
||||
|
||||
if (scrub) {
|
||||
ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
|
||||
in_ifscrub(ifp, ia);
|
||||
|
@ -984,12 +985,10 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
|
|||
ia->ia_allhosts = in_addmulti(&addr, ifp);
|
||||
}
|
||||
|
||||
#if NARP
|
||||
if (hostIsNew && if_do_dad(ifp) &&
|
||||
!in_nullhost(ia->ia_addr.sin_addr) &&
|
||||
ia->ia4_flags & IN_IFF_TENTATIVE)
|
||||
arp_dad_start((struct ifaddr *)ia);
|
||||
#endif
|
||||
ia->ia_dad_start((struct ifaddr *)ia);
|
||||
|
||||
return (error);
|
||||
bad:
|
||||
|
@ -1179,22 +1178,17 @@ in_if_link_up(struct ifnet *ifp)
|
|||
/* If detached then mark as tentative */
|
||||
if (ia->ia4_flags & IN_IFF_DETACHED) {
|
||||
ia->ia4_flags &= ~IN_IFF_DETACHED;
|
||||
#if NARP
|
||||
if (if_do_dad(ifp))
|
||||
if (if_do_dad(ifp) && ia->ia_dad_start != NULL)
|
||||
ia->ia4_flags |= IN_IFF_TENTATIVE;
|
||||
else
|
||||
#endif
|
||||
if ((ia->ia4_flags & IN_IFF_TENTATIVE) == 0)
|
||||
else if ((ia->ia4_flags & IN_IFF_TENTATIVE) == 0)
|
||||
rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
|
||||
}
|
||||
|
||||
#if NARP
|
||||
if (ia->ia4_flags & IN_IFF_TENTATIVE) {
|
||||
/* Clear the duplicated flag as we're starting DAD. */
|
||||
ia->ia4_flags &= ~IN_IFF_DUPLICATED;
|
||||
arp_dad_start(ifa);
|
||||
ia->ia_dad_start(ifa);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1220,10 +1214,9 @@ in_if_link_down(struct ifnet *ifp)
|
|||
continue;
|
||||
ia = (struct in_ifaddr *)ifa;
|
||||
|
||||
#if NARP
|
||||
/* Stop DAD processing */
|
||||
arp_dad_stop(ifa);
|
||||
#endif
|
||||
if (ia->ia_dad_stop != NULL)
|
||||
ia->ia_dad_stop(ifa);
|
||||
|
||||
/*
|
||||
* Mark the address as detached.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in_var.h,v 1.71 2015/05/02 14:41:32 roy Exp $ */
|
||||
/* $NetBSD: in_var.h,v 1.72 2015/05/16 12:12:46 roy Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -69,9 +69,11 @@
|
|||
#define IN_IFF_TENTATIVE 0x01 /* tentative address */
|
||||
#define IN_IFF_DUPLICATED 0x02 /* DAD detected duplicate */
|
||||
#define IN_IFF_DETACHED 0x04 /* may be detached from the link */
|
||||
#define IN_IFF_TRYTENTATIVE 0x08 /* intent to try DAD */
|
||||
|
||||
/* do not input/output */
|
||||
#define IN_IFF_NOTREADY (IN_IFF_TENTATIVE | IN_IFF_DUPLICATED)
|
||||
#define IN_IFF_NOTREADY \
|
||||
(IN_IFF_TRYTENTATIVE | IN_IFF_TENTATIVE | IN_IFF_DUPLICATED)
|
||||
|
||||
/*
|
||||
* Interface address, Internet version. One of these structures
|
||||
|
@ -100,6 +102,8 @@ struct in_ifaddr {
|
|||
the allhosts multicast group */
|
||||
uint16_t ia_idsalt; /* ip_id salt for this ia */
|
||||
int ia4_flags; /* address flags */
|
||||
void (*ia_dad_start) (struct ifaddr *); /* DAD start function */
|
||||
void (*ia_dad_stop) (struct ifaddr *); /* DAD stop function */
|
||||
};
|
||||
|
||||
struct in_aliasreq {
|
||||
|
|
Loading…
Reference in New Issue