resolved-link.c revision da927ba997d68401563b927f92e6e40e021a8e5c
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering This file is part of systemd.
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering Copyright 2014 Lennart Poettering
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering (at your option) any later version.
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering systemd is distributed in the hope that it will be useful, but
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering Lesser General Public License for more details.
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poetteringint link_new(Manager *m, Link **ret, int ifindex) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = hashmap_ensure_allocated(&m->links, NULL);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poetteringstatic void link_allocate_scopes(Link *l) {
1c7dd82563ff2e71a067aea20d2acb2d0553644bLennart Poettering r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
1c7dd82563ff2e71a067aea20d2acb2d0553644bLennart Poettering log_warning_errno(r, "Failed to allocate DNS scope: %m");
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering l->unicast_scope = dns_scope_free(l->unicast_scope);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering l->manager->llmnr_support != SUPPORT_NO) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering l->manager->llmnr_support != SUPPORT_NO &&
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poetteringvoid link_add_rrs(Link *l, bool force_remove) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poetteringint link_update_rtnl(Link *l, sd_rtnl_message *m) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering const char *n = NULL;
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = sd_rtnl_message_link_get_flags(m, &l->flags);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering sd_rtnl_message_read_u32(m, IFLA_MTU, &l->mtu);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if (sd_rtnl_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poetteringstatic int link_update_dns_servers(Link *l) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering _cleanup_strv_free_ char **nameservers = NULL;
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = sd_network_link_get_dns(l->ifindex, &nameservers);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = in_addr_from_string_auto(*nameserver, &family, &a);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poetteringstatic int link_update_llmnr_support(Link *l) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = sd_network_link_get_llmnr(l->ifindex, &b);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering } else if (r > 0)
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering r = sd_network_link_get_domains(l->ifindex,
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering /* A link is relevant if it isn't a loopback or pointopoint
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering * device, has a link beat, can do multicast and has at least
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering * one relevant IP address */
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if (l->flags & (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_DORMANT))
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if ((l->flags & (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST)) != (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST))
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering sd_network_link_get_operational_state(l->ifindex, &state);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if (a->family == family && link_address_relevant(a))
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart PoetteringLinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart PoetteringDnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr))
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart PoetteringDnsServer* link_set_dns_server(Link *l, DnsServer *s) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering in_addr_to_string(s->family, &s->address, &ip);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering log_info("Switching to DNS server %s for interface %s.", strna(ip), l->name);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering dns_cache_flush(&l->unicast_scope->cache);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if (l->current_dns_server->servers_next) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering link_set_dns_server(l, l->current_dns_server->servers_next);
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poetteringint link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
return -ENOMEM;
a->link = l;
if (ret)
*ret = a;
return NULL;
if (a->link) {
if (a->llmnr_address_rr) {
if (a->llmnr_ptr_rr) {
free(a);
return NULL;
assert(a);
if (!force_remove &&
link_address_relevant(a) &&
a->link->manager->host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->hostname);
r = -ENOMEM;
goto fail;
if (!a->llmnr_address_rr) {
if (!a->llmnr_address_rr) {
r = -ENOMEM;
goto fail;
if (!a->llmnr_ptr_rr) {
r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
goto fail;
r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
if (a->llmnr_address_rr) {
if (a->llmnr_ptr_rr) {
if (!force_remove &&
link_address_relevant(a) &&
a->link->manager->host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->hostname);
r = -ENOMEM;
goto fail;
if (!a->llmnr_address_rr) {
if (!a->llmnr_address_rr) {
r = -ENOMEM;
goto fail;
if (!a->llmnr_ptr_rr) {
r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
goto fail;
r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
if (a->llmnr_address_rr) {
if (a->llmnr_ptr_rr) {
fail:
assert(a);
assert(m);
assert(a);