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