File: | build-scan/../src/resolve/resolved-dns-rr.c |
Warning: | line 815, column 24 Use of zero-allocated memory |
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
| ||||
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_A21 = ((old_rr->ttl)); const typeof((max_ttl)) __unique_prefix_B22 = ((max_ttl)); __unique_prefix_A21 < __unique_prefix_B22 ? __unique_prefix_A21 : __unique_prefix_B22; }); | ||||
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; }; |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | #pragma once |
3 | |
4 | #include <alloca.h> |
5 | #include <stddef.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | |
9 | #include "macro.h" |
10 | |
11 | #define new(t, n)((t*) malloc_multiply(sizeof(t), (n))) ((t*) malloc_multiply(sizeof(t), (n))) |
12 | |
13 | #define new0(t, n)((t*) calloc((n), sizeof(t))) ((t*) calloc((n), sizeof(t))) |
14 | |
15 | #define newa(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 15, __PRETTY_FUNCTION__); } while (0); (t*) __builtin_alloca (sizeof(t)*(n)); }) \ |
16 | ({ \ |
17 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 17, __PRETTY_FUNCTION__); } while (0); \ |
18 | (t*) alloca(sizeof(t)*(n))__builtin_alloca (sizeof(t)*(n)); \ |
19 | }) |
20 | |
21 | #define newa0(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 21, __PRETTY_FUNCTION__); } while (0); (t*) ({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_) ; }); }) \ |
22 | ({ \ |
23 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 23, __PRETTY_FUNCTION__); } while (0); \ |
24 | (t*) alloca0(sizeof(t)*(n))({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_); }); \ |
25 | }) |
26 | |
27 | #define newdup(t, p, n)((t*) memdup_multiply(p, sizeof(t), (n))) ((t*) memdup_multiply(p, sizeof(t), (n))) |
28 | |
29 | #define newdup_suffix0(t, p, n)((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) |
30 | |
31 | #define malloc0(n)(calloc(1, (n))) (calloc(1, (n))) |
32 | |
33 | static inline void *mfree(void *memory) { |
34 | free(memory); |
35 | return NULL((void*)0); |
36 | } |
37 | |
38 | #define free_and_replace(a, b)({ free(a); (a) = (b); (b) = ((void*)0); 0; }) \ |
39 | ({ \ |
40 | free(a); \ |
41 | (a) = (b); \ |
42 | (b) = NULL((void*)0); \ |
43 | 0; \ |
44 | }) |
45 | |
46 | void* memdup(const void *p, size_t l) _alloc_(2); |
47 | void* memdup_suffix0(const void *p, size_t l) _alloc_(2); |
48 | |
49 | static inline void freep(void *p) { |
50 | free(*(void**) p); |
51 | } |
52 | |
53 | #define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep))) |
54 | |
55 | static inline bool_Bool size_multiply_overflow(size_t size, size_t need) { |
56 | return _unlikely_(need != 0 && size > (SIZE_MAX / need))(__builtin_expect(!!(need != 0 && size > ((18446744073709551615UL ) / need)),0)); |
57 | } |
58 | |
59 | _malloc___attribute__ ((malloc)) _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) { |
60 | if (size_multiply_overflow(size, need)) |
61 | return NULL((void*)0); |
62 | |
63 | return malloc(size * need); |
64 | } |
65 | |
66 | #if !HAVE_REALLOCARRAY1 |
67 | _alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { |
68 | if (size_multiply_overflow(size, need)) |
69 | return NULL((void*)0); |
70 | |
71 | return realloc(p, size * need); |
72 | } |
73 | #endif |
74 | |
75 | _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { |
76 | if (size_multiply_overflow(size, need)) |
77 | return NULL((void*)0); |
78 | |
79 | return memdup(p, size * need); |
80 | } |
81 | |
82 | _alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) { |
83 | if (size_multiply_overflow(size, need)) |
84 | return NULL((void*)0); |
85 | |
86 | return memdup_suffix0(p, size * need); |
87 | } |
88 | |
89 | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); |
90 | void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); |
91 | |
92 | #define GREEDY_REALLOC(array, allocated, need)greedy_realloc((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
93 | greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
94 | |
95 | #define GREEDY_REALLOC0(array, allocated, need)greedy_realloc0((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
96 | greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
97 | |
98 | #define alloca0(n)({ char *_new_; size_t _len_ = n; _new_ = __builtin_alloca (_len_ ); (void *) memset(_new_, 0, _len_); }) \ |
99 | ({ \ |
100 | char *_new_; \ |
101 | size_t _len_ = n; \ |
102 | _new_ = alloca(_len_)__builtin_alloca (_len_); \ |
103 | (void *) memset(_new_, 0, _len_); \ |
104 | }) |
105 | |
106 | /* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ |
107 | #define alloca_align(size, align)({ void *_ptr_; size_t _mask_ = (align) - 1; _ptr_ = __builtin_alloca ((size) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }) \ |
108 | ({ \ |
109 | void *_ptr_; \ |
110 | size_t _mask_ = (align) - 1; \ |
111 | _ptr_ = alloca((size) + _mask_)__builtin_alloca ((size) + _mask_); \ |
112 | (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ |
113 | }) |
114 | |
115 | #define alloca0_align(size, align)({ void *_new_; size_t _size_ = (size); _new_ = ({ void *_ptr_ ; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_ ) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_ ); }); (void*)memset(_new_, 0, _size_); }) \ |
116 | ({ \ |
117 | void *_new_; \ |
118 | size_t _size_ = (size); \ |
119 | _new_ = alloca_align(_size_, (align))({ void *_ptr_; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }); \ |
120 | (void*)memset(_new_, 0, _size_); \ |
121 | }) |
122 | |
123 | /* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to |
124 | * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ |
125 | #define TAKE_PTR(ptr)({ typeof(ptr) _ptr_ = (ptr); (ptr) = ((void*)0); _ptr_; }) \ |
126 | ({ \ |
127 | typeof(ptr) _ptr_ = (ptr); \ |
128 | (ptr) = NULL((void*)0); \ |
129 | _ptr_; \ |
130 | }) |