]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-rr.c
bus: prefix custom endpoints with "$UID-"
[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
d5099efc 136static unsigned long dns_resource_key_hash_func(const void *i, const uint8_t hash_key[HASH_KEY_SIZE]) {
322345fd
LP
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
d5099efc 147static int dns_resource_key_compare_func(const void *a, const void *b) {
322345fd
LP
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
d5099efc
MS
168const struct hash_ops dns_resource_key_hash_ops = {
169 .hash = dns_resource_key_hash_func,
170 .compare = dns_resource_key_compare_func
171};
172
2d4c5cbc
LP
173int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
174 char cbuf[DECIMAL_STR_MAX(uint16_t)], tbuf[DECIMAL_STR_MAX(uint16_t)];
175 const char *c, *t;
176 char *s;
177
178 c = dns_class_to_string(key->class);
179 if (!c) {
180 sprintf(cbuf, "%i", key->class);
181 c = cbuf;
182 }
183
184 t = dns_type_to_string(key->type);
185 if (!t){
186 sprintf(tbuf, "%i", key->type);
187 t = tbuf;
188 }
189
23432a1c 190 if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
2d4c5cbc
LP
191 return -ENOMEM;
192
193 *ret = s;
194 return 0;
195}
196
faa133f3 197DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
74b2466e
LP
198 DnsResourceRecord *rr;
199
200 rr = new0(DnsResourceRecord, 1);
201 if (!rr)
202 return NULL;
203
204 rr->n_ref = 1;
faa133f3
LP
205 rr->key = dns_resource_key_ref(key);
206
74b2466e
LP
207 return rr;
208}
209
8bf52d3d
LP
210DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
211 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
212
213 key = dns_resource_key_new(class, type, name);
214 if (!key)
215 return NULL;
216
217 return dns_resource_record_new(key);
218}
219
74b2466e
LP
220DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
221 if (!rr)
222 return NULL;
223
224 assert(rr->n_ref > 0);
225 rr->n_ref++;
226
227 return rr;
228}
229
230DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
231 if (!rr)
232 return NULL;
233
234 assert(rr->n_ref > 0);
235
236 if (rr->n_ref > 1) {
237 rr->n_ref--;
238 return NULL;
239 }
240
faa133f3 241 if (rr->key) {
9de3e329 242 switch(rr->key->type) {
9c92ce6d
LP
243
244 case DNS_TYPE_SRV:
245 free(rr->srv.name);
246 break;
247
9de3e329
ZJS
248 case DNS_TYPE_PTR:
249 case DNS_TYPE_NS:
250 case DNS_TYPE_CNAME:
8ac4e9e1 251 case DNS_TYPE_DNAME:
faa133f3 252 free(rr->ptr.name);
9de3e329 253 break;
9c92ce6d 254
9de3e329 255 case DNS_TYPE_HINFO:
faa133f3
LP
256 free(rr->hinfo.cpu);
257 free(rr->hinfo.os);
9de3e329 258 break;
9c92ce6d 259
9de3e329 260 case DNS_TYPE_TXT:
9c92ce6d 261 case DNS_TYPE_SPF:
2e276efc 262 strv_free(rr->txt.strings);
9de3e329 263 break;
9c92ce6d 264
9de3e329 265 case DNS_TYPE_SOA:
7e8e0422
LP
266 free(rr->soa.mname);
267 free(rr->soa.rname);
9de3e329 268 break;
9c92ce6d 269
9de3e329 270 case DNS_TYPE_MX:
946c7094 271 free(rr->mx.exchange);
9de3e329 272 break;
9c92ce6d 273
42cc2eeb
LP
274 case DNS_TYPE_SSHFP:
275 free(rr->sshfp.key);
276 break;
277
8db0d2f5
ZJS
278 case DNS_TYPE_DNSKEY:
279 free(rr->dnskey.key);
280 break;
281
151226ab
ZJS
282 case DNS_TYPE_RRSIG:
283 free(rr->rrsig.signer);
284 free(rr->rrsig.signature);
285 break;
286
0dae31d4 287 case DNS_TYPE_LOC:
9de3e329
ZJS
288 case DNS_TYPE_A:
289 case DNS_TYPE_AAAA:
290 break;
9c92ce6d 291
9de3e329 292 default:
faa133f3 293 free(rr->generic.data);
9de3e329 294 }
322345fd 295
faa133f3
LP
296 dns_resource_key_unref(rr->key);
297 }
322345fd 298
faa133f3 299 free(rr);
322345fd 300
322345fd
LP
301 return NULL;
302}
303
623a4c97
LP
304int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
305 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
306 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
307 _cleanup_free_ char *ptr = NULL;
308 int r;
309
310 assert(ret);
311 assert(address);
312 assert(hostname);
313
314 r = dns_name_reverse(family, address, &ptr);
315 if (r < 0)
316 return r;
317
318 key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
319 if (!key)
320 return -ENOMEM;
321
322 ptr = NULL;
323
324 rr = dns_resource_record_new(key);
325 if (!rr)
326 return -ENOMEM;
327
328 rr->ptr.name = strdup(hostname);
329 if (!rr->ptr.name)
330 return -ENOMEM;
331
332 *ret = rr;
333 rr = NULL;
334
335 return 0;
336}
337
322345fd
LP
338int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
339 int r;
340
341 assert(a);
342 assert(b);
343
faa133f3 344 r = dns_resource_key_equal(a->key, b->key);
322345fd
LP
345 if (r <= 0)
346 return r;
347
fd0b4602
LP
348 if (a->unparseable != b->unparseable)
349 return 0;
350
351 switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
2d4c5cbc 352
9c92ce6d
LP
353 case DNS_TYPE_SRV:
354 r = dns_name_equal(a->srv.name, b->srv.name);
355 if (r <= 0)
356 return r;
357
358 return a->srv.priority == b->srv.priority &&
359 a->srv.weight == b->srv.weight &&
360 a->srv.port == b->srv.port;
361
2d4c5cbc
LP
362 case DNS_TYPE_PTR:
363 case DNS_TYPE_NS:
364 case DNS_TYPE_CNAME:
8ac4e9e1 365 case DNS_TYPE_DNAME:
322345fd 366 return dns_name_equal(a->ptr.name, b->ptr.name);
2d4c5cbc
LP
367
368 case DNS_TYPE_HINFO:
369 return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
370 strcaseeq(a->hinfo.os, b->hinfo.os);
371
9de3e329 372 case DNS_TYPE_SPF: /* exactly the same as TXT */
2e276efc
ZJS
373 case DNS_TYPE_TXT: {
374 int i;
375
376 for (i = 0; a->txt.strings[i] || b->txt.strings[i]; i++)
377 if (!streq_ptr(a->txt.strings[i], b->txt.strings[i]))
378 return false;
379 return true;
380 }
381
2d4c5cbc 382 case DNS_TYPE_A:
322345fd 383 return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
2d4c5cbc
LP
384
385 case DNS_TYPE_AAAA:
322345fd 386 return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
2d4c5cbc
LP
387
388 case DNS_TYPE_SOA:
7e8e0422
LP
389 r = dns_name_equal(a->soa.mname, b->soa.mname);
390 if (r <= 0)
391 return r;
392 r = dns_name_equal(a->soa.rname, b->soa.rname);
393 if (r <= 0)
394 return r;
395
396 return a->soa.serial == b->soa.serial &&
397 a->soa.refresh == b->soa.refresh &&
398 a->soa.retry == b->soa.retry &&
399 a->soa.expire == b->soa.expire &&
400 a->soa.minimum == b->soa.minimum;
9c92ce6d 401
946c7094
ZJS
402 case DNS_TYPE_MX:
403 if (a->mx.priority != b->mx.priority)
404 return 0;
405
406 return dns_name_equal(a->mx.exchange, b->mx.exchange);
407
0dae31d4
ZJS
408 case DNS_TYPE_LOC:
409 assert(a->loc.version == b->loc.version);
410
411 return a->loc.size == b->loc.size &&
412 a->loc.horiz_pre == b->loc.horiz_pre &&
413 a->loc.vert_pre == b->loc.vert_pre &&
414 a->loc.latitude == b->loc.latitude &&
415 a->loc.longitude == b->loc.longitude &&
416 a->loc.altitude == b->loc.altitude;
417
42cc2eeb
LP
418 case DNS_TYPE_SSHFP:
419 return a->sshfp.algorithm == b->sshfp.algorithm &&
420 a->sshfp.fptype == b->sshfp.fptype &&
421 a->sshfp.key_size == b->sshfp.key_size &&
422 memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
423
8db0d2f5
ZJS
424 case DNS_TYPE_DNSKEY:
425 return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
426 a->dnskey.sep_flag == b->dnskey.sep_flag &&
427 a->dnskey.algorithm == b->dnskey.algorithm &&
428 a->dnskey.key_size == b->dnskey.key_size &&
429 memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
430
151226ab
ZJS
431 case DNS_TYPE_RRSIG:
432 /* do the fast comparisons first */
03664a62
LN
433 if (a->rrsig.type_covered != b->rrsig.type_covered ||
434 a->rrsig.algorithm != b->rrsig.algorithm ||
435 a->rrsig.labels != b->rrsig.labels ||
436 a->rrsig.original_ttl != b->rrsig.original_ttl ||
437 a->rrsig.expiration != b->rrsig.expiration ||
438 a->rrsig.inception != b->rrsig.inception ||
439 a->rrsig.key_tag != b->rrsig.key_tag ||
151226ab
ZJS
440 a->rrsig.signature_size != b->rrsig.signature_size ||
441 memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
442 return false;
443
444 return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
445
2d4c5cbc 446 default:
322345fd
LP
447 return a->generic.size == b->generic.size &&
448 memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
2d4c5cbc 449 }
322345fd
LP
450}
451
0dae31d4
ZJS
452static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
453 uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
454 char *s;
455 char NS = latitude >= 1U<<31 ? 'N' : 'S';
456 char EW = longitude >= 1U<<31 ? 'E' : 'W';
457
458 int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
459 int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
460 double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
461 double siz = (size >> 4) * exp10((double) (size & 0xF));
462 double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
463 double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
464
465 if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
466 (lat / 60000 / 60),
467 (lat / 60000) % 60,
468 (lat % 60000) / 1000.,
469 NS,
470 (lon / 60000 / 60),
471 (lon / 60000) % 60,
472 (lon % 60000) / 1000.,
473 EW,
474 alt / 100.,
475 siz / 100.,
476 hor / 100.,
477 ver / 100.) < 0)
478 return NULL;
479
480 return s;
481}
482
2d4c5cbc 483int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
8db0d2f5 484 _cleanup_free_ char *k = NULL, *t = NULL;
2d4c5cbc
LP
485 char *s;
486 int r;
322345fd 487
2d4c5cbc 488 assert(rr);
322345fd 489
2d4c5cbc
LP
490 r = dns_resource_key_to_string(rr->key, &k);
491 if (r < 0)
492 return r;
322345fd 493
0dae31d4 494 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
322345fd 495
9c92ce6d
LP
496 case DNS_TYPE_SRV:
497 r = asprintf(&s, "%s %u %u %u %s",
498 k,
499 rr->srv.priority,
500 rr->srv.weight,
501 rr->srv.port,
502 strna(rr->srv.name));
503 if (r < 0)
504 return -ENOMEM;
505 break;
506
2d4c5cbc
LP
507 case DNS_TYPE_PTR:
508 case DNS_TYPE_NS:
509 case DNS_TYPE_CNAME:
8ac4e9e1 510 case DNS_TYPE_DNAME:
2d4c5cbc
LP
511 s = strjoin(k, " ", rr->ptr.name, NULL);
512 if (!s)
513 return -ENOMEM;
322345fd 514
2d4c5cbc 515 break;
322345fd 516
2d4c5cbc
LP
517 case DNS_TYPE_HINFO:
518 s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL);
519 if (!s)
520 return -ENOMEM;
521 break;
322345fd 522
9de3e329 523 case DNS_TYPE_SPF: /* exactly the same as TXT */
8db0d2f5 524 case DNS_TYPE_TXT:
2e276efc
ZJS
525 t = strv_join_quoted(rr->txt.strings);
526 if (!t)
527 return -ENOMEM;
528
529 s = strjoin(k, " ", t, NULL);
530 if (!s)
531 return -ENOMEM;
532
533 break;
2e276efc 534
2d4c5cbc
LP
535 case DNS_TYPE_A: {
536 _cleanup_free_ char *x = NULL;
322345fd 537
2d4c5cbc
LP
538 r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
539 if (r < 0)
540 return r;
322345fd 541
2d4c5cbc
LP
542 s = strjoin(k, " ", x, NULL);
543 if (!s)
544 return -ENOMEM;
545 break;
546 }
322345fd 547
8db0d2f5
ZJS
548 case DNS_TYPE_AAAA:
549 r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
2d4c5cbc
LP
550 if (r < 0)
551 return r;
322345fd 552
8db0d2f5 553 s = strjoin(k, " ", t, NULL);
2d4c5cbc
LP
554 if (!s)
555 return -ENOMEM;
556 break;
322345fd 557
2d4c5cbc
LP
558 case DNS_TYPE_SOA:
559 r = asprintf(&s, "%s %s %s %u %u %u %u %u",
560 k,
561 strna(rr->soa.mname),
562 strna(rr->soa.rname),
563 rr->soa.serial,
564 rr->soa.refresh,
565 rr->soa.retry,
566 rr->soa.expire,
567 rr->soa.minimum);
568 if (r < 0)
569 return -ENOMEM;
570 break;
571
946c7094
ZJS
572 case DNS_TYPE_MX:
573 r = asprintf(&s, "%s %u %s",
574 k,
575 rr->mx.priority,
576 rr->mx.exchange);
577 if (r < 0)
578 return -ENOMEM;
579 break;
580
8db0d2f5 581 case DNS_TYPE_LOC:
0dae31d4
ZJS
582 assert(rr->loc.version == 0);
583
8db0d2f5
ZJS
584 t = format_location(rr->loc.latitude,
585 rr->loc.longitude,
586 rr->loc.altitude,
587 rr->loc.size,
588 rr->loc.horiz_pre,
589 rr->loc.vert_pre);
590 if (!t)
0dae31d4
ZJS
591 return -ENOMEM;
592
8db0d2f5 593 s = strjoin(k, " ", t, NULL);
0dae31d4
ZJS
594 if (!s)
595 return -ENOMEM;
0dae31d4 596 break;
0dae31d4 597
8db0d2f5
ZJS
598 case DNS_TYPE_SSHFP:
599 t = hexmem(rr->sshfp.key, rr->sshfp.key_size);
600 if (!t)
42cc2eeb
LP
601 return -ENOMEM;
602
603 r = asprintf(&s, "%s %u %u %s",
604 k,
605 rr->sshfp.algorithm,
606 rr->sshfp.fptype,
8db0d2f5 607 t);
42cc2eeb
LP
608 if (r < 0)
609 return -ENOMEM;
610 break;
42cc2eeb 611
ff3d6560
ZJS
612 case DNS_TYPE_DNSKEY: {
613 const char *alg;
614
615 alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
616
8db0d2f5
ZJS
617 t = hexmem(rr->dnskey.key, rr->dnskey.key_size);
618 if (!t)
619 return -ENOMEM;
2d4c5cbc 620
ff3d6560 621 r = asprintf(&s, "%s %u 3 %.*s%.*u %s",
8db0d2f5
ZJS
622 k,
623 dnskey_to_flags(rr),
ff3d6560
ZJS
624 alg ? -1 : 0, alg,
625 alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
8db0d2f5
ZJS
626 t);
627 if (r < 0)
2d4c5cbc 628 return -ENOMEM;
8db0d2f5 629 break;
ff3d6560 630 }
2d4c5cbc 631
151226ab
ZJS
632 case DNS_TYPE_RRSIG: {
633 const char *type, *alg;
634
635 type = dns_type_to_string(rr->rrsig.type_covered);
636 alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
637
638 t = hexmem(rr->rrsig.signature, rr->rrsig.signature_size);
639 if (!t)
640 return -ENOMEM;
641
642 /* TYPE?? follows
643 * http://tools.ietf.org/html/rfc3597#section-5 */
644
645 r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %u %u %u %s %s",
646 k,
647 type ?: "TYPE",
648 type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
649 alg ? -1 : 0, alg,
650 alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
651 rr->rrsig.labels,
652 rr->rrsig.original_ttl,
653 rr->rrsig.expiration,
654 rr->rrsig.inception,
655 rr->rrsig.key_tag,
656 rr->rrsig.signer,
657 t);
658 if (r < 0)
659 return -ENOMEM;
660 break;
661 }
662
8db0d2f5
ZJS
663 default:
664 t = hexmem(rr->generic.data, rr->generic.size);
665 if (!t)
666 return -ENOMEM;
667
668 s = strjoin(k, " ", t, NULL);
2d4c5cbc
LP
669 if (!s)
670 return -ENOMEM;
671 break;
8db0d2f5 672 }
2d4c5cbc
LP
673
674 *ret = s;
675 return 0;
676}
322345fd 677
2d4c5cbc 678const char *dns_class_to_string(uint16_t class) {
322345fd 679
2d4c5cbc 680 switch (class) {
322345fd 681
2d4c5cbc
LP
682 case DNS_CLASS_IN:
683 return "IN";
322345fd 684
2d4c5cbc
LP
685 case DNS_CLASS_ANY:
686 return "ANY";
687 }
322345fd 688
2d4c5cbc
LP
689 return NULL;
690}
322345fd 691
2d4c5cbc
LP
692int dns_class_from_string(const char *s, uint16_t *class) {
693 assert(s);
694 assert(class);
695
696 if (strcaseeq(s, "IN"))
697 *class = DNS_CLASS_IN;
698 else if (strcaseeq(s, "ANY"))
699 *class = DNS_TYPE_ANY;
700 else
701 return -EINVAL;
322345fd 702
2d4c5cbc
LP
703 return 0;
704}