static uint8_t *state_data[_STATE_MAX] = {NULL};
static size_t state_len[_STATE_MAX] = {0};
static volatile int do_signal = 0;
static int urandom_fd = -1, allow_slaac_only = 0;
static bool bound = false, release = true;
static uint8_t *state_data[_STATE_MAX] = {NULL};
static size_t state_len[_STATE_MAX] = {0};
static volatile int do_signal = 0;
static int urandom_fd = -1, allow_slaac_only = 0;
static bool bound = false, release = true;
signal(SIGUSR2, sighandler);
if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 ||
signal(SIGUSR2, sighandler);
if ((urandom_fd = open("/dev/urandom", O_CLOEXEC | O_RDONLY)) < 0 ||
- init_dhcpv6(ifname, request_pd) || ra_init(ifname) ||
- script_init(script, ifname)) {
+ init_dhcpv6(ifname, request_pd, sol_timeout) ||
+ ra_init(ifname, &ifid) || script_init(script, ifname)) {
odhcp6c_clear_state(STATE_IA_PD);
odhcp6c_clear_state(STATE_SNTP_IP);
odhcp6c_clear_state(STATE_SNTP_FQDN);
odhcp6c_clear_state(STATE_SIP_IP);
odhcp6c_clear_state(STATE_SIP_FQDN);
odhcp6c_clear_state(STATE_IA_PD);
odhcp6c_clear_state(STATE_SNTP_IP);
odhcp6c_clear_state(STATE_SNTP_FQDN);
odhcp6c_clear_state(STATE_SIP_IP);
odhcp6c_clear_state(STATE_SIP_FQDN);
+ // Server candidates need deep-delete
+ size_t cand_len;
+ struct dhcpv6_server_cand *cand = odhcp6c_get_state(STATE_SERVER_CAND, &cand_len);
+ for (size_t i = 0; i < cand_len / sizeof(*cand); ++i) {
+ free(cand[i].ia_na);
+ free(cand[i].ia_pd);
+ }
+ odhcp6c_clear_state(STATE_SERVER_CAND);
+
syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
do_signal = 0;
int res = dhcpv6_request(DHCPV6_MSG_SOLICIT);
odhcp6c_signal_process();
syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
do_signal = 0;
int res = dhcpv6_request(DHCPV6_MSG_SOLICIT);
odhcp6c_signal_process();
continue; // Might happen if we got a signal
} else if (res == DHCPV6_STATELESS) { // Stateless mode
while (do_signal == 0 || do_signal == SIGUSR1) {
continue; // Might happen if we got a signal
} else if (res == DHCPV6_STATELESS) { // Stateless mode
while (do_signal == 0 || do_signal == SIGUSR1) {
// Wait for T1 to expire or until we get a reconfigure
int res = dhcpv6_poll_reconfigure();
odhcp6c_signal_process();
// Wait for T1 to expire or until we get a reconfigure
int res = dhcpv6_poll_reconfigure();
odhcp6c_signal_process();
odhcp6c_get_state(STATE_IA_PD, &ia_pd_new);
odhcp6c_get_state(STATE_IA_NA, &ia_na_new);
odhcp6c_get_state(STATE_IA_PD, &ia_pd_new);
odhcp6c_get_state(STATE_IA_NA, &ia_na_new);
(ia_na_new == 0 && ia_na_len))
break; // We lost all our IAs, restart
else if (res > 0)
(ia_na_new == 0 && ia_na_len))
break; // We lost all our IAs, restart
else if (res > 0)
" -S <time> Wait at least <time> sec for a DHCP-server (0)\n"
" -N <mode> Mode for requesting addresses [try|force|none]\n"
" -P <length> Request IPv6-Prefix (0 = auto)\n"
" -S <time> Wait at least <time> sec for a DHCP-server (0)\n"
" -N <mode> Mode for requesting addresses [try|force|none]\n"
" -P <length> Request IPv6-Prefix (0 = auto)\n"
" -r <options> Options to be requested (comma-separated)\n"
" -s <script> Status update script (/usr/sbin/odhcp6c-update)\n"
" -k Don't send a RELEASE when stopping\n"
" -r <options> Options to be requested (comma-separated)\n"
" -s <script> Status update script (/usr/sbin/odhcp6c-update)\n"
" -k Don't send a RELEASE when stopping\n"
script_call("ra-updated"); // Immediate process urgent events
else if (ra_updated && !bound && allow_slaac_only > 0)
script_delay_call("ra-updated", allow_slaac_only);
script_call("ra-updated"); // Immediate process urgent events
else if (ra_updated && !bound && allow_slaac_only > 0)
script_delay_call("ra-updated", allow_slaac_only);
+void* odhcp6c_move_state(enum odhcp6c_state state, size_t *len)
+{
+ *len = state_len[state];
+ void *data = state_data[state];
+
+ state_len[state] = 0;
+ state_data[state] = NULL;
+
+ return data;
+}
+
+
{
size_t len;
struct odhcp6c_entry *x = odhcp6c_find_entry(state, new);
struct odhcp6c_entry *start = odhcp6c_get_state(state, &len);
{
size_t len;
struct odhcp6c_entry *x = odhcp6c_find_entry(state, new);
struct odhcp6c_entry *start = odhcp6c_get_state(state, &len);
} else {
odhcp6c_add_state(state, new, sizeof(*new));
}
} else if (x) {
odhcp6c_remove_state(state, (x - start) * sizeof(*x), sizeof(*x));
}
} else {
odhcp6c_add_state(state, new, sizeof(*new));
}
} else if (x) {
odhcp6c_remove_state(state, (x - start) * sizeof(*x), sizeof(*x));
}
size_t len;
struct odhcp6c_entry *start = odhcp6c_get_state(state, &len);
for (struct odhcp6c_entry *c = start; c < &start[len / sizeof(*c)]; ++c) {
size_t len;
struct odhcp6c_entry *start = odhcp6c_get_state(state, &len);
for (struct odhcp6c_entry *c = start; c < &start[len / sizeof(*c)]; ++c) {
void odhcp6c_random(void *buf, size_t len)
{
read(urandom_fd, buf, len);
}
void odhcp6c_random(void *buf, size_t len)
{
read(urandom_fd, buf, len);
}