summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVladislav Grishenko <themiron@mail.ru>2015-04-25 20:52:57 +0500
committerVladislav Grishenko <themiron@mail.ru>2015-04-25 21:00:46 +0500
commit0f72844fc537413df8595ad07ad6ce2b86989521 (patch)
tree4f7dd2663d5268dab06885fab3d0f9c247afb529 /src
parentb5f6ace7148fda6bf336758d2544a23a90d845bf (diff)
downloadodhcp6c-0f72844fc537413df8595ad07ad6ce2b86989521.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/dhcpv6.c24
-rw-r--r--src/odhcp6c.c5
-rw-r--r--src/odhcp6c.h2
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);