networkd-dhcp6.c revision 10c9ce615d98e125bc520efa94aebaef250a4061
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt/***
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt This file is part of systemd.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Copyright (C) 2014 Intel Corporation. All rights reserved.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt systemd is free software; you can redistribute it and/or modify it
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt under the terms of the GNU Lesser General Public License as published by
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt the Free Software Foundation; either version 2.1 of the License, or
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt (at your option) any later version.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt systemd is distributed in the hope that it will be useful, but
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Lesser General Public License for more details.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt You should have received a copy of the GNU Lesser General Public License
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt***/
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <netinet/ether.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include <linux/if.h>
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include "networkd-link.h"
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include "network-internal.h"
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include "sd-icmp6-nd.h"
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt#include "sd-dhcp6-client.h"
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flyktstatic int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktstatic int dhcp6_lease_information_acquired(sd_dhcp6_client *client,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt Link *link) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return 0;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt}
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt void *userdata) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt _cleanup_link_unref_ Link *link = userdata;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt int r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt assert(link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_message_get_errno(m);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0 && r != -EEXIST) {
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (link->rtnl_extended_attrs) {
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt log_link_warning(link, "Could not set extended netlink attributes, reverting to fallback mechanism");
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt link->rtnl_extended_attrs = false;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt dhcp6_lease_address_acquired(link->dhcp6_client, link);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return 1;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt }
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_error(link, "Could not set DHCPv6 address: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt strerror(-r));
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt link_enter_failed(link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt } else if (r >= 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt link_rtnl_process_address(rtnl, m, link->manager);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return 1;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt}
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktstatic int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt uint8_t prefixlen, uint32_t lifetime_preferred,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt uint32_t lifetime_valid) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt int r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt _cleanup_address_free_ Address *addr = NULL;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = address_new_dynamic(&addr);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt addr->family = AF_INET6;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
851c9f82736c89d423b244a292e153ec7124d309Patrik Flykt
851c9f82736c89d423b244a292e153ec7124d309Patrik Flykt addr->flags = IFA_F_NOPREFIXROUTE;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt addr->prefixlen = prefixlen;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt addr->cinfo.ifa_prefered = lifetime_preferred;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt addr->cinfo.ifa_valid = lifetime_valid;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering log_link_info(link,
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering "DHCPv6 address "SD_ICMP6_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering SD_ICMP6_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering addr->prefixlen, lifetime_preferred, lifetime_valid);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = address_update(addr, link, dhcp6_address_handler);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0)
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m");
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt}
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktstatic int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt int r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt sd_dhcp6_lease *lease;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt struct in6_addr ip6_addr;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt uint32_t lifetime_preferred, lifetime_valid;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt uint8_t prefixlen;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = sd_dhcp6_client_get_lease(client, &lease);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt sd_dhcp6_lease_reset_address_iter(lease);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt &lifetime_preferred,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt &lifetime_valid) >= 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = sd_icmp6_ra_get_prefixlen(link->icmp6_router_discovery,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt &ip6_addr, &prefixlen);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0 && r != -EADDRNOTAVAIL) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not get prefix information: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt strerror(-r));
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt }
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r == -EADDRNOTAVAIL)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt prefixlen = 128;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = dhcp6_address_update(link, &ip6_addr, prefixlen,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt lifetime_preferred, lifetime_valid);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return r;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt }
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return 0;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt}
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktstatic void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt int r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Link *link = userdata;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(link);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(link->network);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(link->manager);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt switch(event) {
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann case SD_DHCP6_CLIENT_EVENT_STOP:
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE:
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX:
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_debug(link, "DHCPv6 event %d", event);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt break;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = dhcp6_lease_address_acquired(client, link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt link_enter_failed(link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt }
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt /* fall through */
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = dhcp6_lease_information_acquired(client, link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt link_enter_failed(link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt return;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt break;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt default:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (event < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_link_warning(link, "DHCPv6 error: %s",
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt strerror(-event));
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt else
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_link_warning(link, "DHCPv6 unknown event: %d",
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt event);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt}
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flyktstatic int dhcp6_configure(Link *link, int event) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt int r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt bool information_request;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert_return(link, -EINVAL);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (link->dhcp6_client) {
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (event != ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED)
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return 0;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = sd_dhcp6_client_get_information_request(link->dhcp6_client,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt &information_request);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not get DHCPv6 Information request setting: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt strerror(-r));
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt link->dhcp6_client =
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt sd_dhcp6_client_unref(link->dhcp6_client);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (!information_request)
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt false);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not unset DHCPv6 Information request: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt strerror(-r));
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt link->dhcp6_client =
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt sd_dhcp6_client_unref(link->dhcp6_client);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = sd_dhcp6_client_start(link->dhcp6_client);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not restart DHCPv6 after enabling Information request: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt strerror(-r));
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt link->dhcp6_client =
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt sd_dhcp6_client_unref(link->dhcp6_client);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_dhcp6_client_new(&link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_dhcp6_client_set_mac(link->dhcp6_client,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt (const uint8_t *) &link->mac,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt sizeof (link->mac), ARPHRD_ETHER);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (event == ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER) {
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt true);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt link->dhcp6_client =
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt sd_dhcp6_client_unref(link->dhcp6_client);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt return r;
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt }
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_dhcp6_client_start(link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt}
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flyktstatic int dhcp6_prefix_expired(Link *link) {
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt int r;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt sd_dhcp6_lease *lease;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt struct in6_addr *expired_prefix, ip6_addr;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt uint8_t expired_prefixlen;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt uint32_t lifetime_preferred, lifetime_valid;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt &expired_prefix, &expired_prefixlen);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (r < 0)
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return r;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (r < 0)
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return r;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering log_link_info(link, "IPv6 prefix "SD_ICMP6_ADDRESS_FORMAT_STR"/%d expired",
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering SD_ICMP6_ADDRESS_FORMAT_VAL(*expired_prefix),
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering expired_prefixlen);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt sd_dhcp6_lease_reset_address_iter(lease);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt &lifetime_preferred,
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt &lifetime_valid) >= 0) {
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen,
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt &ip6_addr);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (r < 0)
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt continue;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering log_link_info(link, "IPv6 prefix length updated "SD_ICMP6_ADDRESS_FORMAT_STR"/%d", SD_ICMP6_ADDRESS_FORMAT_VAL(ip6_addr), 128);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
f2341e0a87cab1558c84c933956e9181d5fb6c52Lennart Poettering dhcp6_address_update(link, &ip6_addr, 128, lifetime_preferred, lifetime_valid);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt }
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt return 0;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt}
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktstatic void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Link *link = userdata;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(link);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(link->network);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert(link->manager);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt switch(event) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt dhcp6_configure(link, event);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt break;
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED:
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt if (!link->rtnl_extended_attrs)
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt dhcp6_prefix_expired(link);
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt break;
be3a09b7ffe62b52658e77ae4d6638d1b0dae654Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt default:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (event < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_link_warning(link, "ICMPv6 error: %s",
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt strerror(-event));
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt else
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_link_warning(link, "ICMPv6 unknown event: %d",
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt event);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt break;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt}
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktint icmp6_configure(Link *link) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt int r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert_return(link, -EINVAL);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery, NULL, 0);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery, &link->mac);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_set_index(link->icmp6_router_discovery, link->ifindex);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt icmp6_router_handler, link);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt}