File: | build-scan/../src/resolve/resolved-dns-answer.c |
Warning: | line 492, column 40 Potential leak of memory pointed to by 'copy' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | ||||||
2 | |||||||
3 | #include "alloc-util.h" | ||||||
4 | #include "dns-domain.h" | ||||||
5 | #include "resolved-dns-answer.h" | ||||||
6 | #include "resolved-dns-dnssec.h" | ||||||
7 | #include "string-util.h" | ||||||
8 | |||||||
9 | DnsAnswer *dns_answer_new(size_t n) { | ||||||
10 | DnsAnswer *a; | ||||||
11 | |||||||
12 | a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n)(calloc(1, (__builtin_offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem ) * n))); | ||||||
13 | if (!a) | ||||||
14 | return NULL((void*)0); | ||||||
15 | |||||||
16 | a->n_ref = 1; | ||||||
17 | a->n_allocated = n; | ||||||
18 | |||||||
19 | return a; | ||||||
20 | } | ||||||
21 | |||||||
22 | DnsAnswer *dns_answer_ref(DnsAnswer *a) { | ||||||
23 | if (!a) | ||||||
24 | return NULL((void*)0); | ||||||
25 | |||||||
26 | assert(a->n_ref > 0)do { if ((__builtin_expect(!!(!(a->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a->n_ref > 0"), "../src/resolve/resolved-dns-answer.c" , 26, __PRETTY_FUNCTION__); } while (0); | ||||||
27 | a->n_ref++; | ||||||
28 | return a; | ||||||
29 | } | ||||||
30 | |||||||
31 | static void dns_answer_flush(DnsAnswer *a) { | ||||||
32 | DnsResourceRecord *rr; | ||||||
33 | |||||||
34 | if (!a) | ||||||
35 | return; | ||||||
36 | |||||||
37 | DNS_ANSWER_FOREACH(rr, a)for (size_t __unique_prefix_i20 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); 0; } ); (a) && (__unique_prefix_i20 < (a)->n_rrs); __unique_prefix_i20 ++, (rr) = (__unique_prefix_i20 < (a)->n_rrs ? (a)-> items[__unique_prefix_i20].rr : ((void*)0))) | ||||||
38 | dns_resource_record_unref(rr); | ||||||
39 | |||||||
40 | a->n_rrs = 0; | ||||||
41 | } | ||||||
42 | |||||||
43 | DnsAnswer *dns_answer_unref(DnsAnswer *a) { | ||||||
44 | if (!a) | ||||||
45 | return NULL((void*)0); | ||||||
46 | |||||||
47 | assert(a->n_ref > 0)do { if ((__builtin_expect(!!(!(a->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a->n_ref > 0"), "../src/resolve/resolved-dns-answer.c" , 47, __PRETTY_FUNCTION__); } while (0); | ||||||
48 | |||||||
49 | if (a->n_ref == 1) { | ||||||
50 | dns_answer_flush(a); | ||||||
51 | free(a); | ||||||
52 | } else | ||||||
53 | a->n_ref--; | ||||||
54 | |||||||
55 | return NULL((void*)0); | ||||||
56 | } | ||||||
57 | |||||||
58 | static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { | ||||||
59 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 59, __PRETTY_FUNCTION__); } while (0); | ||||||
60 | |||||||
61 | if (!a) | ||||||
62 | return -ENOSPC28; | ||||||
63 | |||||||
64 | if (a->n_rrs >= a->n_allocated) | ||||||
65 | return -ENOSPC28; | ||||||
66 | |||||||
67 | a->items[a->n_rrs++] = (DnsAnswerItem) { | ||||||
68 | .rr = dns_resource_record_ref(rr), | ||||||
69 | .ifindex = ifindex, | ||||||
70 | .flags = flags, | ||||||
71 | }; | ||||||
72 | |||||||
73 | return 1; | ||||||
74 | } | ||||||
75 | |||||||
76 | static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) { | ||||||
77 | DnsResourceRecord *rr; | ||||||
78 | DnsAnswerFlags flags; | ||||||
79 | int ifindex, r; | ||||||
80 | |||||||
81 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source)for (size_t __unique_prefix_i21 = ({ (rr) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].rr : ((void *)0); (ifindex) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].ifindex : 0; (flags) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].flags : 0 ; 0; }); (source) && (__unique_prefix_i21 < (source )->n_rrs); __unique_prefix_i21++, (rr) = ((__unique_prefix_i21 < (source)->n_rrs) ? (source)->items[__unique_prefix_i21 ].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i21 < (source )->n_rrs) ? (source)->items[__unique_prefix_i21].ifindex : 0), (flags) = ((__unique_prefix_i21 < (source)->n_rrs ) ? (source)->items[__unique_prefix_i21].flags : 0)) { | ||||||
82 | r = dns_answer_add_raw(a, rr, ifindex, flags); | ||||||
83 | if (r < 0) | ||||||
84 | return r; | ||||||
85 | } | ||||||
86 | |||||||
87 | return 0; | ||||||
88 | } | ||||||
89 | |||||||
90 | int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { | ||||||
91 | size_t i; | ||||||
92 | int r; | ||||||
93 | |||||||
94 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 94, __PRETTY_FUNCTION__); } while (0); | ||||||
95 | |||||||
96 | if (!a) | ||||||
97 | return -ENOSPC28; | ||||||
98 | if (a->n_ref > 1) | ||||||
99 | return -EBUSY16; | ||||||
100 | |||||||
101 | for (i = 0; i < a->n_rrs; i++) { | ||||||
102 | if (a->items[i].ifindex != ifindex) | ||||||
103 | continue; | ||||||
104 | |||||||
105 | r = dns_resource_record_equal(a->items[i].rr, rr); | ||||||
106 | if (r < 0) | ||||||
107 | return r; | ||||||
108 | if (r > 0) { | ||||||
109 | /* Don't mix contradicting TTLs (see below) */ | ||||||
110 | if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0)) | ||||||
111 | return -EINVAL22; | ||||||
112 | |||||||
113 | /* Entry already exists, keep the entry with | ||||||
114 | * the higher RR. */ | ||||||
115 | if (rr->ttl > a->items[i].rr->ttl) { | ||||||
116 | dns_resource_record_ref(rr); | ||||||
117 | dns_resource_record_unref(a->items[i].rr); | ||||||
118 | a->items[i].rr = rr; | ||||||
119 | } | ||||||
120 | |||||||
121 | a->items[i].flags |= flags; | ||||||
122 | return 0; | ||||||
123 | } | ||||||
124 | |||||||
125 | r = dns_resource_key_equal(a->items[i].rr->key, rr->key); | ||||||
126 | if (r < 0) | ||||||
127 | return r; | ||||||
128 | if (r > 0) { | ||||||
129 | /* There's already an RR of the same RRset in | ||||||
130 | * place! Let's see if the TTLs more or less | ||||||
131 | * match. We don't really care if they match | ||||||
132 | * precisely, but we do care whether one is 0 | ||||||
133 | * and the other is not. See RFC 2181, Section | ||||||
134 | * 5.2. */ | ||||||
135 | |||||||
136 | if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0)) | ||||||
137 | return -EINVAL22; | ||||||
138 | } | ||||||
139 | } | ||||||
140 | |||||||
141 | return dns_answer_add_raw(a, rr, ifindex, flags); | ||||||
142 | } | ||||||
143 | |||||||
144 | static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) { | ||||||
145 | DnsResourceRecord *rr; | ||||||
146 | DnsAnswerFlags flags; | ||||||
147 | int ifindex, r; | ||||||
148 | |||||||
149 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b)for (size_t __unique_prefix_i22 = ({ (rr) = ((b) && ( b)->n_rrs > 0) ? (b)->items[0].rr : ((void*)0); (ifindex ) = ((b) && (b)->n_rrs > 0) ? (b)->items[0]. ifindex : 0; (flags) = ((b) && (b)->n_rrs > 0) ? (b)->items[0].flags : 0; 0; }); (b) && (__unique_prefix_i22 < (b)->n_rrs); __unique_prefix_i22++, (rr) = ((__unique_prefix_i22 < (b)->n_rrs) ? (b)->items[__unique_prefix_i22].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i22 < (b)-> n_rrs) ? (b)->items[__unique_prefix_i22].ifindex : 0), (flags ) = ((__unique_prefix_i22 < (b)->n_rrs) ? (b)->items [__unique_prefix_i22].flags : 0)) { | ||||||
150 | r = dns_answer_add(a, rr, ifindex, flags); | ||||||
151 | if (r < 0) | ||||||
152 | return r; | ||||||
153 | } | ||||||
154 | |||||||
155 | return 0; | ||||||
156 | } | ||||||
157 | |||||||
158 | int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) { | ||||||
159 | int r; | ||||||
160 | |||||||
161 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 161, __PRETTY_FUNCTION__); } while (0); | ||||||
162 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 162, __PRETTY_FUNCTION__); } while (0); | ||||||
163 | |||||||
164 | r = dns_answer_reserve_or_clone(a, 1); | ||||||
165 | if (r < 0) | ||||||
166 | return r; | ||||||
167 | |||||||
168 | return dns_answer_add(*a, rr, ifindex, flags); | ||||||
169 | } | ||||||
170 | |||||||
171 | int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) { | ||||||
172 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *soa = NULL((void*)0); | ||||||
173 | |||||||
174 | soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name); | ||||||
175 | if (!soa) | ||||||
176 | return -ENOMEM12; | ||||||
177 | |||||||
178 | soa->ttl = ttl; | ||||||
179 | |||||||
180 | soa->soa.mname = strdup(name); | ||||||
181 | if (!soa->soa.mname) | ||||||
182 | return -ENOMEM12; | ||||||
183 | |||||||
184 | soa->soa.rname = strappend("root.", name); | ||||||
185 | if (!soa->soa.rname) | ||||||
186 | return -ENOMEM12; | ||||||
187 | |||||||
188 | soa->soa.serial = 1; | ||||||
189 | soa->soa.refresh = 1; | ||||||
190 | soa->soa.retry = 1; | ||||||
191 | soa->soa.expire = 1; | ||||||
192 | soa->soa.minimum = ttl; | ||||||
193 | |||||||
194 | return dns_answer_add(a, soa, ifindex, DNS_ANSWER_AUTHENTICATED); | ||||||
195 | } | ||||||
196 | |||||||
197 | int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { | ||||||
198 | DnsAnswerFlags flags = 0, i_flags; | ||||||
199 | DnsResourceRecord *i; | ||||||
200 | bool_Bool found = false0; | ||||||
201 | int r; | ||||||
202 | |||||||
203 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 203, __PRETTY_FUNCTION__); } while (0); | ||||||
204 | |||||||
205 | DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a)for (size_t __unique_prefix_i23 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (i_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i23 < (a )->n_rrs); __unique_prefix_i23++, (i) = ((__unique_prefix_i23 < (a)->n_rrs) ? (a)->items[__unique_prefix_i23].rr : ((void*)0)), (i_flags) = ((__unique_prefix_i23 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i23].flags : 0)) { | ||||||
206 | r = dns_resource_key_match_rr(key, i, NULL((void*)0)); | ||||||
207 | if (r < 0) | ||||||
208 | return r; | ||||||
209 | if (r == 0) | ||||||
210 | continue; | ||||||
211 | |||||||
212 | if (!ret_flags) | ||||||
213 | return 1; | ||||||
214 | |||||||
215 | if (found) | ||||||
216 | flags &= i_flags; | ||||||
217 | else { | ||||||
218 | flags = i_flags; | ||||||
219 | found = true1; | ||||||
220 | } | ||||||
221 | } | ||||||
222 | |||||||
223 | if (ret_flags) | ||||||
224 | *ret_flags = flags; | ||||||
225 | |||||||
226 | return found; | ||||||
227 | } | ||||||
228 | |||||||
229 | int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *ret_flags) { | ||||||
230 | DnsAnswerFlags flags = 0, i_flags; | ||||||
231 | DnsResourceRecord *i; | ||||||
232 | bool_Bool found = false0; | ||||||
233 | int r; | ||||||
234 | |||||||
235 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-answer.c" , 235, __PRETTY_FUNCTION__); } while (0); | ||||||
236 | |||||||
237 | DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a)for (size_t __unique_prefix_i24 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (i_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i24 < (a )->n_rrs); __unique_prefix_i24++, (i) = ((__unique_prefix_i24 < (a)->n_rrs) ? (a)->items[__unique_prefix_i24].rr : ((void*)0)), (i_flags) = ((__unique_prefix_i24 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i24].flags : 0)) { | ||||||
238 | r = dns_resource_record_equal(i, rr); | ||||||
239 | if (r < 0) | ||||||
240 | return r; | ||||||
241 | if (r == 0) | ||||||
242 | continue; | ||||||
243 | |||||||
244 | if (!ret_flags) | ||||||
245 | return 1; | ||||||
246 | |||||||
247 | if (found) | ||||||
248 | flags &= i_flags; | ||||||
249 | else { | ||||||
250 | flags = i_flags; | ||||||
251 | found = true1; | ||||||
252 | } | ||||||
253 | } | ||||||
254 | |||||||
255 | if (ret_flags) | ||||||
256 | *ret_flags = flags; | ||||||
257 | |||||||
258 | return found; | ||||||
259 | } | ||||||
260 | |||||||
261 | int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) { | ||||||
262 | DnsAnswerFlags flags = 0, i_flags; | ||||||
263 | DnsResourceRecord *i; | ||||||
264 | bool_Bool found = false0; | ||||||
265 | int r; | ||||||
266 | |||||||
267 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 267, __PRETTY_FUNCTION__); } while (0); | ||||||
268 | |||||||
269 | DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a)for (size_t __unique_prefix_i25 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (i_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i25 < (a )->n_rrs); __unique_prefix_i25++, (i) = ((__unique_prefix_i25 < (a)->n_rrs) ? (a)->items[__unique_prefix_i25].rr : ((void*)0)), (i_flags) = ((__unique_prefix_i25 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i25].flags : 0)) { | ||||||
270 | r = dns_resource_key_equal(i->key, key); | ||||||
271 | if (r < 0) | ||||||
272 | return r; | ||||||
273 | if (r == 0) | ||||||
274 | continue; | ||||||
275 | |||||||
276 | if (!ret_flags) | ||||||
277 | return true1; | ||||||
278 | |||||||
279 | if (found) | ||||||
280 | flags &= i_flags; | ||||||
281 | else { | ||||||
282 | flags = i_flags; | ||||||
283 | found = true1; | ||||||
284 | } | ||||||
285 | } | ||||||
286 | |||||||
287 | if (ret_flags) | ||||||
288 | *ret_flags = flags; | ||||||
289 | |||||||
290 | return found; | ||||||
291 | } | ||||||
292 | |||||||
293 | int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) { | ||||||
294 | DnsResourceRecord *i; | ||||||
295 | |||||||
296 | DNS_ANSWER_FOREACH(i, a)for (size_t __unique_prefix_i26 = ({ (i) = ((a) && (a )->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); 0; }) ; (a) && (__unique_prefix_i26 < (a)->n_rrs); __unique_prefix_i26 ++, (i) = (__unique_prefix_i26 < (a)->n_rrs ? (a)->items [__unique_prefix_i26].rr : ((void*)0))) { | ||||||
297 | if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_TYPE_NSEC, DNS_TYPE_NSEC3})/sizeof(int )]; switch(i->key->type) { case DNS_TYPE_NSEC: case DNS_TYPE_NSEC3 : _found = 1; break; default: break; } _found; })) | ||||||
298 | return true1; | ||||||
299 | } | ||||||
300 | |||||||
301 | return false0; | ||||||
302 | } | ||||||
303 | |||||||
304 | int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) { | ||||||
305 | DnsResourceRecord *rr; | ||||||
306 | int r; | ||||||
307 | |||||||
308 | /* Checks whether the specified answer contains at least one NSEC3 RR in the specified zone */ | ||||||
309 | |||||||
310 | 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))) { | ||||||
311 | const char *p; | ||||||
312 | |||||||
313 | if (rr->key->type != DNS_TYPE_NSEC3) | ||||||
314 | continue; | ||||||
315 | |||||||
316 | p = dns_resource_key_name(rr->key); | ||||||
317 | r = dns_name_parent(&p); | ||||||
318 | if (r < 0) | ||||||
319 | return r; | ||||||
320 | if (r == 0) | ||||||
321 | continue; | ||||||
322 | |||||||
323 | r = dns_name_equal(p, zone); | ||||||
324 | if (r != 0) | ||||||
325 | return r; | ||||||
326 | } | ||||||
327 | |||||||
328 | return false0; | ||||||
329 | } | ||||||
330 | |||||||
331 | int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { | ||||||
332 | DnsResourceRecord *rr, *soa = NULL((void*)0); | ||||||
333 | DnsAnswerFlags rr_flags, soa_flags = 0; | ||||||
334 | int r; | ||||||
335 | |||||||
336 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 336, __PRETTY_FUNCTION__); } while (0); | ||||||
337 | |||||||
338 | /* For a SOA record we can never find a matching SOA record */ | ||||||
339 | if (key->type == DNS_TYPE_SOA) | ||||||
340 | return 0; | ||||||
341 | |||||||
342 | DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a)for (size_t __unique_prefix_i28 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (rr_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i28 < (a )->n_rrs); __unique_prefix_i28++, (rr) = ((__unique_prefix_i28 < (a)->n_rrs) ? (a)->items[__unique_prefix_i28].rr : ((void*)0)), (rr_flags) = ((__unique_prefix_i28 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i28].flags : 0)) { | ||||||
343 | r = dns_resource_key_match_soa(key, rr->key); | ||||||
344 | if (r < 0) | ||||||
345 | return r; | ||||||
346 | if (r > 0) { | ||||||
347 | |||||||
348 | if (soa) { | ||||||
349 | r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(soa->key)); | ||||||
350 | if (r < 0) | ||||||
351 | return r; | ||||||
352 | if (r > 0) | ||||||
353 | continue; | ||||||
354 | } | ||||||
355 | |||||||
356 | soa = rr; | ||||||
357 | soa_flags = rr_flags; | ||||||
358 | } | ||||||
359 | } | ||||||
360 | |||||||
361 | if (!soa) | ||||||
362 | return 0; | ||||||
363 | |||||||
364 | if (ret) | ||||||
365 | *ret = soa; | ||||||
366 | if (flags) | ||||||
367 | *flags = soa_flags; | ||||||
368 | |||||||
369 | return 1; | ||||||
370 | } | ||||||
371 | |||||||
372 | int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) { | ||||||
373 | DnsResourceRecord *rr; | ||||||
374 | DnsAnswerFlags rr_flags; | ||||||
375 | int r; | ||||||
376 | |||||||
377 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 377, __PRETTY_FUNCTION__); } while (0); | ||||||
378 | |||||||
379 | /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */ | ||||||
380 | if (!dns_type_may_redirect(key->type)) | ||||||
381 | return 0; | ||||||
382 | |||||||
383 | DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a)for (size_t __unique_prefix_i29 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); (rr_flags ) = ((a) && (a)->n_rrs > 0) ? (a)->items[0]. flags : 0; 0; }); (a) && (__unique_prefix_i29 < (a )->n_rrs); __unique_prefix_i29++, (rr) = ((__unique_prefix_i29 < (a)->n_rrs) ? (a)->items[__unique_prefix_i29].rr : ((void*)0)), (rr_flags) = ((__unique_prefix_i29 < (a)-> n_rrs) ? (a)->items[__unique_prefix_i29].flags : 0)) { | ||||||
384 | r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL((void*)0)); | ||||||
385 | if (r < 0) | ||||||
386 | return r; | ||||||
387 | if (r > 0) { | ||||||
388 | if (ret) | ||||||
389 | *ret = rr; | ||||||
390 | if (flags) | ||||||
391 | *flags = rr_flags; | ||||||
392 | return 1; | ||||||
393 | } | ||||||
394 | } | ||||||
395 | |||||||
396 | return 0; | ||||||
397 | } | ||||||
398 | |||||||
399 | int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) { | ||||||
400 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *k = NULL((void*)0); | ||||||
401 | int r; | ||||||
402 | |||||||
403 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-answer.c" , 403, __PRETTY_FUNCTION__); } while (0); | ||||||
404 | |||||||
405 | if (dns_answer_size(a) <= 0) { | ||||||
406 | *ret = dns_answer_ref(b); | ||||||
407 | return 0; | ||||||
408 | } | ||||||
409 | |||||||
410 | if (dns_answer_size(b) <= 0) { | ||||||
411 | *ret = dns_answer_ref(a); | ||||||
412 | return 0; | ||||||
413 | } | ||||||
414 | |||||||
415 | k = dns_answer_new(a->n_rrs + b->n_rrs); | ||||||
416 | if (!k) | ||||||
417 | return -ENOMEM12; | ||||||
418 | |||||||
419 | r = dns_answer_add_raw_all(k, a); | ||||||
420 | if (r < 0) | ||||||
421 | return r; | ||||||
422 | |||||||
423 | r = dns_answer_add_all(k, b); | ||||||
424 | if (r < 0) | ||||||
425 | return r; | ||||||
426 | |||||||
427 | *ret = TAKE_PTR(k)({ typeof(k) _ptr_ = (k); (k) = ((void*)0); _ptr_; }); | ||||||
428 | |||||||
429 | return 0; | ||||||
430 | } | ||||||
431 | |||||||
432 | int dns_answer_extend(DnsAnswer **a, DnsAnswer *b) { | ||||||
433 | DnsAnswer *merged; | ||||||
434 | int r; | ||||||
435 | |||||||
436 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 436, __PRETTY_FUNCTION__); } while (0); | ||||||
437 | |||||||
438 | r = dns_answer_merge(*a, b, &merged); | ||||||
439 | if (r < 0) | ||||||
440 | return r; | ||||||
441 | |||||||
442 | dns_answer_unref(*a); | ||||||
443 | *a = merged; | ||||||
444 | |||||||
445 | return 0; | ||||||
446 | } | ||||||
447 | |||||||
448 | int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) { | ||||||
449 | bool_Bool found = false0, other = false0; | ||||||
450 | DnsResourceRecord *rr; | ||||||
451 | size_t i; | ||||||
452 | int r; | ||||||
453 | |||||||
454 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 454, __PRETTY_FUNCTION__); } while (0); | ||||||
455 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 455, __PRETTY_FUNCTION__); } while (0); | ||||||
456 | |||||||
457 | /* Remove all entries matching the specified key from *a */ | ||||||
458 | |||||||
459 | DNS_ANSWER_FOREACH(rr, *a)for (size_t __unique_prefix_i30 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); 0; }); (*a) && (__unique_prefix_i30 < (*a)->n_rrs ); __unique_prefix_i30++, (rr) = (__unique_prefix_i30 < (* a)->n_rrs ? (*a)->items[__unique_prefix_i30].rr : ((void *)0))) { | ||||||
460 | r = dns_resource_key_equal(rr->key, key); | ||||||
461 | if (r < 0) | ||||||
462 | return r; | ||||||
463 | if (r > 0) | ||||||
464 | found = true1; | ||||||
465 | else | ||||||
466 | other = true1; | ||||||
467 | |||||||
468 | if (found
| ||||||
469 | break; | ||||||
470 | } | ||||||
471 | |||||||
472 | if (!found
| ||||||
473 | return 0; | ||||||
474 | |||||||
475 | if (!other
| ||||||
476 | *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ | ||||||
477 | return 1; | ||||||
478 | } | ||||||
479 | |||||||
480 | if ((*a)->n_ref > 1) { | ||||||
481 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *copy = NULL((void*)0); | ||||||
482 | DnsAnswerFlags flags; | ||||||
483 | int ifindex; | ||||||
484 | |||||||
485 | copy = dns_answer_new((*a)->n_rrs); | ||||||
486 | if (!copy
| ||||||
487 | return -ENOMEM12; | ||||||
488 | |||||||
489 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a)for (size_t __unique_prefix_i31 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); (ifindex ) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[ 0].ifindex : 0; (flags) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[0].flags : 0; 0; }); (*a) && (__unique_prefix_i31 < (*a)->n_rrs); __unique_prefix_i31++, (rr) = ((__unique_prefix_i31 < (*a)->n_rrs) ? (*a)->items[__unique_prefix_i31].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i31 < (*a)-> n_rrs) ? (*a)->items[__unique_prefix_i31].ifindex : 0), (flags ) = ((__unique_prefix_i31 < (*a)->n_rrs) ? (*a)->items [__unique_prefix_i31].flags : 0)) { | ||||||
490 | r = dns_resource_key_equal(rr->key, key); | ||||||
491 | if (r < 0) | ||||||
492 | return r; | ||||||
| |||||||
493 | if (r > 0) | ||||||
494 | continue; | ||||||
495 | |||||||
496 | r = dns_answer_add_raw(copy, rr, ifindex, flags); | ||||||
497 | if (r < 0) | ||||||
498 | return r; | ||||||
499 | } | ||||||
500 | |||||||
501 | dns_answer_unref(*a); | ||||||
502 | *a = TAKE_PTR(copy)({ typeof(copy) _ptr_ = (copy); (copy) = ((void*)0); _ptr_; } ); | ||||||
503 | |||||||
504 | return 1; | ||||||
505 | } | ||||||
506 | |||||||
507 | /* Only a single reference, edit in-place */ | ||||||
508 | |||||||
509 | i = 0; | ||||||
510 | for (;;) { | ||||||
511 | if (i >= (*a)->n_rrs) | ||||||
512 | break; | ||||||
513 | |||||||
514 | r = dns_resource_key_equal((*a)->items[i].rr->key, key); | ||||||
515 | if (r < 0) | ||||||
516 | return r; | ||||||
517 | if (r > 0) { | ||||||
518 | /* Kill this entry */ | ||||||
519 | |||||||
520 | dns_resource_record_unref((*a)->items[i].rr); | ||||||
521 | memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); | ||||||
522 | (*a)->n_rrs--; | ||||||
523 | continue; | ||||||
524 | |||||||
525 | } else | ||||||
526 | /* Keep this entry */ | ||||||
527 | i++; | ||||||
528 | } | ||||||
529 | |||||||
530 | return 1; | ||||||
531 | } | ||||||
532 | |||||||
533 | int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) { | ||||||
534 | bool_Bool found = false0, other = false0; | ||||||
535 | DnsResourceRecord *rr; | ||||||
536 | size_t i; | ||||||
537 | int r; | ||||||
538 | |||||||
539 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 539, __PRETTY_FUNCTION__); } while (0); | ||||||
540 | assert(rm)do { if ((__builtin_expect(!!(!(rm)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rm"), "../src/resolve/resolved-dns-answer.c" , 540, __PRETTY_FUNCTION__); } while (0); | ||||||
541 | |||||||
542 | /* Remove all entries matching the specified RR from *a */ | ||||||
543 | |||||||
544 | DNS_ANSWER_FOREACH(rr, *a)for (size_t __unique_prefix_i32 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); 0; }); (*a) && (__unique_prefix_i32 < (*a)->n_rrs ); __unique_prefix_i32++, (rr) = (__unique_prefix_i32 < (* a)->n_rrs ? (*a)->items[__unique_prefix_i32].rr : ((void *)0))) { | ||||||
545 | r = dns_resource_record_equal(rr, rm); | ||||||
546 | if (r < 0) | ||||||
547 | return r; | ||||||
548 | if (r > 0) | ||||||
549 | found = true1; | ||||||
550 | else | ||||||
551 | other = true1; | ||||||
552 | |||||||
553 | if (found && other) | ||||||
554 | break; | ||||||
555 | } | ||||||
556 | |||||||
557 | if (!found) | ||||||
558 | return 0; | ||||||
559 | |||||||
560 | if (!other) { | ||||||
561 | *a = dns_answer_unref(*a); /* Return NULL for the empty answer */ | ||||||
562 | return 1; | ||||||
563 | } | ||||||
564 | |||||||
565 | if ((*a)->n_ref > 1) { | ||||||
566 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *copy = NULL((void*)0); | ||||||
567 | DnsAnswerFlags flags; | ||||||
568 | int ifindex; | ||||||
569 | |||||||
570 | copy = dns_answer_new((*a)->n_rrs); | ||||||
571 | if (!copy) | ||||||
572 | return -ENOMEM12; | ||||||
573 | |||||||
574 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a)for (size_t __unique_prefix_i33 = ({ (rr) = ((*a) && ( *a)->n_rrs > 0) ? (*a)->items[0].rr : ((void*)0); (ifindex ) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[ 0].ifindex : 0; (flags) = ((*a) && (*a)->n_rrs > 0) ? (*a)->items[0].flags : 0; 0; }); (*a) && (__unique_prefix_i33 < (*a)->n_rrs); __unique_prefix_i33++, (rr) = ((__unique_prefix_i33 < (*a)->n_rrs) ? (*a)->items[__unique_prefix_i33].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i33 < (*a)-> n_rrs) ? (*a)->items[__unique_prefix_i33].ifindex : 0), (flags ) = ((__unique_prefix_i33 < (*a)->n_rrs) ? (*a)->items [__unique_prefix_i33].flags : 0)) { | ||||||
575 | r = dns_resource_record_equal(rr, rm); | ||||||
576 | if (r < 0) | ||||||
577 | return r; | ||||||
578 | if (r > 0) | ||||||
579 | continue; | ||||||
580 | |||||||
581 | r = dns_answer_add_raw(copy, rr, ifindex, flags); | ||||||
582 | if (r < 0) | ||||||
583 | return r; | ||||||
584 | } | ||||||
585 | |||||||
586 | dns_answer_unref(*a); | ||||||
587 | *a = TAKE_PTR(copy)({ typeof(copy) _ptr_ = (copy); (copy) = ((void*)0); _ptr_; } ); | ||||||
588 | |||||||
589 | return 1; | ||||||
590 | } | ||||||
591 | |||||||
592 | /* Only a single reference, edit in-place */ | ||||||
593 | |||||||
594 | i = 0; | ||||||
595 | for (;;) { | ||||||
596 | if (i >= (*a)->n_rrs) | ||||||
597 | break; | ||||||
598 | |||||||
599 | r = dns_resource_record_equal((*a)->items[i].rr, rm); | ||||||
600 | if (r < 0) | ||||||
601 | return r; | ||||||
602 | if (r > 0) { | ||||||
603 | /* Kill this entry */ | ||||||
604 | |||||||
605 | dns_resource_record_unref((*a)->items[i].rr); | ||||||
606 | memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1)); | ||||||
607 | (*a)->n_rrs--; | ||||||
608 | continue; | ||||||
609 | |||||||
610 | } else | ||||||
611 | /* Keep this entry */ | ||||||
612 | i++; | ||||||
613 | } | ||||||
614 | |||||||
615 | return 1; | ||||||
616 | } | ||||||
617 | |||||||
618 | int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) { | ||||||
619 | DnsResourceRecord *rr_source; | ||||||
620 | int ifindex_source, r; | ||||||
621 | DnsAnswerFlags flags_source; | ||||||
622 | |||||||
623 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 623, __PRETTY_FUNCTION__); } while (0); | ||||||
624 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 624, __PRETTY_FUNCTION__); } while (0); | ||||||
625 | |||||||
626 | /* Copy all RRs matching the specified key from source into *a */ | ||||||
627 | |||||||
628 | DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source)for (size_t __unique_prefix_i34 = ({ (rr_source) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].rr : ((void *)0); (ifindex_source) = ((source) && (source)->n_rrs > 0) ? (source)->items[0].ifindex : 0; (flags_source) = ((source) && (source)->n_rrs > 0) ? (source)-> items[0].flags : 0; 0; }); (source) && (__unique_prefix_i34 < (source)->n_rrs); __unique_prefix_i34++, (rr_source) = ((__unique_prefix_i34 < (source)->n_rrs) ? (source)-> items[__unique_prefix_i34].rr : ((void*)0)), (ifindex_source) = ((__unique_prefix_i34 < (source)->n_rrs) ? (source)-> items[__unique_prefix_i34].ifindex : 0), (flags_source) = ((__unique_prefix_i34 < (source)->n_rrs) ? (source)->items[__unique_prefix_i34 ].flags : 0)) { | ||||||
629 | |||||||
630 | r = dns_resource_key_equal(rr_source->key, key); | ||||||
631 | if (r < 0) | ||||||
632 | return r; | ||||||
633 | if (r == 0) | ||||||
634 | continue; | ||||||
635 | |||||||
636 | /* Make space for at least one entry */ | ||||||
637 | r = dns_answer_reserve_or_clone(a, 1); | ||||||
638 | if (r < 0) | ||||||
639 | return r; | ||||||
640 | |||||||
641 | r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags); | ||||||
642 | if (r < 0) | ||||||
643 | return r; | ||||||
644 | } | ||||||
645 | |||||||
646 | return 0; | ||||||
647 | } | ||||||
648 | |||||||
649 | int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) { | ||||||
650 | int r; | ||||||
651 | |||||||
652 | assert(to)do { if ((__builtin_expect(!!(!(to)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("to"), "../src/resolve/resolved-dns-answer.c" , 652, __PRETTY_FUNCTION__); } while (0); | ||||||
| |||||||
653 | assert(from)do { if ((__builtin_expect(!!(!(from)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("from"), "../src/resolve/resolved-dns-answer.c" , 653, __PRETTY_FUNCTION__); } while (0); | ||||||
654 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-answer.c" , 654, __PRETTY_FUNCTION__); } while (0); | ||||||
655 | |||||||
656 | r = dns_answer_copy_by_key(to, *from, key, or_flags); | ||||||
657 | if (r
| ||||||
658 | return r; | ||||||
659 | |||||||
660 | return dns_answer_remove_by_key(from, key); | ||||||
661 | } | ||||||
662 | |||||||
663 | void dns_answer_order_by_scope(DnsAnswer *a, bool_Bool prefer_link_local) { | ||||||
664 | DnsAnswerItem *items; | ||||||
665 | size_t i, start, end; | ||||||
666 | |||||||
667 | if (!a) | ||||||
668 | return; | ||||||
669 | |||||||
670 | if (a->n_rrs <= 1) | ||||||
671 | return; | ||||||
672 | |||||||
673 | start = 0; | ||||||
674 | end = a->n_rrs-1; | ||||||
675 | |||||||
676 | /* RFC 4795, Section 2.6 suggests we should order entries | ||||||
677 | * depending on whether the sender is a link-local address. */ | ||||||
678 | |||||||
679 | items = newa(DnsAnswerItem, a->n_rrs)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (DnsAnswerItem), a->n_rrs))),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(DnsAnswerItem), a->n_rrs)" ), "../src/resolve/resolved-dns-answer.c", 679, __PRETTY_FUNCTION__ ); } while (0); (DnsAnswerItem*) __builtin_alloca (sizeof(DnsAnswerItem )*(a->n_rrs)); }); | ||||||
680 | for (i = 0; i < a->n_rrs; i++) { | ||||||
681 | |||||||
682 | if (a->items[i].rr->key->class == DNS_CLASS_IN && | ||||||
683 | ((a->items[i].rr->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET2, (union in_addr_union*) &a->items[i].rr->a.in_addr) != prefer_link_local) || | ||||||
684 | (a->items[i].rr->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET610, (union in_addr_union*) &a->items[i].rr->aaaa.in6_addr) != prefer_link_local))) | ||||||
685 | /* Order address records that are not preferred to the end of the array */ | ||||||
686 | items[end--] = a->items[i]; | ||||||
687 | else | ||||||
688 | /* Order all other records to the beginning of the array */ | ||||||
689 | items[start++] = a->items[i]; | ||||||
690 | } | ||||||
691 | |||||||
692 | assert(start == end+1)do { if ((__builtin_expect(!!(!(start == end+1)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("start == end+1"), "../src/resolve/resolved-dns-answer.c" , 692, __PRETTY_FUNCTION__); } while (0); | ||||||
693 | memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs); | ||||||
694 | } | ||||||
695 | |||||||
696 | int dns_answer_reserve(DnsAnswer **a, size_t n_free) { | ||||||
697 | DnsAnswer *n; | ||||||
698 | |||||||
699 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 699, __PRETTY_FUNCTION__); } while (0); | ||||||
700 | |||||||
701 | if (n_free <= 0) | ||||||
702 | return 0; | ||||||
703 | |||||||
704 | if (*a) { | ||||||
705 | size_t ns; | ||||||
706 | |||||||
707 | if ((*a)->n_ref > 1) | ||||||
708 | return -EBUSY16; | ||||||
709 | |||||||
710 | ns = (*a)->n_rrs + n_free; | ||||||
711 | |||||||
712 | if ((*a)->n_allocated >= ns) | ||||||
713 | return 0; | ||||||
714 | |||||||
715 | /* Allocate more than we need */ | ||||||
716 | ns *= 2; | ||||||
717 | |||||||
718 | n = realloc(*a, offsetof(DnsAnswer, items)__builtin_offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns); | ||||||
719 | if (!n) | ||||||
720 | return -ENOMEM12; | ||||||
721 | |||||||
722 | n->n_allocated = ns; | ||||||
723 | } else { | ||||||
724 | n = dns_answer_new(n_free); | ||||||
725 | if (!n) | ||||||
726 | return -ENOMEM12; | ||||||
727 | } | ||||||
728 | |||||||
729 | *a = n; | ||||||
730 | return 0; | ||||||
731 | } | ||||||
732 | |||||||
733 | int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) { | ||||||
734 | _cleanup_(dns_answer_unrefp)__attribute__((cleanup(dns_answer_unrefp))) DnsAnswer *n = NULL((void*)0); | ||||||
735 | int r; | ||||||
736 | |||||||
737 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-answer.c" , 737, __PRETTY_FUNCTION__); } while (0); | ||||||
738 | |||||||
739 | /* Tries to extend the DnsAnswer object. And if that's not | ||||||
740 | * possible, since we are not the sole owner, then allocate a | ||||||
741 | * new, appropriately sized one. Either way, after this call | ||||||
742 | * the object will only have a single reference, and has room | ||||||
743 | * for at least the specified number of RRs. */ | ||||||
744 | |||||||
745 | r = dns_answer_reserve(a, n_free); | ||||||
746 | if (r != -EBUSY16) | ||||||
747 | return r; | ||||||
748 | |||||||
749 | assert(*a)do { if ((__builtin_expect(!!(!(*a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*a"), "../src/resolve/resolved-dns-answer.c" , 749, __PRETTY_FUNCTION__); } while (0); | ||||||
750 | |||||||
751 | n = dns_answer_new(((*a)->n_rrs + n_free) * 2); | ||||||
752 | if (!n) | ||||||
753 | return -ENOMEM12; | ||||||
754 | |||||||
755 | r = dns_answer_add_raw_all(n, *a); | ||||||
756 | if (r < 0) | ||||||
757 | return r; | ||||||
758 | |||||||
759 | dns_answer_unref(*a); | ||||||
760 | *a = TAKE_PTR(n)({ typeof(n) _ptr_ = (n); (n) = ((void*)0); _ptr_; }); | ||||||
761 | |||||||
762 | return 0; | ||||||
763 | } | ||||||
764 | |||||||
765 | void dns_answer_dump(DnsAnswer *answer, FILE *f) { | ||||||
766 | DnsResourceRecord *rr; | ||||||
767 | DnsAnswerFlags flags; | ||||||
768 | int ifindex; | ||||||
769 | |||||||
770 | if (!f) | ||||||
771 | f = stdoutstdout; | ||||||
772 | |||||||
773 | DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer)for (size_t __unique_prefix_i35 = ({ (rr) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].rr : ((void *)0); (ifindex) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].ifindex : 0; (flags) = ((answer) && (answer)->n_rrs > 0) ? (answer)->items[0].flags : 0 ; 0; }); (answer) && (__unique_prefix_i35 < (answer )->n_rrs); __unique_prefix_i35++, (rr) = ((__unique_prefix_i35 < (answer)->n_rrs) ? (answer)->items[__unique_prefix_i35 ].rr : ((void*)0)), (ifindex) = ((__unique_prefix_i35 < (answer )->n_rrs) ? (answer)->items[__unique_prefix_i35].ifindex : 0), (flags) = ((__unique_prefix_i35 < (answer)->n_rrs ) ? (answer)->items[__unique_prefix_i35].flags : 0)) { | ||||||
774 | const char *t; | ||||||
775 | |||||||
776 | fputc('\t', f); | ||||||
777 | |||||||
778 | t = dns_resource_record_to_string(rr); | ||||||
779 | if (!t) { | ||||||
780 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/resolve/resolved-dns-answer.c" , 780, __func__); | ||||||
781 | continue; | ||||||
782 | } | ||||||
783 | |||||||
784 | fputs(t, f); | ||||||
785 | |||||||
786 | if (ifindex != 0 || flags & (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE|DNS_ANSWER_SHARED_OWNER)) | ||||||
787 | fputs("\t;", f); | ||||||
788 | |||||||
789 | if (ifindex != 0) | ||||||
790 | printf(" ifindex=%i", ifindex); | ||||||
791 | if (flags & DNS_ANSWER_AUTHENTICATED) | ||||||
792 | fputs(" authenticated", f); | ||||||
793 | if (flags & DNS_ANSWER_CACHEABLE) | ||||||
794 | fputs(" cachable", f); | ||||||
795 | if (flags & DNS_ANSWER_SHARED_OWNER) | ||||||
796 | fputs(" shared-owner", f); | ||||||
797 | |||||||
798 | fputc('\n', f); | ||||||
799 | } | ||||||
800 | } | ||||||
801 | |||||||
802 | bool_Bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) { | ||||||
803 | DnsResourceRecord *rr; | ||||||
804 | int r; | ||||||
805 | |||||||
806 | assert(cname)do { if ((__builtin_expect(!!(!(cname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("cname"), "../src/resolve/resolved-dns-answer.c" , 806, __PRETTY_FUNCTION__); } while (0); | ||||||
807 | |||||||
808 | /* Checks whether the answer contains a DNAME record that indicates that the specified CNAME record is | ||||||
809 | * synthesized from it */ | ||||||
810 | |||||||
811 | if (cname->key->type != DNS_TYPE_CNAME) | ||||||
812 | return 0; | ||||||
813 | |||||||
814 | DNS_ANSWER_FOREACH(rr, a)for (size_t __unique_prefix_i36 = ({ (rr) = ((a) && ( a)->n_rrs > 0) ? (a)->items[0].rr : ((void*)0); 0; } ); (a) && (__unique_prefix_i36 < (a)->n_rrs); __unique_prefix_i36 ++, (rr) = (__unique_prefix_i36 < (a)->n_rrs ? (a)-> items[__unique_prefix_i36].rr : ((void*)0))) { | ||||||
815 | _cleanup_free___attribute__((cleanup(freep))) char *n = NULL((void*)0); | ||||||
816 | |||||||
817 | if (rr->key->type != DNS_TYPE_DNAME) | ||||||
818 | continue; | ||||||
819 | if (rr->key->class != cname->key->class) | ||||||
820 | continue; | ||||||
821 | |||||||
822 | r = dns_name_change_suffix(cname->cname.name, rr->dname.name, dns_resource_key_name(rr->key), &n); | ||||||
823 | if (r < 0) | ||||||
824 | return r; | ||||||
825 | if (r == 0) | ||||||
826 | continue; | ||||||
827 | |||||||
828 | r = dns_name_equal(n, dns_resource_key_name(cname->key)); | ||||||
829 | if (r < 0) | ||||||
830 | return r; | ||||||
831 | if (r > 0) | ||||||
832 | return 1; | ||||||
833 | |||||||
834 | } | ||||||
835 | |||||||
836 | return 0; | ||||||
837 | } |