Set a global default DHCPv6 exchange timeout
authorSteven Barth <steven@midlink.org>
Sun, 5 May 2013 13:56:42 +0000 (15:56 +0200)
committerSteven Barth <steven@midlink.org>
Sun, 5 May 2013 13:56:42 +0000 (15:56 +0200)
This delays SLAAC-updates before any DHCPv6-binding is established.

src/odhcp6c.c
src/odhcp6c.h
src/script.c

index a97e4c914cf646d680edd869bcfe258e4f652372..6ce9adf33ce344548b72ed700d40f9c3934066b0 100644 (file)
@@ -40,8 +40,8 @@ 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;
-static bool bound = false, allow_slaac_only = true, release = true;
+static int urandom_fd = -1, allow_slaac_only = 15;
+static bool bound = false, release = true;
 
 
 int main(_unused int argc, char* const argv[])
@@ -58,10 +58,10 @@ int main(_unused int argc, char* const argv[])
        bool help = false, daemonize = false;
        int logopt = LOG_PID;
        int c, request_pd = 0;
-       while ((c = getopt(argc, argv, "SN:P:c:r:s:khedp:")) != -1) {
+       while ((c = getopt(argc, argv, "S::N:P:c:r:s:khedp:")) != -1) {
                switch (c) {
                case 'S':
-                       allow_slaac_only = false;
+                       allow_slaac_only = (optarg) ? atoi(optarg) : -1;
                        break;
 
                case 'N':
@@ -76,7 +76,6 @@ int main(_unused int argc, char* const argv[])
                        break;
 
                case 'P':
-                       allow_slaac_only = false;
                        request_pd = strtoul(optarg, NULL, 10);
                        if (request_pd == 0)
                                request_pd = -1;
@@ -307,7 +306,7 @@ static int usage(void)
        const char buf[] =
        "Usage: odhcp6c [options] <interface>\n"
        "\nFeature options:\n"
-       "       -S              Don't allow SLAAC-only (implied by -P)\n"
+       "       -S <time>       Wait at least <time> sec for a DHCP-server (15)\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"
@@ -355,12 +354,12 @@ bool odhcp6c_signal_process(void)
 {
        if (do_signal == SIGIO) {
                do_signal = 0;
-               bool updated = ra_process();
-               updated |= ra_rtnl_process();
-               if (updated && (bound || allow_slaac_only)) {
-                       odhcp6c_expire();
-                       script_call("ra-updated");
-               }
+               bool ra_updated = ra_process();
+
+               if (ra_rtnl_process() || (ra_updated && (bound || allow_slaac_only == 0)))
+                       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);
        }
 
        return do_signal != 0;
index fd3b07a8cf93fe5b9ae753df532ec188689dd533..cfd1a53565f580cca6a179b14dcc7d33b0044747 100644 (file)
@@ -224,6 +224,7 @@ int set_rtnetlink_addr(int ifindex, const struct in6_addr *addr,
 int script_init(const char *path, const char *ifname);
 ssize_t script_unhexlify(uint8_t *dst, size_t len, const char *src);
 void script_call(const char *status);
+void script_delay_call(const char *status, int timeout);
 
 bool odhcp6c_signal_process(void);
 uint64_t odhcp6c_get_milli_time(void);
index ffb39f3f5726470513e8f0004f12bd7007048b61..a56d9b4df42c62947ec9d9c5d6b1f05668aa70da 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
+#include <signal.h>
 #include <unistd.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
@@ -38,6 +39,7 @@ static const int8_t hexvals[] = {
 
 
 static char *argv[4] = {NULL, NULL, NULL, NULL};
+static volatile char *delayed_call = NULL;
 
 
 int script_init(const char *path, const char *ifname)
@@ -176,11 +178,32 @@ static void entry_to_env(const char *name, const void *data, size_t len, enum en
 }
 
 
+static void script_call_delayed(int signal __attribute__((unused)))
+{
+       if (delayed_call)
+               script_call((char*)delayed_call);
+}
+
+
+void script_delay_call(const char *status, int timeout)
+{
+       if (!delayed_call) {
+               delayed_call = strdup(status);
+               signal(SIGALRM, script_call_delayed);
+               alarm(timeout);
+       }
+}
+
+
 void script_call(const char *status)
 {
        size_t dns_len, search_len, custom_len, sntp_ip_len, sntp_dns_len;
        size_t sip_ip_len, sip_fqdn_len;
 
+       odhcp6c_expire();
+       if (delayed_call)
+               alarm(0);
+
        struct in6_addr *dns = odhcp6c_get_state(STATE_DNS, &dns_len);
        uint8_t *search = odhcp6c_get_state(STATE_SEARCH, &search_len);
        uint8_t *custom = odhcp6c_get_state(STATE_CUSTOM_OPTS, &custom_len);