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