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