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