mirror of
https://github.com/rsmarples/dhcpcd.git
synced 2024-11-23 10:06:42 +08:00
IPv6: Only advertise addresses when needed
Remember when we have advertised an address. If we want to advertise it again, check this first. If we still want to advertise it, clear this flag for all other matching addresses. Clear advertised flags from all addresses on carrier up. This reduces needless NA spam from dhcpcd when the IPv6 Router is needlessly chatty with RA.
This commit is contained in:
parent
4f9648737c
commit
d0fef9f768
@ -1832,16 +1832,19 @@ ipv6_startstatic(struct interface *ifp)
|
||||
int
|
||||
ipv6_start(struct interface *ifp)
|
||||
{
|
||||
#ifdef IPV6_POLLADDRFLAG
|
||||
#if defined(ND6_ADVERTISE) || defined(IPV6_POLLADDRFLAG)
|
||||
struct ipv6_state *state;
|
||||
|
||||
/* We need to update the address flags. */
|
||||
if ((state = IPV6_STATE(ifp)) != NULL) {
|
||||
struct ipv6_addr *ia;
|
||||
#ifdef IPV6_POLLADDRFLAG
|
||||
const char *alias;
|
||||
int flags;
|
||||
#endif
|
||||
|
||||
TAILQ_FOREACH(ia, &state->addrs, next) {
|
||||
#ifdef IPV6_POLLADDRFLAG
|
||||
#ifdef ALIAS_ADDR
|
||||
alias = ia->alias;
|
||||
#else
|
||||
@ -1850,6 +1853,9 @@ ipv6_start(struct interface *ifp)
|
||||
flags = if_addrflags6(ia->iface, &ia->addr, alias);
|
||||
if (flags != -1)
|
||||
ia->addr_flags = flags;
|
||||
#endif
|
||||
/* hwaddr could have changed */
|
||||
ia->flags &= ~IPV6_AF_ADVERTISED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -160,7 +160,8 @@
|
||||
|
||||
/*
|
||||
* ND6 Advertising is only used for IP address sharing to prefer
|
||||
* the address on a specific interface.
|
||||
* the address on a specific interface or when the hardware address
|
||||
* of the interface changes.
|
||||
* This just fails to work on OpenBSD and causes erroneous duplicate
|
||||
* address messages on BSD's other then DragonFly and NetBSD.
|
||||
*/
|
||||
@ -227,8 +228,9 @@ struct ipv6_addr {
|
||||
#define IPV6_AF_EXTENDED (1U << 13)
|
||||
#define IPV6_AF_REGEN (1U << 14)
|
||||
#define IPV6_AF_ROUTER (1U << 15)
|
||||
#define IPV6_AF_ADVERTISED (1U << 16)
|
||||
#ifdef IPV6_MANAGETEMPADDR
|
||||
#define IPV6_AF_TEMPORARY (1U << 16)
|
||||
#define IPV6_AF_TEMPORARY (1U << 17)
|
||||
#endif
|
||||
|
||||
struct ll_callback {
|
||||
|
38
src/ipv6nd.c
38
src/ipv6nd.c
@ -514,6 +514,7 @@ ipv6nd_advertise(struct ipv6_addr *ia)
|
||||
struct interface *ifp;
|
||||
struct ipv6_state *state;
|
||||
struct ipv6_addr *iap, *iaf;
|
||||
bool found_another = false;
|
||||
struct nd_neighbor_advert *na;
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST(&ia->addr))
|
||||
@ -529,20 +530,20 @@ ipv6nd_advertise(struct ipv6_addr *ia)
|
||||
iaf = NULL;
|
||||
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
|
||||
state = IPV6_STATE(ifp);
|
||||
if (state == NULL || !if_is_link_up(ifp))
|
||||
if (state == NULL)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(iap, &state->addrs, next) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr))
|
||||
continue;
|
||||
|
||||
/* Cancel any current advertisement. */
|
||||
eloop_timeout_delete(ctx->eloop,
|
||||
ipv6nd_sendadvertisement, iap);
|
||||
if (iaf != NULL)
|
||||
found_another = true;
|
||||
|
||||
/* Don't advertise what we can't use. */
|
||||
if (iap->prefix_vltime == 0 ||
|
||||
iap->addr_flags & IN6_IFF_NOTUSEABLE)
|
||||
iap->addr_flags & IN6_IFF_NOTUSEABLE ||
|
||||
!if_is_link_up(ifp))
|
||||
continue;
|
||||
|
||||
if (iaf == NULL ||
|
||||
@ -550,9 +551,32 @@ ipv6nd_advertise(struct ipv6_addr *ia)
|
||||
iaf = iap;
|
||||
}
|
||||
}
|
||||
if (iaf == NULL)
|
||||
|
||||
/* If we have already advertised the address, return. */
|
||||
if (iaf == NULL || iaf->flags & IPV6_AF_ADVERTISED)
|
||||
return;
|
||||
|
||||
/* Now cancel any other advertisements for the same address. */
|
||||
if (found_another) {
|
||||
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
|
||||
state = IPV6_STATE(ifp);
|
||||
if (state == NULL)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(iap, &state->addrs, next) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&iap->addr, &ia->addr))
|
||||
continue;
|
||||
|
||||
iap->flags &= ~IPV6_AF_ADVERTISED;
|
||||
eloop_timeout_delete(ctx->eloop,
|
||||
ipv6nd_sendadvertisement, iap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eloop_timeout_delete(ctx->eloop,
|
||||
ipv6nd_sendadvertisement, iaf);
|
||||
}
|
||||
|
||||
/* Make the packet. */
|
||||
ifp = iaf->iface;
|
||||
iaf->na_len = sizeof(*na);
|
||||
@ -588,7 +612,7 @@ ipv6nd_advertise(struct ipv6_addr *ia)
|
||||
iaf->na_count = 0;
|
||||
free(iaf->na);
|
||||
iaf->na = na;
|
||||
eloop_timeout_delete(ctx->eloop, ipv6nd_sendadvertisement, iaf);
|
||||
iaf->flags |= IPV6_AF_ADVERTISED;
|
||||
ipv6nd_sendadvertisement(iaf);
|
||||
}
|
||||
#elif !defined(SMALL)
|
||||
|
Loading…
Reference in New Issue
Block a user