sd-dhcp6-client.c revision ed19c567e5fcdcec1a2b6dbac63787e001ad5d55
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/***
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
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
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
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/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering***/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering#include <errno.h>
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering#include <string.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/ioctl.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <linux/if_infiniband.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "udev.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "udev-util.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "util.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "random-util.h"
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "network-internal.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "sd-dhcp6-client.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "dhcp6-protocol.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "dhcp6-internal.h"
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack#include "dhcp6-lease-internal.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "dhcp-identifier.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstruct sd_dhcp6_client {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unsigned n_ref;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering enum DHCP6State state;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event *event;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int event_priority;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int index;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint8_t mac_addr[MAX_MAC_ADDR_LEN];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t mac_addr_len;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint16_t arp_type;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering DHCP6IA ia_na;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering be32_t transaction_id;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering usec_t transaction_start;
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering struct sd_dhcp6_lease *lease;
4f10118016f9b2fd7e1d26c9ef7d91eb33fba694Lennart Poettering int fd;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering bool information_request;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering be16_t *req_opts;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering size_t req_opts_allocated;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering size_t req_opts_len;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source *receive_message;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering usec_t retransmit_time;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering uint8_t retransmit_count;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source *timeout_resend;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source *timeout_resend_expire;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_dhcp6_client_cb_t cb;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering void *userdata;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering struct duid duid;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering size_t duid_len;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering};
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic const uint16_t default_req_opts[] = {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering DHCP6_OPTION_DNS_SERVERS,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering DHCP6_OPTION_DOMAIN_LIST,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering DHCP6_OPTION_NTP_SERVER,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering DHCP6_OPTION_SNTP_SERVERS,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering};
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringconst char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_SOLICIT] = "SOLICIT",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_ADVERTISE] = "ADVERTISE",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_REQUEST] = "REQUEST",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_CONFIRM] = "CONFIRM",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_RENEW] = "RENEW",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_REBIND] = "REBIND",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_REPLY] = "REPLY",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_RELEASE] = "RELEASE",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering [DHCP6_DECLINE] = "DECLINE",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering [DHCP6_RECONFIGURE] = "RECONFIGURE",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering [DHCP6_RELAY_FORW] = "RELAY-FORW",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering [DHCP6_RELAY_REPL] = "RELAY-REPL",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering};
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringconst char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering [DHCP6_STATUS_SUCCESS] = "Success",
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",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering};
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
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
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 Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(client, -EINVAL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->cb = cb;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->userdata = userdata;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(client, -EINVAL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(interface_index >= -1, -EINVAL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->index = interface_index;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_set_mac(
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_dhcp6_client *client,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const uint8_t *addr, size_t addr_len,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint16_t arp_type) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(addr, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(arp_type > 0, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (arp_type == ARPHRD_ETHER)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(addr_len == ETH_ALEN, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (arp_type == ARPHRD_INFINIBAND)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->mac_addr_len == addr_len &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcmp(&client->mac_addr, addr, addr_len) == 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcpy(&client->mac_addr, addr, addr_len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->mac_addr_len = addr_len;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->arp_type = arp_type;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_ensure_duid(sd_dhcp6_client *client) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->duid_len != 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack}
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_set_duid(
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack sd_dhcp6_client *client,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack uint16_t type,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack uint8_t *duid, size_t duid_len) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert_return(client, -EINVAL);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert_return(duid, -EINVAL);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch (type) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_DUID_LLT:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (duid_len <= sizeof(client->duid.llt))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_DUID_EN:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (duid_len != sizeof(client->duid.en))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_DUID_LL:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (duid_len <= sizeof(client->duid.ll))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_DUID_UUID:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (duid_len != sizeof(client->duid.uuid))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering default:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* accept unknown type in order to be forward compatible */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->duid.type = htobe16(type);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering memcpy(&client->duid.raw.data, duid, duid_len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->duid_len = duid_len + sizeof(client->duid.type);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, bool enabled) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->information_request = enabled;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, bool *enabled) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(enabled, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *enabled = client->information_request;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t t;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch(option) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_OPTION_DNS_SERVERS:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_OPTION_DOMAIN_LIST:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_OPTION_SNTP_SERVERS:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_OPTION_NTP_SERVER:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering default:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack for (t = 0; t < client->req_opts_len; t++)
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (client->req_opts[t] == htobe16(option))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EEXIST;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack client->req_opts_len + 1))
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering return -ENOMEM;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->req_opts[client->req_opts_len++] = htobe16(option);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(ret, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!client->lease)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ENOMSG;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *ret = client->lease;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void client_notify(sd_dhcp6_client *client, int event) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->cb)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->cb(client, event, client->userdata);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->lease) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_lease_clear_timers(&client->lease->ia);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_dhcp6_lease_unref(client->lease);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->lease = lease;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_reset(sd_dhcp6_client *client) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_set_lease(client, NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->receive_message =
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->receive_message);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->fd = safe_close(client->fd);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->transaction_id = 0;
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek client->transaction_start = 0;
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek client->ia_na.timeout_t1 =
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->ia_na.timeout_t1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->ia_na.timeout_t2 =
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->ia_na.timeout_t2);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_time = 0;
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek client->retransmit_count = 0;
8f077bf94e129fa1b6f0159e3140c4326f1066cfZbigniew Jędrzejewski-Szmek client->timeout_resend = sd_event_source_unref(client->timeout_resend);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt client->timeout_resend_expire =
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt sd_event_source_unref(client->timeout_resend_expire);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->state = DHCP6_STATE_STOPPED;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void client_stop(sd_dhcp6_client *client, int error) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering DHCP6_CLIENT_DONT_DESTROY(client);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(client);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_notify(client, error);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_reset(client);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_free_ DHCP6Message *message = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering struct in6_addr all_servers =
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t len, optlen = 512;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint8_t *opt;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering usec_t elapsed_usec;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering be16_t elapsed_time;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering len = sizeof(DHCP6Message) + optlen;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message = malloc0(len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!message)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ENOMEM;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering opt = (uint8_t *)(message + 1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message->transaction_id = client->transaction_id;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch(client->state) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_INFORMATION_REQUEST:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message->type = DHCP6_INFORMATION_REQUEST;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_STATE_SOLICITATION:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering message->type = DHCP6_SOLICIT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append(&opt, &optlen,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_REQUEST:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_RENEW:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_REQUEST)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message->type = DHCP6_REQUEST;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message->type = DHCP6_RENEW;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->lease->serverid_len,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->lease->serverid);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_STATE_REBIND:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering message->type = DHCP6_REBIND;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_STATE_STOPPED:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_STATE_BOUND:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -EINVAL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->req_opts_len * sizeof(be16_t),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->req_opts);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert (client->duid_len);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->duid_len, &client->duid);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
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 else
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering elapsed_time = 0xffff;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sizeof(elapsed_time), &elapsed_time);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering len - optlen);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_dhcp6_client(client, "Sent %s",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_timeout_t2(sd_event_source *s, uint64_t usec,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering void *userdata) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_dhcp6_client *client = userdata;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(s, -EINVAL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->lease, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->lease->ia.timeout_t2 =
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(client->lease->ia.timeout_t2);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_dhcp6_client(client, "Timeout T2");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_start(client, DHCP6_STATE_REBIND);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
db2cb23b5b179707000d28a11efb3d888d06ee80Umut Tezduyar Lindskog
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_timeout_t1(sd_event_source *s, uint64_t usec,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering void *userdata) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_dhcp6_client *client = userdata;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt assert_return(s, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->lease, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->lease->ia.timeout_t1 =
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source_unref(client->lease->ia.timeout_t1);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt log_dhcp6_client(client, "Timeout T1");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_start(client, DHCP6_STATE_RENEW);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering void *userdata) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_dhcp6_client *client = userdata;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering DHCP6_CLIENT_DONT_DESTROY(client);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering enum DHCP6State state;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(s);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(client);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(client->event);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering state = client->state;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
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..." */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (state == DHCP6_STATE_REBIND)
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt client_start(client, DHCP6_STATE_SOLICITATION);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return 0;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack}
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mackstatic usec_t client_timeout_compute_random(usec_t val) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return val - val / 10 +
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_timeout_resend(sd_event_source *s, uint64_t usec,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering void *userdata) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_dhcp6_client *client = userdata;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering usec_t max_retransmit_duration = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering uint8_t max_retransmit_count = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering char time_string[FORMAT_TIMESPAN_MAX];
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering uint32_t expire = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(s);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(client);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(client->event);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
8d0e0ddda6501479eb69164687c83c1a7667b33aJan Engelhardt client->timeout_resend = sd_event_source_unref(client->timeout_resend);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering switch (client->state) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_STATE_INFORMATION_REQUEST:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering init_retransmit_time = DHCP6_INF_TIMEOUT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering max_retransmit_time = DHCP6_INF_MAX_RT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_STATE_SOLICITATION:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (client->retransmit_count && client->lease) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_start(client, DHCP6_STATE_REQUEST);
8d0e0ddda6501479eb69164687c83c1a7667b33aJan Engelhardt return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering init_retransmit_time = DHCP6_SOL_TIMEOUT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering max_retransmit_time = DHCP6_SOL_MAX_RT;
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_STATE_REQUEST:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering init_retransmit_time = DHCP6_REQ_TIMEOUT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering max_retransmit_time = DHCP6_REQ_MAX_RT;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering max_retransmit_count = DHCP6_REQ_MAX_RC;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_RENEW:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering init_retransmit_time = DHCP6_REN_TIMEOUT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering max_retransmit_time = DHCP6_REN_MAX_RT;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
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
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_REBIND:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering init_retransmit_time = DHCP6_REB_TIMEOUT;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack max_retransmit_time = DHCP6_REB_MAX_RT;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (!client->timeout_resend_expire) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_lease_ia_rebind_expire(&client->lease->ia,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering &expire);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_stop(client, r);
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering return 0;
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering }
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering max_retransmit_duration = expire * USEC_PER_SEC;
ff975efb2e88dcd5221a2f0d76c4c87e85b821a8Lennart Poettering }
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_STOPPED:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_BOUND:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (max_retransmit_count &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_count >= max_retransmit_count) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_stop(client, SD_DHCP6_CLIENT_EVENT_RETRANS_MAX);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto error;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_send_message(client, time_now);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r >= 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_count++;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!client->retransmit_time) {
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering client->retransmit_time =
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_timeout_compute_random(init_retransmit_time);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_SOLICITATION)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_time += init_retransmit_time / 10;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (max_retransmit_time &&
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->retransmit_time > max_retransmit_time / 2)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->retransmit_time = client_timeout_compute_random(max_retransmit_time);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering else
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->retransmit_time += client_timeout_compute_random(client->retransmit_time);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
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
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_add_time(client->event, &client->timeout_resend,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack clock_boottime_or_monotonic(),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering time_now + client->retransmit_time,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering 10 * USEC_PER_MSEC, client_timeout_resend,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto error;
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_priority(client->timeout_resend,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->event_priority);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto error;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto error;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (max_retransmit_duration && !client->timeout_resend_expire) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering max_retransmit_duration / USEC_PER_SEC);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_add_time(client->event,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering &client->timeout_resend_expire,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering clock_boottime_or_monotonic(),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering time_now + max_retransmit_duration,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering USEC_PER_SEC,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_timeout_resend_expire, client);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto error;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_source_set_priority(client->timeout_resend_expire,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->event_priority);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto error;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer");
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering goto error;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringerror:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_stop(client, r);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_ensure_iaid(sd_dhcp6_client *client) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(client);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (client->ia_na.id)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->ia_na.id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_parse_message(sd_dhcp6_client *client,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering DHCP6Message *message, size_t len,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_dhcp6_lease *lease) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint8_t *optval, *option, *id = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uint16_t optcode, status;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t optlen, id_len;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bool clientid = false;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering be32_t iaid_lease;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering option = (uint8_t *)message + sizeof(DHCP6Message);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering len -= sizeof(DHCP6Message);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering &optval)) >= 0) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch (optcode) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_OPTION_CLIENTID:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (clientid) {
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering log_dhcp6_client(client, "%s contains multiple clientids",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (optlen != client->duid_len ||
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
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering clientid = true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_OPTION_SERVERID:
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));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering r = dhcp6_lease_set_serverid(lease, optval, optlen);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering case DHCP6_OPTION_PREFERENCE:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (optlen != 1)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_lease_set_preference(lease, *optval);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_OPTION_STATUS_CODE:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (optlen < 2)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering status = optval[0] << 8 | optval[1];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (status) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "%s Status %s",
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering dhcp6_message_type_to_string(message->type),
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering dhcp6_message_status_to_string(status));
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann return -EINVAL;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
e24e415e5f3af2fe86d2be9a1f1a2e8d5f8c96bfDaniel Mack break;
e24e415e5f3af2fe86d2be9a1f1a2e8d5f8c96bfDaniel Mack
e24e415e5f3af2fe86d2be9a1f1a2e8d5f8c96bfDaniel Mack case DHCP6_OPTION_IA_NA:
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering log_dhcp6_client(client, "Information request ignoring IA NA option");
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering break;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_option_parse_ia(&optval, &optlen, optcode,
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering &lease->ia);
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering if (r < 0 && r != -ENOMSG)
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering return r;
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering r = dhcp6_lease_get_iaid(lease, &iaid_lease);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering if (client->ia_na.id != iaid_lease) {
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering log_dhcp6_client(client, "%s has wrong IAID",
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering dhcp6_message_type_to_string(message->type));
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering return -EINVAL;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering break;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering case DHCP6_OPTION_RAPID_COMMIT:
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_lease_set_rapid_commit(lease);
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering break;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering case DHCP6_OPTION_DNS_SERVERS:
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_lease_set_dns(lease, optval, optlen);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering break;
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann case DHCP6_OPTION_DOMAIN_LIST:
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann r = dhcp6_lease_set_domains(lease, optval, optlen);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering break;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering case DHCP6_OPTION_NTP_SERVER:
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_lease_set_ntp(lease, optval, optlen);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering break;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering case DHCP6_OPTION_SNTP_SERVERS:
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering r = dhcp6_lease_set_sntp(lease, optval, optlen);
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering break;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering if (r == -ENOMSG)
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering r = 0;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
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));
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return -EINVAL;
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
94e15fdc4d9d96fa6607bfb4eaaea164a3aec417David Herrmann if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
dcc2fc01fa850e9ee36c549dc2691e7e5c71bebfLennart Poettering r = dhcp6_lease_get_serverid(lease, &id, &id_len);
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering log_dhcp6_client(client, "%s has no server id",
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering dhcp6_message_type_to_string(message->type));
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering }
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering int r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bool rapid_commit;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (reply->type != DHCP6_REPLY)
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_lease_new(&lease);
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -ENOMEM;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_parse_message(client, reply, len, lease);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
bd5f920f1288c0d4d488629fadf067f709227030Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_SOLICITATION) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!rapid_commit)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_set_lease(client, lease);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering lease = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return DHCP6_STATE_BOUND;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering uint8_t pref_advertise = 0, pref_lease = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (advertise->type != DHCP6_ADVERTISE)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_lease_new(&lease);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
deffddf1df29a5ed047feff3a0f2b765006fb71bLukas Nykryn return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = client_parse_message(client, advertise, len, lease);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering r = dhcp6_lease_get_preference(lease, &pref_advertise);
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = dhcp6_lease_get_preference(client->lease, &pref_lease);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0 || pref_advertise > pref_lease) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_set_lease(client, lease);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering lease = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (pref_advertise == 255 || client->retransmit_count > 1)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = DHCP6_STATE_REQUEST;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_dhcp6_client *client = userdata;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering DHCP6_CLIENT_DONT_DESTROY(client);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering _cleanup_free_ DHCP6Message *message;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r, buflen, len;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(s);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(client);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(client->event);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = ioctl(fd, FIONREAD, &buflen);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0 || buflen <= 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering buflen = DHCP6_MIN_OPTIONS_SIZE;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering message = malloc0(buflen);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!message)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -ENOMEM;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering len = read(fd, message, buflen);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if ((size_t)len < sizeof(DHCP6Message)) {
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering log_dhcp6_client(client, "could not receive message from UDP socket: %m");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering switch(message->type) {
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering case DHCP6_SOLICIT:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_REQUEST:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_CONFIRM:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_RENEW:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_REBIND:
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering case DHCP6_RELEASE:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_DECLINE:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_INFORMATION_REQUEST:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_RELAY_FORW:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_RELAY_REPL:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_ADVERTISE:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_REPLY:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case DHCP6_RECONFIGURE:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering default:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "unknown message type %d",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering message->type);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->transaction_id != (message->transaction_id &
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering htobe32(0x00ffffff)))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch (client->state) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_INFORMATION_REQUEST:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_receive_reply(client, message, len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_notify(client, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client_start(client, DHCP6_STATE_STOPPED);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_SOLICITATION:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = client_receive_advertise(client, message, len);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering if (r == DHCP6_STATE_REQUEST) {
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering client_start(client, r);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering break;
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering }
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering /* fall through for Soliciation Rapid Commit option check */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_REQUEST:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_RENEW:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_REBIND:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = client_receive_reply(client, message, len);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r == DHCP6_STATE_BOUND) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = client_start(client, DHCP6_STATE_BOUND);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_stop(client, r);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client_notify(client, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering case DHCP6_STATE_BOUND:
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering break;
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering case DHCP6_STATE_STOPPED:
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering return 0;
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering }
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering if (r >= 0) {
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering log_dhcp6_client(client, "Recv %s",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering dhcp6_message_type_to_string(message->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering usec_t timeout, time_now;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char time_string[FORMAT_TIMESPAN_MAX];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->event, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->index > 0, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_return(client->state != state, -EINVAL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->timeout_resend_expire =
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source_unref(client->timeout_resend_expire);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->timeout_resend = sd_event_source_unref(client->timeout_resend);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->retransmit_time = 0;
700ff4d97311902a440109a2c081731ab6ae8a20Lennart Poettering client->retransmit_count = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch (state) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_STOPPED:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->state = DHCP6_STATE_STOPPED;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* fall through */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_SOLICITATION:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->state = DHCP6_STATE_SOLICITATION;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_INFORMATION_REQUEST:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_REQUEST:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_RENEW:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_REBIND:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering client->state = state;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case DHCP6_STATE_BOUND:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (client->lease->ia.lifetime_t1 == 0xffffffff ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->lease->ia.lifetime_t2 == 0xffffffff) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_dhcp6_client(client, "infinite T1 0x%08x or T2 0x%08x",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering be32toh(client->lease->ia.lifetime_t1),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering be32toh(client->lease->ia.lifetime_t2));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC);
0faacd470dfbd24f4c6504da6f04213aa05f9d19Lennart Poettering
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
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_add_time(client->event,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering &client->lease->ia.timeout_t1,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering clock_boottime_or_monotonic(), time_now + timeout,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering 10 * USEC_PER_SEC, client_timeout_t1,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering client->event_priority);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
if (r < 0)
return r;
timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC);
log_dhcp6_client(client, "T2 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
&client->lease->ia.timeout_t2,
clock_boottime_or_monotonic(), time_now + timeout,
10 * USEC_PER_SEC, client_timeout_t2,
client);
if (r < 0)
return r;
r = sd_event_source_set_priority(client->lease->ia.timeout_t2,
client->event_priority);
if (r < 0)
return r;
r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
if (r < 0)
return r;
client->state = state;
return 0;
}
client->transaction_id = random_u32() & htobe32(0x00ffffff);
client->transaction_start = time_now;
r = sd_event_add_time(client->event, &client->timeout_resend,
clock_boottime_or_monotonic(), 0, 0, client_timeout_resend,
client);
if (r < 0)
return r;
r = sd_event_source_set_priority(client->timeout_resend,
client->event_priority);
if (r < 0)
return r;
r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout");
if (r < 0)
return r;
return 0;
}
int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP);
return 0;
}
int sd_dhcp6_client_start(sd_dhcp6_client *client) {
int r = 0;
enum DHCP6State state = DHCP6_STATE_SOLICITATION;
assert_return(client, -EINVAL);
assert_return(client->event, -EINVAL);
assert_return(client->index > 0, -EINVAL);
if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
return -EALREADY;
r = client_reset(client);
if (r < 0)
return r;
r = client_ensure_iaid(client);
if (r < 0)
return r;
r = client_ensure_duid(client);
if (r < 0)
return r;
r = dhcp6_network_bind_udp_socket(client->index, NULL);
if (r < 0)
return r;
client->fd = r;
r = sd_event_add_io(client->event, &client->receive_message,
client->fd, EPOLLIN, client_receive_message,
client);
if (r < 0)
goto error;
r = sd_event_source_set_priority(client->receive_message,
client->event_priority);
if (r < 0)
goto error;
r = sd_event_source_set_description(client->receive_message,
"dhcp6-receive-message");
if (r < 0)
goto error;
if (client->information_request)
state = DHCP6_STATE_INFORMATION_REQUEST;
log_dhcp6_client(client, "Started in %s mode",
client->information_request? "Information request":
"Managed");
return client_start(client, state);
error:
client_reset(client);
return r;
}
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) {
int r;
assert_return(client, -EINVAL);
assert_return(!client->event, -EBUSY);
if (event)
client->event = sd_event_ref(event);
else {
r = sd_event_default(&client->event);
if (r < 0)
return 0;
}
client->event_priority = priority;
return 0;
}
int sd_dhcp6_client_detach_event(sd_dhcp6_client *client) {
assert_return(client, -EINVAL);
client->event = sd_event_unref(client->event);
return 0;
}
sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
if (!client)
return NULL;
return client->event;
}
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
if (!client)
return NULL;
assert(client->n_ref >= 1);
client->n_ref++;
return client;
}
sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
if (!client)
return NULL;
assert(client->n_ref >= 1);
client->n_ref--;
if (client->n_ref > 0)
return NULL;
client_reset(client);
sd_dhcp6_client_detach_event(client);
free(client->req_opts);
free(client);
return NULL;
}
int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
_cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
size_t t;
assert_return(ret, -EINVAL);
client = new0(sd_dhcp6_client, 1);
if (!client)
return -ENOMEM;
client->n_ref = 1;
client->ia_na.type = DHCP6_OPTION_IA_NA;
client->index = -1;
client->fd = -1;
client->req_opts_len = ELEMENTSOF(default_req_opts);
client->req_opts = new0(be16_t, client->req_opts_len);
if (!client->req_opts)
return -ENOMEM;
for (t = 0; t < client->req_opts_len; t++)
client->req_opts[t] = htobe16(default_req_opts[t]);
*ret = client;
client = NULL;
return 0;
}