1/*	$NetBSD: rdata.c,v 1.6 2012/12/04 23:38:42 spz Exp $	*/
2
3/*
4 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2003  Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/* Id */
21
22/*! \file */
23
24#include <config.h>
25#include <ctype.h>
26
27#include <isc/base64.h>
28#include <isc/hex.h>
29#include <isc/lex.h>
30#include <isc/mem.h>
31#include <isc/parseint.h>
32#include <isc/print.h>
33#include <isc/string.h>
34#include <isc/stdlib.h>
35#include <isc/util.h>
36
37#include <dns/callbacks.h>
38#include <dns/cert.h>
39#include <dns/compress.h>
40#include <dns/enumtype.h>
41#include <dns/keyflags.h>
42#include <dns/keyvalues.h>
43#include <dns/message.h>
44#include <dns/rcode.h>
45#include <dns/rdata.h>
46#include <dns/rdataclass.h>
47#include <dns/rdatastruct.h>
48#include <dns/rdatatype.h>
49#include <dns/result.h>
50#include <dns/secalg.h>
51#include <dns/secproto.h>
52#include <dns/time.h>
53#include <dns/ttl.h>
54
55#define RETERR(x) \
56	do { \
57		isc_result_t _r = (x); \
58		if (_r != ISC_R_SUCCESS) \
59			return (_r); \
60	} while (/*CONSTCOND*/0)
61
62#define RETTOK(x) \
63	do { \
64		isc_result_t _r = (x); \
65		if (_r != ISC_R_SUCCESS) { \
66			isc_lex_ungettoken(lexer, &token); \
67			return (_r); \
68		} \
69	} while (/*CONSTCOND*/0)
70
71#define DNS_AS_STR(t) ((t).value.as_textregion.base)
72
73#define ARGS_FROMTEXT	int rdclass, dns_rdatatype_t type, \
74			isc_lex_t *lexer, dns_name_t *origin, \
75			unsigned int options, isc_buffer_t *target, \
76			dns_rdatacallbacks_t *callbacks
77
78#define ARGS_TOTEXT	dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
79			isc_buffer_t *target
80
81#define ARGS_FROMWIRE	int rdclass, dns_rdatatype_t type, \
82			isc_buffer_t *source, dns_decompress_t *dctx, \
83			unsigned int options, isc_buffer_t *target
84
85#define ARGS_TOWIRE	dns_rdata_t *rdata, dns_compress_t *cctx, \
86			isc_buffer_t *target
87
88#define ARGS_COMPARE	const dns_rdata_t *rdata1, const dns_rdata_t *rdata2
89
90#define ARGS_FROMSTRUCT	int rdclass, dns_rdatatype_t type, \
91			void *source, isc_buffer_t *target
92
93#define ARGS_TOSTRUCT	dns_rdata_t *rdata, void *target, isc_mem_t *mctx
94
95#define ARGS_FREESTRUCT void *source
96
97#define ARGS_ADDLDATA	dns_rdata_t *rdata, dns_additionaldatafunc_t add, \
98			void *arg
99
100#define ARGS_DIGEST	dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg
101
102#define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \
103			dns_rdatatype_t type, isc_boolean_t wildcard
104
105#define ARGS_CHECKNAMES dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad
106
107
108/*%
109 * Context structure for the totext_ functions.
110 * Contains formatting options for rdata-to-text
111 * conversion.
112 */
113typedef struct dns_rdata_textctx {
114	dns_name_t *origin;	/*%< Current origin, or NULL. */
115	unsigned int flags;	/*%< DNS_STYLEFLAG_*  */
116	unsigned int width;	/*%< Width of rdata column. */
117	const char *linebreak;	/*%< Line break string. */
118} dns_rdata_textctx_t;
119
120static isc_result_t
121txt_totext(isc_region_t *source, isc_buffer_t *target);
122
123static isc_result_t
124txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
125
126static isc_result_t
127txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
128
129static isc_result_t
130multitxt_totext(isc_region_t *source, isc_buffer_t *target);
131
132static isc_result_t
133multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
134
135static isc_result_t
136multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
137
138static isc_boolean_t
139name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
140
141static unsigned int
142name_length(dns_name_t *name);
143
144static isc_result_t
145str_totext(const char *source, isc_buffer_t *target);
146
147static isc_result_t
148inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
149
150static isc_boolean_t
151buffer_empty(isc_buffer_t *source);
152
153static void
154buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region);
155
156static isc_result_t
157uint32_tobuffer(isc_uint32_t, isc_buffer_t *target);
158
159static isc_result_t
160uint16_tobuffer(isc_uint32_t, isc_buffer_t *target);
161
162static isc_result_t
163uint8_tobuffer(isc_uint32_t, isc_buffer_t *target);
164
165static isc_result_t
166name_tobuffer(dns_name_t *name, isc_buffer_t *target);
167
168static isc_uint32_t
169uint32_fromregion(isc_region_t *region);
170
171static isc_uint16_t
172uint16_fromregion(isc_region_t *region);
173
174static isc_uint8_t
175uint8_fromregion(isc_region_t *region);
176
177static isc_uint8_t
178uint8_consume_fromregion(isc_region_t *region);
179
180static isc_result_t
181mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
182
183static int
184hexvalue(char value);
185
186static int
187decvalue(char value);
188
189static isc_result_t
190btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
191
192static isc_result_t
193atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target);
194
195static void
196default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...)
197     ISC_FORMAT_PRINTF(2, 3);
198
199static void
200fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
201	       dns_rdatacallbacks_t *callbacks, const char *name,
202	       unsigned long line, isc_token_t *token, isc_result_t result);
203
204static void
205fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);
206
207static isc_result_t
208rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
209	     isc_buffer_t *target);
210
211static void
212warn_badname(dns_name_t *name, isc_lex_t *lexer,
213	     dns_rdatacallbacks_t *callbacks);
214
215static void
216warn_badmx(isc_token_t *token, isc_lex_t *lexer,
217	   dns_rdatacallbacks_t *callbacks);
218
219static isc_uint16_t
220uint16_consume_fromregion(isc_region_t *region);
221
222static isc_result_t
223unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
224	       isc_buffer_t *target);
225
226static inline int
227getquad(const void *src, struct in_addr *dst,
228	isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks)
229{
230	int result;
231	struct in_addr *tmp;
232
233	result = inet_aton(src, dst);
234	if (result == 1 && callbacks != NULL &&
235	    inet_pton(AF_INET, src, &tmp) != 1) {
236		const char *name = isc_lex_getsourcename(lexer);
237		if (name == NULL)
238			name = "UNKNOWN";
239		(*callbacks->warn)(callbacks, "%s:%lu: \"%s\" "
240				   "is not a decimal dotted quad", name,
241				   isc_lex_getsourceline(lexer), src);
242	}
243	return (result);
244}
245
246static inline isc_result_t
247name_duporclone(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
248
249	if (mctx != NULL)
250		return (dns_name_dup(source, mctx, target));
251	dns_name_clone(source, target);
252	return (ISC_R_SUCCESS);
253}
254
255static inline void *
256mem_maybedup(isc_mem_t *mctx, void *source, size_t length) {
257	void *new;
258
259	if (mctx == NULL)
260		return (source);
261	new = isc_mem_allocate(mctx, length);
262	if (new != NULL)
263		memcpy(new, source, length);
264
265	return (new);
266}
267
268static const char hexdigits[] = "0123456789abcdef";
269static const char decdigits[] = "0123456789";
270
271#include "code.h"
272
273#define META 0x0001
274#define RESERVED 0x0002
275
276/***
277 *** Initialization
278 ***/
279
280void
281dns_rdata_init(dns_rdata_t *rdata) {
282
283	REQUIRE(rdata != NULL);
284
285	rdata->data = NULL;
286	rdata->length = 0;
287	rdata->rdclass = 0;
288	rdata->type = 0;
289	rdata->flags = 0;
290	ISC_LINK_INIT(rdata, link);
291	/* ISC_LIST_INIT(rdata->list); */
292}
293
294void
295dns_rdata_reset(dns_rdata_t *rdata) {
296
297	REQUIRE(rdata != NULL);
298
299	REQUIRE(!ISC_LINK_LINKED(rdata, link));
300	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
301
302	rdata->data = NULL;
303	rdata->length = 0;
304	rdata->rdclass = 0;
305	rdata->type = 0;
306	rdata->flags = 0;
307}
308
309/***
310 ***
311 ***/
312
313void
314dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
315
316	REQUIRE(src != NULL);
317	REQUIRE(target != NULL);
318
319	REQUIRE(DNS_RDATA_INITIALIZED(target));
320
321	REQUIRE(DNS_RDATA_VALIDFLAGS(src));
322	REQUIRE(DNS_RDATA_VALIDFLAGS(target));
323
324	target->data = src->data;
325	target->length = src->length;
326	target->rdclass = src->rdclass;
327	target->type = src->type;
328	target->flags = src->flags;
329}
330
331
332/***
333 *** Comparisons
334 ***/
335
336int
337dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
338	int result = 0;
339	isc_boolean_t use_default = ISC_FALSE;
340
341	REQUIRE(rdata1 != NULL);
342	REQUIRE(rdata2 != NULL);
343	REQUIRE(rdata1->length == 0 || rdata1->data != NULL);
344	REQUIRE(rdata2->length == 0 || rdata2->data != NULL);
345	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
346	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
347
348	if (rdata1->rdclass != rdata2->rdclass)
349		return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
350
351	if (rdata1->type != rdata2->type)
352		return (rdata1->type < rdata2->type ? -1 : 1);
353
354	COMPARESWITCH
355
356	if (use_default) {
357		isc_region_t r1;
358		isc_region_t r2;
359
360		dns_rdata_toregion(rdata1, &r1);
361		dns_rdata_toregion(rdata2, &r2);
362		result = isc_region_compare(&r1, &r2);
363	}
364	return (result);
365}
366
367int
368dns_rdata_casecompare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
369	int result = 0;
370	isc_boolean_t use_default = ISC_FALSE;
371
372	REQUIRE(rdata1 != NULL);
373	REQUIRE(rdata2 != NULL);
374	REQUIRE(rdata1->length == 0 || rdata1->data != NULL);
375	REQUIRE(rdata2->length == 0 || rdata2->data != NULL);
376	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
377	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
378
379	if (rdata1->rdclass != rdata2->rdclass)
380		return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
381
382	if (rdata1->type != rdata2->type)
383		return (rdata1->type < rdata2->type ? -1 : 1);
384
385	CASECOMPARESWITCH
386
387	if (use_default) {
388		isc_region_t r1;
389		isc_region_t r2;
390
391		dns_rdata_toregion(rdata1, &r1);
392		dns_rdata_toregion(rdata2, &r2);
393		result = isc_region_compare(&r1, &r2);
394	}
395	return (result);
396}
397
398/***
399 *** Conversions
400 ***/
401
402void
403dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
404		     dns_rdatatype_t type, isc_region_t *r)
405{
406
407	REQUIRE(rdata != NULL);
408	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
409	REQUIRE(r != NULL);
410
411	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
412
413	rdata->data = r->base;
414	rdata->length = r->length;
415	rdata->rdclass = rdclass;
416	rdata->type = type;
417	rdata->flags = 0;
418}
419
420void
421dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
422
423	REQUIRE(rdata != NULL);
424	REQUIRE(r != NULL);
425	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
426
427	r->base = rdata->data;
428	r->length = rdata->length;
429}
430
431isc_result_t
432dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
433		   dns_rdatatype_t type, isc_buffer_t *source,
434		   dns_decompress_t *dctx, unsigned int options,
435		   isc_buffer_t *target)
436{
437	isc_result_t result = ISC_R_NOTIMPLEMENTED;
438	isc_region_t region;
439	isc_buffer_t ss;
440	isc_buffer_t st;
441	isc_boolean_t use_default = ISC_FALSE;
442	isc_uint32_t activelength;
443	size_t length;
444
445	REQUIRE(dctx != NULL);
446	if (rdata != NULL) {
447		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
448		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
449	}
450	REQUIRE(source != NULL);
451	REQUIRE(target != NULL);
452
453	if (type == 0)
454		return (DNS_R_FORMERR);
455
456	ss = *source;
457	st = *target;
458
459	activelength = isc_buffer_activelength(source);
460	INSIST(activelength < 65536);
461
462	FROMWIRESWITCH
463
464	if (use_default) {
465		if (activelength > isc_buffer_availablelength(target))
466			result = ISC_R_NOSPACE;
467		else {
468			isc_buffer_putmem(target, isc_buffer_current(source),
469					  activelength);
470			isc_buffer_forward(source, activelength);
471			result = ISC_R_SUCCESS;
472		}
473	}
474
475	/*
476	 * Reject any rdata that expands out to more than DNS_RDATA_MAXLENGTH
477	 * as we cannot transmit it.
478	 */
479	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
480	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
481		result = DNS_R_FORMERR;
482
483	/*
484	 * We should have consumed all of our buffer.
485	 */
486	if (result == ISC_R_SUCCESS && !buffer_empty(source))
487		result = DNS_R_EXTRADATA;
488
489	if (rdata != NULL && result == ISC_R_SUCCESS) {
490		region.base = isc_buffer_used(&st);
491		region.length = length;
492		dns_rdata_fromregion(rdata, rdclass, type, &region);
493	}
494
495	if (result != ISC_R_SUCCESS) {
496		*source = ss;
497		*target = st;
498	}
499	return (result);
500}
501
502isc_result_t
503dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
504		 isc_buffer_t *target)
505{
506	isc_result_t result = ISC_R_NOTIMPLEMENTED;
507	isc_boolean_t use_default = ISC_FALSE;
508	isc_region_t tr;
509	isc_buffer_t st;
510
511	REQUIRE(rdata != NULL);
512	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
513
514	/*
515	 * Some DynDNS meta-RRs have empty rdata.
516	 */
517	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
518		INSIST(rdata->length == 0);
519		return (ISC_R_SUCCESS);
520	}
521
522	st = *target;
523
524	TOWIRESWITCH
525
526	if (use_default) {
527		isc_buffer_availableregion(target, &tr);
528		if (tr.length < rdata->length)
529			return (ISC_R_NOSPACE);
530		memcpy(tr.base, rdata->data, rdata->length);
531		isc_buffer_add(target, rdata->length);
532		return (ISC_R_SUCCESS);
533	}
534	if (result != ISC_R_SUCCESS) {
535		*target = st;
536		INSIST(target->used < 65536);
537		dns_compress_rollback(cctx, (isc_uint16_t)target->used);
538	}
539	return (result);
540}
541
542/*
543 * If the binary data in 'src' is valid uncompressed wire format
544 * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS
545 * and copy the validated rdata to 'dest'.  Otherwise return an error.
546 */
547static isc_result_t
548rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass,
549	    dns_rdatatype_t type)
550{
551	dns_decompress_t dctx;
552	isc_result_t result;
553
554	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
555	isc_buffer_setactive(src, isc_buffer_usedlength(src));
556	result = dns_rdata_fromwire(NULL, rdclass, type, src, &dctx, 0, dest);
557	dns_decompress_invalidate(&dctx);
558
559	return (result);
560}
561
562static isc_result_t
563unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type,
564		 isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target)
565{
566	isc_result_t result;
567	isc_buffer_t *buf = NULL;
568	isc_token_t token;
569
570	if (type == 0 || dns_rdatatype_ismeta(type))
571		return (DNS_R_METATYPE);
572
573	result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
574					ISC_FALSE);
575	if (result == ISC_R_SUCCESS && token.value.as_ulong > 65535U)
576		return (ISC_R_RANGE);
577	result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong);
578	if (result != ISC_R_SUCCESS)
579		return (result);
580
581	result = isc_hex_tobuffer(lexer, buf,
582				  (unsigned int)token.value.as_ulong);
583	if (result != ISC_R_SUCCESS)
584	       goto failure;
585	if (isc_buffer_usedlength(buf) != token.value.as_ulong) {
586		result = ISC_R_UNEXPECTEDEND;
587		goto failure;
588	}
589
590	if (dns_rdatatype_isknown(type)) {
591		result = rdata_validate(buf, target, rdclass, type);
592	} else {
593		isc_region_t r;
594		isc_buffer_usedregion(buf, &r);
595		result = isc_buffer_copyregion(target, &r);
596	}
597	if (result != ISC_R_SUCCESS)
598		goto failure;
599
600	isc_buffer_free(&buf);
601	return (ISC_R_SUCCESS);
602
603 failure:
604	isc_buffer_free(&buf);
605	return (result);
606}
607
608isc_result_t
609dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
610		   dns_rdatatype_t type, isc_lex_t *lexer,
611		   dns_name_t *origin, unsigned int options, isc_mem_t *mctx,
612		   isc_buffer_t *target, dns_rdatacallbacks_t *callbacks)
613{
614	isc_result_t result = ISC_R_NOTIMPLEMENTED;
615	isc_region_t region;
616	isc_buffer_t st;
617	isc_token_t token;
618	unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
619				  ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
620	char *name;
621	unsigned long line;
622	void (*callback)(dns_rdatacallbacks_t *, const char *, ...);
623	isc_result_t tresult;
624	size_t length;
625
626	REQUIRE(origin == NULL || dns_name_isabsolute(origin) == ISC_TRUE);
627	if (rdata != NULL) {
628		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
629		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
630	}
631	if (callbacks != NULL) {
632		REQUIRE(callbacks->warn != NULL);
633		REQUIRE(callbacks->error != NULL);
634	}
635
636	st = *target;
637
638	if (callbacks != NULL)
639		callback = callbacks->error;
640	else
641		callback = default_fromtext_callback;
642
643	result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
644					ISC_FALSE);
645	if (result != ISC_R_SUCCESS) {
646		name = isc_lex_getsourcename(lexer);
647		line = isc_lex_getsourceline(lexer);
648		fromtext_error(callback, callbacks, name, line, NULL, result);
649		return (result);
650	}
651
652	if (strcmp(DNS_AS_STR(token), "\\#") == 0)
653		result = unknown_fromtext(rdclass, type, lexer, mctx, target);
654	else {
655		isc_lex_ungettoken(lexer, &token);
656
657		FROMTEXTSWITCH
658	}
659
660	/*
661	 * Consume to end of line / file.
662	 * If not at end of line initially set error code.
663	 * Call callback via fromtext_error once if there was an error.
664	 */
665	do {
666		name = isc_lex_getsourcename(lexer);
667		line = isc_lex_getsourceline(lexer);
668		tresult = isc_lex_gettoken(lexer, lexoptions, &token);
669		if (tresult != ISC_R_SUCCESS) {
670			if (result == ISC_R_SUCCESS)
671				result = tresult;
672			if (callback != NULL)
673				fromtext_error(callback, callbacks, name,
674					       line, NULL, result);
675			break;
676		} else if (token.type != isc_tokentype_eol &&
677			   token.type != isc_tokentype_eof) {
678			if (result == ISC_R_SUCCESS)
679				result = DNS_R_EXTRATOKEN;
680			if (callback != NULL) {
681				fromtext_error(callback, callbacks, name,
682					       line, &token, result);
683				callback = NULL;
684			}
685		} else if (result != ISC_R_SUCCESS && callback != NULL) {
686			fromtext_error(callback, callbacks, name, line,
687				       &token, result);
688			break;
689		} else {
690			if (token.type == isc_tokentype_eof)
691				fromtext_warneof(lexer, callbacks);
692			break;
693		}
694	} while (1);
695
696	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
697	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
698		result = ISC_R_NOSPACE;
699
700	if (rdata != NULL && result == ISC_R_SUCCESS) {
701		region.base = isc_buffer_used(&st);
702		region.length = length;
703		dns_rdata_fromregion(rdata, rdclass, type, &region);
704	}
705	if (result != ISC_R_SUCCESS) {
706		*target = st;
707	}
708	return (result);
709}
710
711static isc_result_t
712unknown_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
713	       isc_buffer_t *target)
714{
715	isc_result_t result;
716	char buf[sizeof("65535")];
717	isc_region_t sr;
718
719	strlcpy(buf, "\\# ", sizeof(buf));
720	result = str_totext(buf, target);
721	if (result != ISC_R_SUCCESS)
722		return (result);
723
724	dns_rdata_toregion(rdata, &sr);
725	INSIST(sr.length < 65536);
726	snprintf(buf, sizeof(buf), "%u", sr.length);
727	result = str_totext(buf, target);
728	if (result != ISC_R_SUCCESS)
729		return (result);
730
731	if (sr.length != 0U) {
732		if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
733			result = str_totext(" ( ", target);
734		else
735			result = str_totext(" ", target);
736
737		if (result != ISC_R_SUCCESS)
738			return (result);
739
740		if (tctx->width == 0) /* No splitting */
741			result = isc_hex_totext(&sr, 0, "", target);
742		else
743			result = isc_hex_totext(&sr, tctx->width - 2,
744						tctx->linebreak,
745						target);
746		if (result == ISC_R_SUCCESS &&
747		    (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
748			result = str_totext(" )", target);
749	}
750	return (result);
751}
752
753static isc_result_t
754rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
755	     isc_buffer_t *target)
756{
757	isc_result_t result = ISC_R_NOTIMPLEMENTED;
758	isc_boolean_t use_default = ISC_FALSE;
759
760	REQUIRE(rdata != NULL);
761	REQUIRE(tctx->origin == NULL ||
762		dns_name_isabsolute(tctx->origin) == ISC_TRUE);
763
764	/*
765	 * Some DynDNS meta-RRs have empty rdata.
766	 */
767	if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
768		INSIST(rdata->length == 0);
769		return (ISC_R_SUCCESS);
770	}
771
772	TOTEXTSWITCH
773
774	if (use_default)
775		result = unknown_totext(rdata, tctx, target);
776
777	return (result);
778}
779
780isc_result_t
781dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
782{
783	dns_rdata_textctx_t tctx;
784
785	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
786
787	/*
788	 * Set up formatting options for single-line output.
789	 */
790	tctx.origin = origin;
791	tctx.flags = 0;
792	tctx.width = 60;
793	tctx.linebreak = " ";
794	return (rdata_totext(rdata, &tctx, target));
795}
796
797isc_result_t
798dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
799		    unsigned int flags, unsigned int width,
800		    unsigned int split_width, const char *linebreak,
801		    isc_buffer_t *target)
802{
803	dns_rdata_textctx_t tctx;
804
805	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
806
807	/*
808	 * Set up formatting options for formatted output.
809	 */
810	tctx.origin = origin;
811	tctx.flags = flags;
812	if (split_width == 0xffffffff)
813		tctx.width = width;
814	else
815		tctx.width = split_width;
816
817	if ((flags & DNS_STYLEFLAG_MULTILINE) != 0)
818		tctx.linebreak = linebreak;
819	else {
820		if (split_width == 0xffffffff)
821			tctx.width = 60; /* Used for hex word length only. */
822		tctx.linebreak = " ";
823	}
824	return (rdata_totext(rdata, &tctx, target));
825}
826
827isc_result_t
828dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
829		     dns_rdatatype_t type, void *source,
830		     isc_buffer_t *target)
831{
832	isc_result_t result = ISC_R_NOTIMPLEMENTED;
833	isc_buffer_t st;
834	isc_region_t region;
835	isc_boolean_t use_default = ISC_FALSE;
836	size_t length;
837
838	REQUIRE(source != NULL);
839	if (rdata != NULL) {
840		REQUIRE(DNS_RDATA_INITIALIZED(rdata));
841		REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
842	}
843
844	st = *target;
845
846	FROMSTRUCTSWITCH
847
848	if (use_default)
849		(void)NULL;
850
851	length = isc_buffer_usedlength(target) - isc_buffer_usedlength(&st);
852	if (result == ISC_R_SUCCESS && length > DNS_RDATA_MAXLENGTH)
853		result = ISC_R_NOSPACE;
854
855	if (rdata != NULL && result == ISC_R_SUCCESS) {
856		region.base = isc_buffer_used(&st);
857		region.length = length;
858		dns_rdata_fromregion(rdata, rdclass, type, &region);
859	}
860	if (result != ISC_R_SUCCESS)
861		*target = st;
862	return (result);
863}
864
865isc_result_t
866dns_rdata_tostruct(dns_rdata_t *rdata, void *target, isc_mem_t *mctx) {
867	isc_result_t result = ISC_R_NOTIMPLEMENTED;
868	isc_boolean_t use_default = ISC_FALSE;
869
870	REQUIRE(rdata != NULL);
871	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
872
873	TOSTRUCTSWITCH
874
875	if (use_default)
876		(void)NULL;
877
878	return (result);
879}
880
881void
882dns_rdata_freestruct(void *source) {
883	dns_rdatacommon_t *common = source;
884	REQUIRE(source != NULL);
885
886	FREESTRUCTSWITCH
887}
888
889isc_result_t
890dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
891			 void *arg)
892{
893	isc_result_t result = ISC_R_NOTIMPLEMENTED;
894	isc_boolean_t use_default = ISC_FALSE;
895
896	/*
897	 * Call 'add' for each name and type from 'rdata' which is subject to
898	 * additional section processing.
899	 */
900
901	REQUIRE(rdata != NULL);
902	REQUIRE(add != NULL);
903	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
904
905	ADDITIONALDATASWITCH
906
907	/* No additional processing for unknown types */
908	if (use_default)
909		result = ISC_R_SUCCESS;
910
911	return (result);
912}
913
914isc_result_t
915dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) {
916	isc_result_t result = ISC_R_NOTIMPLEMENTED;
917	isc_boolean_t use_default = ISC_FALSE;
918	isc_region_t r;
919
920	/*
921	 * Send 'rdata' in DNSSEC canonical form to 'digest'.
922	 */
923
924	REQUIRE(rdata != NULL);
925	REQUIRE(digest != NULL);
926	REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
927
928	DIGESTSWITCH
929
930	if (use_default) {
931		dns_rdata_toregion(rdata, &r);
932		result = (digest)(arg, &r);
933	}
934
935	return (result);
936}
937
938isc_boolean_t
939dns_rdata_checkowner(dns_name_t *name, dns_rdataclass_t rdclass,
940		     dns_rdatatype_t type, isc_boolean_t wildcard)
941{
942	isc_boolean_t result;
943
944	CHECKOWNERSWITCH
945	return (result);
946}
947
948isc_boolean_t
949dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad)
950{
951	isc_boolean_t result;
952
953	CHECKNAMESSWITCH
954	return (result);
955}
956
957unsigned int
958dns_rdatatype_attributes(dns_rdatatype_t type)
959{
960	RDATATYPE_ATTRIBUTE_SW
961	if (type >= (dns_rdatatype_t)128 && type < (dns_rdatatype_t)255)
962		return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META);
963	return (DNS_RDATATYPEATTR_UNKNOWN);
964}
965
966isc_result_t
967dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
968	unsigned int hash;
969	unsigned int n;
970	unsigned char a, b;
971
972	n = source->length;
973
974	if (n == 0)
975		return (DNS_R_UNKNOWN);
976
977	a = tolower((unsigned char)source->base[0]);
978	b = tolower((unsigned char)source->base[n - 1]);
979
980	hash = ((a + n) * b) % 256;
981
982	/*
983	 * This switch block is inlined via \#define, and will use "return"
984	 * to return a result to the caller if it is a valid (known)
985	 * rdatatype name.
986	 */
987	RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep);
988
989	if (source->length > 4 && source->length < (4 + sizeof("65000")) &&
990	    strncasecmp("type", source->base, 4) == 0) {
991		char buf[sizeof("65000")];
992		char *endp;
993		unsigned int val;
994
995		strncpy(buf, source->base + 4, source->length - 4);
996		buf[source->length - 4] = '\0';
997		val = strtoul(buf, &endp, 10);
998		if (*endp == '\0' && val <= 0xffff) {
999			*typep = (dns_rdatatype_t)val;
1000			return (ISC_R_SUCCESS);
1001		}
1002	}
1003
1004	return (DNS_R_UNKNOWN);
1005}
1006
1007isc_result_t
1008dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
1009	char buf[sizeof("TYPE65535")];
1010
1011	RDATATYPE_TOTEXT_SW
1012	snprintf(buf, sizeof(buf), "TYPE%u", type);
1013	return (str_totext(buf, target));
1014}
1015
1016void
1017dns_rdatatype_format(dns_rdatatype_t rdtype,
1018		     char *array, unsigned int size)
1019{
1020	isc_result_t result;
1021	isc_buffer_t buf;
1022
1023	if (size == 0U)
1024		return;
1025
1026	isc_buffer_init(&buf, array, size);
1027	result = dns_rdatatype_totext(rdtype, &buf);
1028	/*
1029	 * Null terminate.
1030	 */
1031	if (result == ISC_R_SUCCESS) {
1032		if (isc_buffer_availablelength(&buf) >= 1)
1033			isc_buffer_putuint8(&buf, 0);
1034		else
1035			result = ISC_R_NOSPACE;
1036	}
1037	if (result != ISC_R_SUCCESS)
1038		strlcpy(array, "<unknown>", size);
1039}
1040
1041/*
1042 * Private function.
1043 */
1044
1045static unsigned int
1046name_length(dns_name_t *name) {
1047	return (name->length);
1048}
1049
1050static isc_result_t
1051txt_totext(isc_region_t *source, isc_buffer_t *target) {
1052	unsigned int tl;
1053	unsigned int n;
1054	unsigned char *sp;
1055	char *tp;
1056	isc_region_t region;
1057
1058	isc_buffer_availableregion(target, &region);
1059	sp = source->base;
1060	tp = (char *)region.base;
1061	tl = region.length;
1062
1063	n = *sp++;
1064
1065	REQUIRE(n + 1 <= source->length);
1066
1067	if (tl < 1)
1068		return (ISC_R_NOSPACE);
1069	*tp++ = '"';
1070	tl--;
1071	while (n--) {
1072		if (*sp < 0x20 || *sp >= 0x7f) {
1073			if (tl < 4)
1074				return (ISC_R_NOSPACE);
1075			*tp++ = 0x5c;
1076			*tp++ = 0x30 + ((*sp / 100) % 10);
1077			*tp++ = 0x30 + ((*sp / 10) % 10);
1078			*tp++ = 0x30 + (*sp % 10);
1079			sp++;
1080			tl -= 4;
1081			continue;
1082		}
1083		/* double quote, semi-colon, backslash */
1084		if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) {
1085			if (tl < 2)
1086				return (ISC_R_NOSPACE);
1087			*tp++ = '\\';
1088			tl--;
1089		}
1090		if (tl < 1)
1091			return (ISC_R_NOSPACE);
1092		*tp++ = *sp++;
1093		tl--;
1094	}
1095	if (tl < 1)
1096		return (ISC_R_NOSPACE);
1097	*tp++ = '"';
1098	tl--;
1099	isc_buffer_add(target, tp - (char *)region.base);
1100	isc_region_consume(source, *source->base + 1);
1101	return (ISC_R_SUCCESS);
1102}
1103
1104static isc_result_t
1105txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
1106	isc_region_t tregion;
1107	isc_boolean_t escape;
1108	unsigned int n, nrem;
1109	char *s;
1110	unsigned char *t;
1111	int d;
1112	int c;
1113
1114	isc_buffer_availableregion(target, &tregion);
1115	s = source->base;
1116	n = source->length;
1117	t = tregion.base;
1118	nrem = tregion.length;
1119	escape = ISC_FALSE;
1120	if (nrem < 1)
1121		return (ISC_R_NOSPACE);
1122	/*
1123	 * Length byte.
1124	 */
1125	nrem--;
1126	t++;
1127	/*
1128	 * Maximum text string length.
1129	 */
1130	if (nrem > 255)
1131		nrem = 255;
1132	while (n-- != 0) {
1133		c = (*s++) & 0xff;
1134		if (escape && (d = decvalue((char)c)) != -1) {
1135			c = d;
1136			if (n == 0)
1137				return (DNS_R_SYNTAX);
1138			n--;
1139			if ((d = decvalue(*s++)) != -1)
1140				c = c * 10 + d;
1141			else
1142				return (DNS_R_SYNTAX);
1143			if (n == 0)
1144				return (DNS_R_SYNTAX);
1145			n--;
1146			if ((d = decvalue(*s++)) != -1)
1147				c = c * 10 + d;
1148			else
1149				return (DNS_R_SYNTAX);
1150			if (c > 255)
1151				return (DNS_R_SYNTAX);
1152		} else if (!escape && c == '\\') {
1153			escape = ISC_TRUE;
1154			continue;
1155		}
1156		escape = ISC_FALSE;
1157		if (nrem == 0)
1158			return ((tregion.length <= 256U) ?
1159				ISC_R_NOSPACE : DNS_R_SYNTAX);
1160		*t++ = c;
1161		nrem--;
1162	}
1163	if (escape)
1164		return (DNS_R_SYNTAX);
1165	*tregion.base = t - tregion.base - 1;
1166	isc_buffer_add(target, *tregion.base + 1);
1167	return (ISC_R_SUCCESS);
1168}
1169
1170static isc_result_t
1171txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
1172	unsigned int n;
1173	isc_region_t sregion;
1174	isc_region_t tregion;
1175
1176	isc_buffer_activeregion(source, &sregion);
1177	if (sregion.length == 0)
1178		return(ISC_R_UNEXPECTEDEND);
1179	n = *sregion.base + 1;
1180	if (n > sregion.length)
1181		return (ISC_R_UNEXPECTEDEND);
1182
1183	isc_buffer_availableregion(target, &tregion);
1184	if (n > tregion.length)
1185		return (ISC_R_NOSPACE);
1186
1187	if (tregion.base != sregion.base)
1188	memcpy(tregion.base, sregion.base, n);
1189	isc_buffer_forward(source, n);
1190	isc_buffer_add(target, n);
1191	return (ISC_R_SUCCESS);
1192}
1193
1194static isc_result_t
1195multitxt_totext(isc_region_t *source, isc_buffer_t *target) {
1196	unsigned int tl;
1197	unsigned int n0, n;
1198	unsigned char *sp;
1199	char *tp;
1200	isc_region_t region;
1201
1202	isc_buffer_availableregion(target, &region);
1203	sp = source->base;
1204	tp = (char *)region.base;
1205	tl = region.length;
1206
1207	if (tl < 1)
1208		return (ISC_R_NOSPACE);
1209	*tp++ = '"';
1210	tl--;
1211	do {
1212		n0 = n = *sp++;
1213
1214		REQUIRE(n0 + 1 <= source->length);
1215
1216		while (n--) {
1217			if (*sp < 0x20 || *sp >= 0x7f) {
1218				if (tl < 4)
1219					return (ISC_R_NOSPACE);
1220				*tp++ = 0x5c;
1221				*tp++ = 0x30 + ((*sp / 100) % 10);
1222				*tp++ = 0x30 + ((*sp / 10) % 10);
1223				*tp++ = 0x30 + (*sp % 10);
1224				sp++;
1225				tl -= 4;
1226				continue;
1227			}
1228			/* double quote, semi-colon, backslash */
1229			if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) {
1230				if (tl < 2)
1231					return (ISC_R_NOSPACE);
1232				*tp++ = '\\';
1233				tl--;
1234			}
1235			if (tl < 1)
1236				return (ISC_R_NOSPACE);
1237			*tp++ = *sp++;
1238			tl--;
1239		}
1240		isc_region_consume(source, n0 + 1);
1241	} while (source->length != 0);
1242	if (tl < 1)
1243		return (ISC_R_NOSPACE);
1244	*tp++ = '"';
1245	tl--;
1246	isc_buffer_add(target, tp - (char *)region.base);
1247	return (ISC_R_SUCCESS);
1248}
1249
1250static isc_result_t
1251multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
1252	isc_region_t tregion;
1253	isc_boolean_t escape;
1254	unsigned int n, nrem;
1255	char *s;
1256	unsigned char *t0, *t;
1257	int d;
1258	int c;
1259
1260	s = source->base;
1261	n = source->length;
1262	escape = ISC_FALSE;
1263
1264	do {
1265		isc_buffer_availableregion(target, &tregion);
1266		t0 = tregion.base;
1267		nrem = tregion.length;
1268		if (nrem < 1)
1269			return (ISC_R_NOSPACE);
1270		/* length byte */
1271		t = t0;
1272		nrem--;
1273		t++;
1274		/* 255 byte character-string slice */
1275		if (nrem > 255)
1276			nrem = 255;
1277		while (n != 0) {
1278			--n;
1279			c = (*s++) & 0xff;
1280			if (escape && (d = decvalue((char)c)) != -1) {
1281				c = d;
1282				if (n == 0)
1283					return (DNS_R_SYNTAX);
1284				n--;
1285				if ((d = decvalue(*s++)) != -1)
1286					c = c * 10 + d;
1287				else
1288					return (DNS_R_SYNTAX);
1289				if (n == 0)
1290					return (DNS_R_SYNTAX);
1291				n--;
1292				if ((d = decvalue(*s++)) != -1)
1293					c = c * 10 + d;
1294				else
1295					return (DNS_R_SYNTAX);
1296				if (c > 255)
1297					return (DNS_R_SYNTAX);
1298			} else if (!escape && c == '\\') {
1299				escape = ISC_TRUE;
1300				continue;
1301			}
1302			escape = ISC_FALSE;
1303			*t++ = c;
1304			nrem--;
1305			if (nrem == 0)
1306				break;
1307		}
1308		if (escape)
1309			return (DNS_R_SYNTAX);
1310		*t0 = t - t0 - 1;
1311		isc_buffer_add(target, *t0 + 1);
1312	} while (n != 0);
1313	return (ISC_R_SUCCESS);
1314}
1315
1316static isc_result_t
1317multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
1318	unsigned int n;
1319	isc_region_t sregion;
1320	isc_region_t tregion;
1321
1322	isc_buffer_activeregion(source, &sregion);
1323	if (sregion.length == 0)
1324		return(ISC_R_UNEXPECTEDEND);
1325	n = 256U;
1326	do {
1327		if (n != 256U)
1328			return (DNS_R_SYNTAX);
1329		n = *sregion.base + 1;
1330		if (n > sregion.length)
1331			return (ISC_R_UNEXPECTEDEND);
1332
1333		isc_buffer_availableregion(target, &tregion);
1334		if (n > tregion.length)
1335			return (ISC_R_NOSPACE);
1336
1337		if (tregion.base != sregion.base)
1338		memcpy(tregion.base, sregion.base, n);
1339		isc_buffer_forward(source, n);
1340		isc_buffer_add(target, n);
1341		isc_buffer_activeregion(source, &sregion);
1342	} while (sregion.length != 0);
1343	return (ISC_R_SUCCESS);
1344}
1345
1346static isc_boolean_t
1347name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) {
1348	int l1, l2;
1349
1350	if (origin == NULL)
1351		goto return_false;
1352
1353	if (dns_name_compare(origin, dns_rootname) == 0)
1354		goto return_false;
1355
1356	if (!dns_name_issubdomain(name, origin))
1357		goto return_false;
1358
1359	l1 = dns_name_countlabels(name);
1360	l2 = dns_name_countlabels(origin);
1361
1362	if (l1 == l2)
1363		goto return_false;
1364
1365	/* Master files should be case preserving. */
1366	dns_name_getlabelsequence(name, l1 - l2, l2, target);
1367	if (!dns_name_caseequal(origin, target))
1368		goto return_false;
1369
1370	dns_name_getlabelsequence(name, 0, l1 - l2, target);
1371	return (ISC_TRUE);
1372
1373return_false:
1374	*target = *name;
1375	return (ISC_FALSE);
1376}
1377
1378static isc_result_t
1379str_totext(const char *source, isc_buffer_t *target) {
1380	unsigned int l;
1381	isc_region_t region;
1382
1383	isc_buffer_availableregion(target, &region);
1384	l = strlen(source);
1385
1386	if (l > region.length)
1387		return (ISC_R_NOSPACE);
1388
1389	memcpy(region.base, source, l);
1390	isc_buffer_add(target, l);
1391	return (ISC_R_SUCCESS);
1392}
1393
1394static isc_result_t
1395inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
1396	char tmpbuf[64];
1397
1398	/* Note - inet_ntop doesn't do size checking on its input. */
1399	if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
1400		return (ISC_R_NOSPACE);
1401	if (strlen(tmpbuf) > isc_buffer_availablelength(target))
1402		return (ISC_R_NOSPACE);
1403	isc_buffer_putstr(target, tmpbuf);
1404	return (ISC_R_SUCCESS);
1405}
1406
1407static isc_boolean_t
1408buffer_empty(isc_buffer_t *source) {
1409	return((source->current == source->active) ? ISC_TRUE : ISC_FALSE);
1410}
1411
1412static void
1413buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) {
1414	isc_buffer_init(buffer, region->base, region->length);
1415	isc_buffer_add(buffer, region->length);
1416	isc_buffer_setactive(buffer, region->length);
1417}
1418
1419static isc_result_t
1420uint32_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1421	isc_region_t region;
1422
1423	isc_buffer_availableregion(target, &region);
1424	if (region.length < 4)
1425		return (ISC_R_NOSPACE);
1426	isc_buffer_putuint32(target, value);
1427	return (ISC_R_SUCCESS);
1428}
1429
1430static isc_result_t
1431uint16_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1432	isc_region_t region;
1433
1434	if (value > 0xffff)
1435		return (ISC_R_RANGE);
1436	isc_buffer_availableregion(target, &region);
1437	if (region.length < 2)
1438		return (ISC_R_NOSPACE);
1439	isc_buffer_putuint16(target, (isc_uint16_t)value);
1440	return (ISC_R_SUCCESS);
1441}
1442
1443static isc_result_t
1444uint8_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1445	isc_region_t region;
1446
1447	if (value > 0xff)
1448		return (ISC_R_RANGE);
1449	isc_buffer_availableregion(target, &region);
1450	if (region.length < 1)
1451		return (ISC_R_NOSPACE);
1452	isc_buffer_putuint8(target, (isc_uint8_t)value);
1453	return (ISC_R_SUCCESS);
1454}
1455
1456static isc_result_t
1457name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
1458	isc_region_t r;
1459	dns_name_toregion(name, &r);
1460	return (isc_buffer_copyregion(target, &r));
1461}
1462
1463static isc_uint32_t
1464uint32_fromregion(isc_region_t *region) {
1465	isc_uint32_t value;
1466
1467	REQUIRE(region->length >= 4);
1468	value = region->base[0] << 24;
1469	value |= region->base[1] << 16;
1470	value |= region->base[2] << 8;
1471	value |= region->base[3];
1472	return(value);
1473}
1474
1475static isc_uint16_t
1476uint16_consume_fromregion(isc_region_t *region) {
1477	isc_uint16_t r = uint16_fromregion(region);
1478
1479	isc_region_consume(region, 2);
1480	return r;
1481}
1482
1483static isc_uint16_t
1484uint16_fromregion(isc_region_t *region) {
1485
1486	REQUIRE(region->length >= 2);
1487
1488	return ((region->base[0] << 8) | region->base[1]);
1489}
1490
1491static isc_uint8_t
1492uint8_fromregion(isc_region_t *region) {
1493
1494	REQUIRE(region->length >= 1);
1495
1496	return (region->base[0]);
1497}
1498
1499static isc_uint8_t
1500uint8_consume_fromregion(isc_region_t *region) {
1501	isc_uint8_t r = uint8_fromregion(region);
1502
1503	isc_region_consume(region, 1);
1504	return r;
1505}
1506
1507static isc_result_t
1508mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
1509	isc_region_t tr;
1510
1511	isc_buffer_availableregion(target, &tr);
1512	if (length > tr.length)
1513		return (ISC_R_NOSPACE);
1514	if (tr.base != base)
1515	memcpy(tr.base, base, length);
1516	isc_buffer_add(target, length);
1517	return (ISC_R_SUCCESS);
1518}
1519
1520static int
1521hexvalue(char value) {
1522	char *s;
1523	unsigned char c;
1524
1525	c = (unsigned char)value;
1526
1527	if (!isascii(c))
1528		return (-1);
1529	if (isupper(c))
1530		c = tolower(c);
1531	if ((s = strchr(hexdigits, c)) == NULL)
1532		return (-1);
1533	return (s - hexdigits);
1534}
1535
1536static int
1537decvalue(char value) {
1538	char *s;
1539
1540	/*
1541	 * isascii() is valid for full range of int values, no need to
1542	 * mask or cast.
1543	 */
1544	if (!isascii(value))
1545		return (-1);
1546	if ((s = strchr(decdigits, value)) == NULL)
1547		return (-1);
1548	return (s - decdigits);
1549}
1550
1551static const char atob_digits[86] =
1552	"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
1553	"abcdefghijklmnopqrstu";
1554/*
1555 * Subroutines to convert between 8 bit binary bytes and printable ASCII.
1556 * Computes the number of bytes, and three kinds of simple checksums.
1557 * Incoming bytes are collected into 32-bit words, then printed in base 85:
1558 *	exp(85,5) > exp(2,32)
1559 * The ASCII characters used are between '!' and 'u';
1560 * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
1561 *
1562 * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
1563 * the atob/btoa programs, released with the compress program, in mod.sources.
1564 * Modified by Mike Schwartz 8/19/86 for use in BIND.
1565 * Modified to be re-entrant 3/2/99.
1566 */
1567
1568
1569struct state {
1570	isc_int32_t Ceor;
1571	isc_int32_t Csum;
1572	isc_int32_t Crot;
1573	isc_int32_t word;
1574	isc_int32_t bcount;
1575};
1576
1577#define Ceor state->Ceor
1578#define Csum state->Csum
1579#define Crot state->Crot
1580#define word state->word
1581#define bcount state->bcount
1582
1583#define times85(x)	((((((x<<2)+x)<<2)+x)<<2)+x)
1584
1585static isc_result_t	byte_atob(int c, isc_buffer_t *target,
1586				  struct state *state);
1587static isc_result_t	putbyte(int c, isc_buffer_t *, struct state *state);
1588static isc_result_t	byte_btoa(int c, isc_buffer_t *, struct state *state);
1589
1590/*
1591 * Decode ASCII-encoded byte c into binary representation and
1592 * place into *bufp, advancing bufp.
1593 */
1594static isc_result_t
1595byte_atob(int c, isc_buffer_t *target, struct state *state) {
1596	char *s;
1597	if (c == 'z') {
1598		if (bcount != 0)
1599			return(DNS_R_SYNTAX);
1600		else {
1601			RETERR(putbyte(0, target, state));
1602			RETERR(putbyte(0, target, state));
1603			RETERR(putbyte(0, target, state));
1604			RETERR(putbyte(0, target, state));
1605		}
1606	} else if ((s = strchr(atob_digits, c)) != NULL) {
1607		if (bcount == 0) {
1608			word = s - atob_digits;
1609			++bcount;
1610		} else if (bcount < 4) {
1611			word = times85(word);
1612			word += s - atob_digits;
1613			++bcount;
1614		} else {
1615			word = times85(word);
1616			word += s - atob_digits;
1617			RETERR(putbyte((word >> 24) & 0xff, target, state));
1618			RETERR(putbyte((word >> 16) & 0xff, target, state));
1619			RETERR(putbyte((word >> 8) & 0xff, target, state));
1620			RETERR(putbyte(word & 0xff, target, state));
1621			word = 0;
1622			bcount = 0;
1623		}
1624	} else
1625		return(DNS_R_SYNTAX);
1626	return(ISC_R_SUCCESS);
1627}
1628
1629/*
1630 * Compute checksum info and place c into target.
1631 */
1632static isc_result_t
1633putbyte(int c, isc_buffer_t *target, struct state *state) {
1634	isc_region_t tr;
1635
1636	Ceor ^= c;
1637	Csum += c;
1638	Csum += 1;
1639	if ((Crot & 0x80000000)) {
1640		Crot <<= 1;
1641		Crot += 1;
1642	} else {
1643		Crot <<= 1;
1644	}
1645	Crot += c;
1646	isc_buffer_availableregion(target, &tr);
1647	if (tr.length < 1)
1648		return (ISC_R_NOSPACE);
1649	tr.base[0] = c;
1650	isc_buffer_add(target, 1);
1651	return (ISC_R_SUCCESS);
1652}
1653
1654/*
1655 * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
1656 * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
1657 * outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
1658 * in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
1659 * boundary, there will be no problem...it will be padded with 0 bytes, and
1660 * numbytes will indicate the correct number of bytes.  The main point is
1661 * that since the buffer is filled in 4 bytes at a time, even if there is
1662 * not a full 4 bytes of data at the end, there has to be room to 0-pad the
1663 * data, so the buffer must be of size divisible by 4).  Place the number of
1664 * output bytes in numbytes, and return a failure/success status.
1665 */
1666
1667static isc_result_t
1668atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) {
1669	long oeor, osum, orot;
1670	struct state statebuf, *state= &statebuf;
1671	isc_token_t token;
1672	char c;
1673	char *e;
1674
1675	Ceor = Csum = Crot = word = bcount = 0;
1676
1677	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1678				      ISC_FALSE));
1679	while (token.value.as_textregion.length != 0) {
1680		if ((c = token.value.as_textregion.base[0]) == 'x') {
1681			break;
1682		} else
1683			RETERR(byte_atob(c, target, state));
1684		isc_textregion_consume(&token.value.as_textregion, 1);
1685	}
1686
1687	/*
1688	 * Number of bytes.
1689	 */
1690	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
1691				      ISC_FALSE));
1692	if ((token.value.as_ulong % 4) != 0U)
1693		isc_buffer_subtract(target,  4 - (token.value.as_ulong % 4));
1694
1695	/*
1696	 * Checksum.
1697	 */
1698	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1699				      ISC_FALSE));
1700	oeor = strtol(DNS_AS_STR(token), &e, 16);
1701	if (*e != 0)
1702		return (DNS_R_SYNTAX);
1703
1704	/*
1705	 * Checksum.
1706	 */
1707	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1708				      ISC_FALSE));
1709	osum = strtol(DNS_AS_STR(token), &e, 16);
1710	if (*e != 0)
1711		return (DNS_R_SYNTAX);
1712
1713	/*
1714	 * Checksum.
1715	 */
1716	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1717				      ISC_FALSE));
1718	orot = strtol(DNS_AS_STR(token), &e, 16);
1719	if (*e != 0)
1720		return (DNS_R_SYNTAX);
1721
1722	if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
1723		return(DNS_R_BADCKSUM);
1724	return (ISC_R_SUCCESS);
1725}
1726
1727/*
1728 * Encode binary byte c into ASCII representation and place into *bufp,
1729 * advancing bufp.
1730 */
1731static isc_result_t
1732byte_btoa(int c, isc_buffer_t *target, struct state *state) {
1733	isc_region_t tr;
1734
1735	isc_buffer_availableregion(target, &tr);
1736	Ceor ^= c;
1737	Csum += c;
1738	Csum += 1;
1739	if ((Crot & 0x80000000)) {
1740		Crot <<= 1;
1741		Crot += 1;
1742	} else {
1743		Crot <<= 1;
1744	}
1745	Crot += c;
1746
1747	word <<= 8;
1748	word |= c;
1749	if (bcount == 3) {
1750		if (word == 0) {
1751			if (tr.length < 1)
1752				return (ISC_R_NOSPACE);
1753			tr.base[0] = 'z';
1754			isc_buffer_add(target, 1);
1755		} else {
1756		    register int tmp = 0;
1757		    register isc_int32_t tmpword = word;
1758
1759		    if (tmpword < 0) {
1760			   /*
1761			    * Because some don't support u_long.
1762			    */
1763			tmp = 32;
1764			tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1765		    }
1766		    if (tmpword < 0) {
1767			tmp = 64;
1768			tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1769		    }
1770			if (tr.length < 5)
1771				return (ISC_R_NOSPACE);
1772			tr.base[0] = atob_digits[(tmpword /
1773					      (isc_int32_t)(85 * 85 * 85 * 85))
1774						+ tmp];
1775			tmpword %= (isc_int32_t)(85 * 85 * 85 * 85);
1776			tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
1777			tmpword %= (85 * 85 * 85);
1778			tr.base[2] = atob_digits[tmpword / (85 * 85)];
1779			tmpword %= (85 * 85);
1780			tr.base[3] = atob_digits[tmpword / 85];
1781			tmpword %= 85;
1782			tr.base[4] = atob_digits[tmpword];
1783			isc_buffer_add(target, 5);
1784		}
1785		bcount = 0;
1786	} else {
1787		bcount += 1;
1788	}
1789	return (ISC_R_SUCCESS);
1790}
1791
1792
1793/*
1794 * Encode the binary data from inbuf, of length inbuflen, into a
1795 * target.  Return success/failure status
1796 */
1797static isc_result_t
1798btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
1799	int inc;
1800	struct state statebuf, *state = &statebuf;
1801	char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
1802
1803	Ceor = Csum = Crot = word = bcount = 0;
1804	for (inc = 0; inc < inbuflen; inbuf++, inc++)
1805		RETERR(byte_btoa(*inbuf, target, state));
1806
1807	while (bcount != 0)
1808		RETERR(byte_btoa(0, target, state));
1809
1810	/*
1811	 * Put byte count and checksum information at end of buffer,
1812	 * delimited by 'x'
1813	 */
1814	snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
1815	return (str_totext(buf, target));
1816}
1817
1818
1819static void
1820default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt,
1821			  ...)
1822{
1823	va_list ap;
1824
1825	UNUSED(callbacks);
1826
1827	va_start(ap, fmt);
1828	vfprintf(stderr, fmt, ap);
1829	va_end(ap);
1830	fprintf(stderr, "\n");
1831}
1832
1833static void
1834fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) {
1835	if (isc_lex_isfile(lexer) && callbacks != NULL) {
1836		const char *name = isc_lex_getsourcename(lexer);
1837		if (name == NULL)
1838			name = "UNKNOWN";
1839		(*callbacks->warn)(callbacks,
1840				   "%s:%lu: file does not end with newline",
1841				   name, isc_lex_getsourceline(lexer));
1842	}
1843}
1844
1845static void
1846warn_badmx(isc_token_t *token, isc_lex_t *lexer,
1847	   dns_rdatacallbacks_t *callbacks)
1848{
1849	const char *file;
1850	unsigned long line;
1851
1852	if (lexer != NULL) {
1853		file = isc_lex_getsourcename(lexer);
1854		line = isc_lex_getsourceline(lexer);
1855		(*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
1856				   file, line, DNS_AS_STR(*token),
1857				   dns_result_totext(DNS_R_MXISADDRESS));
1858	}
1859}
1860
1861static void
1862warn_badname(dns_name_t *name, isc_lex_t *lexer,
1863	     dns_rdatacallbacks_t *callbacks)
1864{
1865	const char *file;
1866	unsigned long line;
1867	char namebuf[DNS_NAME_FORMATSIZE];
1868
1869	if (lexer != NULL) {
1870		file = isc_lex_getsourcename(lexer);
1871		line = isc_lex_getsourceline(lexer);
1872		dns_name_format(name, namebuf, sizeof(namebuf));
1873		(*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
1874				   file, line, namebuf,
1875				   dns_result_totext(DNS_R_BADNAME));
1876	}
1877}
1878
1879static void
1880fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
1881	       dns_rdatacallbacks_t *callbacks, const char *name,
1882	       unsigned long line, isc_token_t *token, isc_result_t result)
1883{
1884	if (name == NULL)
1885		name = "UNKNOWN";
1886
1887	if (token != NULL) {
1888		switch (token->type) {
1889		case isc_tokentype_eol:
1890			(*callback)(callbacks, "%s: %s:%lu: near eol: %s",
1891				    "dns_rdata_fromtext", name, line,
1892				    dns_result_totext(result));
1893			break;
1894		case isc_tokentype_eof:
1895			(*callback)(callbacks, "%s: %s:%lu: near eof: %s",
1896				    "dns_rdata_fromtext", name, line,
1897				    dns_result_totext(result));
1898			break;
1899		case isc_tokentype_number:
1900			(*callback)(callbacks, "%s: %s:%lu: near %lu: %s",
1901				    "dns_rdata_fromtext", name, line,
1902				    token->value.as_ulong,
1903				    dns_result_totext(result));
1904			break;
1905		case isc_tokentype_string:
1906		case isc_tokentype_qstring:
1907			(*callback)(callbacks, "%s: %s:%lu: near '%s': %s",
1908				    "dns_rdata_fromtext", name, line,
1909				    DNS_AS_STR(*token),
1910				    dns_result_totext(result));
1911			break;
1912		default:
1913			(*callback)(callbacks, "%s: %s:%lu: %s",
1914				    "dns_rdata_fromtext", name, line,
1915				    dns_result_totext(result));
1916			break;
1917		}
1918	} else {
1919		(*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s",
1920			    name, line, dns_result_totext(result));
1921	}
1922}
1923
1924dns_rdatatype_t
1925dns_rdata_covers(dns_rdata_t *rdata) {
1926	if (rdata->type == 46)
1927		return (covers_rrsig(rdata));
1928	return (covers_sig(rdata));
1929}
1930
1931isc_boolean_t
1932dns_rdatatype_ismeta(dns_rdatatype_t type) {
1933	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0)
1934		return (ISC_TRUE);
1935	return (ISC_FALSE);
1936}
1937
1938isc_boolean_t
1939dns_rdatatype_issingleton(dns_rdatatype_t type) {
1940	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON)
1941	    != 0)
1942		return (ISC_TRUE);
1943	return (ISC_FALSE);
1944}
1945
1946isc_boolean_t
1947dns_rdatatype_notquestion(dns_rdatatype_t type) {
1948	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION)
1949	    != 0)
1950		return (ISC_TRUE);
1951	return (ISC_FALSE);
1952}
1953
1954isc_boolean_t
1955dns_rdatatype_questiononly(dns_rdatatype_t type) {
1956	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY)
1957	    != 0)
1958		return (ISC_TRUE);
1959	return (ISC_FALSE);
1960}
1961
1962isc_boolean_t
1963dns_rdatatype_atparent(dns_rdatatype_t type) {
1964	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0)
1965		return (ISC_TRUE);
1966	return (ISC_FALSE);
1967}
1968
1969isc_boolean_t
1970dns_rdataclass_ismeta(dns_rdataclass_t rdclass) {
1971
1972	if (rdclass == dns_rdataclass_reserved0
1973	    || rdclass == dns_rdataclass_none
1974	    || rdclass == dns_rdataclass_any)
1975		return (ISC_TRUE);
1976
1977	return (ISC_FALSE);  /* Assume it is not a meta class. */
1978}
1979
1980isc_boolean_t
1981dns_rdatatype_isdnssec(dns_rdatatype_t type) {
1982	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0)
1983		return (ISC_TRUE);
1984	return (ISC_FALSE);
1985}
1986
1987isc_boolean_t
1988dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
1989	if ((dns_rdatatype_attributes(type)
1990	     & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH))
1991	    != 0)
1992		return (ISC_TRUE);
1993	return (ISC_FALSE);
1994}
1995
1996isc_boolean_t
1997dns_rdatatype_isknown(dns_rdatatype_t type) {
1998	if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN)
1999	    == 0)
2000		return (ISC_TRUE);
2001	return (ISC_FALSE);
2002}
2003
2004void
2005dns_rdata_exists(dns_rdata_t *rdata, dns_rdatatype_t type) {
2006
2007	REQUIRE(rdata != NULL);
2008	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2009
2010	rdata->data = NULL;
2011	rdata->length = 0;
2012	rdata->flags = DNS_RDATA_UPDATE;
2013	rdata->type = type;
2014	rdata->rdclass = dns_rdataclass_any;
2015}
2016
2017void
2018dns_rdata_notexist(dns_rdata_t *rdata, dns_rdatatype_t type) {
2019
2020	REQUIRE(rdata != NULL);
2021	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2022
2023	rdata->data = NULL;
2024	rdata->length = 0;
2025	rdata->flags = DNS_RDATA_UPDATE;
2026	rdata->type = type;
2027	rdata->rdclass = dns_rdataclass_none;
2028}
2029
2030void
2031dns_rdata_deleterrset(dns_rdata_t *rdata, dns_rdatatype_t type) {
2032
2033	REQUIRE(rdata != NULL);
2034	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2035
2036	rdata->data = NULL;
2037	rdata->length = 0;
2038	rdata->flags = DNS_RDATA_UPDATE;
2039	rdata->type = type;
2040	rdata->rdclass = dns_rdataclass_any;
2041}
2042
2043void
2044dns_rdata_makedelete(dns_rdata_t *rdata) {
2045	REQUIRE(rdata != NULL);
2046
2047	rdata->rdclass = dns_rdataclass_none;
2048}
2049
2050const char *
2051dns_rdata_updateop(dns_rdata_t *rdata, dns_section_t section) {
2052
2053	REQUIRE(rdata != NULL);
2054	REQUIRE(DNS_RDATA_INITIALIZED(rdata));
2055
2056	switch (section) {
2057	case DNS_SECTION_PREREQUISITE:
2058		switch (rdata->rdclass) {
2059		case dns_rdataclass_none:
2060			switch (rdata->type) {
2061			case dns_rdatatype_any:
2062				return ("domain doesn't exist");
2063			default:
2064				return ("rrset doesn't exist");
2065			}
2066		case dns_rdataclass_any:
2067			switch (rdata->type) {
2068			case dns_rdatatype_any:
2069				return ("domain exists");
2070			default:
2071				return ("rrset exists (value independent)");
2072			}
2073		default:
2074			return ("rrset exists (value dependent)");
2075		}
2076	case DNS_SECTION_UPDATE:
2077		switch (rdata->rdclass) {
2078		case dns_rdataclass_none:
2079			return ("delete");
2080		case dns_rdataclass_any:
2081			switch (rdata->type) {
2082			case dns_rdatatype_any:
2083				return ("delete all rrsets");
2084			default:
2085				return ("delete rrset");
2086			}
2087		default:
2088			return ("add");
2089		}
2090	}
2091	return ("invalid");
2092}
2093