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