resolved-link.c revision 623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbf
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2014 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic void link_address_add_rrs(LinkAddress *a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint link_new(Manager *m, Link **ret, int ifindex) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = hashmap_ensure_allocated(&m->links, NULL, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic void link_allocate_scopes(Link *l) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_warning("Failed to allocate DNS scope: %s", strerror(-r));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering l->unicast_scope = dns_scope_free(l->unicast_scope);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (link_relevant(l, AF_INET) && l->manager->use_llmnr) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_warning("Failed to allocate LLMNR IPv4 scope: %s", strerror(-r));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (link_relevant(l, AF_INET6) && l->manager->use_llmnr) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_warning("Failed to allocate LLMNR IPv6 scope: %s", strerror(-r));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint link_update_rtnl(Link *l, sd_rtnl_message *m) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering const char *n = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_link_get_flags(m, &l->flags);
c5ed93163e6ef51a7462aa558a7e0912b17c4951Lennart Poettering sd_rtnl_message_read_u32(m, IFLA_MTU, &l->mtu);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (sd_rtnl_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen _cleanup_strv_free_ char **nameservers = NULL;
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen r = sd_network_get_dns(l->ifindex, &nameservers);
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen r = in_addr_from_string_auto(*nameserver, &family, &a);
6f4dedb250f2d607eceefaa491f338becbeee7c0Tom Gundersen r = dns_server_new(l->manager, NULL, l, family, &a);
6073b6f26ab9fc6bf335faa7073ec443eef093fdTom Gundersen LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* A link is relevant if it isn't a loopback device and has at
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * least one relevant IP address */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sd_network_get_link_operational_state(l->ifindex, &state);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (a->family == family && link_address_relevant(a))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart PoetteringLinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart PoetteringDnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Switch to the next DNS server */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (l->current_dns_server->servers_next) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l->current_dns_server = l->current_dns_server->servers_next;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_PREPEND(addresses, l->addresses, a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringLinkAddress *link_address_free(LinkAddress *a) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_REMOVE(addresses, a->link->addresses, a);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_resource_record_unref(a->llmnr_address_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_resource_record_unref(a->llmnr_ptr_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic void link_address_add_rrs(LinkAddress *a) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (a->family == AF_INET && a->link->llmnr_ipv4_scope) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering a->link->manager->host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->hostname);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering a->llmnr_address_rr = dns_resource_record_new(a->link->manager->host_ipv4_key);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering a->llmnr_address_rr->a.in_addr = a->in_addr.in;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering a->link->manager->host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->hostname);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering a->llmnr_address_rr = dns_resource_record_new(a->link->manager->host_ipv6_key);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_debug("Failed to update address RRs: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint link_address_update_rtnl(LinkAddress *a, sd_rtnl_message *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_flags(m, &a->flags);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sd_rtnl_message_addr_get_scope(m, &a->scope);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringbool link_address_relevant(LinkAddress *a) {