sd-dhcp6-client.c revision ed19c567e5fcdcec1a2b6dbac63787e001ad5d55
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic const uint16_t default_req_opts[] = {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringconst char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringconst char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_STATUS_NO_BINDING] = "Binding unavailable",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_STATUS_NOT_ON_LINK] = "Not on link",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering [DHCP6_STATUS_USE_MULTICAST] = "Use multicast",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#define _cleanup_dhcp6_client_unref_ _cleanup_(sd_dhcp6_client_unrefp)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#define DHCP6_CLIENT_DONT_DESTROY(client) \
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_dhcp6_client_unref_ _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(interface_index >= -1, -EINVAL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(addr_len == ETH_ALEN, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcmp(&client->mac_addr, addr, addr_len) == 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcpy(&client->mac_addr, addr, addr_len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_ensure_duid(sd_dhcp6_client *client) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (duid_len <= sizeof(client->duid.llt))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (duid_len != sizeof(client->duid.uuid))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* accept unknown type in order to be forward compatible */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcpy(&client->duid.raw.data, duid, duid_len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->duid_len = duid_len + sizeof(client->duid.type);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, bool enabled) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, bool *enabled) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (client->req_opts[t] == htobe16(option))
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->req_opts[client->req_opts_len++] = htobe16(option);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void client_notify(sd_dhcp6_client *client, int event) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->cb(client, event, client->userdata);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_lease_clear_timers(&client->lease->ia);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_reset(sd_dhcp6_client *client) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->receive_message);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->ia_na.timeout_t1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->ia_na.timeout_t2);
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek client->timeout_resend = sd_event_source_unref(client->timeout_resend);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt sd_event_source_unref(client->timeout_resend_expire);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void client_stop(sd_dhcp6_client *client, int error) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ DHCP6Message *message = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message->transaction_id = client->transaction_id;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message->type = DHCP6_INFORMATION_REQUEST;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_REQUEST)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID,
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt elapsed_usec = time_now - client->transaction_start;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_timeout_t2(sd_event_source *s, uint64_t usec,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->lease->ia.timeout_t2);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_start(client, DHCP6_STATE_REBIND);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_timeout_t1(sd_event_source *s, uint64_t usec,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source_unref(client->lease->ia.timeout_t1);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* RFC 3315, section 18.1.4., says that "...the client may choose to
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack use a Solicit message to locate a new DHCP server..." */
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt client_start(client, DHCP6_STATE_SOLICITATION);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mackstatic usec_t client_timeout_compute_random(usec_t val) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_timeout_resend(sd_event_source *s, uint64_t usec,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
8d0e0ddda6501479eb69164687c83c1a7667b33aJan Engelhardt client->timeout_resend = sd_event_source_unref(client->timeout_resend);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering init_retransmit_time = DHCP6_INF_TIMEOUT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (client->retransmit_count && client->lease) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_start(client, DHCP6_STATE_REQUEST);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering init_retransmit_time = DHCP6_SOL_TIMEOUT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering init_retransmit_time = DHCP6_REQ_TIMEOUT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering init_retransmit_time = DHCP6_REN_TIMEOUT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* RFC 3315, section 18.1.3. says max retransmit duration will
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering be the remaining time until T2. Instead of setting MRD,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering wait for T2 to trigger with the same end result */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering init_retransmit_time = DHCP6_REB_TIMEOUT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_lease_ia_rebind_expire(&client->lease->ia,
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering max_retransmit_duration = expire * USEC_PER_SEC;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_count >= max_retransmit_count) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_stop(client, SD_DHCP6_CLIENT_EVENT_RETRANS_MAX);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_send_message(client, time_now);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_timeout_compute_random(init_retransmit_time);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_SOLICITATION)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_time += init_retransmit_time / 10;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_time > max_retransmit_time / 2)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->retransmit_time = client_timeout_compute_random(max_retransmit_time);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->retransmit_time += client_timeout_compute_random(client->retransmit_time);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_dhcp6_client(client, "Next retransmission in %s",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_add_time(client->event, &client->timeout_resend,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering 10 * USEC_PER_MSEC, client_timeout_resend,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_priority(client->timeout_resend,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (max_retransmit_duration && !client->timeout_resend_expire) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_source_set_priority(client->timeout_resend_expire,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_ensure_iaid(sd_dhcp6_client *client) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->ia_na.id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_parse_message(sd_dhcp6_client *client,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering option = (uint8_t *)message + sizeof(DHCP6Message);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering log_dhcp6_client(client, "%s contains multiple clientids",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcmp(&client->duid, optval, optlen) != 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "%s DUID does not match",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering r = dhcp6_lease_get_serverid(lease, &id, &id_len);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r >= 0 && id) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_dhcp6_client(client, "%s contains multiple serverids",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering r = dhcp6_lease_set_serverid(lease, optval, optlen);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_lease_set_preference(lease, *optval);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering dhcp6_message_type_to_string(message->type),
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering log_dhcp6_client(client, "Information request ignoring IA NA option");
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_option_parse_ia(&optval, &optlen, optcode,
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering if (r < 0 && r != -ENOMSG)
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering r = dhcp6_lease_get_iaid(lease, &iaid_lease);
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering log_dhcp6_client(client, "%s has wrong IAID",
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering dhcp6_message_type_to_string(message->type));
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_lease_set_dns(lease, optval, optlen);
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann r = dhcp6_lease_set_domains(lease, optval, optlen);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_lease_set_ntp(lease, optval, optlen);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_lease_set_sntp(lease, optval, optlen);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0 || !clientid) {
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering log_dhcp6_client(client, "%s has incomplete options",
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering dhcp6_message_type_to_string(message->type));
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering r = dhcp6_lease_get_serverid(lease, &id, &id_len);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering log_dhcp6_client(client, "%s has no server id",
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering dhcp6_message_type_to_string(message->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_parse_message(client, reply, len, lease);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_SOLICITATION) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering uint8_t pref_advertise = 0, pref_lease = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = client_parse_message(client, advertise, len, lease);
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering r = dhcp6_lease_get_preference(lease, &pref_advertise);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_lease_get_preference(client->lease, &pref_lease);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0 || pref_advertise > pref_lease) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (pref_advertise == 255 || client->retransmit_count > 1)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0 || buflen <= 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if ((size_t)len < sizeof(DHCP6Message)) {
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering log_dhcp6_client(client, "could not receive message from UDP socket: %m");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "unknown message type %d",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->transaction_id != (message->transaction_id &
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_receive_reply(client, message, len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_notify(client, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_start(client, DHCP6_STATE_STOPPED);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_receive_advertise(client, message, len);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering /* fall through for Soliciation Rapid Commit option check */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = client_receive_reply(client, message, len);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = client_start(client, DHCP6_STATE_BOUND);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_notify(client, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->index > 0, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->state != state, -EINVAL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source_unref(client->timeout_resend_expire);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->timeout_resend = sd_event_source_unref(client->timeout_resend);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* fall through */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->state = DHCP6_STATE_SOLICITATION;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->lease->ia.lifetime_t1 == 0xffffffff ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->lease->ia.lifetime_t2 == 0xffffffff) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "infinite T1 0x%08x or T2 0x%08x",
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "T1 expires in %s",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering clock_boottime_or_monotonic(), time_now + timeout,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
client);
client);
return -EALREADY;
client);
goto error;
goto error;
goto error;
if (event)
if (!client)
return NULL;
if (!client)
return NULL;
return client;
if (!client)
return NULL;
return NULL;
return NULL;
size_t t;
if (!client)
return -ENOMEM;
return -ENOMEM;