]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-rr.c
build: colorize gcc only if on tty
[thirdparty/systemd.git] / src / resolve / resolved-dns-rr.c
CommitLineData
74b2466e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
0dae31d4
ZJS
22#include <math.h>
23
2e276efc
ZJS
24#include "strv.h"
25
322345fd 26#include "resolved-dns-domain.h"
74b2466e 27#include "resolved-dns-rr.h"
8db0d2f5 28#include "resolved-dns-packet.h"
7263f724 29#include "dns-type.h"
74b2466e 30
faa133f3
LP
31DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
32 DnsResourceKey *k;
33 size_t l;
74b2466e 34
faa133f3
LP
35 assert(name);
36
37 l = strlen(name);
38 k = malloc0(sizeof(DnsResourceKey) + l + 1);
39 if (!k)
40 return NULL;
41
42 k->n_ref = 1;
43 k->class = class;
44 k->type = type;
45
46 strcpy((char*) k + sizeof(DnsResourceKey), name);
47
48 return k;
49}
50
51DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
52 DnsResourceKey *k;
53
54 assert(name);
55
56 k = new0(DnsResourceKey, 1);
57 if (!k)
58 return NULL;
59
60 k->n_ref = 1;
61 k->class = class;
62 k->type = type;
63 k->_name = name;
64
65 return k;
66}
67
68DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
69
70 if (!k)
71 return NULL;
72
73 assert(k->n_ref > 0);
74 k->n_ref++;
75
76 return k;
77}
78
79DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
80 if (!k)
81 return NULL;
82
83 assert(k->n_ref > 0);
84
85 if (k->n_ref == 1) {
86 free(k->_name);
87 free(k);
88 } else
89 k->n_ref--;
90
91 return NULL;
92}
93
94int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
95 int r;
96
97 r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
98 if (r <= 0)
99 return r;
100
101 if (a->class != b->class)
102 return 0;
103
104 if (a->type != b->type)
105 return 0;
106
107 return 1;
108}
109
110int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
111 assert(key);
112 assert(rr);
113
114 if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
115 return 0;
116
117 if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
118 return 0;
119
120 return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
121}
122
123int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr) {
124 assert(key);
125 assert(rr);
126
127 if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
128 return 0;
129
130 if (rr->key->type != DNS_TYPE_CNAME)
131 return 0;
132
133 return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
74b2466e
LP
134}
135
322345fd
LP
136unsigned long dns_resource_key_hash_func(const void *i, const uint8_t hash_key[HASH_KEY_SIZE]) {
137 const DnsResourceKey *k = i;
138 unsigned long ul;
139
faa133f3 140 ul = dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), hash_key);
322345fd
LP
141 ul = ul * hash_key[0] + ul + k->class;
142 ul = ul * hash_key[1] + ul + k->type;
143
144 return ul;
145}
146
147int dns_resource_key_compare_func(const void *a, const void *b) {
148 const DnsResourceKey *x = a, *y = b;
149 int ret;
150
faa133f3 151 ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
322345fd
LP
152 if (ret != 0)
153 return ret;
154
155 if (x->type < y->type)
156 return -1;
157 if (x->type > y->type)
158 return 1;
159
160 if (x->class < y->class)
161 return -1;
162 if (x->class > y->class)
163 return 1;
164
165 return 0;
166}
167
2d4c5cbc
LP
168int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
169 char cbuf[DECIMAL_STR_MAX(uint16_t)], tbuf[DECIMAL_STR_MAX(uint16_t)];
170 const char *c, *t;
171 char *s;
172
173 c = dns_class_to_string(key->class);
174 if (!c) {
175 sprintf(cbuf, "%i", key->class);
176 c = cbuf;
177 }
178
179 t = dns_type_to_string(key->type);
180 if (!t){
181 sprintf(tbuf, "%i", key->type);
182 t = tbuf;
183 }
184
23432a1c 185 if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
2d4c5cbc
LP
186 return -ENOMEM;
187
188 *ret = s;
189 return 0;
190}
191
faa133f3 192DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
74b2466e
LP
193 DnsResourceRecord *rr;
194
195 rr = new0(DnsResourceRecord, 1);
196 if (!rr)
197 return NULL;
198
199 rr->n_ref = 1;
faa133f3
LP
200 rr->key = dns_resource_key_ref(key);
201
74b2466e
LP
202 return rr;
203}
204
8bf52d3d
LP
205DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
206 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
207
208 key = dns_resource_key_new(class, type, name);
209 if (!key)
210 return NULL;
211
212 return dns_resource_record_new(key);
213}
214
74b2466e
LP
215DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
216 if (!rr)
217 return NULL;
218
219 assert(rr->n_ref > 0);
220 rr->n_ref++;
221
222 return rr;
223}
224
225DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
226 if (!rr)
227 return NULL;
228
229 assert(rr->n_ref > 0);
230
231 if (rr->n_ref > 1) {
232 rr->n_ref--;
233 return NULL;
234 }
235
faa133f3 236 if (rr->key) {
9de3e329 237 switch(rr->key->type) {
9c92ce6d
LP
238
239 case DNS_TYPE_SRV:
240 free(rr->srv.name);
241 break;
242
9de3e329
ZJS
243 case DNS_TYPE_PTR:
244 case DNS_TYPE_NS:
245 case DNS_TYPE_CNAME:
8ac4e9e1 246 case DNS_TYPE_DNAME:
faa133f3 247 free(rr->ptr.name);
9de3e329 248 break;
9c92ce6d 249
9de3e329 250 case DNS_TYPE_HINFO:
faa133f3
LP
251 free(rr->hinfo.cpu);
252 free(rr->hinfo.os);
9de3e329 253 break;
9c92ce6d 254
9de3e329 255 case DNS_TYPE_TXT:
9c92ce6d 256 case DNS_TYPE_SPF:
2e276efc 257 strv_free(rr->txt.strings);
9de3e329 258 break;
9c92ce6d 259
9de3e329 260 case DNS_TYPE_SOA:
7e8e0422
LP
261 free(rr->soa.mname);
262 free(rr->soa.rname);
9de3e329 263 break;
9c92ce6d 264
9de3e329 265 case DNS_TYPE_MX:
946c7094 266 free(rr->mx.exchange);
9de3e329 267 break;
9c92ce6d 268
42cc2eeb
LP
269 case DNS_TYPE_SSHFP:
270 free(rr->sshfp.key);
271 break;
272
8db0d2f5
ZJS
273 case DNS_TYPE_DNSKEY:
274 free(rr->dnskey.key);
275 break;
276
151226ab
ZJS
277 case DNS_TYPE_RRSIG:
278 free(rr->rrsig.signer);
279 free(rr->rrsig.signature);
280 break;
281
0dae31d4 282 case DNS_TYPE_LOC:
9de3e329
ZJS
283 case DNS_TYPE_A:
284 case DNS_TYPE_AAAA:
285 break;
9c92ce6d 286
9de3e329 287 default:
faa133f3 288 free(rr->generic.data);
9de3e329 289 }
322345fd 290
faa133f3
LP
291 dns_resource_key_unref(rr->key);
292 }
322345fd 293
faa133f3 294 free(rr);
322345fd 295
322345fd
LP
296 return NULL;
297}
298
623a4c97
LP
299int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
300 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
301 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
302 _cleanup_free_ char *ptr = NULL;
303 int r;
304
305 assert(ret);
306 assert(address);
307 assert(hostname);
308
309 r = dns_name_reverse(family, address, &ptr);
310 if (r < 0)
311 return r;
312
313 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
314 if (!key)
315 return -ENOMEM;
316
317 ptr = NULL;
318
319 rr = dns_resource_record_new(key);
320 if (!rr)
321 return -ENOMEM;
322
323 rr->ptr.name = strdup(hostname);
324 if (!rr->ptr.name)
325 return -ENOMEM;
326
327 *ret = rr;
328 rr = NULL;
329
330 return 0;
331}
332
322345fd
LP
333int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
334 int r;
335
336 assert(a);
337 assert(b);
338
faa133f3 339 r = dns_resource_key_equal(a->key, b->key);
322345fd
LP
340 if (r <= 0)
341 return r;
342
fd0b4602
LP
343 if (a->unparseable != b->unparseable)
344 return 0;
345
346 switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
2d4c5cbc 347
9c92ce6d
LP
348 case DNS_TYPE_SRV:
349 r = dns_name_equal(a->srv.name, b->srv.name);
350 if (r <= 0)
351 return r;
352
353 return a->srv.priority == b->srv.priority &&
354 a->srv.weight == b->srv.weight &&
355 a->srv.port == b->srv.port;
356
2d4c5cbc
LP
357 case DNS_TYPE_PTR:
358 case DNS_TYPE_NS:
359 case DNS_TYPE_CNAME:
8ac4e9e1 360 case DNS_TYPE_DNAME:
322345fd 361 return dns_name_equal(a->ptr.name, b->ptr.name);
2d4c5cbc
LP
362
363 case DNS_TYPE_HINFO:
364 return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
365 strcaseeq(a->hinfo.os, b->hinfo.os);
366
9de3e329 367 case DNS_TYPE_SPF: /* exactly the same as TXT */
2e276efc
ZJS
368 case DNS_TYPE_TXT: {
369 int i;
370
371 for (i = 0; a->txt.strings[i] || b->txt.strings[i]; i++)
372 if (!streq_ptr(a->txt.strings[i], b->txt.strings[i]))
373 return false;
374 return true;
375 }
376
2d4c5cbc 377 case DNS_TYPE_A:
322345fd 378 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
2d4c5cbc
LP
379
380 case DNS_TYPE_AAAA:
322345fd 381 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
2d4c5cbc
LP
382
383 case DNS_TYPE_SOA:
7e8e0422
LP
384 r = dns_name_equal(a->soa.mname, b->soa.mname);
385 if (r <= 0)
386 return r;
387 r = dns_name_equal(a->soa.rname, b->soa.rname);
388 if (r <= 0)
389 return r;
390
391 return a->soa.serial == b->soa.serial &&
392 a->soa.refresh == b->soa.refresh &&
393 a->soa.retry == b->soa.retry &&
394 a->soa.expire == b->soa.expire &&
395 a->soa.minimum == b->soa.minimum;
9c92ce6d 396
946c7094
ZJS
397 case DNS_TYPE_MX:
398 if (a->mx.priority != b->mx.priority)
399 return 0;
400
401 return dns_name_equal(a->mx.exchange, b->mx.exchange);
402
0dae31d4
ZJS
403 case DNS_TYPE_LOC:
404 assert(a->loc.version == b->loc.version);
405
406 return a->loc.size == b->loc.size &&
407 a->loc.horiz_pre == b->loc.horiz_pre &&
408 a->loc.vert_pre == b->loc.vert_pre &&
409 a->loc.latitude == b->loc.latitude &&
410 a->loc.longitude == b->loc.longitude &&
411 a->loc.altitude == b->loc.altitude;
412
42cc2eeb
LP
413 case DNS_TYPE_SSHFP:
414 return a->sshfp.algorithm == b->sshfp.algorithm &&
415 a->sshfp.fptype == b->sshfp.fptype &&
416 a->sshfp.key_size == b->sshfp.key_size &&
417 memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
418
8db0d2f5
ZJS
419 case DNS_TYPE_DNSKEY:
420 return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
421 a->dnskey.sep_flag == b->dnskey.sep_flag &&
422 a->dnskey.algorithm == b->dnskey.algorithm &&
423 a->dnskey.key_size == b->dnskey.key_size &&
424 memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
425
151226ab
ZJS
426 case DNS_TYPE_RRSIG:
427 /* do the fast comparisons first */
03664a62
LN
428 if (a->rrsig.type_covered != b->rrsig.type_covered ||
429 a->rrsig.algorithm != b->rrsig.algorithm ||
430 a->rrsig.labels != b->rrsig.labels ||
431 a->rrsig.original_ttl != b->rrsig.original_ttl ||
432 a->rrsig.expiration != b->rrsig.expiration ||
433 a->rrsig.inception != b->rrsig.inception ||
434 a->rrsig.key_tag != b->rrsig.key_tag ||
151226ab
ZJS
435 a->rrsig.signature_size != b->rrsig.signature_size ||
436 memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
437 return false;
438
439 return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
440
2d4c5cbc 441 default:
322345fd
LP
442 return a->generic.size == b->generic.size &&
443 memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
2d4c5cbc 444 }
322345fd
LP
445}
446
0dae31d4
ZJS
447static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
448 uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
449 char *s;
450 char NS = latitude >= 1U<<31 ? 'N' : 'S';
451 char EW = longitude >= 1U<<31 ? 'E' : 'W';
452
453 int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
454 int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
455 double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
456 double siz = (size >> 4) * exp10((double) (size & 0xF));
457 double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
458 double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
459
460 if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
461 (lat / 60000 / 60),
462 (lat / 60000) % 60,
463 (lat % 60000) / 1000.,
464 NS,
465 (lon / 60000 / 60),
466 (lon / 60000) % 60,
467 (lon % 60000) / 1000.,
468 EW,
469 alt / 100.,
470 siz / 100.,
471 hor / 100.,
472 ver / 100.) < 0)
473 return NULL;
474
475 return s;
476}
477
2d4c5cbc 478int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
8db0d2f5 479 _cleanup_free_ char *k = NULL, *t = NULL;
2d4c5cbc
LP
480 char *s;
481 int r;
322345fd 482
2d4c5cbc 483 assert(rr);
322345fd 484
2d4c5cbc
LP
485 r = dns_resource_key_to_string(rr->key, &k);
486 if (r < 0)
487 return r;
322345fd 488
0dae31d4 489 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
322345fd 490
9c92ce6d
LP
491 case DNS_TYPE_SRV:
492 r = asprintf(&s, "%s %u %u %u %s",
493 k,
494 rr->srv.priority,
495 rr->srv.weight,
496 rr->srv.port,
497 strna(rr->srv.name));
498 if (r < 0)
499 return -ENOMEM;
500 break;
501
2d4c5cbc
LP
502 case DNS_TYPE_PTR:
503 case DNS_TYPE_NS:
504 case DNS_TYPE_CNAME:
8ac4e9e1 505 case DNS_TYPE_DNAME:
2d4c5cbc
LP
506 s = strjoin(k, " ", rr->ptr.name, NULL);
507 if (!s)
508 return -ENOMEM;
322345fd 509
2d4c5cbc 510 break;
322345fd 511
2d4c5cbc
LP
512 case DNS_TYPE_HINFO:
513 s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL);
514 if (!s)
515 return -ENOMEM;
516 break;
322345fd 517
9de3e329 518 case DNS_TYPE_SPF: /* exactly the same as TXT */
8db0d2f5 519 case DNS_TYPE_TXT:
2e276efc
ZJS
520 t = strv_join_quoted(rr->txt.strings);
521 if (!t)
522 return -ENOMEM;
523
524 s = strjoin(k, " ", t, NULL);
525 if (!s)
526 return -ENOMEM;
527
528 break;
2e276efc 529
2d4c5cbc
LP
530 case DNS_TYPE_A: {
531 _cleanup_free_ char *x = NULL;
322345fd 532
2d4c5cbc
LP
533 r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
534 if (r < 0)
535 return r;
322345fd 536
2d4c5cbc
LP
537 s = strjoin(k, " ", x, NULL);
538 if (!s)
539 return -ENOMEM;
540 break;
541 }
322345fd 542
8db0d2f5
ZJS
543 case DNS_TYPE_AAAA:
544 r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
2d4c5cbc
LP
545 if (r < 0)
546 return r;
322345fd 547
8db0d2f5 548 s = strjoin(k, " ", t, NULL);
2d4c5cbc
LP
549 if (!s)
550 return -ENOMEM;
551 break;
322345fd 552
2d4c5cbc
LP
553 case DNS_TYPE_SOA:
554 r = asprintf(&s, "%s %s %s %u %u %u %u %u",
555 k,
556 strna(rr->soa.mname),
557 strna(rr->soa.rname),
558 rr->soa.serial,
559 rr->soa.refresh,
560 rr->soa.retry,
561 rr->soa.expire,
562 rr->soa.minimum);
563 if (r < 0)
564 return -ENOMEM;
565 break;
566
946c7094
ZJS
567 case DNS_TYPE_MX:
568 r = asprintf(&s, "%s %u %s",
569 k,
570 rr->mx.priority,
571 rr->mx.exchange);
572 if (r < 0)
573 return -ENOMEM;
574 break;
575
8db0d2f5 576 case DNS_TYPE_LOC:
0dae31d4
ZJS
577 assert(rr->loc.version == 0);
578
8db0d2f5
ZJS
579 t = format_location(rr->loc.latitude,
580 rr->loc.longitude,
581 rr->loc.altitude,
582 rr->loc.size,
583 rr->loc.horiz_pre,
584 rr->loc.vert_pre);
585 if (!t)
0dae31d4
ZJS
586 return -ENOMEM;
587
8db0d2f5 588 s = strjoin(k, " ", t, NULL);
0dae31d4
ZJS
589 if (!s)
590 return -ENOMEM;
0dae31d4 591 break;
0dae31d4 592
8db0d2f5
ZJS
593 case DNS_TYPE_SSHFP:
594 t = hexmem(rr->sshfp.key, rr->sshfp.key_size);
595 if (!t)
42cc2eeb
LP
596 return -ENOMEM;
597
598 r = asprintf(&s, "%s %u %u %s",
599 k,
600 rr->sshfp.algorithm,
601 rr->sshfp.fptype,
8db0d2f5 602 t);
42cc2eeb
LP
603 if (r < 0)
604 return -ENOMEM;
605 break;
42cc2eeb 606
ff3d6560
ZJS
607 case DNS_TYPE_DNSKEY: {
608 const char *alg;
609
610 alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
611
8db0d2f5
ZJS
612 t = hexmem(rr->dnskey.key, rr->dnskey.key_size);
613 if (!t)
614 return -ENOMEM;
2d4c5cbc 615
ff3d6560 616 r = asprintf(&s, "%s %u 3 %.*s%.*u %s",
8db0d2f5
ZJS
617 k,
618 dnskey_to_flags(rr),
ff3d6560
ZJS
619 alg ? -1 : 0, alg,
620 alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
8db0d2f5
ZJS
621 t);
622 if (r < 0)
2d4c5cbc 623 return -ENOMEM;
8db0d2f5 624 break;
ff3d6560 625 }
2d4c5cbc 626
151226ab
ZJS
627 case DNS_TYPE_RRSIG: {
628 const char *type, *alg;
629
630 type = dns_type_to_string(rr->rrsig.type_covered);
631 alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
632
633 t = hexmem(rr->rrsig.signature, rr->rrsig.signature_size);
634 if (!t)
635 return -ENOMEM;
636
637 /* TYPE?? follows
638 * http://tools.ietf.org/html/rfc3597#section-5 */
639
640 r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %u %u %u %s %s",
641 k,
642 type ?: "TYPE",
643 type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
644 alg ? -1 : 0, alg,
645 alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
646 rr->rrsig.labels,
647 rr->rrsig.original_ttl,
648 rr->rrsig.expiration,
649 rr->rrsig.inception,
650 rr->rrsig.key_tag,
651 rr->rrsig.signer,
652 t);
653 if (r < 0)
654 return -ENOMEM;
655 break;
656 }
657
8db0d2f5
ZJS
658 default:
659 t = hexmem(rr->generic.data, rr->generic.size);
660 if (!t)
661 return -ENOMEM;
662
663 s = strjoin(k, " ", t, NULL);
2d4c5cbc
LP
664 if (!s)
665 return -ENOMEM;
666 break;
8db0d2f5 667 }
2d4c5cbc
LP
668
669 *ret = s;
670 return 0;
671}
322345fd 672
2d4c5cbc 673const char *dns_class_to_string(uint16_t class) {
322345fd 674
2d4c5cbc 675 switch (class) {
322345fd 676
2d4c5cbc
LP
677 case DNS_CLASS_IN:
678 return "IN";
322345fd 679
2d4c5cbc
LP
680 case DNS_CLASS_ANY:
681 return "ANY";
682 }
322345fd 683
2d4c5cbc
LP
684 return NULL;
685}
322345fd 686
2d4c5cbc
LP
687int dns_class_from_string(const char *s, uint16_t *class) {
688 assert(s);
689 assert(class);
690
691 if (strcaseeq(s, "IN"))
692 *class = DNS_CLASS_IN;
693 else if (strcaseeq(s, "ANY"))
694 *class = DNS_TYPE_ANY;
695 else
696 return -EINVAL;
322345fd 697
2d4c5cbc
LP
698 return 0;
699}