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