diff --git a/sys/netinet/if_arp.c b/sys/netinet/if_arp.c index c72f24557aff..4c0a1ede441b 100644 --- a/sys/netinet/if_arp.c +++ b/sys/netinet/if_arp.c @@ -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 -__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; diff --git a/sys/netinet/if_inarp.h b/sys/netinet/if_inarp.h index 6450c332a8ea..2da4ba2fee49 100644 --- a/sys/netinet/if_inarp.h +++ b/sys/netinet/if_inarp.h @@ -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 *); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 6be47abb89a3..b1e7bf9993d9 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -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 -__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. diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 7091b90c0cff..221ca8deea7b 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -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 {