Avoid of waiting for Advertise in stateless-only mode
authorVladislav Grishenko <themiron@mail.ru>
Sat, 25 Apr 2015 15:52:57 +0000 (20:52 +0500)
committerVladislav Grishenko <themiron@mail.ru>
Sat, 25 Apr 2015 16:00:46 +0000 (21:00 +0500)
Start with Information-request when configured not to ask
IA_NA/IA_PD. It allows to complete the exchange using only
two messages, instead of four, and fixes infinite Advertise
waiting loop with servers that just ignore Solicit messages.

src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h

index bc403b9..425aee1 100644 (file)
@@ -216,10 +216,19 @@ enum {
        IOV_TOTAL
 };
 
-void 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)
 {
+       int mode = DHCPV6_UNKNOWN;
+
        na_mode = na;
        pd_mode = pd;
+
+       if (na_mode == IA_MODE_NONE && pd_mode == IA_MODE_NONE)
+               mode = DHCPV6_STATELESS;
+       else if (na_mode == IA_MODE_FORCE || pd_mode == IA_MODE_FORCE)
+               mode = DHCPV6_STATEFUL;
+
+       return mode;
 }
 
 static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs)
@@ -547,10 +556,15 @@ int dhcpv6_request(enum dhcpv6_msg type)
                        round_end = timeout * 1000 + start;
 
                // Built and send package
-               if (type != DHCPV6_MSG_UNKNOWN) {
-                       if (type != DHCPV6_MSG_SOLICIT)
-                               syslog(LOG_NOTICE, "Send %s message (elapsed %llums, rc %d)",
-                                               retx->name, (unsigned long long)elapsed, rc);
+               switch (type) {
+               case DHCPV6_MSG_UNKNOWN:
+                       break;
+               default:
+                       syslog(LOG_NOTICE, "Send %s message (elapsed %llums, rc %d)",
+                                       retx->name, (unsigned long long)elapsed, rc);
+                       // Fall through
+               case DHCPV6_MSG_SOLICIT:
+               case DHCPV6_MSG_INFO_REQ:
                        dhcpv6_send(type, trid, elapsed / 10);
                        rc++;
                }
index 4605792..a71218c 100644 (file)
@@ -278,13 +278,14 @@ int main(_unused int argc, char* const argv[])
                odhcp6c_clear_state(STATE_NTP_FQDN);
                odhcp6c_clear_state(STATE_SIP_IP);
                odhcp6c_clear_state(STATE_SIP_FQDN);
-               dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
                bound = false;
 
                syslog(LOG_NOTICE, "(re)starting transaction on %s", ifname);
 
                signal_usr1 = signal_usr2 = false;
-               int mode = dhcpv6_request(DHCPV6_MSG_SOLICIT);
+               int mode = dhcpv6_set_ia_mode(ia_na_mode, ia_pd_mode);
+               if (mode != DHCPV6_STATELESS)
+                       mode = dhcpv6_request(DHCPV6_MSG_SOLICIT);
                odhcp6c_signal_process();
 
                if (mode < 0)
index fb572d0..c9a7398 100644 (file)
@@ -308,7 +308,7 @@ struct odhcp6c_request_prefix {
 };
 
 int init_dhcpv6(const char *ifname, unsigned int client_options, int sol_timeout);
-void 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);
 int dhcpv6_request(enum dhcpv6_msg type);
 int dhcpv6_poll_reconfigure(void);
 int dhcpv6_promote_server_cand(void);