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