File: | build-scan/../src/resolve/resolved-dns-rr.c |
Warning: | line 537, column 12 Potential leak of memory pointed to by 'key' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <math.h> | |||
4 | ||||
5 | #include "alloc-util.h" | |||
6 | #include "dns-domain.h" | |||
7 | #include "dns-type.h" | |||
8 | #include "escape.h" | |||
9 | #include "hexdecoct.h" | |||
10 | #include "resolved-dns-dnssec.h" | |||
11 | #include "resolved-dns-packet.h" | |||
12 | #include "resolved-dns-rr.h" | |||
13 | #include "string-table.h" | |||
14 | #include "string-util.h" | |||
15 | #include "strv.h" | |||
16 | #include "terminal-util.h" | |||
17 | ||||
18 | DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) { | |||
19 | DnsResourceKey *k; | |||
20 | size_t l; | |||
21 | ||||
22 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/resolve/resolved-dns-rr.c" , 22, __PRETTY_FUNCTION__); } while (0); | |||
23 | ||||
24 | l = strlen(name); | |||
25 | k = malloc0(sizeof(DnsResourceKey) + l + 1)(calloc(1, (sizeof(DnsResourceKey) + l + 1))); | |||
26 | if (!k) | |||
27 | return NULL((void*)0); | |||
28 | ||||
29 | k->n_ref = 1; | |||
30 | k->class = class; | |||
31 | k->type = type; | |||
32 | ||||
33 | strcpy((char*) k + sizeof(DnsResourceKey), name); | |||
34 | ||||
35 | return k; | |||
36 | } | |||
37 | ||||
38 | DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) { | |||
39 | int r; | |||
40 | ||||
41 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-rr.c" , 41, __PRETTY_FUNCTION__); } while (0); | |||
42 | assert(cname)do { if ((__builtin_expect(!!(!(cname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("cname"), "../src/resolve/resolved-dns-rr.c" , 42, __PRETTY_FUNCTION__); } while (0); | |||
43 | ||||
44 | assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){DNS_TYPE_CNAME, DNS_TYPE_DNAME})/sizeof(int )]; switch(cname->key->type) { case DNS_TYPE_CNAME: case DNS_TYPE_DNAME: _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME)" ), "../src/resolve/resolved-dns-rr.c", 44, __PRETTY_FUNCTION__ ); } while (0); | |||
45 | ||||
46 | if (cname->key->type == DNS_TYPE_CNAME) | |||
47 | return dns_resource_key_new(key->class, key->type, cname->cname.name); | |||
48 | else { | |||
49 | DnsResourceKey *k; | |||
50 | char *destination = NULL((void*)0); | |||
51 | ||||
52 | r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination); | |||
53 | if (r < 0) | |||
54 | return NULL((void*)0); | |||
55 | if (r == 0) | |||
56 | return dns_resource_key_ref((DnsResourceKey*) key); | |||
57 | ||||
58 | k = dns_resource_key_new_consume(key->class, key->type, destination); | |||
59 | if (!k) | |||
60 | return mfree(destination); | |||
61 | ||||
62 | return k; | |||
63 | } | |||
64 | } | |||
65 | ||||
66 | int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) { | |||
67 | DnsResourceKey *new_key; | |||
68 | char *joined; | |||
69 | int r; | |||
70 | ||||
71 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-rr.c" , 71, __PRETTY_FUNCTION__); } while (0); | |||
72 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-rr.c" , 72, __PRETTY_FUNCTION__); } while (0); | |||
73 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/resolve/resolved-dns-rr.c" , 73, __PRETTY_FUNCTION__); } while (0); | |||
74 | ||||
75 | if (dns_name_is_root(name)) { | |||
76 | *ret = dns_resource_key_ref(key); | |||
77 | return 0; | |||
78 | } | |||
79 | ||||
80 | r = dns_name_concat(dns_resource_key_name(key), name, &joined); | |||
81 | if (r < 0) | |||
82 | return r; | |||
83 | ||||
84 | new_key = dns_resource_key_new_consume(key->class, key->type, joined); | |||
85 | if (!new_key) { | |||
86 | free(joined); | |||
87 | return -ENOMEM12; | |||
88 | } | |||
89 | ||||
90 | *ret = new_key; | |||
91 | return 0; | |||
92 | } | |||
93 | ||||
94 | DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) { | |||
95 | DnsResourceKey *k; | |||
96 | ||||
97 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/resolve/resolved-dns-rr.c" , 97, __PRETTY_FUNCTION__); } while (0); | |||
98 | ||||
99 | k = new0(DnsResourceKey, 1)((DnsResourceKey*) calloc((1), sizeof(DnsResourceKey))); | |||
100 | if (!k) | |||
101 | return NULL((void*)0); | |||
102 | ||||
103 | k->n_ref = 1; | |||
104 | k->class = class; | |||
105 | k->type = type; | |||
106 | k->_name = name; | |||
107 | ||||
108 | return k; | |||
109 | } | |||
110 | ||||
111 | DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) { | |||
112 | ||||
113 | if (!k) | |||
114 | return NULL((void*)0); | |||
115 | ||||
116 | /* Static/const keys created with DNS_RESOURCE_KEY_CONST will | |||
117 | * set this to -1, they should not be reffed/unreffed */ | |||
118 | assert(k->n_ref != (unsigned) -1)do { if ((__builtin_expect(!!(!(k->n_ref != (unsigned) -1) ),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("k->n_ref != (unsigned) -1" ), "../src/resolve/resolved-dns-rr.c", 118, __PRETTY_FUNCTION__ ); } while (0); | |||
119 | ||||
120 | assert(k->n_ref > 0)do { if ((__builtin_expect(!!(!(k->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("k->n_ref > 0"), "../src/resolve/resolved-dns-rr.c" , 120, __PRETTY_FUNCTION__); } while (0); | |||
121 | k->n_ref++; | |||
122 | ||||
123 | return k; | |||
124 | } | |||
125 | ||||
126 | DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) { | |||
127 | if (!k) | |||
128 | return NULL((void*)0); | |||
129 | ||||
130 | assert(k->n_ref != (unsigned) -1)do { if ((__builtin_expect(!!(!(k->n_ref != (unsigned) -1) ),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("k->n_ref != (unsigned) -1" ), "../src/resolve/resolved-dns-rr.c", 130, __PRETTY_FUNCTION__ ); } while (0); | |||
131 | assert(k->n_ref > 0)do { if ((__builtin_expect(!!(!(k->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("k->n_ref > 0"), "../src/resolve/resolved-dns-rr.c" , 131, __PRETTY_FUNCTION__); } while (0); | |||
132 | ||||
133 | if (k->n_ref == 1) { | |||
134 | free(k->_name); | |||
135 | free(k); | |||
136 | } else | |||
137 | k->n_ref--; | |||
138 | ||||
139 | return NULL((void*)0); | |||
140 | } | |||
141 | ||||
142 | const char* dns_resource_key_name(const DnsResourceKey *key) { | |||
143 | const char *name; | |||
144 | ||||
145 | if (!key) | |||
146 | return NULL((void*)0); | |||
147 | ||||
148 | if (key->_name) | |||
149 | name = key->_name; | |||
150 | else | |||
151 | name = (char*) key + sizeof(DnsResourceKey); | |||
152 | ||||
153 | if (dns_name_is_root(name)) | |||
154 | return "."; | |||
155 | else | |||
156 | return name; | |||
157 | } | |||
158 | ||||
159 | bool_Bool dns_resource_key_is_address(const DnsResourceKey *key) { | |||
160 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-rr.c" , 160, __PRETTY_FUNCTION__); } while (0); | |||
161 | ||||
162 | /* Check if this is an A or AAAA resource key */ | |||
163 | ||||
164 | return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){DNS_TYPE_A, DNS_TYPE_AAAA})/sizeof(int)] ; switch(key->type) { case DNS_TYPE_A: case DNS_TYPE_AAAA: _found = 1; break; default: break; } _found; }); | |||
165 | } | |||
166 | ||||
167 | bool_Bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key) { | |||
168 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-rr.c" , 168, __PRETTY_FUNCTION__); } while (0); | |||
169 | ||||
170 | /* Check if this is a PTR resource key used in | |||
171 | Service Instance Enumeration as described in RFC6763 p4.1. */ | |||
172 | ||||
173 | if (key->type != DNS_TYPE_PTR) | |||
174 | return false0; | |||
175 | ||||
176 | return dns_name_endswith(dns_resource_key_name(key), "_tcp.local") || | |||
177 | dns_name_endswith(dns_resource_key_name(key), "_udp.local"); | |||
178 | } | |||
179 | ||||
180 | int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) { | |||
181 | int r; | |||
182 | ||||
183 | if (a == b) | |||
184 | return 1; | |||
185 | ||||
186 | r = dns_name_equal(dns_resource_key_name(a), dns_resource_key_name(b)); | |||
187 | if (r <= 0) | |||
188 | return r; | |||
189 | ||||
190 | if (a->class != b->class) | |||
191 | return 0; | |||
192 | ||||
193 | if (a->type != b->type) | |||
194 | return 0; | |||
195 | ||||
196 | return 1; | |||
197 | } | |||
198 | ||||
199 | int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) { | |||
200 | int r; | |||
201 | ||||
202 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-rr.c" , 202, __PRETTY_FUNCTION__); } while (0); | |||
203 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 203, __PRETTY_FUNCTION__); } while (0); | |||
204 | ||||
205 | if (key == rr->key) | |||
206 | return 1; | |||
207 | ||||
208 | /* Checks if an rr matches the specified key. If a search | |||
209 | * domain is specified, it will also be checked if the key | |||
210 | * with the search domain suffixed might match the RR. */ | |||
211 | ||||
212 | if (rr->key->class != key->class && key->class != DNS_CLASS_ANY) | |||
213 | return 0; | |||
214 | ||||
215 | if (rr->key->type != key->type && key->type != DNS_TYPE_ANY) | |||
216 | return 0; | |||
217 | ||||
218 | r = dns_name_equal(dns_resource_key_name(rr->key), dns_resource_key_name(key)); | |||
219 | if (r != 0) | |||
220 | return r; | |||
221 | ||||
222 | if (search_domain) { | |||
223 | _cleanup_free___attribute__((cleanup(freep))) char *joined = NULL((void*)0); | |||
224 | ||||
225 | r = dns_name_concat(dns_resource_key_name(key), search_domain, &joined); | |||
226 | if (r < 0) | |||
227 | return r; | |||
228 | ||||
229 | return dns_name_equal(dns_resource_key_name(rr->key), joined); | |||
230 | } | |||
231 | ||||
232 | return 0; | |||
233 | } | |||
234 | ||||
235 | int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) { | |||
236 | int r; | |||
237 | ||||
238 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-rr.c" , 238, __PRETTY_FUNCTION__); } while (0); | |||
239 | assert(cname)do { if ((__builtin_expect(!!(!(cname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("cname"), "../src/resolve/resolved-dns-rr.c" , 239, __PRETTY_FUNCTION__); } while (0); | |||
240 | ||||
241 | if (cname->class != key->class && key->class != DNS_CLASS_ANY) | |||
242 | return 0; | |||
243 | ||||
244 | if (cname->type == DNS_TYPE_CNAME) | |||
245 | r = dns_name_equal(dns_resource_key_name(key), dns_resource_key_name(cname)); | |||
246 | else if (cname->type == DNS_TYPE_DNAME) | |||
247 | r = dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(cname)); | |||
248 | else | |||
249 | return 0; | |||
250 | ||||
251 | if (r != 0) | |||
252 | return r; | |||
253 | ||||
254 | if (search_domain) { | |||
255 | _cleanup_free___attribute__((cleanup(freep))) char *joined = NULL((void*)0); | |||
256 | ||||
257 | r = dns_name_concat(dns_resource_key_name(key), search_domain, &joined); | |||
258 | if (r < 0) | |||
259 | return r; | |||
260 | ||||
261 | if (cname->type == DNS_TYPE_CNAME) | |||
262 | return dns_name_equal(joined, dns_resource_key_name(cname)); | |||
263 | else if (cname->type == DNS_TYPE_DNAME) | |||
264 | return dns_name_endswith(joined, dns_resource_key_name(cname)); | |||
265 | } | |||
266 | ||||
267 | return 0; | |||
268 | } | |||
269 | ||||
270 | int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) { | |||
271 | assert(soa)do { if ((__builtin_expect(!!(!(soa)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("soa"), "../src/resolve/resolved-dns-rr.c" , 271, __PRETTY_FUNCTION__); } while (0); | |||
272 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/resolve/resolved-dns-rr.c" , 272, __PRETTY_FUNCTION__); } while (0); | |||
273 | ||||
274 | /* Checks whether 'soa' is a SOA record for the specified key. */ | |||
275 | ||||
276 | if (soa->class != key->class) | |||
277 | return 0; | |||
278 | ||||
279 | if (soa->type != DNS_TYPE_SOA) | |||
280 | return 0; | |||
281 | ||||
282 | return dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(soa)); | |||
283 | } | |||
284 | ||||
285 | static void dns_resource_key_hash_func(const void *i, struct siphash *state) { | |||
286 | const DnsResourceKey *k = i; | |||
287 | ||||
288 | assert(k)do { if ((__builtin_expect(!!(!(k)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("k"), "../src/resolve/resolved-dns-rr.c" , 288, __PRETTY_FUNCTION__); } while (0); | |||
289 | ||||
290 | dns_name_hash_func(dns_resource_key_name(k), state); | |||
291 | siphash24_compress(&k->class, sizeof(k->class), state); | |||
292 | siphash24_compress(&k->type, sizeof(k->type), state); | |||
293 | } | |||
294 | ||||
295 | static int dns_resource_key_compare_func(const void *a, const void *b) { | |||
296 | const DnsResourceKey *x = a, *y = b; | |||
297 | int ret; | |||
298 | ||||
299 | ret = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y)); | |||
300 | if (ret != 0) | |||
301 | return ret; | |||
302 | ||||
303 | if (x->type < y->type) | |||
304 | return -1; | |||
305 | if (x->type > y->type) | |||
306 | return 1; | |||
307 | ||||
308 | if (x->class < y->class) | |||
309 | return -1; | |||
310 | if (x->class > y->class) | |||
311 | return 1; | |||
312 | ||||
313 | return 0; | |||
314 | } | |||
315 | ||||
316 | const struct hash_ops dns_resource_key_hash_ops = { | |||
317 | .hash = dns_resource_key_hash_func, | |||
318 | .compare = dns_resource_key_compare_func | |||
319 | }; | |||
320 | ||||
321 | char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size) { | |||
322 | const char *c, *t; | |||
323 | char *ans = buf; | |||
324 | ||||
325 | /* If we cannot convert the CLASS/TYPE into a known string, | |||
326 | use the format recommended by RFC 3597, Section 5. */ | |||
327 | ||||
328 | c = dns_class_to_string(key->class); | |||
329 | t = dns_type_to_string(key->type); | |||
330 | ||||
331 | snprintf(buf, buf_size, "%s %s%s%.0u %s%s%.0u", | |||
332 | dns_resource_key_name(key), | |||
333 | strempty(c), c ? "" : "CLASS", c ? 0 : key->class, | |||
334 | strempty(t), t ? "" : "TYPE", t ? 0 : key->type); | |||
335 | ||||
336 | return ans; | |||
337 | } | |||
338 | ||||
339 | bool_Bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) { | |||
340 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-rr.c" , 340, __PRETTY_FUNCTION__); } while (0); | |||
341 | assert(b)do { if ((__builtin_expect(!!(!(b)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("b"), "../src/resolve/resolved-dns-rr.c" , 341, __PRETTY_FUNCTION__); } while (0); | |||
342 | ||||
343 | /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do | |||
344 | * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come | |||
345 | * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same | |||
346 | * superficial data. */ | |||
347 | ||||
348 | if (!*a) | |||
349 | return false0; | |||
350 | if (!*b) | |||
351 | return false0; | |||
352 | ||||
353 | /* We refuse merging const keys */ | |||
354 | if ((*a)->n_ref == (unsigned) -1) | |||
355 | return false0; | |||
356 | if ((*b)->n_ref == (unsigned) -1) | |||
357 | return false0; | |||
358 | ||||
359 | /* Already the same? */ | |||
360 | if (*a == *b) | |||
361 | return true1; | |||
362 | ||||
363 | /* Are they really identical? */ | |||
364 | if (dns_resource_key_equal(*a, *b) <= 0) | |||
365 | return false0; | |||
366 | ||||
367 | /* Keep the one which already has more references. */ | |||
368 | if ((*a)->n_ref > (*b)->n_ref) { | |||
369 | dns_resource_key_unref(*b); | |||
370 | *b = dns_resource_key_ref(*a); | |||
371 | } else { | |||
372 | dns_resource_key_unref(*a); | |||
373 | *a = dns_resource_key_ref(*b); | |||
374 | } | |||
375 | ||||
376 | return true1; | |||
377 | } | |||
378 | ||||
379 | DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) { | |||
380 | DnsResourceRecord *rr; | |||
381 | ||||
382 | rr = new0(DnsResourceRecord, 1)((DnsResourceRecord*) calloc((1), sizeof(DnsResourceRecord))); | |||
383 | if (!rr) | |||
384 | return NULL((void*)0); | |||
385 | ||||
386 | rr->n_ref = 1; | |||
387 | rr->key = dns_resource_key_ref(key); | |||
388 | rr->expiry = USEC_INFINITY((usec_t) -1); | |||
389 | rr->n_skip_labels_signer = rr->n_skip_labels_source = (unsigned) -1; | |||
390 | ||||
391 | return rr; | |||
392 | } | |||
393 | ||||
394 | DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) { | |||
395 | _cleanup_(dns_resource_key_unrefp)__attribute__((cleanup(dns_resource_key_unrefp))) DnsResourceKey *key = NULL((void*)0); | |||
396 | ||||
397 | key = dns_resource_key_new(class, type, name); | |||
398 | if (!key) | |||
399 | return NULL((void*)0); | |||
400 | ||||
401 | return dns_resource_record_new(key); | |||
402 | } | |||
403 | ||||
404 | DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) { | |||
405 | if (!rr) | |||
406 | return NULL((void*)0); | |||
407 | ||||
408 | assert(rr->n_ref > 0)do { if ((__builtin_expect(!!(!(rr->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr->n_ref > 0"), "../src/resolve/resolved-dns-rr.c" , 408, __PRETTY_FUNCTION__); } while (0); | |||
409 | rr->n_ref++; | |||
410 | ||||
411 | return rr; | |||
412 | } | |||
413 | ||||
414 | DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) { | |||
415 | if (!rr) | |||
416 | return NULL((void*)0); | |||
417 | ||||
418 | assert(rr->n_ref > 0)do { if ((__builtin_expect(!!(!(rr->n_ref > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr->n_ref > 0"), "../src/resolve/resolved-dns-rr.c" , 418, __PRETTY_FUNCTION__); } while (0); | |||
419 | ||||
420 | if (rr->n_ref > 1) { | |||
421 | rr->n_ref--; | |||
422 | return NULL((void*)0); | |||
423 | } | |||
424 | ||||
425 | if (rr->key) { | |||
426 | switch(rr->key->type) { | |||
427 | ||||
428 | case DNS_TYPE_SRV: | |||
429 | free(rr->srv.name); | |||
430 | break; | |||
431 | ||||
432 | case DNS_TYPE_PTR: | |||
433 | case DNS_TYPE_NS: | |||
434 | case DNS_TYPE_CNAME: | |||
435 | case DNS_TYPE_DNAME: | |||
436 | free(rr->ptr.name); | |||
437 | break; | |||
438 | ||||
439 | case DNS_TYPE_HINFO: | |||
440 | free(rr->hinfo.cpu); | |||
441 | free(rr->hinfo.os); | |||
442 | break; | |||
443 | ||||
444 | case DNS_TYPE_TXT: | |||
445 | case DNS_TYPE_SPF: | |||
446 | dns_txt_item_free_all(rr->txt.items); | |||
447 | break; | |||
448 | ||||
449 | case DNS_TYPE_SOA: | |||
450 | free(rr->soa.mname); | |||
451 | free(rr->soa.rname); | |||
452 | break; | |||
453 | ||||
454 | case DNS_TYPE_MX: | |||
455 | free(rr->mx.exchange); | |||
456 | break; | |||
457 | ||||
458 | case DNS_TYPE_DS: | |||
459 | free(rr->ds.digest); | |||
460 | break; | |||
461 | ||||
462 | case DNS_TYPE_SSHFP: | |||
463 | free(rr->sshfp.fingerprint); | |||
464 | break; | |||
465 | ||||
466 | case DNS_TYPE_DNSKEY: | |||
467 | free(rr->dnskey.key); | |||
468 | break; | |||
469 | ||||
470 | case DNS_TYPE_RRSIG: | |||
471 | free(rr->rrsig.signer); | |||
472 | free(rr->rrsig.signature); | |||
473 | break; | |||
474 | ||||
475 | case DNS_TYPE_NSEC: | |||
476 | free(rr->nsec.next_domain_name); | |||
477 | bitmap_free(rr->nsec.types); | |||
478 | break; | |||
479 | ||||
480 | case DNS_TYPE_NSEC3: | |||
481 | free(rr->nsec3.next_hashed_name); | |||
482 | free(rr->nsec3.salt); | |||
483 | bitmap_free(rr->nsec3.types); | |||
484 | break; | |||
485 | ||||
486 | case DNS_TYPE_LOC: | |||
487 | case DNS_TYPE_A: | |||
488 | case DNS_TYPE_AAAA: | |||
489 | break; | |||
490 | ||||
491 | case DNS_TYPE_TLSA: | |||
492 | free(rr->tlsa.data); | |||
493 | break; | |||
494 | ||||
495 | case DNS_TYPE_CAA: | |||
496 | free(rr->caa.tag); | |||
497 | free(rr->caa.value); | |||
498 | break; | |||
499 | ||||
500 | case DNS_TYPE_OPENPGPKEY: | |||
501 | default: | |||
502 | if (!rr->unparseable) | |||
503 | free(rr->generic.data); | |||
504 | } | |||
505 | ||||
506 | if (rr->unparseable) | |||
507 | free(rr->generic.data); | |||
508 | ||||
509 | free(rr->wire_format); | |||
510 | dns_resource_key_unref(rr->key); | |||
511 | } | |||
512 | ||||
513 | free(rr->to_string); | |||
514 | return mfree(rr); | |||
515 | } | |||
516 | ||||
517 | int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) { | |||
518 | _cleanup_(dns_resource_key_unrefp)__attribute__((cleanup(dns_resource_key_unrefp))) DnsResourceKey *key = NULL((void*)0); | |||
519 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *rr = NULL((void*)0); | |||
520 | _cleanup_free___attribute__((cleanup(freep))) char *ptr = NULL((void*)0); | |||
521 | int r; | |||
522 | ||||
523 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-rr.c" , 523, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
524 | assert(address)do { if ((__builtin_expect(!!(!(address)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("address"), "../src/resolve/resolved-dns-rr.c" , 524, __PRETTY_FUNCTION__); } while (0); | |||
525 | assert(hostname)do { if ((__builtin_expect(!!(!(hostname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("hostname"), "../src/resolve/resolved-dns-rr.c" , 525, __PRETTY_FUNCTION__); } while (0); | |||
526 | ||||
527 | r = dns_name_reverse(family, address, &ptr); | |||
528 | if (r < 0) | |||
529 | return r; | |||
530 | ||||
531 | key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr); | |||
532 | if (!key
| |||
533 | return -ENOMEM12; | |||
534 | ||||
535 | ptr = NULL((void*)0); | |||
536 | ||||
537 | rr = dns_resource_record_new(key); | |||
| ||||
538 | if (!rr) | |||
539 | return -ENOMEM12; | |||
540 | ||||
541 | rr->ptr.name = strdup(hostname); | |||
542 | if (!rr->ptr.name) | |||
543 | return -ENOMEM12; | |||
544 | ||||
545 | *ret = TAKE_PTR(rr)({ typeof(rr) _ptr_ = (rr); (rr) = ((void*)0); _ptr_; }); | |||
546 | ||||
547 | return 0; | |||
548 | } | |||
549 | ||||
550 | int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) { | |||
551 | DnsResourceRecord *rr; | |||
552 | ||||
553 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-rr.c" , 553, __PRETTY_FUNCTION__); } while (0); | |||
554 | assert(address)do { if ((__builtin_expect(!!(!(address)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("address"), "../src/resolve/resolved-dns-rr.c" , 554, __PRETTY_FUNCTION__); } while (0); | |||
555 | assert(family)do { if ((__builtin_expect(!!(!(family)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("family"), "../src/resolve/resolved-dns-rr.c" , 555, __PRETTY_FUNCTION__); } while (0); | |||
556 | ||||
557 | if (family == AF_INET2) { | |||
558 | ||||
559 | rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name); | |||
560 | if (!rr) | |||
561 | return -ENOMEM12; | |||
562 | ||||
563 | rr->a.in_addr = address->in; | |||
564 | ||||
565 | } else if (family == AF_INET610) { | |||
566 | ||||
567 | rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name); | |||
568 | if (!rr) | |||
569 | return -ENOMEM12; | |||
570 | ||||
571 | rr->aaaa.in6_addr = address->in6; | |||
572 | } else | |||
573 | return -EAFNOSUPPORT97; | |||
574 | ||||
575 | *ret = rr; | |||
576 | ||||
577 | return 0; | |||
578 | } | |||
579 | ||||
580 | #define FIELD_EQUAL(a, b, field)((a).field_size == (b).field_size && memcmp((a).field , (b).field, (a).field_size) == 0) \ | |||
581 | ((a).field ## _size == (b).field ## _size && \ | |||
582 | memcmp((a).field, (b).field, (a).field ## _size) == 0) | |||
583 | ||||
584 | int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) { | |||
585 | int r; | |||
586 | ||||
587 | assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("a"), "../src/resolve/resolved-dns-rr.c" , 587, __PRETTY_FUNCTION__); } while (0); | |||
588 | assert(b)do { if ((__builtin_expect(!!(!(b)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("b"), "../src/resolve/resolved-dns-rr.c" , 588, __PRETTY_FUNCTION__); } while (0); | |||
589 | ||||
590 | if (a == b) | |||
591 | return 1; | |||
592 | ||||
593 | r = dns_resource_key_equal(a->key, b->key); | |||
594 | if (r <= 0) | |||
595 | return r; | |||
596 | ||||
597 | if (a->unparseable != b->unparseable) | |||
598 | return 0; | |||
599 | ||||
600 | switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) { | |||
601 | ||||
602 | case DNS_TYPE_SRV: | |||
603 | r = dns_name_equal(a->srv.name, b->srv.name); | |||
604 | if (r <= 0) | |||
605 | return r; | |||
606 | ||||
607 | return a->srv.priority == b->srv.priority && | |||
608 | a->srv.weight == b->srv.weight && | |||
609 | a->srv.port == b->srv.port; | |||
610 | ||||
611 | case DNS_TYPE_PTR: | |||
612 | case DNS_TYPE_NS: | |||
613 | case DNS_TYPE_CNAME: | |||
614 | case DNS_TYPE_DNAME: | |||
615 | return dns_name_equal(a->ptr.name, b->ptr.name); | |||
616 | ||||
617 | case DNS_TYPE_HINFO: | |||
618 | return strcaseeq(a->hinfo.cpu, b->hinfo.cpu)(strcasecmp((a->hinfo.cpu),(b->hinfo.cpu)) == 0) && | |||
619 | strcaseeq(a->hinfo.os, b->hinfo.os)(strcasecmp((a->hinfo.os),(b->hinfo.os)) == 0); | |||
620 | ||||
621 | case DNS_TYPE_SPF: /* exactly the same as TXT */ | |||
622 | case DNS_TYPE_TXT: | |||
623 | return dns_txt_item_equal(a->txt.items, b->txt.items); | |||
624 | ||||
625 | case DNS_TYPE_A: | |||
626 | return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0; | |||
627 | ||||
628 | case DNS_TYPE_AAAA: | |||
629 | return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0; | |||
630 | ||||
631 | case DNS_TYPE_SOA: | |||
632 | r = dns_name_equal(a->soa.mname, b->soa.mname); | |||
633 | if (r <= 0) | |||
634 | return r; | |||
635 | r = dns_name_equal(a->soa.rname, b->soa.rname); | |||
636 | if (r <= 0) | |||
637 | return r; | |||
638 | ||||
639 | return a->soa.serial == b->soa.serial && | |||
640 | a->soa.refresh == b->soa.refresh && | |||
641 | a->soa.retry == b->soa.retry && | |||
642 | a->soa.expire == b->soa.expire && | |||
643 | a->soa.minimum == b->soa.minimum; | |||
644 | ||||
645 | case DNS_TYPE_MX: | |||
646 | if (a->mx.priority != b->mx.priority) | |||
647 | return 0; | |||
648 | ||||
649 | return dns_name_equal(a->mx.exchange, b->mx.exchange); | |||
650 | ||||
651 | case DNS_TYPE_LOC: | |||
652 | assert(a->loc.version == b->loc.version)do { if ((__builtin_expect(!!(!(a->loc.version == b->loc .version)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("a->loc.version == b->loc.version" ), "../src/resolve/resolved-dns-rr.c", 652, __PRETTY_FUNCTION__ ); } while (0); | |||
653 | ||||
654 | return a->loc.size == b->loc.size && | |||
655 | a->loc.horiz_pre == b->loc.horiz_pre && | |||
656 | a->loc.vert_pre == b->loc.vert_pre && | |||
657 | a->loc.latitude == b->loc.latitude && | |||
658 | a->loc.longitude == b->loc.longitude && | |||
659 | a->loc.altitude == b->loc.altitude; | |||
660 | ||||
661 | case DNS_TYPE_DS: | |||
662 | return a->ds.key_tag == b->ds.key_tag && | |||
663 | a->ds.algorithm == b->ds.algorithm && | |||
664 | a->ds.digest_type == b->ds.digest_type && | |||
665 | FIELD_EQUAL(a->ds, b->ds, digest)((a->ds).digest_size == (b->ds).digest_size && memcmp ((a->ds).digest, (b->ds).digest, (a->ds).digest_size ) == 0); | |||
666 | ||||
667 | case DNS_TYPE_SSHFP: | |||
668 | return a->sshfp.algorithm == b->sshfp.algorithm && | |||
669 | a->sshfp.fptype == b->sshfp.fptype && | |||
670 | FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint)((a->sshfp).fingerprint_size == (b->sshfp).fingerprint_size && memcmp((a->sshfp).fingerprint, (b->sshfp).fingerprint , (a->sshfp).fingerprint_size) == 0); | |||
671 | ||||
672 | case DNS_TYPE_DNSKEY: | |||
673 | return a->dnskey.flags == b->dnskey.flags && | |||
674 | a->dnskey.protocol == b->dnskey.protocol && | |||
675 | a->dnskey.algorithm == b->dnskey.algorithm && | |||
676 | FIELD_EQUAL(a->dnskey, b->dnskey, key)((a->dnskey).key_size == (b->dnskey).key_size && memcmp((a->dnskey).key, (b->dnskey).key, (a->dnskey ).key_size) == 0); | |||
677 | ||||
678 | case DNS_TYPE_RRSIG: | |||
679 | /* do the fast comparisons first */ | |||
680 | return a->rrsig.type_covered == b->rrsig.type_covered && | |||
681 | a->rrsig.algorithm == b->rrsig.algorithm && | |||
682 | a->rrsig.labels == b->rrsig.labels && | |||
683 | a->rrsig.original_ttl == b->rrsig.original_ttl && | |||
684 | a->rrsig.expiration == b->rrsig.expiration && | |||
685 | a->rrsig.inception == b->rrsig.inception && | |||
686 | a->rrsig.key_tag == b->rrsig.key_tag && | |||
687 | FIELD_EQUAL(a->rrsig, b->rrsig, signature)((a->rrsig).signature_size == (b->rrsig).signature_size && memcmp((a->rrsig).signature, (b->rrsig).signature , (a->rrsig).signature_size) == 0) && | |||
688 | dns_name_equal(a->rrsig.signer, b->rrsig.signer); | |||
689 | ||||
690 | case DNS_TYPE_NSEC: | |||
691 | return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) && | |||
692 | bitmap_equal(a->nsec.types, b->nsec.types); | |||
693 | ||||
694 | case DNS_TYPE_NSEC3: | |||
695 | return a->nsec3.algorithm == b->nsec3.algorithm && | |||
696 | a->nsec3.flags == b->nsec3.flags && | |||
697 | a->nsec3.iterations == b->nsec3.iterations && | |||
698 | FIELD_EQUAL(a->nsec3, b->nsec3, salt)((a->nsec3).salt_size == (b->nsec3).salt_size && memcmp((a->nsec3).salt, (b->nsec3).salt, (a->nsec3) .salt_size) == 0) && | |||
699 | FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name)((a->nsec3).next_hashed_name_size == (b->nsec3).next_hashed_name_size && memcmp((a->nsec3).next_hashed_name, (b->nsec3 ).next_hashed_name, (a->nsec3).next_hashed_name_size) == 0 ) && | |||
700 | bitmap_equal(a->nsec3.types, b->nsec3.types); | |||
701 | ||||
702 | case DNS_TYPE_TLSA: | |||
703 | return a->tlsa.cert_usage == b->tlsa.cert_usage && | |||
704 | a->tlsa.selector == b->tlsa.selector && | |||
705 | a->tlsa.matching_type == b->tlsa.matching_type && | |||
706 | FIELD_EQUAL(a->tlsa, b->tlsa, data)((a->tlsa).data_size == (b->tlsa).data_size && memcmp ((a->tlsa).data, (b->tlsa).data, (a->tlsa).data_size ) == 0); | |||
707 | ||||
708 | case DNS_TYPE_CAA: | |||
709 | return a->caa.flags == b->caa.flags && | |||
710 | streq(a->caa.tag, b->caa.tag)(strcmp((a->caa.tag),(b->caa.tag)) == 0) && | |||
711 | FIELD_EQUAL(a->caa, b->caa, value)((a->caa).value_size == (b->caa).value_size && memcmp ((a->caa).value, (b->caa).value, (a->caa).value_size ) == 0); | |||
712 | ||||
713 | case DNS_TYPE_OPENPGPKEY: | |||
714 | default: | |||
715 | return FIELD_EQUAL(a->generic, b->generic, data)((a->generic).data_size == (b->generic).data_size && memcmp((a->generic).data, (b->generic).data, (a->generic ).data_size) == 0); | |||
716 | } | |||
717 | } | |||
718 | ||||
719 | static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude, | |||
720 | uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) { | |||
721 | char *s; | |||
722 | char NS = latitude >= 1U<<31 ? 'N' : 'S'; | |||
723 | char EW = longitude >= 1U<<31 ? 'E' : 'W'; | |||
724 | ||||
725 | int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude); | |||
726 | int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude); | |||
727 | double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude); | |||
728 | double siz = (size >> 4) * exp10((double) (size & 0xF)); | |||
729 | double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF)); | |||
730 | double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF)); | |||
731 | ||||
732 | if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm", | |||
733 | (lat / 60000 / 60), | |||
734 | (lat / 60000) % 60, | |||
735 | (lat % 60000) / 1000., | |||
736 | NS, | |||
737 | (lon / 60000 / 60), | |||
738 | (lon / 60000) % 60, | |||
739 | (lon % 60000) / 1000., | |||
740 | EW, | |||
741 | alt / 100., | |||
742 | siz / 100., | |||
743 | hor / 100., | |||
744 | ver / 100.) < 0) | |||
745 | return NULL((void*)0); | |||
746 | ||||
747 | return s; | |||
748 | } | |||
749 | ||||
750 | static int format_timestamp_dns(char *buf, size_t l, time_t sec) { | |||
751 | struct tm tm; | |||
752 | ||||
753 | assert(buf)do { if ((__builtin_expect(!!(!(buf)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buf"), "../src/resolve/resolved-dns-rr.c" , 753, __PRETTY_FUNCTION__); } while (0); | |||
754 | assert(l > STRLEN("YYYYMMDDHHmmSS"))do { if ((__builtin_expect(!!(!(l > (sizeof("""YYYYMMDDHHmmSS" "") - 1))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("l > STRLEN(\"YYYYMMDDHHmmSS\")" ), "../src/resolve/resolved-dns-rr.c", 754, __PRETTY_FUNCTION__ ); } while (0); | |||
755 | ||||
756 | if (!gmtime_r(&sec, &tm)) | |||
757 | return -EINVAL22; | |||
758 | ||||
759 | if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0) | |||
760 | return -EINVAL22; | |||
761 | ||||
762 | return 0; | |||
763 | } | |||
764 | ||||
765 | static char *format_types(Bitmap *types) { | |||
766 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **strv = NULL((void*)0); | |||
767 | _cleanup_free___attribute__((cleanup(freep))) char *str = NULL((void*)0); | |||
768 | Iterator i; | |||
769 | unsigned type; | |||
770 | int r; | |||
771 | ||||
772 | BITMAP_FOREACH(type, types, i)for ((i).idx = 0; bitmap_iterate((types), &(i), (unsigned *)&(type)); ) { | |||
773 | if (dns_type_to_string(type)) { | |||
774 | r = strv_extend(&strv, dns_type_to_string(type)); | |||
775 | if (r < 0) | |||
776 | return NULL((void*)0); | |||
777 | } else { | |||
778 | char *t; | |||
779 | ||||
780 | r = asprintf(&t, "TYPE%u", type); | |||
781 | if (r < 0) | |||
782 | return NULL((void*)0); | |||
783 | ||||
784 | r = strv_consume(&strv, t); | |||
785 | if (r < 0) | |||
786 | return NULL((void*)0); | |||
787 | } | |||
788 | } | |||
789 | ||||
790 | str = strv_join(strv, " "); | |||
791 | if (!str) | |||
792 | return NULL((void*)0); | |||
793 | ||||
794 | return strjoin("( ", str, " )")strjoin_real(("( "), str, " )", ((void*)0)); | |||
795 | } | |||
796 | ||||
797 | static char *format_txt(DnsTxtItem *first) { | |||
798 | DnsTxtItem *i; | |||
799 | size_t c = 1; | |||
800 | char *p, *s; | |||
801 | ||||
802 | LIST_FOREACH(items, i, first)for ((i) = (first); (i); (i) = (i)->items_next) | |||
803 | c += i->length * 4 + 3; | |||
804 | ||||
805 | p = s = new(char, c)((char*) malloc_multiply(sizeof(char), (c))); | |||
806 | if (!s) | |||
807 | return NULL((void*)0); | |||
808 | ||||
809 | LIST_FOREACH(items, i, first)for ((i) = (first); (i); (i) = (i)->items_next) { | |||
810 | size_t j; | |||
811 | ||||
812 | if (i != first) | |||
813 | *(p++) = ' '; | |||
814 | ||||
815 | *(p++) = '"'; | |||
816 | ||||
817 | for (j = 0; j < i->length; j++) { | |||
818 | if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) { | |||
819 | *(p++) = '\\'; | |||
820 | *(p++) = '0' + (i->data[j] / 100); | |||
821 | *(p++) = '0' + ((i->data[j] / 10) % 10); | |||
822 | *(p++) = '0' + (i->data[j] % 10); | |||
823 | } else | |||
824 | *(p++) = i->data[j]; | |||
825 | } | |||
826 | ||||
827 | *(p++) = '"'; | |||
828 | } | |||
829 | ||||
830 | *p = 0; | |||
831 | return s; | |||
832 | } | |||
833 | ||||
834 | const char *dns_resource_record_to_string(DnsResourceRecord *rr) { | |||
835 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); | |||
836 | char *s, k[DNS_RESOURCE_KEY_STRING_MAX((sizeof "CLASS" + (2+(sizeof(uint16_t) <= 1 ? 3 : sizeof( uint16_t) <= 2 ? 5 : sizeof(uint16_t) <= 4 ? 10 : sizeof (uint16_t) <= 8 ? 20 : sizeof(int[-2*(sizeof(uint16_t) > 8)])))) + (sizeof "CLASS" + (2+(sizeof(uint16_t) <= 1 ? 3 : sizeof(uint16_t) <= 2 ? 5 : sizeof(uint16_t) <= 4 ? 10 : sizeof(uint16_t) <= 8 ? 20 : sizeof(int[-2*(sizeof(uint16_t ) > 8)])))) + 253 + 1)]; | |||
837 | int r; | |||
838 | ||||
839 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 839, __PRETTY_FUNCTION__); } while (0); | |||
840 | ||||
841 | if (rr->to_string) | |||
842 | return rr->to_string; | |||
843 | ||||
844 | dns_resource_key_to_string(rr->key, k, sizeof(k)); | |||
845 | ||||
846 | switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { | |||
847 | ||||
848 | case DNS_TYPE_SRV: | |||
849 | r = asprintf(&s, "%s %u %u %u %s", | |||
850 | k, | |||
851 | rr->srv.priority, | |||
852 | rr->srv.weight, | |||
853 | rr->srv.port, | |||
854 | strna(rr->srv.name)); | |||
855 | if (r < 0) | |||
856 | return NULL((void*)0); | |||
857 | break; | |||
858 | ||||
859 | case DNS_TYPE_PTR: | |||
860 | case DNS_TYPE_NS: | |||
861 | case DNS_TYPE_CNAME: | |||
862 | case DNS_TYPE_DNAME: | |||
863 | s = strjoin(k, " ", rr->ptr.name)strjoin_real((k), " ", rr->ptr.name, ((void*)0)); | |||
864 | if (!s) | |||
865 | return NULL((void*)0); | |||
866 | ||||
867 | break; | |||
868 | ||||
869 | case DNS_TYPE_HINFO: | |||
870 | s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os)strjoin_real((k), " ", rr->hinfo.cpu, " ", rr->hinfo.os , ((void*)0)); | |||
871 | if (!s) | |||
872 | return NULL((void*)0); | |||
873 | break; | |||
874 | ||||
875 | case DNS_TYPE_SPF: /* exactly the same as TXT */ | |||
876 | case DNS_TYPE_TXT: | |||
877 | t = format_txt(rr->txt.items); | |||
878 | if (!t) | |||
879 | return NULL((void*)0); | |||
880 | ||||
881 | s = strjoin(k, " ", t)strjoin_real((k), " ", t, ((void*)0)); | |||
882 | if (!s) | |||
883 | return NULL((void*)0); | |||
884 | break; | |||
885 | ||||
886 | case DNS_TYPE_A: { | |||
887 | _cleanup_free___attribute__((cleanup(freep))) char *x = NULL((void*)0); | |||
888 | ||||
889 | r = in_addr_to_string(AF_INET2, (const union in_addr_union*) &rr->a.in_addr, &x); | |||
890 | if (r < 0) | |||
891 | return NULL((void*)0); | |||
892 | ||||
893 | s = strjoin(k, " ", x)strjoin_real((k), " ", x, ((void*)0)); | |||
894 | if (!s) | |||
895 | return NULL((void*)0); | |||
896 | break; | |||
897 | } | |||
898 | ||||
899 | case DNS_TYPE_AAAA: | |||
900 | r = in_addr_to_string(AF_INET610, (const union in_addr_union*) &rr->aaaa.in6_addr, &t); | |||
901 | if (r < 0) | |||
902 | return NULL((void*)0); | |||
903 | ||||
904 | s = strjoin(k, " ", t)strjoin_real((k), " ", t, ((void*)0)); | |||
905 | if (!s) | |||
906 | return NULL((void*)0); | |||
907 | break; | |||
908 | ||||
909 | case DNS_TYPE_SOA: | |||
910 | r = asprintf(&s, "%s %s %s %u %u %u %u %u", | |||
911 | k, | |||
912 | strna(rr->soa.mname), | |||
913 | strna(rr->soa.rname), | |||
914 | rr->soa.serial, | |||
915 | rr->soa.refresh, | |||
916 | rr->soa.retry, | |||
917 | rr->soa.expire, | |||
918 | rr->soa.minimum); | |||
919 | if (r < 0) | |||
920 | return NULL((void*)0); | |||
921 | break; | |||
922 | ||||
923 | case DNS_TYPE_MX: | |||
924 | r = asprintf(&s, "%s %u %s", | |||
925 | k, | |||
926 | rr->mx.priority, | |||
927 | rr->mx.exchange); | |||
928 | if (r < 0) | |||
929 | return NULL((void*)0); | |||
930 | break; | |||
931 | ||||
932 | case DNS_TYPE_LOC: | |||
933 | assert(rr->loc.version == 0)do { if ((__builtin_expect(!!(!(rr->loc.version == 0)),0)) ) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("rr->loc.version == 0" ), "../src/resolve/resolved-dns-rr.c", 933, __PRETTY_FUNCTION__ ); } while (0); | |||
934 | ||||
935 | t = format_location(rr->loc.latitude, | |||
936 | rr->loc.longitude, | |||
937 | rr->loc.altitude, | |||
938 | rr->loc.size, | |||
939 | rr->loc.horiz_pre, | |||
940 | rr->loc.vert_pre); | |||
941 | if (!t) | |||
942 | return NULL((void*)0); | |||
943 | ||||
944 | s = strjoin(k, " ", t)strjoin_real((k), " ", t, ((void*)0)); | |||
945 | if (!s) | |||
946 | return NULL((void*)0); | |||
947 | break; | |||
948 | ||||
949 | case DNS_TYPE_DS: | |||
950 | t = hexmem(rr->ds.digest, rr->ds.digest_size); | |||
951 | if (!t) | |||
952 | return NULL((void*)0); | |||
953 | ||||
954 | r = asprintf(&s, "%s %u %u %u %s", | |||
955 | k, | |||
956 | rr->ds.key_tag, | |||
957 | rr->ds.algorithm, | |||
958 | rr->ds.digest_type, | |||
959 | t); | |||
960 | if (r < 0) | |||
961 | return NULL((void*)0); | |||
962 | break; | |||
963 | ||||
964 | case DNS_TYPE_SSHFP: | |||
965 | t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); | |||
966 | if (!t) | |||
967 | return NULL((void*)0); | |||
968 | ||||
969 | r = asprintf(&s, "%s %u %u %s", | |||
970 | k, | |||
971 | rr->sshfp.algorithm, | |||
972 | rr->sshfp.fptype, | |||
973 | t); | |||
974 | if (r < 0) | |||
975 | return NULL((void*)0); | |||
976 | break; | |||
977 | ||||
978 | case DNS_TYPE_DNSKEY: { | |||
979 | _cleanup_free___attribute__((cleanup(freep))) char *alg = NULL((void*)0); | |||
980 | char *ss; | |||
981 | int n; | |||
982 | uint16_t key_tag; | |||
983 | ||||
984 | key_tag = dnssec_keytag(rr, true1); | |||
985 | ||||
986 | r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg); | |||
987 | if (r < 0) | |||
988 | return NULL((void*)0); | |||
989 | ||||
990 | r = asprintf(&s, "%s %u %u %s %n", | |||
991 | k, | |||
992 | rr->dnskey.flags, | |||
993 | rr->dnskey.protocol, | |||
994 | alg, | |||
995 | &n); | |||
996 | if (r < 0) | |||
997 | return NULL((void*)0); | |||
998 | ||||
999 | r = base64_append(&s, n, | |||
1000 | rr->dnskey.key, rr->dnskey.key_size, | |||
1001 | 8, columns()); | |||
1002 | if (r < 0) | |||
1003 | return NULL((void*)0); | |||
1004 | ||||
1005 | r = asprintf(&ss, "%s\n" | |||
1006 | " -- Flags:%s%s%s\n" | |||
1007 | " -- Key tag: %u", | |||
1008 | s, | |||
1009 | rr->dnskey.flags & DNSKEY_FLAG_SEP(1 << 0) ? " SEP" : "", | |||
1010 | rr->dnskey.flags & DNSKEY_FLAG_REVOKE(1 << 7) ? " REVOKE" : "", | |||
1011 | rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY(1 << 8) ? " ZONE_KEY" : "", | |||
1012 | key_tag); | |||
1013 | if (r < 0) | |||
1014 | return NULL((void*)0); | |||
1015 | free(s); | |||
1016 | s = ss; | |||
1017 | ||||
1018 | break; | |||
1019 | } | |||
1020 | ||||
1021 | case DNS_TYPE_RRSIG: { | |||
1022 | _cleanup_free___attribute__((cleanup(freep))) char *alg = NULL((void*)0); | |||
1023 | char expiration[STRLEN("YYYYMMDDHHmmSS")(sizeof("""YYYYMMDDHHmmSS""") - 1) + 1], inception[STRLEN("YYYYMMDDHHmmSS")(sizeof("""YYYYMMDDHHmmSS""") - 1) + 1]; | |||
1024 | const char *type; | |||
1025 | int n; | |||
1026 | ||||
1027 | type = dns_type_to_string(rr->rrsig.type_covered); | |||
1028 | ||||
1029 | r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg); | |||
1030 | if (r < 0) | |||
1031 | return NULL((void*)0); | |||
1032 | ||||
1033 | r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration); | |||
1034 | if (r < 0) | |||
1035 | return NULL((void*)0); | |||
1036 | ||||
1037 | r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception); | |||
1038 | if (r < 0) | |||
1039 | return NULL((void*)0); | |||
1040 | ||||
1041 | /* TYPE?? follows | |||
1042 | * http://tools.ietf.org/html/rfc3597#section-5 */ | |||
1043 | ||||
1044 | r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n", | |||
1045 | k, | |||
1046 | type ?: "TYPE", | |||
1047 | type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered, | |||
1048 | alg, | |||
1049 | rr->rrsig.labels, | |||
1050 | rr->rrsig.original_ttl, | |||
1051 | expiration, | |||
1052 | inception, | |||
1053 | rr->rrsig.key_tag, | |||
1054 | rr->rrsig.signer, | |||
1055 | &n); | |||
1056 | if (r < 0) | |||
1057 | return NULL((void*)0); | |||
1058 | ||||
1059 | r = base64_append(&s, n, | |||
1060 | rr->rrsig.signature, rr->rrsig.signature_size, | |||
1061 | 8, columns()); | |||
1062 | if (r < 0) | |||
1063 | return NULL((void*)0); | |||
1064 | ||||
1065 | break; | |||
1066 | } | |||
1067 | ||||
1068 | case DNS_TYPE_NSEC: | |||
1069 | t = format_types(rr->nsec.types); | |||
1070 | if (!t) | |||
1071 | return NULL((void*)0); | |||
1072 | ||||
1073 | r = asprintf(&s, "%s %s %s", | |||
1074 | k, | |||
1075 | rr->nsec.next_domain_name, | |||
1076 | t); | |||
1077 | if (r < 0) | |||
1078 | return NULL((void*)0); | |||
1079 | break; | |||
1080 | ||||
1081 | case DNS_TYPE_NSEC3: { | |||
1082 | _cleanup_free___attribute__((cleanup(freep))) char *salt = NULL((void*)0), *hash = NULL((void*)0); | |||
1083 | ||||
1084 | if (rr->nsec3.salt_size > 0) { | |||
1085 | salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size); | |||
1086 | if (!salt) | |||
1087 | return NULL((void*)0); | |||
1088 | } | |||
1089 | ||||
1090 | hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false0); | |||
1091 | if (!hash) | |||
1092 | return NULL((void*)0); | |||
1093 | ||||
1094 | t = format_types(rr->nsec3.types); | |||
1095 | if (!t) | |||
1096 | return NULL((void*)0); | |||
1097 | ||||
1098 | r = asprintf(&s, "%s %"PRIu8"u"" %"PRIu8"u"" %"PRIu16"u"" %s %s %s", | |||
1099 | k, | |||
1100 | rr->nsec3.algorithm, | |||
1101 | rr->nsec3.flags, | |||
1102 | rr->nsec3.iterations, | |||
1103 | rr->nsec3.salt_size > 0 ? salt : "-", | |||
1104 | hash, | |||
1105 | t); | |||
1106 | if (r < 0) | |||
1107 | return NULL((void*)0); | |||
1108 | ||||
1109 | break; | |||
1110 | } | |||
1111 | ||||
1112 | case DNS_TYPE_TLSA: { | |||
1113 | const char *cert_usage, *selector, *matching_type; | |||
1114 | ||||
1115 | cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage); | |||
1116 | selector = tlsa_selector_to_string(rr->tlsa.selector); | |||
1117 | matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type); | |||
1118 | ||||
1119 | t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); | |||
1120 | if (!t) | |||
1121 | return NULL((void*)0); | |||
1122 | ||||
1123 | r = asprintf(&s, | |||
1124 | "%s %u %u %u %s\n" | |||
1125 | " -- Cert. usage: %s\n" | |||
1126 | " -- Selector: %s\n" | |||
1127 | " -- Matching type: %s", | |||
1128 | k, | |||
1129 | rr->tlsa.cert_usage, | |||
1130 | rr->tlsa.selector, | |||
1131 | rr->tlsa.matching_type, | |||
1132 | t, | |||
1133 | cert_usage, | |||
1134 | selector, | |||
1135 | matching_type); | |||
1136 | if (r < 0) | |||
1137 | return NULL((void*)0); | |||
1138 | ||||
1139 | break; | |||
1140 | } | |||
1141 | ||||
1142 | case DNS_TYPE_CAA: { | |||
1143 | _cleanup_free___attribute__((cleanup(freep))) char *value; | |||
1144 | ||||
1145 | value = octescape(rr->caa.value, rr->caa.value_size); | |||
1146 | if (!value) | |||
1147 | return NULL((void*)0); | |||
1148 | ||||
1149 | r = asprintf(&s, "%s %u %s \"%s\"%s%s%s%.0u", | |||
1150 | k, | |||
1151 | rr->caa.flags, | |||
1152 | rr->caa.tag, | |||
1153 | value, | |||
1154 | rr->caa.flags ? "\n -- Flags:" : "", | |||
1155 | rr->caa.flags & CAA_FLAG_CRITICAL(1u << 7) ? " critical" : "", | |||
1156 | rr->caa.flags & ~CAA_FLAG_CRITICAL(1u << 7) ? " " : "", | |||
1157 | rr->caa.flags & ~CAA_FLAG_CRITICAL(1u << 7)); | |||
1158 | if (r < 0) | |||
1159 | return NULL((void*)0); | |||
1160 | ||||
1161 | break; | |||
1162 | } | |||
1163 | ||||
1164 | case DNS_TYPE_OPENPGPKEY: { | |||
1165 | int n; | |||
1166 | ||||
1167 | r = asprintf(&s, "%s %n", | |||
1168 | k, | |||
1169 | &n); | |||
1170 | if (r < 0) | |||
1171 | return NULL((void*)0); | |||
1172 | ||||
1173 | r = base64_append(&s, n, | |||
1174 | rr->generic.data, rr->generic.data_size, | |||
1175 | 8, columns()); | |||
1176 | if (r < 0) | |||
1177 | return NULL((void*)0); | |||
1178 | break; | |||
1179 | } | |||
1180 | ||||
1181 | default: | |||
1182 | t = hexmem(rr->generic.data, rr->generic.data_size); | |||
1183 | if (!t) | |||
1184 | return NULL((void*)0); | |||
1185 | ||||
1186 | /* Format as documented in RFC 3597, Section 5 */ | |||
1187 | r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t); | |||
1188 | if (r < 0) | |||
1189 | return NULL((void*)0); | |||
1190 | break; | |||
1191 | } | |||
1192 | ||||
1193 | rr->to_string = s; | |||
1194 | return s; | |||
1195 | } | |||
1196 | ||||
1197 | ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) { | |||
1198 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1198, __PRETTY_FUNCTION__); } while (0); | |||
1199 | assert(out)do { if ((__builtin_expect(!!(!(out)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("out"), "../src/resolve/resolved-dns-rr.c" , 1199, __PRETTY_FUNCTION__); } while (0); | |||
1200 | ||||
1201 | switch(rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { | |||
1202 | case DNS_TYPE_SRV: | |||
1203 | case DNS_TYPE_PTR: | |||
1204 | case DNS_TYPE_NS: | |||
1205 | case DNS_TYPE_CNAME: | |||
1206 | case DNS_TYPE_DNAME: | |||
1207 | case DNS_TYPE_HINFO: | |||
1208 | case DNS_TYPE_SPF: | |||
1209 | case DNS_TYPE_TXT: | |||
1210 | case DNS_TYPE_A: | |||
1211 | case DNS_TYPE_AAAA: | |||
1212 | case DNS_TYPE_SOA: | |||
1213 | case DNS_TYPE_MX: | |||
1214 | case DNS_TYPE_LOC: | |||
1215 | case DNS_TYPE_DS: | |||
1216 | case DNS_TYPE_DNSKEY: | |||
1217 | case DNS_TYPE_RRSIG: | |||
1218 | case DNS_TYPE_NSEC: | |||
1219 | case DNS_TYPE_NSEC3: | |||
1220 | return -EINVAL22; | |||
1221 | ||||
1222 | case DNS_TYPE_SSHFP: | |||
1223 | *out = rr->sshfp.fingerprint; | |||
1224 | return rr->sshfp.fingerprint_size; | |||
1225 | ||||
1226 | case DNS_TYPE_TLSA: | |||
1227 | *out = rr->tlsa.data; | |||
1228 | return rr->tlsa.data_size; | |||
1229 | ||||
1230 | case DNS_TYPE_OPENPGPKEY: | |||
1231 | default: | |||
1232 | *out = rr->generic.data; | |||
1233 | return rr->generic.data_size; | |||
1234 | } | |||
1235 | } | |||
1236 | ||||
1237 | int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool_Bool canonical) { | |||
1238 | ||||
1239 | DnsPacket packet = { | |||
1240 | .n_ref = 1, | |||
1241 | .protocol = DNS_PROTOCOL_DNS, | |||
1242 | .on_stack = true1, | |||
1243 | .refuse_compression = true1, | |||
1244 | .canonical_form = canonical, | |||
1245 | }; | |||
1246 | ||||
1247 | size_t start, rds; | |||
1248 | int r; | |||
1249 | ||||
1250 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1250, __PRETTY_FUNCTION__); } while (0); | |||
1251 | ||||
1252 | /* Generates the RR in wire-format, optionally in the | |||
1253 | * canonical form as discussed in the DNSSEC RFC 4034, Section | |||
1254 | * 6.2. We allocate a throw-away DnsPacket object on the stack | |||
1255 | * here, because we need some book-keeping for memory | |||
1256 | * management, and can reuse the DnsPacket serializer, that | |||
1257 | * can generate the canonical form, too, but also knows label | |||
1258 | * compression and suchlike. */ | |||
1259 | ||||
1260 | if (rr->wire_format && rr->wire_format_canonical == canonical) | |||
1261 | return 0; | |||
1262 | ||||
1263 | r = dns_packet_append_rr(&packet, rr, 0, &start, &rds); | |||
1264 | if (r < 0) | |||
1265 | return r; | |||
1266 | ||||
1267 | assert(start == 0)do { if ((__builtin_expect(!!(!(start == 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("start == 0"), "../src/resolve/resolved-dns-rr.c" , 1267, __PRETTY_FUNCTION__); } while (0); | |||
1268 | assert(packet._data)do { if ((__builtin_expect(!!(!(packet._data)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("packet._data"), "../src/resolve/resolved-dns-rr.c" , 1268, __PRETTY_FUNCTION__); } while (0); | |||
1269 | ||||
1270 | free(rr->wire_format); | |||
1271 | rr->wire_format = packet._data; | |||
1272 | rr->wire_format_size = packet.size; | |||
1273 | rr->wire_format_rdata_offset = rds; | |||
1274 | rr->wire_format_canonical = canonical; | |||
1275 | ||||
1276 | packet._data = NULL((void*)0); | |||
1277 | dns_packet_unref(&packet); | |||
1278 | ||||
1279 | return 0; | |||
1280 | } | |||
1281 | ||||
1282 | int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) { | |||
1283 | const char *n; | |||
1284 | int r; | |||
1285 | ||||
1286 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1286, __PRETTY_FUNCTION__); } while (0); | |||
1287 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-rr.c" , 1287, __PRETTY_FUNCTION__); } while (0); | |||
1288 | ||||
1289 | /* Returns the RRset's signer, if it is known. */ | |||
1290 | ||||
1291 | if (rr->n_skip_labels_signer == (unsigned) -1) | |||
1292 | return -ENODATA61; | |||
1293 | ||||
1294 | n = dns_resource_key_name(rr->key); | |||
1295 | r = dns_name_skip(n, rr->n_skip_labels_signer, &n); | |||
1296 | if (r < 0) | |||
1297 | return r; | |||
1298 | if (r == 0) | |||
1299 | return -EINVAL22; | |||
1300 | ||||
1301 | *ret = n; | |||
1302 | return 0; | |||
1303 | } | |||
1304 | ||||
1305 | int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) { | |||
1306 | const char *n; | |||
1307 | int r; | |||
1308 | ||||
1309 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1309, __PRETTY_FUNCTION__); } while (0); | |||
1310 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/resolve/resolved-dns-rr.c" , 1310, __PRETTY_FUNCTION__); } while (0); | |||
1311 | ||||
1312 | /* Returns the RRset's synthesizing source, if it is known. */ | |||
1313 | ||||
1314 | if (rr->n_skip_labels_source == (unsigned) -1) | |||
1315 | return -ENODATA61; | |||
1316 | ||||
1317 | n = dns_resource_key_name(rr->key); | |||
1318 | r = dns_name_skip(n, rr->n_skip_labels_source, &n); | |||
1319 | if (r < 0) | |||
1320 | return r; | |||
1321 | if (r == 0) | |||
1322 | return -EINVAL22; | |||
1323 | ||||
1324 | *ret = n; | |||
1325 | return 0; | |||
1326 | } | |||
1327 | ||||
1328 | int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) { | |||
1329 | const char *signer; | |||
1330 | int r; | |||
1331 | ||||
1332 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1332, __PRETTY_FUNCTION__); } while (0); | |||
1333 | ||||
1334 | r = dns_resource_record_signer(rr, &signer); | |||
1335 | if (r < 0) | |||
1336 | return r; | |||
1337 | ||||
1338 | return dns_name_equal(zone, signer); | |||
1339 | } | |||
1340 | ||||
1341 | int dns_resource_record_is_synthetic(DnsResourceRecord *rr) { | |||
1342 | int r; | |||
1343 | ||||
1344 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1344, __PRETTY_FUNCTION__); } while (0); | |||
1345 | ||||
1346 | /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */ | |||
1347 | ||||
1348 | if (rr->n_skip_labels_source == (unsigned) -1) | |||
1349 | return -ENODATA61; | |||
1350 | ||||
1351 | if (rr->n_skip_labels_source == 0) | |||
1352 | return 0; | |||
1353 | ||||
1354 | if (rr->n_skip_labels_source > 1) | |||
1355 | return 1; | |||
1356 | ||||
1357 | r = dns_name_startswith(dns_resource_key_name(rr->key), "*"); | |||
1358 | if (r < 0) | |||
1359 | return r; | |||
1360 | ||||
1361 | return !r; | |||
1362 | } | |||
1363 | ||||
1364 | void dns_resource_record_hash_func(const void *i, struct siphash *state) { | |||
1365 | const DnsResourceRecord *rr = i; | |||
1366 | ||||
1367 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1367, __PRETTY_FUNCTION__); } while (0); | |||
1368 | ||||
1369 | dns_resource_key_hash_func(rr->key, state); | |||
1370 | ||||
1371 | switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { | |||
1372 | ||||
1373 | case DNS_TYPE_SRV: | |||
1374 | siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state); | |||
1375 | siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state); | |||
1376 | siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state); | |||
1377 | dns_name_hash_func(rr->srv.name, state); | |||
1378 | break; | |||
1379 | ||||
1380 | case DNS_TYPE_PTR: | |||
1381 | case DNS_TYPE_NS: | |||
1382 | case DNS_TYPE_CNAME: | |||
1383 | case DNS_TYPE_DNAME: | |||
1384 | dns_name_hash_func(rr->ptr.name, state); | |||
1385 | break; | |||
1386 | ||||
1387 | case DNS_TYPE_HINFO: | |||
1388 | string_hash_func(rr->hinfo.cpu, state); | |||
1389 | string_hash_func(rr->hinfo.os, state); | |||
1390 | break; | |||
1391 | ||||
1392 | case DNS_TYPE_TXT: | |||
1393 | case DNS_TYPE_SPF: { | |||
1394 | DnsTxtItem *j; | |||
1395 | ||||
1396 | LIST_FOREACH(items, j, rr->txt.items)for ((j) = (rr->txt.items); (j); (j) = (j)->items_next) { | |||
1397 | siphash24_compress(j->data, j->length, state); | |||
1398 | ||||
1399 | /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab" | |||
1400 | * followed by "". */ | |||
1401 | siphash24_compress_byte(0, state)siphash24_compress((const uint8_t[]) { (0) }, 1, (state)); | |||
1402 | } | |||
1403 | break; | |||
1404 | } | |||
1405 | ||||
1406 | case DNS_TYPE_A: | |||
1407 | siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state); | |||
1408 | break; | |||
1409 | ||||
1410 | case DNS_TYPE_AAAA: | |||
1411 | siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state); | |||
1412 | break; | |||
1413 | ||||
1414 | case DNS_TYPE_SOA: | |||
1415 | dns_name_hash_func(rr->soa.mname, state); | |||
1416 | dns_name_hash_func(rr->soa.rname, state); | |||
1417 | siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state); | |||
1418 | siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state); | |||
1419 | siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state); | |||
1420 | siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state); | |||
1421 | siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state); | |||
1422 | break; | |||
1423 | ||||
1424 | case DNS_TYPE_MX: | |||
1425 | siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state); | |||
1426 | dns_name_hash_func(rr->mx.exchange, state); | |||
1427 | break; | |||
1428 | ||||
1429 | case DNS_TYPE_LOC: | |||
1430 | siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state); | |||
1431 | siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state); | |||
1432 | siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state); | |||
1433 | siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state); | |||
1434 | siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state); | |||
1435 | siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state); | |||
1436 | siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state); | |||
1437 | break; | |||
1438 | ||||
1439 | case DNS_TYPE_SSHFP: | |||
1440 | siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state); | |||
1441 | siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state); | |||
1442 | siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state); | |||
1443 | break; | |||
1444 | ||||
1445 | case DNS_TYPE_DNSKEY: | |||
1446 | siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state); | |||
1447 | siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state); | |||
1448 | siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state); | |||
1449 | siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state); | |||
1450 | break; | |||
1451 | ||||
1452 | case DNS_TYPE_RRSIG: | |||
1453 | siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state); | |||
1454 | siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state); | |||
1455 | siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state); | |||
1456 | siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state); | |||
1457 | siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state); | |||
1458 | siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state); | |||
1459 | siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state); | |||
1460 | dns_name_hash_func(rr->rrsig.signer, state); | |||
1461 | siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state); | |||
1462 | break; | |||
1463 | ||||
1464 | case DNS_TYPE_NSEC: | |||
1465 | dns_name_hash_func(rr->nsec.next_domain_name, state); | |||
1466 | /* FIXME: we leave out the type bitmap here. Hash | |||
1467 | * would be better if we'd take it into account | |||
1468 | * too. */ | |||
1469 | break; | |||
1470 | ||||
1471 | case DNS_TYPE_DS: | |||
1472 | siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state); | |||
1473 | siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state); | |||
1474 | siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state); | |||
1475 | siphash24_compress(rr->ds.digest, rr->ds.digest_size, state); | |||
1476 | break; | |||
1477 | ||||
1478 | case DNS_TYPE_NSEC3: | |||
1479 | siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state); | |||
1480 | siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state); | |||
1481 | siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state); | |||
1482 | siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state); | |||
1483 | siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state); | |||
1484 | /* FIXME: We leave the bitmaps out */ | |||
1485 | break; | |||
1486 | ||||
1487 | case DNS_TYPE_TLSA: | |||
1488 | siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state); | |||
1489 | siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state); | |||
1490 | siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state); | |||
1491 | siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state); | |||
1492 | break; | |||
1493 | ||||
1494 | case DNS_TYPE_CAA: | |||
1495 | siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state); | |||
1496 | string_hash_func(rr->caa.tag, state); | |||
1497 | siphash24_compress(rr->caa.value, rr->caa.value_size, state); | |||
1498 | break; | |||
1499 | ||||
1500 | case DNS_TYPE_OPENPGPKEY: | |||
1501 | default: | |||
1502 | siphash24_compress(rr->generic.data, rr->generic.data_size, state); | |||
1503 | break; | |||
1504 | } | |||
1505 | } | |||
1506 | ||||
1507 | static int dns_resource_record_compare_func(const void *a, const void *b) { | |||
1508 | const DnsResourceRecord *x = a, *y = b; | |||
1509 | int ret; | |||
1510 | ||||
1511 | ret = dns_resource_key_compare_func(x->key, y->key); | |||
1512 | if (ret != 0) | |||
1513 | return ret; | |||
1514 | ||||
1515 | if (dns_resource_record_equal(x, y)) | |||
1516 | return 0; | |||
1517 | ||||
1518 | /* This is a bit dirty, we don't implement proper ordering, but | |||
1519 | * the hashtable doesn't need ordering anyway, hence we don't | |||
1520 | * care. */ | |||
1521 | return x < y ? -1 : 1; | |||
1522 | } | |||
1523 | ||||
1524 | const struct hash_ops dns_resource_record_hash_ops = { | |||
1525 | .hash = dns_resource_record_hash_func, | |||
1526 | .compare = dns_resource_record_compare_func, | |||
1527 | }; | |||
1528 | ||||
1529 | DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) { | |||
1530 | _cleanup_(dns_resource_record_unrefp)__attribute__((cleanup(dns_resource_record_unrefp))) DnsResourceRecord *copy = NULL((void*)0); | |||
1531 | DnsResourceRecord *t; | |||
1532 | ||||
1533 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1533, __PRETTY_FUNCTION__); } while (0); | |||
1534 | ||||
1535 | copy = dns_resource_record_new(rr->key); | |||
1536 | if (!copy) | |||
1537 | return NULL((void*)0); | |||
1538 | ||||
1539 | copy->ttl = rr->ttl; | |||
1540 | copy->expiry = rr->expiry; | |||
1541 | copy->n_skip_labels_signer = rr->n_skip_labels_signer; | |||
1542 | copy->n_skip_labels_source = rr->n_skip_labels_source; | |||
1543 | copy->unparseable = rr->unparseable; | |||
1544 | ||||
1545 | switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) { | |||
1546 | ||||
1547 | case DNS_TYPE_SRV: | |||
1548 | copy->srv.priority = rr->srv.priority; | |||
1549 | copy->srv.weight = rr->srv.weight; | |||
1550 | copy->srv.port = rr->srv.port; | |||
1551 | copy->srv.name = strdup(rr->srv.name); | |||
1552 | if (!copy->srv.name) | |||
1553 | return NULL((void*)0); | |||
1554 | break; | |||
1555 | ||||
1556 | case DNS_TYPE_PTR: | |||
1557 | case DNS_TYPE_NS: | |||
1558 | case DNS_TYPE_CNAME: | |||
1559 | case DNS_TYPE_DNAME: | |||
1560 | copy->ptr.name = strdup(rr->ptr.name); | |||
1561 | if (!copy->ptr.name) | |||
1562 | return NULL((void*)0); | |||
1563 | break; | |||
1564 | ||||
1565 | case DNS_TYPE_HINFO: | |||
1566 | copy->hinfo.cpu = strdup(rr->hinfo.cpu); | |||
1567 | if (!copy->hinfo.cpu) | |||
1568 | return NULL((void*)0); | |||
1569 | ||||
1570 | copy->hinfo.os = strdup(rr->hinfo.os); | |||
1571 | if (!copy->hinfo.os) | |||
1572 | return NULL((void*)0); | |||
1573 | break; | |||
1574 | ||||
1575 | case DNS_TYPE_TXT: | |||
1576 | case DNS_TYPE_SPF: | |||
1577 | copy->txt.items = dns_txt_item_copy(rr->txt.items); | |||
1578 | if (!copy->txt.items) | |||
1579 | return NULL((void*)0); | |||
1580 | break; | |||
1581 | ||||
1582 | case DNS_TYPE_A: | |||
1583 | copy->a = rr->a; | |||
1584 | break; | |||
1585 | ||||
1586 | case DNS_TYPE_AAAA: | |||
1587 | copy->aaaa = rr->aaaa; | |||
1588 | break; | |||
1589 | ||||
1590 | case DNS_TYPE_SOA: | |||
1591 | copy->soa.mname = strdup(rr->soa.mname); | |||
1592 | if (!copy->soa.mname) | |||
1593 | return NULL((void*)0); | |||
1594 | copy->soa.rname = strdup(rr->soa.rname); | |||
1595 | if (!copy->soa.rname) | |||
1596 | return NULL((void*)0); | |||
1597 | copy->soa.serial = rr->soa.serial; | |||
1598 | copy->soa.refresh = rr->soa.refresh; | |||
1599 | copy->soa.retry = rr->soa.retry; | |||
1600 | copy->soa.expire = rr->soa.expire; | |||
1601 | copy->soa.minimum = rr->soa.minimum; | |||
1602 | break; | |||
1603 | ||||
1604 | case DNS_TYPE_MX: | |||
1605 | copy->mx.priority = rr->mx.priority; | |||
1606 | copy->mx.exchange = strdup(rr->mx.exchange); | |||
1607 | if (!copy->mx.exchange) | |||
1608 | return NULL((void*)0); | |||
1609 | break; | |||
1610 | ||||
1611 | case DNS_TYPE_LOC: | |||
1612 | copy->loc = rr->loc; | |||
1613 | break; | |||
1614 | ||||
1615 | case DNS_TYPE_SSHFP: | |||
1616 | copy->sshfp.algorithm = rr->sshfp.algorithm; | |||
1617 | copy->sshfp.fptype = rr->sshfp.fptype; | |||
1618 | copy->sshfp.fingerprint = memdup(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size); | |||
1619 | if (!copy->sshfp.fingerprint) | |||
1620 | return NULL((void*)0); | |||
1621 | copy->sshfp.fingerprint_size = rr->sshfp.fingerprint_size; | |||
1622 | break; | |||
1623 | ||||
1624 | case DNS_TYPE_DNSKEY: | |||
1625 | copy->dnskey.flags = rr->dnskey.flags; | |||
1626 | copy->dnskey.protocol = rr->dnskey.protocol; | |||
1627 | copy->dnskey.algorithm = rr->dnskey.algorithm; | |||
1628 | copy->dnskey.key = memdup(rr->dnskey.key, rr->dnskey.key_size); | |||
1629 | if (!copy->dnskey.key) | |||
1630 | return NULL((void*)0); | |||
1631 | copy->dnskey.key_size = rr->dnskey.key_size; | |||
1632 | break; | |||
1633 | ||||
1634 | case DNS_TYPE_RRSIG: | |||
1635 | copy->rrsig.type_covered = rr->rrsig.type_covered; | |||
1636 | copy->rrsig.algorithm = rr->rrsig.algorithm; | |||
1637 | copy->rrsig.labels = rr->rrsig.labels; | |||
1638 | copy->rrsig.original_ttl = rr->rrsig.original_ttl; | |||
1639 | copy->rrsig.expiration = rr->rrsig.expiration; | |||
1640 | copy->rrsig.inception = rr->rrsig.inception; | |||
1641 | copy->rrsig.key_tag = rr->rrsig.key_tag; | |||
1642 | copy->rrsig.signer = strdup(rr->rrsig.signer); | |||
1643 | if (!copy->rrsig.signer) | |||
1644 | return NULL((void*)0); | |||
1645 | copy->rrsig.signature = memdup(rr->rrsig.signature, rr->rrsig.signature_size); | |||
1646 | if (!copy->rrsig.signature) | |||
1647 | return NULL((void*)0); | |||
1648 | copy->rrsig.signature_size = rr->rrsig.signature_size; | |||
1649 | break; | |||
1650 | ||||
1651 | case DNS_TYPE_NSEC: | |||
1652 | copy->nsec.next_domain_name = strdup(rr->nsec.next_domain_name); | |||
1653 | if (!copy->nsec.next_domain_name) | |||
1654 | return NULL((void*)0); | |||
1655 | copy->nsec.types = bitmap_copy(rr->nsec.types); | |||
1656 | if (!copy->nsec.types) | |||
1657 | return NULL((void*)0); | |||
1658 | break; | |||
1659 | ||||
1660 | case DNS_TYPE_DS: | |||
1661 | copy->ds.key_tag = rr->ds.key_tag; | |||
1662 | copy->ds.algorithm = rr->ds.algorithm; | |||
1663 | copy->ds.digest_type = rr->ds.digest_type; | |||
1664 | copy->ds.digest = memdup(rr->ds.digest, rr->ds.digest_size); | |||
1665 | if (!copy->ds.digest) | |||
1666 | return NULL((void*)0); | |||
1667 | copy->ds.digest_size = rr->ds.digest_size; | |||
1668 | break; | |||
1669 | ||||
1670 | case DNS_TYPE_NSEC3: | |||
1671 | copy->nsec3.algorithm = rr->nsec3.algorithm; | |||
1672 | copy->nsec3.flags = rr->nsec3.flags; | |||
1673 | copy->nsec3.iterations = rr->nsec3.iterations; | |||
1674 | copy->nsec3.salt = memdup(rr->nsec3.salt, rr->nsec3.salt_size); | |||
1675 | if (!copy->nsec3.salt) | |||
1676 | return NULL((void*)0); | |||
1677 | copy->nsec3.salt_size = rr->nsec3.salt_size; | |||
1678 | copy->nsec3.next_hashed_name = memdup(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size); | |||
1679 | if (!copy->nsec3.next_hashed_name_size) | |||
1680 | return NULL((void*)0); | |||
1681 | copy->nsec3.next_hashed_name_size = rr->nsec3.next_hashed_name_size; | |||
1682 | copy->nsec3.types = bitmap_copy(rr->nsec3.types); | |||
1683 | if (!copy->nsec3.types) | |||
1684 | return NULL((void*)0); | |||
1685 | break; | |||
1686 | ||||
1687 | case DNS_TYPE_TLSA: | |||
1688 | copy->tlsa.cert_usage = rr->tlsa.cert_usage; | |||
1689 | copy->tlsa.selector = rr->tlsa.selector; | |||
1690 | copy->tlsa.matching_type = rr->tlsa.matching_type; | |||
1691 | copy->tlsa.data = memdup(rr->tlsa.data, rr->tlsa.data_size); | |||
1692 | if (!copy->tlsa.data) | |||
1693 | return NULL((void*)0); | |||
1694 | copy->tlsa.data_size = rr->tlsa.data_size; | |||
1695 | break; | |||
1696 | ||||
1697 | case DNS_TYPE_CAA: | |||
1698 | copy->caa.flags = rr->caa.flags; | |||
1699 | copy->caa.tag = strdup(rr->caa.tag); | |||
1700 | if (!copy->caa.tag) | |||
1701 | return NULL((void*)0); | |||
1702 | copy->caa.value = memdup(rr->caa.value, rr->caa.value_size); | |||
1703 | if (!copy->caa.value) | |||
1704 | return NULL((void*)0); | |||
1705 | copy->caa.value_size = rr->caa.value_size; | |||
1706 | break; | |||
1707 | ||||
1708 | case DNS_TYPE_OPT: | |||
1709 | default: | |||
1710 | copy->generic.data = memdup(rr->generic.data, rr->generic.data_size); | |||
1711 | if (!copy->generic.data) | |||
1712 | return NULL((void*)0); | |||
1713 | copy->generic.data_size = rr->generic.data_size; | |||
1714 | break; | |||
1715 | } | |||
1716 | ||||
1717 | t = TAKE_PTR(copy)({ typeof(copy) _ptr_ = (copy); (copy) = ((void*)0); _ptr_; } ); | |||
1718 | ||||
1719 | return t; | |||
1720 | } | |||
1721 | ||||
1722 | int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) { | |||
1723 | DnsResourceRecord *old_rr, *new_rr; | |||
1724 | uint32_t new_ttl; | |||
1725 | ||||
1726 | assert(rr)do { if ((__builtin_expect(!!(!(rr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rr"), "../src/resolve/resolved-dns-rr.c" , 1726, __PRETTY_FUNCTION__); } while (0); | |||
1727 | old_rr = *rr; | |||
1728 | ||||
1729 | if (old_rr->key->type == DNS_TYPE_OPT) | |||
1730 | return -EINVAL22; | |||
1731 | ||||
1732 | new_ttl = MIN(old_rr->ttl, max_ttl)__extension__ ({ const typeof((old_rr->ttl)) __unique_prefix_A17 = ((old_rr->ttl)); const typeof((max_ttl)) __unique_prefix_B18 = ((max_ttl)); __unique_prefix_A17 < __unique_prefix_B18 ? __unique_prefix_A17 : __unique_prefix_B18; }); | |||
1733 | if (new_ttl == old_rr->ttl) | |||
1734 | return 0; | |||
1735 | ||||
1736 | if (old_rr->n_ref == 1) { | |||
1737 | /* Patch in place */ | |||
1738 | old_rr->ttl = new_ttl; | |||
1739 | return 1; | |||
1740 | } | |||
1741 | ||||
1742 | new_rr = dns_resource_record_copy(old_rr); | |||
1743 | if (!new_rr) | |||
1744 | return -ENOMEM12; | |||
1745 | ||||
1746 | new_rr->ttl = new_ttl; | |||
1747 | ||||
1748 | dns_resource_record_unref(*rr); | |||
1749 | *rr = new_rr; | |||
1750 | ||||
1751 | return 1; | |||
1752 | } | |||
1753 | ||||
1754 | DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) { | |||
1755 | DnsTxtItem *n; | |||
1756 | ||||
1757 | if (!i) | |||
1758 | return NULL((void*)0); | |||
1759 | ||||
1760 | n = i->items_next; | |||
1761 | ||||
1762 | free(i); | |||
1763 | return dns_txt_item_free_all(n); | |||
1764 | } | |||
1765 | ||||
1766 | bool_Bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) { | |||
1767 | ||||
1768 | if (a == b) | |||
1769 | return true1; | |||
1770 | ||||
1771 | if (!a != !b) | |||
1772 | return false0; | |||
1773 | ||||
1774 | if (!a) | |||
1775 | return true1; | |||
1776 | ||||
1777 | if (a->length != b->length) | |||
1778 | return false0; | |||
1779 | ||||
1780 | if (memcmp(a->data, b->data, a->length) != 0) | |||
1781 | return false0; | |||
1782 | ||||
1783 | return dns_txt_item_equal(a->items_next, b->items_next); | |||
1784 | } | |||
1785 | ||||
1786 | DnsTxtItem *dns_txt_item_copy(DnsTxtItem *first) { | |||
1787 | DnsTxtItem *i, *copy = NULL((void*)0), *end = NULL((void*)0); | |||
1788 | ||||
1789 | LIST_FOREACH(items, i, first)for ((i) = (first); (i); (i) = (i)->items_next) { | |||
1790 | DnsTxtItem *j; | |||
1791 | ||||
1792 | j = memdup(i, offsetof(DnsTxtItem, data)__builtin_offsetof(DnsTxtItem, data) + i->length + 1); | |||
1793 | if (!j) { | |||
1794 | dns_txt_item_free_all(copy); | |||
1795 | return NULL((void*)0); | |||
1796 | } | |||
1797 | ||||
1798 | LIST_INSERT_AFTER(items, copy, end, j)do { typeof(*(copy)) **_head = &(copy), *_a = (end), *_b = (j); do { if ((__builtin_expect(!!(!(_b)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_b"), "../src/resolve/resolved-dns-rr.c" , 1798, __PRETTY_FUNCTION__); } while (0); if (!_a) { if ((_b ->items_next = *_head)) _b->items_next->items_prev = _b; _b->items_prev = ((void*)0); *_head = _b; } else { if ((_b->items_next = _a->items_next)) _b->items_next-> items_prev = _b; _b->items_prev = _a; _a->items_next = _b ; } } while (0); | |||
1799 | end = j; | |||
1800 | } | |||
1801 | ||||
1802 | return copy; | |||
1803 | } | |||
1804 | ||||
1805 | int dns_txt_item_new_empty(DnsTxtItem **ret) { | |||
1806 | DnsTxtItem *i; | |||
1807 | ||||
1808 | /* RFC 6763, section 6.1 suggests to treat | |||
1809 | * empty TXT RRs as equivalent to a TXT record | |||
1810 | * with a single empty string. */ | |||
1811 | ||||
1812 | i = malloc0(offsetof(DnsTxtItem, data) + 1)(calloc(1, (__builtin_offsetof(DnsTxtItem, data) + 1))); /* for safety reasons we add an extra NUL byte */ | |||
1813 | if (!i) | |||
1814 | return -ENOMEM12; | |||
1815 | ||||
1816 | *ret = i; | |||
1817 | ||||
1818 | return 0; | |||
1819 | } | |||
1820 | ||||
1821 | static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = { | |||
1822 | /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */ | |||
1823 | [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5", | |||
1824 | [DNSSEC_ALGORITHM_DH] = "DH", | |||
1825 | [DNSSEC_ALGORITHM_DSA] = "DSA", | |||
1826 | [DNSSEC_ALGORITHM_ECC] = "ECC", | |||
1827 | [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1", | |||
1828 | [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1", | |||
1829 | [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1", | |||
1830 | [DNSSEC_ALGORITHM_RSASHA256] = "RSASHA256", | |||
1831 | [DNSSEC_ALGORITHM_RSASHA512] = "RSASHA512", | |||
1832 | [DNSSEC_ALGORITHM_ECC_GOST] = "ECC-GOST", | |||
1833 | [DNSSEC_ALGORITHM_ECDSAP256SHA256] = "ECDSAP256SHA256", | |||
1834 | [DNSSEC_ALGORITHM_ECDSAP384SHA384] = "ECDSAP384SHA384", | |||
1835 | [DNSSEC_ALGORITHM_ED25519] = "ED25519", | |||
1836 | [DNSSEC_ALGORITHM_ED448] = "ED448", | |||
1837 | [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT", | |||
1838 | [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS", | |||
1839 | [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID", | |||
1840 | }; | |||
1841 | DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255)int dnssec_algorithm_to_string_alloc(int i, char **str) { char *s; if (i < 0 || i > 255) return -34; if (i < (int) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(dnssec_algorithm_table), typeof(&*(dnssec_algorithm_table ))), sizeof(dnssec_algorithm_table)/sizeof((dnssec_algorithm_table )[0]), ((void)0)))) { s = strdup(dnssec_algorithm_table[i]); if (!s) return -12; } else { if (asprintf(&s, "%i", i) < 0) return -12; } *str = s; return 0; } int dnssec_algorithm_from_string (const char *s) { int i; unsigned u = 0; if (!s) return (int) -1; for (i = 0; i < (int) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(dnssec_algorithm_table ), typeof(&*(dnssec_algorithm_table))), sizeof(dnssec_algorithm_table )/sizeof((dnssec_algorithm_table)[0]), ((void)0))); i++) if ( streq_ptr(dnssec_algorithm_table[i], s)) return i; if (safe_atou (s, &u) >= 0 && u <= 255) return (int) u; return (int) -1; }; | |||
1842 | ||||
1843 | static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = { | |||
1844 | /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */ | |||
1845 | [DNSSEC_DIGEST_SHA1] = "SHA-1", | |||
1846 | [DNSSEC_DIGEST_SHA256] = "SHA-256", | |||
1847 | [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94", | |||
1848 | [DNSSEC_DIGEST_SHA384] = "SHA-384", | |||
1849 | }; | |||
1850 | DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255)int dnssec_digest_to_string_alloc(int i, char **str) { char * s; if (i < 0 || i > 255) return -34; if (i < (int) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (dnssec_digest_table), typeof(&*(dnssec_digest_table))), sizeof (dnssec_digest_table)/sizeof((dnssec_digest_table)[0]), ((void )0)))) { s = strdup(dnssec_digest_table[i]); if (!s) return - 12; } else { if (asprintf(&s, "%i", i) < 0) return -12 ; } *str = s; return 0; } int dnssec_digest_from_string(const char *s) { int i; unsigned u = 0; if (!s) return (int) -1; for (i = 0; i < (int) __extension__ (__builtin_choose_expr( ! __builtin_types_compatible_p(typeof(dnssec_digest_table), typeof (&*(dnssec_digest_table))), sizeof(dnssec_digest_table)/sizeof ((dnssec_digest_table)[0]), ((void)0))); i++) if (streq_ptr(dnssec_digest_table [i], s)) return i; if (safe_atou(s, &u) >= 0 && u <= 255) return (int) u; return (int) -1; }; |