networkd-dhcp6.c revision 5c79bd79839f1e50bd3c34a0670037f7965ca5a4
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
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktstatic void dhcp6_handler(sd_dhcp6_client *client, 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 DHCP6_EVENT_STOP:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case DHCP6_EVENT_RESEND_EXPIRE:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case DHCP6_EVENT_RETRANS_MAX:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case DHCP6_EVENT_IP_ACQUIRE:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt log_link_debug(link, "DHCPv6 event %d", event);
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
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flyktstatic int dhcp6_configure(Link *link) {
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt int r;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt assert_return(link, -EINVAL);
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt if (link->dhcp6_client)
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return 0;
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
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
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 case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt break;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik 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
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt return;
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt }
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt
5c79bd79839f1e50bd3c34a0670037f7965ca5a4Patrik Flykt dhcp6_configure(link);
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}