user could change from IA_PD to IA_NA.
Re-send INFORM_REQUEST at each ROUTERADVERT.
Save some code by sharing the drop addrs loop.
const struct interface *ifd)
{
struct dhcp6_state *state;
- struct ipv6_addr *ap, *apn;
state = D6_STATE(ifp);
- if (state == NULL)
- return;
- TAILQ_FOREACH_SAFE(ap, &state->addrs, next, apn) {
- if (ifd && ap->delegating_iface != ifd)
- continue;
- TAILQ_REMOVE(&state->addrs, ap, next);
- if (ap->dadcallback)
- eloop_q_timeout_delete(0, NULL, ap->dadcallback);
- /* Only drop the address if no other RAs have assigned it.
- * This is safe because the RA is removed from the list
- * before we are called. */
- if (drop && ap->flags & IPV6_AF_ONLINK &&
- !dhcp6_addrexists(ap) &&
- !ipv6rs_addrexists(ap))
- {
- syslog(LOG_INFO, "%s: deleting address %s",
- ap->iface->name, ap->saddr);
- if (del_address6(ap) == -1 &&
- errno != EADDRNOTAVAIL && errno != ENXIO)
- syslog(LOG_ERR, "del_address6 %m");
- }
- free(ap);
+ if (state) {
+ ipv6_freedrop_addrs(&state->addrs, drop, ifd);
+ if (drop)
+ ipv6_buildroutes();
}
- if (drop)
- ipv6_buildroutes();
}
static void dhcp6_delete_delegates(struct interface *ifp)
{
struct dhcp6_state *state;
- syslog(LOG_INFO, "%s: requesting DHCPv6 information", ifp->name);
-
state = D6_STATE(ifp);
+ if (state->new == NULL || ifp->options->options & DHCPCD_DEBUG)
+ syslog(LOG_INFO, "%s: requesting DHCPv6 information",
+ ifp->name);
state->state = DH6S_INFORM;
state->start_uptime = uptime();
state->RTC = 0;
return bytes;
}
-static ssize_t
+static int
dhcp6_readlease(struct interface *ifp)
{
struct dhcp6_state *state;
close(fd);
/* Check to see if the lease is still valid */
- if (dhcp6_validatelease(ifp, state->new, state->new_len, NULL) == -1)
+ fd = dhcp6_validatelease(ifp, state->new, state->new_len, NULL);
+ if (fd == -1)
+ goto ex;
+ if (fd == 0) {
+ syslog(LOG_INFO, "%s: lease was for different IA type",
+ ifp->name);
goto ex;
+ }
if (state->expire != ND6_INFINITE_LIFETIME) {
gettimeofday(&now, NULL);
}
}
- return bytes;
+ return fd;
ex:
dhcp6_freedrop_addrs(ifp, 0, NULL);
if (options & DHCPCD_TEST)
script_runreason(ifp, "TEST");
else {
- state->state = DH6S_BOUND;
+ if (state->state != DH6S_INFORM)
+ state->state = DH6S_BOUND;
if (state->renew && state->renew != ND6_INFINITE_LIFETIME)
eloop_timeout_add_sec(state->renew,
dhcp6_startrenew, ifp);
dhcp6_find_delegates(ifp);
return 0;
}
+ if (state->state == DH6S_INFORM && init_state == DH6S_INFORM) {
+ dhcp6_startinform(ifp);
+ return 0;
+ }
/* We're already running DHCP6 */
/* XXX: What if the managed flag changes? */
return 0;
return 0;
}
+void
+ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
+ const struct interface *ifd)
+{
+ struct ipv6_addr *ap, *apn;
+
+ TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
+ if (ifd && ap->delegating_iface != ifd)
+ continue;
+ TAILQ_REMOVE(addrs, ap, next);
+ if (ap->dadcallback)
+ eloop_q_timeout_delete(0, NULL, ap->dadcallback);
+ /* Only drop the address if no other RAs have assigned it.
+ * This is safe because the RA is removed from the list
+ * before we are called. */
+ if (drop && ap->flags & IPV6_AF_ADDED &&
+ !ipv6rs_addrexists(ap) && !dhcp6_addrexists(ap))
+ {
+ syslog(LOG_INFO, "%s: deleting address %s",
+ ap->iface->name, ap->saddr);
+ if (del_address6(ap) == -1 &&
+ errno != EADDRNOTAVAIL && errno != ENXIO)
+ syslog(LOG_ERR, "del_address6 %m");
+ }
+ free(ap);
+ }
+}
+
static struct ipv6_state *
ipv6_getstate(struct interface *ifp)
{
int ipv6_userprefix( const struct in6_addr *, short prefix_len,
uint64_t user_number, struct in6_addr *result, short result_len);
int ipv6_addaddr(struct ipv6_addr *);
+void ipv6_freedrop_addrs(struct ipv6_addrhead *, int,
+ const struct interface *);
void ipv6_handleifa(int, struct if_head *,
const char *, const struct in6_addr *, int);
int ipv6_handleifa_addrs(int, struct ipv6_addrhead *,
return 0;
}
-static void
-ipv6rs_freedrop_addrs(struct ra *rap, int drop)
-{
- struct ipv6_addr *ap;
-
- while ((ap = TAILQ_FIRST(&rap->addrs))) {
- TAILQ_REMOVE(&rap->addrs, ap, next);
- if (ap->dadcallback)
- eloop_q_timeout_delete(0, NULL, ap->dadcallback);
- /* Only drop the address if no other RAs have assigned it.
- * This is safe because the RA is removed from the list
- * before we are called. */
- if (drop && ap->flags & IPV6_AF_ADDED &&
- !IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
- !ipv6rs_addrexists(ap) && !dhcp6_addrexists(ap))
- {
- syslog(LOG_INFO, "%s: deleting address %s",
- rap->iface->name, ap->saddr);
- if (del_address6(ap) == -1 &&
- errno != EADDRNOTAVAIL && errno != ENXIO)
- syslog(LOG_ERR, "del_address6 %m");
- }
- free(ap);
- }
-}
-
void ipv6rs_freedrop_ra(struct ra *rap, int drop)
{
eloop_timeout_delete(NULL, rap);
if (!drop)
TAILQ_REMOVE(&ipv6_routers, rap, next);
- ipv6rs_freedrop_addrs(rap, drop);
+ ipv6_freedrop_addrs(&rap->addrs, drop, NULL);
ipv6rs_free_opts(rap);
free(rap->data);
free(rap->ns);
handle_flag:
if (rap->flags & ND_RA_FLAG_MANAGED) {
- if (dhcp6_start(ifp, DH6S_INIT) == -1)
+ if (rap->lifetime && dhcp6_start(ifp, DH6S_INIT) == -1)
syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
} else if (rap->flags & ND_RA_FLAG_OTHER) {
- if (dhcp6_start(ifp, DH6S_INFORM) == -1)
+ if (rap->lifetime && dhcp6_start(ifp, DH6S_INFORM) == -1)
syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
} else {
- if (new_data)
+ if (rap->lifetime && new_data)
syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA",
ifp->name);
if (options & DHCPCD_TEST)