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