sd-dhcp6-client.c revision fa94c34b083b5b4019975624453e53d0cbad2a5d
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright (C) 2014 Intel Corporation. All rights reserved.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic const uint16_t default_req_opts[] = {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringconst char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST",
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidtconst char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure",
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available",
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt [DHCP6_STATUS_NO_BINDING] = "Binding unavailable",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering [DHCP6_STATUS_NOT_ON_LINK] = "Not on link",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering [DHCP6_STATUS_USE_MULTICAST] = "Use multicast",
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define _cleanup_dhcp6_client_unref_ _cleanup_(sd_dhcp6_client_unrefp)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define DHCP6_CLIENT_DONT_DESTROY(client) \
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_dhcp6_client_unref_ _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekint sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(client, -EINVAL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert_return(interface_index >= -1, -EINVAL);
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmekint sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek const struct ether_addr *mac_addr)
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek assert_return(client, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering memcpy(&client->mac_addr, mac_addr, sizeof(client->mac_addr));
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek memset(&client->mac_addr, 0x00, sizeof(client->mac_addr));
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekint sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(client, -EINVAL);
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek case DHCP6_OPTION_SNTP_SERVERS:
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek for (t = 0; t < client->req_opts_len; t++)
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (client->req_opts[t] == htobe16(option))
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek client->req_opts[client->req_opts_len++] = htobe16(option);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekint sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(client, -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek *ret = sd_dhcp6_lease_ref(client->lease);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekstatic void client_notify(sd_dhcp6_client *client, int event) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek client->cb(client, event, client->userdata);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int client_reset(sd_dhcp6_client *client) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek sd_event_source_unref(client->receive_message);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_event_source_unref(client->ia_na.timeout_t1);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt sd_event_source_unref(client->ia_na.timeout_t2);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek client->timeout_resend = sd_event_source_unref(client->timeout_resend);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek sd_event_source_unref(client->timeout_resend_expire);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek client->state = DHCP6_STATE_STOPPED;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void client_stop(sd_dhcp6_client *client, int error) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int client_send_message(sd_dhcp6_client *client) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_free_ DHCP6Message *message = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bcZbigniew Jędrzejewski-Szmek len = sizeof(DHCP6Message) + optlen;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek message->transaction_id = client->transaction_id;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (client->state == DHCP6_STATE_REQUEST)
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dhcp6_message_type_to_string(message->type));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int client_timeout_t2(sd_event_source *s, uint64_t usec,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(client, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(client->lease, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sd_event_source_unref(client->lease->ia.timeout_t2);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_dhcp6_client(client, "Timeout T2");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek client_start(client, DHCP6_STATE_REBIND);
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidtstatic int client_timeout_t1(sd_event_source *s, uint64_t usec,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sd_dhcp6_client *client = userdata;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sd_event_source_unref(client->lease->ia.timeout_t1);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_dhcp6_client(client, "Timeout T1");
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek client_start(client, DHCP6_STATE_RENEW);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sd_dhcp6_client *client = userdata;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek DHCP6_CLIENT_DONT_DESTROY(client);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek client_stop(client, DHCP6_EVENT_RESEND_EXPIRE);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek /* RFC 3315, section 18.1.4., says that "...the client may choose to
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek use a Solicit message to locate a new DHCP server..." */
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering client_start(client, DHCP6_STATE_SOLICITATION);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic usec_t client_timeout_compute_random(usec_t val) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekstatic int client_timeout_resend(sd_event_source *s, uint64_t usec,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek sd_dhcp6_client *client = userdata;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek uint8_t max_retransmit_count = 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek char time_string[FORMAT_TIMESPAN_MAX];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client->timeout_resend = sd_event_source_unref(client->timeout_resend);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (client->retransmit_count && client->lease) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering init_retransmit_time = DHCP6_SOL_TIMEOUT;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek init_retransmit_time = DHCP6_REN_TIMEOUT;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek max_retransmit_time = DHCP6_REN_MAX_RT;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek /* RFC 3315, section 18.1.3. says max retransmit duration will
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek be the remaining time until T2. Instead of setting MRD,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering wait for T2 to trigger with the same end result */
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek init_retransmit_time = DHCP6_REB_TIMEOUT;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek max_retransmit_time = DHCP6_REB_MAX_RT;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_lease_ia_rebind_expire(&client->lease->ia,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering max_retransmit_duration = expire * USEC_PER_SEC;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client->retransmit_count >= max_retransmit_count) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek client_stop(client, DHCP6_EVENT_RETRANS_MAX);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = client_send_message(client);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client_timeout_compute_random(init_retransmit_time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (client->state == DHCP6_STATE_SOLICITATION)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client->retransmit_time += init_retransmit_time / 10;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client->retransmit_time > max_retransmit_time / 2)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client->retransmit_time = client_timeout_compute_random(max_retransmit_time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client->retransmit_time += client_timeout_compute_random(client->retransmit_time);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_dhcp6_client(client, "Next retransmission in %s",
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering format_timespan(time_string, FORMAT_TIMESPAN_MAX,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_add_time(client->event, &client->timeout_resend,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering 10 * USEC_PER_MSEC, client_timeout_resend,
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering r = sd_event_source_set_priority(client->timeout_resend,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (max_retransmit_duration && !client->timeout_resend_expire) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_event_source_set_priority(client->timeout_resend_expire,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int client_ensure_iaid(sd_dhcp6_client *client) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* name is a pointer to memory in the udev_device struct, so must
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering have the same scope */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *device = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* not in a container, udev will be around */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering char ifindex_str[2 + DECIMAL_STR_MAX(int)];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sprintf(ifindex_str, "n%d", client->index);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering device = udev_device_new_from_device_id(udev, ifindex_str);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering if (udev_device_get_is_initialized(device) <= 0)
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering /* not yet ready */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering siphash24((uint8_t*)&id, name, strlen(name), HASH_KEY.bytes);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* fall back to mac address if no predictable name available */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering siphash24((uint8_t*)&id, &client->mac_addr, ETH_ALEN,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek /* fold into 32 bits */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering client->ia_na.id = (id & 0xffffffff) ^ (id >> 32);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic int client_parse_message(sd_dhcp6_client *client,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint8_t *optval, *option = (uint8_t *)(message + 1), *id = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_dhcp6_client(client, "%s contains multiple clientids",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dhcp6_message_type_to_string(message->type));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering memcmp(&client->duid, optval, optlen) != 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_dhcp6_client(client, "%s DUID does not match",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dhcp6_message_type_to_string(message->type));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_lease_get_serverid(lease, &id, &id_len);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r >= 0 && id) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_dhcp6_client(client, "%s contains multiple serverids",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dhcp6_message_type_to_string(message->type));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_lease_set_serverid(lease, optval, optlen);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = dhcp6_lease_set_preference(lease, *optval);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek status = optval[0] << 8 | optval[1];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dhcp6_message_type_to_string(message->type),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_option_parse_ia(&optval, &optlen, optcode,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0 && r != -ENOMSG)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = dhcp6_lease_get_iaid(lease, &iaid_lease);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering log_dhcp6_client(client, "%s has wrong IAID",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering dhcp6_message_type_to_string(message->type));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if ((r < 0 && r != -ENOMSG) || !clientid) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek log_dhcp6_client(client, "%s has incomplete options",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek dhcp6_message_type_to_string(message->type));
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = dhcp6_lease_get_serverid(lease, &id, &id_len);
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer log_dhcp6_client(client, "%s has no server id",
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek dhcp6_message_type_to_string(message->type));
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykrynstatic int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (reply->type != DHCP6_REPLY)
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = client_parse_message(client, reply, len, lease);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (client->state == DHCP6_STATE_SOLICITATION) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
if (!rapid_commit)
return DHCP6_STATE_BOUND;
r = DHCP6_STATE_REQUEST;
void *userdata) {
assert(s);
if (r < 0 || buflen <= 0)
if (!message)
return -ENOMEM;
case DHCP6_SOLICIT:
case DHCP6_REQUEST:
case DHCP6_CONFIRM:
case DHCP6_RENEW:
case DHCP6_REBIND:
case DHCP6_RELEASE:
case DHCP6_DECLINE:
case DHCP6_RELAY_FORW:
case DHCP6_RELAY_REPL:
case DHCP6_ADVERTISE:
case DHCP6_REPLY:
case DHCP6_RECONFIGURE:
case DHCP6_STATE_SOLICITATION:
if (r == DHCP6_STATE_REQUEST) {
case DHCP6_STATE_REQUEST:
case DHCP6_STATE_RENEW:
case DHCP6_STATE_REBIND:
if (r == DHCP6_STATE_BOUND) {
case DHCP6_STATE_BOUND:
case DHCP6_STATE_STOPPED:
switch (state) {
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_SOLICITATION:
client);
case DHCP6_STATE_REQUEST:
case DHCP6_STATE_RENEW:
case DHCP6_STATE_REBIND:
case DHCP6_STATE_BOUND:
timeout, 0));
client);
timeout, 0));
client);
client);
int priority)
if (event)
if (!client)
return NULL;
if (client)
return client;
return NULL;
return client;
size_t t;
if (!client)
return -ENOMEM;
return -ENOMEM;