// Update address IA
dhcpv6_for_each_option(&ia_hdr[1], end, otype, olen, odata) {
- struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, 0, 0,
- IN6ADDR_ANY_INIT, 0, 0, 0, 0, 0, 0};
-
- entry.iaid = ia_hdr->iaid;
+ struct odhcp6c_entry entry = {
+ .router = IN6ADDR_ANY_INIT,
+ .auxlen = 0,
+ .length = 0,
+ .ra_flags = 0,
+ .target = IN6ADDR_ANY_INIT,
+ .priority = 0,
+ .valid = 0,
+ .preferred = 0,
+ .t1 = 0,
+ .t2 = 0,
+ .iaid = ia_hdr->iaid,
+ };
switch (otype) {
case DHCPV6_OPT_IA_PREFIX: {
#include <limits.h>
#include <linux/if_addr.h>
#include <net/if.h>
+#include <netinet/icmp6.h>
#include <poll.h>
#include <resolv.h>
#include <signal.h>
return n;
}
+static bool odhcp6c_server_advertised()
+{
+ size_t len;
+ uint8_t *start = odhcp6c_get_state(STATE_RA_ROUTE, &len);
+
+ for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
+ (uint8_t*)c < &start[len] &&
+ (uint8_t*)odhcp6c_next_entry(c) <= &start[len];
+ c = odhcp6c_next_entry(c)) {
+ // Only default route entries have flags
+ if (c->length != 0 || IN6_IS_ADDR_UNSPECIFIED(&c->router))
+ continue;
+
+ if (c->ra_flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))
+ return true;
+ }
+
+ return false;
+}
+
bool odhcp6c_signal_process(void)
{
while (signal_io) {
signal_io = false;
+ size_t old_ra_prefix_size = state_len[STATE_RA_PREFIX];
bool ra_updated = ra_process();
if (ra_link_up()) {
signal_usr2 = true;
ra = false;
+ } else if (old_ra_prefix_size != state_len[STATE_RA_PREFIX] &&
+ odhcp6c_server_advertised()) {
+ // Restart DHCPv6 transaction when router advertisement flags
+ // show presence of a DHCPv6 server and new prefixes were
+ // added to STATE_RA_PREFIX state
+ signal_usr2 = true;
}
if (ra_updated && (bound || config_dhcp->allow_slaac_only >= 0)) {
return false;
x->valid = new->valid;
+ x->ra_flags = new->ra_flags;
+ x->priority = new->priority;
x->preferred = new->preferred;
x->t1 = new->t1;
x->t2 = new->t2;
entry->target = any;
entry->length = 0;
entry->router = from.sin6_addr;
+ entry->ra_flags = adv->nd_ra_flags_reserved & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER);
entry->priority = pref_to_priority(adv->nd_ra_flags_reserved);
if (entry->priority < 0)
entry->priority = pref_to_priority(0);
entry->preferred = entry->valid;
changed |= odhcp6c_update_entry(STATE_RA_ROUTE, entry,
ra_holdoff_interval);
+ entry->ra_flags = 0; // other STATE_RA_* entries don't have flags
// Parse hop limit
changed |= ra_set_hoplimit(adv->nd_ra_curhoplimit);