2 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
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: message.c,v 1.222.18.16 2008/07/28 23:46:20 tbox Exp $ */
28 #include <isc/buffer.h>
30 #include <isc/print.h>
31 #include <isc/string.h> /* Required for HP/UX (and others?) */
34 #include <dns/dnssec.h>
35 #include <dns/keyvalues.h>
37 #include <dns/masterdump.h>
38 #include <dns/message.h>
39 #include <dns/opcode.h>
40 #include <dns/rdata.h>
41 #include <dns/rdatalist.h>
42 #include <dns/rdataset.h>
43 #include <dns/rdatastruct.h>
44 #include <dns/result.h>
48 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
49 #define DNS_MESSAGE_OPCODE_SHIFT 11
50 #define DNS_MESSAGE_RCODE_MASK 0x000fU
51 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
52 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
53 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
54 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
55 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
57 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
58 && ((s) < DNS_SECTION_MAX))
59 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
60 && ((s) < DNS_SECTION_MAX))
61 #define ADD_STRING(b, s) {if (strlen(s) >= \
62 isc_buffer_availablelength(b)) \
63 return(ISC_R_NOSPACE); else \
64 isc_buffer_putstr(b, s);}
65 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
66 && ((s) < DNS_PSEUDOSECTION_MAX))
69 * This is the size of each individual scratchpad buffer, and the numbers
70 * of various block allocations used within the server.
71 * XXXMLG These should come from a config setting.
73 #define SCRATCHPAD_SIZE 512
75 #define OFFSET_COUNT 4
77 #define RDATALIST_COUNT 8
78 #define RDATASET_COUNT RDATALIST_COUNT
81 * Text representation of the different items, for message_totext
84 static const char *sectiontext[] = {
91 static const char *updsectiontext[] = {
98 static const char *opcodetext[] = {
117 static const char *rcodetext[] = {
139 * "helper" type, which consists of a block of some type, and is linkable.
140 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
141 * size, or the allocated elements will not be alligned correctly.
143 struct dns_msgblock {
145 unsigned int remaining;
146 ISC_LINK(dns_msgblock_t) link;
147 }; /* dynamically sized */
149 static inline dns_msgblock_t *
150 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
152 #define msgblock_get(block, type) \
153 ((type *)msgblock_internalget(block, sizeof(type)))
156 msgblock_internalget(dns_msgblock_t *, unsigned int);
159 msgblock_reset(dns_msgblock_t *);
162 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
165 * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
166 * is free, return NULL.
168 static inline dns_msgblock_t *
169 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
172 dns_msgblock_t *block;
175 length = sizeof(dns_msgblock_t) + (sizeof_type * count);
177 block = isc_mem_get(mctx, length);
181 block->count = count;
182 block->remaining = count;
184 ISC_LINK_INIT(block, link);
190 * Return an element from the msgblock. If no more are available, return
194 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
197 if (block == NULL || block->remaining == 0)
202 ptr = (((unsigned char *)block)
203 + sizeof(dns_msgblock_t)
204 + (sizeof_type * block->remaining));
210 msgblock_reset(dns_msgblock_t *block) {
211 block->remaining = block->count;
215 * Release memory associated with a message block.
218 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
222 length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
224 isc_mem_put(mctx, block, length);
228 * Allocate a new dynamic buffer, and attach it to this message as the
229 * "current" buffer. (which is always the last on the list, for our
232 static inline isc_result_t
233 newbuffer(dns_message_t *msg, unsigned int size) {
235 isc_buffer_t *dynbuf;
238 result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
239 if (result != ISC_R_SUCCESS)
240 return (ISC_R_NOMEMORY);
242 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
243 return (ISC_R_SUCCESS);
246 static inline isc_buffer_t *
247 currentbuffer(dns_message_t *msg) {
248 isc_buffer_t *dynbuf;
250 dynbuf = ISC_LIST_TAIL(msg->scratchpad);
251 INSIST(dynbuf != NULL);
257 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
258 ISC_LIST_PREPEND(msg->freerdata, rdata, link);
261 static inline dns_rdata_t *
262 newrdata(dns_message_t *msg) {
263 dns_msgblock_t *msgblock;
266 rdata = ISC_LIST_HEAD(msg->freerdata);
268 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
272 msgblock = ISC_LIST_TAIL(msg->rdatas);
273 rdata = msgblock_get(msgblock, dns_rdata_t);
275 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
277 if (msgblock == NULL)
280 ISC_LIST_APPEND(msg->rdatas, msgblock, link);
282 rdata = msgblock_get(msgblock, dns_rdata_t);
285 dns_rdata_init(rdata);
290 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
291 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
294 static inline dns_rdatalist_t *
295 newrdatalist(dns_message_t *msg) {
296 dns_msgblock_t *msgblock;
297 dns_rdatalist_t *rdatalist;
299 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
300 if (rdatalist != NULL) {
301 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
305 msgblock = ISC_LIST_TAIL(msg->rdatalists);
306 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
307 if (rdatalist == NULL) {
308 msgblock = msgblock_allocate(msg->mctx,
309 sizeof(dns_rdatalist_t),
311 if (msgblock == NULL)
314 ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
316 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
322 static inline dns_offsets_t *
323 newoffsets(dns_message_t *msg) {
324 dns_msgblock_t *msgblock;
325 dns_offsets_t *offsets;
327 msgblock = ISC_LIST_TAIL(msg->offsets);
328 offsets = msgblock_get(msgblock, dns_offsets_t);
329 if (offsets == NULL) {
330 msgblock = msgblock_allocate(msg->mctx,
331 sizeof(dns_offsets_t),
333 if (msgblock == NULL)
336 ISC_LIST_APPEND(msg->offsets, msgblock, link);
338 offsets = msgblock_get(msgblock, dns_offsets_t);
345 msginitheader(dns_message_t *m) {
354 msginitprivate(dns_message_t *m) {
357 for (i = 0; i < DNS_SECTION_MAX; i++) {
358 m->cursors[i] = NULL;
366 m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
374 msginittsig(dns_message_t *m) {
375 m->tsigstatus = dns_rcode_noerror;
376 m->querytsigstatus = dns_rcode_noerror;
381 m->sig0status = dns_rcode_noerror;
386 * Init elements to default state. Used both when allocating a new element
387 * and when resetting one.
390 msginit(dns_message_t *m) {
396 m->tcp_continuation = 0;
398 m->verify_attempted = 0;
401 m->query.base = NULL;
404 m->saved.base = NULL;
411 msgresetnames(dns_message_t *msg, unsigned int first_section) {
413 dns_name_t *name, *next_name;
414 dns_rdataset_t *rds, *next_rds;
417 * Clean up name lists by calling the rdataset disassociate function.
419 for (i = first_section; i < DNS_SECTION_MAX; i++) {
420 name = ISC_LIST_HEAD(msg->sections[i]);
421 while (name != NULL) {
422 next_name = ISC_LIST_NEXT(name, link);
423 ISC_LIST_UNLINK(msg->sections[i], name, link);
425 rds = ISC_LIST_HEAD(name->list);
426 while (rds != NULL) {
427 next_rds = ISC_LIST_NEXT(rds, link);
428 ISC_LIST_UNLINK(name->list, rds, link);
430 INSIST(dns_rdataset_isassociated(rds));
431 dns_rdataset_disassociate(rds);
432 isc_mempool_put(msg->rdspool, rds);
435 if (dns_name_dynamic(name))
436 dns_name_free(name, msg->mctx);
437 isc_mempool_put(msg->namepool, name);
444 msgresetopt(dns_message_t *msg)
446 if (msg->opt != NULL) {
447 if (msg->opt_reserved > 0) {
448 dns_message_renderrelease(msg, msg->opt_reserved);
449 msg->opt_reserved = 0;
451 INSIST(dns_rdataset_isassociated(msg->opt));
452 dns_rdataset_disassociate(msg->opt);
453 isc_mempool_put(msg->rdspool, msg->opt);
459 msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
460 if (msg->sig_reserved > 0) {
461 dns_message_renderrelease(msg, msg->sig_reserved);
462 msg->sig_reserved = 0;
464 if (msg->tsig != NULL) {
465 INSIST(dns_rdataset_isassociated(msg->tsig));
466 INSIST(msg->namepool != NULL);
468 INSIST(msg->querytsig == NULL);
469 msg->querytsig = msg->tsig;
471 dns_rdataset_disassociate(msg->tsig);
472 isc_mempool_put(msg->rdspool, msg->tsig);
473 if (msg->querytsig != NULL) {
474 dns_rdataset_disassociate(msg->querytsig);
475 isc_mempool_put(msg->rdspool, msg->querytsig);
478 if (dns_name_dynamic(msg->tsigname))
479 dns_name_free(msg->tsigname, msg->mctx);
480 isc_mempool_put(msg->namepool, msg->tsigname);
482 msg->tsigname = NULL;
483 } else if (msg->querytsig != NULL && !replying) {
484 dns_rdataset_disassociate(msg->querytsig);
485 isc_mempool_put(msg->rdspool, msg->querytsig);
486 msg->querytsig = NULL;
488 if (msg->sig0 != NULL) {
489 INSIST(dns_rdataset_isassociated(msg->sig0));
490 dns_rdataset_disassociate(msg->sig0);
491 isc_mempool_put(msg->rdspool, msg->sig0);
492 if (msg->sig0name != NULL) {
493 if (dns_name_dynamic(msg->sig0name))
494 dns_name_free(msg->sig0name, msg->mctx);
495 isc_mempool_put(msg->namepool, msg->sig0name);
498 msg->sig0name = NULL;
503 * Free all but one (or everything) for this message. This is used by
504 * both dns_message_reset() and dns_message_destroy().
507 msgreset(dns_message_t *msg, isc_boolean_t everything) {
508 dns_msgblock_t *msgblock, *next_msgblock;
509 isc_buffer_t *dynbuf, *next_dynbuf;
511 dns_rdatalist_t *rdatalist;
513 msgresetnames(msg, 0);
515 msgresetsigs(msg, ISC_FALSE);
518 * Clean up linked lists.
522 * Run through the free lists, and just unlink anything found there.
523 * The memory isn't lost since these are part of message blocks we
526 rdata = ISC_LIST_HEAD(msg->freerdata);
527 while (rdata != NULL) {
528 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
529 rdata = ISC_LIST_HEAD(msg->freerdata);
531 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
532 while (rdatalist != NULL) {
533 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
534 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
537 dynbuf = ISC_LIST_HEAD(msg->scratchpad);
538 INSIST(dynbuf != NULL);
540 isc_buffer_clear(dynbuf);
541 dynbuf = ISC_LIST_NEXT(dynbuf, link);
543 while (dynbuf != NULL) {
544 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
545 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
546 isc_buffer_free(&dynbuf);
547 dynbuf = next_dynbuf;
550 msgblock = ISC_LIST_HEAD(msg->rdatas);
551 if (!everything && msgblock != NULL) {
552 msgblock_reset(msgblock);
553 msgblock = ISC_LIST_NEXT(msgblock, link);
555 while (msgblock != NULL) {
556 next_msgblock = ISC_LIST_NEXT(msgblock, link);
557 ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
558 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
559 msgblock = next_msgblock;
563 * rdatalists could be empty.
566 msgblock = ISC_LIST_HEAD(msg->rdatalists);
567 if (!everything && msgblock != NULL) {
568 msgblock_reset(msgblock);
569 msgblock = ISC_LIST_NEXT(msgblock, link);
571 while (msgblock != NULL) {
572 next_msgblock = ISC_LIST_NEXT(msgblock, link);
573 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
574 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
575 msgblock = next_msgblock;
578 msgblock = ISC_LIST_HEAD(msg->offsets);
579 if (!everything && msgblock != NULL) {
580 msgblock_reset(msgblock);
581 msgblock = ISC_LIST_NEXT(msgblock, link);
583 while (msgblock != NULL) {
584 next_msgblock = ISC_LIST_NEXT(msgblock, link);
585 ISC_LIST_UNLINK(msg->offsets, msgblock, link);
586 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
587 msgblock = next_msgblock;
590 if (msg->tsigkey != NULL) {
591 dns_tsigkey_detach(&msg->tsigkey);
595 if (msg->tsigctx != NULL)
596 dst_context_destroy(&msg->tsigctx);
598 if (msg->query.base != NULL) {
599 if (msg->free_query != 0)
600 isc_mem_put(msg->mctx, msg->query.base,
602 msg->query.base = NULL;
603 msg->query.length = 0;
606 if (msg->saved.base != NULL) {
607 if (msg->free_saved != 0)
608 isc_mem_put(msg->mctx, msg->saved.base,
610 msg->saved.base = NULL;
611 msg->saved.length = 0;
615 * cleanup the buffer cleanup list
617 dynbuf = ISC_LIST_HEAD(msg->cleanup);
618 while (dynbuf != NULL) {
619 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
620 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
621 isc_buffer_free(&dynbuf);
622 dynbuf = next_dynbuf;
626 * Set other bits to normal default values.
631 ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
632 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
636 spacefortsig(dns_tsigkey_t *key, int otherlen) {
642 * The space required for an TSIG record is:
644 * n1 bytes for the name
645 * 2 bytes for the type
646 * 2 bytes for the class
647 * 4 bytes for the ttl
648 * 2 bytes for the rdlength
649 * n2 bytes for the algorithm name
650 * 6 bytes for the time signed
651 * 2 bytes for the fudge
652 * 2 bytes for the MAC size
653 * x bytes for the MAC
654 * 2 bytes for the original id
655 * 2 bytes for the error
656 * 2 bytes for the other data length
657 * y bytes for the other data (at most)
658 * ---------------------------------
659 * 26 + n1 + n2 + x + y bytes
662 dns_name_toregion(&key->name, &r1);
663 dns_name_toregion(key->algorithm, &r2);
664 if (key->key == NULL)
667 result = dst_key_sigsize(key->key, &x);
668 if (result != ISC_R_SUCCESS)
671 return (26 + r1.length + r2.length + x + otherlen);
675 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
679 isc_buffer_t *dynbuf;
682 REQUIRE(mctx != NULL);
683 REQUIRE(msgp != NULL);
684 REQUIRE(*msgp == NULL);
685 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
686 || intent == DNS_MESSAGE_INTENTRENDER);
688 m = isc_mem_get(mctx, sizeof(dns_message_t));
690 return (ISC_R_NOMEMORY);
693 * No allocations until further notice. Just initialize all lists
694 * and other members that are freed in the cleanup phase here.
697 m->magic = DNS_MESSAGE_MAGIC;
698 m->from_to_wire = intent;
701 for (i = 0; i < DNS_SECTION_MAX; i++)
702 ISC_LIST_INIT(m->sections[i]);
705 ISC_LIST_INIT(m->scratchpad);
706 ISC_LIST_INIT(m->cleanup);
709 ISC_LIST_INIT(m->rdatas);
710 ISC_LIST_INIT(m->rdatalists);
711 ISC_LIST_INIT(m->offsets);
712 ISC_LIST_INIT(m->freerdata);
713 ISC_LIST_INIT(m->freerdatalist);
716 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
719 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
720 if (result != ISC_R_SUCCESS)
722 isc_mempool_setfreemax(m->namepool, NAME_COUNT);
723 isc_mempool_setname(m->namepool, "msg:names");
725 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
727 if (result != ISC_R_SUCCESS)
729 isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
730 isc_mempool_setname(m->rdspool, "msg:rdataset");
733 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
734 if (result != ISC_R_SUCCESS)
736 ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
741 return (ISC_R_SUCCESS);
744 * Cleanup for error returns.
747 dynbuf = ISC_LIST_HEAD(m->scratchpad);
748 if (dynbuf != NULL) {
749 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
750 isc_buffer_free(&dynbuf);
752 if (m->namepool != NULL)
753 isc_mempool_destroy(&m->namepool);
754 if (m->rdspool != NULL)
755 isc_mempool_destroy(&m->rdspool);
757 isc_mem_put(mctx, m, sizeof(dns_message_t));
759 return (ISC_R_NOMEMORY);
763 dns_message_reset(dns_message_t *msg, unsigned int intent) {
764 REQUIRE(DNS_MESSAGE_VALID(msg));
765 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
766 || intent == DNS_MESSAGE_INTENTRENDER);
768 msgreset(msg, ISC_FALSE);
769 msg->from_to_wire = intent;
773 dns_message_destroy(dns_message_t **msgp) {
776 REQUIRE(msgp != NULL);
777 REQUIRE(DNS_MESSAGE_VALID(*msgp));
782 msgreset(msg, ISC_TRUE);
783 isc_mempool_destroy(&msg->namepool);
784 isc_mempool_destroy(&msg->rdspool);
786 isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
790 findname(dns_name_t **foundname, dns_name_t *target,
791 dns_namelist_t *section)
795 for (curr = ISC_LIST_TAIL(*section);
797 curr = ISC_LIST_PREV(curr, link)) {
798 if (dns_name_equal(curr, target)) {
799 if (foundname != NULL)
801 return (ISC_R_SUCCESS);
805 return (ISC_R_NOTFOUND);
809 dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
810 dns_rdatatype_t type, dns_rdatatype_t covers,
811 dns_rdataset_t **rdataset)
813 dns_rdataset_t *curr;
815 if (rdataset != NULL) {
816 REQUIRE(*rdataset == NULL);
819 for (curr = ISC_LIST_TAIL(name->list);
821 curr = ISC_LIST_PREV(curr, link)) {
822 if (curr->rdclass == rdclass &&
823 curr->type == type && curr->covers == covers) {
824 if (rdataset != NULL)
826 return (ISC_R_SUCCESS);
830 return (ISC_R_NOTFOUND);
834 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
835 dns_rdatatype_t covers, dns_rdataset_t **rdataset)
837 dns_rdataset_t *curr;
839 REQUIRE(name != NULL);
840 if (rdataset != NULL) {
841 REQUIRE(*rdataset == NULL);
844 for (curr = ISC_LIST_TAIL(name->list);
846 curr = ISC_LIST_PREV(curr, link)) {
847 if (curr->type == type && curr->covers == covers) {
848 if (rdataset != NULL)
850 return (ISC_R_SUCCESS);
854 return (ISC_R_NOTFOUND);
858 * Read a name from buffer "source".
861 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
862 dns_decompress_t *dctx)
864 isc_buffer_t *scratch;
868 scratch = currentbuffer(msg);
871 * First try: use current buffer.
872 * Second try: allocate a new buffer and use that.
876 result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
879 if (result == ISC_R_NOSPACE) {
882 result = newbuffer(msg, SCRATCHPAD_SIZE);
883 if (result != ISC_R_SUCCESS)
886 scratch = currentbuffer(msg);
887 dns_name_reset(name);
893 INSIST(0); /* Cannot get here... */
894 return (ISC_R_UNEXPECTED);
898 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
899 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
900 unsigned int rdatalen, dns_rdata_t *rdata)
902 isc_buffer_t *scratch;
905 unsigned int trysize;
907 scratch = currentbuffer(msg);
909 isc_buffer_setactive(source, rdatalen);
912 * First try: use current buffer.
913 * Second try: allocate a new buffer of size
914 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
915 * (the data will fit if it was not more than 50% compressed)
916 * Subsequent tries: double buffer size on each try.
920 /* XXX possibly change this to a while (tries < 2) loop */
922 result = dns_rdata_fromwire(rdata, rdclass, rdtype,
926 if (result == ISC_R_NOSPACE) {
928 trysize = 2 * rdatalen;
929 if (trysize < SCRATCHPAD_SIZE)
930 trysize = SCRATCHPAD_SIZE;
932 INSIST(trysize != 0);
933 if (trysize >= 65535)
934 return (ISC_R_NOSPACE);
935 /* XXX DNS_R_RRTOOLONG? */
939 result = newbuffer(msg, trysize);
940 if (result != ISC_R_SUCCESS)
943 scratch = currentbuffer(msg);
953 seen_problem = ISC_TRUE; \
955 result = DNS_R_FORMERR; \
961 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
962 unsigned int options)
968 dns_offsets_t *offsets;
969 dns_rdataset_t *rdataset;
970 dns_rdatalist_t *rdatalist;
972 dns_rdatatype_t rdtype;
973 dns_rdataclass_t rdclass;
974 dns_namelist_t *section;
975 isc_boolean_t free_name;
976 isc_boolean_t best_effort;
977 isc_boolean_t seen_problem;
979 section = &msg->sections[DNS_SECTION_QUESTION];
981 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
982 seen_problem = ISC_FALSE;
988 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
989 name = isc_mempool_get(msg->namepool);
991 return (ISC_R_NOMEMORY);
992 free_name = ISC_TRUE;
994 offsets = newoffsets(msg);
995 if (offsets == NULL) {
996 result = ISC_R_NOMEMORY;
999 dns_name_init(name, *offsets);
1002 * Parse the name out of this packet.
1004 isc_buffer_remainingregion(source, &r);
1005 isc_buffer_setactive(source, r.length);
1006 result = getname(name, source, msg, dctx);
1007 if (result != ISC_R_SUCCESS)
1011 * Run through the section, looking to see if this name
1012 * is already there. If it is found, put back the allocated
1013 * name since we no longer need it, and set our name pointer
1014 * to point to the name we found.
1016 result = findname(&name2, name, section);
1019 * If it is the first name in the section, accept it.
1021 * If it is not, but is not the same as the name already
1022 * in the question section, append to the section. Note that
1023 * here in the question section this is illegal, so return
1024 * FORMERR. In the future, check the opcode to see if
1025 * this should be legal or not. In either case we no longer
1026 * need this name pointer.
1028 if (result != ISC_R_SUCCESS) {
1029 if (!ISC_LIST_EMPTY(*section))
1031 ISC_LIST_APPEND(*section, name, link);
1032 free_name = ISC_FALSE;
1034 isc_mempool_put(msg->namepool, name);
1037 free_name = ISC_FALSE;
1041 * Get type and class.
1043 isc_buffer_remainingregion(source, &r);
1045 result = ISC_R_UNEXPECTEDEND;
1048 rdtype = isc_buffer_getuint16(source);
1049 rdclass = isc_buffer_getuint16(source);
1052 * If this class is different than the one we already read,
1055 if (msg->state == DNS_SECTION_ANY) {
1056 msg->state = DNS_SECTION_QUESTION;
1057 msg->rdclass = rdclass;
1058 } else if (msg->rdclass != rdclass)
1062 * Can't ask the same question twice.
1064 result = dns_message_find(name, rdclass, rdtype, 0, NULL);
1065 if (result == ISC_R_SUCCESS)
1069 * Allocate a new rdatalist.
1071 rdatalist = newrdatalist(msg);
1072 if (rdatalist == NULL) {
1073 result = ISC_R_NOMEMORY;
1076 rdataset = isc_mempool_get(msg->rdspool);
1077 if (rdataset == NULL) {
1078 result = ISC_R_NOMEMORY;
1083 * Convert rdatalist to rdataset, and attach the latter to
1086 rdatalist->type = rdtype;
1087 rdatalist->covers = 0;
1088 rdatalist->rdclass = rdclass;
1090 ISC_LIST_INIT(rdatalist->rdata);
1092 dns_rdataset_init(rdataset);
1093 result = dns_rdatalist_tordataset(rdatalist, rdataset);
1094 if (result != ISC_R_SUCCESS)
1097 rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
1099 ISC_LIST_APPEND(name->list, rdataset, link);
1104 return (DNS_R_RECOVERABLE);
1105 return (ISC_R_SUCCESS);
1108 if (rdataset != NULL) {
1109 INSIST(!dns_rdataset_isassociated(rdataset));
1110 isc_mempool_put(msg->rdspool, rdataset);
1113 if (rdatalist != NULL)
1114 isc_mempool_put(msg->rdlpool, rdatalist);
1117 isc_mempool_put(msg->namepool, name);
1122 static isc_boolean_t
1123 update(dns_section_t section, dns_rdataclass_t rdclass) {
1124 if (section == DNS_SECTION_PREREQUISITE)
1125 return (ISC_TF(rdclass == dns_rdataclass_any ||
1126 rdclass == dns_rdataclass_none));
1127 if (section == DNS_SECTION_UPDATE)
1128 return (ISC_TF(rdclass == dns_rdataclass_any));
1133 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
1134 dns_section_t sectionid, unsigned int options)
1137 unsigned int count, rdatalen;
1140 dns_offsets_t *offsets;
1141 dns_rdataset_t *rdataset;
1142 dns_rdatalist_t *rdatalist;
1143 isc_result_t result;
1144 dns_rdatatype_t rdtype, covers;
1145 dns_rdataclass_t rdclass;
1148 dns_namelist_t *section;
1149 isc_boolean_t free_name, free_rdataset;
1150 isc_boolean_t preserve_order, best_effort, seen_problem;
1151 isc_boolean_t issigzero;
1153 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
1154 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1155 seen_problem = ISC_FALSE;
1157 for (count = 0; count < msg->counts[sectionid]; count++) {
1158 int recstart = source->current;
1159 isc_boolean_t skip_name_search, skip_type_search;
1161 section = &msg->sections[sectionid];
1163 skip_name_search = ISC_FALSE;
1164 skip_type_search = ISC_FALSE;
1165 free_name = ISC_FALSE;
1166 free_rdataset = ISC_FALSE;
1168 name = isc_mempool_get(msg->namepool);
1170 return (ISC_R_NOMEMORY);
1171 free_name = ISC_TRUE;
1173 offsets = newoffsets(msg);
1174 if (offsets == NULL) {
1175 result = ISC_R_NOMEMORY;
1178 dns_name_init(name, *offsets);
1181 * Parse the name out of this packet.
1183 isc_buffer_remainingregion(source, &r);
1184 isc_buffer_setactive(source, r.length);
1185 result = getname(name, source, msg, dctx);
1186 if (result != ISC_R_SUCCESS)
1190 * Get type, class, ttl, and rdatalen. Verify that at least
1191 * rdatalen bytes remain. (Some of this is deferred to
1194 isc_buffer_remainingregion(source, &r);
1195 if (r.length < 2 + 2 + 4 + 2) {
1196 result = ISC_R_UNEXPECTEDEND;
1199 rdtype = isc_buffer_getuint16(source);
1200 rdclass = isc_buffer_getuint16(source);
1203 * If there was no question section, we may not yet have
1204 * established a class. Do so now.
1206 if (msg->state == DNS_SECTION_ANY &&
1207 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
1208 rdtype != dns_rdatatype_tsig && /* class is ANY */
1209 rdtype != dns_rdatatype_tkey) { /* class is undefined */
1210 msg->rdclass = rdclass;
1211 msg->state = DNS_SECTION_QUESTION;
1215 * If this class is different than the one in the question
1218 if (msg->opcode != dns_opcode_update
1219 && rdtype != dns_rdatatype_tsig
1220 && rdtype != dns_rdatatype_opt
1221 && rdtype != dns_rdatatype_dnskey /* in a TKEY query */
1222 && rdtype != dns_rdatatype_sig /* SIG(0) */
1223 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
1224 && msg->rdclass != dns_rdataclass_any
1225 && msg->rdclass != rdclass)
1229 * Special type handling for TSIG, OPT, and TKEY.
1231 if (rdtype == dns_rdatatype_tsig) {
1233 * If it is a tsig, verify that it is in the
1234 * additional data section.
1236 if (sectionid != DNS_SECTION_ADDITIONAL ||
1237 rdclass != dns_rdataclass_any ||
1238 count != msg->counts[sectionid] - 1)
1240 msg->sigstart = recstart;
1241 skip_name_search = ISC_TRUE;
1242 skip_type_search = ISC_TRUE;
1243 } else if (rdtype == dns_rdatatype_opt) {
1245 * The name of an OPT record must be ".", it
1246 * must be in the additional data section, and
1247 * it must be the first OPT we've seen.
1249 if (!dns_name_equal(dns_rootname, name) ||
1252 skip_name_search = ISC_TRUE;
1253 skip_type_search = ISC_TRUE;
1254 } else if (rdtype == dns_rdatatype_tkey) {
1256 * A TKEY must be in the additional section if this
1257 * is a query, and the answer section if this is a
1258 * response. Unless it's a Win2000 client.
1260 * Its class is ignored.
1262 dns_section_t tkeysection;
1264 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
1265 tkeysection = DNS_SECTION_ADDITIONAL;
1267 tkeysection = DNS_SECTION_ANSWER;
1268 if (sectionid != tkeysection &&
1269 sectionid != DNS_SECTION_ANSWER)
1274 * ... now get ttl and rdatalen, and check buffer.
1276 ttl = isc_buffer_getuint32(source);
1277 rdatalen = isc_buffer_getuint16(source);
1278 r.length -= (2 + 2 + 4 + 2);
1279 if (r.length < rdatalen) {
1280 result = ISC_R_UNEXPECTEDEND;
1285 * Read the rdata from the wire format. Interpret the
1286 * rdata according to its actual class, even if it had a
1287 * DynDNS meta-class in the packet (unless this is a TSIG).
1288 * Then put the meta-class back into the finished rdata.
1290 rdata = newrdata(msg);
1291 if (rdata == NULL) {
1292 result = ISC_R_NOMEMORY;
1295 if (msg->opcode == dns_opcode_update &&
1296 update(sectionid, rdclass)) {
1297 if (rdatalen != 0) {
1298 result = DNS_R_FORMERR;
1302 * When the rdata is empty, the data pointer is
1303 * never dereferenced, but it must still be non-NULL.
1304 * Casting 1 rather than "" avoids warnings about
1305 * discarding the const attribute of a string,
1306 * for compilers that would warn about such things.
1308 rdata->data = (unsigned char *)1;
1310 rdata->rdclass = rdclass;
1311 rdata->type = rdtype;
1312 rdata->flags = DNS_RDATA_UPDATE;
1313 result = ISC_R_SUCCESS;
1314 } else if (rdclass == dns_rdataclass_none &&
1315 msg->opcode == dns_opcode_update &&
1316 sectionid == DNS_SECTION_UPDATE) {
1317 result = getrdata(source, msg, dctx, msg->rdclass,
1318 rdtype, rdatalen, rdata);
1320 result = getrdata(source, msg, dctx, rdclass,
1321 rdtype, rdatalen, rdata);
1322 if (result != ISC_R_SUCCESS)
1324 rdata->rdclass = rdclass;
1325 issigzero = ISC_FALSE;
1326 if (rdtype == dns_rdatatype_rrsig &&
1327 rdata->flags == 0) {
1328 covers = dns_rdata_covers(rdata);
1331 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ &&
1332 rdata->flags == 0) {
1333 covers = dns_rdata_covers(rdata);
1335 if (sectionid != DNS_SECTION_ADDITIONAL ||
1336 count != msg->counts[sectionid] - 1)
1338 msg->sigstart = recstart;
1339 skip_name_search = ISC_TRUE;
1340 skip_type_search = ISC_TRUE;
1341 issigzero = ISC_TRUE;
1347 * If we are doing a dynamic update or this is a meta-type,
1348 * don't bother searching for a name, just append this one
1349 * to the end of the message.
1351 if (preserve_order || msg->opcode == dns_opcode_update ||
1353 if (rdtype != dns_rdatatype_opt &&
1354 rdtype != dns_rdatatype_tsig &&
1357 ISC_LIST_APPEND(*section, name, link);
1358 free_name = ISC_FALSE;
1362 * Run through the section, looking to see if this name
1363 * is already there. If it is found, put back the
1364 * allocated name since we no longer need it, and set
1365 * our name pointer to point to the name we found.
1367 result = findname(&name2, name, section);
1370 * If it is a new name, append to the section.
1372 if (result == ISC_R_SUCCESS) {
1373 isc_mempool_put(msg->namepool, name);
1376 ISC_LIST_APPEND(*section, name, link);
1378 free_name = ISC_FALSE;
1382 * Search name for the particular type and class.
1383 * Skip this stage if in update mode or this is a meta-type.
1385 if (preserve_order || msg->opcode == dns_opcode_update ||
1387 result = ISC_R_NOTFOUND;
1390 * If this is a type that can only occur in
1391 * the question section, fail.
1393 if (dns_rdatatype_questiononly(rdtype))
1397 result = dns_message_find(name, rdclass, rdtype,
1402 * If we found an rdataset that matches, we need to
1403 * append this rdata to that set. If we did not, we need
1404 * to create a new rdatalist, store the important bits there,
1405 * convert it to an rdataset, and link the latter to the name.
1406 * Yuck. When appending, make certain that the type isn't
1407 * a singleton type, such as SOA or CNAME.
1409 * Note that this check will be bypassed when preserving order,
1410 * the opcode is an update, or the type search is skipped.
1412 if (result == ISC_R_SUCCESS) {
1413 if (dns_rdatatype_issingleton(rdtype))
1417 if (result == ISC_R_NOTFOUND) {
1418 rdataset = isc_mempool_get(msg->rdspool);
1419 if (rdataset == NULL) {
1420 result = ISC_R_NOMEMORY;
1423 free_rdataset = ISC_TRUE;
1425 rdatalist = newrdatalist(msg);
1426 if (rdatalist == NULL) {
1427 result = ISC_R_NOMEMORY;
1431 rdatalist->type = rdtype;
1432 rdatalist->covers = covers;
1433 rdatalist->rdclass = rdclass;
1434 rdatalist->ttl = ttl;
1435 ISC_LIST_INIT(rdatalist->rdata);
1437 dns_rdataset_init(rdataset);
1438 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist,
1442 if (rdtype != dns_rdatatype_opt &&
1443 rdtype != dns_rdatatype_tsig &&
1446 ISC_LIST_APPEND(name->list, rdataset, link);
1447 free_rdataset = ISC_FALSE;
1454 * Section 5.2 of RFC2181 says we should drop
1455 * nonauthoritative rrsets where the TTLs differ, but we
1456 * currently treat them the as if they were authoritative and
1459 if (ttl != rdataset->ttl) {
1460 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
1461 if (ttl < rdataset->ttl)
1462 rdataset->ttl = ttl;
1466 * XXXMLG Perform a totally ugly hack here to pull
1467 * the rdatalist out of the private field in the rdataset,
1468 * and append this rdata to the rdatalist's linked list
1471 rdatalist = (dns_rdatalist_t *)(rdataset->private1);
1473 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1476 * If this is an OPT record, remember it. Also, set
1477 * the extended rcode. Note that msg->opt will only be set
1478 * if best-effort parsing is enabled.
1480 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
1483 msg->opt = rdataset;
1485 free_rdataset = ISC_FALSE;
1486 ercode = (dns_rcode_t)
1487 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
1489 msg->rcode |= ercode;
1490 isc_mempool_put(msg->namepool, name);
1491 free_name = ISC_FALSE;
1495 * If this is an SIG(0) or TSIG record, remember it. Note
1496 * that msg->sig0 or msg->tsig will only be set if best-effort
1497 * parsing is enabled.
1499 if (issigzero && msg->sig0 == NULL) {
1500 msg->sig0 = rdataset;
1501 msg->sig0name = name;
1503 free_rdataset = ISC_FALSE;
1504 free_name = ISC_FALSE;
1505 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
1506 msg->tsig = rdataset;
1507 msg->tsigname = name;
1509 free_rdataset = ISC_FALSE;
1510 free_name = ISC_FALSE;
1515 isc_mempool_put(msg->namepool, name);
1517 isc_mempool_put(msg->rdspool, rdataset);
1518 free_name = free_rdataset = ISC_FALSE;
1520 INSIST(free_name == ISC_FALSE);
1521 INSIST(free_rdataset == ISC_FALSE);
1525 return (DNS_R_RECOVERABLE);
1526 return (ISC_R_SUCCESS);
1530 isc_mempool_put(msg->namepool, name);
1532 isc_mempool_put(msg->rdspool, rdataset);
1538 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
1539 unsigned int options)
1542 dns_decompress_t dctx;
1544 isc_uint16_t tmpflags;
1545 isc_buffer_t origsource;
1546 isc_boolean_t seen_problem;
1547 isc_boolean_t ignore_tc;
1549 REQUIRE(DNS_MESSAGE_VALID(msg));
1550 REQUIRE(source != NULL);
1551 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
1553 seen_problem = ISC_FALSE;
1554 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
1556 origsource = *source;
1559 msg->question_ok = 0;
1561 isc_buffer_remainingregion(source, &r);
1562 if (r.length < DNS_MESSAGE_HEADERLEN)
1563 return (ISC_R_UNEXPECTEDEND);
1565 msg->id = isc_buffer_getuint16(source);
1566 tmpflags = isc_buffer_getuint16(source);
1567 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
1568 >> DNS_MESSAGE_OPCODE_SHIFT);
1569 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
1570 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
1571 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
1572 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
1573 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
1574 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
1581 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
1583 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
1585 ret = getquestions(source, msg, &dctx, options);
1586 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1588 if (ret == DNS_R_RECOVERABLE) {
1589 seen_problem = ISC_TRUE;
1590 ret = ISC_R_SUCCESS;
1592 if (ret != ISC_R_SUCCESS)
1594 msg->question_ok = 1;
1596 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
1597 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1599 if (ret == DNS_R_RECOVERABLE) {
1600 seen_problem = ISC_TRUE;
1601 ret = ISC_R_SUCCESS;
1603 if (ret != ISC_R_SUCCESS)
1606 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
1607 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1609 if (ret == DNS_R_RECOVERABLE) {
1610 seen_problem = ISC_TRUE;
1611 ret = ISC_R_SUCCESS;
1613 if (ret != ISC_R_SUCCESS)
1616 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
1617 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1619 if (ret == DNS_R_RECOVERABLE) {
1620 seen_problem = ISC_TRUE;
1621 ret = ISC_R_SUCCESS;
1623 if (ret != ISC_R_SUCCESS)
1626 isc_buffer_remainingregion(source, &r);
1627 if (r.length != 0) {
1628 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1629 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
1630 "message has %u byte(s) of trailing garbage",
1635 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
1636 isc_buffer_usedregion(&origsource, &msg->saved);
1638 msg->saved.length = isc_buffer_usedlength(&origsource);
1639 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
1640 if (msg->saved.base == NULL)
1641 return (ISC_R_NOMEMORY);
1642 memcpy(msg->saved.base, isc_buffer_base(&origsource),
1644 msg->free_saved = 1;
1647 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1648 return (DNS_R_RECOVERABLE);
1649 if (seen_problem == ISC_TRUE)
1650 return (DNS_R_RECOVERABLE);
1651 return (ISC_R_SUCCESS);
1655 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
1656 isc_buffer_t *buffer)
1660 REQUIRE(DNS_MESSAGE_VALID(msg));
1661 REQUIRE(buffer != NULL);
1662 REQUIRE(msg->buffer == NULL);
1663 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
1668 * Erase the contents of this buffer.
1670 isc_buffer_clear(buffer);
1673 * Make certain there is enough for at least the header in this
1676 isc_buffer_availableregion(buffer, &r);
1677 if (r.length < DNS_MESSAGE_HEADERLEN)
1678 return (ISC_R_NOSPACE);
1680 if (r.length < msg->reserved)
1681 return (ISC_R_NOSPACE);
1684 * Reserve enough space for the header in this buffer.
1686 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
1688 msg->buffer = buffer;
1690 return (ISC_R_SUCCESS);
1694 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
1697 REQUIRE(DNS_MESSAGE_VALID(msg));
1698 REQUIRE(buffer != NULL);
1699 REQUIRE(msg->buffer != NULL);
1702 * Ensure that the new buffer is empty, and has enough space to
1703 * hold the current contents.
1705 isc_buffer_clear(buffer);
1707 isc_buffer_availableregion(buffer, &rn);
1708 isc_buffer_usedregion(msg->buffer, &r);
1709 REQUIRE(rn.length > r.length);
1712 * Copy the contents from the old to the new buffer.
1714 isc_buffer_add(buffer, r.length);
1715 memcpy(rn.base, r.base, r.length);
1717 msg->buffer = buffer;
1719 return (ISC_R_SUCCESS);
1723 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
1724 REQUIRE(DNS_MESSAGE_VALID(msg));
1725 REQUIRE(space <= msg->reserved);
1727 msg->reserved -= space;
1731 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
1734 REQUIRE(DNS_MESSAGE_VALID(msg));
1736 if (msg->buffer != NULL) {
1737 isc_buffer_availableregion(msg->buffer, &r);
1738 if (r.length < (space + msg->reserved))
1739 return (ISC_R_NOSPACE);
1742 msg->reserved += space;
1744 return (ISC_R_SUCCESS);
1747 static inline isc_boolean_t
1748 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
1752 * If we are not rendering class IN, this ordering is bogus.
1754 if (rds->rdclass != dns_rdataclass_in)
1757 switch (rds->type) {
1758 case dns_rdatatype_a:
1759 case dns_rdatatype_aaaa:
1760 if (preferred_glue == rds->type)
1765 case dns_rdatatype_rrsig:
1766 case dns_rdatatype_dnskey:
1773 if (pass_needed >= pass)
1780 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
1781 unsigned int options)
1783 dns_namelist_t *section;
1784 dns_name_t *name, *next_name;
1785 dns_rdataset_t *rdataset, *next_rdataset;
1786 unsigned int count, total;
1787 isc_result_t result;
1788 isc_buffer_t st; /* for rollbacks */
1790 isc_boolean_t partial = ISC_FALSE;
1791 unsigned int rd_options;
1792 dns_rdatatype_t preferred_glue = 0;
1794 REQUIRE(DNS_MESSAGE_VALID(msg));
1795 REQUIRE(msg->buffer != NULL);
1796 REQUIRE(VALID_NAMED_SECTION(sectionid));
1798 section = &msg->sections[sectionid];
1800 if ((sectionid == DNS_SECTION_ADDITIONAL)
1801 && (options & DNS_MESSAGERENDER_ORDERED) == 0) {
1802 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
1803 preferred_glue = dns_rdatatype_a;
1805 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
1806 preferred_glue = dns_rdatatype_aaaa;
1813 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0)
1816 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
1819 * Shrink the space in the buffer by the reserved amount.
1821 msg->buffer->length -= msg->reserved;
1824 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
1828 * Render required glue first. Set TC if it won't fit.
1830 name = ISC_LIST_HEAD(*section);
1832 rdataset = ISC_LIST_HEAD(name->list);
1833 if (rdataset != NULL &&
1834 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
1835 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
1836 const void *order_arg = msg->order_arg;
1837 st = *(msg->buffer);
1840 result = dns_rdataset_towirepartial(rdataset,
1850 result = dns_rdataset_towiresorted(rdataset,
1859 if (partial && result == ISC_R_NOSPACE) {
1860 msg->flags |= DNS_MESSAGEFLAG_TC;
1861 msg->buffer->length += msg->reserved;
1862 msg->counts[sectionid] += total;
1865 if (result != ISC_R_SUCCESS) {
1866 INSIST(st.used < 65536);
1867 dns_compress_rollback(msg->cctx,
1868 (isc_uint16_t)st.used);
1869 *(msg->buffer) = st; /* rollback */
1870 msg->buffer->length += msg->reserved;
1871 msg->counts[sectionid] += total;
1874 rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
1879 name = ISC_LIST_HEAD(*section);
1881 msg->buffer->length += msg->reserved;
1882 msg->counts[sectionid] += total;
1883 return (ISC_R_SUCCESS);
1886 while (name != NULL) {
1887 next_name = ISC_LIST_NEXT(name, link);
1889 rdataset = ISC_LIST_HEAD(name->list);
1890 while (rdataset != NULL) {
1891 next_rdataset = ISC_LIST_NEXT(rdataset, link);
1893 if ((rdataset->attributes &
1894 DNS_RDATASETATTR_RENDERED) != 0)
1897 if (((options & DNS_MESSAGERENDER_ORDERED)
1899 && (sectionid == DNS_SECTION_ADDITIONAL)
1900 && wrong_priority(rdataset, pass,
1904 st = *(msg->buffer);
1908 result = dns_rdataset_towirepartial(
1919 result = dns_rdataset_towiresorted(
1932 * If out of space, record stats on what we
1933 * rendered so far, and return that status.
1935 * XXXMLG Need to change this when
1936 * dns_rdataset_towire() can render partial
1937 * sets starting at some arbitary point in the
1938 * set. This will include setting a bit in the
1939 * rdataset to indicate that a partial
1940 * rendering was done, and some state saved
1941 * somewhere (probably in the message struct)
1942 * to indicate where to continue from.
1944 if (partial && result == ISC_R_NOSPACE) {
1945 msg->buffer->length += msg->reserved;
1946 msg->counts[sectionid] += total;
1949 if (result != ISC_R_SUCCESS) {
1950 INSIST(st.used < 65536);
1951 dns_compress_rollback(msg->cctx,
1952 (isc_uint16_t)st.used);
1953 *(msg->buffer) = st; /* rollback */
1954 msg->buffer->length += msg->reserved;
1955 msg->counts[sectionid] += total;
1960 * If we have rendered non-validated data,
1961 * ensure that the AD bit is not set.
1963 if (rdataset->trust != dns_trust_secure &&
1964 (sectionid == DNS_SECTION_ANSWER ||
1965 sectionid == DNS_SECTION_AUTHORITY))
1966 msg->flags &= ~DNS_MESSAGEFLAG_AD;
1968 rdataset->attributes |=
1969 DNS_RDATASETATTR_RENDERED;
1972 rdataset = next_rdataset;
1977 } while (--pass != 0);
1979 msg->buffer->length += msg->reserved;
1980 msg->counts[sectionid] += total;
1982 return (ISC_R_SUCCESS);
1986 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
1990 REQUIRE(DNS_MESSAGE_VALID(msg));
1991 REQUIRE(target != NULL);
1993 isc_buffer_availableregion(target, &r);
1994 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
1996 isc_buffer_putuint16(target, msg->id);
1998 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
1999 & DNS_MESSAGE_OPCODE_MASK);
2000 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
2001 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
2003 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
2004 msg->counts[DNS_SECTION_ANSWER] < 65536 &&
2005 msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
2006 msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
2008 isc_buffer_putuint16(target, tmp);
2009 isc_buffer_putuint16(target,
2010 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
2011 isc_buffer_putuint16(target,
2012 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
2013 isc_buffer_putuint16(target,
2014 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
2015 isc_buffer_putuint16(target,
2016 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
2020 dns_message_renderend(dns_message_t *msg) {
2021 isc_buffer_t tmpbuf;
2026 REQUIRE(DNS_MESSAGE_VALID(msg));
2027 REQUIRE(msg->buffer != NULL);
2029 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
2031 * We have an extended rcode but are not using EDNS.
2033 return (DNS_R_FORMERR);
2037 * If we've got an OPT record, render it.
2039 if (msg->opt != NULL) {
2040 dns_message_renderrelease(msg, msg->opt_reserved);
2041 msg->opt_reserved = 0;
2043 * Set the extended rcode.
2045 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
2046 msg->opt->ttl |= ((msg->rcode << 20) &
2047 DNS_MESSAGE_EDNSRCODE_MASK);
2052 result = dns_rdataset_towire(msg->opt, dns_rootname,
2053 msg->cctx, msg->buffer, 0,
2055 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2056 if (result != ISC_R_SUCCESS)
2061 * If we're adding a TSIG or SIG(0) to a truncated message,
2062 * clear all rdatasets from the message except for the question
2063 * before adding the TSIG or SIG(0). If the question doesn't fit,
2066 if ((msg->tsigkey != NULL || msg->sig0key != NULL) &&
2067 (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
2071 msgresetnames(msg, DNS_SECTION_ANSWER);
2073 dns_message_renderreset(msg);
2075 isc_buffer_clear(msg->buffer);
2076 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
2077 dns_compress_rollback(msg->cctx, 0);
2078 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
2080 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
2085 * If we're adding a TSIG record, generate and render it.
2087 if (msg->tsigkey != NULL) {
2088 dns_message_renderrelease(msg, msg->sig_reserved);
2089 msg->sig_reserved = 0;
2090 result = dns_tsig_sign(msg);
2091 if (result != ISC_R_SUCCESS)
2094 result = dns_rdataset_towire(msg->tsig, msg->tsigname,
2095 msg->cctx, msg->buffer, 0,
2097 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2098 if (result != ISC_R_SUCCESS)
2103 * If we're adding a SIG(0) record, generate and render it.
2105 if (msg->sig0key != NULL) {
2106 dns_message_renderrelease(msg, msg->sig_reserved);
2107 msg->sig_reserved = 0;
2108 result = dns_dnssec_signmessage(msg, msg->sig0key);
2109 if (result != ISC_R_SUCCESS)
2113 * Note: dns_rootname is used here, not msg->sig0name, since
2114 * the owner name of a SIG(0) is irrelevant, and will not
2115 * be set in a message being rendered.
2117 result = dns_rdataset_towire(msg->sig0, dns_rootname,
2118 msg->cctx, msg->buffer, 0,
2120 msg->counts[DNS_SECTION_ADDITIONAL] += count;
2121 if (result != ISC_R_SUCCESS)
2125 isc_buffer_usedregion(msg->buffer, &r);
2126 isc_buffer_init(&tmpbuf, r.base, r.length);
2128 dns_message_renderheader(msg, &tmpbuf);
2130 msg->buffer = NULL; /* forget about this buffer only on success XXX */
2132 return (ISC_R_SUCCESS);
2136 dns_message_renderreset(dns_message_t *msg) {
2139 dns_rdataset_t *rds;
2142 * Reset the message so that it may be rendered again.
2145 REQUIRE(DNS_MESSAGE_VALID(msg));
2146 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2150 for (i = 0; i < DNS_SECTION_MAX; i++) {
2151 msg->cursors[i] = NULL;
2153 for (name = ISC_LIST_HEAD(msg->sections[i]);
2155 name = ISC_LIST_NEXT(name, link)) {
2156 for (rds = ISC_LIST_HEAD(name->list);
2158 rds = ISC_LIST_NEXT(rds, link)) {
2159 rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
2163 if (msg->tsigname != NULL)
2164 dns_message_puttempname(msg, &msg->tsigname);
2165 if (msg->tsig != NULL) {
2166 dns_rdataset_disassociate(msg->tsig);
2167 dns_message_puttemprdataset(msg, &msg->tsig);
2169 if (msg->sig0 != NULL) {
2170 dns_rdataset_disassociate(msg->sig0);
2171 dns_message_puttemprdataset(msg, &msg->sig0);
2176 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
2177 REQUIRE(DNS_MESSAGE_VALID(msg));
2178 REQUIRE(VALID_NAMED_SECTION(section));
2180 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
2182 if (msg->cursors[section] == NULL)
2183 return (ISC_R_NOMORE);
2185 return (ISC_R_SUCCESS);
2189 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
2190 REQUIRE(DNS_MESSAGE_VALID(msg));
2191 REQUIRE(VALID_NAMED_SECTION(section));
2192 REQUIRE(msg->cursors[section] != NULL);
2194 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
2196 if (msg->cursors[section] == NULL)
2197 return (ISC_R_NOMORE);
2199 return (ISC_R_SUCCESS);
2203 dns_message_currentname(dns_message_t *msg, dns_section_t section,
2206 REQUIRE(DNS_MESSAGE_VALID(msg));
2207 REQUIRE(VALID_NAMED_SECTION(section));
2208 REQUIRE(name != NULL && *name == NULL);
2209 REQUIRE(msg->cursors[section] != NULL);
2211 *name = msg->cursors[section];
2215 dns_message_findname(dns_message_t *msg, dns_section_t section,
2216 dns_name_t *target, dns_rdatatype_t type,
2217 dns_rdatatype_t covers, dns_name_t **name,
2218 dns_rdataset_t **rdataset)
2220 dns_name_t *foundname;
2221 isc_result_t result;
2224 * XXX These requirements are probably too intensive, especially
2225 * where things can be NULL, but as they are they ensure that if
2226 * something is NON-NULL, indicating that the caller expects it
2227 * to be filled in, that we can in fact fill it in.
2229 REQUIRE(msg != NULL);
2230 REQUIRE(VALID_SECTION(section));
2231 REQUIRE(target != NULL);
2233 REQUIRE(*name == NULL);
2234 if (type == dns_rdatatype_any) {
2235 REQUIRE(rdataset == NULL);
2237 if (rdataset != NULL)
2238 REQUIRE(*rdataset == NULL);
2241 result = findname(&foundname, target,
2242 &msg->sections[section]);
2244 if (result == ISC_R_NOTFOUND)
2245 return (DNS_R_NXDOMAIN);
2246 else if (result != ISC_R_SUCCESS)
2253 * And now look for the type.
2255 if (type == dns_rdatatype_any)
2256 return (ISC_R_SUCCESS);
2258 result = dns_message_findtype(foundname, type, covers, rdataset);
2259 if (result == ISC_R_NOTFOUND)
2260 return (DNS_R_NXRRSET);
2266 dns_message_movename(dns_message_t *msg, dns_name_t *name,
2267 dns_section_t fromsection,
2268 dns_section_t tosection)
2270 REQUIRE(msg != NULL);
2271 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2272 REQUIRE(name != NULL);
2273 REQUIRE(VALID_NAMED_SECTION(fromsection));
2274 REQUIRE(VALID_NAMED_SECTION(tosection));
2277 * Unlink the name from the old section
2279 ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
2280 ISC_LIST_APPEND(msg->sections[tosection], name, link);
2284 dns_message_addname(dns_message_t *msg, dns_name_t *name,
2285 dns_section_t section)
2287 REQUIRE(msg != NULL);
2288 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2289 REQUIRE(name != NULL);
2290 REQUIRE(VALID_NAMED_SECTION(section));
2292 ISC_LIST_APPEND(msg->sections[section], name, link);
2296 dns_message_removename(dns_message_t *msg, dns_name_t *name,
2297 dns_section_t section)
2299 REQUIRE(msg != NULL);
2300 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2301 REQUIRE(name != NULL);
2302 REQUIRE(VALID_NAMED_SECTION(section));
2304 ISC_LIST_UNLINK(msg->sections[section], name, link);
2308 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
2309 REQUIRE(DNS_MESSAGE_VALID(msg));
2310 REQUIRE(item != NULL && *item == NULL);
2312 *item = isc_mempool_get(msg->namepool);
2314 return (ISC_R_NOMEMORY);
2315 dns_name_init(*item, NULL);
2317 return (ISC_R_SUCCESS);
2321 dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
2322 REQUIRE(DNS_MESSAGE_VALID(msg));
2323 REQUIRE(item != NULL && *item == NULL);
2325 *item = newoffsets(msg);
2327 return (ISC_R_NOMEMORY);
2329 return (ISC_R_SUCCESS);
2333 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
2334 REQUIRE(DNS_MESSAGE_VALID(msg));
2335 REQUIRE(item != NULL && *item == NULL);
2337 *item = newrdata(msg);
2339 return (ISC_R_NOMEMORY);
2341 return (ISC_R_SUCCESS);
2345 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2346 REQUIRE(DNS_MESSAGE_VALID(msg));
2347 REQUIRE(item != NULL && *item == NULL);
2349 *item = isc_mempool_get(msg->rdspool);
2351 return (ISC_R_NOMEMORY);
2353 dns_rdataset_init(*item);
2355 return (ISC_R_SUCCESS);
2359 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2360 REQUIRE(DNS_MESSAGE_VALID(msg));
2361 REQUIRE(item != NULL && *item == NULL);
2363 *item = newrdatalist(msg);
2365 return (ISC_R_NOMEMORY);
2367 return (ISC_R_SUCCESS);
2371 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
2372 REQUIRE(DNS_MESSAGE_VALID(msg));
2373 REQUIRE(item != NULL && *item != NULL);
2375 if (dns_name_dynamic(*item))
2376 dns_name_free(*item, msg->mctx);
2377 isc_mempool_put(msg->namepool, *item);
2382 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
2383 REQUIRE(DNS_MESSAGE_VALID(msg));
2384 REQUIRE(item != NULL && *item != NULL);
2386 releaserdata(msg, *item);
2391 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2392 REQUIRE(DNS_MESSAGE_VALID(msg));
2393 REQUIRE(item != NULL && *item != NULL);
2395 REQUIRE(!dns_rdataset_isassociated(*item));
2396 isc_mempool_put(msg->rdspool, *item);
2401 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2402 REQUIRE(DNS_MESSAGE_VALID(msg));
2403 REQUIRE(item != NULL && *item != NULL);
2405 releaserdatalist(msg, *item);
2410 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
2411 unsigned int *flagsp)
2414 isc_buffer_t buffer;
2418 REQUIRE(source != NULL);
2422 isc_buffer_remainingregion(&buffer, &r);
2423 if (r.length < DNS_MESSAGE_HEADERLEN)
2424 return (ISC_R_UNEXPECTEDEND);
2426 id = isc_buffer_getuint16(&buffer);
2427 flags = isc_buffer_getuint16(&buffer);
2428 flags &= DNS_MESSAGE_FLAG_MASK;
2435 return (ISC_R_SUCCESS);
2439 dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
2440 unsigned int first_section;
2441 isc_result_t result;
2443 REQUIRE(DNS_MESSAGE_VALID(msg));
2444 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
2446 if (!msg->header_ok)
2447 return (DNS_R_FORMERR);
2448 if (msg->opcode != dns_opcode_query &&
2449 msg->opcode != dns_opcode_notify)
2450 want_question_section = ISC_FALSE;
2451 if (want_question_section) {
2452 if (!msg->question_ok)
2453 return (DNS_R_FORMERR);
2454 first_section = DNS_SECTION_ANSWER;
2456 first_section = DNS_SECTION_QUESTION;
2457 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
2458 msgresetnames(msg, first_section);
2460 msgresetsigs(msg, ISC_TRUE);
2461 msginitprivate(msg);
2463 * We now clear most flags and then set QR, ensuring that the
2464 * reply's flags will be in a reasonable state.
2466 msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
2467 msg->flags |= DNS_MESSAGEFLAG_QR;
2470 * This saves the query TSIG status, if the query was signed, and
2471 * reserves space in the reply for the TSIG.
2473 if (msg->tsigkey != NULL) {
2474 unsigned int otherlen = 0;
2475 msg->querytsigstatus = msg->tsigstatus;
2476 msg->tsigstatus = dns_rcode_noerror;
2477 if (msg->querytsigstatus == dns_tsigerror_badtime)
2479 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
2480 result = dns_message_renderreserve(msg, msg->sig_reserved);
2481 if (result != ISC_R_SUCCESS) {
2482 msg->sig_reserved = 0;
2486 if (msg->saved.base != NULL) {
2487 msg->query.base = msg->saved.base;
2488 msg->query.length = msg->saved.length;
2489 msg->free_query = msg->free_saved;
2490 msg->saved.base = NULL;
2491 msg->saved.length = 0;
2492 msg->free_saved = 0;
2495 return (ISC_R_SUCCESS);
2499 dns_message_getopt(dns_message_t *msg) {
2502 * Get the OPT record for 'msg'.
2505 REQUIRE(DNS_MESSAGE_VALID(msg));
2511 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
2512 isc_result_t result;
2513 dns_rdata_t rdata = DNS_RDATA_INIT;
2516 * Set the OPT record for 'msg'.
2520 * The space required for an OPT record is:
2522 * 1 byte for the name
2523 * 2 bytes for the type
2524 * 2 bytes for the class
2525 * 4 bytes for the ttl
2526 * 2 bytes for the rdata length
2527 * ---------------------------------
2530 * plus the length of the rdata.
2533 REQUIRE(DNS_MESSAGE_VALID(msg));
2534 REQUIRE(opt->type == dns_rdatatype_opt);
2535 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2536 REQUIRE(msg->state == DNS_SECTION_ANY);
2540 result = dns_rdataset_first(opt);
2541 if (result != ISC_R_SUCCESS)
2543 dns_rdataset_current(opt, &rdata);
2544 msg->opt_reserved = 11 + rdata.length;
2545 result = dns_message_renderreserve(msg, msg->opt_reserved);
2546 if (result != ISC_R_SUCCESS) {
2547 msg->opt_reserved = 0;
2553 return (ISC_R_SUCCESS);
2556 dns_message_puttemprdataset(msg, &opt);
2562 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
2565 * Get the TSIG record and owner for 'msg'.
2568 REQUIRE(DNS_MESSAGE_VALID(msg));
2569 REQUIRE(owner == NULL || *owner == NULL);
2572 *owner = msg->tsigname;
2577 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
2578 isc_result_t result;
2581 * Set the TSIG key for 'msg'
2584 REQUIRE(DNS_MESSAGE_VALID(msg));
2585 REQUIRE(msg->state == DNS_SECTION_ANY);
2587 if (key == NULL && msg->tsigkey != NULL) {
2588 if (msg->sig_reserved != 0) {
2589 dns_message_renderrelease(msg, msg->sig_reserved);
2590 msg->sig_reserved = 0;
2592 dns_tsigkey_detach(&msg->tsigkey);
2595 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
2596 dns_tsigkey_attach(key, &msg->tsigkey);
2597 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
2598 msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
2599 result = dns_message_renderreserve(msg,
2601 if (result != ISC_R_SUCCESS) {
2602 dns_tsigkey_detach(&msg->tsigkey);
2603 msg->sig_reserved = 0;
2608 return (ISC_R_SUCCESS);
2612 dns_message_gettsigkey(dns_message_t *msg) {
2615 * Get the TSIG key for 'msg'
2618 REQUIRE(DNS_MESSAGE_VALID(msg));
2620 return (msg->tsigkey);
2624 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
2625 dns_rdata_t *rdata = NULL;
2626 dns_rdatalist_t *list = NULL;
2627 dns_rdataset_t *set = NULL;
2628 isc_buffer_t *buf = NULL;
2630 isc_result_t result;
2632 REQUIRE(DNS_MESSAGE_VALID(msg));
2633 REQUIRE(msg->querytsig == NULL);
2635 if (querytsig == NULL)
2636 return (ISC_R_SUCCESS);
2638 result = dns_message_gettemprdata(msg, &rdata);
2639 if (result != ISC_R_SUCCESS)
2642 result = dns_message_gettemprdatalist(msg, &list);
2643 if (result != ISC_R_SUCCESS)
2645 result = dns_message_gettemprdataset(msg, &set);
2646 if (result != ISC_R_SUCCESS)
2649 isc_buffer_usedregion(querytsig, &r);
2650 result = isc_buffer_allocate(msg->mctx, &buf, r.length);
2651 if (result != ISC_R_SUCCESS)
2653 isc_buffer_putmem(buf, r.base, r.length);
2654 isc_buffer_usedregion(buf, &r);
2655 dns_rdata_init(rdata);
2656 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
2657 dns_message_takebuffer(msg, &buf);
2658 ISC_LIST_INIT(list->rdata);
2659 ISC_LIST_APPEND(list->rdata, rdata, link);
2660 result = dns_rdatalist_tordataset(list, set);
2661 if (result != ISC_R_SUCCESS)
2664 msg->querytsig = set;
2670 dns_message_puttemprdata(msg, &rdata);
2672 dns_message_puttemprdatalist(msg, &list);
2674 dns_message_puttemprdataset(msg, &set);
2675 return (ISC_R_NOMEMORY);
2679 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
2680 isc_buffer_t **querytsig) {
2681 isc_result_t result;
2682 dns_rdata_t rdata = DNS_RDATA_INIT;
2685 REQUIRE(DNS_MESSAGE_VALID(msg));
2686 REQUIRE(mctx != NULL);
2687 REQUIRE(querytsig != NULL && *querytsig == NULL);
2689 if (msg->tsig == NULL)
2690 return (ISC_R_SUCCESS);
2692 result = dns_rdataset_first(msg->tsig);
2693 if (result != ISC_R_SUCCESS)
2695 dns_rdataset_current(msg->tsig, &rdata);
2696 dns_rdata_toregion(&rdata, &r);
2698 result = isc_buffer_allocate(mctx, querytsig, r.length);
2699 if (result != ISC_R_SUCCESS)
2701 isc_buffer_putmem(*querytsig, r.base, r.length);
2702 return (ISC_R_SUCCESS);
2706 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
2709 * Get the SIG(0) record for 'msg'.
2712 REQUIRE(DNS_MESSAGE_VALID(msg));
2713 REQUIRE(owner == NULL || *owner == NULL);
2715 if (msg->sig0 != NULL && owner != NULL) {
2716 /* If dns_message_getsig0 is called on a rendered message
2717 * after the SIG(0) has been applied, we need to return the
2718 * root name, not NULL.
2720 if (msg->sig0name == NULL)
2721 *owner = dns_rootname;
2723 *owner = msg->sig0name;
2729 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
2732 isc_result_t result;
2735 * Set the SIG(0) key for 'msg'
2739 * The space required for an SIG(0) record is:
2741 * 1 byte for the name
2742 * 2 bytes for the type
2743 * 2 bytes for the class
2744 * 4 bytes for the ttl
2745 * 2 bytes for the type covered
2746 * 1 byte for the algorithm
2747 * 1 bytes for the labels
2748 * 4 bytes for the original ttl
2749 * 4 bytes for the signature expiration
2750 * 4 bytes for the signature inception
2751 * 2 bytes for the key tag
2752 * n bytes for the signer's name
2753 * x bytes for the signature
2754 * ---------------------------------
2757 REQUIRE(DNS_MESSAGE_VALID(msg));
2758 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2759 REQUIRE(msg->state == DNS_SECTION_ANY);
2762 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
2763 dns_name_toregion(dst_key_name(key), &r);
2764 result = dst_key_sigsize(key, &x);
2765 if (result != ISC_R_SUCCESS) {
2766 msg->sig_reserved = 0;
2769 msg->sig_reserved = 27 + r.length + x;
2770 result = dns_message_renderreserve(msg, msg->sig_reserved);
2771 if (result != ISC_R_SUCCESS) {
2772 msg->sig_reserved = 0;
2777 return (ISC_R_SUCCESS);
2781 dns_message_getsig0key(dns_message_t *msg) {
2784 * Get the SIG(0) key for 'msg'
2787 REQUIRE(DNS_MESSAGE_VALID(msg));
2789 return (msg->sig0key);
2793 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
2794 REQUIRE(DNS_MESSAGE_VALID(msg));
2795 REQUIRE(buffer != NULL);
2796 REQUIRE(ISC_BUFFER_VALID(*buffer));
2798 ISC_LIST_APPEND(msg->cleanup, *buffer, link);
2803 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
2804 isc_result_t result = ISC_R_SUCCESS;
2805 dns_rdata_t rdata = DNS_RDATA_INIT;
2807 REQUIRE(DNS_MESSAGE_VALID(msg));
2808 REQUIRE(signer != NULL);
2809 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
2811 if (msg->tsig == NULL && msg->sig0 == NULL)
2812 return (ISC_R_NOTFOUND);
2814 if (msg->verify_attempted == 0)
2815 return (DNS_R_NOTVERIFIEDYET);
2817 if (!dns_name_hasbuffer(signer)) {
2818 isc_buffer_t *dynbuf = NULL;
2819 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
2820 if (result != ISC_R_SUCCESS)
2822 dns_name_setbuffer(signer, dynbuf);
2823 dns_message_takebuffer(msg, &dynbuf);
2826 if (msg->sig0 != NULL) {
2827 dns_rdata_sig_t sig;
2829 result = dns_rdataset_first(msg->sig0);
2830 INSIST(result == ISC_R_SUCCESS);
2831 dns_rdataset_current(msg->sig0, &rdata);
2833 result = dns_rdata_tostruct(&rdata, &sig, NULL);
2834 if (result != ISC_R_SUCCESS)
2837 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
2838 result = ISC_R_SUCCESS;
2840 result = DNS_R_SIGINVALID;
2841 dns_name_clone(&sig.signer, signer);
2842 dns_rdata_freestruct(&sig);
2844 dns_name_t *identity;
2845 dns_rdata_any_tsig_t tsig;
2847 result = dns_rdataset_first(msg->tsig);
2848 INSIST(result == ISC_R_SUCCESS);
2849 dns_rdataset_current(msg->tsig, &rdata);
2851 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2852 if (msg->tsigstatus != dns_rcode_noerror)
2853 result = DNS_R_TSIGVERIFYFAILURE;
2854 else if (tsig.error != dns_rcode_noerror)
2855 result = DNS_R_TSIGERRORSET;
2857 result = ISC_R_SUCCESS;
2858 dns_rdata_freestruct(&tsig);
2860 if (msg->tsigkey == NULL) {
2862 * If msg->tsigstatus & tsig.error are both
2863 * dns_rcode_noerror, the message must have been
2864 * verified, which means msg->tsigkey will be
2867 INSIST(result != ISC_R_SUCCESS);
2869 identity = dns_tsigkey_identity(msg->tsigkey);
2870 if (identity == NULL) {
2871 if (result == ISC_R_SUCCESS)
2872 result = DNS_R_NOIDENTITY;
2873 identity = &msg->tsigkey->name;
2875 dns_name_clone(identity, signer);
2883 dns_message_resetsig(dns_message_t *msg) {
2884 REQUIRE(DNS_MESSAGE_VALID(msg));
2885 msg->verified_sig = 0;
2886 msg->verify_attempted = 0;
2887 msg->tsigstatus = dns_rcode_noerror;
2888 msg->sig0status = dns_rcode_noerror;
2889 msg->timeadjust = 0;
2890 if (msg->tsigkey != NULL) {
2891 dns_tsigkey_detach(&msg->tsigkey);
2892 msg->tsigkey = NULL;
2897 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
2898 dns_message_resetsig(msg);
2899 return (dns_message_checksig(msg, view));
2903 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
2904 isc_buffer_t b, msgb;
2906 REQUIRE(DNS_MESSAGE_VALID(msg));
2908 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
2909 return (ISC_R_SUCCESS);
2910 INSIST(msg->saved.base != NULL);
2911 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
2912 isc_buffer_add(&msgb, msg->saved.length);
2913 if (msg->tsigkey != NULL || msg->tsig != NULL) {
2915 return (dns_view_checksig(view, &msgb, msg));
2917 return (dns_tsig_verify(&msgb, msg, NULL, NULL));
2919 dns_rdata_t rdata = DNS_RDATA_INIT;
2920 dns_rdata_sig_t sig;
2921 dns_rdataset_t keyset;
2922 isc_result_t result;
2924 result = dns_rdataset_first(msg->sig0);
2925 INSIST(result == ISC_R_SUCCESS);
2926 dns_rdataset_current(msg->sig0, &rdata);
2929 * This can occur when the message is a dynamic update, since
2930 * the rdata length checking is relaxed. This should not
2931 * happen in a well-formed message, since the SIG(0) is only
2932 * looked for in the additional section, and the dynamic update
2933 * meta-records are in the prerequisite and update sections.
2935 if (rdata.length == 0)
2936 return (ISC_R_UNEXPECTEDEND);
2938 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
2939 if (result != ISC_R_SUCCESS)
2942 dns_rdataset_init(&keyset);
2944 return (DNS_R_KEYUNAUTHORIZED);
2945 result = dns_view_simplefind(view, &sig.signer,
2946 dns_rdatatype_key /* SIG(0) */,
2947 0, 0, ISC_FALSE, &keyset, NULL);
2949 if (result != ISC_R_SUCCESS) {
2950 /* XXXBEW Should possibly create a fetch here */
2951 result = DNS_R_KEYUNAUTHORIZED;
2953 } else if (keyset.trust < dns_trust_secure) {
2954 /* XXXBEW Should call a validator here */
2955 result = DNS_R_KEYUNAUTHORIZED;
2958 result = dns_rdataset_first(&keyset);
2959 INSIST(result == ISC_R_SUCCESS);
2961 result == ISC_R_SUCCESS;
2962 result = dns_rdataset_next(&keyset))
2964 dst_key_t *key = NULL;
2966 dns_rdataset_current(&keyset, &rdata);
2967 isc_buffer_init(&b, rdata.data, rdata.length);
2968 isc_buffer_add(&b, rdata.length);
2970 result = dst_key_fromdns(&sig.signer, rdata.rdclass,
2971 &b, view->mctx, &key);
2972 if (result != ISC_R_SUCCESS)
2974 if (dst_key_alg(key) != sig.algorithm ||
2975 dst_key_id(key) != sig.keyid ||
2976 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
2977 dst_key_proto(key) == DNS_KEYPROTO_ANY))
2982 result = dns_dnssec_verifymessage(&msgb, msg, key);
2984 if (result == ISC_R_SUCCESS)
2987 if (result == ISC_R_NOMORE)
2988 result = DNS_R_KEYUNAUTHORIZED;
2991 if (dns_rdataset_isassociated(&keyset))
2992 dns_rdataset_disassociate(&keyset);
2993 dns_rdata_freestruct(&sig);
2999 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
3000 const dns_master_style_t *style,
3001 dns_messagetextflag_t flags,
3002 isc_buffer_t *target) {
3003 dns_name_t *name, empty_name;
3004 dns_rdataset_t *rdataset;
3005 isc_result_t result;
3007 REQUIRE(DNS_MESSAGE_VALID(msg));
3008 REQUIRE(target != NULL);
3009 REQUIRE(VALID_SECTION(section));
3011 if (ISC_LIST_EMPTY(msg->sections[section]))
3012 return (ISC_R_SUCCESS);
3014 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
3015 ADD_STRING(target, ";; ");
3016 if (msg->opcode != dns_opcode_update) {
3017 ADD_STRING(target, sectiontext[section]);
3019 ADD_STRING(target, updsectiontext[section]);
3021 ADD_STRING(target, " SECTION:\n");
3024 dns_name_init(&empty_name, NULL);
3025 result = dns_message_firstname(msg, section);
3026 if (result != ISC_R_SUCCESS) {
3031 dns_message_currentname(msg, section, &name);
3032 for (rdataset = ISC_LIST_HEAD(name->list);
3034 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3035 if (section == DNS_SECTION_QUESTION) {
3036 ADD_STRING(target, ";");
3037 result = dns_master_questiontotext(name,
3042 result = dns_master_rdatasettotext(name,
3047 if (result != ISC_R_SUCCESS)
3050 result = dns_message_nextname(msg, section);
3051 } while (result == ISC_R_SUCCESS);
3052 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3053 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3054 ADD_STRING(target, "\n");
3055 if (result == ISC_R_NOMORE)
3056 result = ISC_R_SUCCESS;
3061 dns_message_pseudosectiontotext(dns_message_t *msg,
3062 dns_pseudosection_t section,
3063 const dns_master_style_t *style,
3064 dns_messagetextflag_t flags,
3065 isc_buffer_t *target) {
3066 dns_rdataset_t *ps = NULL;
3067 dns_name_t *name = NULL;
3068 isc_result_t result;
3069 char buf[sizeof("1234567890")];
3072 REQUIRE(DNS_MESSAGE_VALID(msg));
3073 REQUIRE(target != NULL);
3074 REQUIRE(VALID_PSEUDOSECTION(section));
3077 case DNS_PSEUDOSECTION_OPT:
3078 ps = dns_message_getopt(msg);
3080 return (ISC_R_SUCCESS);
3081 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3082 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
3083 ADD_STRING(target, "; EDNS: version: ");
3084 snprintf(buf, sizeof(buf), "%u",
3085 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
3086 ADD_STRING(target, buf);
3087 ADD_STRING(target, ", flags:");
3088 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
3089 ADD_STRING(target, " do");
3090 mbz = ps->ttl & ~DNS_MESSAGEEXTFLAG_DO & 0xffff;
3092 ADD_STRING(target, "; MBZ: ");
3093 snprintf(buf, sizeof(buf), "%.4x ", mbz);
3094 ADD_STRING(target, buf);
3095 ADD_STRING(target, ", udp: ");
3097 ADD_STRING(target, "; udp: ");
3098 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
3099 ADD_STRING(target, buf);
3100 return (ISC_R_SUCCESS);
3101 case DNS_PSEUDOSECTION_TSIG:
3102 ps = dns_message_gettsig(msg, &name);
3104 return (ISC_R_SUCCESS);
3105 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3106 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
3107 result = dns_master_rdatasettotext(name, ps, style, target);
3108 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3109 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3110 ADD_STRING(target, "\n");
3112 case DNS_PSEUDOSECTION_SIG0:
3113 ps = dns_message_getsig0(msg, &name);
3115 return (ISC_R_SUCCESS);
3116 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3117 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
3118 result = dns_master_rdatasettotext(name, ps, style, target);
3119 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3120 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3121 ADD_STRING(target, "\n");
3124 return (ISC_R_UNEXPECTED);
3128 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
3129 dns_messagetextflag_t flags, isc_buffer_t *target) {
3130 char buf[sizeof("1234567890")];
3131 isc_result_t result;
3133 REQUIRE(DNS_MESSAGE_VALID(msg));
3134 REQUIRE(target != NULL);
3136 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
3137 ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
3138 ADD_STRING(target, opcodetext[msg->opcode]);
3139 ADD_STRING(target, ", status: ");
3140 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
3141 ADD_STRING(target, rcodetext[msg->rcode]);
3143 snprintf(buf, sizeof(buf), "%4u", msg->rcode);
3144 ADD_STRING(target, buf);
3146 ADD_STRING(target, ", id: ");
3147 snprintf(buf, sizeof(buf), "%6u", msg->id);
3148 ADD_STRING(target, buf);
3149 ADD_STRING(target, "\n;; flags: ");
3150 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
3151 ADD_STRING(target, "qr ");
3152 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
3153 ADD_STRING(target, "aa ");
3154 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
3155 ADD_STRING(target, "tc ");
3156 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
3157 ADD_STRING(target, "rd ");
3158 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
3159 ADD_STRING(target, "ra ");
3160 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
3161 ADD_STRING(target, "ad ");
3162 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
3163 ADD_STRING(target, "cd ");
3164 if (msg->opcode != dns_opcode_update) {
3165 ADD_STRING(target, "; QUESTION: ");
3167 ADD_STRING(target, "; ZONE: ");
3169 snprintf(buf, sizeof(buf), "%1u",
3170 msg->counts[DNS_SECTION_QUESTION]);
3171 ADD_STRING(target, buf);
3172 if (msg->opcode != dns_opcode_update) {
3173 ADD_STRING(target, ", ANSWER: ");
3175 ADD_STRING(target, ", PREREQ: ");
3177 snprintf(buf, sizeof(buf), "%1u",
3178 msg->counts[DNS_SECTION_ANSWER]);
3179 ADD_STRING(target, buf);
3180 if (msg->opcode != dns_opcode_update) {
3181 ADD_STRING(target, ", AUTHORITY: ");
3183 ADD_STRING(target, ", UPDATE: ");
3185 snprintf(buf, sizeof(buf), "%1u",
3186 msg->counts[DNS_SECTION_AUTHORITY]);
3187 ADD_STRING(target, buf);
3188 ADD_STRING(target, ", ADDITIONAL: ");
3189 snprintf(buf, sizeof(buf), "%1u",
3190 msg->counts[DNS_SECTION_ADDITIONAL]);
3191 ADD_STRING(target, buf);
3192 ADD_STRING(target, "\n");
3194 result = dns_message_pseudosectiontotext(msg,
3195 DNS_PSEUDOSECTION_OPT,
3196 style, flags, target);
3197 if (result != ISC_R_SUCCESS)
3200 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
3201 style, flags, target);
3202 if (result != ISC_R_SUCCESS)
3204 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
3205 style, flags, target);
3206 if (result != ISC_R_SUCCESS)
3208 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
3209 style, flags, target);
3210 if (result != ISC_R_SUCCESS)
3212 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
3213 style, flags, target);
3214 if (result != ISC_R_SUCCESS)
3217 result = dns_message_pseudosectiontotext(msg,
3218 DNS_PSEUDOSECTION_TSIG,
3219 style, flags, target);
3220 if (result != ISC_R_SUCCESS)
3223 result = dns_message_pseudosectiontotext(msg,
3224 DNS_PSEUDOSECTION_SIG0,
3225 style, flags, target);
3226 if (result != ISC_R_SUCCESS)
3229 return (ISC_R_SUCCESS);
3233 dns_message_getrawmessage(dns_message_t *msg) {
3234 REQUIRE(DNS_MESSAGE_VALID(msg));
3235 return (&msg->saved);
3239 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
3240 const void *order_arg)
3242 REQUIRE(DNS_MESSAGE_VALID(msg));
3244 msg->order_arg = order_arg;
3248 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
3249 REQUIRE(DNS_MESSAGE_VALID(msg));
3250 msg->timeadjust = timeadjust;
3254 dns_message_gettimeadjust(dns_message_t *msg) {
3255 REQUIRE(DNS_MESSAGE_VALID(msg));
3256 return (msg->timeadjust);
3260 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
3262 REQUIRE(opcode < 16);
3264 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode]))
3265 return (ISC_R_NOSPACE);
3266 isc_buffer_putstr(target, opcodetext[opcode]);
3267 return (ISC_R_SUCCESS);