xref: /freebsd/contrib/unbound/sldns/wire2str.c (revision 5fa84c6ec176d186ddad25d31f8760e50f48157f)
1 /*
2  * wire2str.c
3  *
4  * conversion routines from the wire format
5  * to the presentation format (strings)
6  *
7  * (c) NLnet Labs, 2004-2006
8  *
9  * See the file LICENSE for the license
10  */
11 /**
12  * \file
13  *
14  * Contains functions to translate the wireformat to text
15  * representation, as well as functions to print them.
16  */
17 #include "config.h"
18 #include "sldns/wire2str.h"
19 #include "sldns/str2wire.h"
20 #include "sldns/rrdef.h"
21 #include "sldns/pkthdr.h"
22 #include "sldns/parseutil.h"
23 #include "sldns/sbuffer.h"
24 #include "sldns/keyraw.h"
25 #include "util/data/dname.h"
26 #ifdef HAVE_TIME_H
27 #include <time.h>
28 #endif
29 #include <sys/time.h>
30 #include <stdarg.h>
31 #include <ctype.h>
32 #ifdef HAVE_NETDB_H
33 #include <netdb.h>
34 #endif
35 
36 /* lookup tables for standard DNS stuff  */
37 /* Taken from RFC 2535, section 7.  */
38 static sldns_lookup_table sldns_algorithms_data[] = {
39 	{ LDNS_RSAMD5, "RSAMD5" },
40 	{ LDNS_DH, "DH" },
41 	{ LDNS_DSA, "DSA" },
42 	{ LDNS_ECC, "ECC" },
43 	{ LDNS_RSASHA1, "RSASHA1" },
44 	{ LDNS_DSA_NSEC3, "DSA-NSEC3-SHA1" },
45 	{ LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
46 	{ LDNS_RSASHA256, "RSASHA256"},
47 	{ LDNS_RSASHA512, "RSASHA512"},
48 	{ LDNS_ECC_GOST, "ECC-GOST"},
49 	{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
50 	{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
51 	{ LDNS_ED25519, "ED25519"},
52 	{ LDNS_ED448, "ED448"},
53 	{ LDNS_INDIRECT, "INDIRECT" },
54 	{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
55 	{ LDNS_PRIVATEOID, "PRIVATEOID" },
56 	{ 0, NULL }
57 };
58 sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
59 
60 /* hash algorithms in DS record */
61 static sldns_lookup_table sldns_hashes_data[] = {
62 	{ LDNS_SHA1, "SHA1" },
63 	{ LDNS_SHA256, "SHA256" },
64 	{ LDNS_HASH_GOST, "HASH-GOST" },
65 	{ LDNS_SHA384, "SHA384" },
66 	{ 0, NULL }
67 };
68 sldns_lookup_table* sldns_hashes = sldns_hashes_data;
69 
70 /* Taken from RFC 4398  */
71 static sldns_lookup_table sldns_cert_algorithms_data[] = {
72 	{ LDNS_CERT_PKIX, "PKIX" },
73 	{ LDNS_CERT_SPKI, "SPKI" },
74 	{ LDNS_CERT_PGP, "PGP" },
75 	{ LDNS_CERT_IPKIX, "IPKIX" },
76 	{ LDNS_CERT_ISPKI, "ISPKI" },
77 	{ LDNS_CERT_IPGP, "IPGP" },
78 	{ LDNS_CERT_ACPKIX, "ACPKIX" },
79 	{ LDNS_CERT_IACPKIX, "IACPKIX" },
80 	{ LDNS_CERT_URI, "URI" },
81 	{ LDNS_CERT_OID, "OID" },
82 	{ 0, NULL }
83 };
84 sldns_lookup_table* sldns_cert_algorithms = sldns_cert_algorithms_data;
85 
86 /* if these are used elsewhere */
87 static sldns_lookup_table sldns_rcodes_data[] = {
88 	{ LDNS_RCODE_NOERROR, "NOERROR" },
89 	{ LDNS_RCODE_FORMERR, "FORMERR" },
90 	{ LDNS_RCODE_SERVFAIL, "SERVFAIL" },
91 	{ LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
92 	{ LDNS_RCODE_NOTIMPL, "NOTIMPL" },
93 	{ LDNS_RCODE_REFUSED, "REFUSED" },
94 	{ LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
95 	{ LDNS_RCODE_YXRRSET, "YXRRSET" },
96 	{ LDNS_RCODE_NXRRSET, "NXRRSET" },
97 	{ LDNS_RCODE_NOTAUTH, "NOTAUTH" },
98 	{ LDNS_RCODE_NOTZONE, "NOTZONE" },
99 	{ 0, NULL }
100 };
101 sldns_lookup_table* sldns_rcodes = sldns_rcodes_data;
102 
103 static sldns_lookup_table sldns_opcodes_data[] = {
104 	{ LDNS_PACKET_QUERY, "QUERY" },
105 	{ LDNS_PACKET_IQUERY, "IQUERY" },
106 	{ LDNS_PACKET_STATUS, "STATUS" },
107 	{ LDNS_PACKET_NOTIFY, "NOTIFY" },
108 	{ LDNS_PACKET_UPDATE, "UPDATE" },
109 	{ 0, NULL }
110 };
111 sldns_lookup_table* sldns_opcodes = sldns_opcodes_data;
112 
113 static sldns_lookup_table sldns_wireparse_errors_data[] = {
114 	{ LDNS_WIREPARSE_ERR_OK, "no parse error" },
115 	{ LDNS_WIREPARSE_ERR_GENERAL, "parse error" },
116 	{ LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, "Domainname length overflow" },
117 	{ LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, "Domainname length underflow (zero length)" },
118 	{ LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, "buffer too small" },
119 	{ LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, "Label length overflow" },
120 	{ LDNS_WIREPARSE_ERR_EMPTY_LABEL, "Empty label" },
121 	{ LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, "Syntax error, bad escape sequence" },
122 	{ LDNS_WIREPARSE_ERR_SYNTAX, "Syntax error, could not parse the RR" },
123 	{ LDNS_WIREPARSE_ERR_SYNTAX_TTL, "Syntax error, could not parse the RR's TTL" },
124 	{ LDNS_WIREPARSE_ERR_SYNTAX_TYPE, "Syntax error, could not parse the RR's type" },
125 	{ LDNS_WIREPARSE_ERR_SYNTAX_CLASS, "Syntax error, could not parse the RR's class" },
126 	{ LDNS_WIREPARSE_ERR_SYNTAX_RDATA, "Syntax error, could not parse the RR's rdata" },
127 	{ LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, "Syntax error, value expected" },
128 	{ LDNS_WIREPARSE_ERR_INVALID_STR, "Conversion error, string expected" },
129 	{ LDNS_WIREPARSE_ERR_SYNTAX_B64, "Conversion error, b64 encoding expected" },
130 	{ LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT, "Conversion error, b32 ext encoding expected" },
131 	{ LDNS_WIREPARSE_ERR_SYNTAX_HEX, "Conversion error, hex encoding expected" },
132 	{ LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM, "Bad algorithm type for CERT record" },
133 	{ LDNS_WIREPARSE_ERR_SYNTAX_TIME, "Conversion error, time encoding expected" },
134 	{ LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, "Conversion error, time period encoding expected" },
135 	{ LDNS_WIREPARSE_ERR_SYNTAX_ILNP64, "Conversion error, 4 colon separated hex numbers expected" },
136 	{ LDNS_WIREPARSE_ERR_SYNTAX_EUI48,
137 		"Conversion error, 6 two character hex numbers "
138 		"separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx" },
139 	{ LDNS_WIREPARSE_ERR_SYNTAX_EUI64,
140 		"Conversion error, 8 two character hex numbers "
141 		"separated by dashes expected (i.e. xx-xx-xx-xx-xx-xx-xx-xx" },
142 	{ LDNS_WIREPARSE_ERR_SYNTAX_TAG,
143 		"Conversion error, a non-zero sequence of US-ASCII letters "
144 		"and numbers in lower case expected" },
145 	{ LDNS_WIREPARSE_ERR_NOT_IMPL, "not implemented" },
146 	{ LDNS_WIREPARSE_ERR_SYNTAX_INT, "Conversion error, integer expected" },
147 	{ LDNS_WIREPARSE_ERR_SYNTAX_IP4, "Conversion error, ip4 addr expected" },
148 	{ LDNS_WIREPARSE_ERR_SYNTAX_IP6, "Conversion error, ip6 addr expected" },
149 	{ LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, "Syntax error, integer overflow" },
150 	{ LDNS_WIREPARSE_ERR_INCLUDE, "$INCLUDE directive was seen in the zone" },
151 	{ LDNS_WIREPARSE_ERR_PARENTHESIS, "Parse error, parenthesis mismatch" },
152 	{ LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY, "Unknown SvcParamKey"},
153 	{ LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM, "SvcParam is missing a SvcParamValue"},
154 	{ LDNS_WIREPARSE_ERR_SVCB_DUPLICATE_KEYS, "Duplicate SVCB key found"},
155 	{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS, "Too many keys in mandatory" },
156 	{ LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS,
157 		"Too many SvcParams. Unbound only allows 63 entries" },
158 	{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_MISSING_PARAM,
159 		"Mandatory SvcParamKey is missing"},
160 	{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY,
161 		"Keys in SvcParam mandatory MUST be unique" },
162 	{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY,
163 		"mandatory MUST not be included as mandatory parameter" },
164 	{ LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX,
165 		"Could not parse port SvcParamValue" },
166 	{ LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES,
167 		"Too many IPv4 addresses in ipv4hint" },
168 	{ LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES,
169 		"Too many IPv6 addresses in ipv6hint" },
170 	{ LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE,
171 		"Alpn strings need to be smaller than 255 chars"},
172 	{ LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE,
173 		"No-default-alpn should not have a value" },
174 	{ LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA,
175 		"General SVCParam error" },
176 	{ 0, NULL }
177 };
178 sldns_lookup_table* sldns_wireparse_errors = sldns_wireparse_errors_data;
179 
180 static sldns_lookup_table sldns_edns_flags_data[] = {
181 	{ 3600, "do"},
182 	{ 0, NULL}
183 };
184 sldns_lookup_table* sldns_edns_flags = sldns_edns_flags_data;
185 
186 static sldns_lookup_table sldns_edns_options_data[] = {
187 	{ 1, "LLQ" },
188 	{ 2, "UL" },
189 	{ 3, "NSID" },
190 	/* 4 draft-cheshire-edns0-owner-option */
191 	{ 5, "DAU" },
192 	{ 6, "DHU" },
193 	{ 7, "N3U" },
194 	{ 8, "edns-client-subnet" },
195 	{ 10, "COOKIE" },
196 	{ 11, "edns-tcp-keepalive"},
197 	{ 12, "Padding" },
198 	{ 15, "EDE"},
199 	{ 0, NULL}
200 };
201 sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
202 
203 /* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */
204 static sldns_lookup_table sldns_edns_ede_codes_data[] = {
205 	{ LDNS_EDE_NONE, "None" },
206 	{ LDNS_EDE_OTHER, "Other Error" },
207 	{ LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" },
208 	{ LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" },
209 	{ LDNS_EDE_STALE_ANSWER, "Stale Answer" },
210 	{ LDNS_EDE_FORGED_ANSWER, "Forged Answer" },
211 	{ LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" },
212 	{ LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" },
213 	{ LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" },
214 	{ LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" },
215 	{ LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" },
216 	{ LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" },
217 	{ LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" },
218 	{ LDNS_EDE_NSEC_MISSING, "NSEC Missing" },
219 	{ LDNS_EDE_CACHED_ERROR, "Cached Error" },
220 	{ LDNS_EDE_NOT_READY, "Not Ready" },
221 	{ LDNS_EDE_BLOCKED, "Blocked" },
222 	{ LDNS_EDE_CENSORED, "Censored" },
223 	{ LDNS_EDE_FILTERED, "Filtered" },
224 	{ LDNS_EDE_PROHIBITED, "Prohibited" },
225 	{ LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" },
226 	{ LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" },
227 	{ LDNS_EDE_NOT_SUPPORTED, "Not Supported" },
228 	{ LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" },
229 	{ LDNS_EDE_NETWORK_ERROR, "Network Error" },
230 	{ LDNS_EDE_INVALID_DATA, "Invalid Data" },
231 	{ LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID, "Signature Expired Before Valid" },
232 	{ LDNS_EDE_TOO_EARLY, "Non-Replayable Transactions Received in 0-RTT Data" },
233 	{ LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS, "Unsupported NSEC3 Iterations Value" },
234 	{ LDNS_EDE_BADPROXYPOLICY, "Unable to Conform to Policy" },
235 	{ LDNS_EDE_SYNTHESIZED, "Synthesized Answer" },
236 	{ LDNS_EDE_INVALID_QUERY_TYPE, "Invalid Query Type" },
237 	{ 0, NULL}
238 };
239 sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data;
240 
241 static sldns_lookup_table sldns_tsig_errors_data[] = {
242 	{ LDNS_TSIG_ERROR_NOERROR, "NOERROR" },
243 	{ LDNS_RCODE_FORMERR, "FORMERR" },
244 	{ LDNS_RCODE_SERVFAIL, "SERVFAIL" },
245 	{ LDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
246 	{ LDNS_RCODE_NOTIMPL, "NOTIMPL" },
247 	{ LDNS_RCODE_REFUSED, "REFUSED" },
248 	{ LDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
249 	{ LDNS_RCODE_YXRRSET, "YXRRSET" },
250 	{ LDNS_RCODE_NXRRSET, "NXRRSET" },
251 	{ LDNS_RCODE_NOTAUTH, "NOTAUTH" },
252 	{ LDNS_RCODE_NOTZONE, "NOTZONE" },
253 	{ LDNS_TSIG_ERROR_BADSIG, "BADSIG" },
254 	{ LDNS_TSIG_ERROR_BADKEY, "BADKEY" },
255 	{ LDNS_TSIG_ERROR_BADTIME, "BADTIME" },
256 	{ LDNS_TSIG_ERROR_BADMODE, "BADMODE" },
257 	{ LDNS_TSIG_ERROR_BADNAME, "BADNAME" },
258 	{ LDNS_TSIG_ERROR_BADALG, "BADALG" },
259 	{ 0, NULL }
260 };
261 sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
262 
263 /* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */
264 const char *svcparamkey_strs[] = {
265 	"mandatory", "alpn", "no-default-alpn", "port",
266 	"ipv4hint", "ech", "ipv6hint", "dohpath"
267 };
268 
sldns_wire2str_pkt(uint8_t * data,size_t len)269 char* sldns_wire2str_pkt(uint8_t* data, size_t len)
270 {
271 	size_t slen = (size_t)sldns_wire2str_pkt_buf(data, len, NULL, 0);
272 	char* result = (char*)malloc(slen+1);
273 	if(!result) return NULL;
274 	sldns_wire2str_pkt_buf(data, len, result, slen+1);
275 	return result;
276 }
277 
sldns_wire2str_rr(uint8_t * rr,size_t len)278 char* sldns_wire2str_rr(uint8_t* rr, size_t len)
279 {
280 	size_t slen = (size_t)sldns_wire2str_rr_buf(rr, len, NULL, 0);
281 	char* result = (char*)malloc(slen+1);
282 	if(!result) return NULL;
283 	sldns_wire2str_rr_buf(rr, len, result, slen+1);
284 	return result;
285 }
286 
sldns_wire2str_type(uint16_t rrtype)287 char* sldns_wire2str_type(uint16_t rrtype)
288 {
289 	char buf[16];
290 	sldns_wire2str_type_buf(rrtype, buf, sizeof(buf));
291 	return strdup(buf);
292 }
293 
sldns_wire2str_class(uint16_t rrclass)294 char* sldns_wire2str_class(uint16_t rrclass)
295 {
296 	char buf[16];
297 	sldns_wire2str_class_buf(rrclass, buf, sizeof(buf));
298 	return strdup(buf);
299 }
300 
sldns_wire2str_dname(uint8_t * dname,size_t dname_len)301 char* sldns_wire2str_dname(uint8_t* dname, size_t dname_len)
302 {
303 	size_t slen=(size_t)sldns_wire2str_dname_buf(dname, dname_len, NULL, 0);
304 	char* result = (char*)malloc(slen+1);
305 	if(!result) return NULL;
306 	sldns_wire2str_dname_buf(dname, dname_len, result, slen+1);
307 	return result;
308 }
309 
sldns_wire2str_rcode(int rcode)310 char* sldns_wire2str_rcode(int rcode)
311 {
312 	char buf[16];
313 	sldns_wire2str_rcode_buf(rcode, buf, sizeof(buf));
314 	return strdup(buf);
315 }
316 
sldns_wire2str_pkt_buf(uint8_t * d,size_t dlen,char * s,size_t slen)317 int sldns_wire2str_pkt_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
318 {
319 	/* use arguments as temporary variables */
320 	return sldns_wire2str_pkt_scan(&d, &dlen, &s, &slen);
321 }
322 
sldns_wire2str_rr_buf(uint8_t * d,size_t dlen,char * s,size_t slen)323 int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
324 {
325 	/* use arguments as temporary variables */
326 	return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
327 }
328 
sldns_wire2str_rrquestion_buf(uint8_t * d,size_t dlen,char * s,size_t slen)329 int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
330 {
331 	/* use arguments as temporary variables */
332 	return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
333 }
334 
sldns_wire2str_rdata_buf(uint8_t * rdata,size_t rdata_len,char * str,size_t str_len,uint16_t rrtype)335 int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
336 	size_t str_len, uint16_t rrtype)
337 {
338 	/* use arguments as temporary variables */
339 	return sldns_wire2str_rdata_scan(&rdata, &rdata_len, &str, &str_len,
340 		rrtype, NULL, 0, NULL);
341 }
342 
sldns_wire2str_rr_unknown_buf(uint8_t * d,size_t dlen,char * s,size_t slen)343 int sldns_wire2str_rr_unknown_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
344 {
345 	/* use arguments as temporary variables */
346 	return sldns_wire2str_rr_unknown_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
347 }
348 
sldns_wire2str_rr_comment_buf(uint8_t * rr,size_t rrlen,size_t dname_len,char * s,size_t slen)349 int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rrlen, size_t dname_len,
350 	char* s, size_t slen)
351 {
352 	uint16_t rrtype = sldns_wirerr_get_type(rr, rrlen, dname_len);
353 	return sldns_wire2str_rr_comment_print(&s, &slen, rr, rrlen, dname_len,
354 		rrtype);
355 }
356 
sldns_wire2str_type_buf(uint16_t rrtype,char * s,size_t slen)357 int sldns_wire2str_type_buf(uint16_t rrtype, char* s, size_t slen)
358 {
359 	/* use arguments as temporary variables */
360 	return sldns_wire2str_type_print(&s, &slen, rrtype);
361 }
362 
sldns_wire2str_class_buf(uint16_t rrclass,char * s,size_t slen)363 int sldns_wire2str_class_buf(uint16_t rrclass, char* s, size_t slen)
364 {
365 	/* use arguments as temporary variables */
366 	return sldns_wire2str_class_print(&s, &slen, rrclass);
367 }
368 
sldns_wire2str_rcode_buf(int rcode,char * s,size_t slen)369 int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen)
370 {
371 	/* use arguments as temporary variables */
372 	return sldns_wire2str_rcode_print(&s, &slen, rcode);
373 }
374 
sldns_wire2str_opcode_buf(int opcode,char * s,size_t slen)375 int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen)
376 {
377 	/* use arguments as temporary variables */
378 	return sldns_wire2str_opcode_print(&s, &slen, opcode);
379 }
380 
sldns_wire2str_dname_buf(uint8_t * d,size_t dlen,char * s,size_t slen)381 int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
382 {
383 	/* use arguments as temporary variables */
384 	return sldns_wire2str_dname_scan(&d, &dlen, &s, &slen, NULL, 0, NULL);
385 }
386 
sldns_str_vprint(char ** str,size_t * slen,const char * format,va_list args)387 int sldns_str_vprint(char** str, size_t* slen, const char* format, va_list args)
388 {
389 	int w = vsnprintf(*str, *slen, format, args);
390 	if(w < 0) {
391 		/* error in printout */
392 		return 0;
393 	} else if((size_t)w >= *slen) {
394 		*str = NULL; /* we do not want str to point outside of buffer*/
395 		*slen = 0;
396 	} else {
397 		*str += w;
398 		*slen -= w;
399 	}
400 	return w;
401 }
402 
sldns_str_print(char ** str,size_t * slen,const char * format,...)403 int sldns_str_print(char** str, size_t* slen, const char* format, ...)
404 {
405 	int w;
406 	va_list args;
407 	va_start(args, format);
408 	w = sldns_str_vprint(str, slen, format, args);
409 	va_end(args);
410 	return w;
411 }
412 
413 /** print hex format into text buffer for specified length */
print_hex_buf(char ** s,size_t * slen,uint8_t * buf,size_t len)414 static int print_hex_buf(char** s, size_t* slen, uint8_t* buf, size_t len)
415 {
416 	const char* hex = "0123456789ABCDEF";
417 	size_t i;
418 	for(i=0; i<len; i++) {
419 		(void)sldns_str_print(s, slen, "%c%c", hex[(buf[i]&0xf0)>>4],
420 			hex[buf[i]&0x0f]);
421 	}
422 	return (int)len*2;
423 }
424 
425 /** print remainder of buffer in hex format with prefixed text */
print_remainder_hex(const char * pref,uint8_t ** d,size_t * dlen,char ** s,size_t * slen)426 static int print_remainder_hex(const char* pref, uint8_t** d, size_t* dlen,
427 	char** s, size_t* slen)
428 {
429 	int w = 0;
430 	w += sldns_str_print(s, slen, "%s", pref);
431 	w += print_hex_buf(s, slen, *d, *dlen);
432 	*d += *dlen;
433 	*dlen = 0;
434 	return w;
435 }
436 
sldns_wire2str_pkt_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen)437 int sldns_wire2str_pkt_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
438 {
439 	int w = 0, comprloop = 0;
440 	unsigned qdcount, ancount, nscount, arcount, i;
441 	uint8_t* pkt = *d;
442 	size_t pktlen = *dlen;
443 	if(*dlen >= LDNS_HEADER_SIZE) {
444 		qdcount = (unsigned)LDNS_QDCOUNT(*d);
445 		ancount = (unsigned)LDNS_ANCOUNT(*d);
446 		nscount = (unsigned)LDNS_NSCOUNT(*d);
447 		arcount = (unsigned)LDNS_ARCOUNT(*d);
448 	} else {
449 		qdcount = ancount = nscount = arcount = 0;
450 	}
451 	w += sldns_wire2str_header_scan(d, dlen, s, slen);
452 	w += sldns_str_print(s, slen, "\n");
453 	w += sldns_str_print(s, slen, ";; QUESTION SECTION:\n");
454 	for(i=0; i<qdcount; i++) {
455 		w += sldns_wire2str_rrquestion_scan(d, dlen, s, slen,
456 			pkt, pktlen, &comprloop);
457 		if(!*dlen) break;
458 	}
459 	w += sldns_str_print(s, slen, "\n");
460 	w += sldns_str_print(s, slen, ";; ANSWER SECTION:\n");
461 	for(i=0; i<ancount; i++) {
462 		w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop);
463 		if(!*dlen) break;
464 	}
465 	w += sldns_str_print(s, slen, "\n");
466 	w += sldns_str_print(s, slen, ";; AUTHORITY SECTION:\n");
467 	for(i=0; i<nscount; i++) {
468 		w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop);
469 		if(!*dlen) break;
470 	}
471 	w += sldns_str_print(s, slen, "\n");
472 	w += sldns_str_print(s, slen, ";; ADDITIONAL SECTION:\n");
473 	for(i=0; i<arcount; i++) {
474 		w += sldns_wire2str_rr_scan(d, dlen, s, slen, pkt, pktlen, &comprloop);
475 		if(!*dlen) break;
476 	}
477 	/* other fields: WHEN(time), SERVER(IP) not available here. */
478 	w += sldns_str_print(s, slen, ";; MSG SIZE  rcvd: %d\n", (int)pktlen);
479 	if(*dlen > 0) {
480 		w += print_remainder_hex(";; trailing garbage 0x",
481 			d, dlen, s, slen);
482 		w += sldns_str_print(s, slen, "\n");
483 	}
484 	return w;
485 }
486 
487 /** scan type, class and ttl and printout, for rr */
sldns_rr_tcttl_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)488 static int sldns_rr_tcttl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
489 {
490 	int w = 0;
491 	uint16_t t, c;
492 	uint32_t ttl;
493 	if(*dl < 8) {
494 		if(*dl < 4)
495 			return w + print_remainder_hex("; Error malformed 0x",
496 				d, dl, s, sl);
497 		/* these print values or 0x.. if none left */
498 		t = sldns_read_uint16(*d);
499 		c = sldns_read_uint16((*d)+2);
500 		(*d)+=4;
501 		(*dl)-=4;
502 		w += sldns_wire2str_class_print(s, sl, c);
503 		w += sldns_str_print(s, sl, "\t");
504 		w += sldns_wire2str_type_print(s, sl, t);
505 		if(*dl == 0)
506 			return w + sldns_str_print(s, sl, "; Error no ttl");
507 		return w + print_remainder_hex(
508 			"; Error malformed ttl 0x", d, dl, s, sl);
509 	}
510 	t = sldns_read_uint16(*d);
511 	c = sldns_read_uint16((*d)+2);
512 	ttl = sldns_read_uint32((*d)+4);
513 	(*d)+=8;
514 	(*dl)-=8;
515 	w += sldns_str_print(s, sl, "%lu\t", (unsigned long)ttl);
516 	w += sldns_wire2str_class_print(s, sl, c);
517 	w += sldns_str_print(s, sl, "\t");
518 	w += sldns_wire2str_type_print(s, sl, t);
519 	return w;
520 }
521 
sldns_wire2str_rr_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen,uint8_t * pkt,size_t pktlen,int * comprloop)522 int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
523 	uint8_t* pkt, size_t pktlen, int* comprloop)
524 {
525 	int w = 0;
526 	uint8_t* rr = *d;
527 	size_t rrlen = *dlen, dname_off, rdlen, ordlen;
528 	uint16_t rrtype = 0;
529 
530 	if(*dlen >= 3 && (*d)[0]==0 &&
531 		sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) {
532 		/* perform EDNS OPT processing */
533 		return sldns_wire2str_edns_scan(d, dlen, s, slen, pkt, pktlen);
534 	}
535 
536 	/* try to scan the rdata with pretty-printing, but if that fails, then
537 	 * scan the rdata as an unknown RR type */
538 	w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
539 	w += sldns_str_print(s, slen, "\t");
540 	dname_off = rrlen-(*dlen);
541 	if(*dlen == 4) {
542 		/* like a question-RR */
543 		uint16_t t = sldns_read_uint16(*d);
544 		uint16_t c = sldns_read_uint16((*d)+2);
545 		(*d)+=4;
546 		(*dlen)-=4;
547 		w += sldns_wire2str_class_print(s, slen, c);
548 		w += sldns_str_print(s, slen, "\t");
549 		w += sldns_wire2str_type_print(s, slen, t);
550 		w += sldns_str_print(s, slen, " ; Error no ttl,rdata\n");
551 		return w;
552 	}
553 	if(*dlen < 8) {
554 		if(*dlen == 0)
555 			return w + sldns_str_print(s, slen, ";Error missing RR\n");
556 		w += print_remainder_hex(";Error partial RR 0x", d, dlen, s, slen);
557 		return w + sldns_str_print(s, slen, "\n");
558 	}
559 	rrtype = sldns_read_uint16(*d);
560 	w += sldns_rr_tcttl_scan(d, dlen, s, slen);
561 	w += sldns_str_print(s, slen, "\t");
562 
563 	/* rdata */
564 	if(*dlen < 2) {
565 		if(*dlen == 0)
566 			return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
567 		w += print_remainder_hex(";Error missing rdatalen 0x",
568 			d, dlen, s, slen);
569 		return w + sldns_str_print(s, slen, "\n");
570 	}
571 	rdlen = sldns_read_uint16(*d);
572 	ordlen = rdlen;
573 	(*d)+=2;
574 	(*dlen)-=2;
575 	if(*dlen < rdlen) {
576 		w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
577 		if(*dlen == 0)
578 			return w + sldns_str_print(s, slen, ";Error missing rdata\n");
579 		w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
580 		return w + sldns_str_print(s, slen, "\n");
581 	}
582 	w += sldns_wire2str_rdata_scan(d, &rdlen, s, slen, rrtype, pkt, pktlen,
583 		comprloop);
584 	(*dlen) -= (ordlen-rdlen);
585 
586 	/* default comment */
587 	w += sldns_wire2str_rr_comment_print(s, slen, rr, rrlen, dname_off,
588 		rrtype);
589 	w += sldns_str_print(s, slen, "\n");
590 	return w;
591 }
592 
sldns_wire2str_rrquestion_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen,uint8_t * pkt,size_t pktlen,int * comprloop)593 int sldns_wire2str_rrquestion_scan(uint8_t** d, size_t* dlen, char** s,
594 	size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop)
595 {
596 	int w = 0;
597 	uint16_t t, c;
598 	w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
599 	w += sldns_str_print(s, slen, "\t");
600 	if(*dlen < 4) {
601 		if(*dlen == 0)
602 			return w + sldns_str_print(s, slen, "Error malformed\n");
603 		w += print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
604 		return w + sldns_str_print(s, slen, "\n");
605 	}
606 	t = sldns_read_uint16(*d);
607 	c = sldns_read_uint16((*d)+2);
608 	(*d)+=4;
609 	(*dlen)-=4;
610 	w += sldns_wire2str_class_print(s, slen, c);
611 	w += sldns_str_print(s, slen, "\t");
612 	w += sldns_wire2str_type_print(s, slen, t);
613 	w += sldns_str_print(s, slen, "\n");
614 	return w;
615 }
616 
sldns_wire2str_rr_unknown_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen,uint8_t * pkt,size_t pktlen,int * comprloop)617 int sldns_wire2str_rr_unknown_scan(uint8_t** d, size_t* dlen, char** s,
618 	size_t* slen, uint8_t* pkt, size_t pktlen, int* comprloop)
619 {
620 	size_t rdlen, ordlen;
621 	int w = 0;
622 	w += sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
623 	w += sldns_str_print(s, slen, "\t");
624 	w += sldns_rr_tcttl_scan(d, dlen, s, slen);
625 	w += sldns_str_print(s, slen, "\t");
626 	if(*dlen < 2) {
627 		if(*dlen == 0)
628 			return w + sldns_str_print(s, slen, ";Error missing rdatalen\n");
629 		w += print_remainder_hex(";Error missing rdatalen 0x",
630 			d, dlen, s, slen);
631 		return w + sldns_str_print(s, slen, "\n");
632 	}
633 	rdlen = sldns_read_uint16(*d);
634 	ordlen = rdlen;
635 	(*d) += 2;
636 	(*dlen) -= 2;
637 	if(*dlen < rdlen) {
638 		w += sldns_str_print(s, slen, "\\# %u ", (unsigned)rdlen);
639 		if(*dlen == 0)
640 			return w + sldns_str_print(s, slen, ";Error missing rdata\n");
641 		w += print_remainder_hex(";Error partial rdata 0x", d, dlen, s, slen);
642 		return w + sldns_str_print(s, slen, "\n");
643 	}
644 	w += sldns_wire2str_rdata_unknown_scan(d, &rdlen, s, slen);
645 	(*dlen) -= (ordlen-rdlen);
646 	w += sldns_str_print(s, slen, "\n");
647 	return w;
648 }
649 
650 /** print rr comment for type DNSKEY */
rr_comment_dnskey(char ** s,size_t * slen,uint8_t * rr,size_t rrlen,size_t dname_off)651 static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr,
652 	size_t rrlen, size_t dname_off)
653 {
654 	size_t rdlen;
655 	uint8_t* rdata;
656 	int flags, w = 0;
657 	if(rrlen < dname_off + 10) return 0;
658 	rdlen = sldns_read_uint16(rr+dname_off+8);
659 	if(rrlen < dname_off + 10 + rdlen) return 0;
660 	if(rdlen < 2) return 0;
661 	rdata = rr + dname_off + 10;
662 	flags = (int)sldns_read_uint16(rdata);
663 	w += sldns_str_print(s, slen, " ;{");
664 
665 	/* id */
666 	w += sldns_str_print(s, slen, "id = %u",
667 		sldns_calc_keytag_raw(rdata, rdlen));
668 
669 	/* flags */
670 	if((flags&LDNS_KEY_ZONE_KEY)) {
671 		if((flags&LDNS_KEY_SEP_KEY))
672 			w += sldns_str_print(s, slen, " (ksk)");
673 		else 	w += sldns_str_print(s, slen, " (zsk)");
674 	}
675 
676 	/* keysize */
677 	if(rdlen > 4) {
678 		w += sldns_str_print(s, slen, ", ");
679 		w += sldns_str_print(s, slen, "size = %db",
680 			(int)sldns_rr_dnskey_key_size_raw(
681 			(unsigned char*)rdata+4, rdlen-4, (int)(rdata[3])));
682 	}
683 
684 	w += sldns_str_print(s, slen, "}");
685 	return w;
686 }
687 
688 /** print rr comment for type RRSIG */
rr_comment_rrsig(char ** s,size_t * slen,uint8_t * rr,size_t rrlen,size_t dname_off)689 static int rr_comment_rrsig(char** s, size_t* slen, uint8_t* rr,
690 	size_t rrlen, size_t dname_off)
691 {
692 	size_t rdlen;
693 	uint8_t* rdata;
694 	if(rrlen < dname_off + 10) return 0;
695 	rdlen = sldns_read_uint16(rr+dname_off+8);
696 	if(rrlen < dname_off + 10 + rdlen) return 0;
697 	rdata = rr + dname_off + 10;
698 	if(rdlen < 18) return 0;
699 	return sldns_str_print(s, slen, " ;{id = %d}",
700 		(int)sldns_read_uint16(rdata+16));
701 }
702 
703 /** print rr comment for type NSEC3 */
rr_comment_nsec3(char ** s,size_t * slen,uint8_t * rr,size_t rrlen,size_t dname_off)704 static int rr_comment_nsec3(char** s, size_t* slen, uint8_t* rr,
705 	size_t rrlen, size_t dname_off)
706 {
707 	size_t rdlen;
708 	uint8_t* rdata;
709 	int w = 0;
710 	if(rrlen < dname_off + 10) return 0;
711 	rdlen = sldns_read_uint16(rr+dname_off+8);
712 	if(rrlen < dname_off + 10 + rdlen) return 0;
713 	rdata = rr + dname_off + 10;
714 	if(rdlen < 2) return 0;
715 	if((rdata[1] & LDNS_NSEC3_VARS_OPTOUT_MASK))
716 		w += sldns_str_print(s, slen, " ;{flags: optout}");
717 	return w;
718 }
719 
sldns_wire2str_rr_comment_print(char ** s,size_t * slen,uint8_t * rr,size_t rrlen,size_t dname_off,uint16_t rrtype)720 int sldns_wire2str_rr_comment_print(char** s, size_t* slen, uint8_t* rr,
721 	size_t rrlen, size_t dname_off, uint16_t rrtype)
722 {
723 	if(rrtype == LDNS_RR_TYPE_DNSKEY) {
724 		return rr_comment_dnskey(s, slen, rr, rrlen, dname_off);
725 	} else if(rrtype == LDNS_RR_TYPE_RRSIG) {
726 		return rr_comment_rrsig(s, slen, rr, rrlen, dname_off);
727 	} else if(rrtype == LDNS_RR_TYPE_NSEC3) {
728 		return rr_comment_nsec3(s, slen, rr, rrlen, dname_off);
729 	}
730 	return 0;
731 }
732 
sldns_wire2str_header_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen)733 int sldns_wire2str_header_scan(uint8_t** d, size_t* dlen, char** s,
734 	size_t* slen)
735 {
736 	int w = 0;
737 	int opcode, rcode;
738 	w += sldns_str_print(s, slen, ";; ->>HEADER<<- ");
739 	if(*dlen == 0)
740 		return w+sldns_str_print(s, slen, "Error empty packet");
741 	if(*dlen < 4)
742 		return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
743 	opcode = (int)LDNS_OPCODE_WIRE(*d);
744 	rcode = (int)LDNS_RCODE_WIRE(*d);
745 	w += sldns_str_print(s, slen, "opcode: ");
746 	w += sldns_wire2str_opcode_print(s, slen, opcode);
747 	w += sldns_str_print(s, slen, ", ");
748 	w += sldns_str_print(s, slen, "rcode: ");
749 	w += sldns_wire2str_rcode_print(s, slen, rcode);
750 	w += sldns_str_print(s, slen, ", ");
751 	w += sldns_str_print(s, slen, "id: %d\n", (int)LDNS_ID_WIRE(*d));
752 	w += sldns_str_print(s, slen, ";; flags:");
753 	if(LDNS_QR_WIRE(*d)) w += sldns_str_print(s, slen, " qr");
754 	if(LDNS_AA_WIRE(*d)) w += sldns_str_print(s, slen, " aa");
755 	if(LDNS_TC_WIRE(*d)) w += sldns_str_print(s, slen, " tc");
756 	if(LDNS_RD_WIRE(*d)) w += sldns_str_print(s, slen, " rd");
757 	if(LDNS_CD_WIRE(*d)) w += sldns_str_print(s, slen, " cd");
758 	if(LDNS_RA_WIRE(*d)) w += sldns_str_print(s, slen, " ra");
759 	if(LDNS_AD_WIRE(*d)) w += sldns_str_print(s, slen, " ad");
760 	if(LDNS_Z_WIRE(*d))  w += sldns_str_print(s, slen, " z");
761 	w += sldns_str_print(s, slen, " ; ");
762 	if(*dlen < LDNS_HEADER_SIZE)
763 		return w+print_remainder_hex("Error header too short 0x", d, dlen, s, slen);
764 	w += sldns_str_print(s, slen, "QUERY: %d, ", (int)LDNS_QDCOUNT(*d));
765 	w += sldns_str_print(s, slen, "ANSWER: %d, ", (int)LDNS_ANCOUNT(*d));
766 	w += sldns_str_print(s, slen, "AUTHORITY: %d, ", (int)LDNS_NSCOUNT(*d));
767 	w += sldns_str_print(s, slen, "ADDITIONAL: %d ", (int)LDNS_ARCOUNT(*d));
768 	*d += LDNS_HEADER_SIZE;
769 	*dlen -= LDNS_HEADER_SIZE;
770 	return w;
771 }
772 
sldns_wire2str_rdata_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen,uint16_t rrtype,uint8_t * pkt,size_t pktlen,int * comprloop)773 int sldns_wire2str_rdata_scan(uint8_t** d, size_t* dlen, char** s,
774 	size_t* slen, uint16_t rrtype, uint8_t* pkt, size_t pktlen,
775 	int* comprloop)
776 {
777 	/* try to prettyprint, but if that fails, use unknown format */
778 	uint8_t* origd = *d;
779 	char* origs = *s;
780 	size_t origdlen = *dlen, origslen = *slen;
781 	size_t r_cnt, r_max;
782 	sldns_rdf_type rdftype;
783 	int w = 0, n;
784 
785 	const sldns_rr_descriptor *desc = sldns_rr_descript(rrtype);
786 	if(!desc) /* unknown format */
787 		return sldns_wire2str_rdata_unknown_scan(d, dlen, s, slen);
788 	/* dlen equals the rdatalen for the rdata */
789 
790 	r_max = sldns_rr_descriptor_maximum(desc);
791 	for(r_cnt=0; r_cnt < r_max; r_cnt++) {
792 		if(*dlen == 0) {
793 			if(r_cnt < sldns_rr_descriptor_minimum(desc))
794 				goto failed;
795 			break; /* nothing more to print */
796 		}
797 		rdftype = sldns_rr_descriptor_field_type(desc, r_cnt);
798 		if(r_cnt != 0)
799 			w += sldns_str_print(s, slen, " ");
800 		n = sldns_wire2str_rdf_scan(d, dlen, s, slen, rdftype,
801 			pkt, pktlen, comprloop);
802 		if(n == -1) {
803 		failed:
804 			/* failed, use unknown format */
805 			*d = origd; *s = origs;
806 			*dlen = origdlen; *slen = origslen;
807 			return sldns_wire2str_rdata_unknown_scan(d, dlen,
808 				s, slen);
809 		}
810 		w += n;
811 	}
812 	if(*dlen != 0) {
813 		goto failed;
814 	}
815 	return w;
816 }
817 
sldns_wire2str_rdata_unknown_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen)818 int sldns_wire2str_rdata_unknown_scan(uint8_t** d, size_t* dlen, char** s,
819 	size_t* slen)
820 {
821 	int w = 0;
822 
823 	/* print length */
824 	w += sldns_str_print(s, slen, "\\# %u", (unsigned)*dlen);
825 
826 	/* print rdlen in hex */
827 	if(*dlen != 0)
828 		w += sldns_str_print(s, slen, " ");
829 	w += print_hex_buf(s, slen, *d, *dlen);
830 	(*d) += *dlen;
831 	(*dlen) = 0;
832 	return w;
833 }
834 
835 /** print and escape one character for a domain dname */
dname_char_print(char ** s,size_t * slen,uint8_t c)836 static int dname_char_print(char** s, size_t* slen, uint8_t c)
837 {
838 	if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\')
839 		return sldns_str_print(s, slen, "\\%c", c);
840 	else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c)))
841 		return sldns_str_print(s, slen, "\\%03u", (unsigned)c);
842 	/* plain printout */
843 	if(*slen) {
844 		**s = (char)c;
845 		(*s)++;
846 		(*slen)--;
847 	}
848 	return 1;
849 }
850 
sldns_wire2str_dname_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen,uint8_t * pkt,size_t pktlen,int * comprloop)851 int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
852 	uint8_t* pkt, size_t pktlen, int* comprloop)
853 {
854 	int w = 0;
855 	/* spool labels onto the string, use compression if its there */
856 	uint8_t* pos = *d;
857 	unsigned i, counter=0;
858 	unsigned maxcompr = MAX_COMPRESS_PTRS; /* loop detection, max compr ptrs */
859 	int in_buf = 1;
860 	size_t dname_len = 0;
861 	if(comprloop) {
862 		if(*comprloop != 0)
863 			maxcompr = 30; /* for like ipv6 reverse name, per label */
864 		if(*comprloop > 4)
865 			maxcompr = 4; /* just don't want to spend time, any more */
866 	}
867 	if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname");
868 	if(*pos == 0) {
869 		(*d)++;
870 		(*dlen)--;
871 		return sldns_str_print(s, slen, ".");
872 	}
873 	while((!pkt || pos < pkt+pktlen) && *pos) {
874 		/* read label length */
875 		uint8_t labellen = *pos++;
876 		if(in_buf) { (*d)++; (*dlen)--; }
877 
878 		/* find out what sort of label we have */
879 		if((labellen&0xc0) == 0xc0) {
880 			/* compressed */
881 			uint16_t target = 0;
882 			if(in_buf && *dlen == 0)
883 				return w + sldns_str_print(s, slen,
884 					"ErrorPartialDname");
885 			else if(!in_buf && pos+1 > pkt+pktlen)
886 				return w + sldns_str_print(s, slen,
887 					"ErrorPartialDname");
888 			target = ((labellen&0x3f)<<8) | *pos;
889 			if(in_buf) { (*d)++; (*dlen)--; }
890 			/* move to target, if possible */
891 			if(!pkt || target >= pktlen)
892 				return w + sldns_str_print(s, slen,
893 					"ErrorComprPtrOutOfBounds");
894 			if(counter++ > maxcompr) {
895 				if(comprloop && *comprloop < 10)
896 					(*comprloop)++;
897 				return w + sldns_str_print(s, slen,
898 					"ErrorComprPtrLooped");
899 			}
900 			in_buf = 0;
901 			pos = pkt+target;
902 			continue;
903 		} else if((labellen&0xc0)) {
904 			/* notimpl label type */
905 			w += sldns_str_print(s, slen,
906 				"ErrorLABELTYPE%xIsUnknown",
907 				(int)(labellen&0xc0));
908 			return w;
909 		}
910 
911 		/* spool label characters, end with '.' */
912 		if(in_buf && *dlen < (size_t)labellen)
913 			labellen = (uint8_t)*dlen;
914 		else if(!in_buf && pos+(size_t)labellen > pkt+pktlen)
915 			labellen = (uint8_t)(pkt + pktlen - pos);
916 		dname_len += ((size_t)labellen)+1;
917 		if(dname_len > LDNS_MAX_DOMAINLEN) {
918 			/* dname_len counts the uncompressed length we have
919 			 * seen so far, and the domain name has become too
920 			 * long, prevent the loop from printing overly long
921 			 * content. */
922 			w += sldns_str_print(s, slen,
923 				"ErrorDomainNameTooLong");
924 			return w;
925 		}
926 		for(i=0; i<(unsigned)labellen; i++) {
927 			w += dname_char_print(s, slen, *pos++);
928 		}
929 		if(in_buf) {
930 			(*d) += labellen;
931 			(*dlen) -= labellen;
932 			if(*dlen == 0) break;
933 		}
934 		w += sldns_str_print(s, slen, ".");
935 	}
936 	/* skip over final root label */
937 	if(in_buf && *dlen > 0) { (*d)++; (*dlen)--; }
938 	/* in case we printed no labels, terminate dname */
939 	if(w == 0) w += sldns_str_print(s, slen, ".");
940 	return w;
941 }
942 
sldns_wire2str_opcode_print(char ** s,size_t * slen,int opcode)943 int sldns_wire2str_opcode_print(char** s, size_t* slen, int opcode)
944 {
945 	sldns_lookup_table *lt = sldns_lookup_by_id(sldns_opcodes, opcode);
946 	if (lt && lt->name) {
947 		return sldns_str_print(s, slen, "%s", lt->name);
948 	}
949 	return sldns_str_print(s, slen, "OPCODE%u", (unsigned)opcode);
950 }
951 
sldns_wire2str_rcode_print(char ** s,size_t * slen,int rcode)952 int sldns_wire2str_rcode_print(char** s, size_t* slen, int rcode)
953 {
954 	sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rcodes, rcode);
955 	if (lt && lt->name) {
956 		return sldns_str_print(s, slen, "%s", lt->name);
957 	}
958 	return sldns_str_print(s, slen, "RCODE%u", (unsigned)rcode);
959 }
960 
sldns_wire2str_class_print(char ** s,size_t * slen,uint16_t rrclass)961 int sldns_wire2str_class_print(char** s, size_t* slen, uint16_t rrclass)
962 {
963 	sldns_lookup_table *lt = sldns_lookup_by_id(sldns_rr_classes,
964 		(int)rrclass);
965 	if (lt && lt->name) {
966 		return sldns_str_print(s, slen, "%s", lt->name);
967 	}
968 	return sldns_str_print(s, slen, "CLASS%u", (unsigned)rrclass);
969 }
970 
sldns_wire2str_type_print(char ** s,size_t * slen,uint16_t rrtype)971 int sldns_wire2str_type_print(char** s, size_t* slen, uint16_t rrtype)
972 {
973 	const sldns_rr_descriptor *descriptor = sldns_rr_descript(rrtype);
974 	if (descriptor && descriptor->_name) {
975 		return sldns_str_print(s, slen, "%s", descriptor->_name);
976 	}
977 	return sldns_str_print(s, slen, "TYPE%u", (unsigned)rrtype);
978 }
979 
sldns_wire2str_edns_option_code_print(char ** s,size_t * slen,uint16_t opcode)980 int sldns_wire2str_edns_option_code_print(char** s, size_t* slen,
981 	uint16_t opcode)
982 {
983 	sldns_lookup_table *lt = sldns_lookup_by_id(sldns_edns_options,
984 		(int)opcode);
985 	if (lt && lt->name) {
986 		return sldns_str_print(s, slen, "%s", lt->name);
987 	}
988 	return sldns_str_print(s, slen, "OPT%u", (unsigned)opcode);
989 }
990 
sldns_wire2str_class_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen)991 int sldns_wire2str_class_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
992 {
993 	uint16_t c;
994 	if(*dlen == 0) return 0;
995 	if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
996 	c = sldns_read_uint16(*d);
997 	(*d)+=2;
998 	(*dlen)-=2;
999 	return sldns_wire2str_class_print(s, slen, c);
1000 }
1001 
sldns_wire2str_type_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen)1002 int sldns_wire2str_type_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
1003 {
1004 	uint16_t t;
1005 	if(*dlen == 0) return 0;
1006 	if(*dlen < 2) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
1007 	t = sldns_read_uint16(*d);
1008 	(*d)+=2;
1009 	(*dlen)-=2;
1010 	return sldns_wire2str_type_print(s, slen, t);
1011 }
1012 
sldns_wire2str_ttl_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen)1013 int sldns_wire2str_ttl_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
1014 {
1015 	uint32_t ttl;
1016 	if(*dlen == 0) return 0;
1017 	if(*dlen < 4) return print_remainder_hex("Error malformed 0x", d, dlen, s, slen);
1018 	ttl = sldns_read_uint32(*d);
1019 	(*d)+=4;
1020 	(*dlen)-=4;
1021 	return sldns_str_print(s, slen, "%u", (unsigned)ttl);
1022 }
1023 
1024 static int
sldns_print_svcparamkey(char ** s,size_t * slen,uint16_t svcparamkey)1025 sldns_print_svcparamkey(char** s, size_t* slen, uint16_t svcparamkey)
1026 {
1027 	if (svcparamkey < SVCPARAMKEY_COUNT) {
1028 		return sldns_str_print(s, slen, "%s", svcparamkey_strs[svcparamkey]);
1029 	}
1030 	else {
1031 		return sldns_str_print(s, slen, "key%d", (int)svcparamkey);
1032 	}
1033 }
1034 
sldns_wire2str_svcparam_port2str(char ** s,size_t * slen,uint16_t data_len,uint8_t * data)1035 static int sldns_wire2str_svcparam_port2str(char** s,
1036 	size_t* slen, uint16_t data_len, uint8_t* data)
1037 {
1038 	int w = 0;
1039 
1040 	if (data_len != 2)
1041 		return -1; /* wireformat error, a short is 2 bytes */
1042 	w = sldns_str_print(s, slen, "=%d", (int)sldns_read_uint16(data));
1043 
1044 	return w;
1045 }
1046 
sldns_wire2str_svcparam_ipv4hint2str(char ** s,size_t * slen,uint16_t data_len,uint8_t * data)1047 static int sldns_wire2str_svcparam_ipv4hint2str(char** s,
1048 	size_t* slen, uint16_t data_len, uint8_t* data)
1049 {
1050 	char ip_str[INET_ADDRSTRLEN + 1];
1051 
1052 	int w = 0;
1053 
1054 	assert(data_len > 0);
1055 
1056 	if ((data_len % LDNS_IP4ADDRLEN) == 0) {
1057 		if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
1058 			return -1; /* wireformat error, incorrect size or inet family */
1059 
1060 		w += sldns_str_print(s, slen, "=%s", ip_str);
1061 		data += LDNS_IP4ADDRLEN;
1062 
1063 		while ((data_len -= LDNS_IP4ADDRLEN) > 0) {
1064 			if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL)
1065 				return -1; /* wireformat error, incorrect size or inet family */
1066 
1067 			w += sldns_str_print(s, slen, ",%s", ip_str);
1068 			data += LDNS_IP4ADDRLEN;
1069 		}
1070 	} else
1071 		return -1;
1072 
1073 	return w;
1074 }
1075 
sldns_wire2str_svcparam_ipv6hint2str(char ** s,size_t * slen,uint16_t data_len,uint8_t * data)1076 static int sldns_wire2str_svcparam_ipv6hint2str(char** s,
1077 	size_t* slen, uint16_t data_len, uint8_t* data)
1078 {
1079 	char ip_str[INET6_ADDRSTRLEN + 1];
1080 
1081 	int w = 0;
1082 
1083 	assert(data_len > 0);
1084 
1085 	if ((data_len % LDNS_IP6ADDRLEN) == 0) {
1086 		if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
1087 			return -1; /* wireformat error, incorrect size or inet family */
1088 
1089 		w += sldns_str_print(s, slen, "=%s", ip_str);
1090 		data += LDNS_IP6ADDRLEN;
1091 
1092 		while ((data_len -= LDNS_IP6ADDRLEN) > 0) {
1093 			if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL)
1094 				return -1; /* wireformat error, incorrect size or inet family */
1095 
1096 			w += sldns_str_print(s, slen, ",%s", ip_str);
1097 			data += LDNS_IP6ADDRLEN;
1098 		}
1099 	} else
1100 		return -1;
1101 
1102 	return w;
1103 }
1104 
sldns_wire2str_svcparam_mandatory2str(char ** s,size_t * slen,uint16_t data_len,uint8_t * data)1105 static int sldns_wire2str_svcparam_mandatory2str(char** s,
1106 	size_t* slen, uint16_t data_len, uint8_t* data)
1107 {
1108 	int w = 0;
1109 
1110 	assert(data_len > 0);
1111 
1112 	if (data_len % sizeof(uint16_t))
1113 		return -1; /* wireformat error, data_len must be multiple of shorts */
1114 	w += sldns_str_print(s, slen, "=");
1115 	w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
1116 	data += 2;
1117 
1118 	while ((data_len -= sizeof(uint16_t))) {
1119 		w += sldns_str_print(s, slen, ",");
1120 		w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
1121 		data += 2;
1122 	}
1123 
1124 	return w;
1125 }
1126 
sldns_wire2str_svcparam_alpn2str(char ** s,size_t * slen,uint16_t data_len,uint8_t * data)1127 static int sldns_wire2str_svcparam_alpn2str(char** s,
1128 	size_t* slen, uint16_t data_len, uint8_t* data)
1129 {
1130 	uint8_t *dp = (void *)data;
1131 	int w = 0;
1132 
1133 	assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */
1134 
1135 	w += sldns_str_print(s, slen, "=\"");
1136 	while (data_len) {
1137 		/* alpn is list of length byte (str_len) followed by a string of that size */
1138 		uint8_t i, str_len = *dp++;
1139 
1140 		if (str_len > --data_len)
1141 			return -1;
1142 
1143 		for (i = 0; i < str_len; i++) {
1144 			if (dp[i] == '"' || dp[i] == '\\')
1145 				w += sldns_str_print(s, slen, "\\\\\\%c", dp[i]);
1146 
1147 			else if (dp[i] == ',')
1148 				w += sldns_str_print(s, slen, "\\\\%c", dp[i]);
1149 
1150 			else if (!isprint(dp[i]))
1151 				w += sldns_str_print(s, slen, "\\%03u", (unsigned) dp[i]);
1152 
1153 			else
1154 				w += sldns_str_print(s, slen, "%c", dp[i]);
1155 		}
1156 		dp += str_len;
1157 		if ((data_len -= str_len))
1158 			w += sldns_str_print(s, slen, "%s", ",");
1159 	}
1160 	w += sldns_str_print(s, slen, "\"");
1161 
1162 	return w;
1163 }
1164 
sldns_wire2str_svcparam_ech2str(char ** s,size_t * slen,uint16_t data_len,uint8_t * data)1165 static int sldns_wire2str_svcparam_ech2str(char** s,
1166 	size_t* slen, uint16_t data_len, uint8_t* data)
1167 {
1168 	int size;
1169 	int w = 0;
1170 
1171 	assert(data_len > 0); /* Guaranteed by sldns_wire2str_svcparam_scan */
1172 
1173 	w += sldns_str_print(s, slen, "=\"");
1174 
1175 	if ((size = sldns_b64_ntop(data, data_len, *s, *slen)) < 0)
1176 		return -1;
1177 
1178 	(*s) += size;
1179 	(*slen) -= size;
1180 
1181 	w += sldns_str_print(s, slen, "\"");
1182 
1183 	return w + size;
1184 }
1185 
sldns_wire2str_svcparam_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen)1186 int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen)
1187 {
1188 	uint8_t ch;
1189 	uint16_t svcparamkey, data_len;
1190 	int written_chars = 0;
1191 	int r, i;
1192 
1193 	/* verify that we have enough data to read svcparamkey and data_len */
1194 	if(*dlen < 4)
1195 		return -1;
1196 
1197 	svcparamkey = sldns_read_uint16(*d);
1198 	data_len = sldns_read_uint16(*d+2);
1199 	*d    += 4;
1200 	*dlen -= 4;
1201 
1202 	/* verify that we have data_len data */
1203 	if (data_len > *dlen)
1204 		return -1;
1205 
1206 	written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
1207 	if (!data_len) {
1208 
1209 	 	/* Some SvcParams MUST have values */
1210 	 	switch (svcparamkey) {
1211 	 	case SVCB_KEY_ALPN:
1212 	 	case SVCB_KEY_PORT:
1213 	 	case SVCB_KEY_IPV4HINT:
1214 	 	case SVCB_KEY_IPV6HINT:
1215 	 	case SVCB_KEY_MANDATORY:
1216 	 	case SVCB_KEY_DOHPATH:
1217 	 		return -1;
1218 	 	default:
1219 	 		return written_chars;
1220 	 	}
1221 	}
1222 
1223 	switch (svcparamkey) {
1224 	case SVCB_KEY_PORT:
1225 		r = sldns_wire2str_svcparam_port2str(s, slen, data_len, *d);
1226 		break;
1227 	case SVCB_KEY_IPV4HINT:
1228 		r = sldns_wire2str_svcparam_ipv4hint2str(s, slen, data_len, *d);
1229 		break;
1230 	case SVCB_KEY_IPV6HINT:
1231 		r = sldns_wire2str_svcparam_ipv6hint2str(s, slen, data_len, *d);
1232 		break;
1233 	case SVCB_KEY_MANDATORY:
1234 		r = sldns_wire2str_svcparam_mandatory2str(s, slen, data_len, *d);
1235 		break;
1236 	case SVCB_KEY_NO_DEFAULT_ALPN:
1237 		return -1;  /* wireformat error, should not have a value */
1238 	case SVCB_KEY_ALPN:
1239 		r = sldns_wire2str_svcparam_alpn2str(s, slen, data_len, *d);
1240 		break;
1241 	case SVCB_KEY_ECH:
1242 		r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
1243 		break;
1244 	case SVCB_KEY_DOHPATH:
1245 		ATTR_FALLTHROUGH
1246 		/* fallthrough */
1247 	default:
1248 		r = sldns_str_print(s, slen, "=\"");
1249 
1250 		for (i = 0; i < data_len; i++) {
1251 			ch = (*d)[i];
1252 
1253 			if (ch == '"' || ch == '\\')
1254 				r += sldns_str_print(s, slen, "\\%c", ch);
1255 
1256 			else if (!isprint(ch))
1257 				r += sldns_str_print(s, slen, "\\%03u", (unsigned) ch);
1258 
1259 			else
1260 				r += sldns_str_print(s, slen, "%c", ch);
1261 
1262 		}
1263 		r += sldns_str_print(s, slen, "\"");
1264 		break;
1265 	}
1266 	if (r <= 0)
1267 		return -1; /* wireformat error */
1268 
1269 	written_chars += r;
1270 	*d    += data_len;
1271 	*dlen -= data_len;
1272 	return written_chars;
1273 }
1274 
sldns_wire2str_rdf_scan(uint8_t ** d,size_t * dlen,char ** s,size_t * slen,int rdftype,uint8_t * pkt,size_t pktlen,int * comprloop)1275 int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
1276 	int rdftype, uint8_t* pkt, size_t pktlen, int* comprloop)
1277 {
1278 	if(*dlen == 0) return 0;
1279 	switch(rdftype) {
1280 	case LDNS_RDF_TYPE_NONE:
1281 		return 0;
1282 	case LDNS_RDF_TYPE_DNAME:
1283 		return sldns_wire2str_dname_scan(d, dlen, s, slen, pkt, pktlen, comprloop);
1284 	case LDNS_RDF_TYPE_INT8:
1285 		return sldns_wire2str_int8_scan(d, dlen, s, slen);
1286 	case LDNS_RDF_TYPE_INT16:
1287 		return sldns_wire2str_int16_scan(d, dlen, s, slen);
1288 	case LDNS_RDF_TYPE_INT32:
1289 		return sldns_wire2str_int32_scan(d, dlen, s, slen);
1290 	case LDNS_RDF_TYPE_PERIOD:
1291 		return sldns_wire2str_period_scan(d, dlen, s, slen);
1292 	case LDNS_RDF_TYPE_TSIGTIME:
1293 		return sldns_wire2str_tsigtime_scan(d, dlen, s, slen);
1294 	case LDNS_RDF_TYPE_A:
1295 		return sldns_wire2str_a_scan(d, dlen, s, slen);
1296 	case LDNS_RDF_TYPE_AAAA:
1297 		return sldns_wire2str_aaaa_scan(d, dlen, s, slen);
1298 	case LDNS_RDF_TYPE_STR:
1299 		return sldns_wire2str_str_scan(d, dlen, s, slen);
1300 	case LDNS_RDF_TYPE_APL:
1301 		return sldns_wire2str_apl_scan(d, dlen, s, slen);
1302 	case LDNS_RDF_TYPE_B32_EXT:
1303 		return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
1304 	case LDNS_RDF_TYPE_B64:
1305 		return sldns_wire2str_b64_scan(d, dlen, s, slen);
1306 	case LDNS_RDF_TYPE_HEX:
1307 		return sldns_wire2str_hex_scan(d, dlen, s, slen);
1308 	case LDNS_RDF_TYPE_NSEC:
1309 		return sldns_wire2str_nsec_scan(d, dlen, s, slen);
1310 	case LDNS_RDF_TYPE_NSEC3_SALT:
1311 		return sldns_wire2str_nsec3_salt_scan(d, dlen, s, slen);
1312 	case LDNS_RDF_TYPE_TYPE:
1313 		return sldns_wire2str_type_scan(d, dlen, s, slen);
1314 	case LDNS_RDF_TYPE_CLASS:
1315 		return sldns_wire2str_class_scan(d, dlen, s, slen);
1316 	case LDNS_RDF_TYPE_CERT_ALG:
1317 		return sldns_wire2str_cert_alg_scan(d, dlen, s, slen);
1318 	case LDNS_RDF_TYPE_ALG:
1319 		return sldns_wire2str_alg_scan(d, dlen, s, slen);
1320 	case LDNS_RDF_TYPE_UNKNOWN:
1321 		return sldns_wire2str_unknown_scan(d, dlen, s, slen);
1322 	case LDNS_RDF_TYPE_TIME:
1323 		return sldns_wire2str_time_scan(d, dlen, s, slen);
1324 	case LDNS_RDF_TYPE_LOC:
1325 		return sldns_wire2str_loc_scan(d, dlen, s, slen);
1326 	case LDNS_RDF_TYPE_WKS:
1327 	case LDNS_RDF_TYPE_SERVICE:
1328 		return sldns_wire2str_wks_scan(d, dlen, s, slen);
1329 	case LDNS_RDF_TYPE_NSAP:
1330 		return sldns_wire2str_nsap_scan(d, dlen, s, slen);
1331 	case LDNS_RDF_TYPE_ATMA:
1332 		return sldns_wire2str_atma_scan(d, dlen, s, slen);
1333 	case LDNS_RDF_TYPE_IPSECKEY:
1334 		return sldns_wire2str_ipseckey_scan(d, dlen, s, slen, pkt,
1335 			pktlen, comprloop);
1336 	case LDNS_RDF_TYPE_HIP:
1337 		return sldns_wire2str_hip_scan(d, dlen, s, slen);
1338 	case LDNS_RDF_TYPE_INT16_DATA:
1339 		return sldns_wire2str_int16_data_scan(d, dlen, s, slen);
1340 	case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
1341 		return sldns_wire2str_b32_ext_scan(d, dlen, s, slen);
1342 	case LDNS_RDF_TYPE_ILNP64:
1343 		return sldns_wire2str_ilnp64_scan(d, dlen, s, slen);
1344 	case LDNS_RDF_TYPE_EUI48:
1345 		return sldns_wire2str_eui48_scan(d, dlen, s, slen);
1346 	case LDNS_RDF_TYPE_EUI64:
1347 		return sldns_wire2str_eui64_scan(d, dlen, s, slen);
1348 	case LDNS_RDF_TYPE_UNQUOTED:
1349 		return sldns_wire2str_unquoted_scan(d, dlen, s, slen);
1350 	case LDNS_RDF_TYPE_TAG:
1351 		return sldns_wire2str_tag_scan(d, dlen, s, slen);
1352 	case LDNS_RDF_TYPE_LONG_STR:
1353 		return sldns_wire2str_long_str_scan(d, dlen, s, slen);
1354 	case LDNS_RDF_TYPE_SVCPARAM:
1355 		return sldns_wire2str_svcparam_scan(d, dlen, s, slen);
1356 	case LDNS_RDF_TYPE_TSIGERROR:
1357 		return sldns_wire2str_tsigerror_scan(d, dlen, s, slen);
1358 	}
1359 	/* unknown rdf type */
1360 	return -1;
1361 }
1362 
sldns_wire2str_int8_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1363 int sldns_wire2str_int8_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1364 {
1365 	int w;
1366 	if(*dl < 1) return -1;
1367 	w = sldns_str_print(s, sl, "%u", (unsigned)**d);
1368 	(*d)++;
1369 	(*dl)--;
1370 	return w;
1371 }
1372 
sldns_wire2str_int16_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1373 int sldns_wire2str_int16_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1374 {
1375 	int w;
1376 	if(*dl < 2) return -1;
1377 	w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint16(*d));
1378 	(*d)+=2;
1379 	(*dl)-=2;
1380 	return w;
1381 }
1382 
sldns_wire2str_int32_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1383 int sldns_wire2str_int32_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1384 {
1385 	int w;
1386 	if(*dl < 4) return -1;
1387 	w = sldns_str_print(s, sl, "%lu", (unsigned long)sldns_read_uint32(*d));
1388 	(*d)+=4;
1389 	(*dl)-=4;
1390 	return w;
1391 }
1392 
sldns_wire2str_period_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1393 int sldns_wire2str_period_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1394 {
1395 	int w;
1396 	if(*dl < 4) return -1;
1397 	w = sldns_str_print(s, sl, "%u", (unsigned)sldns_read_uint32(*d));
1398 	(*d)+=4;
1399 	(*dl)-=4;
1400 	return w;
1401 }
1402 
sldns_wire2str_tsigtime_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1403 int sldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1404 {
1405 	/* tsigtime is 48 bits network order unsigned integer */
1406 	int w;
1407 	uint64_t tsigtime = 0;
1408 	uint64_t d0, d1, d2, d3, d4, d5;
1409 	if(*dl < 6) return -1;
1410 	d0 = (*d)[0]; /* cast to uint64 for shift operations */
1411 	d1 = (*d)[1];
1412 	d2 = (*d)[2];
1413 	d3 = (*d)[3];
1414 	d4 = (*d)[4];
1415 	d5 = (*d)[5];
1416 	tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
1417 #ifndef USE_WINSOCK
1418 	w = sldns_str_print(s, sl, "%llu", (long long)tsigtime);
1419 #else
1420 	w = sldns_str_print(s, sl, "%I64u", (long long)tsigtime);
1421 #endif
1422 	(*d)+=6;
1423 	(*dl)-=6;
1424 	return w;
1425 }
1426 
sldns_wire2str_a_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1427 int sldns_wire2str_a_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1428 {
1429 	char buf[32];
1430 	int w;
1431 	if(*dl < 4) return -1;
1432 	if(!inet_ntop(AF_INET, *d, buf, (socklen_t)sizeof(buf)))
1433 		return -1;
1434 	w = sldns_str_print(s, sl, "%s", buf);
1435 	(*d)+=4;
1436 	(*dl)-=4;
1437 	return w;
1438 }
1439 
sldns_wire2str_aaaa_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1440 int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1441 {
1442 #ifdef AF_INET6
1443 	char buf[64];
1444 	int w;
1445 	if(*dl < 16) return -1;
1446 	if(!inet_ntop(AF_INET6, *d, buf, (socklen_t)sizeof(buf)))
1447 		return -1;
1448 	w = sldns_str_print(s, sl, "%s", buf);
1449 	(*d)+=16;
1450 	(*dl)-=16;
1451 	return w;
1452 #else
1453 	return -1;
1454 #endif
1455 }
1456 
1457 /** printout escaped TYPE_STR character */
str_char_print(char ** s,size_t * sl,uint8_t c)1458 static int str_char_print(char** s, size_t* sl, uint8_t c)
1459 {
1460 	if(isprint((unsigned char)c) || c == '\t') {
1461 		if(c == '\"' || c == '\\')
1462 			return sldns_str_print(s, sl, "\\%c", c);
1463 		if(*sl) {
1464 			**s = (char)c;
1465 			(*s)++;
1466 			(*sl)--;
1467 		}
1468 		return 1;
1469 	}
1470 	return sldns_str_print(s, sl, "\\%03u", (unsigned)c);
1471 }
1472 
sldns_wire2str_str_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1473 int sldns_wire2str_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1474 {
1475 	int w = 0;
1476 	size_t i, len;
1477 	if(*dl < 1) return -1;
1478 	len = **d;
1479 	if(*dl < 1+len) return -1;
1480 	(*d)++;
1481 	(*dl)--;
1482 	w += sldns_str_print(s, sl, "\"");
1483 	for(i=0; i<len; i++)
1484 		w += str_char_print(s, sl, (*d)[i]);
1485 	w += sldns_str_print(s, sl, "\"");
1486 	(*d)+=len;
1487 	(*dl)-=len;
1488 	return w;
1489 }
1490 
sldns_wire2str_apl_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1491 int sldns_wire2str_apl_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1492 {
1493 	int i, w = 0;
1494 	uint16_t family;
1495 	uint8_t negation, prefix, adflength;
1496 	if(*dl < 4) return -1;
1497 	family = sldns_read_uint16(*d);
1498 	prefix = (*d)[2];
1499 	negation = ((*d)[3] & LDNS_APL_NEGATION);
1500 	adflength = ((*d)[3] & LDNS_APL_MASK);
1501 	if(*dl < 4+(size_t)adflength) return -1;
1502 	if(family != LDNS_APL_IP4 && family != LDNS_APL_IP6)
1503 		return -1; /* unknown address family */
1504 	if(negation)
1505 		w += sldns_str_print(s, sl, "!");
1506 	w += sldns_str_print(s, sl, "%u:", (unsigned)family);
1507 	if(family == LDNS_APL_IP4) {
1508 		/* check if prefix <32 ? */
1509 		/* address is variable length 0 - 4 */
1510 		for(i=0; i<4; i++) {
1511 			if(i > 0)
1512 				w += sldns_str_print(s, sl, ".");
1513 			if(i < (int)adflength)
1514 				w += sldns_str_print(s, sl, "%d", (*d)[4+i]);
1515 			else	w += sldns_str_print(s, sl, "0");
1516 		}
1517 	} else if(family == LDNS_APL_IP6) {
1518 		/* check if prefix <128 ? */
1519 		/* address is variable length 0 - 16 */
1520 		for(i=0; i<16; i++) {
1521 			if(i%2 == 0 && i>0)
1522 				w += sldns_str_print(s, sl, ":");
1523 			if(i < (int)adflength)
1524 				w += sldns_str_print(s, sl, "%02x", (*d)[4+i]);
1525 			else	w += sldns_str_print(s, sl, "00");
1526 		}
1527 	}
1528 	w += sldns_str_print(s, sl, "/%u", (unsigned)prefix);
1529 	(*d) += 4+adflength;
1530 	(*dl) -= 4+adflength;
1531 	return w;
1532 }
1533 
sldns_wire2str_b32_ext_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1534 int sldns_wire2str_b32_ext_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1535 {
1536 	size_t datalen;
1537 	size_t sz;
1538 	if(*dl < 1) return -1;
1539 	datalen = (*d)[0];
1540 	if(*dl < 1+datalen) return -1;
1541 	sz = sldns_b32_ntop_calculate_size(datalen);
1542 	if(*sl < sz+1) {
1543 		(*d) += datalen+1;
1544 		(*dl) -= (datalen+1);
1545 		return (int)sz; /* out of space really, but would need buffer
1546 			in order to truncate the output */
1547 	}
1548 	sldns_b32_ntop_extended_hex((*d)+1, datalen, *s, *sl);
1549 	(*d) += datalen+1;
1550 	(*dl) -= (datalen+1);
1551 	(*s) += sz;
1552 	(*sl) -= sz;
1553 	return (int)sz;
1554 }
1555 
1556 /** scan number of bytes from wire into b64 presentation format */
sldns_wire2str_b64_scan_num(uint8_t ** d,size_t * dl,char ** s,size_t * sl,size_t num)1557 static int sldns_wire2str_b64_scan_num(uint8_t** d, size_t* dl, char** s,
1558 	size_t* sl, size_t num)
1559 {
1560 	/* b64_ntop_calculate size includes null at the end */
1561 	size_t sz = sldns_b64_ntop_calculate_size(num)-1;
1562 	if(*sl < sz+1) {
1563 		(*d) += num;
1564 		(*dl) -= num;
1565 		return (int)sz; /* out of space really, but would need buffer
1566 			in order to truncate the output */
1567 	}
1568 	sldns_b64_ntop(*d, num, *s, *sl);
1569 	(*d) += num;
1570 	(*dl) -= num;
1571 	(*s) += sz;
1572 	(*sl) -= sz;
1573 	return (int)sz;
1574 }
1575 
sldns_wire2str_b64_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1576 int sldns_wire2str_b64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1577 {
1578 	if(*dl == 0) {
1579 		return sldns_str_print(s, sl, "0");
1580 	}
1581 	return sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1582 }
1583 
sldns_wire2str_hex_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1584 int sldns_wire2str_hex_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1585 {
1586 	if(*dl == 0) {
1587 		return sldns_str_print(s, sl, "0");
1588 	}
1589 	return print_remainder_hex("", d, dl, s, sl);
1590 }
1591 
sldns_wire2str_nsec_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1592 int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1593 {
1594 	uint8_t* p = *d;
1595 	size_t pl = *dl;
1596 	unsigned i, bit, window, block_len;
1597 	uint16_t t;
1598 	int w = 0;
1599 
1600 	/* check for errors */
1601 	while(pl) {
1602 		if(pl < 2) return -1;
1603 		block_len = (unsigned)p[1];
1604 		if(pl < 2+block_len) return -1;
1605 		p += block_len+2;
1606 		pl -= block_len+2;
1607 	}
1608 
1609 	/* do it */
1610 	p = *d;
1611 	pl = *dl;
1612 	while(pl) {
1613 		if(pl < 2) return -1; /* cannot happen */
1614 		window = (unsigned)p[0];
1615 		block_len = (unsigned)p[1];
1616 		if(pl < 2+block_len) return -1; /* cannot happen */
1617 		p += 2;
1618 		for(i=0; i<block_len; i++) {
1619 			if(p[i] == 0) continue;
1620 			/* base type number for this octet */
1621 			t = ((window)<<8) | (i << 3);
1622 			for(bit=0; bit<8; bit++) {
1623 				if((p[i]&(0x80>>bit))) {
1624 					if(w) w += sldns_str_print(s, sl, " ");
1625 					w += sldns_wire2str_type_print(s, sl,
1626 						t+bit);
1627 				}
1628 			}
1629 		}
1630 		p += block_len;
1631 		pl -= block_len+2;
1632 	}
1633 	(*d) += *dl;
1634 	(*dl) = 0;
1635 	return w;
1636 }
1637 
sldns_wire2str_nsec3_salt_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1638 int sldns_wire2str_nsec3_salt_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1639 {
1640 	size_t salt_len;
1641 	int w;
1642 	if(*dl < 1) return -1;
1643 	salt_len = (size_t)(*d)[0];
1644 	if(*dl < 1+salt_len) return -1;
1645 	(*d)++;
1646 	(*dl)--;
1647 	if(salt_len == 0) {
1648 		return sldns_str_print(s, sl, "-");
1649 	}
1650 	w = print_hex_buf(s, sl, *d, salt_len);
1651 	(*dl)-=salt_len;
1652 	(*d)+=salt_len;
1653 	return w;
1654 }
1655 
sldns_wire2str_cert_alg_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1656 int sldns_wire2str_cert_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1657 {
1658 	sldns_lookup_table *lt;
1659 	int data, w;
1660 	if(*dl < 2) return -1;
1661 	data = (int)sldns_read_uint16(*d);
1662 	lt = sldns_lookup_by_id(sldns_cert_algorithms, data);
1663 	if(lt && lt->name)
1664 		w = sldns_str_print(s, sl, "%s", lt->name);
1665 	else 	w = sldns_str_print(s, sl, "%d", data);
1666 	(*dl)-=2;
1667 	(*d)+=2;
1668 	return w;
1669 }
1670 
sldns_wire2str_alg_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1671 int sldns_wire2str_alg_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1672 {
1673 	/* don't use algorithm mnemonics in the presentation format
1674 	 * this kind of got sneaked into the rfc's */
1675 	return sldns_wire2str_int8_scan(d, dl, s, sl);
1676 }
1677 
sldns_wire2str_unknown_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1678 int sldns_wire2str_unknown_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1679 {
1680 	return sldns_wire2str_rdata_unknown_scan(d, dl, s, sl);
1681 }
1682 
sldns_wire2str_time_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1683 int sldns_wire2str_time_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1684 {
1685 	/* create a YYYYMMDDHHMMSS string if possible */
1686 	struct tm tm;
1687 	char date_buf[16];
1688 	uint32_t t;
1689 	memset(&tm, 0, sizeof(tm));
1690 	if(*dl < 4) return -1;
1691 	t = sldns_read_uint32(*d);
1692 	date_buf[15]=0;
1693 	if(sldns_serial_arithmetics_gmtime_r(t, time(NULL), &tm) &&
1694 		strftime(date_buf, 15, "%Y%m%d%H%M%S", &tm)) {
1695 		(*d) += 4;
1696 		(*dl) -= 4;
1697 		return sldns_str_print(s, sl, "%s", date_buf);
1698 	}
1699 	return -1;
1700 }
1701 
1702 static int
loc_cm_print(char ** str,size_t * sl,uint8_t mantissa,uint8_t exponent)1703 loc_cm_print(char** str, size_t* sl, uint8_t mantissa, uint8_t exponent)
1704 {
1705 	int w = 0;
1706 	uint8_t i;
1707 	/* is it 0.<two digits> ? */
1708 	if(exponent < 2) {
1709 		if(exponent == 1)
1710 			mantissa *= 10;
1711 		return sldns_str_print(str, sl, "0.%02ld", (long)mantissa);
1712 	}
1713 	/* always <digit><string of zeros> */
1714 	w += sldns_str_print(str, sl, "%d", (int)mantissa);
1715 	for(i=0; i<exponent-2; i++)
1716 		w += sldns_str_print(str, sl, "0");
1717 	return w;
1718 }
1719 
sldns_wire2str_loc_scan(uint8_t ** d,size_t * dl,char ** str,size_t * sl)1720 int sldns_wire2str_loc_scan(uint8_t** d, size_t* dl, char** str, size_t* sl)
1721 {
1722 	/* we could do checking (ie degrees < 90 etc)? */
1723 	uint8_t version;
1724 	uint8_t size;
1725 	uint8_t horizontal_precision;
1726 	uint8_t vertical_precision;
1727 	uint32_t longitude;
1728 	uint32_t latitude;
1729 	uint32_t altitude;
1730 	char northerness;
1731 	char easterness;
1732 	uint32_t h;
1733 	uint32_t m;
1734 	double s;
1735 	uint32_t equator = (uint32_t)1 << 31; /* 2**31 */
1736 	int w = 0;
1737 
1738 	if(*dl < 16) return -1;
1739 	version = (*d)[0];
1740 	if(version != 0)
1741 		return sldns_wire2str_hex_scan(d, dl, str, sl);
1742 	size = (*d)[1];
1743 	horizontal_precision = (*d)[2];
1744 	vertical_precision = (*d)[3];
1745 
1746 	latitude = sldns_read_uint32((*d)+4);
1747 	longitude = sldns_read_uint32((*d)+8);
1748 	altitude = sldns_read_uint32((*d)+12);
1749 
1750 	if (latitude > equator) {
1751 		northerness = 'N';
1752 		latitude = latitude - equator;
1753 	} else {
1754 		northerness = 'S';
1755 		latitude = equator - latitude;
1756 	}
1757 	h = latitude / (1000 * 60 * 60);
1758 	latitude = latitude % (1000 * 60 * 60);
1759 	m = latitude / (1000 * 60);
1760 	latitude = latitude % (1000 * 60);
1761 	s = (double) latitude / 1000.0;
1762 	w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1763 		h, m, s, northerness);
1764 
1765 	if (longitude > equator) {
1766 		easterness = 'E';
1767 		longitude = longitude - equator;
1768 	} else {
1769 		easterness = 'W';
1770 		longitude = equator - longitude;
1771 	}
1772 	h = longitude / (1000 * 60 * 60);
1773 	longitude = longitude % (1000 * 60 * 60);
1774 	m = longitude / (1000 * 60);
1775 	longitude = longitude % (1000 * 60);
1776 	s = (double) longitude / (1000.0);
1777 	w += sldns_str_print(str, sl, "%02u %02u %06.3f %c ",
1778 		h, m, s, easterness);
1779 
1780 	s = ((double) altitude) / 100;
1781 	s -= 100000;
1782 
1783 	if(altitude%100 != 0)
1784 		w += sldns_str_print(str, sl, "%.2f", s);
1785 	else
1786 		w += sldns_str_print(str, sl, "%.0f", s);
1787 
1788 	w += sldns_str_print(str, sl, "m ");
1789 
1790 	w += loc_cm_print(str, sl, (size & 0xf0) >> 4, size & 0x0f);
1791 	w += sldns_str_print(str, sl, "m ");
1792 
1793 	w += loc_cm_print(str, sl, (horizontal_precision & 0xf0) >> 4,
1794 		horizontal_precision & 0x0f);
1795 	w += sldns_str_print(str, sl, "m ");
1796 
1797 	w += loc_cm_print(str, sl, (vertical_precision & 0xf0) >> 4,
1798 		vertical_precision & 0x0f);
1799 	w += sldns_str_print(str, sl, "m");
1800 
1801 	(*d)+=16;
1802 	(*dl)-=16;
1803 	return w;
1804 }
1805 
sldns_wire2str_wks_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1806 int sldns_wire2str_wks_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1807 {
1808 	/* protocol, followed by bitmap of services */
1809 	const char* proto_name = NULL;
1810 	struct protoent *protocol;
1811 	struct servent *service;
1812 	uint8_t protocol_nr;
1813 	int bit, port, w = 0;
1814 	size_t i;
1815 	/* we cannot print with strings because they
1816 	 * are not portable, the presentation format may
1817 	 * not be able to be read in on another computer.  */
1818 	int print_symbols = 0;
1819 
1820 	/* protocol */
1821 	if(*dl < 1) return -1;
1822 	protocol_nr = (*d)[0];
1823 	(*d)++;
1824 	(*dl)--;
1825 	protocol = getprotobynumber((int)protocol_nr);
1826 	if(protocol && (protocol->p_name != NULL)) {
1827 		w += sldns_str_print(s, sl, "%s", protocol->p_name);
1828 		proto_name = protocol->p_name;
1829 	} else if(protocol_nr == 6) {
1830 		w += sldns_str_print(s, sl, "tcp");
1831 	} else if(protocol_nr == 17) {
1832 		w += sldns_str_print(s, sl, "udp");
1833 	} else	{
1834 		w += sldns_str_print(s, sl, "%u", (unsigned)protocol_nr);
1835 	}
1836 
1837 	for(i=0; i<*dl; i++) {
1838 		if((*d)[i] == 0)
1839 			continue;
1840 		for(bit=0; bit<8; bit++) {
1841 			if(!(((*d)[i])&(0x80>>bit)))
1842 				continue;
1843 			port = (int)i*8 + bit;
1844 
1845 			if(!print_symbols)
1846 				service = NULL;
1847 			else
1848 				service = getservbyport(
1849 					(int)htons((uint16_t)port), proto_name);
1850 			if(service && service->s_name)
1851 				w += sldns_str_print(s, sl, " %s",
1852 					service->s_name);
1853 			else 	w += sldns_str_print(s, sl, " %u",
1854 					(unsigned)port);
1855 		}
1856 	}
1857 
1858 #ifdef HAVE_ENDSERVENT
1859 	endservent();
1860 #endif
1861 #ifdef HAVE_ENDPROTOENT
1862         endprotoent();
1863 #endif
1864 	(*d) += *dl;
1865 	(*dl) = 0;
1866 	return w;
1867 }
1868 
sldns_wire2str_nsap_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1869 int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1870 {
1871 	return print_remainder_hex("0x", d, dl, s, sl);
1872 }
1873 
sldns_wire2str_atma_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1874 int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1875 {
1876 	uint8_t format;
1877 	int w = 0;
1878 	size_t i;
1879 
1880 	if(*dl < 1) return -1;
1881 	format = (*d)[0];
1882 	(*d)+=1;
1883 	(*dl)-=1;
1884 
1885 	if(format == 0) {
1886 		/* AESA format (ATM End System Address). */
1887 		return print_remainder_hex("", d, dl, s, sl);
1888 	} else if(format == 1) {
1889 		/* E.164 format. */
1890 		w += sldns_str_print(s, sl, "+");
1891 		for(i=0; i<*dl; i++) {
1892 			if((*d)[i] < '0' || (*d)[0] > '9')
1893 				return -1;
1894 			w += sldns_str_print(s, sl, "%c", (*d)[i]);
1895 		}
1896 		(*d) += *dl;
1897 		(*dl) = 0;
1898 	} else {
1899 		/* Unknown format. */
1900 		return -1;
1901 	}
1902 	return w;
1903 }
1904 
1905 /* internal scan routine that can modify arguments on failure */
sldns_wire2str_ipseckey_scan_internal(uint8_t ** d,size_t * dl,char ** s,size_t * sl,uint8_t * pkt,size_t pktlen,int * comprloop)1906 static int sldns_wire2str_ipseckey_scan_internal(uint8_t** d, size_t* dl,
1907 	char** s, size_t* sl, uint8_t* pkt, size_t pktlen, int* comprloop)
1908 {
1909 	/* http://www.ietf.org/internet-drafts/draft-ietf-ipseckey-rr-12.txt*/
1910 	uint8_t precedence, gateway_type, algorithm;
1911 	int w = 0;
1912 
1913 	if(*dl < 3) return -1;
1914 	precedence = (*d)[0];
1915 	gateway_type = (*d)[1];
1916 	algorithm = (*d)[2];
1917 	if(gateway_type > 3)
1918 		return -1; /* unknown */
1919 	(*d)+=3;
1920 	(*dl)-=3;
1921 	w += sldns_str_print(s, sl, "%d %d %d ",
1922 		(int)precedence, (int)gateway_type, (int)algorithm);
1923 
1924 	switch(gateway_type) {
1925 	case 0: /* no gateway */
1926 		w += sldns_str_print(s, sl, ".");
1927 		break;
1928 	case 1: /* ip4 */
1929 		w += sldns_wire2str_a_scan(d, dl, s, sl);
1930 		break;
1931 	case 2: /* ip6 */
1932 		w += sldns_wire2str_aaaa_scan(d, dl, s, sl);
1933 		break;
1934 	case 3: /* dname */
1935 		w += sldns_wire2str_dname_scan(d, dl, s, sl, pkt, pktlen, comprloop);
1936 		break;
1937 	default: /* unknown */
1938 		return -1;
1939 	}
1940 
1941 	if(*dl < 1)
1942 		return -1;
1943 	w += sldns_str_print(s, sl, " ");
1944 	w += sldns_wire2str_b64_scan_num(d, dl, s, sl, *dl);
1945 	return w;
1946 }
1947 
sldns_wire2str_ipseckey_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl,uint8_t * pkt,size_t pktlen,int * comprloop)1948 int sldns_wire2str_ipseckey_scan(uint8_t** d, size_t* dl, char** s, size_t* sl,
1949 	uint8_t* pkt, size_t pktlen, int* comprloop)
1950 {
1951 	uint8_t* od = *d;
1952 	char* os = *s;
1953 	size_t odl = *dl, osl = *sl;
1954 	int w=sldns_wire2str_ipseckey_scan_internal(d, dl, s, sl, pkt, pktlen, comprloop);
1955 	if(w == -1) {
1956 		*d = od;
1957 		*s = os;
1958 		*dl = odl;
1959 		*sl = osl;
1960 		return -1;
1961 	}
1962 	return w;
1963 }
1964 
sldns_wire2str_hip_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1965 int sldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1966 {
1967 	int w;
1968 	uint8_t algo, hitlen;
1969 	uint16_t pklen;
1970 
1971 	/* read lengths */
1972 	if(*dl < 4)
1973 		return -1;
1974 	hitlen = (*d)[0];
1975 	algo = (*d)[1];
1976 	pklen = sldns_read_uint16((*d)+2);
1977 	if(*dl < (size_t)4 + (size_t)hitlen + (size_t)pklen)
1978 		return -1;
1979 
1980 	/* write: algo hit pubkey */
1981 	w = sldns_str_print(s, sl, "%u ", (unsigned)algo);
1982 	w += print_hex_buf(s, sl, (*d)+4, hitlen);
1983 	w += sldns_str_print(s, sl, " ");
1984 	(*d)+=4+hitlen;
1985 	(*dl)-= (4+hitlen);
1986 	w += sldns_wire2str_b64_scan_num(d, dl, s, sl, pklen);
1987 	return w;
1988 }
1989 
sldns_wire2str_int16_data_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)1990 int sldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
1991 {
1992 	int w;
1993 	uint16_t n;
1994 	if(*dl < 2)
1995 		return -1;
1996 	n = sldns_read_uint16(*d);
1997 	if(*dl < 2+(size_t)n)
1998 		return -1;
1999 	(*d)+=2;
2000 	(*dl)-=2;
2001 	if(n == 0) {
2002 		return sldns_str_print(s, sl, "0");
2003 	}
2004 	w = sldns_str_print(s, sl, "%u ", (unsigned)n);
2005 	w += sldns_wire2str_b64_scan_num(d, dl, s, sl, n);
2006 	return w;
2007 }
2008 
sldns_wire2str_nsec3_next_owner_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2009 int sldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s,
2010 	size_t* sl)
2011 {
2012 	return sldns_wire2str_b32_ext_scan(d, dl, s, sl);
2013 }
2014 
sldns_wire2str_ilnp64_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2015 int sldns_wire2str_ilnp64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2016 {
2017 	int w;
2018 	if(*dl < 8)
2019 		return -1;
2020 	w = sldns_str_print(s, sl, "%.4x:%.4x:%.4x:%.4x",
2021 		sldns_read_uint16(*d), sldns_read_uint16((*d)+2),
2022 		sldns_read_uint16((*d)+4), sldns_read_uint16((*d)+6));
2023 	(*d)+=8;
2024 	(*dl)-=8;
2025 	return w;
2026 }
2027 
sldns_wire2str_eui48_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2028 int sldns_wire2str_eui48_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2029 {
2030 	int w;
2031 	if(*dl < 6)
2032 		return -1;
2033 	w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
2034 		(*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5]);
2035 	(*d)+=6;
2036 	(*dl)-=6;
2037 	return w;
2038 }
2039 
sldns_wire2str_eui64_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2040 int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2041 {
2042 	int w;
2043 	if(*dl < 8)
2044 		return -1;
2045 	w = sldns_str_print(s, sl, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
2046 		(*d)[0], (*d)[1], (*d)[2], (*d)[3], (*d)[4], (*d)[5],
2047 		(*d)[6], (*d)[7]);
2048 	(*d)+=8;
2049 	(*dl)-=8;
2050 	return w;
2051 }
2052 
sldns_wire2str_unquoted_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2053 int sldns_wire2str_unquoted_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2054 {
2055 	int w = 0;
2056 	size_t i, len;
2057 	if(*dl < 1) return -1;
2058 	len = **d;
2059 	if(*dl < 1+len) return -1;
2060 	(*d)++;
2061 	(*dl)--;
2062 	for(i=0; i<len; i++) {
2063 		if(isspace((unsigned char)(*d)[i]) || (*d)[i] == '(' ||
2064 			(*d)[i] == ')' || (*d)[i] == '\'')
2065 			w += sldns_str_print(s, sl, "\\%c", (char)(*d)[i]);
2066 		else	w += str_char_print(s, sl, (*d)[i]);
2067 	}
2068 	(*d)+=len;
2069 	(*dl)-=len;
2070 	return w;
2071 }
2072 
sldns_wire2str_tag_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2073 int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2074 {
2075 	size_t i, n;
2076 	int w = 0;
2077 	if(*dl < 1)
2078 		return -1;
2079 	n = (size_t)((*d)[0]);
2080 	if(*dl < 1+n)
2081 		return -1;
2082 	for(i=0; i<n; i++)
2083 		if(!isalnum((unsigned char)(*d)[i+1]))
2084 			return -1;
2085 	for(i=0; i<n; i++)
2086 		w += sldns_str_print(s, sl, "%c", (char)(*d)[i+1]);
2087 	(*d)+=n+1;
2088 	(*dl)-=(n+1);
2089 	return w;
2090 }
2091 
sldns_wire2str_long_str_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2092 int sldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2093 {
2094 	size_t i;
2095 	int w = 0;
2096 	w += sldns_str_print(s, sl, "\"");
2097 	for(i=0; i<*dl; i++)
2098 		w += str_char_print(s, sl, (*d)[i]);
2099 	w += sldns_str_print(s, sl, "\"");
2100 	(*d)+=*dl;
2101 	(*dl)=0;
2102 	return w;
2103 }
2104 
sldns_wire2str_tsigerror_scan(uint8_t ** d,size_t * dl,char ** s,size_t * sl)2105 int sldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
2106 {
2107 	sldns_lookup_table *lt;
2108 	int data, w;
2109 	if(*dl < 2) return -1;
2110 	data = (int)sldns_read_uint16(*d);
2111 	lt = sldns_lookup_by_id(sldns_tsig_errors, data);
2112 	if(lt && lt->name)
2113 		w = sldns_str_print(s, sl, "%s", lt->name);
2114 	else 	w = sldns_str_print(s, sl, "%d", data);
2115 	(*dl)-=2;
2116 	(*d)+=2;
2117 	return w;
2118 }
2119 
sldns_wire2str_edns_llq_print(char ** s,size_t * sl,uint8_t * data,size_t len)2120 int sldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
2121 	size_t len)
2122 {
2123 	/* LLQ constants */
2124 	const char* llq_errors[] = {"NO-ERROR", "SERV-FULL", "STATIC",
2125 		"FORMAT-ERR", "NO-SUCH-LLQ", "BAD-VERS", "UNKNOWN_ERR"};
2126 	const unsigned int llq_errors_num = 7;
2127 	const char* llq_opcodes[] = {"LLQ-SETUP", "LLQ-REFRESH", "LLQ-EVENT"};
2128 	const unsigned int llq_opcodes_num = 3;
2129 	uint16_t version, llq_opcode, error_code;
2130 	uint64_t llq_id;
2131 	uint32_t lease_life; /* Requested or granted life of LLQ, in seconds */
2132 	int w = 0;
2133 
2134 	/* read the record */
2135 	if(len != 18) {
2136 		w += sldns_str_print(s, sl, "malformed LLQ ");
2137 		w += print_hex_buf(s, sl, data, len);
2138 		return w;
2139 	}
2140 	version = sldns_read_uint16(data);
2141 	llq_opcode = sldns_read_uint16(data+2);
2142 	error_code = sldns_read_uint16(data+4);
2143 	memmove(&llq_id, data+6, sizeof(llq_id));
2144 	lease_life = sldns_read_uint32(data+14);
2145 
2146 	/* print it */
2147 	w += sldns_str_print(s, sl, "v%d ", (int)version);
2148 	if(llq_opcode < llq_opcodes_num)
2149 		w += sldns_str_print(s, sl, "%s", llq_opcodes[llq_opcode]);
2150 	else	w += sldns_str_print(s, sl, "opcode %d", (int)llq_opcode);
2151 	if(error_code < llq_errors_num)
2152 		w += sldns_str_print(s, sl, " %s", llq_errors[error_code]);
2153 	else	w += sldns_str_print(s, sl, " error %d", (int)error_code);
2154 #ifndef USE_WINSOCK
2155 	w += sldns_str_print(s, sl, " id %llx lease-life %lu",
2156 		(unsigned long long)llq_id, (unsigned long)lease_life);
2157 #else
2158 	w += sldns_str_print(s, sl, " id %I64x lease-life %lu",
2159 		(unsigned long long)llq_id, (unsigned long)lease_life);
2160 #endif
2161 	return w;
2162 }
2163 
sldns_wire2str_edns_ul_print(char ** s,size_t * sl,uint8_t * data,size_t len)2164 int sldns_wire2str_edns_ul_print(char** s, size_t* sl, uint8_t* data,
2165 	size_t len)
2166 {
2167 	uint32_t lease;
2168 	int w = 0;
2169 	if(len != 4) {
2170 		w += sldns_str_print(s, sl, "malformed UL ");
2171 		w += print_hex_buf(s, sl, data, len);
2172 		return w;
2173 	}
2174 	lease = sldns_read_uint32(data);
2175 	w += sldns_str_print(s, sl, "lease %lu", (unsigned long)lease);
2176 	return w;
2177 }
2178 
sldns_wire2str_edns_nsid_print(char ** s,size_t * sl,uint8_t * data,size_t len)2179 int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data,
2180 	size_t len)
2181 {
2182 	int w = 0;
2183 	size_t i, printed=0;
2184 	w += print_hex_buf(s, sl, data, len);
2185 	for(i=0; i<len; i++) {
2186 		if(isprint((unsigned char)data[i]) || data[i] == '\t') {
2187 			if(!printed) {
2188 				w += sldns_str_print(s, sl, " (");
2189 				printed = 1;
2190 			}
2191 			w += sldns_str_print(s, sl, "%c", (char)data[i]);
2192 		}
2193 	}
2194 	if(printed)
2195 		w += sldns_str_print(s, sl, ")");
2196 	return w;
2197 }
2198 
sldns_wire2str_edns_dau_print(char ** s,size_t * sl,uint8_t * data,size_t len)2199 int sldns_wire2str_edns_dau_print(char** s, size_t* sl, uint8_t* data,
2200 	size_t len)
2201 {
2202 	sldns_lookup_table *lt;
2203 	size_t i;
2204 	int w = 0;
2205 	for(i=0; i<len; i++) {
2206 		lt = sldns_lookup_by_id(sldns_algorithms, (int)data[i]);
2207 		if(lt && lt->name)
2208 			w += sldns_str_print(s, sl, " %s", lt->name);
2209 		else 	w += sldns_str_print(s, sl, " %d", (int)data[i]);
2210 	}
2211 	return w;
2212 }
2213 
sldns_wire2str_edns_dhu_print(char ** s,size_t * sl,uint8_t * data,size_t len)2214 int sldns_wire2str_edns_dhu_print(char** s, size_t* sl, uint8_t* data,
2215 	size_t len)
2216 {
2217 	sldns_lookup_table *lt;
2218 	size_t i;
2219 	int w = 0;
2220 	for(i=0; i<len; i++) {
2221 		lt = sldns_lookup_by_id(sldns_hashes, (int)data[i]);
2222 		if(lt && lt->name)
2223 			w += sldns_str_print(s, sl, " %s", lt->name);
2224 		else 	w += sldns_str_print(s, sl, " %d", (int)data[i]);
2225 	}
2226 	return w;
2227 }
2228 
sldns_wire2str_edns_n3u_print(char ** s,size_t * sl,uint8_t * data,size_t len)2229 int sldns_wire2str_edns_n3u_print(char** s, size_t* sl, uint8_t* data,
2230 	size_t len)
2231 {
2232 	size_t i;
2233 	int w = 0;
2234 	for(i=0; i<len; i++) {
2235 		if(data[i] == 1)
2236 			w += sldns_str_print(s, sl, " SHA1");
2237 		else 	w += sldns_str_print(s, sl, " %d", (int)data[i]);
2238 	}
2239 	return w;
2240 }
2241 
sldns_wire2str_edns_subnet_print(char ** s,size_t * sl,uint8_t * data,size_t len)2242 int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
2243 	size_t len)
2244 {
2245 	int w = 0;
2246 	uint16_t family;
2247 	uint8_t source, scope;
2248 	if(len < 4) {
2249 		w += sldns_str_print(s, sl, "malformed subnet ");
2250 		w += print_hex_buf(s, sl, data, len);
2251 		return w;
2252 	}
2253 	family = sldns_read_uint16(data);
2254 	source = data[2];
2255 	scope = data[3];
2256 	if(family == 1) {
2257 		/* IP4 */
2258 		char buf[64];
2259 		uint8_t ip4[4];
2260 		memset(ip4, 0, sizeof(ip4));
2261 		if(len-4 > 4) {
2262 			w += sldns_str_print(s, sl, "trailingdata:");
2263 			w += print_hex_buf(s, sl, data+4+4, len-4-4);
2264 			w += sldns_str_print(s, sl, " ");
2265 			len = 4+4;
2266 		}
2267 		memmove(ip4, data+4, len-4);
2268 		if(!inet_ntop(AF_INET, ip4, buf, (socklen_t)sizeof(buf))) {
2269 			w += sldns_str_print(s, sl, "ip4ntoperror ");
2270 			w += print_hex_buf(s, sl, data+4+4, len-4-4);
2271 		} else {
2272 			w += sldns_str_print(s, sl, "%s", buf);
2273 		}
2274 	} else if(family == 2) {
2275 		/* IP6 */
2276 		char buf[64];
2277 		uint8_t ip6[16];
2278 		memset(ip6, 0, sizeof(ip6));
2279 		if(len-4 > 16) {
2280 			w += sldns_str_print(s, sl, "trailingdata:");
2281 			w += print_hex_buf(s, sl, data+4+16, len-4-16);
2282 			w += sldns_str_print(s, sl, " ");
2283 			len = 4+16;
2284 		}
2285 		memmove(ip6, data+4, len-4);
2286 #ifdef AF_INET6
2287 		if(!inet_ntop(AF_INET6, ip6, buf, (socklen_t)sizeof(buf))) {
2288 			w += sldns_str_print(s, sl, "ip6ntoperror ");
2289 			w += print_hex_buf(s, sl, data+4+4, len-4-4);
2290 		} else {
2291 			w += sldns_str_print(s, sl, "%s", buf);
2292 		}
2293 #else
2294 		w += print_hex_buf(s, sl, data+4+4, len-4-4);
2295 #endif
2296 	} else {
2297 		/* unknown */
2298 		w += sldns_str_print(s, sl, "family %d ",
2299 			(int)family);
2300 		w += print_hex_buf(s, sl, data, len);
2301 	}
2302 	w += sldns_str_print(s, sl, "/%d scope /%d", (int)source, (int)scope);
2303 	return w;
2304 }
2305 
sldns_wire2str_edns_keepalive_print(char ** s,size_t * sl,uint8_t * data,size_t len)2306 static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl,
2307 	uint8_t* data, size_t len)
2308 {
2309 	int w = 0;
2310 	uint16_t timeout;
2311 	if(!(len == 0 || len == 2)) {
2312 		w += sldns_str_print(s, sl, "malformed keepalive ");
2313 		w += print_hex_buf(s, sl, data, len);
2314 		return w;
2315 	}
2316 	if(len == 0 ) {
2317 		w += sldns_str_print(s, sl, "no timeout value (only valid for client option) ");
2318 	} else {
2319 		timeout = sldns_read_uint16(data);
2320 		w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout);
2321 	}
2322 	return w;
2323 }
2324 
sldns_wire2str_edns_ede_print(char ** s,size_t * sl,uint8_t * data,size_t len)2325 int sldns_wire2str_edns_ede_print(char** s, size_t* sl,
2326 	uint8_t* data, size_t len)
2327 {
2328 	uint16_t ede_code;
2329 	int w = 0;
2330 	sldns_lookup_table *lt;
2331 	size_t i;
2332 	int printable;
2333 
2334 	if(len < 2) {
2335 		w += sldns_str_print(s, sl, "malformed ede ");
2336 		w += print_hex_buf(s, sl, data, len);
2337 		return w;
2338 	}
2339 
2340 	ede_code = sldns_read_uint16(data);
2341 	lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code);
2342 	if(lt && lt->name)
2343 		w += sldns_str_print(s, sl, "%s", lt->name);
2344 	else 	w += sldns_str_print(s, sl, "%d", (int)ede_code);
2345 
2346 	if(len == 2)
2347 		return w;
2348 
2349 	w += sldns_str_print(s, sl, " ");
2350 
2351 	/* If it looks like text, show it as text. */
2352 	printable=1;
2353 	for(i=2; i<len; i++) {
2354 		if(isprint((unsigned char)data[i]) || data[i] == '\t')
2355 			continue;
2356 		printable = 0;
2357 		break;
2358 	}
2359 	if(printable) {
2360 		w += sldns_str_print(s, sl, "\"");
2361 		for(i=2; i<len; i++) {
2362 			w += str_char_print(s, sl, data[i]);
2363 		}
2364 		w += sldns_str_print(s, sl, "\"");
2365 	} else {
2366 		w += print_hex_buf(s, sl, data+2, len-2);
2367 	}
2368 	return w;
2369 }
2370 
sldns_wire2str_edns_option_print(char ** s,size_t * sl,uint16_t option_code,uint8_t * optdata,size_t optlen)2371 int sldns_wire2str_edns_option_print(char** s, size_t* sl,
2372 	uint16_t option_code, uint8_t* optdata, size_t optlen)
2373 {
2374 	int w = 0;
2375 	w += sldns_wire2str_edns_option_code_print(s, sl, option_code);
2376 	w += sldns_str_print(s, sl, ": ");
2377 	switch(option_code) {
2378 	case LDNS_EDNS_LLQ:
2379 		w += sldns_wire2str_edns_llq_print(s, sl, optdata, optlen);
2380 		break;
2381 	case LDNS_EDNS_UL:
2382 		w += sldns_wire2str_edns_ul_print(s, sl, optdata, optlen);
2383 		break;
2384 	case LDNS_EDNS_NSID:
2385 		w += sldns_wire2str_edns_nsid_print(s, sl, optdata, optlen);
2386 		break;
2387 	case LDNS_EDNS_DAU:
2388 		w += sldns_wire2str_edns_dau_print(s, sl, optdata, optlen);
2389 		break;
2390 	case LDNS_EDNS_DHU:
2391 		w += sldns_wire2str_edns_dhu_print(s, sl, optdata, optlen);
2392 		break;
2393 	case LDNS_EDNS_N3U:
2394 		w += sldns_wire2str_edns_n3u_print(s, sl, optdata, optlen);
2395 		break;
2396 	case LDNS_EDNS_CLIENT_SUBNET:
2397 		w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
2398 		break;
2399 	 case LDNS_EDNS_KEEPALIVE:
2400 		w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen);
2401 		break;
2402 	case LDNS_EDNS_PADDING:
2403 		w += print_hex_buf(s, sl, optdata, optlen);
2404 		break;
2405 	case LDNS_EDNS_EDE:
2406 		w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen);
2407 		break;
2408 	default:
2409 		/* unknown option code */
2410 		w += print_hex_buf(s, sl, optdata, optlen);
2411 		break;
2412 	}
2413 	return w;
2414 }
2415 
2416 /** print the edns options to string */
2417 static int
print_edns_opts(char ** s,size_t * sl,uint8_t * rdata,size_t rdatalen)2418 print_edns_opts(char** s, size_t* sl, uint8_t* rdata, size_t rdatalen)
2419 {
2420 	uint16_t option_code, option_len;
2421 	int w = 0;
2422 	while(rdatalen > 0) {
2423 		/* option name */
2424 		if(rdatalen < 4) {
2425 			w += sldns_str_print(s, sl, " ; malformed: ");
2426 			w += print_hex_buf(s, sl, rdata, rdatalen);
2427 			return w;
2428 		}
2429 		option_code = sldns_read_uint16(rdata);
2430 		option_len = sldns_read_uint16(rdata+2);
2431 		rdata += 4;
2432 		rdatalen -= 4;
2433 
2434 		/* option value */
2435 		if(rdatalen < (size_t)option_len) {
2436 			w += sldns_str_print(s, sl, " ; malformed ");
2437 			w += sldns_wire2str_edns_option_code_print(s, sl,
2438 				option_code);
2439 			w += sldns_str_print(s, sl, ": ");
2440 			w += print_hex_buf(s, sl, rdata, rdatalen);
2441 			return w;
2442 		}
2443 		w += sldns_str_print(s, sl, " ; ");
2444 		w += sldns_wire2str_edns_option_print(s, sl, option_code,
2445 			rdata, option_len);
2446 		rdata += option_len;
2447 		rdatalen -= option_len;
2448 	}
2449 	return w;
2450 }
2451 
sldns_wire2str_edns_scan(uint8_t ** data,size_t * data_len,char ** str,size_t * str_len,uint8_t * pkt,size_t pktlen)2452 int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
2453         size_t* str_len, uint8_t* pkt, size_t pktlen)
2454 {
2455 	int w = 0;
2456 	uint8_t ext_rcode, edns_version;
2457 	uint16_t udpsize, edns_bits, rdatalen;
2458 	w += sldns_str_print(str, str_len, "; EDNS:");
2459 
2460 	/* some input checks, domain name */
2461 	if(*data_len < 1+10)
2462 		return w + print_remainder_hex("Error malformed 0x",
2463 			data, data_len, str, str_len);
2464 	if(*data[0] != 0) {
2465 		return w + print_remainder_hex("Error nonrootdname 0x",
2466 			data, data_len, str, str_len);
2467 	}
2468 	(*data)++;
2469 	(*data_len)--;
2470 
2471 	/* check type and read fixed contents */
2472 	if(sldns_read_uint16((*data)) != LDNS_RR_TYPE_OPT) {
2473 		return w + print_remainder_hex("Error nottypeOPT 0x",
2474 			data, data_len, str, str_len);
2475 	}
2476 	udpsize = sldns_read_uint16((*data)+2);
2477 	ext_rcode = (*data)[4];
2478 	edns_version = (*data)[5];
2479 	edns_bits = sldns_read_uint16((*data)+6);
2480 	rdatalen = sldns_read_uint16((*data)+8);
2481 	(*data)+=10;
2482 	(*data_len)-=10;
2483 
2484 	w += sldns_str_print(str, str_len, " version: %u;",
2485 		(unsigned)edns_version);
2486 	w += sldns_str_print(str, str_len, " flags:");
2487 	if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
2488 		w += sldns_str_print(str, str_len, " do");
2489 	if((edns_bits & LDNS_EDNS_MASK_CO_BIT))
2490 		w += sldns_str_print(str, str_len, " co");
2491 	/* the extended rcode is the value set, shifted four bits,
2492 	 * and or'd with the original rcode */
2493 	if(ext_rcode) {
2494 		int rc = ((int)ext_rcode)<<4;
2495 		if(pkt && pktlen >= LDNS_HEADER_SIZE)
2496 			rc |= LDNS_RCODE_WIRE(pkt);
2497 		w += sldns_str_print(str, str_len, " ; ext-rcode: %d", rc);
2498 	}
2499 	w += sldns_str_print(str, str_len, " ; udp: %u", (unsigned)udpsize);
2500 
2501 	if(rdatalen) {
2502 		if((size_t)*data_len < rdatalen) {
2503 			w += sldns_str_print(str, str_len,
2504 				" ; Error EDNS rdata too short; ");
2505 			rdatalen = (uint16_t)*data_len;
2506 		}
2507 		w += print_edns_opts(str, str_len, *data, rdatalen);
2508 		(*data) += rdatalen;
2509 		(*data_len) -= rdatalen;
2510 	}
2511 	w += sldns_str_print(str, str_len, "\n");
2512 	return w;
2513 }
2514