139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/***
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt***/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <errno.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <string.h>
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt#include <sys/ioctl.h>
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#include <linux/if_infiniband.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "sd-dhcp6-client.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "dhcp-identifier.h"
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include "dhcp6-internal.h"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt#include "dhcp6-lease-internal.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "dhcp6-protocol.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen#include "in-addr-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "network-internal.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "random-util.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "string-table.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "util.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstruct sd_dhcp6_client {
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering unsigned n_ref;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt enum DHCP6State state;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt sd_event *event;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt int event_priority;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt int index;
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen struct in6_addr local_address;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams uint8_t mac_addr[MAX_MAC_ADDR_LEN];
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams size_t mac_addr_len;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams uint16_t arp_type;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt DHCP6IA ia_na;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt be32_t transaction_id;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt usec_t transaction_start;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt struct sd_dhcp6_lease *lease;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int fd;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt bool information_request;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt be16_t *req_opts;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt size_t req_opts_allocated;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt size_t req_opts_len;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt sd_event_source *receive_message;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt usec_t retransmit_time;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt uint8_t retransmit_count;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_source *timeout_resend;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_source *timeout_resend_expire;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt sd_dhcp6_client_cb_t cb;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt void *userdata;
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen struct duid duid;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams size_t duid_len;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt};
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic const uint16_t default_req_opts[] = {
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani SD_DHCP6_OPTION_DNS_SERVERS,
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani SD_DHCP6_OPTION_DOMAIN_LIST,
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani SD_DHCP6_OPTION_NTP_SERVER,
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani SD_DHCP6_OPTION_SNTP_SERVERS,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt};
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktconst char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_SOLICIT] = "SOLICIT",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_ADVERTISE] = "ADVERTISE",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_REQUEST] = "REQUEST",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_CONFIRM] = "CONFIRM",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_RENEW] = "RENEW",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_REBIND] = "REBIND",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_REPLY] = "REPLY",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_RELEASE] = "RELEASE",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_DECLINE] = "DECLINE",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_RECONFIGURE] = "RECONFIGURE",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_RELAY_FORW] = "RELAY-FORW",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt [DHCP6_RELAY_REPL] = "RELAY-REPL",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt};
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik FlyktDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktconst char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt [DHCP6_STATUS_SUCCESS] = "Success",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt [DHCP6_STATUS_NO_BINDING] = "Binding unavailable",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt [DHCP6_STATUS_NOT_ON_LINK] = "Not on link",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt [DHCP6_STATUS_USE_MULTICAST] = "Use multicast",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt};
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik FlyktDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt#define DHCP6_CLIENT_DONT_DESTROY(client) \
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flyktstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->cb = cb;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->userdata = userdata;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(interface_index >= -1, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->index = interface_index;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersenint sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) {
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen assert_return(client, -EINVAL);
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen assert_return(local_address, -EINVAL);
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL);
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen client->local_address = *local_address;
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen return 0;
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen}
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_set_mac(
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering sd_dhcp6_client *client,
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering const uint8_t *addr, size_t addr_len,
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering uint16_t arp_type) {
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client, -EINVAL);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams assert_return(addr, -EINVAL);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams assert_return(arp_type > 0, -EINVAL);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (arp_type == ARPHRD_ETHER)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams assert_return(addr_len == ETH_ALEN, -EINVAL);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams else if (arp_type == ARPHRD_INFINIBAND)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt else
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams return -EINVAL;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (client->mac_addr_len == addr_len &&
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams memcmp(&client->mac_addr, addr, addr_len) == 0)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams return 0;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams memcpy(&client->mac_addr, addr, addr_len);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams client->mac_addr_len = addr_len;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams client->arp_type = arp_type;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringstatic int client_ensure_duid(sd_dhcp6_client *client) {
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller if (client->duid_len != 0)
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller return 0;
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller}
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_set_duid(
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering sd_dhcp6_client *client,
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering uint16_t type,
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering uint8_t *duid, size_t duid_len) {
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams assert_return(client, -EINVAL);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams assert_return(duid, -EINVAL);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen switch (type) {
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen case DHCP6_DUID_LLT:
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen if (duid_len <= sizeof(client->duid.llt))
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return -EINVAL;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen break;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen case DHCP6_DUID_EN:
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen if (duid_len != sizeof(client->duid.en))
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return -EINVAL;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen break;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen case DHCP6_DUID_LL:
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen if (duid_len <= sizeof(client->duid.ll))
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return -EINVAL;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen break;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen case DHCP6_DUID_UUID:
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen if (duid_len != sizeof(client->duid.uuid))
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return -EINVAL;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen break;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen default:
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen /* accept unknown type in order to be forward compatible */
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen break;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen }
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen client->duid.type = htobe16(type);
ebe207d4acf38165adbc45298662982eecdb9e9fTom Gundersen memcpy(&client->duid.raw.data, duid, duid_len);
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen client->duid_len = duid_len + sizeof(client->duid.type);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams return 0;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams}
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
04c0136989b7eb896bfb0fb176e11233d69e1453Lennart Poetteringint sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt assert_return(client, -EINVAL);
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client->information_request = enabled;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt}
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
04c0136989b7eb896bfb0fb176e11233d69e1453Lennart Poetteringint sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt assert_return(client, -EINVAL);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt assert_return(enabled, -EINVAL);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt *enabled = client->information_request;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt}
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt size_t t;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert_return(client, -EINVAL);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt switch(option) {
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_DNS_SERVERS:
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_DOMAIN_LIST:
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_SNTP_SERVERS:
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_NTP_SERVER:
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt break;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt default:
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return -EINVAL;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt }
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (t = 0; t < client->req_opts_len; t++)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (client->req_opts[t] == htobe16(option))
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return -EEXIST;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt client->req_opts_len + 1))
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return -ENOMEM;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt client->req_opts[client->req_opts_len++] = htobe16(option);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return 0;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flyktint sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt assert_return(client, -EINVAL);
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt if (!client->lease)
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt return -ENOMSG;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
3098562c9236fe0bd3e7d950b6c53907304d277fTom Gundersen if (ret)
3098562c9236fe0bd3e7d950b6c53907304d277fTom Gundersen *ret = client->lease;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt return 0;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt}
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flyktstatic void client_notify(sd_dhcp6_client *client, int event) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt if (client->cb)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->cb(client, event, client->userdata);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Hallerstatic void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) {
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt if (client->lease) {
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt dhcp6_lease_clear_timers(&client->lease->ia);
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller sd_dhcp6_lease_unref(client->lease);
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt }
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller client->lease = lease;
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller}
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Hallerstatic int client_reset(sd_dhcp6_client *client) {
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller assert_return(client, -EINVAL);
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller client_set_lease(client, NULL);
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt client->receive_message =
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt sd_event_source_unref(client->receive_message);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek client->fd = safe_close(client->fd);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt client->transaction_id = 0;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt client->transaction_start = 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt client->ia_na.timeout_t1 =
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt sd_event_source_unref(client->ia_na.timeout_t1);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt client->ia_na.timeout_t2 =
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt sd_event_source_unref(client->ia_na.timeout_t2);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->retransmit_time = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->retransmit_count = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->timeout_resend = sd_event_source_unref(client->timeout_resend);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->timeout_resend_expire =
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_source_unref(client->timeout_resend_expire);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->state = DHCP6_STATE_STOPPED;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flyktstatic void client_stop(sd_dhcp6_client *client, int error) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt DHCP6_CLIENT_DONT_DESTROY(client);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt assert(client);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt client_notify(client, error);
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt client_reset(client);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flyktstatic int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt _cleanup_free_ DHCP6Message *message = NULL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt struct in6_addr all_servers =
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt size_t len, optlen = 512;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint8_t *opt;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int r;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt usec_t elapsed_usec;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt be16_t elapsed_time;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt len = sizeof(DHCP6Message) + optlen;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt message = malloc0(len);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!message)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return -ENOMEM;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt opt = (uint8_t *)(message + 1);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt message->transaction_id = client->transaction_id;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt switch(client->state) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt case DHCP6_STATE_INFORMATION_REQUEST:
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt message->type = DHCP6_INFORMATION_REQUEST;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt break;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt case DHCP6_STATE_SOLICITATION:
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt message->type = DHCP6_SOLICIT;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = dhcp6_option_append(&opt, &optlen,
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen if (r < 0)
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen return r;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt break;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt case DHCP6_STATE_REQUEST:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_RENEW:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (client->state == DHCP6_STATE_REQUEST)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt message->type = DHCP6_REQUEST;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt else
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt message->type = DHCP6_RENEW;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID,
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt client->lease->serverid_len,
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt client->lease->serverid);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt break;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_REBIND:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt message->type = DHCP6_REBIND;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt break;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt case DHCP6_STATE_STOPPED:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt case DHCP6_STATE_BOUND:
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return -EINVAL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt client->req_opts_len * sizeof(be16_t),
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt client->req_opts);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller assert (client->duid_len);
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID,
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams client->duid_len, &client->duid);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt elapsed_usec = time_now - client->transaction_start;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10)
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt else
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt elapsed_time = 0xffff;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME,
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt sizeof(elapsed_time), &elapsed_time);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (r < 0)
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt return r;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt len - optlen);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_dhcp6_client(client, "Sent %s",
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt dhcp6_message_type_to_string(message->type));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktstatic int client_timeout_t2(sd_event_source *s, uint64_t usec,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt void *userdata) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt sd_dhcp6_client *client = userdata;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert_return(s, -EINVAL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert_return(client, -EINVAL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert_return(client->lease, -EINVAL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client->lease->ia.timeout_t2 =
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt sd_event_source_unref(client->lease->ia.timeout_t2);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_dhcp6_client(client, "Timeout T2");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt client_start(client, DHCP6_STATE_REBIND);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt}
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktstatic int client_timeout_t1(sd_event_source *s, uint64_t usec,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt void *userdata) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt sd_dhcp6_client *client = userdata;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert_return(s, -EINVAL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert_return(client, -EINVAL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert_return(client->lease, -EINVAL);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client->lease->ia.timeout_t1 =
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt sd_event_source_unref(client->lease->ia.timeout_t1);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_dhcp6_client(client, "Timeout T1");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt client_start(client, DHCP6_STATE_RENEW);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt}
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic int client_timeout_resend_expire(sd_event_source *s, uint64_t usec,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt void *userdata) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_dhcp6_client *client = userdata;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt DHCP6_CLIENT_DONT_DESTROY(client);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt enum DHCP6State state;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(s);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(client);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(client->event);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt state = client->state;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann client_stop(client, SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt /* RFC 3315, section 18.1.4., says that "...the client may choose to
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt use a Solicit message to locate a new DHCP server..." */
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (state == DHCP6_STATE_REBIND)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt client_start(client, DHCP6_STATE_SOLICITATION);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic usec_t client_timeout_compute_random(usec_t val) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return val - val / 10 +
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktstatic int client_timeout_resend(sd_event_source *s, uint64_t usec,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt void *userdata) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt int r = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_dhcp6_client *client = userdata;
4b4923e65423e60d755841b5b264730e8f3deab3Tom Gundersen usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
5e91345094a9e983e7abb2313334e7808bcd2cc2Tom Gundersen usec_t max_retransmit_duration = 0;
513a6fa8679510ea1b55967bdb482dd5f8a39f21Ronny Chevalier uint8_t max_retransmit_count = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt char time_string[FORMAT_TIMESPAN_MAX];
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt uint32_t expire = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(s);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(client);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(client->event);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->timeout_resend = sd_event_source_unref(client->timeout_resend);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt switch (client->state) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt case DHCP6_STATE_INFORMATION_REQUEST:
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt init_retransmit_time = DHCP6_INF_TIMEOUT;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt max_retransmit_time = DHCP6_INF_MAX_RT;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt break;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt case DHCP6_STATE_SOLICITATION:
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (client->retransmit_count && client->lease) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt client_start(client, DHCP6_STATE_REQUEST);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return 0;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt init_retransmit_time = DHCP6_SOL_TIMEOUT;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt max_retransmit_time = DHCP6_SOL_MAX_RT;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt break;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt case DHCP6_STATE_REQUEST:
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt init_retransmit_time = DHCP6_REQ_TIMEOUT;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt max_retransmit_time = DHCP6_REQ_MAX_RT;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt max_retransmit_count = DHCP6_REQ_MAX_RC;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt break;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_RENEW:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt init_retransmit_time = DHCP6_REN_TIMEOUT;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt max_retransmit_time = DHCP6_REN_MAX_RT;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt /* RFC 3315, section 18.1.3. says max retransmit duration will
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt be the remaining time until T2. Instead of setting MRD,
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt wait for T2 to trigger with the same end result */
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt break;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_REBIND:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt init_retransmit_time = DHCP6_REB_TIMEOUT;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt max_retransmit_time = DHCP6_REB_MAX_RT;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (!client->timeout_resend_expire) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = dhcp6_lease_ia_rebind_expire(&client->lease->ia,
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt &expire);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt client_stop(client, r);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt max_retransmit_duration = expire * USEC_PER_SEC;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt break;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt case DHCP6_STATE_STOPPED:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt case DHCP6_STATE_BOUND:
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (max_retransmit_count &&
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->retransmit_count >= max_retransmit_count) {
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann client_stop(client, SD_DHCP6_CLIENT_EVENT_RETRANS_MAX);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto error;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = client_send_message(client, time_now);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (r >= 0)
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt client->retransmit_count++;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!client->retransmit_time) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->retransmit_time =
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client_timeout_compute_random(init_retransmit_time);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (client->state == DHCP6_STATE_SOLICITATION)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt client->retransmit_time += init_retransmit_time / 10;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt } else {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (max_retransmit_time &&
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->retransmit_time > max_retransmit_time / 2)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->retransmit_time = client_timeout_compute_random(max_retransmit_time);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt else
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->retransmit_time += client_timeout_compute_random(client->retransmit_time);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_dhcp6_client(client, "Next retransmission in %s",
ed19c567e5fcdcec1a2b6dbac63787e001ad5d55Tom Gundersen format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC));
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = sd_event_add_time(client->event, &client->timeout_resend,
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen clock_boottime_or_monotonic(),
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt time_now + client->retransmit_time,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt 10 * USEC_PER_MSEC, client_timeout_resend,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto error;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = sd_event_source_set_priority(client->timeout_resend,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->event_priority);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto error;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer");
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen if (r < 0)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen goto error;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (max_retransmit_duration && !client->timeout_resend_expire) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs",
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt max_retransmit_duration / USEC_PER_SEC);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = sd_event_add_time(client->event,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt &client->timeout_resend_expire,
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen clock_boottime_or_monotonic(),
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt time_now + max_retransmit_duration,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt USEC_PER_SEC,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client_timeout_resend_expire, client);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto error;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = sd_event_source_set_priority(client->timeout_resend_expire,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->event_priority);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto error;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer");
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen if (r < 0)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen goto error;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykterror:
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client_stop(client, r);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flyktstatic int client_ensure_iaid(sd_dhcp6_client *client) {
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen int r;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(client);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (client->ia_na.id)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return 0;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->ia_na.id);
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen if (r < 0)
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen return r;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return 0;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt}
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int client_parse_message(sd_dhcp6_client *client,
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt DHCP6Message *message, size_t len,
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt sd_dhcp6_lease *lease) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek uint8_t *optval, *option, *id = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt uint16_t optcode, status;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt size_t optlen, id_len;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt bool clientid = false;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt be32_t iaid_lease;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek option = (uint8_t *)message + sizeof(DHCP6Message);
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek len -= sizeof(DHCP6Message);
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt &optval)) >= 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt switch (optcode) {
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_CLIENTID:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (clientid) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "%s contains multiple clientids",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_type_to_string(message->type));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams if (optlen != client->duid_len ||
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt memcmp(&client->duid, optval, optlen) != 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "%s DUID does not match",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_type_to_string(message->type));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt clientid = true;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_SERVERID:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_lease_get_serverid(lease, &id, &id_len);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r >= 0 && id) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "%s contains multiple serverids",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_type_to_string(message->type));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_lease_set_serverid(lease, optval, optlen);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_PREFERENCE:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (optlen != 1)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_lease_set_preference(lease, *optval);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_STATUS_CODE:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (optlen < 2)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt status = optval[0] << 8 | optval[1];
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (status) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "%s Status %s",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_type_to_string(message->type),
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_status_to_string(status));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_IA_NA:
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_dhcp6_client(client, "Information request ignoring IA NA option");
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt break;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_option_parse_ia(&optval, &optlen, optcode,
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt &lease->ia);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0 && r != -ENOMSG)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_lease_get_iaid(lease, &iaid_lease);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (client->ia_na.id != iaid_lease) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "%s has wrong IAID",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_type_to_string(message->type));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_RAPID_COMMIT:
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = dhcp6_lease_set_rapid_commit(lease);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (r < 0)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt return r;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt break;
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_DNS_SERVERS:
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt r = dhcp6_lease_set_dns(lease, optval, optlen);
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt if (r < 0)
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt return r;
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt break;
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_DOMAIN_LIST:
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt r = dhcp6_lease_set_domains(lease, optval, optlen);
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt if (r < 0)
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt return r;
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt break;
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_NTP_SERVER:
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt r = dhcp6_lease_set_ntp(lease, optval, optlen);
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt if (r < 0)
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt return r;
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt break;
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani case SD_DHCP6_OPTION_SNTP_SERVERS:
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt r = dhcp6_lease_set_sntp(lease, optval, optlen);
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt if (r < 0)
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt return r;
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt if (r == -ENOMSG)
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt r = 0;
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt if (r < 0 || !clientid) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "%s has incomplete options",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_type_to_string(message->type));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -EINVAL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = dhcp6_lease_get_serverid(lease, &id, &id_len);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_dhcp6_client(client, "%s has no server id",
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt dhcp6_message_type_to_string(message->type));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringstatic int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt int r;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt bool rapid_commit;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (reply->type != DHCP6_REPLY)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = dhcp6_lease_new(&lease);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return -ENOMEM;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = client_parse_message(client, reply, len, lease);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (client->state == DHCP6_STATE_SOLICITATION) {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (r < 0)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt return r;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (!rapid_commit)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt return 0;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt }
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller client_set_lease(client, lease);
9d89d1ae71cb298218e35a69d6b70e2c94de5271Patrik Flykt lease = NULL;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return DHCP6_STATE_BOUND;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt}
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringstatic int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt uint8_t pref_advertise = 0, pref_lease = 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (advertise->type != DHCP6_ADVERTISE)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_lease_new(&lease);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = client_parse_message(client, advertise, len, lease);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_lease_get_preference(lease, &pref_advertise);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dhcp6_lease_get_preference(client->lease, &pref_lease);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0 || pref_advertise > pref_lease) {
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller client_set_lease(client, lease);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt lease = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (pref_advertise == 255 || client->retransmit_count > 1)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = DHCP6_STATE_REQUEST;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringstatic int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt sd_dhcp6_client *client = userdata;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt DHCP6_CLIENT_DONT_DESTROY(client);
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen _cleanup_free_ DHCP6Message *message = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r, buflen, len;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt assert(s);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt assert(client);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt assert(client->event);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = ioctl(fd, FIONREAD, &buflen);
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen if (r < 0)
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen return -errno;
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen else if (buflen < 0)
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen /* This really should not happen */
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen return -EIO;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen message = malloc(buflen);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (!message)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -ENOMEM;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt len = read(fd, message, buflen);
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen if (len < 0) {
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen if (errno == EAGAIN || errno == EINTR)
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen return 0;
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen log_dhcp6_client(client, "Could not receive message from UDP socket: %m");
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen return -errno;
0d43d2fcb7ac5264c739dc2f67f93ed0985a418aTom Gundersen } else if ((size_t)len < sizeof(DHCP6Message))
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt switch(message->type) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_SOLICIT:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_REQUEST:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_CONFIRM:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_RENEW:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_REBIND:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_RELEASE:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_DECLINE:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_INFORMATION_REQUEST:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_RELAY_FORW:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_RELAY_REPL:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_ADVERTISE:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_REPLY:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_RECONFIGURE:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt default:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "unknown message type %d",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt message->type);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (client->transaction_id != (message->transaction_id &
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt htobe32(0x00ffffff)))
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt switch (client->state) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt case DHCP6_STATE_INFORMATION_REQUEST:
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = client_receive_reply(client, message, len);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann client_notify(client, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client_start(client, DHCP6_STATE_STOPPED);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt break;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_STATE_SOLICITATION:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = client_receive_advertise(client, message, len);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (r == DHCP6_STATE_REQUEST) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt client_start(client, r);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt break;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt /* fall through for Soliciation Rapid Commit option check */
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt case DHCP6_STATE_REQUEST:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_RENEW:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_REBIND:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = client_receive_reply(client, message, len);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r == DHCP6_STATE_BOUND) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = client_start(client, DHCP6_STATE_BOUND);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client_stop(client, r);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann client_notify(client, SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt break;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt case DHCP6_STATE_BOUND:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt break;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case DHCP6_STATE_STOPPED:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r >= 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_dhcp6_client(client, "Recv %s",
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dhcp6_message_type_to_string(message->type));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt int r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt usec_t timeout, time_now;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt char time_string[FORMAT_TIMESPAN_MAX];
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert_return(client, -EINVAL);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert_return(client->event, -EINVAL);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert_return(client->index > 0, -EINVAL);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt assert_return(client->state != state, -EINVAL);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt client->timeout_resend_expire =
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt sd_event_source_unref(client->timeout_resend_expire);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt client->timeout_resend = sd_event_source_unref(client->timeout_resend);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt client->retransmit_time = 0;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt client->retransmit_count = 0;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering if (r < 0)
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering return r;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt switch (state) {
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt case DHCP6_STATE_STOPPED:
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client->state = DHCP6_STATE_STOPPED;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* fall through */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt case DHCP6_STATE_SOLICITATION:
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt client->state = DHCP6_STATE_SOLICITATION;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt break;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt case DHCP6_STATE_INFORMATION_REQUEST:
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt case DHCP6_STATE_REQUEST:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_RENEW:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case DHCP6_STATE_REBIND:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt client->state = state;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt break;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt case DHCP6_STATE_BOUND:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (client->lease->ia.lifetime_t1 == 0xffffffff ||
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client->lease->ia.lifetime_t2 == 0xffffffff) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_dhcp6_client(client, "infinite T1 0x%08x or T2 0x%08x",
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt be32toh(client->lease->ia.lifetime_t1),
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt be32toh(client->lease->ia.lifetime_t2));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_dhcp6_client(client, "T1 expires in %s",
ed19c567e5fcdcec1a2b6dbac63787e001ad5d55Tom Gundersen format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = sd_event_add_time(client->event,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt &client->lease->ia.timeout_t1,
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen clock_boottime_or_monotonic(), time_now + timeout,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt 10 * USEC_PER_SEC, client_timeout_t1,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client->event_priority);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen if (r < 0)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen return r;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_dhcp6_client(client, "T2 expires in %s",
ed19c567e5fcdcec1a2b6dbac63787e001ad5d55Tom Gundersen format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = sd_event_add_time(client->event,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt &client->lease->ia.timeout_t2,
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen clock_boottime_or_monotonic(), time_now + timeout,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt 10 * USEC_PER_SEC, client_timeout_t2,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = sd_event_source_set_priority(client->lease->ia.timeout_t2,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt client->event_priority);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen if (r < 0)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen return r;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt client->state = state;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt client->transaction_id = random_u32() & htobe32(0x00ffffff);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt client->transaction_start = time_now;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = sd_event_add_time(client->event, &client->timeout_resend,
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen clock_boottime_or_monotonic(), 0, 0, client_timeout_resend,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = sd_event_source_set_priority(client->timeout_resend,
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt client->event_priority);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout");
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen if (r < 0)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen return r;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return 0;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt}
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_stop(sd_dhcp6_client *client) {
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersen assert_return(client, -EINVAL);
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersen
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersenint sd_dhcp6_client_is_running(sd_dhcp6_client *client) {
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersen assert_return(client, -EINVAL);
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersen
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersen return client->state != DHCP6_STATE_STOPPED;
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersen}
f667c150a9116022f348cb6d8f2a553dce2386c3Tom Gundersen
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_start(sd_dhcp6_client *client) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt int r = 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt enum DHCP6State state = DHCP6_STATE_SOLICITATION;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client->event, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client->index > 0, -EINVAL);
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
63348d13fae61fefcb29133bfae8371b33cf4b6dTom Gundersen return -EBUSY;
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek r = client_reset(client);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (r < 0)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return r;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = client_ensure_iaid(client);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller r = client_ensure_duid(client);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller if (r < 0)
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller return r;
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller
c601ebf79f0c54be14d3c16f0f484c0335cdeec4Tom Gundersen r = dhcp6_network_bind_udp_socket(client->index, &client->local_address);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client->fd = r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_event_add_io(client->event, &client->receive_message,
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client->fd, EPOLLIN, client_receive_message,
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt goto error;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_event_source_set_priority(client->receive_message,
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client->event_priority);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt goto error;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_event_source_set_description(client->receive_message,
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt "dhcp6-receive-message");
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt goto error;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (client->information_request)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt state = DHCP6_STATE_INFORMATION_REQUEST;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_dhcp6_client(client, "Started in %s mode",
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client->information_request? "Information request":
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt "Managed");
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return client_start(client, state);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykterror:
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt client_reset(client);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt int r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(!client->event, -EBUSY);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (event)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->event = sd_event_ref(event);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt else {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_event_default(&client->event);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->event_priority = priority;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktint sd_dhcp6_client_detach_event(sd_dhcp6_client *client) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(client, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->event = sd_event_unref(client->event);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktsd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!client)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return client->event;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktsd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering if (!client)
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering return NULL;
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering assert(client->n_ref >= 1);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering client->n_ref++;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return client;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktsd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering if (!client)
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering return NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering assert(client->n_ref >= 1);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering client->n_ref--;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering if (client->n_ref > 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering client_reset(client);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering sd_dhcp6_client_detach_event(client);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering free(client->req_opts);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering free(client);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering return NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringint sd_dhcp6_client_new(sd_dhcp6_client **ret) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt size_t t;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert_return(ret, -EINVAL);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client = new0(sd_dhcp6_client, 1);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!client)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -ENOMEM;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering client->n_ref = 1;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
2c1ab8ca9b5dec48c66eb25dd8af71731e70e517Beniamino Galvani client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client->index = -1;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek client->fd = -1;
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt client->req_opts_len = ELEMENTSOF(default_req_opts);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt client->req_opts = new0(be16_t, client->req_opts_len);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (!client->req_opts)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return -ENOMEM;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (t = 0; t < client->req_opts_len; t++)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt client->req_opts[t] = htobe16(default_req_opts[t]);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt *ret = client;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt client = NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}