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