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