networkd-dhcp6.c revision c62c4628d9dbc27effd36143c75abe528f561867
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt This file is part of systemd.
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt Copyright (C) 2014 Intel Corporation. All rights reserved.
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 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 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/>.
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktstatic int dhcp6_lease_information_acquired(sd_dhcp6_client *client,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktstatic int dhcp6_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0 && r != -EEXIST) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_error(link, "Could not set DHCPv6 address: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt } else if (r >= 0)
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt link_rtnl_process_address(rtnl, m, link->manager);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktstatic int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt uint8_t prefixlen, uint32_t lifetime_preferred,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_struct(link, LOG_INFO, "MESSAGE=%-*s: DHCPv6 address "SD_ICMP6_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt link->ifname, SD_ICMP6_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt addr->prefixlen, lifetime_preferred, lifetime_valid,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = address_update(addr, link, dhcp6_address_handler);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not assign DHCPv6 address: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r >= 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flyktstatic int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = sd_icmp6_ra_get_prefixlen(link->icmp6_router_discovery,
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0 && r != -EADDRNOTAVAIL) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not get prefix information: %s",
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = dhcp6_address_update(link, &ip6_addr, prefixlen,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktstatic void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_debug(link, "DHCPv6 event %d", event);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = dhcp6_lease_address_acquired(client, link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt /* fall through */
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt r = dhcp6_lease_information_acquired(client, link);
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_link_warning(link, "DHCPv6 unknown event: %d",
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flyktstatic int dhcp6_configure(Link *link, int event) {
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (event != ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED)
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = sd_dhcp6_client_get_information_request(link->dhcp6_client,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not get DHCPv6 Information request setting: %s",
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not unset DHCPv6 Information request: %s",
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt log_link_warning(link, "Could not restart DHCPv6 after enabling Information request: %s",
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 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
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 r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (event == ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER) {
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
85bd849f09aceb7f972a0697494ea22b2247a5d7Patrik Flykt if (r < 0) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktstatic void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
c62c4628d9dbc27effd36143c75abe528f561867Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_link_warning(link, "ICMPv6 unknown event: %d",
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery, NULL, 0);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery, &link->mac);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt r = sd_icmp6_nd_set_index(link->icmp6_router_discovery, link->ifindex);