If we receieve an RA without a public prefix but with the Managed flag set,

ignore the RA until we recieve a DHCPv6 lease with a public address at
which point it is applied.
This commit is contained in:
Roy Marples 2015-04-04 21:40:47 +00:00
parent 6c05c9f899
commit d40f2f7b8d
4 changed files with 50 additions and 2 deletions

17
dhcp6.c
View File

@ -487,6 +487,22 @@ dhcp6_delegateaddr(struct in6_addr *addr, struct interface *ifp,
return sla->prefix_len;
}
int
dhcp6_has_public_addr(const struct interface *ifp)
{
const struct dhcp6_state *state = D6_CSTATE(ifp);
const struct ipv6_addr *ia;
if (state == NULL)
return 0;
TAILQ_FOREACH(ia, &state->addrs, next) {
if (ia->prefix_pltime &&
(ia->addr.s6_addr[0] & 0xfe) != 0xc)
return 1;
}
return 0;
}
static int
dhcp6_makemessage(struct interface *ifp)
{
@ -3033,6 +3049,7 @@ recv:
eloop_timeout_add_sec(ifp->ctx->eloop,
(time_t)state->expire, dhcp6_startexpire, ifp);
ipv6nd_runignoredra(ifp);
ipv6_addaddrs(&state->addrs);
dhcp6_delegate_prefix(ifp);

View File

@ -235,6 +235,7 @@ void dhcp6_printoptions(const struct dhcpcd_ctx *,
struct ipv6_addr *dhcp6_findaddr(struct dhcpcd_ctx *, const struct in6_addr *,
short);
size_t dhcp6_find_delegates(struct interface *);
int dhcp6_has_public_addr(const struct interface *);
int dhcp6_start(struct interface *, enum DH6S);
void dhcp6_reboot(struct interface *);
ssize_t dhcp6_env(char **, const char *, const struct interface *,

View File

@ -1136,8 +1136,9 @@ extra_opt:
if (new_rap)
add_router(ifp->ctx->ipv6, rap);
if (!ipv6nd_ra_has_public_addr(rap) &&
!(rap->flags & ND_RA_FLAG_MANAGED) &&
!(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC))
!(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) &&
(!(rap->flags & ND_RA_FLAG_MANAGED) ||
!dhcp6_has_public_addr(rap->iface)))
{
logger(rap->iface->ctx,
rap->no_public_warned ? LOG_DEBUG : LOG_WARNING,
@ -1194,6 +1195,34 @@ nodhcp6:
ipv6nd_expirera(ifp);
}
/* Run RA's we ignored becuase they had no public addresses
* This should only be called when DHCPv6 applies a public address */
void
ipv6nd_runignoredra(struct interface *ifp)
{
struct ra *rap;
TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
if (rap->iface == ifp &&
!rap->expired &&
rap->no_public_warned)
{
rap->no_public_warned = 0;
logger(rap->iface->ctx, LOG_INFO,
"%s: applying ignored RA from %s",
rap->iface->name, rap->sfrom);
if (ifp->ctx->options & DHCPCD_TEST) {
script_runreason(ifp, "TEST");
continue;
}
if (ipv6nd_scriptrun(rap))
return;
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
eloop_timeout_delete(ifp->ctx->eloop, NULL, rap);
}
}
}
int
ipv6nd_hasra(const struct interface *ifp)
{

View File

@ -94,6 +94,7 @@ ssize_t ipv6nd_free(struct interface *);
void ipv6nd_expirera(void *arg);
int ipv6nd_hasra(const struct interface *);
int ipv6nd_hasradhcp(const struct interface *);
void ipv6nd_runignoredra(struct interface *);
void ipv6nd_handleifa(struct dhcpcd_ctx *, int,
const char *, const struct in6_addr *, int);
int ipv6nd_dadcompleted(const struct interface *);