Bug Summary

File:build-scan/../src/resolve/resolved-mdns.c
Warning:line 149, column 32
Potential leak of memory pointed to by 'list'

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-mdns.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-mdns.c

../src/resolve/resolved-mdns.c

1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <resolv.h>
4#include <netinet/in.h>
5#include <arpa/inet.h>
6
7#include "alloc-util.h"
8#include "fd-util.h"
9#include "resolved-manager.h"
10#include "resolved-mdns.h"
11
12#define CLEAR_CACHE_FLUSH(x)(~(1 << 15) & (x)) (~MDNS_RR_CACHE_FLUSH(1 << 15) & (x))
13
14void manager_mdns_stop(Manager *m) {
15 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-mdns.c", 15
, __PRETTY_FUNCTION__); } while (0)
;
16
17 m->mdns_ipv4_event_source = sd_event_source_unref(m->mdns_ipv4_event_source);
18 m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd);
19
20 m->mdns_ipv6_event_source = sd_event_source_unref(m->mdns_ipv6_event_source);
21 m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd);
22}
23
24int manager_mdns_start(Manager *m) {
25 int r;
26
27 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-mdns.c", 27
, __PRETTY_FUNCTION__); } while (0)
;
28
29 if (m->mdns_support == RESOLVE_SUPPORT_NO)
30 return 0;
31
32 r = manager_mdns_ipv4_fd(m);
33 if (r == -EADDRINUSE98)
34 goto eaddrinuse;
35 if (r < 0)
36 return r;
37
38 if (socket_ipv6_is_supported()) {
39 r = manager_mdns_ipv6_fd(m);
40 if (r == -EADDRINUSE98)
41 goto eaddrinuse;
42 if (r < 0)
43 return r;
44 }
45
46 return 0;
47
48eaddrinuse:
49 log_warning("Another mDNS responder prohibits binding the socket to the same port. Turning off mDNS 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-mdns.c", 49, __func__, "Another mDNS responder prohibits binding the socket to the same port. Turning off mDNS support."
) : -abs(_e); })
;
50 m->mdns_support = RESOLVE_SUPPORT_NO;
51 manager_mdns_stop(m);
52
53 return 0;
54}
55
56static int mdns_rr_compare(const void *a, const void *b) {
57 DnsResourceRecord **x = (DnsResourceRecord**) a, **y = (DnsResourceRecord**) b;
58 size_t m;
59 int r;
60
61 assert(x)do { if ((__builtin_expect(!!(!(x)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("x"), "../src/resolve/resolved-mdns.c", 61
, __PRETTY_FUNCTION__); } while (0)
;
62 assert(*x)do { if ((__builtin_expect(!!(!(*x)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("*x"), "../src/resolve/resolved-mdns.c",
62, __PRETTY_FUNCTION__); } while (0)
;
63 assert(y)do { if ((__builtin_expect(!!(!(y)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("y"), "../src/resolve/resolved-mdns.c", 63
, __PRETTY_FUNCTION__); } while (0)
;
64 assert(*y)do { if ((__builtin_expect(!!(!(*y)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("*y"), "../src/resolve/resolved-mdns.c",
64, __PRETTY_FUNCTION__); } while (0)
;
65
66 if (CLEAR_CACHE_FLUSH((*x)->key->class)(~(1 << 15) & ((*x)->key->class)) < CLEAR_CACHE_FLUSH((*y)->key->class)(~(1 << 15) & ((*y)->key->class)))
67 return -1;
68 else if (CLEAR_CACHE_FLUSH((*x)->key->class)(~(1 << 15) & ((*x)->key->class)) > CLEAR_CACHE_FLUSH((*y)->key->class)(~(1 << 15) & ((*y)->key->class)))
69 return 1;
70
71 if ((*x)->key->type < (*y)->key->type)
72 return -1;
73 else if ((*x)->key->type > (*y)->key->type)
74 return 1;
75
76 r = dns_resource_record_to_wire_format(*x, false0);
77 if (r < 0) {
78 log_warning_errno(r, "Can't wire-format RR: %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-mdns.c", 78, __func__, "Can't wire-format RR: %m"
) : -abs(_e); })
;
79 return 0;
80 }
81
82 r = dns_resource_record_to_wire_format(*y, false0);
83 if (r < 0) {
84 log_warning_errno(r, "Can't wire-format RR: %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-mdns.c", 84, __func__, "Can't wire-format RR: %m"
) : -abs(_e); })
;
85 return 0;
86 }
87
88 m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(*x), DNS_RESOURCE_RECORD_RDATA_SIZE(*y))__extension__ ({ const typeof((DNS_RESOURCE_RECORD_RDATA_SIZE
(*x))) __unique_prefix_A13 = ((DNS_RESOURCE_RECORD_RDATA_SIZE
(*x))); const typeof((DNS_RESOURCE_RECORD_RDATA_SIZE(*y))) __unique_prefix_B14
= ((DNS_RESOURCE_RECORD_RDATA_SIZE(*y))); __unique_prefix_A13
< __unique_prefix_B14 ? __unique_prefix_A13 : __unique_prefix_B14
; })
;
89
90 r = memcmp(DNS_RESOURCE_RECORD_RDATA(*x), DNS_RESOURCE_RECORD_RDATA(*y), m);
91 if (r != 0)
92 return r;
93
94 if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) < DNS_RESOURCE_RECORD_RDATA_SIZE(*y))
95 return -1;
96 else if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) > DNS_RESOURCE_RECORD_RDATA_SIZE(*y))
97 return 1;
98
99 return 0;
100}
101
102static int proposed_rrs_cmp(DnsResourceRecord **x, unsigned x_size, DnsResourceRecord **y, unsigned y_size) {
103 unsigned m;
104 int r;
105
106 m = MIN(x_size, y_size)__extension__ ({ const typeof((x_size)) __unique_prefix_A15 =
((x_size)); const typeof((y_size)) __unique_prefix_B16 = ((y_size
)); __unique_prefix_A15 < __unique_prefix_B16 ? __unique_prefix_A15
: __unique_prefix_B16; })
;
107 for (unsigned i = 0; i < m; i++) {
108 r = mdns_rr_compare(&x[i], &y[i]);
109 if (r != 0)
110 return r;
111 }
112
113 if (x_size < y_size)
114 return -1;
115 if (x_size > y_size)
116 return 1;
117
118 return 0;
119}
120
121static int mdns_packet_extract_matching_rrs(DnsPacket *p, DnsResourceKey *key, DnsResourceRecord ***ret_rrs) {
122 _cleanup_free___attribute__((cleanup(freep))) DnsResourceRecord **list = NULL((void*)0);
123 unsigned n = 0, size = 0;
124 int r;
125
126 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-mdns.c", 126
, __PRETTY_FUNCTION__); } while (0)
;
36
Taking false branch
37
Loop condition is false. Exiting loop
127 assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-mdns.c"
, 127, __PRETTY_FUNCTION__); } while (0)
;
38
Assuming 'key' is non-null
39
Taking false branch
40
Loop condition is false. Exiting loop
128 assert(ret_rrs)do { if ((__builtin_expect(!!(!(ret_rrs)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_rrs"), "../src/resolve/resolved-mdns.c"
, 128, __PRETTY_FUNCTION__); } while (0)
;
41
Taking false branch
42
Loop condition is false. Exiting loop
129 assert_return(DNS_PACKET_NSCOUNT(p) > 0, -EINVAL)do { if (!(((__builtin_expect(!!(be16toh(((DnsPacketHeader*) DNS_PACKET_DATA
(p))->nscount) > 0),1))) ? (1) : (log_assert_failed_return_realm
(LOG_REALM_SYSTEMD, ("DNS_PACKET_NSCOUNT(p) > 0"), "../src/resolve/resolved-mdns.c"
, 129, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
43
'?' condition is true
44
Taking false branch
45
Loop condition is false. Exiting loop
130
131 for (size_t i = DNS_PACKET_ANCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->ancount); i < (DNS_PACKET_ANCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->ancount) + DNS_PACKET_NSCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->nscount)); i++) {
46
Assuming the condition is true
47
Loop condition is true. Entering loop body
52
Assuming the condition is false
53
Loop condition is false. Execution continues on line 139
132 r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL((void*)0));
133 if (r < 0)
48
Assuming 'r' is >= 0
49
Taking false branch
134 return r;
135 if (r > 0)
50
Assuming 'r' is > 0
51
Taking true branch
136 size++;
137 }
138
139 if (size
53.1
'size' is not equal to 0
53.1
'size' is not equal to 0
== 0)
54
Taking false branch
140 return 0;
141
142 list = new(DnsResourceRecord *, size)((DnsResourceRecord **) malloc_multiply(sizeof(DnsResourceRecord
*), (size)))
;
55
Calling 'malloc_multiply'
59
Returned allocated memory
143 if (!list)
60
Assuming 'list' is non-null
61
Taking false branch
144 return -ENOMEM12;
145
146 for (size_t i = DNS_PACKET_ANCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->ancount); i < (DNS_PACKET_ANCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->ancount) + DNS_PACKET_NSCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->nscount)); i++) {
62
Loop condition is true. Entering loop body
147 r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL((void*)0));
148 if (r < 0)
63
Assuming 'r' is < 0
64
Taking true branch
149 return r;
65
Potential leak of memory pointed to by 'list'
150 if (r > 0)
151 list[n++] = p->answer->items[i].rr;
152 }
153 assert(n == size)do { if ((__builtin_expect(!!(!(n == size)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("n == size"), "../src/resolve/resolved-mdns.c"
, 153, __PRETTY_FUNCTION__); } while (0)
;
154 qsort_safe(list, size, sizeof(DnsResourceRecord*), mdns_rr_compare);
155
156 *ret_rrs = TAKE_PTR(list)({ typeof(list) _ptr_ = (list); (list) = ((void*)0); _ptr_; }
)
;
157
158 return size;
159}
160
161static int mdns_do_tiebreak(DnsResourceKey *key, DnsAnswer *answer, DnsPacket *p) {
162 _cleanup_free___attribute__((cleanup(freep))) DnsResourceRecord **our = NULL((void*)0), **remote = NULL((void*)0);
163 DnsResourceRecord *rr;
164 size_t i = 0, size;
165 int r;
166
167 size = dns_answer_size(answer);
168 our = new(DnsResourceRecord *, size)((DnsResourceRecord **) malloc_multiply(sizeof(DnsResourceRecord
*), (size)))
;
169 if (!our)
33
Assuming 'our' is non-null
34
Taking false branch
170 return -ENOMEM12;
171
172 DNS_ANSWER_FOREACH(rr, answer)for (size_t __unique_prefix_i17 = ({ (rr) = ((answer) &&
(answer)->n_rrs > 0) ? (answer)->items[0].rr : ((void
*)0); 0; }); (answer) && (__unique_prefix_i17 < (answer
)->n_rrs); __unique_prefix_i17++, (rr) = (__unique_prefix_i17
< (answer)->n_rrs ? (answer)->items[__unique_prefix_i17
].rr : ((void*)0)))
173 our[i++] = rr;
174 qsort_safe(our, size, sizeof(DnsResourceRecord*), mdns_rr_compare);
175
176 r = mdns_packet_extract_matching_rrs(p, key, &remote);
35
Calling 'mdns_packet_extract_matching_rrs'
177 if (r < 0)
178 return r;
179
180 assert(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r > 0"), "../src/resolve/resolved-mdns.c"
, 180, __PRETTY_FUNCTION__); } while (0)
;
181
182 if (proposed_rrs_cmp(remote, r, our, size) > 0)
183 return 1;
184
185 return 0;
186}
187
188static int mdns_scope_process_query(DnsScope *s, DnsPacket *p) {
189 _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *full_answer = NULL((void*)0);
190 _cleanup_(dns_packet_unrefp)__attribute__((cleanup(dns_packet_unrefp))) DnsPacket *reply = NULL((void*)0);
191 DnsResourceKey *key = NULL((void*)0);
192 DnsResourceRecord *rr;
193 bool_Bool tentative = false0;
194 int r;
195
196 assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s"), "../src/resolve/resolved-mdns.c", 196
, __PRETTY_FUNCTION__); } while (0)
;
14
Taking false branch
15
Loop condition is false. Exiting loop
197 assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p"), "../src/resolve/resolved-mdns.c", 197
, __PRETTY_FUNCTION__); } while (0)
;
16
Assuming 'p' is non-null
17
Taking false branch
18
Loop condition is false. Exiting loop
198
199 r = dns_packet_extract(p);
200 if (r < 0)
19
Assuming 'r' is >= 0
20
Taking false branch
201 return log_debug_errno(r, "Failed to extract resource records from incoming packet: %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-mdns.c", 201, __func__, "Failed to extract resource records from incoming packet: %m"
) : -abs(_e); })
;
202
203 assert_return((dns_question_size(p->question) > 0), -EINVAL)do { if (!(((__builtin_expect(!!((dns_question_size(p->question
) > 0)),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD
, ("(dns_question_size(p->question) > 0)"), "../src/resolve/resolved-mdns.c"
, 203, __PRETTY_FUNCTION__), 0))) return (-22); } while (0)
;
21
Assuming the condition is true
22
'?' condition is true
23
Taking false branch
24
Loop condition is false. Exiting loop
204
205 DNS_QUESTION_FOREACH(key, p->question)for (size_t __unique_prefix_i18 = ({ (key) = ((p->question
) && (p->question)->n_keys > 0) ? (p->question
)->keys[0] : ((void*)0); 0; }); (p->question) &&
(__unique_prefix_i18 < (p->question)->n_keys); __unique_prefix_i18
++, (key) = (__unique_prefix_i18 < (p->question)->n_keys
? (p->question)->keys[__unique_prefix_i18] : ((void*)0
)))
{
25
'?' condition is true
26
Loop condition is true. Entering loop body
206 _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *answer = NULL((void*)0), *soa = NULL((void*)0);
207
208 r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
209 if (r < 0)
27
Assuming 'r' is >= 0
28
Taking false branch
210 return log_debug_errno(r, "Failed to lookup key: %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-mdns.c", 210, __func__, "Failed to lookup key: %m"
) : -abs(_e); })
;
211
212 if (tentative && DNS_PACKET_NSCOUNT(p)be16toh(((DnsPacketHeader*) DNS_PACKET_DATA(p))->nscount) > 0) {
29
Assuming 'tentative' is true
30
Assuming the condition is true
31
Taking true branch
213 /*
214 * A race condition detected with the probe packet from
215 * a remote host.
216 * Do simultaneous probe tiebreaking as described in
217 * RFC 6762, Section 8.2. In case we lost don't reply
218 * the question and withdraw conflicting RRs.
219 */
220 r = mdns_do_tiebreak(key, answer, p);
32
Calling 'mdns_do_tiebreak'
221 if (r < 0)
222 return log_debug_errno(r, "Failed to do tiebreaking")({ 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-mdns.c", 222, __func__, "Failed to do tiebreaking"
) : -abs(_e); })
;
223
224 if (r > 0) { /* we lost */
225 DNS_ANSWER_FOREACH(rr, answer)for (size_t __unique_prefix_i19 = ({ (rr) = ((answer) &&
(answer)->n_rrs > 0) ? (answer)->items[0].rr : ((void
*)0); 0; }); (answer) && (__unique_prefix_i19 < (answer
)->n_rrs); __unique_prefix_i19++, (rr) = (__unique_prefix_i19
< (answer)->n_rrs ? (answer)->items[__unique_prefix_i19
].rr : ((void*)0)))
{
226 DnsZoneItem *i;
227
228 i = dns_zone_get(&s->zone, rr);
229 if (i)
230 dns_zone_item_conflict(i);
231 }
232
233 continue;
234 }
235 }
236
237 r = dns_answer_extend(&full_answer, answer);
238 if (r < 0)
239 return log_debug_errno(r, "Failed to extend answer: %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-mdns.c", 239, __func__, "Failed to extend answer: %m"
) : -abs(_e); })
;
240 }
241
242 if (dns_answer_isempty(full_answer))
243 return 0;
244
245 r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p)((DnsPacketHeader*) DNS_PACKET_DATA(p))->id, DNS_RCODE_SUCCESS, NULL((void*)0), full_answer, NULL((void*)0), false0, &reply);
246 if (r < 0)
247 return log_debug_errno(r, "Failed to build reply packet: %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-mdns.c", 247, __func__, "Failed to build reply packet: %m"
) : -abs(_e); })
;
248
249 if (!ratelimit_below(&s->ratelimit))
250 return 0;
251
252 r = dns_scope_emit_udp(s, -1, reply);
253 if (r < 0)
254 return log_debug_errno(r, "Failed to send reply packet: %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-mdns.c", 254, __func__, "Failed to send reply packet: %m"
) : -abs(_e); })
;
255
256 return 0;
257}
258
259static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
260 _cleanup_(dns_packet_unrefp)__attribute__((cleanup(dns_packet_unrefp))) DnsPacket *p = NULL((void*)0);
261 Manager *m = userdata;
262 DnsScope *scope;
263 int r;
264
265 r = manager_recv(m, fd, DNS_PROTOCOL_MDNS, &p);
266 if (r <= 0)
1
Assuming 'r' is > 0
2
Taking false branch
267 return r;
268
269 if (manager_our_packet(m, p))
3
Assuming the condition is false
4
Taking false branch
270 return 0;
271
272 scope = manager_find_scope(m, p);
273 if (!scope) {
5
Assuming 'scope' is non-null
6
Taking false branch
274 log_debug("Got mDNS UDP packet on unknown scope. Ignoring.")({ 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-mdns.c", 274, __func__, "Got mDNS UDP packet on unknown scope. Ignoring."
) : -abs(_e); })
;
275 return 0;
276 }
277
278 if (dns_packet_validate_reply(p) > 0) {
7
Assuming the condition is false
8
Taking false branch
279 DnsResourceRecord *rr;
280
281 log_debug("Got mDNS reply packet")({ 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-mdns.c", 281, __func__, "Got mDNS reply packet"
) : -abs(_e); })
;
282
283 /*
284 * mDNS is different from regular DNS and LLMNR with regard to handling responses.
285 * While on other protocols, we can ignore every answer that doesn't match a question
286 * we broadcast earlier, RFC6762, section 18.1 recommends looking at and caching all
287 * incoming information, regardless of the DNS packet ID.
288 *
289 * Hence, extract the packet here, and try to find a transaction for answer the we got
290 * and complete it. Also store the new information in scope's cache.
291 */
292 r = dns_packet_extract(p);
293 if (r < 0) {
294 log_debug("mDNS packet extraction failed.")({ 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-mdns.c", 294, __func__, "mDNS packet extraction failed."
) : -abs(_e); })
;
295 return 0;
296 }
297
298 dns_scope_check_conflicts(scope, p);
299
300 DNS_ANSWER_FOREACH(rr, p->answer)for (size_t __unique_prefix_i20 = ({ (rr) = ((p->answer) &&
(p->answer)->n_rrs > 0) ? (p->answer)->items[
0].rr : ((void*)0); 0; }); (p->answer) && (__unique_prefix_i20
< (p->answer)->n_rrs); __unique_prefix_i20++, (rr) =
(__unique_prefix_i20 < (p->answer)->n_rrs ? (p->
answer)->items[__unique_prefix_i20].rr : ((void*)0)))
{
301 const char *name = dns_resource_key_name(rr->key);
302 DnsTransaction *t;
303
304 /* If the received reply packet contains ANY record that is not .local or .in-addr.arpa,
305 * we assume someone's playing tricks on us and discard the packet completely. */
306 if (!(dns_name_endswith(name, "in-addr.arpa") > 0 ||
307 dns_name_endswith(name, "local") > 0))
308 return 0;
309
310 if (rr->ttl == 0) {
311 log_debug("Got a goodbye packet")({ 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-mdns.c", 311, __func__, "Got a goodbye packet"
) : -abs(_e); })
;
312 /* See the section 10.1 of RFC6762 */
313 rr->ttl = 1;
314 }
315
316 t = dns_scope_find_transaction(scope, rr->key, false0);
317 if (t)
318 dns_transaction_process_reply(t, p);
319
320 /* Also look for the various types of ANY transactions */
321 t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key))((DnsResourceKey) { .n_ref = (unsigned) -1, .class = rr->key
->class, .type = DNS_TYPE_ANY, ._name = (char*) dns_resource_key_name
(rr->key), })
, false0);
322 if (t)
323 dns_transaction_process_reply(t, p);
324
325 t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key))((DnsResourceKey) { .n_ref = (unsigned) -1, .class = DNS_CLASS_ANY
, .type = rr->key->type, ._name = (char*) dns_resource_key_name
(rr->key), })
, false0);
326 if (t)
327 dns_transaction_process_reply(t, p);
328
329 t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key))((DnsResourceKey) { .n_ref = (unsigned) -1, .class = DNS_CLASS_ANY
, .type = DNS_TYPE_ANY, ._name = (char*) dns_resource_key_name
(rr->key), })
, false0);
330 if (t)
331 dns_transaction_process_reply(t, p);
332 }
333
334 dns_cache_put(&scope->cache, NULL((void*)0), DNS_PACKET_RCODE(p), p->answer, false0, (uint32_t) -1, 0, p->family, &p->sender);
335
336 } else if (dns_packet_validate_query(p) > 0) {
9
Assuming the condition is true
10
Taking true branch
337 log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p))({ 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-mdns.c", 337, __func__, "Got mDNS query packet for id %u"
, ((DnsPacketHeader*) DNS_PACKET_DATA(p))->id) : -abs(_e);
})
;
11
Assuming the condition is false
12
'?' condition is false
338
339 r = mdns_scope_process_query(scope, p);
13
Calling 'mdns_scope_process_query'
340 if (r < 0) {
341 log_debug_errno(r, "mDNS query processing failed: %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-mdns.c", 341, __func__, "mDNS query processing failed: %m"
) : -abs(_e); })
;
342 return 0;
343 }
344 } else
345 log_debug("Invalid mDNS UDP packet.")({ 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-mdns.c", 345, __func__, "Invalid mDNS UDP packet."
) : -abs(_e); })
;
346
347 return 0;
348}
349
350int manager_mdns_ipv4_fd(Manager *m) {
351 union sockaddr_union sa = {
352 .in.sin_family = AF_INET2,
353 .in.sin_port = htobe16(MDNS_PORT5353),
354 };
355 static const int one = 1, pmtu = IP_PMTUDISC_DONT0, ttl = 255;
356 int r;
357
358 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-mdns.c", 358
, __PRETTY_FUNCTION__); } while (0)
;
359
360 if (m->mdns_ipv4_fd >= 0)
361 return m->mdns_ipv4_fd;
362
363 m->mdns_ipv4_fd = socket(AF_INET2, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC|SOCK_NONBLOCKSOCK_NONBLOCK, 0);
364 if (m->mdns_ipv4_fd < 0)
365 return log_error_errno(errno, "mDNS-IPv4: Failed to create socket: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 365, __func__
, "mDNS-IPv4: Failed to create socket: %m") : -abs(_e); })
;
366
367 r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IPIPPROTO_IP, IP_TTL2, &ttl, sizeof(ttl));
368 if (r < 0) {
369 r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_TTL: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 369, __func__
, "mDNS-IPv4: Failed to set IP_TTL: %m") : -abs(_e); })
;
370 goto fail;
371 }
372
373 r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IPIPPROTO_IP, IP_MULTICAST_TTL33, &ttl, sizeof(ttl));
374 if (r < 0) {
375 r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MULTICAST_TTL: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 375, __func__
, "mDNS-IPv4: Failed to set IP_MULTICAST_TTL: %m") : -abs(_e)
; })
;
376 goto fail;
377 }
378
379 r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IPIPPROTO_IP, IP_MULTICAST_LOOP34, &one, sizeof(one));
380 if (r < 0) {
381 r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MULTICAST_LOOP: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 381, __func__
, "mDNS-IPv4: Failed to set IP_MULTICAST_LOOP: %m") : -abs(_e
); })
;
382 goto fail;
383 }
384
385 r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IPIPPROTO_IP, IP_PKTINFO8, &one, sizeof(one));
386 if (r < 0) {
387 r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_PKTINFO: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 387, __func__
, "mDNS-IPv4: Failed to set IP_PKTINFO: %m") : -abs(_e); })
;
388 goto fail;
389 }
390
391 r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IPIPPROTO_IP, IP_RECVTTL12, &one, sizeof(one));
392 if (r < 0) {
393 r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_RECVTTL: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 393, __func__
, "mDNS-IPv4: Failed to set IP_RECVTTL: %m") : -abs(_e); })
;
394 goto fail;
395 }
396
397 /* Disable Don't-Fragment bit in the IP header */
398 r = setsockopt(m->mdns_ipv4_fd, IPPROTO_IPIPPROTO_IP, IP_MTU_DISCOVER10, &pmtu, sizeof(pmtu));
399 if (r < 0) {
400 r = log_error_errno(errno, "mDNS-IPv4: Failed to set IP_MTU_DISCOVER: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 400, __func__
, "mDNS-IPv4: Failed to set IP_MTU_DISCOVER: %m") : -abs(_e);
})
;
401 goto fail;
402 }
403
404 /* See the section 15.1 of RFC6762 */
405 /* first try to bind without SO_REUSEADDR to detect another mDNS responder */
406 r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in));
407 if (r < 0) {
408 if (errno(*__errno_location ()) != EADDRINUSE98) {
409 r = log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 409, __func__
, "mDNS-IPv4: Failed to bind socket: %m") : -abs(_e); })
;
410 goto fail;
411 }
412
413 log_warning("mDNS-IPv4: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers.")({ 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-mdns.c", 413, __func__, "mDNS-IPv4: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers."
) : -abs(_e); })
;
414
415 /* try again with SO_REUSEADDR */
416 r = setsockopt(m->mdns_ipv4_fd, SOL_SOCKET1, SO_REUSEADDR2, &one, sizeof(one));
417 if (r < 0) {
418 r = log_error_errno(errno, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 418, __func__
, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m") : -abs(_e); })
;
419 goto fail;
420 }
421
422 r = bind(m->mdns_ipv4_fd, &sa.sa, sizeof(sa.in));
423 if (r < 0) {
424 r = log_error_errno(errno, "mDNS-IPv4: Failed to bind socket: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 424, __func__
, "mDNS-IPv4: Failed to bind socket: %m") : -abs(_e); })
;
425 goto fail;
426 }
427 } else {
428 /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */
429 r = setsockopt(m->mdns_ipv4_fd, SOL_SOCKET1, SO_REUSEADDR2, &one, sizeof(one));
430 if (r < 0) {
431 r = log_error_errno(errno, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 431, __func__
, "mDNS-IPv4: Failed to set SO_REUSEADDR: %m") : -abs(_e); })
;
432 goto fail;
433 }
434 }
435
436 r = sd_event_add_io(m->event, &m->mdns_ipv4_event_source, m->mdns_ipv4_fd, EPOLLINEPOLLIN, on_mdns_packet, m);
437 if (r < 0)
438 goto fail;
439
440 return m->mdns_ipv4_fd;
441
442fail:
443 m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd);
444 return r;
445}
446
447int manager_mdns_ipv6_fd(Manager *m) {
448 union sockaddr_union sa = {
449 .in6.sin6_family = AF_INET610,
450 .in6.sin6_port = htobe16(MDNS_PORT5353),
451 };
452 static const int one = 1, ttl = 255;
453 int r;
454
455 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/resolve/resolved-mdns.c", 455
, __PRETTY_FUNCTION__); } while (0)
;
456
457 if (m->mdns_ipv6_fd >= 0)
458 return m->mdns_ipv6_fd;
459
460 m->mdns_ipv6_fd = socket(AF_INET610, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC|SOCK_NONBLOCKSOCK_NONBLOCK, 0);
461 if (m->mdns_ipv6_fd < 0)
462 return log_error_errno(errno, "mDNS-IPv6: Failed to create socket: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 462, __func__
, "mDNS-IPv6: Failed to create socket: %m") : -abs(_e); })
;
463
464 r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6IPPROTO_IPV6, IPV6_UNICAST_HOPS16, &ttl, sizeof(ttl));
465 if (r < 0) {
466 r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_UNICAST_HOPS: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 466, __func__
, "mDNS-IPv6: Failed to set IPV6_UNICAST_HOPS: %m") : -abs(_e
); })
;
467 goto fail;
468 }
469
470 /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
471 r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6IPPROTO_IPV6, IPV6_MULTICAST_HOPS18, &ttl, sizeof(ttl));
472 if (r < 0) {
473 r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_MULTICAST_HOPS: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 473, __func__
, "mDNS-IPv6: Failed to set IPV6_MULTICAST_HOPS: %m") : -abs(
_e); })
;
474 goto fail;
475 }
476
477 r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6IPPROTO_IPV6, IPV6_MULTICAST_LOOP19, &one, sizeof(one));
478 if (r < 0) {
479 r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_MULTICAST_LOOP: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 479, __func__
, "mDNS-IPv6: Failed to set IPV6_MULTICAST_LOOP: %m") : -abs(
_e); })
;
480 goto fail;
481 }
482
483 r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6IPPROTO_IPV6, IPV6_V6ONLY26, &one, sizeof(one));
484 if (r < 0) {
485 r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_V6ONLY: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 485, __func__
, "mDNS-IPv6: Failed to set IPV6_V6ONLY: %m") : -abs(_e); })
;
486 goto fail;
487 }
488
489 r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6IPPROTO_IPV6, IPV6_RECVPKTINFO49, &one, sizeof(one));
490 if (r < 0) {
491 r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_RECVPKTINFO: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 491, __func__
, "mDNS-IPv6: Failed to set IPV6_RECVPKTINFO: %m") : -abs(_e)
; })
;
492 goto fail;
493 }
494
495 r = setsockopt(m->mdns_ipv6_fd, IPPROTO_IPV6IPPROTO_IPV6, IPV6_RECVHOPLIMIT51, &one, sizeof(one));
496 if (r < 0) {
497 r = log_error_errno(errno, "mDNS-IPv6: Failed to set IPV6_RECVHOPLIMIT: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 497, __func__
, "mDNS-IPv6: Failed to set IPV6_RECVHOPLIMIT: %m") : -abs(_e
); })
;
498 goto fail;
499 }
500
501 /* See the section 15.1 of RFC6762 */
502 /* first try to bind without SO_REUSEADDR to detect another mDNS responder */
503 r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6));
504 if (r < 0) {
505 if (errno(*__errno_location ()) != EADDRINUSE98) {
506 r = log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 506, __func__
, "mDNS-IPv6: Failed to bind socket: %m") : -abs(_e); })
;
507 goto fail;
508 }
509
510 log_warning("mDNS-IPv6: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers.")({ 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-mdns.c", 510, __func__, "mDNS-IPv6: There appears to be another mDNS responder running, or previously systemd-resolved crashed with some outstanding transfers."
) : -abs(_e); })
;
511
512 /* try again with SO_REUSEADDR */
513 r = setsockopt(m->mdns_ipv6_fd, SOL_SOCKET1, SO_REUSEADDR2, &one, sizeof(one));
514 if (r < 0) {
515 r = log_error_errno(errno, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 515, __func__
, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m") : -abs(_e); })
;
516 goto fail;
517 }
518
519 r = bind(m->mdns_ipv6_fd, &sa.sa, sizeof(sa.in6));
520 if (r < 0) {
521 r = log_error_errno(errno, "mDNS-IPv6: Failed to bind socket: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 521, __func__
, "mDNS-IPv6: Failed to bind socket: %m") : -abs(_e); })
;
522 goto fail;
523 }
524 } else {
525 /* enable SO_REUSEADDR for the case that the user really wants multiple mDNS responders */
526 r = setsockopt(m->mdns_ipv6_fd, SOL_SOCKET1, SO_REUSEADDR2, &one, sizeof(one));
527 if (r < 0) {
528 r = log_error_errno(errno, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/resolve/resolved-mdns.c", 528, __func__
, "mDNS-IPv6: Failed to set SO_REUSEADDR: %m") : -abs(_e); })
;
529 goto fail;
530 }
531 }
532
533 r = sd_event_add_io(m->event, &m->mdns_ipv6_event_source, m->mdns_ipv6_fd, EPOLLINEPOLLIN, on_mdns_packet, m);
534 if (r < 0)
535 goto fail;
536
537 return m->mdns_ipv6_fd;
538
539fail:
540 m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd);
541 return r;
542}

../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);
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))
56
Assuming the condition is false
57
Taking false branch
61 return NULL((void*)0);
62
63 return malloc(size * need);
58
Memory is allocated
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 })