1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "sd-network.h"
25 #include "dhcp-lease-internal.h"
27 #include "resolved-link.h"
29 int link_new(Manager *m, Link **ret, int ifindex) {
30 _cleanup_(link_freep) Link *l = NULL;
36 r = hashmap_ensure_allocated(&m->links, NULL, NULL);
46 r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
59 Link *link_free(Link *l) {
65 link_address_free(l->addresses);
68 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
70 dns_scope_free(l->unicast_scope);
71 dns_scope_free(l->llmnr_ipv4_scope);
72 dns_scope_free(l->llmnr_ipv6_scope);
74 while (l->dhcp_dns_servers)
75 dns_server_free(l->dhcp_dns_servers);
77 while (l->link_dns_servers)
78 dns_server_free(l->link_dns_servers);
84 static void link_allocate_scopes(Link *l) {
89 if (l->link_dns_servers || l->dhcp_dns_servers) {
90 if (!l->unicast_scope) {
91 r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
93 log_warning("Failed to allocate DNS scope: %s", strerror(-r));
96 l->unicast_scope = dns_scope_free(l->unicast_scope);
98 if (link_relevant(l, AF_INET) && l->manager->use_llmnr) {
99 if (!l->llmnr_ipv4_scope) {
100 r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
102 log_warning("Failed to allocate LLMNR IPv4 scope: %s", strerror(-r));
105 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
107 if (link_relevant(l, AF_INET6) && l->manager->use_llmnr) {
108 if (!l->llmnr_ipv6_scope) {
109 r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
111 log_warning("Failed to allocate LLMNR IPv6 scope: %s", strerror(-r));
114 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
117 int link_update_rtnl(Link *l, sd_rtnl_message *m) {
118 const char *n = NULL;
124 r = sd_rtnl_message_link_get_flags(m, &l->flags);
128 sd_rtnl_message_read_u32(m, IFLA_MTU, &l->mtu);
130 if (sd_rtnl_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
131 strncpy(l->name, n, sizeof(l->name));
132 char_array_0(l->name);
135 link_allocate_scopes(l);
139 static int link_update_dhcp_dns_servers(Link *l) {
140 _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
141 const struct in_addr *nameservers = NULL;
147 r = sd_network_dhcp_use_dns(l->ifindex);
151 r = sd_network_get_dhcp_lease(l->ifindex, &lease);
155 LIST_FOREACH(servers, s, l->dhcp_dns_servers)
158 n = sd_dhcp_lease_get_dns(lease, &nameservers);
164 for (i = 0; i < n; i++) {
165 union in_addr_union a = { .in = nameservers[i] };
167 s = link_find_dns_server(l, DNS_SERVER_DHCP, AF_INET, &a);
171 r = dns_server_new(l->manager, NULL, DNS_SERVER_DHCP, l, AF_INET, &a);
177 LIST_FOREACH_SAFE(servers, s, nx, l->dhcp_dns_servers)
184 while (l->dhcp_dns_servers)
185 dns_server_free(l->dhcp_dns_servers);
190 static int link_update_link_dns_servers(Link *l) {
191 _cleanup_free_ struct in_addr *nameservers = NULL;
192 _cleanup_free_ struct in6_addr *nameservers6 = NULL;
198 LIST_FOREACH(servers, s, l->link_dns_servers)
201 n = sd_network_get_dns(l->ifindex, &nameservers);
207 for (i = 0; i < n; i++) {
208 union in_addr_union a = { .in = nameservers[i] };
210 s = link_find_dns_server(l, DNS_SERVER_LINK, AF_INET, &a);
214 r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, AF_INET, &a);
220 n = sd_network_get_dns6(l->ifindex, &nameservers6);
226 for (i = 0; i < n; i++) {
227 union in_addr_union a = { .in6 = nameservers6[i] };
229 s = link_find_dns_server(l, DNS_SERVER_LINK, AF_INET6, &a);
233 r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, AF_INET6, &a);
239 LIST_FOREACH_SAFE(servers, s, nx, l->link_dns_servers)
246 while (l->link_dns_servers)
247 dns_server_free(l->link_dns_servers);
252 int link_update_monitor(Link *l) {
255 link_update_dhcp_dns_servers(l);
256 link_update_link_dns_servers(l);
257 link_allocate_scopes(l);
262 bool link_relevant(Link *l, int family) {
263 _cleanup_free_ char *state = NULL;
268 /* A link is relevant if it isn't a loopback device and has at
269 * least one relevant IP address */
271 if (l->flags & IFF_LOOPBACK)
274 sd_network_get_link_operational_state(l->ifindex, &state);
275 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
278 LIST_FOREACH(addresses, a, l->addresses)
279 if (a->family == family && link_address_relevant(a))
285 LinkAddress *link_find_address(Link *l, int family, union in_addr_union *in_addr) {
290 LIST_FOREACH(addresses, a, l->addresses)
291 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
297 DnsServer* link_find_dns_server(Link *l, DnsServerSource source, int family, union in_addr_union *in_addr) {
298 DnsServer *first, *s;
302 first = source == DNS_SERVER_DHCP ? l->dhcp_dns_servers : l->link_dns_servers;
304 LIST_FOREACH(servers, s, first)
305 if (s->family == family && in_addr_equal(family, &s->address, in_addr))
311 DnsServer *link_get_dns_server(Link *l) {
314 if (!l->current_dns_server)
315 l->current_dns_server = l->link_dns_servers;
316 if (!l->current_dns_server)
317 l->current_dns_server = l->dhcp_dns_servers;
319 return l->current_dns_server;
322 void link_next_dns_server(Link *l) {
325 /* Switch to the next DNS server */
327 if (!l->current_dns_server) {
328 l->current_dns_server = l->link_dns_servers;
329 if (l->current_dns_server)
333 if (!l->current_dns_server) {
334 l->current_dns_server = l->dhcp_dns_servers;
335 if (l->current_dns_server)
339 if (!l->current_dns_server)
342 if (l->current_dns_server->servers_next) {
343 l->current_dns_server = l->current_dns_server->servers_next;
347 if (l->current_dns_server->source == DNS_SERVER_LINK)
348 l->current_dns_server = l->dhcp_dns_servers;
350 assert(l->current_dns_server->source == DNS_SERVER_DHCP);
351 l->current_dns_server = l->link_dns_servers;
355 int link_address_new(Link *l, LinkAddress **ret, int family, union in_addr_union *in_addr) {
361 a = new0(LinkAddress, 1);
366 a->in_addr = *in_addr;
369 LIST_PREPEND(addresses, l->addresses, a);
377 LinkAddress *link_address_free(LinkAddress *a) {
382 LIST_REMOVE(addresses, a->link->addresses, a);
388 int link_address_update_rtnl(LinkAddress *a, sd_rtnl_message *m) {
393 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
397 sd_rtnl_message_addr_get_scope(m, &a->scope);
399 link_allocate_scopes(a->link);
403 bool link_address_relevant(LinkAddress *a) {
406 if (a->flags & IFA_F_DEPRECATED)
409 if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))