// IA states
static enum odhcp6c_ia_mode na_mode = IA_MODE_NONE, pd_mode = IA_MODE_NONE;
+static bool stateful_only_mode = false;
static bool accept_reconfig = false;
// Server unicast address
static struct in6_addr server_addr = IN6ADDR_ANY_INIT;
return "Unknown";
}
-int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout)
+int init_dhcpv6(const char *ifname, unsigned int options, int sk_prio, int sol_timeout)
{
client_options = options;
dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_timeout;
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0)
goto failure;
+ if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &sk_prio, sizeof(sk_prio)) < 0)
+ goto failure;
+
struct sockaddr_in6 client_addr = { .sin6_family = AF_INET6,
.sin6_port = htons(DHCPV6_CLIENT_PORT), .sin6_flowinfo = 0 };
IOV_TOTAL
};
-int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd)
+int dhcpv6_set_ia_mode(enum odhcp6c_ia_mode na, enum odhcp6c_ia_mode pd, bool stateful_only)
{
int mode = DHCPV6_UNKNOWN;
na_mode = na;
pd_mode = pd;
+ stateful_only_mode = stateful_only;
if (na_mode == IA_MODE_NONE && pd_mode == IA_MODE_NONE)
mode = DHCPV6_STATELESS;
}
}
- if ((!have_na && na_mode == IA_MODE_FORCE) ||
+ if ((stateful_only_mode && !have_na && !have_pd) ||
+ (!have_na && na_mode == IA_MODE_FORCE) ||
(!have_pd && pd_mode == IA_MODE_FORCE)) {
/*
* RFC7083 states to process the SOL_MAX_RT and
unsigned int updated_IAs = 0;
bool handled_status_codes[_DHCPV6_Status_Max] = { false, };
- odhcp6c_expire();
+ odhcp6c_expire(true);
if (orig == DHCPV6_MSG_UNKNOWN) {
static time_t last_update = 0;
t1 = ntohl(ia_hdr->t1);
t2 = ntohl(ia_hdr->t2);
- if (t1 > t2)
+ if (t1 > t2 && t1 > 0 && t2 > 0)
return 0;
syslog(LOG_INFO, "%s %04x T1 %d T2 %d", ntohs(ia_hdr->type) == DHCPV6_OPT_IA_PD ? "IA_PD" : "IA_NA", ntohl(ia_hdr->iaid), t1, t2);
{
struct odhcp6c_entry *e;
size_t ia_na_entries, ia_pd_entries, i;
+ size_t invalid_entries = 0;
int64_t l_t1 = UINT32_MAX, l_t2 = UINT32_MAX, l_t3 = 0;
e = odhcp6c_get_state(STATE_IA_NA, &ia_na_entries);
ia_na_entries /= sizeof(*e);
for (i = 0; i < ia_na_entries; i++) {
+ /* Exclude invalid IA_NA entries */
+ if (!e[i].valid) {
+ invalid_entries++;
+ continue;
+ }
+
if (e[i].t1 < l_t1)
l_t1 = e[i].t1;
ia_pd_entries /= sizeof(*e);
for (i = 0; i < ia_pd_entries; i++) {
+ /* Exclude invalid IA_PD entries */
+ if (!e[i].valid) {
+ invalid_entries++;
+ continue;
+ }
+
if (e[i].t1 < l_t1)
l_t1 = e[i].t1;
l_t3 = e[i].valid;
}
- if (ia_pd_entries || ia_na_entries) {
+ if (ia_pd_entries + ia_na_entries - invalid_entries) {
t1 = l_t1;
t2 = l_t2;
t3 = l_t3;