File: | build-scan/../src/resolve/resolved-mdns.c |
Warning: | line 178, column 24 Potential leak of memory pointed to by 'our' |
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_A21 = ((DNS_RESOURCE_RECORD_RDATA_SIZE (*x))); const typeof((DNS_RESOURCE_RECORD_RDATA_SIZE(*y))) __unique_prefix_B22 = ((DNS_RESOURCE_RECORD_RDATA_SIZE(*y))); __unique_prefix_A21 < __unique_prefix_B22 ? __unique_prefix_A21 : __unique_prefix_B22 ; }); | |||
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_A23 = ((x_size)); const typeof((y_size)) __unique_prefix_B24 = ((y_size )); __unique_prefix_A23 < __unique_prefix_B24 ? __unique_prefix_A23 : __unique_prefix_B24; }); | |||
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 == 0) | |||
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_i25 = ({ (rr) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].rr : ((void *)0); 0; }); (answer) && (__unique_prefix_i25 < (answer )->n_rrs); __unique_prefix_i25++, (rr) = (__unique_prefix_i25 < (answer)->n_rrs ? (answer)->items[__unique_prefix_i25 ].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_i26 = ({ (key) = ((p->question ) && (p->question)->n_keys > 0) ? (p->question )->keys[0] : ((void*)0); 0; }); (p->question) && (__unique_prefix_i26 < (p->question)->n_keys); __unique_prefix_i26 ++, (key) = (__unique_prefix_i26 < (p->question)->n_keys ? (p->question)->keys[__unique_prefix_i26] : ((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_i27 = ({ (rr) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].rr : ((void *)0); 0; }); (answer) && (__unique_prefix_i27 < (answer )->n_rrs); __unique_prefix_i27++, (rr) = (__unique_prefix_i27 < (answer)->n_rrs ? (answer)->items[__unique_prefix_i27 ].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_i28 = ({ (rr) = ((p->answer) && (p->answer)->n_rrs > 0) ? (p->answer)->items[ 0].rr : ((void*)0); 0; }); (p->answer) && (__unique_prefix_i28 < (p->answer)->n_rrs); __unique_prefix_i28++, (rr) = (__unique_prefix_i28 < (p->answer)->n_rrs ? (p-> answer)->items[__unique_prefix_i28].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 | }) |