networkd-address.c revision d076c6f9e486587d634d59082d2a13b9cbb4aef3
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi/***
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi This file is part of systemd.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Copyright 2013 Tom Gundersen <teg@jklm.no>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi systemd is free software; you can redistribute it and/or modify it
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi under the terms of the GNU Lesser General Public License as published by
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi the Free Software Foundation; either version 2.1 of the License, or
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi (at your option) any later version.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi systemd is distributed in the hope that it will be useful, but
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi WITHOUT ANY WARRANTY; without even the implied warranty of
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Lesser General Public License for more details.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi You should have received a copy of the GNU Lesser General Public License
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi along with systemd; If not, see <http://www.gnu.org/licenses/>.
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi***/
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include <net/if.h>
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "networkd.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "networkd-link.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "utf8.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "util.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "conf-parser.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi#include "network-internal.h"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic void address_init(Address *address) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address->family = AF_UNSPEC;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address->scope = RT_SCOPE_UNIVERSE;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint address_new_static(Network *network, unsigned section, Address **ret) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_address_free_ Address *address = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (section) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *ret = address;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = new0(Address, 1);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!address)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return -ENOMEM;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address_init(address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address->network = network;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi LIST_PREPEND(addresses, network->static_addresses, address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (section) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address->section = section;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi hashmap_put(network->addresses_by_section,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi UINT_TO_PTR(address->section), address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *ret = address;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint address_new_dynamic(Address **ret) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_address_free_ Address *address = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = new0(Address, 1);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!address)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return -ENOMEM;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address_init(address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *ret = address;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchivoid address_free(Address *address) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!address)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->network) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi LIST_REMOVE(addresses, address->network->static_addresses, address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->section)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi hashmap_remove(address->network->addresses_by_section,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi UINT_TO_PTR(address->section));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint address_drop(Address *address, Link *link,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi sd_rtnl_message_handler_t callback) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(address->family == AF_INET || address->family == AF_INET6);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->ifindex > 0);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->manager);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->manager->rtnl);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi link->ifindex, address->family);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not set prefixlen: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->family == AF_INET)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else if (address->family == AF_INET6)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not send rtnetlink message: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi link_ref(link);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint address_update(Address *address, Link *link,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi sd_rtnl_message_handler_t callback) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(address->family == AF_INET || address->family == AF_INET6);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->ifindex > 0);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->manager);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->manager->rtnl);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi link->ifindex, address->family);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not set prefixlen: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not set flags: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_addr_set_scope(req, address->scope);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not set scope: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->family == AF_INET)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else if (address->family == AF_INET6)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->family == AF_INET) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->label) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not send rtnetlink message: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi link_ref(link);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchistatic int address_acquire(Link *link, Address *original, Address **ret) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi union in_addr_union in_addr = {};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi struct in_addr broadcast = {};
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_address_free_ Address *na = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(original);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(ret);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* Something useful was configured? just use it */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (in_addr_is_null(original->family, &original->in_addr) <= 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* The address is configured to be 0.0.0.0 or [::] by the user?
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * Then let's acquire something more useful from the pool. */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_link_error(link, "Failed to acquire address from pool: %s", strerror(-r));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r == 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_link_error(link, "Couldn't find free address for interface, all taken.");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return -EBUSY;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (original->family == AF_INET) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* Pick first address in range for ourselves ... */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* .. and use last as broadcast address */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi } else if (original->family == AF_INET6)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi in_addr.in6.s6_addr[15] |= 1;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = address_new_dynamic(&na);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na->family = original->family;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na->prefixlen = original->prefixlen;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na->scope = original->scope;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na->cinfo = original->cinfo;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (original->label) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na->label = strdup(original->label);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!na->label)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return -ENOMEM;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na->broadcast = broadcast;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na->in_addr = in_addr;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi LIST_PREPEND(addresses, link->pool_addresses, na);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi *ret = na;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi na = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint address_configure(Address *address, Link *link,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi sd_rtnl_message_handler_t callback) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(address->family == AF_INET || address->family == AF_INET6);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->ifindex > 0);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->manager);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(link->manager->rtnl);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = address_acquire(link, address, &address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi link->ifindex, address->family);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not set prefixlen: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not set flags: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_addr_set_scope(req, address->scope);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not set scope: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->family == AF_INET)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else if (address->family == AF_INET6)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!in_addr_is_null(address->family, &address->in_addr_peer)) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->family == AF_INET)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else if (address->family == AF_INET6)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi } else {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->family == AF_INET) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (address->label) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_string(req, IFA_LABEL, address->label);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_LABEL attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_message_append_cache_info(req, IFA_CACHEINFO,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi &address->cinfo);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_error_errno(r, "Could not send rtnetlink message: %m");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi link_ref(link);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint config_parse_broadcast(
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *unit,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *filename,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi unsigned line,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *section,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi unsigned section_line,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *lvalue,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int ltype,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *rvalue,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi void *data,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi void *userdata) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Network *network = userdata;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_address_free_ Address *n = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(filename);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(section);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(lvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(data);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = address_new_static(network, section_line, &n);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (n->family == AF_INET6) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_syntax(unit, LOG_ERR, filename, line, EINVAL,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_syntax(unit, LOG_ERR, filename, line, EINVAL,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Broadcast is invalid, ignoring assignment: %s", rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->family = AF_INET;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint config_parse_address(const char *unit,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *filename,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi unsigned line,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *section,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi unsigned section_line,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *lvalue,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int ltype,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *rvalue,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi void *data,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi void *userdata) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Network *network = userdata;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_address_free_ Address *n = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *address, *e;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi union in_addr_union buffer;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int r, f;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(filename);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(section);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(lvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(data);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (streq(section, "Network")) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* we are not in an Address section, so treat
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi * this as the special '0' section */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi section_line = 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = address_new_static(network, section_line, &n);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* Address=address/prefixlen */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* prefixlen */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi e = strchr(rvalue, '/');
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (e) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi unsigned i;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = safe_atou(e + 1, &i);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_syntax(unit, LOG_ERR, filename, line, EINVAL,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Prefix length is invalid, ignoring assignment: %s", e + 1);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->prefixlen = (unsigned char) i;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = strndupa(rvalue, e - rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi } else
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi address = rvalue;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = in_addr_from_string_auto(address, &f, &buffer);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_syntax(unit, LOG_ERR, filename, line, EINVAL,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Address is invalid, ignoring assignment: %s", address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!e && f == AF_INET) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = in_addr_default_prefixlen(&buffer.in, &n->prefixlen);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_syntax(unit, LOG_ERR, filename, line, EINVAL,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (n->family != AF_UNSPEC && f != n->family) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_syntax(unit, LOG_ERR, filename, line, EINVAL,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Address is incompatible, ignoring assignment: %s", address);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->family = f;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (streq(lvalue, "Address"))
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->in_addr = buffer;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->in_addr_peer = buffer;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (n->family == AF_INET && n->broadcast.s_addr == 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->broadcast.s_addr = n->in_addr.in.s_addr | htonl(0xfffffffflu >> n->prefixlen);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchiint config_parse_label(const char *unit,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *filename,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi unsigned line,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *section,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi unsigned section_line,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *lvalue,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int ltype,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi const char *rvalue,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi void *data,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi void *userdata) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi Network *network = userdata;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi _cleanup_address_free_ Address *n = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi char *label;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi int r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(filename);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(section);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(lvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert(data);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi r = address_new_static(network, section_line, &n);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (r < 0)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return r;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi label = strdup(rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!label)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return log_oom();
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi log_syntax(unit, LOG_ERR, filename, line, EINVAL,
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi "Interface label is not ASCII clean or is too"
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi " long, ignoring assignment: %s", rvalue);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(label);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(n->label);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (*label)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->label = label;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi free(label);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n->label = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi n = NULL;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return 0;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchibool address_equal(Address *a1, Address *a2) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* same object */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (a1 == a2)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return true;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* one, but not both, is NULL */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (!a1 || !a2)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return false;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (a1->family != a2->family)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return false;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi switch (a1->family) {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi /* use the same notion of equality as the kernel does */
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case AF_UNSPEC:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return true;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case AF_INET:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi if (a1->prefixlen != a2->prefixlen)
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return false;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi else {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi uint32_t b1, b2;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi b1 = be32toh(a1->in_addr.in.s_addr);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi b2 = be32toh(a2->in_addr.in.s_addr);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi case AF_INET6:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi {
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi uint64_t *b1, *b2;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi b1 = (uint64_t*)&a1->in_addr.in6;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi b2 = (uint64_t*)&a2->in_addr.in6;
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi default:
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi assert_not_reached("Invalid address family");
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi }
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi}
d14abf155341d55053c76eeec58b787a456b753bRobert Mustacchi