]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/resolve/resolved-dns-rr.c
Merge pull request #7540 from fbuihuu/systemd-delta-tweaks
[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 free(rr->generic.data);
521 }
522
523 free(rr->wire_format);
524 dns_resource_key_unref(rr->key);
525 }
526
527 free(rr->to_string);
528 return mfree(rr);
529 }
530
531 int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
532 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
533 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
534 _cleanup_free_ char *ptr = NULL;
535 int r;
536
537 assert(ret);
538 assert(address);
539 assert(hostname);
540
541 r = dns_name_reverse(family, address, &ptr);
542 if (r < 0)
543 return r;
544
545 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
546 if (!key)
547 return -ENOMEM;
548
549 ptr = NULL;
550
551 rr = dns_resource_record_new(key);
552 if (!rr)
553 return -ENOMEM;
554
555 rr->ptr.name = strdup(hostname);
556 if (!rr->ptr.name)
557 return -ENOMEM;
558
559 *ret = rr;
560 rr = NULL;
561
562 return 0;
563 }
564
565 int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) {
566 DnsResourceRecord *rr;
567
568 assert(ret);
569 assert(address);
570 assert(family);
571
572 if (family == AF_INET) {
573
574 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name);
575 if (!rr)
576 return -ENOMEM;
577
578 rr->a.in_addr = address->in;
579
580 } else if (family == AF_INET6) {
581
582 rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
583 if (!rr)
584 return -ENOMEM;
585
586 rr->aaaa.in6_addr = address->in6;
587 } else
588 return -EAFNOSUPPORT;
589
590 *ret = rr;
591
592 return 0;
593 }
594
595 #define FIELD_EQUAL(a, b, field) \
596 ((a).field ## _size == (b).field ## _size && \
597 memcmp((a).field, (b).field, (a).field ## _size) == 0)
598
599 int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
600 int r;
601
602 assert(a);
603 assert(b);
604
605 if (a == b)
606 return 1;
607
608 r = dns_resource_key_equal(a->key, b->key);
609 if (r <= 0)
610 return r;
611
612 if (a->unparseable != b->unparseable)
613 return 0;
614
615 switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
616
617 case DNS_TYPE_SRV:
618 r = dns_name_equal(a->srv.name, b->srv.name);
619 if (r <= 0)
620 return r;
621
622 return a->srv.priority == b->srv.priority &&
623 a->srv.weight == b->srv.weight &&
624 a->srv.port == b->srv.port;
625
626 case DNS_TYPE_PTR:
627 case DNS_TYPE_NS:
628 case DNS_TYPE_CNAME:
629 case DNS_TYPE_DNAME:
630 return dns_name_equal(a->ptr.name, b->ptr.name);
631
632 case DNS_TYPE_HINFO:
633 return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
634 strcaseeq(a->hinfo.os, b->hinfo.os);
635
636 case DNS_TYPE_SPF: /* exactly the same as TXT */
637 case DNS_TYPE_TXT:
638 return dns_txt_item_equal(a->txt.items, b->txt.items);
639
640 case DNS_TYPE_A:
641 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
642
643 case DNS_TYPE_AAAA:
644 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
645
646 case DNS_TYPE_SOA:
647 r = dns_name_equal(a->soa.mname, b->soa.mname);
648 if (r <= 0)
649 return r;
650 r = dns_name_equal(a->soa.rname, b->soa.rname);
651 if (r <= 0)
652 return r;
653
654 return a->soa.serial == b->soa.serial &&
655 a->soa.refresh == b->soa.refresh &&
656 a->soa.retry == b->soa.retry &&
657 a->soa.expire == b->soa.expire &&
658 a->soa.minimum == b->soa.minimum;
659
660 case DNS_TYPE_MX:
661 if (a->mx.priority != b->mx.priority)
662 return 0;
663
664 return dns_name_equal(a->mx.exchange, b->mx.exchange);
665
666 case DNS_TYPE_LOC:
667 assert(a->loc.version == b->loc.version);
668
669 return a->loc.size == b->loc.size &&
670 a->loc.horiz_pre == b->loc.horiz_pre &&
671 a->loc.vert_pre == b->loc.vert_pre &&
672 a->loc.latitude == b->loc.latitude &&
673 a->loc.longitude == b->loc.longitude &&
674 a->loc.altitude == b->loc.altitude;
675
676 case DNS_TYPE_DS:
677 return a->ds.key_tag == b->ds.key_tag &&
678 a->ds.algorithm == b->ds.algorithm &&
679 a->ds.digest_type == b->ds.digest_type &&
680 FIELD_EQUAL(a->ds, b->ds, digest);
681
682 case DNS_TYPE_SSHFP:
683 return a->sshfp.algorithm == b->sshfp.algorithm &&
684 a->sshfp.fptype == b->sshfp.fptype &&
685 FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
686
687 case DNS_TYPE_DNSKEY:
688 return a->dnskey.flags == b->dnskey.flags &&
689 a->dnskey.protocol == b->dnskey.protocol &&
690 a->dnskey.algorithm == b->dnskey.algorithm &&
691 FIELD_EQUAL(a->dnskey, b->dnskey, key);
692
693 case DNS_TYPE_RRSIG:
694 /* do the fast comparisons first */
695 return a->rrsig.type_covered == b->rrsig.type_covered &&
696 a->rrsig.algorithm == b->rrsig.algorithm &&
697 a->rrsig.labels == b->rrsig.labels &&
698 a->rrsig.original_ttl == b->rrsig.original_ttl &&
699 a->rrsig.expiration == b->rrsig.expiration &&
700 a->rrsig.inception == b->rrsig.inception &&
701 a->rrsig.key_tag == b->rrsig.key_tag &&
702 FIELD_EQUAL(a->rrsig, b->rrsig, signature) &&
703 dns_name_equal(a->rrsig.signer, b->rrsig.signer);
704
705 case DNS_TYPE_NSEC:
706 return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
707 bitmap_equal(a->nsec.types, b->nsec.types);
708
709 case DNS_TYPE_NSEC3:
710 return a->nsec3.algorithm == b->nsec3.algorithm &&
711 a->nsec3.flags == b->nsec3.flags &&
712 a->nsec3.iterations == b->nsec3.iterations &&
713 FIELD_EQUAL(a->nsec3, b->nsec3, salt) &&
714 FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) &&
715 bitmap_equal(a->nsec3.types, b->nsec3.types);
716
717 case DNS_TYPE_TLSA:
718 return a->tlsa.cert_usage == b->tlsa.cert_usage &&
719 a->tlsa.selector == b->tlsa.selector &&
720 a->tlsa.matching_type == b->tlsa.matching_type &&
721 FIELD_EQUAL(a->tlsa, b->tlsa, data);
722
723 case DNS_TYPE_CAA:
724 return a->caa.flags == b->caa.flags &&
725 streq(a->caa.tag, b->caa.tag) &&
726 FIELD_EQUAL(a->caa, b->caa, value);
727
728 case DNS_TYPE_OPENPGPKEY:
729 default:
730 return FIELD_EQUAL(a->generic, b->generic, data);
731 }
732 }
733
734 static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
735 uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
736 char *s;
737 char NS = latitude >= 1U<<31 ? 'N' : 'S';
738 char EW = longitude >= 1U<<31 ? 'E' : 'W';
739
740 int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
741 int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
742 double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
743 double siz = (size >> 4) * exp10((double) (size & 0xF));
744 double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
745 double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
746
747 if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
748 (lat / 60000 / 60),
749 (lat / 60000) % 60,
750 (lat % 60000) / 1000.,
751 NS,
752 (lon / 60000 / 60),
753 (lon / 60000) % 60,
754 (lon % 60000) / 1000.,
755 EW,
756 alt / 100.,
757 siz / 100.,
758 hor / 100.,
759 ver / 100.) < 0)
760 return NULL;
761
762 return s;
763 }
764
765 static int format_timestamp_dns(char *buf, size_t l, time_t sec) {
766 struct tm tm;
767
768 assert(buf);
769 assert(l > STRLEN("YYYYMMDDHHmmSS"));
770
771 if (!gmtime_r(&sec, &tm))
772 return -EINVAL;
773
774 if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
775 return -EINVAL;
776
777 return 0;
778 }
779
780 static char *format_types(Bitmap *types) {
781 _cleanup_strv_free_ char **strv = NULL;
782 _cleanup_free_ char *str = NULL;
783 Iterator i;
784 unsigned type;
785 int r;
786
787 BITMAP_FOREACH(type, types, i) {
788 if (dns_type_to_string(type)) {
789 r = strv_extend(&strv, dns_type_to_string(type));
790 if (r < 0)
791 return NULL;
792 } else {
793 char *t;
794
795 r = asprintf(&t, "TYPE%u", type);
796 if (r < 0)
797 return NULL;
798
799 r = strv_consume(&strv, t);
800 if (r < 0)
801 return NULL;
802 }
803 }
804
805 str = strv_join(strv, " ");
806 if (!str)
807 return NULL;
808
809 return strjoin("( ", str, " )");
810 }
811
812 static char *format_txt(DnsTxtItem *first) {
813 DnsTxtItem *i;
814 size_t c = 1;
815 char *p, *s;
816
817 LIST_FOREACH(items, i, first)
818 c += i->length * 4 + 3;
819
820 p = s = new(char, c);
821 if (!s)
822 return NULL;
823
824 LIST_FOREACH(items, i, first) {
825 size_t j;
826
827 if (i != first)
828 *(p++) = ' ';
829
830 *(p++) = '"';
831
832 for (j = 0; j < i->length; j++) {
833 if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) {
834 *(p++) = '\\';
835 *(p++) = '0' + (i->data[j] / 100);
836 *(p++) = '0' + ((i->data[j] / 10) % 10);
837 *(p++) = '0' + (i->data[j] % 10);
838 } else
839 *(p++) = i->data[j];
840 }
841
842 *(p++) = '"';
843 }
844
845 *p = 0;
846 return s;
847 }
848
849 const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
850 _cleanup_free_ char *t = NULL;
851 char *s, k[DNS_RESOURCE_KEY_STRING_MAX];
852 int r;
853
854 assert(rr);
855
856 if (rr->to_string)
857 return rr->to_string;
858
859 dns_resource_key_to_string(rr->key, k, sizeof(k));
860
861 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
862
863 case DNS_TYPE_SRV:
864 r = asprintf(&s, "%s %u %u %u %s",
865 k,
866 rr->srv.priority,
867 rr->srv.weight,
868 rr->srv.port,
869 strna(rr->srv.name));
870 if (r < 0)
871 return NULL;
872 break;
873
874 case DNS_TYPE_PTR:
875 case DNS_TYPE_NS:
876 case DNS_TYPE_CNAME:
877 case DNS_TYPE_DNAME:
878 s = strjoin(k, " ", rr->ptr.name);
879 if (!s)
880 return NULL;
881
882 break;
883
884 case DNS_TYPE_HINFO:
885 s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os);
886 if (!s)
887 return NULL;
888 break;
889
890 case DNS_TYPE_SPF: /* exactly the same as TXT */
891 case DNS_TYPE_TXT:
892 t = format_txt(rr->txt.items);
893 if (!t)
894 return NULL;
895
896 s = strjoin(k, " ", t);
897 if (!s)
898 return NULL;
899 break;
900
901 case DNS_TYPE_A: {
902 _cleanup_free_ char *x = NULL;
903
904 r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
905 if (r < 0)
906 return NULL;
907
908 s = strjoin(k, " ", x);
909 if (!s)
910 return NULL;
911 break;
912 }
913
914 case DNS_TYPE_AAAA:
915 r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
916 if (r < 0)
917 return NULL;
918
919 s = strjoin(k, " ", t);
920 if (!s)
921 return NULL;
922 break;
923
924 case DNS_TYPE_SOA:
925 r = asprintf(&s, "%s %s %s %u %u %u %u %u",
926 k,
927 strna(rr->soa.mname),
928 strna(rr->soa.rname),
929 rr->soa.serial,
930 rr->soa.refresh,
931 rr->soa.retry,
932 rr->soa.expire,
933 rr->soa.minimum);
934 if (r < 0)
935 return NULL;
936 break;
937
938 case DNS_TYPE_MX:
939 r = asprintf(&s, "%s %u %s",
940 k,
941 rr->mx.priority,
942 rr->mx.exchange);
943 if (r < 0)
944 return NULL;
945 break;
946
947 case DNS_TYPE_LOC:
948 assert(rr->loc.version == 0);
949
950 t = format_location(rr->loc.latitude,
951 rr->loc.longitude,
952 rr->loc.altitude,
953 rr->loc.size,
954 rr->loc.horiz_pre,
955 rr->loc.vert_pre);
956 if (!t)
957 return NULL;
958
959 s = strjoin(k, " ", t);
960 if (!s)
961 return NULL;
962 break;
963
964 case DNS_TYPE_DS:
965 t = hexmem(rr->ds.digest, rr->ds.digest_size);
966 if (!t)
967 return NULL;
968
969 r = asprintf(&s, "%s %u %u %u %s",
970 k,
971 rr->ds.key_tag,
972 rr->ds.algorithm,
973 rr->ds.digest_type,
974 t);
975 if (r < 0)
976 return NULL;
977 break;
978
979 case DNS_TYPE_SSHFP:
980 t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
981 if (!t)
982 return NULL;
983
984 r = asprintf(&s, "%s %u %u %s",
985 k,
986 rr->sshfp.algorithm,
987 rr->sshfp.fptype,
988 t);
989 if (r < 0)
990 return NULL;
991 break;
992
993 case DNS_TYPE_DNSKEY: {
994 _cleanup_free_ char *alg = NULL;
995 char *ss;
996 int n;
997 uint16_t key_tag;
998
999 key_tag = dnssec_keytag(rr, true);
1000
1001 r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
1002 if (r < 0)
1003 return NULL;
1004
1005 r = asprintf(&s, "%s %u %u %s %n",
1006 k,
1007 rr->dnskey.flags,
1008 rr->dnskey.protocol,
1009 alg,
1010 &n);
1011 if (r < 0)
1012 return NULL;
1013
1014 r = base64_append(&s, n,
1015 rr->dnskey.key, rr->dnskey.key_size,
1016 8, columns());
1017 if (r < 0)
1018 return NULL;
1019
1020 r = asprintf(&ss, "%s\n"
1021 " -- Flags:%s%s%s\n"
1022 " -- Key tag: %u",
1023 s,
1024 rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "",
1025 rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "",
1026 rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "",
1027 key_tag);
1028 if (r < 0)
1029 return NULL;
1030 free(s);
1031 s = ss;
1032
1033 break;
1034 }
1035
1036 case DNS_TYPE_RRSIG: {
1037 _cleanup_free_ char *alg = NULL;
1038 char expiration[STRLEN("YYYYMMDDHHmmSS") + 1], inception[STRLEN("YYYYMMDDHHmmSS") + 1];
1039 const char *type;
1040 int n;
1041
1042 type = dns_type_to_string(rr->rrsig.type_covered);
1043
1044 r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg);
1045 if (r < 0)
1046 return NULL;
1047
1048 r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
1049 if (r < 0)
1050 return NULL;
1051
1052 r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
1053 if (r < 0)
1054 return NULL;
1055
1056 /* TYPE?? follows
1057 * http://tools.ietf.org/html/rfc3597#section-5 */
1058
1059 r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n",
1060 k,
1061 type ?: "TYPE",
1062 type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
1063 alg,
1064 rr->rrsig.labels,
1065 rr->rrsig.original_ttl,
1066 expiration,
1067 inception,
1068 rr->rrsig.key_tag,
1069 rr->rrsig.signer,
1070 &n);
1071 if (r < 0)
1072 return NULL;
1073
1074 r = base64_append(&s, n,
1075 rr->rrsig.signature, rr->rrsig.signature_size,
1076 8, columns());
1077 if (r < 0)
1078 return NULL;
1079
1080 break;
1081 }
1082
1083 case DNS_TYPE_NSEC:
1084 t = format_types(rr->nsec.types);
1085 if (!t)
1086 return NULL;
1087
1088 r = asprintf(&s, "%s %s %s",
1089 k,
1090 rr->nsec.next_domain_name,
1091 t);
1092 if (r < 0)
1093 return NULL;
1094 break;
1095
1096 case DNS_TYPE_NSEC3: {
1097 _cleanup_free_ char *salt = NULL, *hash = NULL;
1098
1099 if (rr->nsec3.salt_size > 0) {
1100 salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
1101 if (!salt)
1102 return NULL;
1103 }
1104
1105 hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
1106 if (!hash)
1107 return NULL;
1108
1109 t = format_types(rr->nsec3.types);
1110 if (!t)
1111 return NULL;
1112
1113 r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
1114 k,
1115 rr->nsec3.algorithm,
1116 rr->nsec3.flags,
1117 rr->nsec3.iterations,
1118 rr->nsec3.salt_size > 0 ? salt : "-",
1119 hash,
1120 t);
1121 if (r < 0)
1122 return NULL;
1123
1124 break;
1125 }
1126
1127 case DNS_TYPE_TLSA: {
1128 const char *cert_usage, *selector, *matching_type;
1129
1130 cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage);
1131 selector = tlsa_selector_to_string(rr->tlsa.selector);
1132 matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type);
1133
1134 t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
1135 if (!t)
1136 return NULL;
1137
1138 r = asprintf(&s,
1139 "%s %u %u %u %s\n"
1140 " -- Cert. usage: %s\n"
1141 " -- Selector: %s\n"
1142 " -- Matching type: %s",
1143 k,
1144 rr->tlsa.cert_usage,
1145 rr->tlsa.selector,
1146 rr->tlsa.matching_type,
1147 t,
1148 cert_usage,
1149 selector,
1150 matching_type);
1151 if (r < 0)
1152 return NULL;
1153
1154 break;
1155 }
1156
1157 case DNS_TYPE_CAA: {
1158 _cleanup_free_ char *value;
1159
1160 value = octescape(rr->caa.value, rr->caa.value_size);
1161 if (!value)
1162 return NULL;
1163
1164 r = asprintf(&s, "%s %u %s \"%s\"%s%s%s%.0u",
1165 k,
1166 rr->caa.flags,
1167 rr->caa.tag,
1168 value,
1169 rr->caa.flags ? "\n -- Flags:" : "",
1170 rr->caa.flags & CAA_FLAG_CRITICAL ? " critical" : "",
1171 rr->caa.flags & ~CAA_FLAG_CRITICAL ? " " : "",
1172 rr->caa.flags & ~CAA_FLAG_CRITICAL);
1173 if (r < 0)
1174 return NULL;
1175
1176 break;
1177 }
1178
1179 case DNS_TYPE_OPENPGPKEY: {
1180 int n;
1181
1182 r = asprintf(&s, "%s %n",
1183 k,
1184 &n);
1185 if (r < 0)
1186 return NULL;
1187
1188 r = base64_append(&s, n,
1189 rr->generic.data, rr->generic.data_size,
1190 8, columns());
1191 if (r < 0)
1192 return NULL;
1193 break;
1194 }
1195
1196 default:
1197 t = hexmem(rr->generic.data, rr->generic.data_size);
1198 if (!t)
1199 return NULL;
1200
1201 /* Format as documented in RFC 3597, Section 5 */
1202 r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
1203 if (r < 0)
1204 return NULL;
1205 break;
1206 }
1207
1208 rr->to_string = s;
1209 return s;
1210 }
1211
1212 ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) {
1213 assert(rr);
1214 assert(out);
1215
1216 switch(rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
1217 case DNS_TYPE_SRV:
1218 case DNS_TYPE_PTR:
1219 case DNS_TYPE_NS:
1220 case DNS_TYPE_CNAME:
1221 case DNS_TYPE_DNAME:
1222 case DNS_TYPE_HINFO:
1223 case DNS_TYPE_SPF:
1224 case DNS_TYPE_TXT:
1225 case DNS_TYPE_A:
1226 case DNS_TYPE_AAAA:
1227 case DNS_TYPE_SOA:
1228 case DNS_TYPE_MX:
1229 case DNS_TYPE_LOC:
1230 case DNS_TYPE_DS:
1231 case DNS_TYPE_DNSKEY:
1232 case DNS_TYPE_RRSIG:
1233 case DNS_TYPE_NSEC:
1234 case DNS_TYPE_NSEC3:
1235 return -EINVAL;
1236
1237 case DNS_TYPE_SSHFP:
1238 *out = rr->sshfp.fingerprint;
1239 return rr->sshfp.fingerprint_size;
1240
1241 case DNS_TYPE_TLSA:
1242 *out = rr->tlsa.data;
1243 return rr->tlsa.data_size;
1244
1245
1246 case DNS_TYPE_OPENPGPKEY:
1247 default:
1248 *out = rr->generic.data;
1249 return rr->generic.data_size;
1250 }
1251 }
1252
1253 int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) {
1254
1255 DnsPacket packet = {
1256 .n_ref = 1,
1257 .protocol = DNS_PROTOCOL_DNS,
1258 .on_stack = true,
1259 .refuse_compression = true,
1260 .canonical_form = canonical,
1261 };
1262
1263 size_t start, rds;
1264 int r;
1265
1266 assert(rr);
1267
1268 /* Generates the RR in wire-format, optionally in the
1269 * canonical form as discussed in the DNSSEC RFC 4034, Section
1270 * 6.2. We allocate a throw-away DnsPacket object on the stack
1271 * here, because we need some book-keeping for memory
1272 * management, and can reuse the DnsPacket serializer, that
1273 * can generate the canonical form, too, but also knows label
1274 * compression and suchlike. */
1275
1276 if (rr->wire_format && rr->wire_format_canonical == canonical)
1277 return 0;
1278
1279 r = dns_packet_append_rr(&packet, rr, 0, &start, &rds);
1280 if (r < 0)
1281 return r;
1282
1283 assert(start == 0);
1284 assert(packet._data);
1285
1286 free(rr->wire_format);
1287 rr->wire_format = packet._data;
1288 rr->wire_format_size = packet.size;
1289 rr->wire_format_rdata_offset = rds;
1290 rr->wire_format_canonical = canonical;
1291
1292 packet._data = NULL;
1293 dns_packet_unref(&packet);
1294
1295 return 0;
1296 }
1297
1298 int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
1299 const char *n;
1300 int r;
1301
1302 assert(rr);
1303 assert(ret);
1304
1305 /* Returns the RRset's signer, if it is known. */
1306
1307 if (rr->n_skip_labels_signer == (unsigned) -1)
1308 return -ENODATA;
1309
1310 n = dns_resource_key_name(rr->key);
1311 r = dns_name_skip(n, rr->n_skip_labels_signer, &n);
1312 if (r < 0)
1313 return r;
1314 if (r == 0)
1315 return -EINVAL;
1316
1317 *ret = n;
1318 return 0;
1319 }
1320
1321 int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
1322 const char *n;
1323 int r;
1324
1325 assert(rr);
1326 assert(ret);
1327
1328 /* Returns the RRset's synthesizing source, if it is known. */
1329
1330 if (rr->n_skip_labels_source == (unsigned) -1)
1331 return -ENODATA;
1332
1333 n = dns_resource_key_name(rr->key);
1334 r = dns_name_skip(n, rr->n_skip_labels_source, &n);
1335 if (r < 0)
1336 return r;
1337 if (r == 0)
1338 return -EINVAL;
1339
1340 *ret = n;
1341 return 0;
1342 }
1343
1344 int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) {
1345 const char *signer;
1346 int r;
1347
1348 assert(rr);
1349
1350 r = dns_resource_record_signer(rr, &signer);
1351 if (r < 0)
1352 return r;
1353
1354 return dns_name_equal(zone, signer);
1355 }
1356
1357 int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
1358 int r;
1359
1360 assert(rr);
1361
1362 /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1363
1364 if (rr->n_skip_labels_source == (unsigned) -1)
1365 return -ENODATA;
1366
1367 if (rr->n_skip_labels_source == 0)
1368 return 0;
1369
1370 if (rr->n_skip_labels_source > 1)
1371 return 1;
1372
1373 r = dns_name_startswith(dns_resource_key_name(rr->key), "*");
1374 if (r < 0)
1375 return r;
1376
1377 return !r;
1378 }
1379
1380 void dns_resource_record_hash_func(const void *i, struct siphash *state) {
1381 const DnsResourceRecord *rr = i;
1382
1383 assert(rr);
1384
1385 dns_resource_key_hash_func(rr->key, state);
1386
1387 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
1388
1389 case DNS_TYPE_SRV:
1390 siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state);
1391 siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state);
1392 siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state);
1393 dns_name_hash_func(rr->srv.name, state);
1394 break;
1395
1396 case DNS_TYPE_PTR:
1397 case DNS_TYPE_NS:
1398 case DNS_TYPE_CNAME:
1399 case DNS_TYPE_DNAME:
1400 dns_name_hash_func(rr->ptr.name, state);
1401 break;
1402
1403 case DNS_TYPE_HINFO:
1404 string_hash_func(rr->hinfo.cpu, state);
1405 string_hash_func(rr->hinfo.os, state);
1406 break;
1407
1408 case DNS_TYPE_TXT:
1409 case DNS_TYPE_SPF: {
1410 DnsTxtItem *j;
1411
1412 LIST_FOREACH(items, j, rr->txt.items) {
1413 siphash24_compress(j->data, j->length, state);
1414
1415 /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1416 * followed by "". */
1417 siphash24_compress_byte(0, state);
1418 }
1419 break;
1420 }
1421
1422 case DNS_TYPE_A:
1423 siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state);
1424 break;
1425
1426 case DNS_TYPE_AAAA:
1427 siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state);
1428 break;
1429
1430 case DNS_TYPE_SOA:
1431 dns_name_hash_func(rr->soa.mname, state);
1432 dns_name_hash_func(rr->soa.rname, state);
1433 siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state);
1434 siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state);
1435 siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state);
1436 siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state);
1437 siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state);
1438 break;
1439
1440 case DNS_TYPE_MX:
1441 siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state);
1442 dns_name_hash_func(rr->mx.exchange, state);
1443 break;
1444
1445 case DNS_TYPE_LOC:
1446 siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state);
1447 siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state);
1448 siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state);
1449 siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state);
1450 siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state);
1451 siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state);
1452 siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state);
1453 break;
1454
1455 case DNS_TYPE_SSHFP:
1456 siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state);
1457 siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state);
1458 siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
1459 break;
1460
1461 case DNS_TYPE_DNSKEY:
1462 siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state);
1463 siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state);
1464 siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state);
1465 siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state);
1466 break;
1467
1468 case DNS_TYPE_RRSIG:
1469 siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state);
1470 siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state);
1471 siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state);
1472 siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state);
1473 siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state);
1474 siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state);
1475 siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state);
1476 dns_name_hash_func(rr->rrsig.signer, state);
1477 siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state);
1478 break;
1479
1480 case DNS_TYPE_NSEC:
1481 dns_name_hash_func(rr->nsec.next_domain_name, state);
1482 /* FIXME: we leave out the type bitmap here. Hash
1483 * would be better if we'd take it into account
1484 * too. */
1485 break;
1486
1487 case DNS_TYPE_DS:
1488 siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state);
1489 siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state);
1490 siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state);
1491 siphash24_compress(rr->ds.digest, rr->ds.digest_size, state);
1492 break;
1493
1494 case DNS_TYPE_NSEC3:
1495 siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state);
1496 siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state);
1497 siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state);
1498 siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state);
1499 siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
1500 /* FIXME: We leave the bitmaps out */
1501 break;
1502
1503 case DNS_TYPE_TLSA:
1504 siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
1505 siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
1506 siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
1507 siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state);
1508 break;
1509
1510 case DNS_TYPE_CAA:
1511 siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state);
1512 string_hash_func(rr->caa.tag, state);
1513 siphash24_compress(rr->caa.value, rr->caa.value_size, state);
1514 break;
1515
1516 case DNS_TYPE_OPENPGPKEY:
1517 default:
1518 siphash24_compress(rr->generic.data, rr->generic.data_size, state);
1519 break;
1520 }
1521 }
1522
1523 static int dns_resource_record_compare_func(const void *a, const void *b) {
1524 const DnsResourceRecord *x = a, *y = b;
1525 int ret;
1526
1527 ret = dns_resource_key_compare_func(x->key, y->key);
1528 if (ret != 0)
1529 return ret;
1530
1531 if (dns_resource_record_equal(x, y))
1532 return 0;
1533
1534 /* This is a bit dirty, we don't implement proper ordering, but
1535 * the hashtable doesn't need ordering anyway, hence we don't
1536 * care. */
1537 return x < y ? -1 : 1;
1538 }
1539
1540 const struct hash_ops dns_resource_record_hash_ops = {
1541 .hash = dns_resource_record_hash_func,
1542 .compare = dns_resource_record_compare_func,
1543 };
1544
1545 DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) {
1546 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *copy = NULL;
1547 DnsResourceRecord *t;
1548
1549 assert(rr);
1550
1551 copy = dns_resource_record_new(rr->key);
1552 if (!copy)
1553 return NULL;
1554
1555 copy->ttl = rr->ttl;
1556 copy->expiry = rr->expiry;
1557 copy->n_skip_labels_signer = rr->n_skip_labels_signer;
1558 copy->n_skip_labels_source = rr->n_skip_labels_source;
1559 copy->unparseable = rr->unparseable;
1560
1561 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
1562
1563 case DNS_TYPE_SRV:
1564 copy->srv.priority = rr->srv.priority;
1565 copy->srv.weight = rr->srv.weight;
1566 copy->srv.port = rr->srv.port;
1567 copy->srv.name = strdup(rr->srv.name);
1568 if (!copy->srv.name)
1569 return NULL;
1570 break;
1571
1572 case DNS_TYPE_PTR:
1573 case DNS_TYPE_NS:
1574 case DNS_TYPE_CNAME:
1575 case DNS_TYPE_DNAME:
1576 copy->ptr.name = strdup(rr->ptr.name);
1577 if (!copy->ptr.name)
1578 return NULL;
1579 break;
1580
1581 case DNS_TYPE_HINFO:
1582 copy->hinfo.cpu = strdup(rr->hinfo.cpu);
1583 if (!copy->hinfo.cpu)
1584 return NULL;
1585
1586 copy->hinfo.os = strdup(rr->hinfo.os);
1587 if (!copy->hinfo.os)
1588 return NULL;
1589 break;
1590
1591 case DNS_TYPE_TXT:
1592 case DNS_TYPE_SPF:
1593 copy->txt.items = dns_txt_item_copy(rr->txt.items);
1594 if (!copy->txt.items)
1595 return NULL;
1596 break;
1597
1598 case DNS_TYPE_A:
1599 copy->a = rr->a;
1600 break;
1601
1602 case DNS_TYPE_AAAA:
1603 copy->aaaa = rr->aaaa;
1604 break;
1605
1606 case DNS_TYPE_SOA:
1607 copy->soa.mname = strdup(rr->soa.mname);
1608 if (!copy->soa.mname)
1609 return NULL;
1610 copy->soa.rname = strdup(rr->soa.rname);
1611 if (!copy->soa.rname)
1612 return NULL;
1613 copy->soa.serial = rr->soa.serial;
1614 copy->soa.refresh = rr->soa.refresh;
1615 copy->soa.retry = rr->soa.retry;
1616 copy->soa.expire = rr->soa.expire;
1617 copy->soa.minimum = rr->soa.minimum;
1618 break;
1619
1620 case DNS_TYPE_MX:
1621 copy->mx.priority = rr->mx.priority;
1622 copy->mx.exchange = strdup(rr->mx.exchange);
1623 if (!copy->mx.exchange)
1624 return NULL;
1625 break;
1626
1627 case DNS_TYPE_LOC:
1628 copy->loc = rr->loc;
1629 break;
1630
1631 case DNS_TYPE_SSHFP:
1632 copy->sshfp.algorithm = rr->sshfp.algorithm;
1633 copy->sshfp.fptype = rr->sshfp.fptype;
1634 copy->sshfp.fingerprint = memdup(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
1635 if (!copy->sshfp.fingerprint)
1636 return NULL;
1637 copy->sshfp.fingerprint_size = rr->sshfp.fingerprint_size;
1638 break;
1639
1640 case DNS_TYPE_DNSKEY:
1641 copy->dnskey.flags = rr->dnskey.flags;
1642 copy->dnskey.protocol = rr->dnskey.protocol;
1643 copy->dnskey.algorithm = rr->dnskey.algorithm;
1644 copy->dnskey.key = memdup(rr->dnskey.key, rr->dnskey.key_size);
1645 if (!copy->dnskey.key)
1646 return NULL;
1647 copy->dnskey.key_size = rr->dnskey.key_size;
1648 break;
1649
1650 case DNS_TYPE_RRSIG:
1651 copy->rrsig.type_covered = rr->rrsig.type_covered;
1652 copy->rrsig.algorithm = rr->rrsig.algorithm;
1653 copy->rrsig.labels = rr->rrsig.labels;
1654 copy->rrsig.original_ttl = rr->rrsig.original_ttl;
1655 copy->rrsig.expiration = rr->rrsig.expiration;
1656 copy->rrsig.inception = rr->rrsig.inception;
1657 copy->rrsig.key_tag = rr->rrsig.key_tag;
1658 copy->rrsig.signer = strdup(rr->rrsig.signer);
1659 if (!copy->rrsig.signer)
1660 return NULL;
1661 copy->rrsig.signature = memdup(rr->rrsig.signature, rr->rrsig.signature_size);
1662 if (!copy->rrsig.signature)
1663 return NULL;
1664 copy->rrsig.signature_size = rr->rrsig.signature_size;
1665 break;
1666
1667 case DNS_TYPE_NSEC:
1668 copy->nsec.next_domain_name = strdup(rr->nsec.next_domain_name);
1669 if (!copy->nsec.next_domain_name)
1670 return NULL;
1671 copy->nsec.types = bitmap_copy(rr->nsec.types);
1672 if (!copy->nsec.types)
1673 return NULL;
1674 break;
1675
1676 case DNS_TYPE_DS:
1677 copy->ds.key_tag = rr->ds.key_tag;
1678 copy->ds.algorithm = rr->ds.algorithm;
1679 copy->ds.digest_type = rr->ds.digest_type;
1680 copy->ds.digest = memdup(rr->ds.digest, rr->ds.digest_size);
1681 if (!copy->ds.digest)
1682 return NULL;
1683 copy->ds.digest_size = rr->ds.digest_size;
1684 break;
1685
1686 case DNS_TYPE_NSEC3:
1687 copy->nsec3.algorithm = rr->nsec3.algorithm;
1688 copy->nsec3.flags = rr->nsec3.flags;
1689 copy->nsec3.iterations = rr->nsec3.iterations;
1690 copy->nsec3.salt = memdup(rr->nsec3.salt, rr->nsec3.salt_size);
1691 if (!copy->nsec3.salt)
1692 return NULL;
1693 copy->nsec3.salt_size = rr->nsec3.salt_size;
1694 copy->nsec3.next_hashed_name = memdup(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size);
1695 if (!copy->nsec3.next_hashed_name_size)
1696 return NULL;
1697 copy->nsec3.next_hashed_name_size = rr->nsec3.next_hashed_name_size;
1698 copy->nsec3.types = bitmap_copy(rr->nsec3.types);
1699 if (!copy->nsec3.types)
1700 return NULL;
1701 break;
1702
1703 case DNS_TYPE_TLSA:
1704 copy->tlsa.cert_usage = rr->tlsa.cert_usage;
1705 copy->tlsa.selector = rr->tlsa.selector;
1706 copy->tlsa.matching_type = rr->tlsa.matching_type;
1707 copy->tlsa.data = memdup(rr->tlsa.data, rr->tlsa.data_size);
1708 if (!copy->tlsa.data)
1709 return NULL;
1710 copy->tlsa.data_size = rr->tlsa.data_size;
1711 break;
1712
1713 case DNS_TYPE_CAA:
1714 copy->caa.flags = rr->caa.flags;
1715 copy->caa.tag = strdup(rr->caa.tag);
1716 if (!copy->caa.tag)
1717 return NULL;
1718 copy->caa.value = memdup(rr->caa.value, rr->caa.value_size);
1719 if (!copy->caa.value)
1720 return NULL;
1721 copy->caa.value_size = rr->caa.value_size;
1722 break;
1723
1724 case DNS_TYPE_OPT:
1725 default:
1726 copy->generic.data = memdup(rr->generic.data, rr->generic.data_size);
1727 if (!copy->generic.data)
1728 return NULL;
1729 copy->generic.data_size = rr->generic.data_size;
1730 break;
1731 }
1732
1733 t = copy;
1734 copy = NULL;
1735
1736 return t;
1737 }
1738
1739 int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl) {
1740 DnsResourceRecord *old_rr, *new_rr;
1741 uint32_t new_ttl;
1742
1743 assert(rr);
1744 old_rr = *rr;
1745
1746 if (old_rr->key->type == DNS_TYPE_OPT)
1747 return -EINVAL;
1748
1749 new_ttl = MIN(old_rr->ttl, max_ttl);
1750 if (new_ttl == old_rr->ttl)
1751 return 0;
1752
1753 if (old_rr->n_ref == 1) {
1754 /* Patch in place */
1755 old_rr->ttl = new_ttl;
1756 return 1;
1757 }
1758
1759 new_rr = dns_resource_record_copy(old_rr);
1760 if (!new_rr)
1761 return -ENOMEM;
1762
1763 new_rr->ttl = new_ttl;
1764
1765 dns_resource_record_unref(*rr);
1766 *rr = new_rr;
1767
1768 return 1;
1769 }
1770
1771 DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
1772 DnsTxtItem *n;
1773
1774 if (!i)
1775 return NULL;
1776
1777 n = i->items_next;
1778
1779 free(i);
1780 return dns_txt_item_free_all(n);
1781 }
1782
1783 bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) {
1784
1785 if (a == b)
1786 return true;
1787
1788 if (!a != !b)
1789 return false;
1790
1791 if (!a)
1792 return true;
1793
1794 if (a->length != b->length)
1795 return false;
1796
1797 if (memcmp(a->data, b->data, a->length) != 0)
1798 return false;
1799
1800 return dns_txt_item_equal(a->items_next, b->items_next);
1801 }
1802
1803 DnsTxtItem *dns_txt_item_copy(DnsTxtItem *first) {
1804 DnsTxtItem *i, *copy = NULL, *end = NULL;
1805
1806 LIST_FOREACH(items, i, first) {
1807 DnsTxtItem *j;
1808
1809 j = memdup(i, offsetof(DnsTxtItem, data) + i->length + 1);
1810 if (!j) {
1811 dns_txt_item_free_all(copy);
1812 return NULL;
1813 }
1814
1815 LIST_INSERT_AFTER(items, copy, end, j);
1816 end = j;
1817 }
1818
1819 return copy;
1820 }
1821
1822 int dns_txt_item_new_empty(DnsTxtItem **ret) {
1823 DnsTxtItem *i;
1824
1825 /* RFC 6763, section 6.1 suggests to treat
1826 * empty TXT RRs as equivalent to a TXT record
1827 * with a single empty string. */
1828
1829 i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
1830 if (!i)
1831 return -ENOMEM;
1832
1833 *ret = i;
1834
1835 return 0;
1836 }
1837
1838 static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
1839 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
1840 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1841 [DNSSEC_ALGORITHM_DH] = "DH",
1842 [DNSSEC_ALGORITHM_DSA] = "DSA",
1843 [DNSSEC_ALGORITHM_ECC] = "ECC",
1844 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1845 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
1846 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
1847 [DNSSEC_ALGORITHM_RSASHA256] = "RSASHA256",
1848 [DNSSEC_ALGORITHM_RSASHA512] = "RSASHA512",
1849 [DNSSEC_ALGORITHM_ECC_GOST] = "ECC-GOST",
1850 [DNSSEC_ALGORITHM_ECDSAP256SHA256] = "ECDSAP256SHA256",
1851 [DNSSEC_ALGORITHM_ECDSAP384SHA384] = "ECDSAP384SHA384",
1852 [DNSSEC_ALGORITHM_ED25519] = "ED25519",
1853 [DNSSEC_ALGORITHM_ED448] = "ED448",
1854 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1855 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1856 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
1857 };
1858 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255);
1859
1860 static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
1861 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
1862 [DNSSEC_DIGEST_SHA1] = "SHA-1",
1863 [DNSSEC_DIGEST_SHA256] = "SHA-256",
1864 [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94",
1865 [DNSSEC_DIGEST_SHA384] = "SHA-384",
1866 };
1867 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255);