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