resolved-link.c revision 2e1bab34bdb1a5e849060afa8361b865ce39f87f
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering/***
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering This file is part of systemd.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Copyright 2014 Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is free software; you can redistribute it and/or modify it
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering under the terms of the GNU Lesser General Public License as published by
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering (at your option) any later version.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is distributed in the hope that it will be useful, but
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Lesser General Public License for more details.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering You should have received a copy of the GNU Lesser General Public License
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering***/
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include <net/if.h>
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "sd-network.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "alloc-util.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "missing.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "parse-util.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "resolved-link.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "string-util.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "strv.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint link_new(Manager *m, Link **ret, int ifindex) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_(link_freep) Link *l = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(m);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(ifindex > 0);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = hashmap_ensure_allocated(&m->links, NULL);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l = new0(Link, 1);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!l)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ENOMEM;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering l->ifindex = ifindex;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->llmnr_support = RESOLVE_SUPPORT_YES;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->mdns_support = RESOLVE_SUPPORT_NO;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->dnssec_mode = _DNSSEC_MODE_INVALID;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->manager = m;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (ret)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering *ret = l;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering l = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
e627440b41bb0284e4892f7aa9d84c77972487e2Lennart Poettering return 0;
e627440b41bb0284e4892f7aa9d84c77972487e2Lennart Poettering}
e627440b41bb0284e4892f7aa9d84c77972487e2Lennart Poettering
e627440b41bb0284e4892f7aa9d84c77972487e2Lennart PoetteringLink *link_free(Link *l) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!l)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_server_unlink_all(l->dns_servers);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_search_domain_unlink_all(l->search_domains);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering while (l->addresses)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering link_address_free(l->addresses);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (l->manager)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_scope_free(l->unicast_scope);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering dns_scope_free(l->llmnr_ipv4_scope);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_scope_free(l->llmnr_ipv6_scope);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_scope_free(l->mdns_ipv4_scope);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_scope_free(l->mdns_ipv6_scope);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering set_free_free(l->dnssec_negative_trust_anchors);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering free(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic void link_allocate_scopes(Link *l) {
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (l->dns_servers) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!l->unicast_scope) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_warning_errno(r, "Failed to allocate DNS scope: %m");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->unicast_scope = dns_scope_free(l->unicast_scope);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering if (link_relevant(l, AF_INET) &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->llmnr_support != RESOLVE_SUPPORT_NO &&
baed47c3c20512507e497058d388782400a072f6Lennart Poettering l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
baed47c3c20512507e497058d388782400a072f6Lennart Poettering if (!l->llmnr_ipv4_scope) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
baed47c3c20512507e497058d388782400a072f6Lennart Poettering log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else
baed47c3c20512507e497058d388782400a072f6Lennart Poettering l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (link_relevant(l, AF_INET6) &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->llmnr_support != RESOLVE_SUPPORT_NO &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering socket_ipv6_is_supported()) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!l->llmnr_ipv6_scope) {
baed47c3c20512507e497058d388782400a072f6Lennart Poettering r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else
baed47c3c20512507e497058d388782400a072f6Lennart Poettering l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (link_relevant(l, AF_INET) &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->mdns_support != RESOLVE_SUPPORT_NO &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!l->mdns_ipv4_scope) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (link_relevant(l, AF_INET6) &&
baed47c3c20512507e497058d388782400a072f6Lennart Poettering l->mdns_support != RESOLVE_SUPPORT_NO &&
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!l->mdns_ipv6_scope) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m");
baed47c3c20512507e497058d388782400a072f6Lennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering } else
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringvoid link_add_rrs(Link *l, bool force_remove) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LinkAddress *a;
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_FOREACH(addresses, a, l->addresses)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering link_address_add_rrs(a, force_remove);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint link_update_rtnl(Link *l, sd_netlink_message *m) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering const char *n = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering assert(m);
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_rtnl_message_link_get_flags(m, &l->flags);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering strncpy(l->name, n, sizeof(l->name)-1);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering char_array_0(l->name);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering }
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering link_allocate_scopes(l);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering link_add_rrs(l, false);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering return 0;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering}
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poetteringstatic int link_update_dns_servers(Link *l) {
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering _cleanup_strv_free_ char **nameservers = NULL;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering char **nameserver;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering int r;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering assert(l);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering r = sd_network_link_get_dns(l->ifindex, &nameservers);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering if (r == -ENODATA) {
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering r = 0;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering goto clear;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering }
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering if (r < 0)
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering goto clear;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering dns_server_mark_all(l->dns_servers);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering STRV_FOREACH(nameserver, nameservers) {
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering union in_addr_union a;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering DnsServer *s;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering int family;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering r = in_addr_from_string_auto(*nameserver, &family, &a);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering s = dns_server_find(l->dns_servers, family, &a);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (s)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_server_move_back_and_unmark(s);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering else {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering goto clear;
671e021c92c835c6c701dc61463149d05b6f31afLennart Poettering }
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering }
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_server_unlink_marked(l->dns_servers);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringclear:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_server_unlink_all(l->dns_servers);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int link_update_llmnr_support(Link *l) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_free_ char *b = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_network_link_get_llmnr(l->ifindex, &b);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r == -ENODATA) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
baed47c3c20512507e497058d388782400a072f6Lennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->llmnr_support = resolve_support_from_string(b);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (l->llmnr_support < 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EINVAL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringclear:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->llmnr_support = RESOLVE_SUPPORT_YES;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int link_update_mdns_support(Link *l) {
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering _cleanup_free_ char *b = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_network_link_get_mdns(l->ifindex, &b);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r == -ENODATA) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->mdns_support = resolve_support_from_string(b);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (l->mdns_support < 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EINVAL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringclear:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->mdns_support = RESOLVE_SUPPORT_NO;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int link_update_dnssec_mode(Link *l) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_free_ char *m = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering DnssecMode mode;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering r = sd_network_link_get_dnssec(l->ifindex, &m);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r == -ENODATA) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering mode = dnssec_mode_from_string(m);
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering if (mode < 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EINVAL;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering goto clear;
14d10188de1fd58e663d73683a400d8d7dc67dbaLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if ((l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering * allow-downgrade mode to full DNSSEC mode, flush it too. */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (l->unicast_scope)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_cache_flush(&l->unicast_scope->cache);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->dnssec_mode = mode;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringclear:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->dnssec_mode = _DNSSEC_MODE_INVALID;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int link_update_dnssec_negative_trust_anchors(Link *l) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_strv_free_ char **ntas = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_set_free_free_ Set *ns = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering char **i;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r == -ENODATA) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering ns = set_new(&dns_name_hash_ops);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!ns)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ENOMEM;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering STRV_FOREACH(i, ntas) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = set_put_strdup(ns, *i);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering set_free_free(l->dnssec_negative_trust_anchors);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering l->dnssec_negative_trust_anchors = ns;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering ns = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringclear:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int link_update_search_domains(Link *l) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering _cleanup_strv_free_ char **domains = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering char **i;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering r = sd_network_link_get_domains(l->ifindex, &domains);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r == -ENODATA) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* networkd knows nothing about this interface, and that's fine. */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
3e4b9b506d676d1cb8692306b38c05f8529e5cdbLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_search_domain_mark_all(l->search_domains);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering STRV_FOREACH(i, domains) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering DnsSearchDomain *d;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = dns_search_domain_find(l->search_domains, *i, &d);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r > 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_search_domain_move_back_and_unmark(d);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering else {
baed47c3c20512507e497058d388782400a072f6Lennart Poettering r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto clear;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering dns_search_domain_unlink_marked(l->search_domains);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering return 0;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringclear:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering dns_search_domain_unlink_all(l->search_domains);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poetteringint link_update_monitor(Link *l) {
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering int r;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering assert(l);
b7c9ae91d111b3e89d1ffc00e08f9ed97a8ff5dbLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = link_update_dns_servers(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
baed47c3c20512507e497058d388782400a072f6Lennart Poettering r = link_update_llmnr_support(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = link_update_mdns_support(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = link_update_dnssec_mode(l);
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering if (r < 0)
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name);
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering r = link_update_dnssec_negative_trust_anchors(l);
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering if (r < 0)
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name);
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering r = link_update_search_domains(l);
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering if (r < 0)
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering link_allocate_scopes(l);
baed47c3c20512507e497058d388782400a072f6Lennart Poettering link_add_rrs(l, false);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
baed47c3c20512507e497058d388782400a072f6Lennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringbool link_relevant(Link *l, int family) {
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering _cleanup_free_ char *state = NULL;
72fbdd3349ad30d8a5074ea9a650f0909f96c299Lennart Poettering LinkAddress *a;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* A link is relevant if it isn't a loopback or pointopoint
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering * device, has a link beat, can do multicast and has at least
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering * one relevant IP address */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (l->flags & (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_DORMANT))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if ((l->flags & (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST)) != (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST))
baed47c3c20512507e497058d388782400a072f6Lennart Poettering return false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering sd_network_link_get_operational_state(l->ifindex, &state);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_FOREACH(addresses, a, l->addresses)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (a->family == family && link_address_relevant(a))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return true;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart PoetteringLinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LinkAddress *a;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering LIST_FOREACH(addresses, a, l->addresses)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return a;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart PoetteringDnsServer* link_set_dns_server(Link *l, DnsServer *s) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(l);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (l->current_dns_server == s)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return s;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (s)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_info("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name);
4da416aa20b956571d74720bc91222881443e24bLennart Poettering
4da416aa20b956571d74720bc91222881443e24bLennart Poettering dns_server_unref(l->current_dns_server);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering l->current_dns_server = dns_server_ref(s);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering if (l->unicast_scope)
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering dns_cache_flush(&l->unicast_scope->cache);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering return s;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering}
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart PoetteringDnsServer *link_get_dns_server(Link *l) {
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering assert(l);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering if (!l->current_dns_server)
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering link_set_dns_server(l, l->dns_servers);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering return l->current_dns_server;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering}
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poetteringvoid link_next_dns_server(Link *l) {
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering assert(l);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering if (!l->current_dns_server)
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering return;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering /* Change to the next one, but make sure to follow the linked
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering * list only if this server is actually still linked. */
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering link_set_dns_server(l, l->current_dns_server->servers_next);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering return;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering }
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering link_set_dns_server(l, l->dns_servers);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering}
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poetteringint link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering LinkAddress *a;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering assert(l);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering assert(in_addr);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering a = new0(LinkAddress, 1);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering if (!a)
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering return -ENOMEM;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering a->family = family;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering a->in_addr = *in_addr;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering a->link = l;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering LIST_PREPEND(addresses, l->addresses, a);
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering if (ret)
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering *ret = a;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering return 0;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering}
4da416aa20b956571d74720bc91222881443e24bLennart Poettering
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart PoetteringLinkAddress *link_address_free(LinkAddress *a) {
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering if (!a)
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering return NULL;
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering if (a->link) {
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering LIST_REMOVE(addresses, a->link->addresses, a);
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering if (a->llmnr_address_rr) {
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering }
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering if (a->llmnr_ptr_rr) {
89fef99014662a5a63e7deaedd6292b7fb4ab2f8Lennart Poettering if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
}
}
dns_resource_record_unref(a->llmnr_address_rr);
dns_resource_record_unref(a->llmnr_ptr_rr);
free(a);
return NULL;
}
void link_address_add_rrs(LinkAddress *a, bool force_remove) {
int r;
assert(a);
if (a->family == AF_INET) {
if (!force_remove &&
link_address_relevant(a) &&
a->link->llmnr_ipv4_scope &&
a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
if (!a->link->manager->llmnr_host_ipv4_key) {
a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
if (!a->link->manager->llmnr_host_ipv4_key) {
r = -ENOMEM;
goto fail;
}
}
if (!a->llmnr_address_rr) {
a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
if (!a->llmnr_address_rr) {
r = -ENOMEM;
goto fail;
}
a->llmnr_address_rr->a.in_addr = a->in_addr.in;
a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
}
if (!a->llmnr_ptr_rr) {
r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
if (r < 0)
goto fail;
a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
}
r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
if (r < 0)
log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
if (r < 0)
log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
} else {
if (a->llmnr_address_rr) {
if (a->link->llmnr_ipv4_scope)
dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
}
if (a->llmnr_ptr_rr) {
if (a->link->llmnr_ipv4_scope)
dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
}
}
}
if (a->family == AF_INET6) {
if (!force_remove &&
link_address_relevant(a) &&
a->link->llmnr_ipv6_scope &&
a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
if (!a->link->manager->llmnr_host_ipv6_key) {
a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
if (!a->link->manager->llmnr_host_ipv6_key) {
r = -ENOMEM;
goto fail;
}
}
if (!a->llmnr_address_rr) {
a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
if (!a->llmnr_address_rr) {
r = -ENOMEM;
goto fail;
}
a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
}
if (!a->llmnr_ptr_rr) {
r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
if (r < 0)
goto fail;
a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
}
r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
if (r < 0)
log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
if (r < 0)
log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
} else {
if (a->llmnr_address_rr) {
if (a->link->llmnr_ipv6_scope)
dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
}
if (a->llmnr_ptr_rr) {
if (a->link->llmnr_ipv6_scope)
dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
}
}
}
return;
fail:
log_debug_errno(r, "Failed to update address RRs: %m");
}
int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
int r;
assert(a);
assert(m);
r = sd_rtnl_message_addr_get_flags(m, &a->flags);
if (r < 0)
return r;
sd_rtnl_message_addr_get_scope(m, &a->scope);
link_allocate_scopes(a->link);
link_add_rrs(a->link, false);
return 0;
}
bool link_address_relevant(LinkAddress *a) {
assert(a);
if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
return false;
if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
return false;
return true;
}