Import bind-9.3.4
[dragonfly.git] / contrib / bind-9.3 / lib / dns / rdata.c
blobbcd0e1500529367e0c9ba5b2e5cb43f393a3d078
1 /*
2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1998-2003 Internet Software Consortium.
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.
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.
18 /* $Id: rdata.c,v 1.147.2.11.2.22 2006/07/21 02:05:56 marka Exp $ */
20 #include <config.h>
21 #include <ctype.h>
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>
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/rcode.h>
40 #include <dns/rdata.h>
41 #include <dns/rdataclass.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/rdatatype.h>
44 #include <dns/result.h>
45 #include <dns/secalg.h>
46 #include <dns/secproto.h>
47 #include <dns/time.h>
48 #include <dns/ttl.h>
50 #define RETERR(x) \
51 do { \
52 isc_result_t _r = (x); \
53 if (_r != ISC_R_SUCCESS) \
54 return (_r); \
55 } while (0)
57 #define RETTOK(x) \
58 do { \
59 isc_result_t _r = (x); \
60 if (_r != ISC_R_SUCCESS) { \
61 isc_lex_ungettoken(lexer, &token); \
62 return (_r); \
63 } \
64 } while (0)
66 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
68 #define ARGS_FROMTEXT int rdclass, dns_rdatatype_t type, \
69 isc_lex_t *lexer, dns_name_t *origin, \
70 unsigned int options, isc_buffer_t *target, \
71 dns_rdatacallbacks_t *callbacks
73 #define ARGS_TOTEXT dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
74 isc_buffer_t *target
76 #define ARGS_FROMWIRE int rdclass, dns_rdatatype_t type, \
77 isc_buffer_t *source, dns_decompress_t *dctx, \
78 unsigned int options, isc_buffer_t *target
80 #define ARGS_TOWIRE dns_rdata_t *rdata, dns_compress_t *cctx, \
81 isc_buffer_t *target
83 #define ARGS_COMPARE const dns_rdata_t *rdata1, const dns_rdata_t *rdata2
85 #define ARGS_FROMSTRUCT int rdclass, dns_rdatatype_t type, \
86 void *source, isc_buffer_t *target
88 #define ARGS_TOSTRUCT dns_rdata_t *rdata, void *target, isc_mem_t *mctx
90 #define ARGS_FREESTRUCT void *source
92 #define ARGS_ADDLDATA dns_rdata_t *rdata, dns_additionaldatafunc_t add, \
93 void *arg
95 #define ARGS_DIGEST dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg
97 #define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \
98 dns_rdatatype_t type, isc_boolean_t wildcard
100 #define ARGS_CHECKNAMES dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad
104 * Context structure for the totext_ functions.
105 * Contains formatting options for rdata-to-text
106 * conversion.
108 typedef struct dns_rdata_textctx {
109 dns_name_t *origin; /* Current origin, or NULL. */
110 unsigned int flags; /* DNS_STYLEFLAG_* */
111 unsigned int width; /* Width of rdata column. */
112 const char *linebreak; /* Line break string. */
113 } dns_rdata_textctx_t;
115 static isc_result_t
116 txt_totext(isc_region_t *source, isc_buffer_t *target);
118 static isc_result_t
119 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
121 static isc_result_t
122 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
124 static isc_boolean_t
125 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
127 static unsigned int
128 name_length(dns_name_t *name);
130 static isc_result_t
131 str_totext(const char *source, isc_buffer_t *target);
133 static isc_result_t
134 inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
136 static isc_boolean_t
137 buffer_empty(isc_buffer_t *source);
139 static void
140 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region);
142 static isc_result_t
143 uint32_tobuffer(isc_uint32_t, isc_buffer_t *target);
145 static isc_result_t
146 uint16_tobuffer(isc_uint32_t, isc_buffer_t *target);
148 static isc_result_t
149 uint8_tobuffer(isc_uint32_t, isc_buffer_t *target);
151 static isc_result_t
152 name_tobuffer(dns_name_t *name, isc_buffer_t *target);
154 static isc_uint32_t
155 uint32_fromregion(isc_region_t *region);
157 static isc_uint16_t
158 uint16_fromregion(isc_region_t *region);
160 static isc_uint8_t
161 uint8_fromregion(isc_region_t *region);
163 static isc_result_t
164 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
166 static int
167 hexvalue(char value);
169 static int
170 decvalue(char value);
172 static isc_result_t
173 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
175 static isc_result_t
176 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target);
178 static void
179 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...)
180 ISC_FORMAT_PRINTF(2, 3);
182 static void
183 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
184 dns_rdatacallbacks_t *callbacks, const char *name,
185 unsigned long line, isc_token_t *token, isc_result_t result);
187 static void
188 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);
190 static isc_result_t
191 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
192 isc_buffer_t *target);
194 static void
195 warn_badname(dns_name_t *name, isc_lex_t *lexer,
196 dns_rdatacallbacks_t *callbacks);
198 static inline int
199 getquad(const void *src, struct in_addr *dst,
200 isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks)
202 int result;
203 struct in_addr *tmp;
205 result = inet_aton(src, dst);
206 if (result == 1 && callbacks != NULL &&
207 inet_pton(AF_INET, src, &tmp) != 1) {
208 const char *name = isc_lex_getsourcename(lexer);
209 if (name == NULL)
210 name = "UNKNOWN";
211 (*callbacks->warn)(callbacks, "%s:%lu: \"%s\" "
212 "is not a decimal dotted quad", name,
213 isc_lex_getsourceline(lexer), src);
215 return (result);
218 static inline isc_result_t
219 name_duporclone(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
221 if (mctx != NULL)
222 return (dns_name_dup(source, mctx, target));
223 dns_name_clone(source, target);
224 return (ISC_R_SUCCESS);
227 static inline void *
228 mem_maybedup(isc_mem_t *mctx, void *source, size_t length) {
229 void *new;
231 if (mctx == NULL)
232 return (source);
233 new = isc_mem_allocate(mctx, length);
234 if (new != NULL)
235 memcpy(new, source, length);
237 return (new);
240 static const char hexdigits[] = "0123456789abcdef";
241 static const char decdigits[] = "0123456789";
243 #include "code.h"
245 #define META 0x0001
246 #define RESERVED 0x0002
248 /***
249 *** Initialization
250 ***/
252 void
253 dns_rdata_init(dns_rdata_t *rdata) {
255 REQUIRE(rdata != NULL);
257 rdata->data = NULL;
258 rdata->length = 0;
259 rdata->rdclass = 0;
260 rdata->type = 0;
261 rdata->flags = 0;
262 ISC_LINK_INIT(rdata, link);
263 /* ISC_LIST_INIT(rdata->list); */
266 #if 0
267 #define DNS_RDATA_INITIALIZED(rdata) \
268 ((rdata)->data == NULL && (rdata)->length == 0 && \
269 (rdata)->rdclass == 0 && (rdata)->type == 0 && (rdata)->flags == 0 && \
270 !ISC_LINK_LINKED((rdata), link))
271 #else
272 #ifdef ISC_LIST_CHECKINIT
273 #define DNS_RDATA_INITIALIZED(rdata) \
274 (!ISC_LINK_LINKED((rdata), link))
275 #else
276 #define DNS_RDATA_INITIALIZED(rdata) ISC_TRUE
277 #endif
278 #endif
279 #define DNS_RDATA_VALIDFLAGS(rdata) \
280 (((rdata)->flags & ~DNS_RDATA_UPDATE) == 0)
282 void
283 dns_rdata_reset(dns_rdata_t *rdata) {
285 REQUIRE(rdata != NULL);
287 REQUIRE(!ISC_LINK_LINKED(rdata, link));
288 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
290 rdata->data = NULL;
291 rdata->length = 0;
292 rdata->rdclass = 0;
293 rdata->type = 0;
294 rdata->flags = 0;
297 /***
299 ***/
301 void
302 dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
304 REQUIRE(src != NULL);
305 REQUIRE(target != NULL);
307 REQUIRE(DNS_RDATA_INITIALIZED(target));
309 REQUIRE(DNS_RDATA_VALIDFLAGS(src));
310 REQUIRE(DNS_RDATA_VALIDFLAGS(target));
312 target->data = src->data;
313 target->length = src->length;
314 target->rdclass = src->rdclass;
315 target->type = src->type;
316 target->flags = src->flags;
320 /***
321 *** Comparisons
322 ***/
325 dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2) {
326 int result = 0;
327 isc_boolean_t use_default = ISC_FALSE;
329 REQUIRE(rdata1 != NULL);
330 REQUIRE(rdata2 != NULL);
331 REQUIRE(rdata1->data != NULL);
332 REQUIRE(rdata2->data != NULL);
333 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata1));
334 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata2));
336 if (rdata1->rdclass != rdata2->rdclass)
337 return (rdata1->rdclass < rdata2->rdclass ? -1 : 1);
339 if (rdata1->type != rdata2->type)
340 return (rdata1->type < rdata2->type ? -1 : 1);
342 COMPARESWITCH
344 if (use_default) {
345 isc_region_t r1;
346 isc_region_t r2;
348 dns_rdata_toregion(rdata1, &r1);
349 dns_rdata_toregion(rdata2, &r2);
350 result = isc_region_compare(&r1, &r2);
352 return (result);
355 /***
356 *** Conversions
357 ***/
359 void
360 dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
361 dns_rdatatype_t type, isc_region_t *r)
364 REQUIRE(rdata != NULL);
365 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
366 REQUIRE(r != NULL);
368 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
370 rdata->data = r->base;
371 rdata->length = r->length;
372 rdata->rdclass = rdclass;
373 rdata->type = type;
374 rdata->flags = 0;
377 void
378 dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
380 REQUIRE(rdata != NULL);
381 REQUIRE(r != NULL);
382 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
384 r->base = rdata->data;
385 r->length = rdata->length;
388 isc_result_t
389 dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
390 dns_rdatatype_t type, isc_buffer_t *source,
391 dns_decompress_t *dctx, unsigned int options,
392 isc_buffer_t *target)
394 isc_result_t result = ISC_R_NOTIMPLEMENTED;
395 isc_region_t region;
396 isc_buffer_t ss;
397 isc_buffer_t st;
398 isc_boolean_t use_default = ISC_FALSE;
399 isc_uint32_t activelength;
401 REQUIRE(dctx != NULL);
402 if (rdata != NULL) {
403 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
404 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
407 if (type == 0)
408 return (DNS_R_FORMERR);
410 ss = *source;
411 st = *target;
413 activelength = isc_buffer_activelength(source);
414 INSIST(activelength < 65536);
416 FROMWIRESWITCH
418 if (use_default) {
419 if (activelength > isc_buffer_availablelength(target))
420 result = ISC_R_NOSPACE;
421 else {
422 isc_buffer_putmem(target, isc_buffer_current(source),
423 activelength);
424 isc_buffer_forward(source, activelength);
425 result = ISC_R_SUCCESS;
430 * We should have consumed all of our buffer.
432 if (result == ISC_R_SUCCESS && !buffer_empty(source))
433 result = DNS_R_EXTRADATA;
435 if (rdata != NULL && result == ISC_R_SUCCESS) {
436 region.base = isc_buffer_used(&st);
437 region.length = isc_buffer_usedlength(target) -
438 isc_buffer_usedlength(&st);
439 dns_rdata_fromregion(rdata, rdclass, type, &region);
442 if (result != ISC_R_SUCCESS) {
443 *source = ss;
444 *target = st;
446 return (result);
449 isc_result_t
450 dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
451 isc_buffer_t *target)
453 isc_result_t result = ISC_R_NOTIMPLEMENTED;
454 isc_boolean_t use_default = ISC_FALSE;
455 isc_region_t tr;
456 isc_buffer_t st;
458 REQUIRE(rdata != NULL);
459 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
462 * Some DynDNS meta-RRs have empty rdata.
464 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
465 INSIST(rdata->length == 0);
466 return (ISC_R_SUCCESS);
469 st = *target;
471 TOWIRESWITCH
473 if (use_default) {
474 isc_buffer_availableregion(target, &tr);
475 if (tr.length < rdata->length)
476 return (ISC_R_NOSPACE);
477 memcpy(tr.base, rdata->data, rdata->length);
478 isc_buffer_add(target, rdata->length);
479 return (ISC_R_SUCCESS);
481 if (result != ISC_R_SUCCESS) {
482 *target = st;
483 INSIST(target->used < 65536);
484 dns_compress_rollback(cctx, (isc_uint16_t)target->used);
486 return (result);
490 * If the binary data in 'src' is valid uncompressed wire format
491 * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS
492 * and copy the validated rdata to 'dest'. Otherwise return an error.
494 static isc_result_t
495 rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass,
496 dns_rdatatype_t type)
498 dns_decompress_t dctx;
499 dns_rdata_t rdata = DNS_RDATA_INIT;
500 isc_result_t result;
502 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
503 isc_buffer_setactive(src, isc_buffer_usedlength(src));
504 result = dns_rdata_fromwire(&rdata, rdclass, type, src,
505 &dctx, 0, dest);
506 dns_decompress_invalidate(&dctx);
508 return (result);
511 static isc_result_t
512 unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type,
513 isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target)
515 isc_result_t result;
516 isc_buffer_t *buf = NULL;
517 isc_token_t token;
519 if (type == 0 || dns_rdatatype_ismeta(type))
520 return (DNS_R_METATYPE);
522 result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
523 ISC_FALSE);
524 if (result == ISC_R_SUCCESS && token.value.as_ulong > 65535U)
525 return (ISC_R_RANGE);
526 result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong);
527 if (result != ISC_R_SUCCESS)
528 return (result);
530 result = isc_hex_tobuffer(lexer, buf,
531 (unsigned int)token.value.as_ulong);
532 if (result != ISC_R_SUCCESS)
533 goto failure;
534 if (isc_buffer_usedlength(buf) != token.value.as_ulong) {
535 result = ISC_R_UNEXPECTEDEND;
536 goto failure;
539 if (dns_rdatatype_isknown(type)) {
540 result = rdata_validate(buf, target, rdclass, type);
541 } else {
542 isc_region_t r;
543 isc_buffer_usedregion(buf, &r);
544 result = isc_buffer_copyregion(target, &r);
546 if (result != ISC_R_SUCCESS)
547 goto failure;
549 isc_buffer_free(&buf);
550 return (ISC_R_SUCCESS);
552 failure:
553 isc_buffer_free(&buf);
554 return (result);
557 isc_result_t
558 dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
559 dns_rdatatype_t type, isc_lex_t *lexer,
560 dns_name_t *origin, unsigned int options, isc_mem_t *mctx,
561 isc_buffer_t *target, dns_rdatacallbacks_t *callbacks)
563 isc_result_t result = ISC_R_NOTIMPLEMENTED;
564 isc_region_t region;
565 isc_buffer_t st;
566 isc_token_t token;
567 unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
568 ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
569 char *name;
570 unsigned long line;
571 void (*callback)(dns_rdatacallbacks_t *, const char *, ...);
572 isc_result_t tresult;
574 REQUIRE(origin == NULL || dns_name_isabsolute(origin) == ISC_TRUE);
575 if (rdata != NULL) {
576 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
577 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
579 if (callbacks != NULL) {
580 REQUIRE(callbacks->warn != NULL);
581 REQUIRE(callbacks->error != NULL);
584 st = *target;
586 if (callbacks != NULL)
587 callback = callbacks->error;
588 else
589 callback = default_fromtext_callback;
591 result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
592 ISC_FALSE);
593 if (result != ISC_R_SUCCESS) {
594 name = isc_lex_getsourcename(lexer);
595 line = isc_lex_getsourceline(lexer);
596 fromtext_error(callback, callbacks, name, line,
597 &token, result);
598 return (result);
601 if (strcmp(DNS_AS_STR(token), "\\#") == 0)
602 result = unknown_fromtext(rdclass, type, lexer, mctx, target);
603 else {
604 isc_lex_ungettoken(lexer, &token);
606 FROMTEXTSWITCH
610 * Consume to end of line / file.
611 * If not at end of line initially set error code.
612 * Call callback via fromtext_error once if there was an error.
614 do {
615 name = isc_lex_getsourcename(lexer);
616 line = isc_lex_getsourceline(lexer);
617 tresult = isc_lex_gettoken(lexer, lexoptions, &token);
618 if (tresult != ISC_R_SUCCESS) {
619 if (result == ISC_R_SUCCESS)
620 result = tresult;
621 if (callback != NULL)
622 fromtext_error(callback, callbacks, name,
623 line, NULL, result);
624 break;
625 } else if (token.type != isc_tokentype_eol &&
626 token.type != isc_tokentype_eof) {
627 if (result == ISC_R_SUCCESS)
628 result = DNS_R_EXTRATOKEN;
629 if (callback != NULL) {
630 fromtext_error(callback, callbacks, name,
631 line, &token, result);
632 callback = NULL;
634 } else if (result != ISC_R_SUCCESS && callback != NULL) {
635 fromtext_error(callback, callbacks, name, line,
636 &token, result);
637 break;
638 } else {
639 if (token.type == isc_tokentype_eof)
640 fromtext_warneof(lexer, callbacks);
641 break;
643 } while (1);
645 if (rdata != NULL && result == ISC_R_SUCCESS) {
646 region.base = isc_buffer_used(&st);
647 region.length = isc_buffer_usedlength(target) -
648 isc_buffer_usedlength(&st);
649 dns_rdata_fromregion(rdata, rdclass, type, &region);
651 if (result != ISC_R_SUCCESS) {
652 *target = st;
654 return (result);
657 static isc_result_t
658 rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
659 isc_buffer_t *target)
661 isc_result_t result = ISC_R_NOTIMPLEMENTED;
662 isc_boolean_t use_default = ISC_FALSE;
663 char buf[sizeof("65535")];
664 isc_region_t sr;
666 REQUIRE(rdata != NULL);
667 REQUIRE(tctx->origin == NULL ||
668 dns_name_isabsolute(tctx->origin) == ISC_TRUE);
671 * Some DynDNS meta-RRs have empty rdata.
673 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
674 INSIST(rdata->length == 0);
675 return (ISC_R_SUCCESS);
678 TOTEXTSWITCH
680 if (use_default) {
681 strlcpy(buf, "\\# ", sizeof(buf));
682 result = str_totext(buf, target);
683 dns_rdata_toregion(rdata, &sr);
684 INSIST(sr.length < 65536);
685 snprintf(buf, sizeof(buf), "%u", sr.length);
686 result = str_totext(buf, target);
687 if (sr.length != 0 && result == ISC_R_SUCCESS) {
688 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
689 result = str_totext(" ( ", target);
690 else
691 result = str_totext(" ", target);
692 if (result == ISC_R_SUCCESS)
693 result = isc_hex_totext(&sr, tctx->width - 2,
694 tctx->linebreak,
695 target);
696 if (result == ISC_R_SUCCESS &&
697 (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
698 result = str_totext(" )", target);
702 return (result);
705 isc_result_t
706 dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
708 dns_rdata_textctx_t tctx;
710 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
713 * Set up formatting options for single-line output.
715 tctx.origin = origin;
716 tctx.flags = 0;
717 tctx.width = 60;
718 tctx.linebreak = " ";
719 return (rdata_totext(rdata, &tctx, target));
722 isc_result_t
723 dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
724 unsigned int flags, unsigned int width,
725 char *linebreak, isc_buffer_t *target)
727 dns_rdata_textctx_t tctx;
729 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
732 * Set up formatting options for formatted output.
734 tctx.origin = origin;
735 tctx.flags = flags;
736 if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) {
737 tctx.width = width;
738 tctx.linebreak = linebreak;
739 } else {
740 tctx.width = 60; /* Used for hex word length only. */
741 tctx.linebreak = " ";
743 return (rdata_totext(rdata, &tctx, target));
746 isc_result_t
747 dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
748 dns_rdatatype_t type, void *source,
749 isc_buffer_t *target)
751 isc_result_t result = ISC_R_NOTIMPLEMENTED;
752 isc_buffer_t st;
753 isc_region_t region;
754 isc_boolean_t use_default = ISC_FALSE;
756 REQUIRE(source != NULL);
757 if (rdata != NULL) {
758 REQUIRE(DNS_RDATA_INITIALIZED(rdata));
759 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
762 st = *target;
764 FROMSTRUCTSWITCH
766 if (use_default)
767 (void)NULL;
769 if (rdata != NULL && result == ISC_R_SUCCESS) {
770 region.base = isc_buffer_used(&st);
771 region.length = isc_buffer_usedlength(target) -
772 isc_buffer_usedlength(&st);
773 dns_rdata_fromregion(rdata, rdclass, type, &region);
775 if (result != ISC_R_SUCCESS)
776 *target = st;
777 return (result);
780 isc_result_t
781 dns_rdata_tostruct(dns_rdata_t *rdata, void *target, isc_mem_t *mctx) {
782 isc_result_t result = ISC_R_NOTIMPLEMENTED;
783 isc_boolean_t use_default = ISC_FALSE;
785 REQUIRE(rdata != NULL);
786 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
788 TOSTRUCTSWITCH
790 if (use_default)
791 (void)NULL;
793 return (result);
796 void
797 dns_rdata_freestruct(void *source) {
798 dns_rdatacommon_t *common = source;
799 REQUIRE(source != NULL);
801 FREESTRUCTSWITCH
804 isc_result_t
805 dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
806 void *arg)
808 isc_result_t result = ISC_R_NOTIMPLEMENTED;
809 isc_boolean_t use_default = ISC_FALSE;
812 * Call 'add' for each name and type from 'rdata' which is subject to
813 * additional section processing.
816 REQUIRE(rdata != NULL);
817 REQUIRE(add != NULL);
818 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
820 ADDITIONALDATASWITCH
822 /* No additional processing for unknown types */
823 if (use_default)
824 result = ISC_R_SUCCESS;
826 return (result);
829 isc_result_t
830 dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) {
831 isc_result_t result = ISC_R_NOTIMPLEMENTED;
832 isc_boolean_t use_default = ISC_FALSE;
833 isc_region_t r;
836 * Send 'rdata' in DNSSEC canonical form to 'digest'.
839 REQUIRE(rdata != NULL);
840 REQUIRE(digest != NULL);
841 REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
843 DIGESTSWITCH
845 if (use_default) {
846 dns_rdata_toregion(rdata, &r);
847 result = (digest)(arg, &r);
850 return (result);
853 isc_boolean_t
854 dns_rdata_checkowner(dns_name_t *name, dns_rdataclass_t rdclass,
855 dns_rdatatype_t type, isc_boolean_t wildcard)
857 isc_boolean_t result;
859 CHECKOWNERSWITCH
860 return (result);
863 isc_boolean_t
864 dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad)
866 isc_boolean_t result;
868 CHECKNAMESSWITCH
869 return (result);
872 unsigned int
873 dns_rdatatype_attributes(dns_rdatatype_t type)
875 RDATATYPE_ATTRIBUTE_SW
876 if (type >= (dns_rdatatype_t)128 && type < (dns_rdatatype_t)255)
877 return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META);
878 return (DNS_RDATATYPEATTR_UNKNOWN);
881 isc_result_t
882 dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
883 unsigned int hash;
884 unsigned int n;
885 unsigned char a, b;
887 n = source->length;
889 if (n == 0)
890 return (DNS_R_UNKNOWN);
892 a = tolower((unsigned char)source->base[0]);
893 b = tolower((unsigned char)source->base[n - 1]);
895 hash = ((a + n) * b) % 256;
898 * This switch block is inlined via #define, and will use "return"
899 * to return a result to the caller if it is a valid (known)
900 * rdatatype name.
902 RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep);
904 if (source->length > 4 && source->length < (4 + sizeof("65000")) &&
905 strncasecmp("type", source->base, 4) == 0) {
906 char buf[sizeof("65000")];
907 char *endp;
908 unsigned int val;
910 strncpy(buf, source->base + 4, source->length - 4);
911 buf[source->length - 4] = '\0';
912 val = strtoul(buf, &endp, 10);
913 if (*endp == '\0' && val <= 0xffff) {
914 *typep = (dns_rdatatype_t)val;
915 return (ISC_R_SUCCESS);
919 return (DNS_R_UNKNOWN);
922 isc_result_t
923 dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
924 char buf[sizeof("TYPE65535")];
926 RDATATYPE_TOTEXT_SW
927 snprintf(buf, sizeof(buf), "TYPE%u", type);
928 return (str_totext(buf, target));
931 void
932 dns_rdatatype_format(dns_rdatatype_t rdtype,
933 char *array, unsigned int size)
935 isc_result_t result;
936 isc_buffer_t buf;
938 isc_buffer_init(&buf, array, size);
939 result = dns_rdatatype_totext(rdtype, &buf);
941 * Null terminate.
943 if (result == ISC_R_SUCCESS) {
944 if (isc_buffer_availablelength(&buf) >= 1)
945 isc_buffer_putuint8(&buf, 0);
946 else
947 result = ISC_R_NOSPACE;
949 if (result != ISC_R_SUCCESS) {
950 snprintf(array, size, "<unknown>");
951 array[size - 1] = '\0';
956 * Private function.
959 static unsigned int
960 name_length(dns_name_t *name) {
961 return (name->length);
964 static isc_result_t
965 txt_totext(isc_region_t *source, isc_buffer_t *target) {
966 unsigned int tl;
967 unsigned int n;
968 unsigned char *sp;
969 char *tp;
970 isc_region_t region;
972 isc_buffer_availableregion(target, &region);
973 sp = source->base;
974 tp = (char *)region.base;
975 tl = region.length;
977 n = *sp++;
979 REQUIRE(n + 1 <= source->length);
981 if (tl < 1)
982 return (ISC_R_NOSPACE);
983 *tp++ = '"';
984 tl--;
985 while (n--) {
986 if (*sp < 0x20 || *sp >= 0x7f) {
987 if (tl < 4)
988 return (ISC_R_NOSPACE);
989 *tp++ = 0x5c;
990 *tp++ = 0x30 + ((*sp / 100) % 10);
991 *tp++ = 0x30 + ((*sp / 10) % 10);
992 *tp++ = 0x30 + (*sp % 10);
993 sp++;
994 tl -= 4;
995 continue;
997 /* double quote, semi-colon, backslash */
998 if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) {
999 if (tl < 2)
1000 return (ISC_R_NOSPACE);
1001 *tp++ = '\\';
1002 tl--;
1004 if (tl < 1)
1005 return (ISC_R_NOSPACE);
1006 *tp++ = *sp++;
1007 tl--;
1009 if (tl < 1)
1010 return (ISC_R_NOSPACE);
1011 *tp++ = '"';
1012 tl--;
1013 isc_buffer_add(target, tp - (char *)region.base);
1014 isc_region_consume(source, *source->base + 1);
1015 return (ISC_R_SUCCESS);
1018 static isc_result_t
1019 txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
1020 isc_region_t tregion;
1021 isc_boolean_t escape;
1022 unsigned int n, nrem;
1023 char *s;
1024 unsigned char *t;
1025 int d;
1026 int c;
1028 isc_buffer_availableregion(target, &tregion);
1029 s = source->base;
1030 n = source->length;
1031 t = tregion.base;
1032 nrem = tregion.length;
1033 escape = ISC_FALSE;
1034 if (nrem < 1)
1035 return (ISC_R_NOSPACE);
1037 * Length byte.
1039 nrem--;
1040 t++;
1042 * Maximum text string length.
1044 if (nrem > 255)
1045 nrem = 255;
1046 while (n-- != 0) {
1047 c = (*s++) & 0xff;
1048 if (escape && (d = decvalue((char)c)) != -1) {
1049 c = d;
1050 if (n == 0)
1051 return (DNS_R_SYNTAX);
1052 n--;
1053 if ((d = decvalue(*s++)) != -1)
1054 c = c * 10 + d;
1055 else
1056 return (DNS_R_SYNTAX);
1057 if (n == 0)
1058 return (DNS_R_SYNTAX);
1059 n--;
1060 if ((d = decvalue(*s++)) != -1)
1061 c = c * 10 + d;
1062 else
1063 return (DNS_R_SYNTAX);
1064 if (c > 255)
1065 return (DNS_R_SYNTAX);
1066 } else if (!escape && c == '\\') {
1067 escape = ISC_TRUE;
1068 continue;
1070 escape = ISC_FALSE;
1071 if (nrem == 0)
1072 return (ISC_R_NOSPACE);
1073 *t++ = c;
1074 nrem--;
1076 if (escape)
1077 return (DNS_R_SYNTAX);
1078 *tregion.base = t - tregion.base - 1;
1079 isc_buffer_add(target, *tregion.base + 1);
1080 return (ISC_R_SUCCESS);
1083 static isc_result_t
1084 txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
1085 unsigned int n;
1086 isc_region_t sregion;
1087 isc_region_t tregion;
1089 isc_buffer_activeregion(source, &sregion);
1090 if (sregion.length == 0)
1091 return(ISC_R_UNEXPECTEDEND);
1092 n = *sregion.base + 1;
1093 if (n > sregion.length)
1094 return (ISC_R_UNEXPECTEDEND);
1096 isc_buffer_availableregion(target, &tregion);
1097 if (n > tregion.length)
1098 return (ISC_R_NOSPACE);
1100 memcpy(tregion.base, sregion.base, n);
1101 isc_buffer_forward(source, n);
1102 isc_buffer_add(target, n);
1103 return (ISC_R_SUCCESS);
1106 static isc_boolean_t
1107 name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) {
1108 int l1, l2;
1110 if (origin == NULL)
1111 goto return_false;
1113 if (dns_name_compare(origin, dns_rootname) == 0)
1114 goto return_false;
1116 if (!dns_name_issubdomain(name, origin))
1117 goto return_false;
1119 l1 = dns_name_countlabels(name);
1120 l2 = dns_name_countlabels(origin);
1122 if (l1 == l2)
1123 goto return_false;
1125 dns_name_getlabelsequence(name, 0, l1 - l2, target);
1126 return (ISC_TRUE);
1128 return_false:
1129 *target = *name;
1130 return (ISC_FALSE);
1133 static isc_result_t
1134 str_totext(const char *source, isc_buffer_t *target) {
1135 unsigned int l;
1136 isc_region_t region;
1138 isc_buffer_availableregion(target, &region);
1139 l = strlen(source);
1141 if (l > region.length)
1142 return (ISC_R_NOSPACE);
1144 memcpy(region.base, source, l);
1145 isc_buffer_add(target, l);
1146 return (ISC_R_SUCCESS);
1149 static isc_result_t
1150 inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
1151 char tmpbuf[64];
1153 /* Note - inet_ntop doesn't do size checking on its input. */
1154 if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
1155 return (ISC_R_NOSPACE);
1156 if (strlen(tmpbuf) > isc_buffer_availablelength(target))
1157 return (ISC_R_NOSPACE);
1158 isc_buffer_putstr(target, tmpbuf);
1159 return (ISC_R_SUCCESS);
1162 static isc_boolean_t
1163 buffer_empty(isc_buffer_t *source) {
1164 return((source->current == source->active) ? ISC_TRUE : ISC_FALSE);
1167 static void
1168 buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) {
1169 isc_buffer_init(buffer, region->base, region->length);
1170 isc_buffer_add(buffer, region->length);
1171 isc_buffer_setactive(buffer, region->length);
1174 static isc_result_t
1175 uint32_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1176 isc_region_t region;
1178 isc_buffer_availableregion(target, &region);
1179 if (region.length < 4)
1180 return (ISC_R_NOSPACE);
1181 isc_buffer_putuint32(target, value);
1182 return (ISC_R_SUCCESS);
1185 static isc_result_t
1186 uint16_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1187 isc_region_t region;
1189 if (value > 0xffff)
1190 return (ISC_R_RANGE);
1191 isc_buffer_availableregion(target, &region);
1192 if (region.length < 2)
1193 return (ISC_R_NOSPACE);
1194 isc_buffer_putuint16(target, (isc_uint16_t)value);
1195 return (ISC_R_SUCCESS);
1198 static isc_result_t
1199 uint8_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
1200 isc_region_t region;
1202 if (value > 0xff)
1203 return (ISC_R_RANGE);
1204 isc_buffer_availableregion(target, &region);
1205 if (region.length < 1)
1206 return (ISC_R_NOSPACE);
1207 isc_buffer_putuint8(target, (isc_uint8_t)value);
1208 return (ISC_R_SUCCESS);
1211 static isc_result_t
1212 name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
1213 isc_region_t r;
1214 dns_name_toregion(name, &r);
1215 return (isc_buffer_copyregion(target, &r));
1218 static isc_uint32_t
1219 uint32_fromregion(isc_region_t *region) {
1220 isc_uint32_t value;
1222 REQUIRE(region->length >= 4);
1223 value = region->base[0] << 24;
1224 value |= region->base[1] << 16;
1225 value |= region->base[2] << 8;
1226 value |= region->base[3];
1227 return(value);
1230 static isc_uint16_t
1231 uint16_fromregion(isc_region_t *region) {
1233 REQUIRE(region->length >= 2);
1235 return ((region->base[0] << 8) | region->base[1]);
1238 static isc_uint8_t
1239 uint8_fromregion(isc_region_t *region) {
1241 REQUIRE(region->length >= 1);
1243 return (region->base[0]);
1246 static isc_result_t
1247 mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
1248 isc_region_t tr;
1250 isc_buffer_availableregion(target, &tr);
1251 if (length > tr.length)
1252 return (ISC_R_NOSPACE);
1253 memcpy(tr.base, base, length);
1254 isc_buffer_add(target, length);
1255 return (ISC_R_SUCCESS);
1258 static int
1259 hexvalue(char value) {
1260 char *s;
1261 unsigned char c;
1263 c = (unsigned char)value;
1265 if (!isascii(c))
1266 return (-1);
1267 if (isupper(c))
1268 c = tolower(c);
1269 if ((s = strchr(hexdigits, c)) == NULL)
1270 return (-1);
1271 return (s - hexdigits);
1274 static int
1275 decvalue(char value) {
1276 char *s;
1279 * isascii() is valid for full range of int values, no need to
1280 * mask or cast.
1282 if (!isascii(value))
1283 return (-1);
1284 if ((s = strchr(decdigits, value)) == NULL)
1285 return (-1);
1286 return (s - decdigits);
1289 static const char atob_digits[86] =
1290 "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
1291 "abcdefghijklmnopqrstu";
1293 * Subroutines to convert between 8 bit binary bytes and printable ASCII.
1294 * Computes the number of bytes, and three kinds of simple checksums.
1295 * Incoming bytes are collected into 32-bit words, then printed in base 85:
1296 * exp(85,5) > exp(2,32)
1297 * The ASCII characters used are between '!' and 'u';
1298 * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
1300 * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
1301 * the atob/btoa programs, released with the compress program, in mod.sources.
1302 * Modified by Mike Schwartz 8/19/86 for use in BIND.
1303 * Modified to be re-entrant 3/2/99.
1307 struct state {
1308 isc_int32_t Ceor;
1309 isc_int32_t Csum;
1310 isc_int32_t Crot;
1311 isc_int32_t word;
1312 isc_int32_t bcount;
1315 #define Ceor state->Ceor
1316 #define Csum state->Csum
1317 #define Crot state->Crot
1318 #define word state->word
1319 #define bcount state->bcount
1321 #define times85(x) ((((((x<<2)+x)<<2)+x)<<2)+x)
1323 static isc_result_t byte_atob(int c, isc_buffer_t *target,
1324 struct state *state);
1325 static isc_result_t putbyte(int c, isc_buffer_t *, struct state *state);
1326 static isc_result_t byte_btoa(int c, isc_buffer_t *, struct state *state);
1329 * Decode ASCII-encoded byte c into binary representation and
1330 * place into *bufp, advancing bufp.
1332 static isc_result_t
1333 byte_atob(int c, isc_buffer_t *target, struct state *state) {
1334 char *s;
1335 if (c == 'z') {
1336 if (bcount != 0)
1337 return(DNS_R_SYNTAX);
1338 else {
1339 RETERR(putbyte(0, target, state));
1340 RETERR(putbyte(0, target, state));
1341 RETERR(putbyte(0, target, state));
1342 RETERR(putbyte(0, target, state));
1344 } else if ((s = strchr(atob_digits, c)) != NULL) {
1345 if (bcount == 0) {
1346 word = s - atob_digits;
1347 ++bcount;
1348 } else if (bcount < 4) {
1349 word = times85(word);
1350 word += s - atob_digits;
1351 ++bcount;
1352 } else {
1353 word = times85(word);
1354 word += s - atob_digits;
1355 RETERR(putbyte((word >> 24) & 0xff, target, state));
1356 RETERR(putbyte((word >> 16) & 0xff, target, state));
1357 RETERR(putbyte((word >> 8) & 0xff, target, state));
1358 RETERR(putbyte(word & 0xff, target, state));
1359 word = 0;
1360 bcount = 0;
1362 } else
1363 return(DNS_R_SYNTAX);
1364 return(ISC_R_SUCCESS);
1368 * Compute checksum info and place c into target.
1370 static isc_result_t
1371 putbyte(int c, isc_buffer_t *target, struct state *state) {
1372 isc_region_t tr;
1374 Ceor ^= c;
1375 Csum += c;
1376 Csum += 1;
1377 if ((Crot & 0x80000000)) {
1378 Crot <<= 1;
1379 Crot += 1;
1380 } else {
1381 Crot <<= 1;
1383 Crot += c;
1384 isc_buffer_availableregion(target, &tr);
1385 if (tr.length < 1)
1386 return (ISC_R_NOSPACE);
1387 tr.base[0] = c;
1388 isc_buffer_add(target, 1);
1389 return (ISC_R_SUCCESS);
1393 * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
1394 * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
1395 * outbuflen must be divisible by 4. (Note: this is because outbuf is filled
1396 * in 4 bytes at a time. If the actual data doesn't end on an even 4-byte
1397 * boundary, there will be no problem...it will be padded with 0 bytes, and
1398 * numbytes will indicate the correct number of bytes. The main point is
1399 * that since the buffer is filled in 4 bytes at a time, even if there is
1400 * not a full 4 bytes of data at the end, there has to be room to 0-pad the
1401 * data, so the buffer must be of size divisible by 4). Place the number of
1402 * output bytes in numbytes, and return a failure/success status.
1405 static isc_result_t
1406 atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) {
1407 long oeor, osum, orot;
1408 struct state statebuf, *state= &statebuf;
1409 isc_token_t token;
1410 char c;
1411 char *e;
1413 Ceor = Csum = Crot = word = bcount = 0;
1415 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1416 ISC_FALSE));
1417 while (token.value.as_textregion.length != 0) {
1418 if ((c = token.value.as_textregion.base[0]) == 'x') {
1419 break;
1420 } else
1421 RETERR(byte_atob(c, target, state));
1422 isc_textregion_consume(&token.value.as_textregion, 1);
1426 * Number of bytes.
1428 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
1429 ISC_FALSE));
1430 if ((token.value.as_ulong % 4) != 0U)
1431 isc_buffer_subtract(target, 4 - (token.value.as_ulong % 4));
1434 * Checksum.
1436 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1437 ISC_FALSE));
1438 oeor = strtol(DNS_AS_STR(token), &e, 16);
1439 if (*e != 0)
1440 return (DNS_R_SYNTAX);
1443 * Checksum.
1445 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1446 ISC_FALSE));
1447 osum = strtol(DNS_AS_STR(token), &e, 16);
1448 if (*e != 0)
1449 return (DNS_R_SYNTAX);
1452 * Checksum.
1454 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
1455 ISC_FALSE));
1456 orot = strtol(DNS_AS_STR(token), &e, 16);
1457 if (*e != 0)
1458 return (DNS_R_SYNTAX);
1460 if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
1461 return(DNS_R_BADCKSUM);
1462 return (ISC_R_SUCCESS);
1466 * Encode binary byte c into ASCII representation and place into *bufp,
1467 * advancing bufp.
1469 static isc_result_t
1470 byte_btoa(int c, isc_buffer_t *target, struct state *state) {
1471 isc_region_t tr;
1473 isc_buffer_availableregion(target, &tr);
1474 Ceor ^= c;
1475 Csum += c;
1476 Csum += 1;
1477 if ((Crot & 0x80000000)) {
1478 Crot <<= 1;
1479 Crot += 1;
1480 } else {
1481 Crot <<= 1;
1483 Crot += c;
1485 word <<= 8;
1486 word |= c;
1487 if (bcount == 3) {
1488 if (word == 0) {
1489 if (tr.length < 1)
1490 return (ISC_R_NOSPACE);
1491 tr.base[0] = 'z';
1492 isc_buffer_add(target, 1);
1493 } else {
1494 register int tmp = 0;
1495 register isc_int32_t tmpword = word;
1497 if (tmpword < 0) {
1499 * Because some don't support u_long.
1501 tmp = 32;
1502 tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1504 if (tmpword < 0) {
1505 tmp = 64;
1506 tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
1508 if (tr.length < 5)
1509 return (ISC_R_NOSPACE);
1510 tr.base[0] = atob_digits[(tmpword /
1511 (isc_int32_t)(85 * 85 * 85 * 85))
1512 + tmp];
1513 tmpword %= (isc_int32_t)(85 * 85 * 85 * 85);
1514 tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
1515 tmpword %= (85 * 85 * 85);
1516 tr.base[2] = atob_digits[tmpword / (85 * 85)];
1517 tmpword %= (85 * 85);
1518 tr.base[3] = atob_digits[tmpword / 85];
1519 tmpword %= 85;
1520 tr.base[4] = atob_digits[tmpword];
1521 isc_buffer_add(target, 5);
1523 bcount = 0;
1524 } else {
1525 bcount += 1;
1527 return (ISC_R_SUCCESS);
1532 * Encode the binary data from inbuf, of length inbuflen, into a
1533 * target. Return success/failure status
1535 static isc_result_t
1536 btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
1537 int inc;
1538 struct state statebuf, *state = &statebuf;
1539 char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
1541 Ceor = Csum = Crot = word = bcount = 0;
1542 for (inc = 0; inc < inbuflen; inbuf++, inc++)
1543 RETERR(byte_btoa(*inbuf, target, state));
1545 while (bcount != 0)
1546 RETERR(byte_btoa(0, target, state));
1549 * Put byte count and checksum information at end of buffer,
1550 * delimited by 'x'
1552 snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
1553 return (str_totext(buf, target));
1557 static void
1558 default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt,
1559 ...)
1561 va_list ap;
1563 UNUSED(callbacks);
1565 va_start(ap, fmt);
1566 vfprintf(stderr, fmt, ap);
1567 va_end(ap);
1568 fprintf(stderr, "\n");
1571 static void
1572 fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) {
1573 if (isc_lex_isfile(lexer) && callbacks != NULL) {
1574 const char *name = isc_lex_getsourcename(lexer);
1575 if (name == NULL)
1576 name = "UNKNOWN";
1577 (*callbacks->warn)(callbacks,
1578 "%s:%lu: file does not end with newline",
1579 name, isc_lex_getsourceline(lexer));
1583 static void
1584 warn_badname(dns_name_t *name, isc_lex_t *lexer,
1585 dns_rdatacallbacks_t *callbacks)
1587 const char *file;
1588 unsigned long line;
1589 char namebuf[DNS_NAME_FORMATSIZE];
1591 if (lexer != NULL) {
1592 file = isc_lex_getsourcename(lexer);
1593 line = isc_lex_getsourceline(lexer);
1594 dns_name_format(name, namebuf, sizeof(namebuf));
1595 (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
1596 file, line, namebuf,
1597 dns_result_totext(DNS_R_BADNAME));
1601 static void
1602 fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
1603 dns_rdatacallbacks_t *callbacks, const char *name,
1604 unsigned long line, isc_token_t *token, isc_result_t result)
1606 if (name == NULL)
1607 name = "UNKNOWN";
1609 if (token != NULL) {
1610 switch (token->type) {
1611 case isc_tokentype_eol:
1612 (*callback)(callbacks, "%s: %s:%lu: near eol: %s",
1613 "dns_rdata_fromtext", name, line,
1614 dns_result_totext(result));
1615 break;
1616 case isc_tokentype_eof:
1617 (*callback)(callbacks, "%s: %s:%lu: near eof: %s",
1618 "dns_rdata_fromtext", name, line,
1619 dns_result_totext(result));
1620 break;
1621 case isc_tokentype_number:
1622 (*callback)(callbacks, "%s: %s:%lu: near %lu: %s",
1623 "dns_rdata_fromtext", name, line,
1624 token->value.as_ulong,
1625 dns_result_totext(result));
1626 break;
1627 case isc_tokentype_string:
1628 case isc_tokentype_qstring:
1629 (*callback)(callbacks, "%s: %s:%lu: near '%s': %s",
1630 "dns_rdata_fromtext", name, line,
1631 DNS_AS_STR(*token),
1632 dns_result_totext(result));
1633 break;
1634 default:
1635 (*callback)(callbacks, "%s: %s:%lu: %s",
1636 "dns_rdata_fromtext", name, line,
1637 dns_result_totext(result));
1638 break;
1640 } else {
1641 (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s",
1642 name, line, dns_result_totext(result));
1646 dns_rdatatype_t
1647 dns_rdata_covers(dns_rdata_t *rdata) {
1648 if (rdata->type == 46)
1649 return (covers_rrsig(rdata));
1650 return (covers_sig(rdata));
1653 isc_boolean_t
1654 dns_rdatatype_ismeta(dns_rdatatype_t type) {
1655 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0)
1656 return (ISC_TRUE);
1657 return (ISC_FALSE);
1660 isc_boolean_t
1661 dns_rdatatype_issingleton(dns_rdatatype_t type) {
1662 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON)
1663 != 0)
1664 return (ISC_TRUE);
1665 return (ISC_FALSE);
1668 isc_boolean_t
1669 dns_rdatatype_notquestion(dns_rdatatype_t type) {
1670 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION)
1671 != 0)
1672 return (ISC_TRUE);
1673 return (ISC_FALSE);
1676 isc_boolean_t
1677 dns_rdatatype_questiononly(dns_rdatatype_t type) {
1678 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY)
1679 != 0)
1680 return (ISC_TRUE);
1681 return (ISC_FALSE);
1684 isc_boolean_t
1685 dns_rdatatype_atparent(dns_rdatatype_t type) {
1686 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0)
1687 return (ISC_TRUE);
1688 return (ISC_FALSE);
1691 isc_boolean_t
1692 dns_rdataclass_ismeta(dns_rdataclass_t rdclass) {
1694 if (rdclass == dns_rdataclass_reserved0
1695 || rdclass == dns_rdataclass_none
1696 || rdclass == dns_rdataclass_any)
1697 return (ISC_TRUE);
1699 return (ISC_FALSE); /* Assume it is not a meta class. */
1702 isc_boolean_t
1703 dns_rdatatype_isdnssec(dns_rdatatype_t type) {
1704 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0)
1705 return (ISC_TRUE);
1706 return (ISC_FALSE);
1709 isc_boolean_t
1710 dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
1711 if ((dns_rdatatype_attributes(type)
1712 & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH))
1713 != 0)
1714 return (ISC_TRUE);
1715 return (ISC_FALSE);
1718 isc_boolean_t
1719 dns_rdatatype_isknown(dns_rdatatype_t type) {
1720 if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN)
1721 == 0)
1722 return (ISC_TRUE);
1723 return (ISC_FALSE);