162ac0c33Sjakob /*
262ac0c33Sjakob * rdata.c -- RDATA conversion functions.
362ac0c33Sjakob *
4dd5b221eSsthen * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
562ac0c33Sjakob *
662ac0c33Sjakob * See LICENSE for the license.
762ac0c33Sjakob *
862ac0c33Sjakob */
962ac0c33Sjakob
10d11a62c8Ssthen #include "config.h"
1162ac0c33Sjakob
1262ac0c33Sjakob #include <sys/types.h>
1362ac0c33Sjakob #include <sys/socket.h>
1462ac0c33Sjakob #include <netinet/in.h>
1562ac0c33Sjakob #include <arpa/inet.h>
1662ac0c33Sjakob #include <ctype.h>
1762ac0c33Sjakob #include <netdb.h>
1862ac0c33Sjakob #include <stdlib.h>
1962ac0c33Sjakob #include <string.h>
2062ac0c33Sjakob #ifdef HAVE_STRINGS_H
2162ac0c33Sjakob #include <strings.h>
2262ac0c33Sjakob #endif
2362ac0c33Sjakob
2462ac0c33Sjakob #include "rdata.h"
2562ac0c33Sjakob #include "zonec.h"
2662ac0c33Sjakob
2762ac0c33Sjakob /* Taken from RFC 4398, section 2.1. */
2862ac0c33Sjakob lookup_table_type dns_certificate_types[] = {
2962ac0c33Sjakob /* 0 Reserved */
3062ac0c33Sjakob { 1, "PKIX" }, /* X.509 as per PKIX */
3162ac0c33Sjakob { 2, "SPKI" }, /* SPKI cert */
3262ac0c33Sjakob { 3, "PGP" }, /* OpenPGP packet */
3362ac0c33Sjakob { 4, "IPKIX" }, /* The URL of an X.509 data object */
3462ac0c33Sjakob { 5, "ISPKI" }, /* The URL of an SPKI certificate */
3562ac0c33Sjakob { 6, "IPGP" }, /* The fingerprint and URL of an OpenPGP packet */
3662ac0c33Sjakob { 7, "ACPKIX" }, /* Attribute Certificate */
3762ac0c33Sjakob { 8, "IACPKIX" }, /* The URL of an Attribute Certificate */
3862ac0c33Sjakob { 253, "URI" }, /* URI private */
3962ac0c33Sjakob { 254, "OID" }, /* OID private */
4062ac0c33Sjakob /* 255 Reserved */
4162ac0c33Sjakob /* 256-65279 Available for IANA assignment */
4262ac0c33Sjakob /* 65280-65534 Experimental */
4362ac0c33Sjakob /* 65535 Reserved */
4462ac0c33Sjakob { 0, NULL }
4562ac0c33Sjakob };
4662ac0c33Sjakob
4762ac0c33Sjakob /* Taken from RFC 2535, section 7. */
4862ac0c33Sjakob lookup_table_type dns_algorithms[] = {
4962ac0c33Sjakob { 1, "RSAMD5" }, /* RFC 2537 */
5062ac0c33Sjakob { 2, "DH" }, /* RFC 2539 */
5162ac0c33Sjakob { 3, "DSA" }, /* RFC 2536 */
5262ac0c33Sjakob { 4, "ECC" },
5362ac0c33Sjakob { 5, "RSASHA1" }, /* RFC 3110 */
54d11a62c8Ssthen { 6, "DSA-NSEC3-SHA1" }, /* RFC 5155 */
55d11a62c8Ssthen { 7, "RSASHA1-NSEC3-SHA1" }, /* RFC 5155 */
56d11a62c8Ssthen { 8, "RSASHA256" }, /* RFC 5702 */
57d11a62c8Ssthen { 10, "RSASHA512" }, /* RFC 5702 */
58d11a62c8Ssthen { 12, "ECC-GOST" }, /* RFC 5933 */
59d11a62c8Ssthen { 13, "ECDSAP256SHA256" }, /* RFC 6605 */
60d11a62c8Ssthen { 14, "ECDSAP384SHA384" }, /* RFC 6605 */
61db7d0d02Sflorian { 15, "ED25519" }, /* RFC 8080 */
62db7d0d02Sflorian { 16, "ED448" }, /* RFC 8080 */
6362ac0c33Sjakob { 252, "INDIRECT" },
6462ac0c33Sjakob { 253, "PRIVATEDNS" },
6562ac0c33Sjakob { 254, "PRIVATEOID" },
6662ac0c33Sjakob { 0, NULL }
6762ac0c33Sjakob };
6862ac0c33Sjakob
69063644e9Sflorian const char *svcparamkey_strs[] = {
70063644e9Sflorian "mandatory", "alpn", "no-default-alpn", "port",
71*de04d855Ssthen "ipv4hint", "ech", "ipv6hint", "dohpath"
72063644e9Sflorian };
73063644e9Sflorian
7462ac0c33Sjakob typedef int (*rdata_to_string_type)(buffer_type *output,
7562ac0c33Sjakob rdata_atom_type rdata,
7662ac0c33Sjakob rr_type *rr);
7762ac0c33Sjakob
7862ac0c33Sjakob static int
rdata_dname_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))7962ac0c33Sjakob rdata_dname_to_string(buffer_type *output, rdata_atom_type rdata,
8062ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
8162ac0c33Sjakob {
8262ac0c33Sjakob buffer_printf(output,
8362ac0c33Sjakob "%s",
8462ac0c33Sjakob dname_to_string(domain_dname(rdata_atom_domain(rdata)),
8562ac0c33Sjakob NULL));
8662ac0c33Sjakob return 1;
8762ac0c33Sjakob }
8862ac0c33Sjakob
8962ac0c33Sjakob static int
rdata_dns_name_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))9062ac0c33Sjakob rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata,
9162ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
9262ac0c33Sjakob {
9362ac0c33Sjakob const uint8_t *data = rdata_atom_data(rdata);
9462ac0c33Sjakob size_t offset = 0;
9562ac0c33Sjakob uint8_t length = data[offset];
9662ac0c33Sjakob size_t i;
9762ac0c33Sjakob
9862ac0c33Sjakob while (length > 0)
9962ac0c33Sjakob {
10062ac0c33Sjakob if (offset) /* concat label */
10162ac0c33Sjakob buffer_printf(output, ".");
10262ac0c33Sjakob
10362ac0c33Sjakob for (i = 1; i <= length; ++i) {
104d65f3523Sjakob uint8_t ch = data[i+offset];
105d65f3523Sjakob
106d65f3523Sjakob if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') {
107d65f3523Sjakob buffer_printf(output, "\\%c", (char) ch);
10882cafdebSmillert } else if (!isgraph((unsigned char) ch)) {
109d65f3523Sjakob buffer_printf(output, "\\%03u", (unsigned int) ch);
11082cafdebSmillert } else if (isprint((unsigned char) ch)) {
111d65f3523Sjakob buffer_printf(output, "%c", (char) ch);
112d65f3523Sjakob } else {
113d65f3523Sjakob buffer_printf(output, "\\%03u", (unsigned int) ch);
114d65f3523Sjakob }
11562ac0c33Sjakob }
11662ac0c33Sjakob /* next label */
11762ac0c33Sjakob offset = offset+length+1;
11862ac0c33Sjakob length = data[offset];
11962ac0c33Sjakob }
12062ac0c33Sjakob
12162ac0c33Sjakob /* root label */
12262ac0c33Sjakob buffer_printf(output, ".");
12362ac0c33Sjakob return 1;
12462ac0c33Sjakob }
12562ac0c33Sjakob
12662ac0c33Sjakob static int
rdata_text_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))12762ac0c33Sjakob rdata_text_to_string(buffer_type *output, rdata_atom_type rdata,
12862ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
12962ac0c33Sjakob {
13062ac0c33Sjakob const uint8_t *data = rdata_atom_data(rdata);
13162ac0c33Sjakob uint8_t length = data[0];
13262ac0c33Sjakob size_t i;
13362ac0c33Sjakob
13462ac0c33Sjakob buffer_printf(output, "\"");
13562ac0c33Sjakob for (i = 1; i <= length; ++i) {
13662ac0c33Sjakob char ch = (char) data[i];
13782cafdebSmillert if (isprint((unsigned char)ch)) {
13862ac0c33Sjakob if (ch == '"' || ch == '\\') {
13962ac0c33Sjakob buffer_printf(output, "\\");
14062ac0c33Sjakob }
14162ac0c33Sjakob buffer_printf(output, "%c", ch);
14262ac0c33Sjakob } else {
1435bcb494bSjakob buffer_printf(output, "\\%03u", (unsigned) data[i]);
14462ac0c33Sjakob }
14562ac0c33Sjakob }
14662ac0c33Sjakob buffer_printf(output, "\"");
14762ac0c33Sjakob return 1;
14862ac0c33Sjakob }
14962ac0c33Sjakob
15062ac0c33Sjakob static int
rdata_texts_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))151f72b2965Sjakob rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata,
152f72b2965Sjakob rr_type* ATTR_UNUSED(rr))
153f72b2965Sjakob {
154f72b2965Sjakob uint16_t pos = 0;
155f72b2965Sjakob const uint8_t *data = rdata_atom_data(rdata);
156f72b2965Sjakob uint16_t length = rdata_atom_size(rdata);
157f72b2965Sjakob size_t i;
158f72b2965Sjakob
159f72b2965Sjakob while (pos < length && pos + data[pos] < length) {
160f72b2965Sjakob buffer_printf(output, "\"");
161f72b2965Sjakob for (i = 1; i <= data[pos]; ++i) {
162f72b2965Sjakob char ch = (char) data[pos + i];
16382cafdebSmillert if (isprint((unsigned char)ch)) {
164f72b2965Sjakob if (ch == '"' || ch == '\\') {
165f72b2965Sjakob buffer_printf(output, "\\");
166f72b2965Sjakob }
167f72b2965Sjakob buffer_printf(output, "%c", ch);
168f72b2965Sjakob } else {
1695bcb494bSjakob buffer_printf(output, "\\%03u", (unsigned) data[pos+i]);
170f72b2965Sjakob }
171f72b2965Sjakob }
172f72b2965Sjakob pos += data[pos]+1;
173f72b2965Sjakob buffer_printf(output, pos < length?"\" ":"\"");
174f72b2965Sjakob }
175f72b2965Sjakob return 1;
176f72b2965Sjakob }
177f72b2965Sjakob
178f72b2965Sjakob static int
rdata_long_text_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))179a302926fSbrad rdata_long_text_to_string(buffer_type *output, rdata_atom_type rdata,
180a302926fSbrad rr_type* ATTR_UNUSED(rr))
181a302926fSbrad {
182a302926fSbrad const uint8_t *data = rdata_atom_data(rdata);
183a302926fSbrad uint16_t length = rdata_atom_size(rdata);
184a302926fSbrad size_t i;
185a302926fSbrad
186a302926fSbrad buffer_printf(output, "\"");
187a302926fSbrad for (i = 0; i < length; ++i) {
188a302926fSbrad char ch = (char) data[i];
18982cafdebSmillert if (isprint((unsigned char)ch)) {
190a302926fSbrad if (ch == '"' || ch == '\\') {
191a302926fSbrad buffer_printf(output, "\\");
192a302926fSbrad }
193a302926fSbrad buffer_printf(output, "%c", ch);
194a302926fSbrad } else {
195a302926fSbrad buffer_printf(output, "\\%03u", (unsigned) data[i]);
196a302926fSbrad }
197a302926fSbrad }
198a302926fSbrad buffer_printf(output, "\"");
199a302926fSbrad return 1;
200a302926fSbrad }
201a302926fSbrad
202a302926fSbrad static int
rdata_tag_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))203a302926fSbrad rdata_tag_to_string(buffer_type *output, rdata_atom_type rdata,
204a302926fSbrad rr_type* ATTR_UNUSED(rr))
205a302926fSbrad {
206a302926fSbrad const uint8_t *data = rdata_atom_data(rdata);
207a302926fSbrad uint8_t length = data[0];
208a302926fSbrad size_t i;
209a302926fSbrad for (i = 1; i <= length; ++i) {
210a302926fSbrad char ch = (char) data[i];
21182cafdebSmillert if (isdigit((unsigned char)ch) || islower((unsigned char)ch))
212a302926fSbrad buffer_printf(output, "%c", ch);
213a302926fSbrad else return 0;
214a302926fSbrad }
215a302926fSbrad return 1;
216a302926fSbrad }
217a302926fSbrad
218a302926fSbrad static int
rdata_byte_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))21962ac0c33Sjakob rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata,
22062ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
22162ac0c33Sjakob {
22262ac0c33Sjakob uint8_t data = *rdata_atom_data(rdata);
22362ac0c33Sjakob buffer_printf(output, "%lu", (unsigned long) data);
22462ac0c33Sjakob return 1;
22562ac0c33Sjakob }
22662ac0c33Sjakob
22762ac0c33Sjakob static int
rdata_short_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))22862ac0c33Sjakob rdata_short_to_string(buffer_type *output, rdata_atom_type rdata,
22962ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
23062ac0c33Sjakob {
23162ac0c33Sjakob uint16_t data = read_uint16(rdata_atom_data(rdata));
23262ac0c33Sjakob buffer_printf(output, "%lu", (unsigned long) data);
23362ac0c33Sjakob return 1;
23462ac0c33Sjakob }
23562ac0c33Sjakob
23662ac0c33Sjakob static int
rdata_long_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))23762ac0c33Sjakob rdata_long_to_string(buffer_type *output, rdata_atom_type rdata,
23862ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
23962ac0c33Sjakob {
24062ac0c33Sjakob uint32_t data = read_uint32(rdata_atom_data(rdata));
24162ac0c33Sjakob buffer_printf(output, "%lu", (unsigned long) data);
24262ac0c33Sjakob return 1;
24362ac0c33Sjakob }
24462ac0c33Sjakob
24562ac0c33Sjakob static int
rdata_a_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))24662ac0c33Sjakob rdata_a_to_string(buffer_type *output, rdata_atom_type rdata,
24762ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
24862ac0c33Sjakob {
24962ac0c33Sjakob int result = 0;
25062ac0c33Sjakob char str[200];
25162ac0c33Sjakob if (inet_ntop(AF_INET, rdata_atom_data(rdata), str, sizeof(str))) {
25262ac0c33Sjakob buffer_printf(output, "%s", str);
25362ac0c33Sjakob result = 1;
25462ac0c33Sjakob }
25562ac0c33Sjakob return result;
25662ac0c33Sjakob }
25762ac0c33Sjakob
25862ac0c33Sjakob static int
rdata_aaaa_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))25962ac0c33Sjakob rdata_aaaa_to_string(buffer_type *output, rdata_atom_type rdata,
26062ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
26162ac0c33Sjakob {
26262ac0c33Sjakob int result = 0;
26362ac0c33Sjakob char str[200];
26462ac0c33Sjakob if (inet_ntop(AF_INET6, rdata_atom_data(rdata), str, sizeof(str))) {
26562ac0c33Sjakob buffer_printf(output, "%s", str);
26662ac0c33Sjakob result = 1;
26762ac0c33Sjakob }
26862ac0c33Sjakob return result;
26962ac0c33Sjakob }
27062ac0c33Sjakob
27162ac0c33Sjakob static int
rdata_ilnp64_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))27275343be4Ssthen rdata_ilnp64_to_string(buffer_type *output, rdata_atom_type rdata,
27375343be4Ssthen rr_type* ATTR_UNUSED(rr))
27475343be4Ssthen {
27575343be4Ssthen uint8_t* data = rdata_atom_data(rdata);
27675343be4Ssthen uint16_t a1 = read_uint16(data);
27775343be4Ssthen uint16_t a2 = read_uint16(data+2);
27875343be4Ssthen uint16_t a3 = read_uint16(data+4);
27975343be4Ssthen uint16_t a4 = read_uint16(data+6);
28075343be4Ssthen
28175343be4Ssthen buffer_printf(output, "%.4x:%.4x:%.4x:%.4x", a1, a2, a3, a4);
28275343be4Ssthen return 1;
28375343be4Ssthen }
28475343be4Ssthen
2859c620270Ssthen static int
rdata_eui48_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))2869c620270Ssthen rdata_eui48_to_string(buffer_type *output, rdata_atom_type rdata,
2879c620270Ssthen rr_type* ATTR_UNUSED(rr))
2889c620270Ssthen {
2899c620270Ssthen uint8_t* data = rdata_atom_data(rdata);
2909c620270Ssthen uint8_t a1 = data[0];
2919c620270Ssthen uint8_t a2 = data[1];
2929c620270Ssthen uint8_t a3 = data[2];
2939c620270Ssthen uint8_t a4 = data[3];
2949c620270Ssthen uint8_t a5 = data[4];
2959c620270Ssthen uint8_t a6 = data[5];
2969c620270Ssthen
2979c620270Ssthen buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
2989c620270Ssthen a1, a2, a3, a4, a5, a6);
2999c620270Ssthen return 1;
3009c620270Ssthen }
3019c620270Ssthen
3029c620270Ssthen static int
rdata_eui64_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))3039c620270Ssthen rdata_eui64_to_string(buffer_type *output, rdata_atom_type rdata,
3049c620270Ssthen rr_type* ATTR_UNUSED(rr))
3059c620270Ssthen {
3069c620270Ssthen uint8_t* data = rdata_atom_data(rdata);
3079c620270Ssthen uint8_t a1 = data[0];
3089c620270Ssthen uint8_t a2 = data[1];
3099c620270Ssthen uint8_t a3 = data[2];
3109c620270Ssthen uint8_t a4 = data[3];
3119c620270Ssthen uint8_t a5 = data[4];
3129c620270Ssthen uint8_t a6 = data[5];
3139c620270Ssthen uint8_t a7 = data[6];
3149c620270Ssthen uint8_t a8 = data[7];
3159c620270Ssthen
3169c620270Ssthen buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
3179c620270Ssthen a1, a2, a3, a4, a5, a6, a7, a8);
3189c620270Ssthen return 1;
3199c620270Ssthen }
3209c620270Ssthen
32175343be4Ssthen static int
rdata_rrtype_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))32262ac0c33Sjakob rdata_rrtype_to_string(buffer_type *output, rdata_atom_type rdata,
32362ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
32462ac0c33Sjakob {
32562ac0c33Sjakob uint16_t type = read_uint16(rdata_atom_data(rdata));
32662ac0c33Sjakob buffer_printf(output, "%s", rrtype_to_string(type));
32762ac0c33Sjakob return 1;
32862ac0c33Sjakob }
32962ac0c33Sjakob
33062ac0c33Sjakob static int
rdata_algorithm_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))33162ac0c33Sjakob rdata_algorithm_to_string(buffer_type *output, rdata_atom_type rdata,
33262ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
33362ac0c33Sjakob {
33462ac0c33Sjakob uint8_t id = *rdata_atom_data(rdata);
33562ac0c33Sjakob buffer_printf(output, "%u", (unsigned) id);
33662ac0c33Sjakob return 1;
33762ac0c33Sjakob }
33862ac0c33Sjakob
33962ac0c33Sjakob static int
rdata_certificate_type_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))34062ac0c33Sjakob rdata_certificate_type_to_string(buffer_type *output, rdata_atom_type rdata,
34162ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
34262ac0c33Sjakob {
34362ac0c33Sjakob uint16_t id = read_uint16(rdata_atom_data(rdata));
34462ac0c33Sjakob lookup_table_type *type
34562ac0c33Sjakob = lookup_by_id(dns_certificate_types, id);
34662ac0c33Sjakob if (type) {
34762ac0c33Sjakob buffer_printf(output, "%s", type->name);
34862ac0c33Sjakob } else {
34962ac0c33Sjakob buffer_printf(output, "%u", (unsigned) id);
35062ac0c33Sjakob }
35162ac0c33Sjakob return 1;
35262ac0c33Sjakob }
35362ac0c33Sjakob
35462ac0c33Sjakob static int
rdata_period_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))35562ac0c33Sjakob rdata_period_to_string(buffer_type *output, rdata_atom_type rdata,
35662ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
35762ac0c33Sjakob {
35862ac0c33Sjakob uint32_t period = read_uint32(rdata_atom_data(rdata));
35962ac0c33Sjakob buffer_printf(output, "%lu", (unsigned long) period);
36062ac0c33Sjakob return 1;
36162ac0c33Sjakob }
36262ac0c33Sjakob
36362ac0c33Sjakob static int
rdata_time_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))36462ac0c33Sjakob rdata_time_to_string(buffer_type *output, rdata_atom_type rdata,
36562ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
36662ac0c33Sjakob {
36762ac0c33Sjakob int result = 0;
36862ac0c33Sjakob time_t time = (time_t) read_uint32(rdata_atom_data(rdata));
36962ac0c33Sjakob struct tm *tm = gmtime(&time);
37062ac0c33Sjakob char buf[15];
37162ac0c33Sjakob if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tm)) {
37262ac0c33Sjakob buffer_printf(output, "%s", buf);
37362ac0c33Sjakob result = 1;
37462ac0c33Sjakob }
37562ac0c33Sjakob return result;
37662ac0c33Sjakob }
37762ac0c33Sjakob
37862ac0c33Sjakob static int
rdata_base32_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))37962ac0c33Sjakob rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata,
38062ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
38162ac0c33Sjakob {
38262ac0c33Sjakob int length;
38362ac0c33Sjakob size_t size = rdata_atom_size(rdata);
38462ac0c33Sjakob if(size == 0) {
38562ac0c33Sjakob buffer_write(output, "-", 1);
38662ac0c33Sjakob return 1;
38762ac0c33Sjakob }
38862ac0c33Sjakob size -= 1; /* remove length byte from count */
38962ac0c33Sjakob buffer_reserve(output, size * 2 + 1);
39062ac0c33Sjakob length = b32_ntop(rdata_atom_data(rdata)+1, size,
39162ac0c33Sjakob (char *) buffer_current(output), size * 2);
39262ac0c33Sjakob if (length > 0) {
39362ac0c33Sjakob buffer_skip(output, length);
39462ac0c33Sjakob }
39562ac0c33Sjakob return length != -1;
39662ac0c33Sjakob }
39762ac0c33Sjakob
39862ac0c33Sjakob static int
rdata_base64_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))39962ac0c33Sjakob rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata,
40062ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
40162ac0c33Sjakob {
40262ac0c33Sjakob int length;
40362ac0c33Sjakob size_t size = rdata_atom_size(rdata);
404fb800cb5Sflorian if(size == 0) {
405fb800cb5Sflorian /* single zero represents empty buffer */
406fb800cb5Sflorian buffer_write(output, "0", 1);
4075bcb494bSjakob return 1;
408fb800cb5Sflorian }
40962ac0c33Sjakob buffer_reserve(output, size * 2 + 1);
41072628ec9Ssthen length = __b64_ntop(rdata_atom_data(rdata), size,
41162ac0c33Sjakob (char *) buffer_current(output), size * 2);
41262ac0c33Sjakob if (length > 0) {
41362ac0c33Sjakob buffer_skip(output, length);
41462ac0c33Sjakob }
41562ac0c33Sjakob return length != -1;
41662ac0c33Sjakob }
41762ac0c33Sjakob
41862ac0c33Sjakob static void
hex_to_string(buffer_type * output,const uint8_t * data,size_t size)41962ac0c33Sjakob hex_to_string(buffer_type *output, const uint8_t *data, size_t size)
42062ac0c33Sjakob {
42162ac0c33Sjakob static const char hexdigits[] = {
42262ac0c33Sjakob '0', '1', '2', '3', '4', '5', '6', '7',
42362ac0c33Sjakob '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
42462ac0c33Sjakob };
42562ac0c33Sjakob size_t i;
42662ac0c33Sjakob
42762ac0c33Sjakob buffer_reserve(output, size * 2);
42862ac0c33Sjakob for (i = 0; i < size; ++i) {
42962ac0c33Sjakob uint8_t octet = *data++;
43062ac0c33Sjakob buffer_write_u8(output, hexdigits[octet >> 4]);
43162ac0c33Sjakob buffer_write_u8(output, hexdigits[octet & 0x0f]);
43262ac0c33Sjakob }
43362ac0c33Sjakob }
43462ac0c33Sjakob
43562ac0c33Sjakob static int
rdata_hex_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))43662ac0c33Sjakob rdata_hex_to_string(buffer_type *output, rdata_atom_type rdata,
43762ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
43862ac0c33Sjakob {
439fb800cb5Sflorian if(rdata_atom_size(rdata) == 0) {
440fb800cb5Sflorian /* single zero represents empty buffer, such as CDS deletes */
441fb800cb5Sflorian buffer_printf(output, "0");
442fb800cb5Sflorian } else {
44362ac0c33Sjakob hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
444fb800cb5Sflorian }
44562ac0c33Sjakob return 1;
44662ac0c33Sjakob }
44762ac0c33Sjakob
44862ac0c33Sjakob static int
rdata_hexlen_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))44962ac0c33Sjakob rdata_hexlen_to_string(buffer_type *output, rdata_atom_type rdata,
45062ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
45162ac0c33Sjakob {
45262ac0c33Sjakob if(rdata_atom_size(rdata) <= 1) {
45362ac0c33Sjakob /* NSEC3 salt hex can be empty */
45462ac0c33Sjakob buffer_printf(output, "-");
45562ac0c33Sjakob return 1;
45662ac0c33Sjakob }
45762ac0c33Sjakob hex_to_string(output, rdata_atom_data(rdata)+1, rdata_atom_size(rdata)-1);
45862ac0c33Sjakob return 1;
45962ac0c33Sjakob }
46062ac0c33Sjakob
46162ac0c33Sjakob static int
rdata_nsap_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))46262ac0c33Sjakob rdata_nsap_to_string(buffer_type *output, rdata_atom_type rdata,
46362ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
46462ac0c33Sjakob {
46562ac0c33Sjakob buffer_printf(output, "0x");
46662ac0c33Sjakob hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata));
46762ac0c33Sjakob return 1;
46862ac0c33Sjakob }
46962ac0c33Sjakob
47062ac0c33Sjakob static int
rdata_apl_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))47162ac0c33Sjakob rdata_apl_to_string(buffer_type *output, rdata_atom_type rdata,
47262ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
47362ac0c33Sjakob {
47462ac0c33Sjakob int result = 0;
47562ac0c33Sjakob buffer_type packet;
47662ac0c33Sjakob
47762ac0c33Sjakob buffer_create_from(
47862ac0c33Sjakob &packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
47962ac0c33Sjakob
48062ac0c33Sjakob if (buffer_available(&packet, 4)) {
48162ac0c33Sjakob uint16_t address_family = buffer_read_u16(&packet);
48262ac0c33Sjakob uint8_t prefix = buffer_read_u8(&packet);
48362ac0c33Sjakob uint8_t length = buffer_read_u8(&packet);
48462ac0c33Sjakob int negated = length & APL_NEGATION_MASK;
48562ac0c33Sjakob int af = -1;
48662ac0c33Sjakob
48762ac0c33Sjakob length &= APL_LENGTH_MASK;
48862ac0c33Sjakob switch (address_family) {
48962ac0c33Sjakob case 1: af = AF_INET; break;
49062ac0c33Sjakob case 2: af = AF_INET6; break;
49162ac0c33Sjakob }
49262ac0c33Sjakob if (af != -1 && buffer_available(&packet, length)) {
49362ac0c33Sjakob char text_address[1000];
49462ac0c33Sjakob uint8_t address[128];
49562ac0c33Sjakob memset(address, 0, sizeof(address));
49662ac0c33Sjakob buffer_read(&packet, address, length);
49762ac0c33Sjakob if (inet_ntop(af, address, text_address, sizeof(text_address))) {
49862ac0c33Sjakob buffer_printf(output, "%s%d:%s/%d",
49962ac0c33Sjakob negated ? "!" : "",
50062ac0c33Sjakob (int) address_family,
50162ac0c33Sjakob text_address,
50262ac0c33Sjakob (int) prefix);
50362ac0c33Sjakob result = 1;
50462ac0c33Sjakob }
50562ac0c33Sjakob }
50662ac0c33Sjakob }
50762ac0c33Sjakob return result;
50862ac0c33Sjakob }
50962ac0c33Sjakob
51062ac0c33Sjakob static int
rdata_services_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))51162ac0c33Sjakob rdata_services_to_string(buffer_type *output, rdata_atom_type rdata,
51262ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
51362ac0c33Sjakob {
51462ac0c33Sjakob int result = 0;
51562ac0c33Sjakob buffer_type packet;
51662ac0c33Sjakob
51762ac0c33Sjakob buffer_create_from(
51862ac0c33Sjakob &packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
51962ac0c33Sjakob
52062ac0c33Sjakob if (buffer_available(&packet, 1)) {
52162ac0c33Sjakob uint8_t protocol_number = buffer_read_u8(&packet);
52262ac0c33Sjakob ssize_t bitmap_size = buffer_remaining(&packet);
52362ac0c33Sjakob uint8_t *bitmap = buffer_current(&packet);
52462ac0c33Sjakob struct protoent *proto = getprotobynumber(protocol_number);
52562ac0c33Sjakob
52662ac0c33Sjakob if (proto) {
52762ac0c33Sjakob int i;
52862ac0c33Sjakob
52962ac0c33Sjakob buffer_printf(output, "%s", proto->p_name);
53062ac0c33Sjakob
53162ac0c33Sjakob for (i = 0; i < bitmap_size * 8; ++i) {
53262ac0c33Sjakob if (get_bit(bitmap, i)) {
53362ac0c33Sjakob struct servent *service = getservbyport((int)htons(i), proto->p_name);
53462ac0c33Sjakob if (service) {
53562ac0c33Sjakob buffer_printf(output, " %s", service->s_name);
53662ac0c33Sjakob } else {
53762ac0c33Sjakob buffer_printf(output, " %d", i);
53862ac0c33Sjakob }
53962ac0c33Sjakob }
54062ac0c33Sjakob }
54162ac0c33Sjakob buffer_skip(&packet, bitmap_size);
54262ac0c33Sjakob result = 1;
54362ac0c33Sjakob }
54462ac0c33Sjakob }
54562ac0c33Sjakob return result;
54662ac0c33Sjakob }
54762ac0c33Sjakob
54862ac0c33Sjakob static int
rdata_ipsecgateway_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * rr)54962ac0c33Sjakob rdata_ipsecgateway_to_string(buffer_type *output, rdata_atom_type rdata, rr_type* rr)
55062ac0c33Sjakob {
55162ac0c33Sjakob int gateway_type = rdata_atom_data(rr->rdatas[1])[0];
55262ac0c33Sjakob switch(gateway_type) {
55362ac0c33Sjakob case IPSECKEY_NOGATEWAY:
55462ac0c33Sjakob buffer_printf(output, ".");
55562ac0c33Sjakob break;
55662ac0c33Sjakob case IPSECKEY_IP4:
55762ac0c33Sjakob rdata_a_to_string(output, rdata, rr);
55862ac0c33Sjakob break;
55962ac0c33Sjakob case IPSECKEY_IP6:
56062ac0c33Sjakob rdata_aaaa_to_string(output, rdata, rr);
56162ac0c33Sjakob break;
56262ac0c33Sjakob case IPSECKEY_DNAME:
5635bcb494bSjakob {
5645bcb494bSjakob region_type* temp = region_create(xalloc, free);
5655bcb494bSjakob const dname_type* d = dname_make(temp,
5665bcb494bSjakob rdata_atom_data(rdata), 0);
5675bcb494bSjakob if(!d) {
5685bcb494bSjakob region_destroy(temp);
5695bcb494bSjakob return 0;
5705bcb494bSjakob }
5715bcb494bSjakob buffer_printf(output, "%s", dname_to_string(d, NULL));
5725bcb494bSjakob region_destroy(temp);
5735bcb494bSjakob }
57462ac0c33Sjakob break;
57562ac0c33Sjakob default:
57662ac0c33Sjakob return 0;
57762ac0c33Sjakob }
57862ac0c33Sjakob return 1;
57962ac0c33Sjakob }
58062ac0c33Sjakob
58162ac0c33Sjakob static int
rdata_nxt_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))58262ac0c33Sjakob rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata,
58362ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
58462ac0c33Sjakob {
58562ac0c33Sjakob size_t i;
58662ac0c33Sjakob uint8_t *bitmap = rdata_atom_data(rdata);
58762ac0c33Sjakob size_t bitmap_size = rdata_atom_size(rdata);
58862ac0c33Sjakob
58962ac0c33Sjakob for (i = 0; i < bitmap_size * 8; ++i) {
59062ac0c33Sjakob if (get_bit(bitmap, i)) {
59162ac0c33Sjakob buffer_printf(output, "%s ", rrtype_to_string(i));
59262ac0c33Sjakob }
59362ac0c33Sjakob }
59462ac0c33Sjakob
59562ac0c33Sjakob buffer_skip(output, -1);
59662ac0c33Sjakob
59762ac0c33Sjakob return 1;
59862ac0c33Sjakob }
59962ac0c33Sjakob
60062ac0c33Sjakob static int
rdata_nsec_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))60162ac0c33Sjakob rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata,
60262ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
60362ac0c33Sjakob {
60462ac0c33Sjakob size_t saved_position = buffer_position(output);
60562ac0c33Sjakob buffer_type packet;
60662ac0c33Sjakob int insert_space = 0;
60762ac0c33Sjakob
60862ac0c33Sjakob buffer_create_from(
60962ac0c33Sjakob &packet, rdata_atom_data(rdata), rdata_atom_size(rdata));
61062ac0c33Sjakob
61162ac0c33Sjakob while (buffer_available(&packet, 2)) {
61262ac0c33Sjakob uint8_t window = buffer_read_u8(&packet);
61362ac0c33Sjakob uint8_t bitmap_size = buffer_read_u8(&packet);
61462ac0c33Sjakob uint8_t *bitmap = buffer_current(&packet);
61562ac0c33Sjakob int i;
61662ac0c33Sjakob
61762ac0c33Sjakob if (!buffer_available(&packet, bitmap_size)) {
61862ac0c33Sjakob buffer_set_position(output, saved_position);
61962ac0c33Sjakob return 0;
62062ac0c33Sjakob }
62162ac0c33Sjakob
62262ac0c33Sjakob for (i = 0; i < bitmap_size * 8; ++i) {
62362ac0c33Sjakob if (get_bit(bitmap, i)) {
62462ac0c33Sjakob buffer_printf(output,
62562ac0c33Sjakob "%s%s",
62662ac0c33Sjakob insert_space ? " " : "",
62762ac0c33Sjakob rrtype_to_string(
62862ac0c33Sjakob window * 256 + i));
62962ac0c33Sjakob insert_space = 1;
63062ac0c33Sjakob }
63162ac0c33Sjakob }
63262ac0c33Sjakob buffer_skip(&packet, bitmap_size);
63362ac0c33Sjakob }
63462ac0c33Sjakob
63562ac0c33Sjakob return 1;
63662ac0c33Sjakob }
63762ac0c33Sjakob
63862ac0c33Sjakob static int
rdata_loc_to_string(buffer_type * ATTR_UNUSED (output),rdata_atom_type ATTR_UNUSED (rdata),rr_type * ATTR_UNUSED (rr))63962ac0c33Sjakob rdata_loc_to_string(buffer_type *ATTR_UNUSED(output),
64062ac0c33Sjakob rdata_atom_type ATTR_UNUSED(rdata),
64162ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
64262ac0c33Sjakob {
64362ac0c33Sjakob /*
64462ac0c33Sjakob * Returning 0 forces the record to be printed in unknown
64562ac0c33Sjakob * format.
64662ac0c33Sjakob */
64762ac0c33Sjakob return 0;
64862ac0c33Sjakob }
64962ac0c33Sjakob
650063644e9Sflorian static void
buffer_print_svcparamkey(buffer_type * output,uint16_t svcparamkey)651063644e9Sflorian buffer_print_svcparamkey(buffer_type *output, uint16_t svcparamkey)
652063644e9Sflorian {
653063644e9Sflorian if (svcparamkey < SVCPARAMKEY_COUNT)
654063644e9Sflorian buffer_printf(output, "%s", svcparamkey_strs[svcparamkey]);
655063644e9Sflorian else
656063644e9Sflorian buffer_printf(output, "key%d", (int)svcparamkey);
657063644e9Sflorian }
658063644e9Sflorian
659063644e9Sflorian static int
rdata_svcparam_port_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)660063644e9Sflorian rdata_svcparam_port_to_string(buffer_type *output, uint16_t val_len,
661063644e9Sflorian uint16_t *data)
662063644e9Sflorian {
663063644e9Sflorian if (val_len != 2)
664063644e9Sflorian return 0; /* wireformat error, a short is 2 bytes */
665063644e9Sflorian buffer_printf(output, "=%d", (int)ntohs(data[0]));
666063644e9Sflorian return 1;
667063644e9Sflorian }
668063644e9Sflorian
669063644e9Sflorian static int
rdata_svcparam_ipv4hint_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)670063644e9Sflorian rdata_svcparam_ipv4hint_to_string(buffer_type *output, uint16_t val_len,
671063644e9Sflorian uint16_t *data)
672063644e9Sflorian {
673063644e9Sflorian char ip_str[INET_ADDRSTRLEN + 1];
674063644e9Sflorian
675063644e9Sflorian assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
676063644e9Sflorian
677063644e9Sflorian if ((val_len % IP4ADDRLEN) == 0) {
678063644e9Sflorian if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
679063644e9Sflorian return 0; /* wireformat error, incorrect size or inet family */
680063644e9Sflorian
681063644e9Sflorian buffer_printf(output, "=%s", ip_str);
682063644e9Sflorian data += IP4ADDRLEN / sizeof(uint16_t);
683063644e9Sflorian
684063644e9Sflorian while ((val_len -= IP4ADDRLEN) > 0) {
685063644e9Sflorian if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
686063644e9Sflorian return 0; /* wireformat error, incorrect size or inet family */
687063644e9Sflorian
688063644e9Sflorian buffer_printf(output, ",%s", ip_str);
689063644e9Sflorian data += IP4ADDRLEN / sizeof(uint16_t);
690063644e9Sflorian }
691063644e9Sflorian return 1;
692063644e9Sflorian } else
693063644e9Sflorian return 0;
694063644e9Sflorian }
695063644e9Sflorian
696063644e9Sflorian static int
rdata_svcparam_ipv6hint_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)697063644e9Sflorian rdata_svcparam_ipv6hint_to_string(buffer_type *output, uint16_t val_len,
698063644e9Sflorian uint16_t *data)
699063644e9Sflorian {
700063644e9Sflorian char ip_str[INET6_ADDRSTRLEN + 1];
701063644e9Sflorian
702063644e9Sflorian assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
703063644e9Sflorian
704063644e9Sflorian if ((val_len % IP6ADDRLEN) == 0) {
705063644e9Sflorian if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
706063644e9Sflorian return 0; /* wireformat error, incorrect size or inet family */
707063644e9Sflorian
708063644e9Sflorian buffer_printf(output, "=%s", ip_str);
709063644e9Sflorian data += IP6ADDRLEN / sizeof(uint16_t);
710063644e9Sflorian
711063644e9Sflorian while ((val_len -= IP6ADDRLEN) > 0) {
712063644e9Sflorian if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
713063644e9Sflorian return 0; /* wireformat error, incorrect size or inet family */
714063644e9Sflorian
715063644e9Sflorian buffer_printf(output, ",%s", ip_str);
716063644e9Sflorian data += IP6ADDRLEN / sizeof(uint16_t);
717063644e9Sflorian }
718063644e9Sflorian return 1;
719063644e9Sflorian } else
720063644e9Sflorian return 0;
721063644e9Sflorian }
722063644e9Sflorian
723063644e9Sflorian static int
rdata_svcparam_mandatory_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)724063644e9Sflorian rdata_svcparam_mandatory_to_string(buffer_type *output, uint16_t val_len,
725063644e9Sflorian uint16_t *data)
726063644e9Sflorian {
727063644e9Sflorian assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
728063644e9Sflorian
729063644e9Sflorian if (val_len % sizeof(uint16_t))
730063644e9Sflorian return 0; /* wireformat error, val_len must be multiple of shorts */
731063644e9Sflorian buffer_write_u8(output, '=');
732063644e9Sflorian buffer_print_svcparamkey(output, ntohs(*data));
733063644e9Sflorian data += 1;
734063644e9Sflorian
735063644e9Sflorian while ((val_len -= sizeof(uint16_t))) {
736063644e9Sflorian buffer_write_u8(output, ',');
737063644e9Sflorian buffer_print_svcparamkey(output, ntohs(*data));
738063644e9Sflorian data += 1;
739063644e9Sflorian }
740063644e9Sflorian
741063644e9Sflorian return 1;
742063644e9Sflorian }
743063644e9Sflorian
744063644e9Sflorian static int
rdata_svcparam_ech_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)745063644e9Sflorian rdata_svcparam_ech_to_string(buffer_type *output, uint16_t val_len,
746063644e9Sflorian uint16_t *data)
747063644e9Sflorian {
748063644e9Sflorian int length;
749063644e9Sflorian
750063644e9Sflorian assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
751063644e9Sflorian
752063644e9Sflorian buffer_write_u8(output, '=');
753063644e9Sflorian
754063644e9Sflorian buffer_reserve(output, val_len * 2 + 1);
755063644e9Sflorian length = __b64_ntop((uint8_t*) data, val_len,
756063644e9Sflorian (char *) buffer_current(output), val_len * 2);
757063644e9Sflorian if (length > 0) {
758063644e9Sflorian buffer_skip(output, length);
759063644e9Sflorian }
760063644e9Sflorian
761063644e9Sflorian return length != -1;
762063644e9Sflorian }
763063644e9Sflorian
764063644e9Sflorian static int
rdata_svcparam_alpn_to_string(buffer_type * output,uint16_t val_len,uint16_t * data)765063644e9Sflorian rdata_svcparam_alpn_to_string(buffer_type *output, uint16_t val_len,
766063644e9Sflorian uint16_t *data)
767063644e9Sflorian {
768063644e9Sflorian uint8_t *dp = (void *)data;
769063644e9Sflorian
770063644e9Sflorian assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */
771063644e9Sflorian
772063644e9Sflorian buffer_write_u8(output, '=');
773063644e9Sflorian buffer_write_u8(output, '"');
774063644e9Sflorian while (val_len) {
775063644e9Sflorian uint8_t i, str_len = *dp++;
776063644e9Sflorian
777063644e9Sflorian if (str_len > --val_len)
778063644e9Sflorian return 0;
779063644e9Sflorian
780063644e9Sflorian for (i = 0; i < str_len; i++) {
781063644e9Sflorian if (dp[i] == '"' || dp[i] == '\\')
782063644e9Sflorian buffer_printf(output, "\\\\\\%c", dp[i]);
783063644e9Sflorian
784063644e9Sflorian else if (dp[i] == ',')
785063644e9Sflorian buffer_printf(output, "\\\\%c", dp[i]);
786063644e9Sflorian
787063644e9Sflorian else if (!isprint(dp[i]))
788063644e9Sflorian buffer_printf(output, "\\%03u", (unsigned) dp[i]);
789063644e9Sflorian
790063644e9Sflorian else
791063644e9Sflorian buffer_write_u8(output, dp[i]);
792063644e9Sflorian }
793063644e9Sflorian dp += str_len;
794063644e9Sflorian if ((val_len -= str_len))
795063644e9Sflorian buffer_write_u8(output, ',');
796063644e9Sflorian }
797063644e9Sflorian buffer_write_u8(output, '"');
798063644e9Sflorian return 1;
799063644e9Sflorian }
800063644e9Sflorian
801063644e9Sflorian static int
rdata_svcparam_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))802063644e9Sflorian rdata_svcparam_to_string(buffer_type *output, rdata_atom_type rdata,
803063644e9Sflorian rr_type* ATTR_UNUSED(rr))
804063644e9Sflorian {
805063644e9Sflorian uint16_t size = rdata_atom_size(rdata);
806063644e9Sflorian uint16_t* data = (uint16_t *)rdata_atom_data(rdata);
807063644e9Sflorian uint16_t svcparamkey, val_len;
808063644e9Sflorian uint8_t* dp;
809063644e9Sflorian size_t i;
810063644e9Sflorian
811063644e9Sflorian if (size < 4)
812063644e9Sflorian return 0;
813063644e9Sflorian svcparamkey = ntohs(data[0]);
814063644e9Sflorian
815063644e9Sflorian buffer_print_svcparamkey(output, svcparamkey);
816063644e9Sflorian val_len = ntohs(data[1]);
817063644e9Sflorian if (size != val_len + 4)
818063644e9Sflorian return 0; /* wireformat error */
819063644e9Sflorian if (!val_len) {
820063644e9Sflorian /* Some SvcParams MUST have values */
821063644e9Sflorian switch (svcparamkey) {
822063644e9Sflorian case SVCB_KEY_ALPN:
823063644e9Sflorian case SVCB_KEY_PORT:
824063644e9Sflorian case SVCB_KEY_IPV4HINT:
825063644e9Sflorian case SVCB_KEY_IPV6HINT:
826063644e9Sflorian case SVCB_KEY_MANDATORY:
827*de04d855Ssthen case SVCB_KEY_DOHPATH:
828063644e9Sflorian return 0;
829063644e9Sflorian default:
830063644e9Sflorian return 1;
831063644e9Sflorian }
832063644e9Sflorian }
833063644e9Sflorian switch (svcparamkey) {
834063644e9Sflorian case SVCB_KEY_PORT:
835063644e9Sflorian return rdata_svcparam_port_to_string(output, val_len, data+2);
836063644e9Sflorian case SVCB_KEY_IPV4HINT:
837063644e9Sflorian return rdata_svcparam_ipv4hint_to_string(output, val_len, data+2);
838063644e9Sflorian case SVCB_KEY_IPV6HINT:
839063644e9Sflorian return rdata_svcparam_ipv6hint_to_string(output, val_len, data+2);
840063644e9Sflorian case SVCB_KEY_MANDATORY:
841063644e9Sflorian return rdata_svcparam_mandatory_to_string(output, val_len, data+2);
842063644e9Sflorian case SVCB_KEY_NO_DEFAULT_ALPN:
843063644e9Sflorian return 0; /* wireformat error, should not have a value */
844063644e9Sflorian case SVCB_KEY_ALPN:
845063644e9Sflorian return rdata_svcparam_alpn_to_string(output, val_len, data+2);
846063644e9Sflorian case SVCB_KEY_ECH:
847063644e9Sflorian return rdata_svcparam_ech_to_string(output, val_len, data+2);
848*de04d855Ssthen case SVCB_KEY_DOHPATH:
849*de04d855Ssthen /* fallthrough */
850063644e9Sflorian default:
851063644e9Sflorian buffer_write(output, "=\"", 2);
852063644e9Sflorian dp = (void*) (data + 2);
853063644e9Sflorian
854063644e9Sflorian for (i = 0; i < val_len; i++) {
855063644e9Sflorian if (dp[i] == '"' || dp[i] == '\\')
856063644e9Sflorian buffer_printf(output, "\\%c", dp[i]);
857063644e9Sflorian
858063644e9Sflorian else if (!isprint(dp[i]))
859063644e9Sflorian buffer_printf(output, "\\%03u", (unsigned) dp[i]);
860063644e9Sflorian
861063644e9Sflorian else
862063644e9Sflorian buffer_write_u8(output, dp[i]);
863063644e9Sflorian }
864063644e9Sflorian buffer_write_u8(output, '"');
865063644e9Sflorian break;
866063644e9Sflorian }
867063644e9Sflorian return 1;
868063644e9Sflorian }
869063644e9Sflorian
87062ac0c33Sjakob static int
rdata_unknown_to_string(buffer_type * output,rdata_atom_type rdata,rr_type * ATTR_UNUSED (rr))87162ac0c33Sjakob rdata_unknown_to_string(buffer_type *output, rdata_atom_type rdata,
87262ac0c33Sjakob rr_type* ATTR_UNUSED(rr))
87362ac0c33Sjakob {
87462ac0c33Sjakob uint16_t size = rdata_atom_size(rdata);
87562ac0c33Sjakob buffer_printf(output, "\\# %lu ", (unsigned long) size);
87662ac0c33Sjakob hex_to_string(output, rdata_atom_data(rdata), size);
87762ac0c33Sjakob return 1;
87862ac0c33Sjakob }
87962ac0c33Sjakob
88062ac0c33Sjakob static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = {
88162ac0c33Sjakob rdata_dname_to_string,
88262ac0c33Sjakob rdata_dns_name_to_string,
88362ac0c33Sjakob rdata_text_to_string,
884f72b2965Sjakob rdata_texts_to_string,
88562ac0c33Sjakob rdata_byte_to_string,
88662ac0c33Sjakob rdata_short_to_string,
88762ac0c33Sjakob rdata_long_to_string,
88862ac0c33Sjakob rdata_a_to_string,
88962ac0c33Sjakob rdata_aaaa_to_string,
89062ac0c33Sjakob rdata_rrtype_to_string,
89162ac0c33Sjakob rdata_algorithm_to_string,
89262ac0c33Sjakob rdata_certificate_type_to_string,
89362ac0c33Sjakob rdata_period_to_string,
89462ac0c33Sjakob rdata_time_to_string,
89562ac0c33Sjakob rdata_base64_to_string,
89662ac0c33Sjakob rdata_base32_to_string,
89762ac0c33Sjakob rdata_hex_to_string,
89862ac0c33Sjakob rdata_hexlen_to_string,
89962ac0c33Sjakob rdata_nsap_to_string,
90062ac0c33Sjakob rdata_apl_to_string,
90162ac0c33Sjakob rdata_ipsecgateway_to_string,
90262ac0c33Sjakob rdata_services_to_string,
90362ac0c33Sjakob rdata_nxt_to_string,
90462ac0c33Sjakob rdata_nsec_to_string,
90562ac0c33Sjakob rdata_loc_to_string,
90675343be4Ssthen rdata_ilnp64_to_string,
9079c620270Ssthen rdata_eui48_to_string,
9089c620270Ssthen rdata_eui64_to_string,
909a302926fSbrad rdata_long_text_to_string,
910a302926fSbrad rdata_tag_to_string,
911063644e9Sflorian rdata_svcparam_to_string,
91262ac0c33Sjakob rdata_unknown_to_string
91362ac0c33Sjakob };
91462ac0c33Sjakob
91562ac0c33Sjakob int
rdata_atom_to_string(buffer_type * output,rdata_zoneformat_type type,rdata_atom_type rdata,rr_type * record)91662ac0c33Sjakob rdata_atom_to_string(buffer_type *output, rdata_zoneformat_type type,
91762ac0c33Sjakob rdata_atom_type rdata, rr_type* record)
91862ac0c33Sjakob {
91962ac0c33Sjakob return rdata_to_string_table[type](output, rdata, record);
92062ac0c33Sjakob }
92162ac0c33Sjakob
92262ac0c33Sjakob ssize_t
rdata_wireformat_to_rdata_atoms(region_type * region,domain_table_type * owners,uint16_t rrtype,uint16_t data_size,buffer_type * packet,rdata_atom_type ** rdatas)92362ac0c33Sjakob rdata_wireformat_to_rdata_atoms(region_type *region,
92462ac0c33Sjakob domain_table_type *owners,
92562ac0c33Sjakob uint16_t rrtype,
92662ac0c33Sjakob uint16_t data_size,
92762ac0c33Sjakob buffer_type *packet,
92862ac0c33Sjakob rdata_atom_type **rdatas)
92962ac0c33Sjakob {
93062ac0c33Sjakob size_t end = buffer_position(packet) + data_size;
931d65f3523Sjakob size_t i;
93262ac0c33Sjakob rdata_atom_type temp_rdatas[MAXRDATALEN];
93362ac0c33Sjakob rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype);
93462ac0c33Sjakob region_type *temp_region;
93562ac0c33Sjakob
93662ac0c33Sjakob assert(descriptor->maximum <= MAXRDATALEN);
93762ac0c33Sjakob
93862ac0c33Sjakob if (!buffer_available(packet, data_size)) {
93962ac0c33Sjakob return -1;
94062ac0c33Sjakob }
94162ac0c33Sjakob
94262ac0c33Sjakob temp_region = region_create(xalloc, free);
94362ac0c33Sjakob
94462ac0c33Sjakob for (i = 0; i < descriptor->maximum; ++i) {
94562ac0c33Sjakob int is_domain = 0;
94662ac0c33Sjakob int is_normalized = 0;
94762ac0c33Sjakob int is_wirestore = 0;
94862ac0c33Sjakob size_t length = 0;
94962ac0c33Sjakob int required = i < descriptor->minimum;
95062ac0c33Sjakob
95162ac0c33Sjakob switch (rdata_atom_wireformat_type(rrtype, i)) {
95262ac0c33Sjakob case RDATA_WF_COMPRESSED_DNAME:
95362ac0c33Sjakob case RDATA_WF_UNCOMPRESSED_DNAME:
95462ac0c33Sjakob is_domain = 1;
95562ac0c33Sjakob is_normalized = 1;
95662ac0c33Sjakob break;
95762ac0c33Sjakob case RDATA_WF_LITERAL_DNAME:
95862ac0c33Sjakob is_domain = 1;
95962ac0c33Sjakob is_wirestore = 1;
96062ac0c33Sjakob break;
96162ac0c33Sjakob case RDATA_WF_BYTE:
96262ac0c33Sjakob length = sizeof(uint8_t);
96362ac0c33Sjakob break;
96462ac0c33Sjakob case RDATA_WF_SHORT:
96562ac0c33Sjakob length = sizeof(uint16_t);
96662ac0c33Sjakob break;
96762ac0c33Sjakob case RDATA_WF_LONG:
96862ac0c33Sjakob length = sizeof(uint32_t);
96962ac0c33Sjakob break;
970f72b2965Sjakob case RDATA_WF_TEXTS:
971a302926fSbrad case RDATA_WF_LONG_TEXT:
972a302926fSbrad length = end - buffer_position(packet);
973f72b2965Sjakob break;
97462ac0c33Sjakob case RDATA_WF_TEXT:
97562ac0c33Sjakob case RDATA_WF_BINARYWITHLENGTH:
97662ac0c33Sjakob /* Length is stored in the first byte. */
97762ac0c33Sjakob length = 1;
97862ac0c33Sjakob if (buffer_position(packet) + length <= end) {
97962ac0c33Sjakob length += buffer_current(packet)[length - 1];
98062ac0c33Sjakob }
98162ac0c33Sjakob break;
98262ac0c33Sjakob case RDATA_WF_A:
98362ac0c33Sjakob length = sizeof(in_addr_t);
98462ac0c33Sjakob break;
98562ac0c33Sjakob case RDATA_WF_AAAA:
98662ac0c33Sjakob length = IP6ADDRLEN;
98762ac0c33Sjakob break;
98875343be4Ssthen case RDATA_WF_ILNP64:
98975343be4Ssthen length = IP6ADDRLEN/2;
99075343be4Ssthen break;
9919c620270Ssthen case RDATA_WF_EUI48:
9929c620270Ssthen length = EUI48ADDRLEN;
993a302926fSbrad break;
9949c620270Ssthen case RDATA_WF_EUI64:
9959c620270Ssthen length = EUI64ADDRLEN;
9969c620270Ssthen break;
99762ac0c33Sjakob case RDATA_WF_BINARY:
99862ac0c33Sjakob /* Remaining RDATA is binary. */
99962ac0c33Sjakob length = end - buffer_position(packet);
100062ac0c33Sjakob break;
100162ac0c33Sjakob case RDATA_WF_APL:
100262ac0c33Sjakob length = (sizeof(uint16_t) /* address family */
100362ac0c33Sjakob + sizeof(uint8_t) /* prefix */
100462ac0c33Sjakob + sizeof(uint8_t)); /* length */
100562ac0c33Sjakob if (buffer_position(packet) + length <= end) {
100662ac0c33Sjakob /* Mask out negation bit. */
100762ac0c33Sjakob length += (buffer_current(packet)[length - 1]
100862ac0c33Sjakob & APL_LENGTH_MASK);
100962ac0c33Sjakob }
101062ac0c33Sjakob break;
101162ac0c33Sjakob case RDATA_WF_IPSECGATEWAY:
10124564029fSflorian assert(i>1); /* we are past the gateway type */
101362ac0c33Sjakob switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ {
101462ac0c33Sjakob default:
101562ac0c33Sjakob case IPSECKEY_NOGATEWAY:
101662ac0c33Sjakob length = 0;
101762ac0c33Sjakob break;
101862ac0c33Sjakob case IPSECKEY_IP4:
101962ac0c33Sjakob length = IP4ADDRLEN;
102062ac0c33Sjakob break;
102162ac0c33Sjakob case IPSECKEY_IP6:
102262ac0c33Sjakob length = IP6ADDRLEN;
102362ac0c33Sjakob break;
102462ac0c33Sjakob case IPSECKEY_DNAME:
102562ac0c33Sjakob is_domain = 1;
102662ac0c33Sjakob is_normalized = 1;
102762ac0c33Sjakob is_wirestore = 1;
102862ac0c33Sjakob break;
102962ac0c33Sjakob }
103062ac0c33Sjakob break;
1031063644e9Sflorian case RDATA_WF_SVCPARAM:
1032063644e9Sflorian length = 4;
1033063644e9Sflorian if (buffer_position(packet) + 4 <= end) {
1034063644e9Sflorian length +=
1035063644e9Sflorian read_uint16(buffer_current(packet) + 2);
1036063644e9Sflorian }
1037063644e9Sflorian break;
103862ac0c33Sjakob }
103962ac0c33Sjakob
104062ac0c33Sjakob if (is_domain) {
104162ac0c33Sjakob const dname_type *dname;
104262ac0c33Sjakob
104362ac0c33Sjakob if (!required && buffer_position(packet) == end) {
104462ac0c33Sjakob break;
104562ac0c33Sjakob }
104662ac0c33Sjakob
104762ac0c33Sjakob dname = dname_make_from_packet(
104862ac0c33Sjakob temp_region, packet, 1, is_normalized);
104962ac0c33Sjakob if (!dname || buffer_position(packet) > end) {
105062ac0c33Sjakob /* Error in domain name. */
105162ac0c33Sjakob region_destroy(temp_region);
105262ac0c33Sjakob return -1;
105362ac0c33Sjakob }
105462ac0c33Sjakob if(is_wirestore) {
105562ac0c33Sjakob temp_rdatas[i].data = (uint16_t *) region_alloc(
10568d8f1862Ssthen region, sizeof(uint16_t) + ((size_t)dname->name_size));
105762ac0c33Sjakob temp_rdatas[i].data[0] = dname->name_size;
105862ac0c33Sjakob memcpy(temp_rdatas[i].data+1, dname_name(dname),
105962ac0c33Sjakob dname->name_size);
1060dd5b221eSsthen } else {
106162ac0c33Sjakob temp_rdatas[i].domain
106262ac0c33Sjakob = domain_table_insert(owners, dname);
1063dd5b221eSsthen temp_rdatas[i].domain->usage ++;
1064dd5b221eSsthen }
106562ac0c33Sjakob } else {
106662ac0c33Sjakob if (buffer_position(packet) + length > end) {
106762ac0c33Sjakob if (required) {
106862ac0c33Sjakob /* Truncated RDATA. */
106962ac0c33Sjakob region_destroy(temp_region);
107062ac0c33Sjakob return -1;
107162ac0c33Sjakob } else {
107262ac0c33Sjakob break;
107362ac0c33Sjakob }
107462ac0c33Sjakob }
10755bcb494bSjakob if (!required && buffer_position(packet) == end) {
10765bcb494bSjakob break;
10775bcb494bSjakob }
107862ac0c33Sjakob
107962ac0c33Sjakob temp_rdatas[i].data = (uint16_t *) region_alloc(
108062ac0c33Sjakob region, sizeof(uint16_t) + length);
108162ac0c33Sjakob temp_rdatas[i].data[0] = length;
108262ac0c33Sjakob buffer_read(packet, temp_rdatas[i].data + 1, length);
108362ac0c33Sjakob }
108462ac0c33Sjakob }
108562ac0c33Sjakob
108662ac0c33Sjakob if (buffer_position(packet) < end) {
108762ac0c33Sjakob /* Trailing garbage. */
108862ac0c33Sjakob region_destroy(temp_region);
108962ac0c33Sjakob return -1;
109062ac0c33Sjakob }
109162ac0c33Sjakob
10928d8f1862Ssthen *rdatas = (rdata_atom_type *) region_alloc_array_init(
10938d8f1862Ssthen region, temp_rdatas, i, sizeof(rdata_atom_type));
109462ac0c33Sjakob region_destroy(temp_region);
1095d65f3523Sjakob return (ssize_t)i;
109662ac0c33Sjakob }
109762ac0c33Sjakob
109862ac0c33Sjakob size_t
rdata_maximum_wireformat_size(rrtype_descriptor_type * descriptor,size_t rdata_count,rdata_atom_type * rdatas)109962ac0c33Sjakob rdata_maximum_wireformat_size(rrtype_descriptor_type *descriptor,
110062ac0c33Sjakob size_t rdata_count,
110162ac0c33Sjakob rdata_atom_type *rdatas)
110262ac0c33Sjakob {
110362ac0c33Sjakob size_t result = 0;
110462ac0c33Sjakob size_t i;
110562ac0c33Sjakob for (i = 0; i < rdata_count; ++i) {
110662ac0c33Sjakob if (rdata_atom_is_domain(descriptor->type, i)) {
110762ac0c33Sjakob result += domain_dname(rdata_atom_domain(rdatas[i]))->name_size;
110862ac0c33Sjakob } else {
110962ac0c33Sjakob result += rdata_atom_size(rdatas[i]);
111062ac0c33Sjakob }
111162ac0c33Sjakob }
111262ac0c33Sjakob return result;
111362ac0c33Sjakob }
111462ac0c33Sjakob
111562ac0c33Sjakob int
rdata_atoms_to_unknown_string(buffer_type * output,rrtype_descriptor_type * descriptor,size_t rdata_count,rdata_atom_type * rdatas)111662ac0c33Sjakob rdata_atoms_to_unknown_string(buffer_type *output,
111762ac0c33Sjakob rrtype_descriptor_type *descriptor,
111862ac0c33Sjakob size_t rdata_count,
111962ac0c33Sjakob rdata_atom_type *rdatas)
112062ac0c33Sjakob {
112162ac0c33Sjakob size_t i;
112262ac0c33Sjakob size_t size =
112362ac0c33Sjakob rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas);
112462ac0c33Sjakob buffer_printf(output, " \\# %lu ", (unsigned long) size);
112562ac0c33Sjakob for (i = 0; i < rdata_count; ++i) {
112662ac0c33Sjakob if (rdata_atom_is_domain(descriptor->type, i)) {
112762ac0c33Sjakob const dname_type *dname =
112862ac0c33Sjakob domain_dname(rdata_atom_domain(rdatas[i]));
112962ac0c33Sjakob hex_to_string(
113062ac0c33Sjakob output, dname_name(dname), dname->name_size);
113162ac0c33Sjakob } else {
113262ac0c33Sjakob hex_to_string(output, rdata_atom_data(rdatas[i]),
113362ac0c33Sjakob rdata_atom_size(rdatas[i]));
113462ac0c33Sjakob }
113562ac0c33Sjakob }
113662ac0c33Sjakob return 1;
113762ac0c33Sjakob }
113862ac0c33Sjakob
113962ac0c33Sjakob int
print_rdata(buffer_type * output,rrtype_descriptor_type * descriptor,rr_type * record)114062ac0c33Sjakob print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor,
114162ac0c33Sjakob rr_type *record)
114262ac0c33Sjakob {
114362ac0c33Sjakob size_t i;
114462ac0c33Sjakob size_t saved_position = buffer_position(output);
114562ac0c33Sjakob
114662ac0c33Sjakob for (i = 0; i < record->rdata_count; ++i) {
114762ac0c33Sjakob if (i == 0) {
114862ac0c33Sjakob buffer_printf(output, "\t");
114962ac0c33Sjakob } else if (descriptor->type == TYPE_SOA && i == 2) {
115062ac0c33Sjakob buffer_printf(output, " (\n\t\t");
115162ac0c33Sjakob } else {
115262ac0c33Sjakob buffer_printf(output, " ");
115362ac0c33Sjakob }
115462ac0c33Sjakob if (!rdata_atom_to_string(
115562ac0c33Sjakob output,
115662ac0c33Sjakob (rdata_zoneformat_type) descriptor->zoneformat[i],
115762ac0c33Sjakob record->rdatas[i], record))
115862ac0c33Sjakob {
115962ac0c33Sjakob buffer_set_position(output, saved_position);
116062ac0c33Sjakob return 0;
116162ac0c33Sjakob }
116262ac0c33Sjakob }
116362ac0c33Sjakob if (descriptor->type == TYPE_SOA) {
116462ac0c33Sjakob buffer_printf(output, " )");
116562ac0c33Sjakob }
116662ac0c33Sjakob
116762ac0c33Sjakob return 1;
116862ac0c33Sjakob }
116962ac0c33Sjakob
1170