1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-12 09:17:44 +03:00

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.
This commit is contained in:
Patrik Flykt 2014-06-25 14:06:02 +03:00
parent 709d6710d0
commit 3dc34fcc97
2 changed files with 73 additions and 1 deletions

View File

@ -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 {

View File

@ -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;
}