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. --- src/libsystemd-network/dhcp6-protocol.h | 4 +++ 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 e8df509..a3a8be1 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 98835f7..312c84c 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -216,12 +216,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; @@ -232,6 +242,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) @@ -278,6 +293,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; @@ -285,6 +306,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; @@ -541,6 +570,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; } @@ -601,8 +633,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; @@ -660,6 +696,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); -- 1.9.1 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel