File: | build-scan/../src/resolve/resolved-mdns.c |
Warning: | line 149, column 32 Potential leak of memory pointed to by 'list' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||||
14 | void 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 | |||||
24 | int 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 | |||||
48 | eaddrinuse: | ||||
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 | |||||
56 | static 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 | |||||
102 | static 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 | |||||
121 | static 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); | ||||
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); | ||||
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); | ||||
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); | ||||
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++) { | ||||
132 | r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL((void*)0)); | ||||
133 | if (r < 0) | ||||
134 | return r; | ||||
135 | if (r > 0) | ||||
136 | size++; | ||||
137 | } | ||||
138 | |||||
139 | if (size
| ||||
140 | return 0; | ||||
141 | |||||
142 | list = new(DnsResourceRecord *, size)((DnsResourceRecord **) malloc_multiply(sizeof(DnsResourceRecord *), (size))); | ||||
143 | if (!list) | ||||
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++) { | ||||
147 | r = dns_resource_key_match_rr(key, p->answer->items[i].rr, NULL((void*)0)); | ||||
148 | if (r < 0) | ||||
149 | return r; | ||||
| |||||
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 | |||||
161 | static 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) | ||||
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); | ||||
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 | |||||
188 | static 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); | ||||
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); | ||||
198 | |||||
199 | r = dns_packet_extract(p); | ||||
200 | if (r < 0) | ||||
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); | ||||
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 ))) { | ||||
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) | ||||
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) { | ||||
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); | ||||
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 | |||||
259 | static 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) | ||||
| |||||
267 | return r; | ||||
268 | |||||
269 | if (manager_our_packet(m, p)) | ||||
270 | return 0; | ||||
271 | |||||
272 | scope = manager_find_scope(m, p); | ||||
273 | if (!scope) { | ||||
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) { | ||||
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) { | ||||
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); }); | ||||
338 | |||||
339 | r = mdns_scope_process_query(scope, p); | ||||
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 | |||||
350 | int 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 | |||||
442 | fail: | ||||
443 | m->mdns_ipv4_fd = safe_close(m->mdns_ipv4_fd); | ||||
444 | return r; | ||||
445 | } | ||||
446 | |||||
447 | int 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 | |||||
539 | fail: | ||||
540 | m->mdns_ipv6_fd = safe_close(m->mdns_ipv6_fd); | ||||
541 | return r; | ||||
542 | } |
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 | |
33 | static 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 | |
46 | void* memdup(const void *p, size_t l) _alloc_(2); |
47 | void* memdup_suffix0(const void *p, size_t l) _alloc_(2); |
48 | |
49 | static inline void freep(void *p) { |
50 | free(*(void**) p); |
51 | } |
52 | |
53 | #define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep))) |
54 | |
55 | static 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 | |
89 | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); |
90 | void* 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 | }) |