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