Bug Summary

File:build-scan/../src/resolve/resolved-link.c
Warning:line 83, column 24
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name resolved-link.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I systemd-resolved.p -I . -I .. -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I /usr/include/p11-kit-1 -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/resolve/resolved-link.c

../src/resolve/resolved-link.c

1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <net/if.h>
4#include <stdio_ext.h>
5
6#include "sd-network.h"
7
8#include "alloc-util.h"
9#include "fd-util.h"
10#include "fileio.h"
11#include "missing.h"
12#include "mkdir.h"
13#include "parse-util.h"
14#include "resolved-link.h"
15#include "resolved-llmnr.h"
16#include "resolved-mdns.h"
17#include "string-util.h"
18#include "strv.h"
19
20int link_new(Manager *m, Link **ret, int ifindex) {
21 _cleanup_(link_freep)__attribute__((cleanup(link_freep))) Link *l = NULL((void*)0);
22 int r;
23
24 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-link.c", 24
, __PRETTY_FUNCTION__); } while (0)
;
25 assert(ifindex > 0)do { if ((__builtin_expect(!!(!(ifindex > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ifindex > 0"), "../src/resolve/resolved-link.c"
, 25, __PRETTY_FUNCTION__); } while (0)
;
26
27 r = hashmap_ensure_allocated(&m->links, NULL)internal_hashmap_ensure_allocated(&m->links, ((void*)0
) )
;
28 if (r < 0)
29 return r;
30
31 l = new0(Link, 1)((Link*) calloc((1), sizeof(Link)));
32 if (!l)
33 return -ENOMEM12;
34
35 l->ifindex = ifindex;
36 l->llmnr_support = RESOLVE_SUPPORT_YES;
37 l->mdns_support = RESOLVE_SUPPORT_NO;
38 l->dnssec_mode = _DNSSEC_MODE_INVALID;
39 l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
40 l->operstate = IF_OPER_UNKNOWN0;
41
42 if (asprintf(&l->state_file, "/run/systemd/resolve/netif/%i", ifindex) < 0)
43 return -ENOMEM12;
44
45 r = hashmap_put(m->links, INT_TO_PTR(ifindex)((void *) ((intptr_t) (ifindex))), l);
46 if (r < 0)
47 return r;
48
49 l->manager = m;
50
51 if (ret)
52 *ret = l;
53 l = NULL((void*)0);
54
55 return 0;
56}
57
58void link_flush_settings(Link *l) {
59 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 59
, __PRETTY_FUNCTION__); } while (0)
;
60
61 l->llmnr_support = RESOLVE_SUPPORT_YES;
62 l->mdns_support = RESOLVE_SUPPORT_NO;
63 l->dnssec_mode = _DNSSEC_MODE_INVALID;
64 l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
65
66 dns_server_unlink_all(l->dns_servers);
67 dns_search_domain_unlink_all(l->search_domains);
68
69 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
70}
71
72Link *link_free(Link *l) {
73 if (!l)
1
Assuming 'l' is non-null
2
Taking false branch
74 return NULL((void*)0);
75
76 /* Send goodbye messages. */
77 dns_scope_announce(l->mdns_ipv4_scope, true1);
78 dns_scope_announce(l->mdns_ipv6_scope, true1);
79
80 link_flush_settings(l);
81
82 while (l->addresses)
3
Loop condition is true. Entering loop body
12
Loop condition is true. Entering loop body
83 (void) link_address_free(l->addresses);
4
Calling 'link_address_free'
11
Returning; memory was released via 1st parameter
13
Use of memory after it is freed
84
85 if (l->manager)
86 hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)((void *) ((intptr_t) (l->ifindex))));
87
88 dns_scope_free(l->unicast_scope);
89 dns_scope_free(l->llmnr_ipv4_scope);
90 dns_scope_free(l->llmnr_ipv6_scope);
91 dns_scope_free(l->mdns_ipv4_scope);
92 dns_scope_free(l->mdns_ipv6_scope);
93
94 free(l->state_file);
95
96 return mfree(l);
97}
98
99void link_allocate_scopes(Link *l) {
100 bool_Bool unicast_relevant;
101 int r;
102
103 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 103
, __PRETTY_FUNCTION__); } while (0)
;
104
105 /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes
106 * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers
107 * now, even if they have the same addresses as before. */
108
109 unicast_relevant = link_relevant(l, AF_UNSPEC0, false0);
110 if (unicast_relevant != l->unicast_relevant) {
111 l->unicast_relevant = unicast_relevant;
112
113 dns_server_reset_features_all(l->manager->fallback_dns_servers);
114 dns_server_reset_features_all(l->manager->dns_servers);
115
116 /* Also, flush the global unicast scope, to deal with split horizon setups, where talking through one
117 * interface reveals different DNS zones than through others. */
118 if (l->manager->unicast_scope)
119 dns_cache_flush(&l->manager->unicast_scope->cache);
120 }
121
122 /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
123 * need anymore */
124
125 if (unicast_relevant && l->dns_servers) {
126 if (!l->unicast_scope) {
127 dns_server_reset_features_all(l->dns_servers);
128
129 r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC0);
130 if (r < 0)
131 log_warning_errno(r, "Failed to allocate DNS scope: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 131, __func__, "Failed to allocate DNS scope: %m"
) : -abs(_e); })
;
132 }
133 } else
134 l->unicast_scope = dns_scope_free(l->unicast_scope);
135
136 if (link_relevant(l, AF_INET2, true1) &&
137 l->llmnr_support != RESOLVE_SUPPORT_NO &&
138 l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
139 if (!l->llmnr_ipv4_scope) {
140 r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET2);
141 if (r < 0)
142 log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 142, __func__, "Failed to allocate LLMNR IPv4 scope: %m"
) : -abs(_e); })
;
143 }
144 } else
145 l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
146
147 if (link_relevant(l, AF_INET610, true1) &&
148 l->llmnr_support != RESOLVE_SUPPORT_NO &&
149 l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
150 socket_ipv6_is_supported()) {
151 if (!l->llmnr_ipv6_scope) {
152 r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET610);
153 if (r < 0)
154 log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 154, __func__, "Failed to allocate LLMNR IPv6 scope: %m"
) : -abs(_e); })
;
155 }
156 } else
157 l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
158
159 if (link_relevant(l, AF_INET2, true1) &&
160 l->mdns_support != RESOLVE_SUPPORT_NO &&
161 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
162 if (!l->mdns_ipv4_scope) {
163 r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET2);
164 if (r < 0)
165 log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 165, __func__, "Failed to allocate mDNS IPv4 scope: %m"
) : -abs(_e); })
;
166 }
167 } else
168 l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
169
170 if (link_relevant(l, AF_INET610, true1) &&
171 l->mdns_support != RESOLVE_SUPPORT_NO &&
172 l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
173 if (!l->mdns_ipv6_scope) {
174 r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET610);
175 if (r < 0)
176 log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 176, __func__, "Failed to allocate mDNS IPv6 scope: %m"
) : -abs(_e); })
;
177 }
178 } else
179 l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
180}
181
182void link_add_rrs(Link *l, bool_Bool force_remove) {
183 LinkAddress *a;
184 int r;
185
186 LIST_FOREACH(addresses, a, l->addresses)for ((a) = (l->addresses); (a); (a) = (a)->addresses_next
)
187 link_address_add_rrs(a, force_remove);
188
189 if (!force_remove &&
190 l->mdns_support == RESOLVE_SUPPORT_YES &&
191 l->manager->mdns_support == RESOLVE_SUPPORT_YES) {
192
193 if (l->mdns_ipv4_scope) {
194 r = dns_scope_add_dnssd_services(l->mdns_ipv4_scope);
195 if (r < 0)
196 log_warning_errno(r, "Failed to add IPv4 DNS-SD services: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 196, __func__, "Failed to add IPv4 DNS-SD services: %m"
) : -abs(_e); })
;
197 }
198
199 if (l->mdns_ipv6_scope) {
200 r = dns_scope_add_dnssd_services(l->mdns_ipv6_scope);
201 if (r < 0)
202 log_warning_errno(r, "Failed to add IPv6 DNS-SD services: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 202, __func__, "Failed to add IPv6 DNS-SD services: %m"
) : -abs(_e); })
;
203 }
204
205 } else {
206
207 if (l->mdns_ipv4_scope) {
208 r = dns_scope_remove_dnssd_services(l->mdns_ipv4_scope);
209 if (r < 0)
210 log_warning_errno(r, "Failed to remove IPv4 DNS-SD services: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 210, __func__, "Failed to remove IPv4 DNS-SD services: %m"
) : -abs(_e); })
;
211 }
212
213 if (l->mdns_ipv6_scope) {
214 r = dns_scope_remove_dnssd_services(l->mdns_ipv6_scope);
215 if (r < 0)
216 log_warning_errno(r, "Failed to remove IPv6 DNS-SD services: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 216, __func__, "Failed to remove IPv6 DNS-SD services: %m"
) : -abs(_e); })
;
217 }
218 }
219}
220
221int link_process_rtnl(Link *l, sd_netlink_message *m) {
222 const char *n = NULL((void*)0);
223 int r;
224
225 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 225
, __PRETTY_FUNCTION__); } while (0)
;
226 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-link.c", 226
, __PRETTY_FUNCTION__); } while (0)
;
227
228 r = sd_rtnl_message_link_get_flags(m, &l->flags);
229 if (r < 0)
230 return r;
231
232 (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
233 (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
234
235 if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
236 strncpy(l->name, n, sizeof(l->name)-1);
237 char_array_0(l->name)l->name[sizeof(l->name)-1] = 0;;
238 }
239
240 link_allocate_scopes(l);
241 link_add_rrs(l, false0);
242
243 return 0;
244}
245
246static int link_update_dns_server_one(Link *l, const char *name) {
247 union in_addr_union a;
248 DnsServer *s;
249 int family, r;
250
251 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 251
, __PRETTY_FUNCTION__); } while (0)
;
252 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/resolve/resolved-link.c"
, 252, __PRETTY_FUNCTION__); } while (0)
;
253
254 r = in_addr_from_string_auto(name, &family, &a);
255 if (r < 0)
256 return r;
257
258 s = dns_server_find(l->dns_servers, family, &a, 0);
259 if (s) {
260 dns_server_move_back_and_unmark(s);
261 return 0;
262 }
263
264 return dns_server_new(l->manager, NULL((void*)0), DNS_SERVER_LINK, l, family, &a, 0);
265}
266
267static int link_update_dns_servers(Link *l) {
268 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **nameservers = NULL((void*)0);
269 char **nameserver;
270 int r;
271
272 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 272
, __PRETTY_FUNCTION__); } while (0)
;
273
274 r = sd_network_link_get_dns(l->ifindex, &nameservers);
275 if (r == -ENODATA61) {
276 r = 0;
277 goto clear;
278 }
279 if (r < 0)
280 goto clear;
281
282 dns_server_mark_all(l->dns_servers);
283
284 STRV_FOREACH(nameserver, nameservers)for ((nameserver) = (nameservers); (nameserver) && *(
nameserver); (nameserver)++)
{
285 r = link_update_dns_server_one(l, *nameserver);
286 if (r < 0)
287 goto clear;
288 }
289
290 dns_server_unlink_marked(l->dns_servers);
291 return 0;
292
293clear:
294 dns_server_unlink_all(l->dns_servers);
295 return r;
296}
297
298static int link_update_llmnr_support(Link *l) {
299 _cleanup_free___attribute__((cleanup(freep))) char *b = NULL((void*)0);
300 int r;
301
302 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 302
, __PRETTY_FUNCTION__); } while (0)
;
303
304 r = sd_network_link_get_llmnr(l->ifindex, &b);
305 if (r == -ENODATA61) {
306 r = 0;
307 goto clear;
308 }
309 if (r < 0)
310 goto clear;
311
312 l->llmnr_support = resolve_support_from_string(b);
313 if (l->llmnr_support < 0) {
314 r = -EINVAL22;
315 goto clear;
316 }
317
318 return 0;
319
320clear:
321 l->llmnr_support = RESOLVE_SUPPORT_YES;
322 return r;
323}
324
325static int link_update_mdns_support(Link *l) {
326 _cleanup_free___attribute__((cleanup(freep))) char *b = NULL((void*)0);
327 int r;
328
329 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 329
, __PRETTY_FUNCTION__); } while (0)
;
330
331 r = sd_network_link_get_mdns(l->ifindex, &b);
332 if (r == -ENODATA61) {
333 r = 0;
334 goto clear;
335 }
336 if (r < 0)
337 goto clear;
338
339 l->mdns_support = resolve_support_from_string(b);
340 if (l->mdns_support < 0) {
341 r = -EINVAL22;
342 goto clear;
343 }
344
345 return 0;
346
347clear:
348 l->mdns_support = RESOLVE_SUPPORT_NO;
349 return r;
350}
351
352void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) {
353
354 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 354
, __PRETTY_FUNCTION__); } while (0)
;
355
356#if ! ENABLE_DNS_OVER_TLS1
357 if (mode != DNS_OVER_TLS_NO)
358 log_warning("DNS-over-TLS option for the link cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 358, __func__, "DNS-over-TLS option for the link cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support."
) : -abs(_e); })
;
359 return;
360#endif
361
362 l->dns_over_tls_mode = mode;
363}
364
365static int link_update_dns_over_tls_mode(Link *l) {
366 _cleanup_free___attribute__((cleanup(freep))) char *b = NULL((void*)0);
367 int r;
368
369 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 369
, __PRETTY_FUNCTION__); } while (0)
;
370
371 r = sd_network_link_get_dns_over_tls(l->ifindex, &b);
372 if (r == -ENODATA61) {
373 r = 0;
374 goto clear;
375 }
376 if (r < 0)
377 goto clear;
378
379 l->dns_over_tls_mode = dns_over_tls_mode_from_string(b);
380 if (l->dns_over_tls_mode < 0) {
381 r = -EINVAL22;
382 goto clear;
383 }
384
385 return 0;
386
387clear:
388 l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
389 return r;
390}
391
392void link_set_dnssec_mode(Link *l, DnssecMode mode) {
393
394 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 394
, __PRETTY_FUNCTION__); } while (0)
;
395
396#if ! HAVE_GCRYPT1
397 if (IN_SET(mode, DNSSEC_YES, DNSSEC_ALLOW_DOWNGRADE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){DNSSEC_YES, DNSSEC_ALLOW_DOWNGRADE})/sizeof
(int)]; switch(mode) { case DNSSEC_YES: case DNSSEC_ALLOW_DOWNGRADE
: _found = 1; break; default: break; } _found; })
)
398 log_warning("DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 398, __func__, "DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support."
) : -abs(_e); })
;
399 return;
400#endif
401
402 if (l->dnssec_mode == mode)
403 return;
404
405 if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
406 (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
407 (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
408
409 /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
410 * allow-downgrade mode to full DNSSEC mode, flush it too. */
411 if (l->unicast_scope)
412 dns_cache_flush(&l->unicast_scope->cache);
413 }
414
415 l->dnssec_mode = mode;
416}
417
418static int link_update_dnssec_mode(Link *l) {
419 _cleanup_free___attribute__((cleanup(freep))) char *m = NULL((void*)0);
420 DnssecMode mode;
421 int r;
422
423 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 423
, __PRETTY_FUNCTION__); } while (0)
;
424
425 r = sd_network_link_get_dnssec(l->ifindex, &m);
426 if (r == -ENODATA61) {
427 r = 0;
428 goto clear;
429 }
430 if (r < 0)
431 goto clear;
432
433 mode = dnssec_mode_from_string(m);
434 if (mode < 0) {
435 r = -EINVAL22;
436 goto clear;
437 }
438
439 link_set_dnssec_mode(l, mode);
440
441 return 0;
442
443clear:
444 l->dnssec_mode = _DNSSEC_MODE_INVALID;
445 return r;
446}
447
448static int link_update_dnssec_negative_trust_anchors(Link *l) {
449 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **ntas = NULL((void*)0);
450 _cleanup_set_free_free___attribute__((cleanup(set_free_freep))) Set *ns = NULL((void*)0);
451 int r;
452
453 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 453
, __PRETTY_FUNCTION__); } while (0)
;
454
455 r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
456 if (r == -ENODATA61) {
457 r = 0;
458 goto clear;
459 }
460 if (r < 0)
461 goto clear;
462
463 ns = set_new(&dns_name_hash_ops)internal_set_new(&dns_name_hash_ops );
464 if (!ns)
465 return -ENOMEM12;
466
467 r = set_put_strdupv(ns, ntas);
468 if (r < 0)
469 return r;
470
471 set_free_free(l->dnssec_negative_trust_anchors);
472 l->dnssec_negative_trust_anchors = TAKE_PTR(ns)({ typeof(ns) _ptr_ = (ns); (ns) = ((void*)0); _ptr_; });
473
474 return 0;
475
476clear:
477 l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
478 return r;
479}
480
481static int link_update_search_domain_one(Link *l, const char *name, bool_Bool route_only) {
482 DnsSearchDomain *d;
483 int r;
484
485 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 485
, __PRETTY_FUNCTION__); } while (0)
;
486 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/resolve/resolved-link.c"
, 486, __PRETTY_FUNCTION__); } while (0)
;
487
488 r = dns_search_domain_find(l->search_domains, name, &d);
489 if (r < 0)
490 return r;
491 if (r > 0)
492 dns_search_domain_move_back_and_unmark(d);
493 else {
494 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
495 if (r < 0)
496 return r;
497 }
498
499 d->route_only = route_only;
500 return 0;
501}
502
503static int link_update_search_domains(Link *l) {
504 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **sdomains = NULL((void*)0), **rdomains = NULL((void*)0);
505 char **i;
506 int r, q;
507
508 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 508
, __PRETTY_FUNCTION__); } while (0)
;
509
510 r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
511 if (r < 0 && r != -ENODATA61)
512 goto clear;
513
514 q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
515 if (q < 0 && q != -ENODATA61) {
516 r = q;
517 goto clear;
518 }
519
520 if (r == -ENODATA61 && q == -ENODATA61) {
521 /* networkd knows nothing about this interface, and that's fine. */
522 r = 0;
523 goto clear;
524 }
525
526 dns_search_domain_mark_all(l->search_domains);
527
528 STRV_FOREACH(i, sdomains)for ((i) = (sdomains); (i) && *(i); (i)++) {
529 r = link_update_search_domain_one(l, *i, false0);
530 if (r < 0)
531 goto clear;
532 }
533
534 STRV_FOREACH(i, rdomains)for ((i) = (rdomains); (i) && *(i); (i)++) {
535 r = link_update_search_domain_one(l, *i, true1);
536 if (r < 0)
537 goto clear;
538 }
539
540 dns_search_domain_unlink_marked(l->search_domains);
541 return 0;
542
543clear:
544 dns_search_domain_unlink_all(l->search_domains);
545 return r;
546}
547
548static int link_is_managed(Link *l) {
549 _cleanup_free___attribute__((cleanup(freep))) char *state = NULL((void*)0);
550 int r;
551
552 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 552
, __PRETTY_FUNCTION__); } while (0)
;
553
554 r = sd_network_link_get_setup_state(l->ifindex, &state);
555 if (r == -ENODATA61)
556 return 0;
557 if (r < 0)
558 return r;
559
560 return !STR_IN_SET(state, "pending", "unmanaged")(!!strv_find((((char**) ((const char*[]) { "pending", "unmanaged"
, ((void*)0) }))), (state)))
;
561}
562
563static void link_read_settings(Link *l) {
564 int r;
565
566 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 566
, __PRETTY_FUNCTION__); } while (0)
;
567
568 /* Read settings from networkd, except when networkd is not managing this interface. */
569
570 r = link_is_managed(l);
571 if (r < 0) {
572 log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 572, __func__, "Failed to determine whether interface %s is managed: %m"
, l->name) : -abs(_e); })
;
573 return;
574 }
575 if (r == 0) {
576
577 /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
578 if (l->is_managed)
579 link_flush_settings(l);
580
581 l->is_managed = false0;
582 return;
583 }
584
585 l->is_managed = true1;
586
587 r = link_update_dns_servers(l);
588 if (r < 0)
589 log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 589, __func__, "Failed to read DNS servers for interface %s, ignoring: %m"
, l->name) : -abs(_e); })
;
590
591 r = link_update_llmnr_support(l);
592 if (r < 0)
593 log_warning_errno(r, "Failed to read LLMNR support for interface %s, ignoring: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 593, __func__, "Failed to read LLMNR support for interface %s, ignoring: %m"
, l->name) : -abs(_e); })
;
594
595 r = link_update_mdns_support(l);
596 if (r < 0)
597 log_warning_errno(r, "Failed to read mDNS support for interface %s, ignoring: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 597, __func__, "Failed to read mDNS support for interface %s, ignoring: %m"
, l->name) : -abs(_e); })
;
598
599 r = link_update_dns_over_tls_mode(l);
600 if (r < 0)
601 log_warning_errno(r, "Failed to read DNS-over-TLS mode for interface %s, ignoring: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 601, __func__, "Failed to read DNS-over-TLS mode for interface %s, ignoring: %m"
, l->name) : -abs(_e); })
;
602
603 r = link_update_dnssec_mode(l);
604 if (r < 0)
605 log_warning_errno(r, "Failed to read DNSSEC mode for interface %s, ignoring: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 605, __func__, "Failed to read DNSSEC mode for interface %s, ignoring: %m"
, l->name) : -abs(_e); })
;
606
607 r = link_update_dnssec_negative_trust_anchors(l);
608 if (r < 0)
609 log_warning_errno(r, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 609, __func__, "Failed to read DNSSEC negative trust anchors for interface %s, ignoring: %m"
, l->name) : -abs(_e); })
;
610
611 r = link_update_search_domains(l);
612 if (r < 0)
613 log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 613, __func__, "Failed to read search domains for interface %s, ignoring: %m"
, l->name) : -abs(_e); })
;
614}
615
616int link_update(Link *l) {
617 int r;
618
619 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 619
, __PRETTY_FUNCTION__); } while (0)
;
620
621 link_read_settings(l);
622 link_load_user(l);
623
624 if (l->llmnr_support != RESOLVE_SUPPORT_NO) {
625 r = manager_llmnr_start(l->manager);
626 if (r < 0)
627 return r;
628 }
629
630 if (l->mdns_support != RESOLVE_SUPPORT_NO) {
631 r = manager_mdns_start(l->manager);
632 if (r < 0)
633 return r;
634 }
635
636 link_allocate_scopes(l);
637 link_add_rrs(l, false0);
638
639 return 0;
640}
641
642bool_Bool link_relevant(Link *l, int family, bool_Bool local_multicast) {
643 _cleanup_free___attribute__((cleanup(freep))) char *state = NULL((void*)0);
644 LinkAddress *a;
645
646 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 646
, __PRETTY_FUNCTION__); } while (0)
;
647
648 /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link
649 * beat, can do multicast and has at least one link-local (or better) IP address.
650 *
651 * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
652 * least one routable address. */
653
654 if (l->flags & (IFF_LOOPBACKIFF_LOOPBACK|IFF_DORMANT0x20000))
655 return false0;
656
657 if ((l->flags & (IFF_UPIFF_UP|IFF_LOWER_UP0x10000)) != (IFF_UPIFF_UP|IFF_LOWER_UP0x10000))
658 return false0;
659
660 if (local_multicast) {
661 if ((l->flags & IFF_MULTICASTIFF_MULTICAST) != IFF_MULTICASTIFF_MULTICAST)
662 return false0;
663 }
664
665 /* Check kernel operstate
666 * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
667 if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){0, 6})/sizeof(int)]; switch(l->operstate
) { case 0: case 6: _found = 1; break; default: break; } _found
; })
)
668 return false0;
669
670 (void) sd_network_link_get_operational_state(l->ifindex, &state);
671 if (state && !STR_IN_SET(state, "unknown", "degraded", "routable")(!!strv_find((((char**) ((const char*[]) { "unknown", "degraded"
, "routable", ((void*)0) }))), (state)))
)
672 return false0;
673
674 LIST_FOREACH(addresses, a, l->addresses)for ((a) = (l->addresses); (a); (a) = (a)->addresses_next
)
675 if ((family == AF_UNSPEC0 || a->family == family) && link_address_relevant(a, local_multicast))
676 return true1;
677
678 return false0;
679}
680
681LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
682 LinkAddress *a;
683
684 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 684
, __PRETTY_FUNCTION__); } while (0)
;
685
686 LIST_FOREACH(addresses, a, l->addresses)for ((a) = (l->addresses); (a); (a) = (a)->addresses_next
)
687 if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
688 return a;
689
690 return NULL((void*)0);
691}
692
693DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
694 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 694
, __PRETTY_FUNCTION__); } while (0)
;
695
696 if (l->current_dns_server == s)
697 return s;
698
699 if (s)
700 log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 700, __func__, "Switching to DNS server %s for interface %s."
, dns_server_string(s), l->name) : -abs(_e); })
;
701
702 dns_server_unref(l->current_dns_server);
703 l->current_dns_server = dns_server_ref(s);
704
705 if (l->unicast_scope)
706 dns_cache_flush(&l->unicast_scope->cache);
707
708 return s;
709}
710
711DnsServer *link_get_dns_server(Link *l) {
712 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 712
, __PRETTY_FUNCTION__); } while (0)
;
713
714 if (!l->current_dns_server)
715 link_set_dns_server(l, l->dns_servers);
716
717 return l->current_dns_server;
718}
719
720void link_next_dns_server(Link *l) {
721 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 721
, __PRETTY_FUNCTION__); } while (0)
;
722
723 if (!l->current_dns_server)
724 return;
725
726 /* Change to the next one, but make sure to follow the linked
727 * list only if this server is actually still linked. */
728 if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
729 link_set_dns_server(l, l->current_dns_server->servers_next);
730 return;
731 }
732
733 link_set_dns_server(l, l->dns_servers);
734}
735
736DnsOverTlsMode link_get_dns_over_tls_mode(Link *l) {
737 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 737
, __PRETTY_FUNCTION__); } while (0)
;
738
739 if (l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
740 return l->dns_over_tls_mode;
741
742 return manager_get_dns_over_tls_mode(l->manager);
743}
744
745DnssecMode link_get_dnssec_mode(Link *l) {
746 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 746
, __PRETTY_FUNCTION__); } while (0)
;
747
748 if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
749 return l->dnssec_mode;
750
751 return manager_get_dnssec_mode(l->manager);
752}
753
754bool_Bool link_dnssec_supported(Link *l) {
755 DnsServer *server;
756
757 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 757
, __PRETTY_FUNCTION__); } while (0)
;
758
759 if (link_get_dnssec_mode(l) == DNSSEC_NO)
760 return false0;
761
762 server = link_get_dns_server(l);
763 if (server)
764 return dns_server_dnssec_supported(server);
765
766 return true1;
767}
768
769int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
770 LinkAddress *a;
771
772 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 772
, __PRETTY_FUNCTION__); } while (0)
;
773 assert(in_addr)do { if ((__builtin_expect(!!(!(in_addr)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("in_addr"), "../src/resolve/resolved-link.c"
, 773, __PRETTY_FUNCTION__); } while (0)
;
774
775 a = new0(LinkAddress, 1)((LinkAddress*) calloc((1), sizeof(LinkAddress)));
776 if (!a)
777 return -ENOMEM12;
778
779 a->family = family;
780 a->in_addr = *in_addr;
781
782 a->link = l;
783 LIST_PREPEND(addresses, l->addresses, a)do { typeof(*(l->addresses)) **_head = &(l->addresses
), *_item = (a); do { if ((__builtin_expect(!!(!(_item)),0)))
log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/resolve/resolved-link.c"
, 783, __PRETTY_FUNCTION__); } while (0); if ((_item->addresses_next
= *_head)) _item->addresses_next->addresses_prev = _item
; _item->addresses_prev = ((void*)0); *_head = _item; } while
(0)
;
784 l->n_addresses++;
785
786 if (ret)
787 *ret = a;
788
789 return 0;
790}
791
792LinkAddress *link_address_free(LinkAddress *a) {
793 if (!a
4.1
'a' is non-null
4.1
'a' is non-null
)
5
Taking false branch
794 return NULL((void*)0);
795
796 if (a->link) {
6
Assuming field 'link' is null
7
Taking false branch
797 LIST_REMOVE(addresses, a->link->addresses, a)do { typeof(*(a->link->addresses)) **_head = &(a->
link->addresses), *_item = (a); do { if ((__builtin_expect
(!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("_item"), "../src/resolve/resolved-link.c", 797, __PRETTY_FUNCTION__
); } while (0); if (_item->addresses_next) _item->addresses_next
->addresses_prev = _item->addresses_prev; if (_item->
addresses_prev) _item->addresses_prev->addresses_next =
_item->addresses_next; else { do { if ((__builtin_expect(
!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("*_head == _item"), "../src/resolve/resolved-link.c", 797,
__PRETTY_FUNCTION__); } while (0); *_head = _item->addresses_next
; } _item->addresses_next = _item->addresses_prev = ((void
*)0); } while (0)
;
798
799 assert(a->link->n_addresses > 0)do { if ((__builtin_expect(!!(!(a->link->n_addresses >
0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("a->link->n_addresses > 0"
), "../src/resolve/resolved-link.c", 799, __PRETTY_FUNCTION__
); } while (0)
;
800 a->link->n_addresses--;
801
802 if (a->llmnr_address_rr) {
803 if (a->family == AF_INET2 && a->link->llmnr_ipv4_scope)
804 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
805 else if (a->family == AF_INET610 && a->link->llmnr_ipv6_scope)
806 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
807 }
808
809 if (a->llmnr_ptr_rr) {
810 if (a->family == AF_INET2 && a->link->llmnr_ipv4_scope)
811 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
812 else if (a->family == AF_INET610 && a->link->llmnr_ipv6_scope)
813 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
814 }
815
816 if (a->mdns_address_rr) {
817 if (a->family == AF_INET2 && a->link->mdns_ipv4_scope)
818 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
819 else if (a->family == AF_INET610 && a->link->mdns_ipv6_scope)
820 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
821 }
822
823 if (a->mdns_ptr_rr) {
824 if (a->family == AF_INET2 && a->link->mdns_ipv4_scope)
825 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
826 else if (a->family == AF_INET610 && a->link->mdns_ipv6_scope)
827 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
828 }
829 }
830
831 dns_resource_record_unref(a->llmnr_address_rr);
832 dns_resource_record_unref(a->llmnr_ptr_rr);
833 dns_resource_record_unref(a->mdns_address_rr);
834 dns_resource_record_unref(a->mdns_ptr_rr);
835
836 return mfree(a);
8
Calling 'mfree'
10
Returning; memory was released via 1st parameter
837}
838
839void link_address_add_rrs(LinkAddress *a, bool_Bool force_remove) {
840 int r;
841
842 assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-link.c", 842
, __PRETTY_FUNCTION__); } while (0)
;
843
844 if (a->family == AF_INET2) {
845
846 if (!force_remove &&
847 link_address_relevant(a, true1) &&
848 a->link->llmnr_ipv4_scope &&
849 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
850 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
851
852 if (!a->link->manager->llmnr_host_ipv4_key) {
853 a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
854 if (!a->link->manager->llmnr_host_ipv4_key) {
855 r = -ENOMEM12;
856 goto fail;
857 }
858 }
859
860 if (!a->llmnr_address_rr) {
861 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
862 if (!a->llmnr_address_rr) {
863 r = -ENOMEM12;
864 goto fail;
865 }
866
867 a->llmnr_address_rr->a.in_addr = a->in_addr.in;
868 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL(30);
869 }
870
871 if (!a->llmnr_ptr_rr) {
872 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
873 if (r < 0)
874 goto fail;
875
876 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL(30);
877 }
878
879 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true1);
880 if (r < 0)
881 log_warning_errno(r, "Failed to add A record to LLMNR zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 881, __func__, "Failed to add A record to LLMNR zone: %m"
) : -abs(_e); })
;
882
883 r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false0);
884 if (r < 0)
885 log_warning_errno(r, "Failed to add IPv4 PTR record to LLMNR zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 885, __func__, "Failed to add IPv4 PTR record to LLMNR zone: %m"
) : -abs(_e); })
;
886 } else {
887 if (a->llmnr_address_rr) {
888 if (a->link->llmnr_ipv4_scope)
889 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
890 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
891 }
892
893 if (a->llmnr_ptr_rr) {
894 if (a->link->llmnr_ipv4_scope)
895 dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
896 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
897 }
898 }
899
900 if (!force_remove &&
901 link_address_relevant(a, true1) &&
902 a->link->mdns_ipv4_scope &&
903 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
904 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
905 if (!a->link->manager->mdns_host_ipv4_key) {
906 a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname);
907 if (!a->link->manager->mdns_host_ipv4_key) {
908 r = -ENOMEM12;
909 goto fail;
910 }
911 }
912
913 if (!a->mdns_address_rr) {
914 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key);
915 if (!a->mdns_address_rr) {
916 r = -ENOMEM12;
917 goto fail;
918 }
919
920 a->mdns_address_rr->a.in_addr = a->in_addr.in;
921 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL(120);
922 }
923
924 if (!a->mdns_ptr_rr) {
925 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
926 if (r < 0)
927 goto fail;
928
929 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL(120);
930 }
931
932 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true1);
933 if (r < 0)
934 log_warning_errno(r, "Failed to add A record to MDNS zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 934, __func__, "Failed to add A record to MDNS zone: %m"
) : -abs(_e); })
;
935
936 r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false0);
937 if (r < 0)
938 log_warning_errno(r, "Failed to add IPv4 PTR record to MDNS zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 938, __func__, "Failed to add IPv4 PTR record to MDNS zone: %m"
) : -abs(_e); })
;
939 } else {
940 if (a->mdns_address_rr) {
941 if (a->link->mdns_ipv4_scope)
942 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
943 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
944 }
945
946 if (a->mdns_ptr_rr) {
947 if (a->link->mdns_ipv4_scope)
948 dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
949 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
950 }
951 }
952 }
953
954 if (a->family == AF_INET610) {
955
956 if (!force_remove &&
957 link_address_relevant(a, true1) &&
958 a->link->llmnr_ipv6_scope &&
959 a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
960 a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
961
962 if (!a->link->manager->llmnr_host_ipv6_key) {
963 a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
964 if (!a->link->manager->llmnr_host_ipv6_key) {
965 r = -ENOMEM12;
966 goto fail;
967 }
968 }
969
970 if (!a->llmnr_address_rr) {
971 a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
972 if (!a->llmnr_address_rr) {
973 r = -ENOMEM12;
974 goto fail;
975 }
976
977 a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
978 a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL(30);
979 }
980
981 if (!a->llmnr_ptr_rr) {
982 r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
983 if (r < 0)
984 goto fail;
985
986 a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL(30);
987 }
988
989 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true1);
990 if (r < 0)
991 log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 991, __func__, "Failed to add AAAA record to LLMNR zone: %m"
) : -abs(_e); })
;
992
993 r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false0);
994 if (r < 0)
995 log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 995, __func__, "Failed to add IPv6 PTR record to LLMNR zone: %m"
) : -abs(_e); })
;
996 } else {
997 if (a->llmnr_address_rr) {
998 if (a->link->llmnr_ipv6_scope)
999 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
1000 a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
1001 }
1002
1003 if (a->llmnr_ptr_rr) {
1004 if (a->link->llmnr_ipv6_scope)
1005 dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
1006 a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
1007 }
1008 }
1009
1010 if (!force_remove &&
1011 link_address_relevant(a, true1) &&
1012 a->link->mdns_ipv6_scope &&
1013 a->link->mdns_support == RESOLVE_SUPPORT_YES &&
1014 a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
1015
1016 if (!a->link->manager->mdns_host_ipv6_key) {
1017 a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname);
1018 if (!a->link->manager->mdns_host_ipv6_key) {
1019 r = -ENOMEM12;
1020 goto fail;
1021 }
1022 }
1023
1024 if (!a->mdns_address_rr) {
1025 a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key);
1026 if (!a->mdns_address_rr) {
1027 r = -ENOMEM12;
1028 goto fail;
1029 }
1030
1031 a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6;
1032 a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL(120);
1033 }
1034
1035 if (!a->mdns_ptr_rr) {
1036 r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
1037 if (r < 0)
1038 goto fail;
1039
1040 a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL(120);
1041 }
1042
1043 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true1);
1044 if (r < 0)
1045 log_warning_errno(r, "Failed to add AAAA record to MDNS zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 1045, __func__, "Failed to add AAAA record to MDNS zone: %m"
) : -abs(_e); })
;
1046
1047 r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false0);
1048 if (r < 0)
1049 log_warning_errno(r, "Failed to add IPv6 PTR record to MDNS zone: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 1049, __func__, "Failed to add IPv6 PTR record to MDNS zone: %m"
) : -abs(_e); })
;
1050 } else {
1051 if (a->mdns_address_rr) {
1052 if (a->link->mdns_ipv6_scope)
1053 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
1054 a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
1055 }
1056
1057 if (a->mdns_ptr_rr) {
1058 if (a->link->mdns_ipv6_scope)
1059 dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
1060 a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
1061 }
1062 }
1063 }
1064
1065 return;
1066
1067fail:
1068 log_debug_errno(r, "Failed to update address RRs: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 1068, __func__, "Failed to update address RRs: %m"
) : -abs(_e); })
;
1069}
1070
1071int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
1072 int r;
1073 assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-link.c", 1073
, __PRETTY_FUNCTION__); } while (0)
;
1074 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-link.c", 1074
, __PRETTY_FUNCTION__); } while (0)
;
1075
1076 r = sd_rtnl_message_addr_get_flags(m, &a->flags);
1077 if (r < 0)
1078 return r;
1079
1080 sd_rtnl_message_addr_get_scope(m, &a->scope);
1081
1082 link_allocate_scopes(a->link);
1083 link_add_rrs(a->link, false0);
1084
1085 return 0;
1086}
1087
1088bool_Bool link_address_relevant(LinkAddress *a, bool_Bool local_multicast) {
1089 assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-link.c", 1089
, __PRETTY_FUNCTION__); } while (0)
;
1090
1091 if (a->flags & (IFA_F_DEPRECATED0x20|IFA_F_TENTATIVE0x40))
1092 return false0;
1093
1094 if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
1095 return false0;
1096
1097 return true1;
1098}
1099
1100static bool_Bool link_needs_save(Link *l) {
1101 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 1101
, __PRETTY_FUNCTION__); } while (0)
;
1102
1103 /* Returns true if any of the settings where set different from the default */
1104
1105 if (l->is_managed)
1106 return false0;
1107
1108 if (l->llmnr_support != RESOLVE_SUPPORT_YES ||
1109 l->mdns_support != RESOLVE_SUPPORT_NO ||
1110 l->dnssec_mode != _DNSSEC_MODE_INVALID)
1111 return true1;
1112
1113 if (l->dns_servers ||
1114 l->search_domains)
1115 return true1;
1116
1117 if (!set_isempty(l->dnssec_negative_trust_anchors))
1118 return true1;
1119
1120 return false0;
1121}
1122
1123int link_save_user(Link *l) {
1124 _cleanup_free___attribute__((cleanup(freep))) char *temp_path = NULL((void*)0);
1125 _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0);
1126 const char *v;
1127 int r;
1128
1129 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 1129
, __PRETTY_FUNCTION__); } while (0)
;
1130 assert(l->state_file)do { if ((__builtin_expect(!!(!(l->state_file)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l->state_file"), "../src/resolve/resolved-link.c"
, 1130, __PRETTY_FUNCTION__); } while (0)
;
1131
1132 if (!link_needs_save(l)) {
1133 (void) unlink(l->state_file);
1134 return 0;
1135 }
1136
1137 r = mkdir_parents(l->state_file, 0700);
1138 if (r < 0)
1139 goto fail;
1140
1141 r = fopen_temporary(l->state_file, &f, &temp_path);
1142 if (r < 0)
1143 goto fail;
1144
1145 (void) __fsetlocking(f, FSETLOCKING_BYCALLERFSETLOCKING_BYCALLER);
1146 (void) fchmod(fileno(f), 0644);
1147
1148 fputs("# This is private data. Do not parse.\n", f);
1149
1150 v = resolve_support_to_string(l->llmnr_support);
1151 if (v)
1152 fprintf(f, "LLMNR=%s\n", v);
1153
1154 v = resolve_support_to_string(l->mdns_support);
1155 if (v)
1156 fprintf(f, "MDNS=%s\n", v);
1157
1158 v = dnssec_mode_to_string(l->dnssec_mode);
1159 if (v)
1160 fprintf(f, "DNSSEC=%s\n", v);
1161
1162 if (l->dns_servers) {
1163 DnsServer *server;
1164
1165 fputs("SERVERS=", f);
1166 LIST_FOREACH(servers, server, l->dns_servers)for ((server) = (l->dns_servers); (server); (server) = (server
)->servers_next)
{
1167
1168 if (server != l->dns_servers)
1169 fputc(' ', f);
1170
1171 v = dns_server_string(server);
1172 if (!v) {
1173 r = -ENOMEM12;
1174 goto fail;
1175 }
1176
1177 fputs(v, f);
1178 }
1179 fputc('\n', f);
1180 }
1181
1182 if (l->search_domains) {
1183 DnsSearchDomain *domain;
1184
1185 fputs("DOMAINS=", f);
1186 LIST_FOREACH(domains, domain, l->search_domains)for ((domain) = (l->search_domains); (domain); (domain) = (
domain)->domains_next)
{
1187
1188 if (domain != l->search_domains)
1189 fputc(' ', f);
1190
1191 if (domain->route_only)
1192 fputc('~', f);
1193
1194 fputs(DNS_SEARCH_DOMAIN_NAME(domain), f);
1195 }
1196 fputc('\n', f);
1197 }
1198
1199 if (!set_isempty(l->dnssec_negative_trust_anchors)) {
1200 bool_Bool space = false0;
1201 Iterator i;
1202 char *nta;
1203
1204 fputs("NTAS=", f);
1205 SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), .
next_key = ((void*)0) }); set_iterate((l->dnssec_negative_trust_anchors
), &(i), (void**)&(nta)); )
{
1206
1207 if (space)
1208 fputc(' ', f);
1209
1210 fputs(nta, f);
1211 space = true1;
1212 }
1213 fputc('\n', f);
1214 }
1215
1216 r = fflush_and_check(f);
1217 if (r < 0)
1218 goto fail;
1219
1220 if (rename(temp_path, l->state_file) < 0) {
1221 r = -errno(*__errno_location ());
1222 goto fail;
1223 }
1224
1225 return 0;
1226
1227fail:
1228 (void) unlink(l->state_file);
1229
1230 if (temp_path)
1231 (void) unlink(temp_path);
1232
1233 return log_error_errno(r, "Failed to save link data %s: %m", l->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 1233, __func__, "Failed to save link data %s: %m"
, l->state_file) : -abs(_e); })
;
1234}
1235
1236int link_load_user(Link *l) {
1237 _cleanup_free___attribute__((cleanup(freep))) char
1238 *llmnr = NULL((void*)0),
1239 *mdns = NULL((void*)0),
1240 *dnssec = NULL((void*)0),
1241 *servers = NULL((void*)0),
1242 *domains = NULL((void*)0),
1243 *ntas = NULL((void*)0);
1244
1245 ResolveSupport s;
1246 const char *p;
1247 int r;
1248
1249 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 1249
, __PRETTY_FUNCTION__); } while (0)
;
1250 assert(l->state_file)do { if ((__builtin_expect(!!(!(l->state_file)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l->state_file"), "../src/resolve/resolved-link.c"
, 1250, __PRETTY_FUNCTION__); } while (0)
;
1251
1252 /* Try to load only a single time */
1253 if (l->loaded)
1254 return 0;
1255 l->loaded = true1;
1256
1257 if (l->is_managed)
1258 return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1259
1260 r = parse_env_file(NULL((void*)0), l->state_file, NEWLINE"\n\r",
1261 "LLMNR", &llmnr,
1262 "MDNS", &mdns,
1263 "DNSSEC", &dnssec,
1264 "SERVERS", &servers,
1265 "DOMAINS", &domains,
1266 "NTAS", &ntas,
1267 NULL((void*)0));
1268 if (r == -ENOENT2)
1269 return 0;
1270 if (r < 0)
1271 goto fail;
1272
1273 link_flush_settings(l);
1274
1275 /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1276 s = resolve_support_from_string(llmnr);
1277 if (s >= 0)
1278 l->llmnr_support = s;
1279
1280 s = resolve_support_from_string(mdns);
1281 if (s >= 0)
1282 l->mdns_support = s;
1283
1284 /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */
1285 l->dnssec_mode = dnssec_mode_from_string(dnssec);
1286
1287 for (p = servers;;) {
1288 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0);
1289
1290 r = extract_first_word(&p, &word, NULL((void*)0), 0);
1291 if (r < 0)
1292 goto fail;
1293 if (r == 0)
1294 break;
1295
1296 r = link_update_dns_server_one(l, word);
1297 if (r < 0) {
1298 log_debug_errno(r, "Failed to load DNS server '%s', ignoring: %m", word)({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 1298, __func__, "Failed to load DNS server '%s', ignoring: %m"
, word) : -abs(_e); })
;
1299 continue;
1300 }
1301 }
1302
1303 for (p = domains;;) {
1304 _cleanup_free___attribute__((cleanup(freep))) char *word = NULL((void*)0);
1305 const char *n;
1306 bool_Bool is_route;
1307
1308 r = extract_first_word(&p, &word, NULL((void*)0), 0);
1309 if (r < 0)
1310 goto fail;
1311 if (r == 0)
1312 break;
1313
1314 is_route = word[0] == '~';
1315 n = is_route ? word + 1 : word;
1316
1317 r = link_update_search_domain_one(l, n, is_route);
1318 if (r < 0) {
1319 log_debug_errno(r, "Failed to load search domain '%s', ignoring: %m", word)({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 1319, __func__, "Failed to load search domain '%s', ignoring: %m"
, word) : -abs(_e); })
;
1320 continue;
1321 }
1322 }
1323
1324 if (ntas) {
1325 _cleanup_set_free_free___attribute__((cleanup(set_free_freep))) Set *ns = NULL((void*)0);
1326
1327 ns = set_new(&dns_name_hash_ops)internal_set_new(&dns_name_hash_ops );
1328 if (!ns) {
1329 r = -ENOMEM12;
1330 goto fail;
1331 }
1332
1333 r = set_put_strsplit(ns, ntas, NULL((void*)0), 0);
1334 if (r < 0)
1335 goto fail;
1336
1337 l->dnssec_negative_trust_anchors = TAKE_PTR(ns)({ typeof(ns) _ptr_ = (ns); (ns) = ((void*)0); _ptr_; });
1338 }
1339
1340 return 0;
1341
1342fail:
1343 return log_error_errno(r, "Failed to load link data %s: %m", l->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/resolve/resolved-link.c", 1343, __func__, "Failed to load link data %s: %m"
, l->state_file) : -abs(_e); })
;
1344}
1345
1346void link_remove_user(Link *l) {
1347 assert(l)do { if ((__builtin_expect(!!(!(l)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l"), "../src/resolve/resolved-link.c", 1347
, __PRETTY_FUNCTION__); } while (0)
;
1348 assert(l->state_file)do { if ((__builtin_expect(!!(!(l->state_file)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("l->state_file"), "../src/resolve/resolved-link.c"
, 1348, __PRETTY_FUNCTION__); } while (0)
;
1349
1350 (void) unlink(l->state_file);
1351}

../src/basic/alloc-util.h

1/* SPDX-License-Identifier: LGPL-2.1+ */
2#pragma once
3
4#include <alloca.h>
5#include <stddef.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "macro.h"
10
11#define new(t, n)((t*) malloc_multiply(sizeof(t), (n))) ((t*) malloc_multiply(sizeof(t), (n)))
12
13#define new0(t, n)((t*) calloc((n), sizeof(t))) ((t*) calloc((n), sizeof(t)))
14
15#define newa(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 15, __PRETTY_FUNCTION__); } while
(0); (t*) __builtin_alloca (sizeof(t)*(n)); })
\
16 ({ \
17 assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 17, __PRETTY_FUNCTION__); } while
(0)
; \
18 (t*) alloca(sizeof(t)*(n))__builtin_alloca (sizeof(t)*(n)); \
19 })
20
21#define newa0(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 21, __PRETTY_FUNCTION__); } while
(0); (t*) ({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_
= __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_)
; }); })
\
22 ({ \
23 assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof
(t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)"
), "../src/basic/alloc-util.h", 23, __PRETTY_FUNCTION__); } while
(0)
; \
24 (t*) alloca0(sizeof(t)*(n))({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca
(_len_); (void *) memset(_new_, 0, _len_); })
; \
25 })
26
27#define newdup(t, p, n)((t*) memdup_multiply(p, sizeof(t), (n))) ((t*) memdup_multiply(p, sizeof(t), (n)))
28
29#define newdup_suffix0(t, p, n)((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n)))
30
31#define malloc0(n)(calloc(1, (n))) (calloc(1, (n)))
32
33static inline void *mfree(void *memory) {
34 free(memory);
9
Memory is released
35 return NULL((void*)0);
36}
37
38#define free_and_replace(a, b)({ free(a); (a) = (b); (b) = ((void*)0); 0; }) \
39 ({ \
40 free(a); \
41 (a) = (b); \
42 (b) = NULL((void*)0); \
43 0; \
44 })
45
46void* memdup(const void *p, size_t l) _alloc_(2);
47void* memdup_suffix0(const void *p, size_t l) _alloc_(2);
48
49static inline void freep(void *p) {
50 free(*(void**) p);
51}
52
53#define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep)))
54
55static inline bool_Bool size_multiply_overflow(size_t size, size_t need) {
56 return _unlikely_(need != 0 && size > (SIZE_MAX / need))(__builtin_expect(!!(need != 0 && size > ((18446744073709551615UL
) / need)),0))
;
57}
58
59_malloc___attribute__ ((malloc)) _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
60 if (size_multiply_overflow(size, need))
61 return NULL((void*)0);
62
63 return malloc(size * need);
64}
65
66#if !HAVE_REALLOCARRAY1
67_alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) {
68 if (size_multiply_overflow(size, need))
69 return NULL((void*)0);
70
71 return realloc(p, size * need);
72}
73#endif
74
75_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
76 if (size_multiply_overflow(size, need))
77 return NULL((void*)0);
78
79 return memdup(p, size * need);
80}
81
82_alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) {
83 if (size_multiply_overflow(size, need))
84 return NULL((void*)0);
85
86 return memdup_suffix0(p, size * need);
87}
88
89void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
90void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size);
91
92#define GREEDY_REALLOC(array, allocated, need)greedy_realloc((void**) &(array), &(allocated), (need
), sizeof((array)[0]))
\
93 greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0]))
94
95#define GREEDY_REALLOC0(array, allocated, need)greedy_realloc0((void**) &(array), &(allocated), (need
), sizeof((array)[0]))
\
96 greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0]))
97
98#define alloca0(n)({ char *_new_; size_t _len_ = n; _new_ = __builtin_alloca (_len_
); (void *) memset(_new_, 0, _len_); })
\
99 ({ \
100 char *_new_; \
101 size_t _len_ = n; \
102 _new_ = alloca(_len_)__builtin_alloca (_len_); \
103 (void *) memset(_new_, 0, _len_); \
104 })
105
106/* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */
107#define alloca_align(size, align)({ void *_ptr_; size_t _mask_ = (align) - 1; _ptr_ = __builtin_alloca
((size) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) &
~_mask_); })
\
108 ({ \
109 void *_ptr_; \
110 size_t _mask_ = (align) - 1; \
111 _ptr_ = alloca((size) + _mask_)__builtin_alloca ((size) + _mask_); \
112 (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \
113 })
114
115#define alloca0_align(size, align)({ void *_new_; size_t _size_ = (size); _new_ = ({ void *_ptr_
; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_
) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_
); }); (void*)memset(_new_, 0, _size_); })
\
116 ({ \
117 void *_new_; \
118 size_t _size_ = (size); \
119 _new_ = alloca_align(_size_, (align))({ void *_ptr_; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca
((_size_) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) &
~_mask_); })
; \
120 (void*)memset(_new_, 0, _size_); \
121 })
122
123/* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to
124 * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */
125#define TAKE_PTR(ptr)({ typeof(ptr) _ptr_ = (ptr); (ptr) = ((void*)0); _ptr_; }) \
126 ({ \
127 typeof(ptr) _ptr_ = (ptr); \
128 (ptr) = NULL((void*)0); \
129 _ptr_; \
130 })