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