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