static volatile int do_signal = 0;
static int urandom_fd = -1;
-static bool bound = false, allow_slaac_only = false;
+static bool bound = false, allow_slaac_only = true, release = true;
int main(_unused int argc, char* const argv[])
bool help = false, daemonize = false;
int c, request_pd = 0;
- while ((c = getopt(argc, argv, "SN:P:c:r:s:hdp:")) != -1) {
+ while ((c = getopt(argc, argv, "SN:P:c:r:s:khdp:")) != -1) {
switch (c) {
case 'S':
- allow_slaac_only = true;
+ allow_slaac_only = false;
break;
case 'N':
break;
case 'P':
+ allow_slaac_only = false;
request_pd = strtoul(optarg, NULL, 10);
if (request_pd == 0)
request_pd = -1;
buf[0] = 0;
buf[1] = DHCPV6_OPT_CLIENTID;
buf[2] = 0;
- buf[4] = l;
+ buf[3] = l;
odhcp6c_add_state(STATE_CLIENT_ID, buf, l + 4);
} else {
help = true;
script = optarg;
break;
+ case 'k':
+ release = false;
+ break;
+
case 'd':
daemonize = true;
break;
dhcpv6_set_ia_na_mode(ia_na_mode);
bound = false;
+ syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
+
do_signal = 0;
int res = dhcpv6_request(DHCPV6_MSG_SOLICIT);
+ odhcp6c_signal_process();
if (res < 0) {
continue; // Might happen if we got a signal
do_signal = 0;
res = dhcpv6_request(DHCPV6_MSG_INFO_REQ);
+ odhcp6c_signal_process();
if (do_signal == SIGUSR1)
continue;
else if (res < 0)
script_call("informed");
bound = true;
+ syslog(LOG_NOTICE, "entering stateless-mode on %s", ifname);
if (dhcpv6_poll_reconfigure() > 0)
script_call("informed");
if (dhcpv6_request(DHCPV6_MSG_REQUEST) < 0)
continue;
+ odhcp6c_signal_process();
script_call("bound");
bound = true;
+ syslog(LOG_NOTICE, "entering stateful-mode on %s", ifname);
while (do_signal == 0 || do_signal == SIGUSR1) {
// Renew Cycle
// Wait for T1 to expire or until we get a reconfigure
int res = dhcpv6_poll_reconfigure();
+ odhcp6c_signal_process();
if (res >= 0) {
if (res > 0)
script_call("updated");
r = dhcpv6_request(DHCPV6_MSG_REQUEST);
else
r = dhcpv6_request(DHCPV6_MSG_RENEW);
+ odhcp6c_signal_process();
if (r > 0) // Publish updates
script_call("updated");
if (r >= 0)
// If we have IAs, try rebind otherwise restart
res = dhcpv6_request(DHCPV6_MSG_REBIND);
+ odhcp6c_signal_process();
odhcp6c_get_state(STATE_IA_PD, &ia_pd_new);
odhcp6c_get_state(STATE_IA_NA, &ia_na_new);
bound = false;
script_call("unbound");
- if (server_id_len > 0 && (ia_pd_len > 0 || ia_na_len > 0))
+ if (server_id_len > 0 && (ia_pd_len > 0 || ia_na_len > 0) && release)
dhcpv6_request(DHCPV6_MSG_RELEASE);
odhcp6c_clear_state(STATE_IA_NA);
const char buf[] =
"Usage: odhcp6c [options] <interface>\n"
"\nFeature options:\n"
- " -S Allow SLAAC-only assignment\n"
+ " -S Don't allow SLAAC-only (implied by -P)\n"
" -N <mode> Mode for requesting addresses [try|force|none]\n"
" -P <length> Request IPv6-Prefix (0 = auto)\n"
" -c <clientid> Override client-ID (base-16 encoded)\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"
"\nInvocation options:\n"
" -p <pidfile> Set pidfile (/var/run/6relayd.pid)\n"
" -d Daemonize\n"
new->valid = safe;
if (new->valid > 0) {
- if (x)
- *x = *new;
- else
+ if (x) {
+ x->valid = new->valid;
+ x->preferred = new->preferred;
+ } else {
odhcp6c_add_state(state, new, sizeof(*new));
+ }
} else if (x) {
odhcp6c_remove_state(state, (x - start) * sizeof(*x), sizeof(*x));
}