For IPv6, emit RTM_NEWADDR once DAD completes and also when address flag

changes. Tentative addresses are not emitted.

Version bumped so userland can detect this behaviour change.
This commit is contained in:
roy 2013-05-21 08:37:27 +00:00
parent a13a1bd40a
commit a34d72845c
7 changed files with 106 additions and 26 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: route.4,v 1.18 2011/07/03 07:25:52 kefren Exp $
.\" $NetBSD: route.4,v 1.19 2013/05/21 08:37:27 roy Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" @(#)route.4 8.6 (Berkeley) 4/19/94
.\"
.Dd November 13, 2010
.Dd May 21, 2013
.Dt ROUTE 4
.Os
.Sh NAME
@ -128,6 +128,11 @@ to most significant bit within the vector.
.Pp
Any messages sent to the kernel are returned, and copies are sent
to all interested listeners.
The exception to this is a new address marked as tentative, where copies
will be sent once Duplicate Address Detection has completed and
the tentative flag cleared or the duplicated flag set.
Also, new address messages will also be emitted when other flags on the address
change such as deprecated and detached.
The kernel will provide the process ID for the sender, and the
sender may use an additional sequence field to distinguish between
outstanding messages.
@ -329,6 +334,20 @@ Specifiers for which addresses are present in the messages are:
#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
#define RTA_TAG 0x100 /* route tag */
.Ed
.Pp
Flags for IPv6 addresses:
.Bd -literal
#define IN6_IFF_ANYCAST 0x01 /* anycast address */
#define IN6_IFF_TENTATIVE 0x02 /* tentative address */
#define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */
#define IN6_IFF_DETACHED 0x08 /* may be detached from the link */
#define IN6_IFF_DEPRECATED 0x10 /* deprecated address */
#define IN6_IFF_NODAD 0x20 /* don't perform DAD on this address
* (used only at first SIOC* call)
*/
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
#define IN6_IFF_TEMPORARY 0x80 /* temporary (anonymous) address. */
.Ed
.Sh SEE ALSO
.Xr socket 2 ,
.Xr sysctl 3

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6.c,v 1.161 2012/06/23 03:14:03 christos Exp $ */
/* $NetBSD: in6.c,v 1.162 2013/05/21 08:37:27 roy Exp $ */
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
/*
@ -62,7 +62,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.161 2012/06/23 03:14:03 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.162 2013/05/21 08:37:27 roy Exp $");
#include "opt_inet.h"
#include "opt_pfil_hooks.h"
@ -191,13 +191,29 @@ in6_ifloop_request(int cmd, struct ifaddr *ifa)
rt_replace_ifa(nrt, ifa);
/*
* Report the addition/removal of the address to the routing socket.
* Report the addition/removal of the address to the routing socket
* unless the address is marked tentative, where it will be reported
* once DAD completes.
* XXX: since we called rtinit for a p2p interface with a destination,
* we end up reporting twice in such a case. Should we rather
* omit the second report?
*/
if (nrt) {
rt_newaddrmsg(cmd, ifa, e, nrt);
if (cmd != RTM_ADD ||
!(((struct in6_ifaddr *)ifa)->ia6_flags &IN6_IFF_TENTATIVE))
{
#if 0
struct in6_ifaddr *ia;
ia = (struct in6_ifaddr *)ifa;
log(LOG_DEBUG,
"in6_ifloop_request: announced %s (%s %d)\n",
ip6_sprintf(&ia->ia_addr.sin6_addr),
cmd == RTM_ADD ? "RTM_ADD" : "RTM_DELETE",
ia->ia6_flags);
#endif
rt_newaddrmsg(cmd, ifa, e, nrt);
}
if (cmd == RTM_DELETE) {
if (nrt->rt_refcnt <= 0) {
/* XXX: we should free the entry ourselves. */
@ -1058,10 +1074,6 @@ in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra,
} else
ia->ia6_lifetime.ia6t_preferred = 0;
/* reset the interface and routing table appropriately. */
if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
goto unlink;
/*
* configure address flags.
*/
@ -1084,6 +1096,10 @@ in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra,
if (hostIsNew && in6if_do_dad(ifp))
ia->ia6_flags |= IN6_IFF_TENTATIVE;
/* reset the interface and routing table appropriately. */
if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
goto unlink;
/*
* We are done if we have simply modified an existing address.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6.c,v 1.144 2013/01/24 14:23:09 joerg Exp $ */
/* $NetBSD: nd6.c,v 1.145 2013/05/21 08:37:27 roy Exp $ */
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.144 2013/01/24 14:23:09 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.145 2013/05/21 08:37:27 roy Exp $");
#include "opt_ipsec.h"
@ -582,7 +582,10 @@ nd6_timer(void *ignored_arg)
} else if (IFA6_IS_DEPRECATED(ia6)) {
int oldflags = ia6->ia6_flags;
ia6->ia6_flags |= IN6_IFF_DEPRECATED;
if ((oldflags & IN6_IFF_DEPRECATED) == 0) {
ia6->ia6_flags |= IN6_IFF_DEPRECATED;
nd6_newaddrmsg((struct ifaddr *)ia6);
}
/*
* If a temporary address has just become deprecated,
@ -613,7 +616,10 @@ nd6_timer(void *ignored_arg)
* A new RA might have made a deprecated address
* preferred.
*/
ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
if (ia6->ia6_flags & IN6_IFF_DEPRECATED) {
ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
nd6_newaddrmsg((struct ifaddr *)ia6);
}
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6.h,v 1.57 2012/06/23 03:14:04 christos Exp $ */
/* $NetBSD: nd6.h,v 1.58 2013/05/21 08:37:27 roy Exp $ */
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
/*
@ -435,6 +435,7 @@ void nd6_ns_input(struct mbuf *, int, int);
void nd6_ns_output(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, struct llinfo_nd6 *, int);
const void *nd6_ifptomac(const struct ifnet *);
void nd6_newaddrmsg(struct ifaddr *);
void nd6_dad_start(struct ifaddr *, int);
void nd6_dad_stop(struct ifaddr *);
void nd6_dad_duplicated(struct ifaddr *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6_nbr.c,v 1.96 2012/03/22 20:34:41 drochner Exp $ */
/* $NetBSD: nd6_nbr.c,v 1.97 2013/05/21 08:37:27 roy Exp $ */
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.96 2012/03/22 20:34:41 drochner Exp $");
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.97 2013/05/21 08:37:27 roy Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -1055,6 +1055,39 @@ nd6_dad_stoptimer(struct dadq *dp)
callout_stop(&dp->dad_timer_ch);
}
/*
* Routine to report address flag changes to the routing socket
*/
void
nd6_newaddrmsg(struct ifaddr *ifa)
{
struct sockaddr_in6 all1_sa;
struct rtentry *nrt = NULL;
int e;
sockaddr_in6_init(&all1_sa, &in6mask128, 0, 0, 0);
e = rtrequest(RTM_GET, ifa->ifa_addr, ifa->ifa_addr,
(struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
if (e != 0) {
log(LOG_ERR, "nd6_newaddrmsg: "
"RTM_GET operation failed for %s (errno=%d)\n",
ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
e);
}
if (nrt) {
rt_newaddrmsg(RTM_ADD, ifa, e, nrt);
//#if 0
log(LOG_DEBUG, "nd6_newaddrmsg: announced %s\n",
ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr)
);
//#endif
nrt->rt_refcnt--;
}
}
/*
* Start Duplicate Address Detection (DAD) for specified interface address.
*
@ -1085,12 +1118,9 @@ nd6_dad_start(struct ifaddr *ifa, int xtick)
ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
return;
}
if (ia->ia6_flags & IN6_IFF_ANYCAST) {
ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
return;
}
if (!ip6_dad_count) {
if (ia->ia6_flags & IN6_IFF_ANYCAST || !ip6_dad_count) {
ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
nd6_newaddrmsg(ifa);
return;
}
if (ifa->ifa_ifp == NULL)
@ -1246,6 +1276,7 @@ nd6_dad_timer(struct ifaddr *ifa)
* No duplicate address found.
*/
ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
nd6_newaddrmsg(ifa);
nd6log((LOG_DEBUG,
"%s: DAD complete for %s - no duplicates found\n",
@ -1294,6 +1325,9 @@ nd6_dad_duplicated(struct ifaddr *ifa)
log(LOG_ERR, "%s: manual intervention required\n",
if_name(ifp));
/* Inform the routing socket that DAD has completed */
nd6_newaddrmsg(ifa);
/*
* If the address is a link-local address formed from an interface
* identifier based on the hardware address which is supposed to be

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6_rtr.c,v 1.86 2013/02/18 16:45:50 christos Exp $ */
/* $NetBSD: nd6_rtr.c,v 1.87 2013/05/21 08:37:27 roy Exp $ */
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.86 2013/02/18 16:45:50 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.87 2013/05/21 08:37:27 roy Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -1580,10 +1580,14 @@ pfxlist_onlink_check(void)
ifa->ia6_flags |= IN6_IFF_TENTATIVE;
nd6_dad_start((struct ifaddr *)ifa,
0);
/* We will notify the routing socket
* of the DAD result, so no need to
* here */
}
} else {
if ((ifa->ia6_flags & IN6_IFF_DETACHED) == 0) {
ifa->ia6_flags |= IN6_IFF_DETACHED;
nd6_newaddrmsg((struct ifaddr *)ifa);
}
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: param.h,v 1.428 2013/03/29 01:09:45 christos Exp $ */
/* $NetBSD: param.h,v 1.429 2013/05/21 08:37:27 roy Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@ -63,7 +63,7 @@
* 2.99.9 (299000900)
*/
#define __NetBSD_Version__ 699001900 /* NetBSD 6.99.19 */
#define __NetBSD_Version__ 699002000 /* NetBSD 6.99.20 */
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)