summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2014-06-25 14:06:02 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2014-06-26 16:10:38 +0300
commit3dc34fcc97b41f8b7b019027225b121dfbb9871d (patch)
tree2a8d04d48511917319db3bdef816eba7f79d5b2b /src/libsystemd-network
parent709d6710d047566c71f03e579a02c3d99fe15a3e (diff)
sd-dhcp6-client: Implement Renew and Rebind
Start sending Renew and Rebind DHCPv6 messages when respective timers T1 and T2 expire. Rebind messages do not include a Server ID option and the Rebind procedure ends when the last IPv6 address valid lifetime expires, whereafter the client restarts the address acquisition procedure by Soliciting for available servers. See RFC 3315, sections 18.1.3. and 18.1.4. for details.
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp6-protocol.h6
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c68
2 files changed, 73 insertions, 1 deletions
diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
index 37a8671a0..e9ae598b7 100644
--- a/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/libsystemd-network/dhcp6-protocol.h
@@ -57,6 +57,10 @@ enum {
#define DHCP6_REQ_TIMEOUT 1 * USEC_PER_SEC
#define DHCP6_REQ_MAX_RT 120 * USEC_PER_SEC
#define DHCP6_REQ_MAX_RC 10
+#define DHCP6_REN_TIMEOUT 10 * USEC_PER_SEC
+#define DHCP6_REN_MAX_RT 600 * USEC_PER_SEC
+#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC
+#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC
enum {
DHCP6_DUID_LLT = 1,
@@ -71,6 +75,8 @@ enum DHCP6State {
DHCP6_STATE_SOLICITATION = 2,
DHCP6_STATE_REQUEST = 3,
DHCP6_STATE_BOUND = 4,
+ DHCP6_STATE_RENEW = 5,
+ DHCP6_STATE_REBIND = 6,
};
enum {
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 5d65603dc..60d502fcb 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -259,7 +259,12 @@ static int client_send_message(sd_dhcp6_client *client) {
break;
case DHCP6_STATE_REQUEST:
- message->type = DHCP6_REQUEST;
+ case DHCP6_STATE_RENEW:
+
+ if (client->state == DHCP6_STATE_REQUEST)
+ message->type = DHCP6_REQUEST;
+ else
+ message->type = DHCP6_RENEW;
r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
client->lease->serverid_len,
@@ -273,6 +278,15 @@ static int client_send_message(sd_dhcp6_client *client) {
break;
+ case DHCP6_STATE_REBIND:
+ message->type = DHCP6_REBIND;
+
+ r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
+ if (r < 0)
+ return r;
+
+ break;
+
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
case DHCP6_STATE_BOUND:
@@ -314,6 +328,8 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec,
log_dhcp6_client(client, "Timeout T2");
+ client_start(client, DHCP6_STATE_REBIND);
+
return 0;
}
@@ -330,19 +346,30 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
log_dhcp6_client(client, "Timeout T1");
+ client_start(client, DHCP6_STATE_RENEW);
+
return 0;
}
static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
void *userdata) {
sd_dhcp6_client *client = userdata;
+ DHCP6_CLIENT_DONT_DESTROY(client);
+ enum DHCP6State state;
assert(s);
assert(client);
assert(client->event);
+ state = client->state;
+
client_stop(client, DHCP6_EVENT_RESEND_EXPIRE);
+ /* RFC 3315, section 18.1.4., says that "...the client may choose to
+ use a Solicit message to locate a new DHCP server..." */
+ if (state == DHCP6_STATE_REBIND)
+ client_start(client, DHCP6_STATE_SOLICITATION);
+
return 0;
}
@@ -359,6 +386,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
usec_t max_retransmit_duration;
uint8_t max_retransmit_count = 0;
char time_string[FORMAT_TIMESPAN_MAX];
+ uint32_t expire = 0;
assert(s);
assert(client);
@@ -389,6 +417,37 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
break;
+ case DHCP6_STATE_RENEW:
+ init_retransmit_time = DHCP6_REN_TIMEOUT;
+ max_retransmit_time = DHCP6_REN_MAX_RT;
+ max_retransmit_count = 0;
+
+ /* RFC 3315, section 18.1.3. says max retransmit duration will
+ be the remaining time until T2. Instead of setting MRD,
+ wait for T2 to trigger with the same end result */
+ max_retransmit_duration = 0;
+
+ break;
+
+ case DHCP6_STATE_REBIND:
+ init_retransmit_time = DHCP6_REB_TIMEOUT;
+ max_retransmit_time = DHCP6_REB_MAX_RT;
+ max_retransmit_count = 0;
+
+ max_retransmit_duration = 0;
+
+ if (!client->timeout_resend_expire) {
+ r = dhcp6_lease_ia_rebind_expire(&client->lease->ia,
+ &expire);
+ if (r < 0) {
+ client_stop(client, r);
+ return 0;
+ }
+ max_retransmit_duration = expire * USEC_PER_SEC;
+ }
+
+ break;
+
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
case DHCP6_STATE_BOUND:
@@ -740,6 +799,9 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
break;
case DHCP6_STATE_REQUEST:
+ case DHCP6_STATE_RENEW:
+ case DHCP6_STATE_REBIND:
+
r = client_receive_reply(client, message, len);
if (r < 0)
return 0;
@@ -822,6 +884,8 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
break;
case DHCP6_STATE_REQUEST:
+ case DHCP6_STATE_RENEW:
+ case DHCP6_STATE_REBIND:
client->state = state;
@@ -883,6 +947,8 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0)
return r;
+ client->state = state;
+
return 0;
}