From 0f72844fc537413df8595ad07ad6ce2b86989521 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Sat, 25 Apr 2015 20:52:57 +0500 Subject: [PATCH] Avoid of waiting for Advertise in stateless-only mode 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 | 24 +++++++++++++++++++----- src/odhcp6c.c | 5 +++-- src/odhcp6c.h | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index bc403b9..425aee1 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -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++; } diff --git a/src/odhcp6c.c b/src/odhcp6c.c index 4605792..a71218c 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -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) diff --git a/src/odhcp6c.h b/src/odhcp6c.h index fb572d0..c9a7398 100644 --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@ -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); -- 2.39.5