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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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, ®ion);
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