]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-link.c
resolved: don't read DHCP leases
[thirdparty/systemd.git] / src / resolve / resolved-link.c
CommitLineData
74b2466e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
22#include <net/if.h>
23
24#include "sd-network.h"
74b2466e
LP
25#include "strv.h"
26#include "resolved-link.h"
27
28int link_new(Manager *m, Link **ret, int ifindex) {
29 _cleanup_(link_freep) Link *l = NULL;
30 int r;
31
32 assert(m);
33 assert(ifindex > 0);
34
35 r = hashmap_ensure_allocated(&m->links, NULL, NULL);
36 if (r < 0)
37 return r;
38
39 l = new0(Link, 1);
40 if (!l)
41 return -ENOMEM;
42
43 l->ifindex = ifindex;
44
45 r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
46 if (r < 0)
47 return r;
48
49 l->manager = m;
50
51 if (ret)
52 *ret = l;
53 l = NULL;
54
55 return 0;
56}
57
58Link *link_free(Link *l) {
59
60 if (!l)
61 return NULL;
62
63 while (l->addresses)
64 link_address_free(l->addresses);
65
66 if (l->manager)
67 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
68
69 dns_scope_free(l->unicast_scope);
1716f6dc
LP
70 dns_scope_free(l->llmnr_ipv4_scope);
71 dns_scope_free(l->llmnr_ipv6_scope);
74b2466e 72
6073b6f2
TG
73 while (l->dns_servers)
74 dns_server_free(l->dns_servers);
74b2466e
LP
75
76 free(l);
77 return NULL;
1716f6dc
LP
78}
79
80static void link_allocate_scopes(Link *l) {
81 int r;
82
83 assert(l);
84
6073b6f2 85 if (l->dns_servers) {
1716f6dc
LP
86 if (!l->unicast_scope) {
87 r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
88 if (r < 0)
89 log_warning("Failed to allocate DNS scope: %s", strerror(-r));
90 }
91 } else
92 l->unicast_scope = dns_scope_free(l->unicast_scope);
93
94 if (link_relevant(l, AF_INET) && l->manager->use_llmnr) {
95 if (!l->llmnr_ipv4_scope) {
96 r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
97 if (r < 0)
98 log_warning("Failed to allocate LLMNR IPv4 scope: %s", strerror(-r));
99 }
100 } else
101 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
102
103 if (link_relevant(l, AF_INET6) && l->manager->use_llmnr) {
104 if (!l->llmnr_ipv6_scope) {
105 r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
106 if (r < 0)
107 log_warning("Failed to allocate LLMNR IPv6 scope: %s", strerror(-r));
108 }
109 } else
110 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
111}
74b2466e
LP
112
113int link_update_rtnl(Link *l, sd_rtnl_message *m) {
1716f6dc 114 const char *n = NULL;
74b2466e
LP
115 int r;
116
117 assert(l);
118 assert(m);
119
120 r = sd_rtnl_message_link_get_flags(m, &l->flags);
121 if (r < 0)
122 return r;
123
c5ed9316 124 sd_rtnl_message_read_u32(m, IFLA_MTU, &l->mtu);
1716f6dc
LP
125
126 if (sd_rtnl_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
127 strncpy(l->name, n, sizeof(l->name));
128 char_array_0(l->name);
129 }
130
131 link_allocate_scopes(l);
74b2466e
LP
132 return 0;
133}
134
6073b6f2 135static int link_update_dns_servers(Link *l) {
74b2466e
LP
136 _cleanup_free_ struct in_addr *nameservers = NULL;
137 _cleanup_free_ struct in6_addr *nameservers6 = NULL;
138 DnsServer *s, *nx;
a2ba62c7 139 int r, n, i;
74b2466e
LP
140
141 assert(l);
142
6073b6f2 143 LIST_FOREACH(servers, s, l->dns_servers)
74b2466e
LP
144 s->marked = true;
145
a2ba62c7
LP
146 n = sd_network_get_dns(l->ifindex, &nameservers);
147 if (n < 0) {
148 r = n;
74b2466e 149 goto clear;
a2ba62c7 150 }
74b2466e
LP
151
152 for (i = 0; i < n; i++) {
153 union in_addr_union a = { .in = nameservers[i] };
154
6073b6f2 155 s = link_find_dns_server(l, AF_INET, &a);
74b2466e
LP
156 if (s)
157 s->marked = false;
158 else {
6073b6f2 159 r = dns_server_new(l->manager, NULL, l, AF_INET, &a);
74b2466e
LP
160 if (r < 0)
161 goto clear;
162 }
163 }
164
a2ba62c7
LP
165 n = sd_network_get_dns6(l->ifindex, &nameservers6);
166 if (n < 0) {
167 r = n;
74b2466e 168 goto clear;
a2ba62c7 169 }
74b2466e
LP
170
171 for (i = 0; i < n; i++) {
172 union in_addr_union a = { .in6 = nameservers6[i] };
173
6073b6f2 174 s = link_find_dns_server(l, AF_INET6, &a);
74b2466e
LP
175 if (s)
176 s->marked = false;
177 else {
6073b6f2 178 r = dns_server_new(l->manager, NULL, l, AF_INET6, &a);
74b2466e
LP
179 if (r < 0)
180 goto clear;
181 }
182 }
183
6073b6f2 184 LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
74b2466e
LP
185 if (s->marked)
186 dns_server_free(s);
187
188 return 0;
189
190clear:
6073b6f2
TG
191 while (l->dns_servers)
192 dns_server_free(l->dns_servers);
74b2466e
LP
193
194 return r;
195}
196
197int link_update_monitor(Link *l) {
198 assert(l);
199
6073b6f2 200 link_update_dns_servers(l);
1716f6dc 201 link_allocate_scopes(l);
74b2466e
LP
202
203 return 0;
204}
205
0dd25fb9 206bool link_relevant(Link *l, int family) {
1716f6dc 207 _cleanup_free_ char *state = NULL;
74b2466e
LP
208 LinkAddress *a;
209
210 assert(l);
211
212 /* A link is relevant if it isn't a loopback device and has at
213 * least one relevant IP address */
214
215 if (l->flags & IFF_LOOPBACK)
216 return false;
217
1716f6dc
LP
218 sd_network_get_link_operational_state(l->ifindex, &state);
219 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
74b2466e
LP
220 return false;
221
222 LIST_FOREACH(addresses, a, l->addresses)
1716f6dc 223 if (a->family == family && link_address_relevant(a))
74b2466e
LP
224 return true;
225
226 return false;
227}
228
0dd25fb9 229LinkAddress *link_find_address(Link *l, int family, union in_addr_union *in_addr) {
74b2466e
LP
230 LinkAddress *a;
231
232 assert(l);
233
1716f6dc
LP
234 LIST_FOREACH(addresses, a, l->addresses)
235 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
74b2466e 236 return a;
74b2466e
LP
237
238 return NULL;
239}
240
6073b6f2
TG
241DnsServer* link_find_dns_server(Link *l, int family, union in_addr_union *in_addr) {
242 DnsServer *s;
74b2466e
LP
243
244 assert(l);
245
6073b6f2 246 LIST_FOREACH(servers, s, l->dns_servers)
1716f6dc 247 if (s->family == family && in_addr_equal(family, &s->address, in_addr))
74b2466e 248 return s;
74b2466e
LP
249
250 return NULL;
251}
252
253DnsServer *link_get_dns_server(Link *l) {
254 assert(l);
255
256 if (!l->current_dns_server)
6073b6f2 257 l->current_dns_server = l->dns_servers;
74b2466e
LP
258
259 return l->current_dns_server;
260}
261
262void link_next_dns_server(Link *l) {
263 assert(l);
264
265 /* Switch to the next DNS server */
266
267 if (!l->current_dns_server) {
6073b6f2 268 l->current_dns_server = l->dns_servers;
74b2466e
LP
269 if (l->current_dns_server)
270 return;
271 }
272
273 if (!l->current_dns_server)
274 return;
275
276 if (l->current_dns_server->servers_next) {
277 l->current_dns_server = l->current_dns_server->servers_next;
278 return;
279 }
280
6073b6f2 281 l->current_dns_server = l->dns_servers;
74b2466e
LP
282}
283
0dd25fb9 284int link_address_new(Link *l, LinkAddress **ret, int family, union in_addr_union *in_addr) {
74b2466e
LP
285 LinkAddress *a;
286
287 assert(l);
288 assert(in_addr);
289
290 a = new0(LinkAddress, 1);
291 if (!a)
292 return -ENOMEM;
293
294 a->family = family;
295 a->in_addr = *in_addr;
296
297 a->link = l;
298 LIST_PREPEND(addresses, l->addresses, a);
299
300 if (ret)
301 *ret = a;
302
303 return 0;
304}
305
306LinkAddress *link_address_free(LinkAddress *a) {
307 if (!a)
308 return NULL;
309
310 if (a->link)
311 LIST_REMOVE(addresses, a->link->addresses, a);
312
313 free(a);
314 return NULL;
315}
316
317int link_address_update_rtnl(LinkAddress *a, sd_rtnl_message *m) {
318 int r;
319 assert(a);
320 assert(m);
321
322 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
323 if (r < 0)
324 return r;
325
1716f6dc 326 sd_rtnl_message_addr_get_scope(m, &a->scope);
74b2466e 327
1716f6dc 328 link_allocate_scopes(a->link);
74b2466e
LP
329 return 0;
330}
331
332bool link_address_relevant(LinkAddress *a) {
333 assert(a);
334
335 if (a->flags & IFA_F_DEPRECATED)
336 return false;
337
338 if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
339 return false;
340
341 return true;
342}