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