diff options
author | Patrik Flykt <patrik.flykt@linux.intel.com> | 2014-06-19 15:39:53 +0300 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2014-06-19 15:44:44 +0300 |
commit | 7246333cb803b03440d3bd0bdaa233564d09b5ae (patch) | |
tree | 569fe17d15ae29cad27a9ab2548ca99b6eaa5280 | |
parent | c3e2adeaba8e043caed0ef139eeaea016bd152d0 (diff) |
sd-dhcp6-client: Add Request message sending
As described in RFC 3315, Section 17.1.2, a client has to wait until the
first timeout has elapsed before it is allowed to request IPv6 addresses
from the DHCPv6 server. This is indicated by a non-NULL lease and a
non-zero resend count. Should the Advertisement contain a preference
value of 255 or be received after the first timeout, IPv6 address
requesting is started immediately.
In response to these events, create a Request message and set up proper
resend timers to send the message to the server.
-rw-r--r-- | src/libsystemd-network/dhcp6-protocol.h | 4 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp6-client.c | 47 |
2 files changed, 48 insertions, 3 deletions
diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h index 1303a55a82..754e800088 100644 --- a/src/libsystemd-network/dhcp6-protocol.h +++ b/src/libsystemd-network/dhcp6-protocol.h @@ -54,6 +54,9 @@ enum { #define DHCP6_SOL_MAX_DELAY 1 * USEC_PER_SEC #define DHCP6_SOL_TIMEOUT 1 * USEC_PER_SEC #define DHCP6_SOL_MAX_RT 120 * USEC_PER_SEC +#define DHCP6_REQ_TIMEOUT 1 * USEC_PER_SEC +#define DHCP6_REQ_MAX_RT 120 * USEC_PER_SEC +#define DHCP6_REQ_MAX_RC 10 enum { DHCP6_DUID_LLT = 1, @@ -66,6 +69,7 @@ enum DHCP6State { DHCP6_STATE_STOPPED = 0, DHCP6_STATE_RS = 1, DHCP6_STATE_SOLICITATION = 2, + DHCP6_STATE_REQUEST = 3, }; enum { diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 1a59cc2861..55dd65c9eb 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -213,12 +213,22 @@ static int client_send_message(sd_dhcp6_client *client) { case DHCP6_STATE_SOLICITATION: message->type = DHCP6_SOLICIT; - r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID, - sizeof(client->duid), &client->duid); + r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na); if (r < 0) return r; - r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na); + break; + + case DHCP6_STATE_REQUEST: + message->type = DHCP6_REQUEST; + + r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID, + client->lease->serverid_len, + client->lease->serverid); + if (r < 0) + return r; + + r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia); if (r < 0) return r; @@ -229,6 +239,11 @@ static int client_send_message(sd_dhcp6_client *client) { return -EINVAL; } + r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID, + sizeof(client->duid), &client->duid); + if (r < 0) + return r; + r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message, len - optlen); if (r < 0) @@ -275,6 +290,12 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, switch (client->state) { case DHCP6_STATE_SOLICITATION: + + if (client->retransmit_count && client->lease) { + client_start(client, DHCP6_STATE_REQUEST); + return 0; + } + init_retransmit_time = DHCP6_SOL_TIMEOUT; max_retransmit_time = DHCP6_SOL_MAX_RT; max_retransmit_count = 0; @@ -282,6 +303,14 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, break; + case DHCP6_STATE_REQUEST: + init_retransmit_time = DHCP6_REQ_TIMEOUT; + max_retransmit_time = DHCP6_REQ_MAX_RT; + max_retransmit_count = DHCP6_REQ_MAX_RC; + max_retransmit_duration = 0; + + break; + case DHCP6_STATE_STOPPED: case DHCP6_STATE_RS: return 0; @@ -537,6 +566,9 @@ static int client_receive_advertise(sd_dhcp6_client *client, r = 0; } + if (pref_advertise == 255 || client->retransmit_count > 1) + r = DHCP6_STATE_REQUEST; + return r; } @@ -596,8 +628,12 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, case DHCP6_STATE_SOLICITATION: r = client_receive_advertise(client, message, len); + if (r == DHCP6_STATE_REQUEST) + client_start(client, r); + break; + case DHCP6_STATE_REQUEST: case DHCP6_STATE_STOPPED: case DHCP6_STATE_RS: return 0; @@ -655,6 +691,11 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) client->state = DHCP6_STATE_SOLICITATION; break; + + case DHCP6_STATE_REQUEST: + client->state = state; + + break; } client->transaction_id = random_u32() & htobe32(0x00ffffff); |