Home | History | Annotate | Line # | Download | only in dns
message.c revision 1.15
      1 /*	$NetBSD: message.c,v 1.15 2023/01/25 21:43:30 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 /***
     19  *** Imports
     20  ***/
     21 
     22 #include <ctype.h>
     23 #include <inttypes.h>
     24 #include <stdbool.h>
     25 
     26 #include <isc/buffer.h>
     27 #include <isc/mem.h>
     28 #include <isc/print.h>
     29 #include <isc/string.h> /* Required for HP/UX (and others?) */
     30 #include <isc/utf8.h>
     31 #include <isc/util.h>
     32 
     33 #include <dns/dnssec.h>
     34 #include <dns/keyvalues.h>
     35 #include <dns/log.h>
     36 #include <dns/masterdump.h>
     37 #include <dns/message.h>
     38 #include <dns/opcode.h>
     39 #include <dns/rcode.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>
     45 #include <dns/tsig.h>
     46 #include <dns/ttl.h>
     47 #include <dns/view.h>
     48 
     49 #ifdef SKAN_MSG_DEBUG
     50 static void
     51 hexdump(const char *msg, const char *msg2, void *base, size_t len) {
     52 	unsigned char *p;
     53 	unsigned int cnt;
     54 
     55 	p = base;
     56 	cnt = 0;
     57 
     58 	printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, (unsigned)len, base);
     59 
     60 	while (cnt < len) {
     61 		if (cnt % 16 == 0) {
     62 			printf("%p: ", p);
     63 		} else if (cnt % 8 == 0) {
     64 			printf(" |");
     65 		}
     66 		printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
     67 		p++;
     68 		cnt++;
     69 
     70 		if (cnt % 16 == 0) {
     71 			printf("\n");
     72 		}
     73 	}
     74 
     75 	if (cnt % 16 != 0) {
     76 		printf("\n");
     77 	}
     78 }
     79 #endif /* ifdef SKAN_MSG_DEBUG */
     80 
     81 #define DNS_MESSAGE_OPCODE_MASK	      0x7800U
     82 #define DNS_MESSAGE_OPCODE_SHIFT      11
     83 #define DNS_MESSAGE_RCODE_MASK	      0x000fU
     84 #define DNS_MESSAGE_FLAG_MASK	      0x8ff0U
     85 #define DNS_MESSAGE_EDNSRCODE_MASK    0xff000000U
     86 #define DNS_MESSAGE_EDNSRCODE_SHIFT   24
     87 #define DNS_MESSAGE_EDNSVERSION_MASK  0x00ff0000U
     88 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
     89 
     90 #define VALID_NAMED_SECTION(s) \
     91 	(((s) > DNS_SECTION_ANY) && ((s) < DNS_SECTION_MAX))
     92 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) && ((s) < DNS_SECTION_MAX))
     93 #define ADD_STRING(b, s)                                          \
     94 	{                                                         \
     95 		if (strlen(s) >= isc_buffer_availablelength(b)) { \
     96 			result = ISC_R_NOSPACE;                   \
     97 			goto cleanup;                             \
     98 		} else                                            \
     99 			isc_buffer_putstr(b, s);                  \
    100 	}
    101 #define VALID_PSEUDOSECTION(s) \
    102 	(((s) >= DNS_PSEUDOSECTION_ANY) && ((s) < DNS_PSEUDOSECTION_MAX))
    103 
    104 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
    105 
    106 /*%
    107  * This is the size of each individual scratchpad buffer, and the numbers
    108  * of various block allocations used within the server.
    109  * XXXMLG These should come from a config setting.
    110  */
    111 #define SCRATCHPAD_SIZE	   1232
    112 #define NAME_FILLCOUNT	   4
    113 #define NAME_FREEMAX	   8 * NAME_FILLCOUNT
    114 #define OFFSET_COUNT	   4
    115 #define RDATA_COUNT	   8
    116 #define RDATALIST_COUNT	   8
    117 #define RDATASET_FILLCOUNT 4
    118 #define RDATASET_FREEMAX   8 * RDATASET_FILLCOUNT
    119 
    120 /*%
    121  * Text representation of the different items, for message_totext
    122  * functions.
    123  */
    124 static const char *sectiontext[] = { "QUESTION", "ANSWER", "AUTHORITY",
    125 				     "ADDITIONAL" };
    126 
    127 static const char *updsectiontext[] = { "ZONE", "PREREQUISITE", "UPDATE",
    128 					"ADDITIONAL" };
    129 
    130 static const char *opcodetext[] = { "QUERY",	  "IQUERY",	"STATUS",
    131 				    "RESERVED3",  "NOTIFY",	"UPDATE",
    132 				    "RESERVED6",  "RESERVED7",	"RESERVED8",
    133 				    "RESERVED9",  "RESERVED10", "RESERVED11",
    134 				    "RESERVED12", "RESERVED13", "RESERVED14",
    135 				    "RESERVED15" };
    136 
    137 static const char *edetext[] = { "Other",
    138 				 "Unsupported DNSKEY Algorithm",
    139 				 "Unsupported DS Digest Type",
    140 				 "Stale Answer",
    141 				 "Forged Answer",
    142 				 "DNSSEC Indeterminate",
    143 				 "DNSSEC Bogus",
    144 				 "Signature Expired",
    145 				 "Signature Not Yet Valid",
    146 				 "DNSKEY Missing",
    147 				 "RRSIGs Missing",
    148 				 "No Zone Key Bit Set",
    149 				 "NSEC Missing",
    150 				 "Cached Error",
    151 				 "Not Ready",
    152 				 "Blocked",
    153 				 "Censored",
    154 				 "Filtered",
    155 				 "Prohibited",
    156 				 "Stale NXDOMAIN Answer",
    157 				 "Not Authoritative",
    158 				 "Not Supported",
    159 				 "No Reachable Authority",
    160 				 "Network Error",
    161 				 "Invalid Data" };
    162 
    163 /*%
    164  * "helper" type, which consists of a block of some type, and is linkable.
    165  * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
    166  * size, or the allocated elements will not be aligned correctly.
    167  */
    168 struct dns_msgblock {
    169 	unsigned int count;
    170 	unsigned int remaining;
    171 	ISC_LINK(dns_msgblock_t) link;
    172 }; /* dynamically sized */
    173 
    174 static dns_msgblock_t *
    175 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
    176 
    177 #define msgblock_get(block, type) \
    178 	((type *)msgblock_internalget(block, sizeof(type)))
    179 
    180 static void *
    181 msgblock_internalget(dns_msgblock_t *, unsigned int);
    182 
    183 static void
    184 msgblock_reset(dns_msgblock_t *);
    185 
    186 static void
    187 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
    188 
    189 static void
    190 logfmtpacket(dns_message_t *message, const char *description,
    191 	     const isc_sockaddr_t *address, isc_logcategory_t *category,
    192 	     isc_logmodule_t *module, const dns_master_style_t *style,
    193 	     int level, isc_mem_t *mctx);
    194 
    195 /*
    196  * Allocate a new dns_msgblock_t, and return a pointer to it.  If no memory
    197  * is free, return NULL.
    198  */
    199 static dns_msgblock_t *
    200 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
    201 		  unsigned int count) {
    202 	dns_msgblock_t *block;
    203 	unsigned int length;
    204 
    205 	length = sizeof(dns_msgblock_t) + (sizeof_type * count);
    206 
    207 	block = isc_mem_get(mctx, length);
    208 
    209 	block->count = count;
    210 	block->remaining = count;
    211 
    212 	ISC_LINK_INIT(block, link);
    213 
    214 	return (block);
    215 }
    216 
    217 /*
    218  * Return an element from the msgblock.  If no more are available, return
    219  * NULL.
    220  */
    221 static void *
    222 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
    223 	void *ptr;
    224 
    225 	if (block == NULL || block->remaining == 0) {
    226 		return (NULL);
    227 	}
    228 
    229 	block->remaining--;
    230 
    231 	ptr = (((unsigned char *)block) + sizeof(dns_msgblock_t) +
    232 	       (sizeof_type * block->remaining));
    233 
    234 	return (ptr);
    235 }
    236 
    237 static void
    238 msgblock_reset(dns_msgblock_t *block) {
    239 	block->remaining = block->count;
    240 }
    241 
    242 /*
    243  * Release memory associated with a message block.
    244  */
    245 static void
    246 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block,
    247 	      unsigned int sizeof_type) {
    248 	unsigned int length;
    249 
    250 	length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
    251 
    252 	isc_mem_put(mctx, block, length);
    253 }
    254 
    255 /*
    256  * Allocate a new dynamic buffer, and attach it to this message as the
    257  * "current" buffer.  (which is always the last on the list, for our
    258  * uses)
    259  */
    260 static isc_result_t
    261 newbuffer(dns_message_t *msg, unsigned int size) {
    262 	isc_buffer_t *dynbuf;
    263 
    264 	dynbuf = NULL;
    265 	isc_buffer_allocate(msg->mctx, &dynbuf, size);
    266 
    267 	ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
    268 	return (ISC_R_SUCCESS);
    269 }
    270 
    271 static isc_buffer_t *
    272 currentbuffer(dns_message_t *msg) {
    273 	isc_buffer_t *dynbuf;
    274 
    275 	dynbuf = ISC_LIST_TAIL(msg->scratchpad);
    276 	INSIST(dynbuf != NULL);
    277 
    278 	return (dynbuf);
    279 }
    280 
    281 static void
    282 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
    283 	ISC_LIST_PREPEND(msg->freerdata, rdata, link);
    284 }
    285 
    286 static dns_rdata_t *
    287 newrdata(dns_message_t *msg) {
    288 	dns_msgblock_t *msgblock;
    289 	dns_rdata_t *rdata;
    290 
    291 	rdata = ISC_LIST_HEAD(msg->freerdata);
    292 	if (rdata != NULL) {
    293 		ISC_LIST_UNLINK(msg->freerdata, rdata, link);
    294 		return (rdata);
    295 	}
    296 
    297 	msgblock = ISC_LIST_TAIL(msg->rdatas);
    298 	rdata = msgblock_get(msgblock, dns_rdata_t);
    299 	if (rdata == NULL) {
    300 		msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
    301 					     RDATA_COUNT);
    302 		if (msgblock == NULL) {
    303 			return (NULL);
    304 		}
    305 
    306 		ISC_LIST_APPEND(msg->rdatas, msgblock, link);
    307 
    308 		rdata = msgblock_get(msgblock, dns_rdata_t);
    309 	}
    310 
    311 	dns_rdata_init(rdata);
    312 	return (rdata);
    313 }
    314 
    315 static void
    316 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
    317 	ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
    318 }
    319 
    320 static dns_rdatalist_t *
    321 newrdatalist(dns_message_t *msg) {
    322 	dns_msgblock_t *msgblock;
    323 	dns_rdatalist_t *rdatalist;
    324 
    325 	rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
    326 	if (rdatalist != NULL) {
    327 		ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
    328 		goto out;
    329 	}
    330 
    331 	msgblock = ISC_LIST_TAIL(msg->rdatalists);
    332 	rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
    333 	if (rdatalist == NULL) {
    334 		msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdatalist_t),
    335 					     RDATALIST_COUNT);
    336 		if (msgblock == NULL) {
    337 			return (NULL);
    338 		}
    339 
    340 		ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
    341 
    342 		rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
    343 	}
    344 out:
    345 	if (rdatalist != NULL) {
    346 		dns_rdatalist_init(rdatalist);
    347 	}
    348 
    349 	return (rdatalist);
    350 }
    351 
    352 static dns_offsets_t *
    353 newoffsets(dns_message_t *msg) {
    354 	dns_msgblock_t *msgblock;
    355 	dns_offsets_t *offsets;
    356 
    357 	msgblock = ISC_LIST_TAIL(msg->offsets);
    358 	offsets = msgblock_get(msgblock, dns_offsets_t);
    359 	if (offsets == NULL) {
    360 		msgblock = msgblock_allocate(msg->mctx, sizeof(dns_offsets_t),
    361 					     OFFSET_COUNT);
    362 		if (msgblock == NULL) {
    363 			return (NULL);
    364 		}
    365 
    366 		ISC_LIST_APPEND(msg->offsets, msgblock, link);
    367 
    368 		offsets = msgblock_get(msgblock, dns_offsets_t);
    369 	}
    370 
    371 	return (offsets);
    372 }
    373 
    374 static void
    375 msginitheader(dns_message_t *m) {
    376 	m->id = 0;
    377 	m->flags = 0;
    378 	m->rcode = 0;
    379 	m->opcode = 0;
    380 	m->rdclass = 0;
    381 }
    382 
    383 static void
    384 msginitprivate(dns_message_t *m) {
    385 	unsigned int i;
    386 
    387 	for (i = 0; i < DNS_SECTION_MAX; i++) {
    388 		m->cursors[i] = NULL;
    389 		m->counts[i] = 0;
    390 	}
    391 	m->opt = NULL;
    392 	m->sig0 = NULL;
    393 	m->sig0name = NULL;
    394 	m->tsig = NULL;
    395 	m->tsigname = NULL;
    396 	m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
    397 	m->opt_reserved = 0;
    398 	m->sig_reserved = 0;
    399 	m->reserved = 0;
    400 	m->padding = 0;
    401 	m->padding_off = 0;
    402 	m->buffer = NULL;
    403 }
    404 
    405 static void
    406 msginittsig(dns_message_t *m) {
    407 	m->tsigstatus = dns_rcode_noerror;
    408 	m->querytsigstatus = dns_rcode_noerror;
    409 	m->tsigkey = NULL;
    410 	m->tsigctx = NULL;
    411 	m->sigstart = -1;
    412 	m->sig0key = NULL;
    413 	m->sig0status = dns_rcode_noerror;
    414 	m->timeadjust = 0;
    415 }
    416 
    417 /*
    418  * Init elements to default state.  Used both when allocating a new element
    419  * and when resetting one.
    420  */
    421 static void
    422 msginit(dns_message_t *m) {
    423 	msginitheader(m);
    424 	msginitprivate(m);
    425 	msginittsig(m);
    426 	m->header_ok = 0;
    427 	m->question_ok = 0;
    428 	m->tcp_continuation = 0;
    429 	m->verified_sig = 0;
    430 	m->verify_attempted = 0;
    431 	m->order = NULL;
    432 	m->order_arg.env = NULL;
    433 	m->order_arg.acl = NULL;
    434 	m->order_arg.element = NULL;
    435 	m->query.base = NULL;
    436 	m->query.length = 0;
    437 	m->free_query = 0;
    438 	m->saved.base = NULL;
    439 	m->saved.length = 0;
    440 	m->free_saved = 0;
    441 	m->cc_ok = 0;
    442 	m->cc_bad = 0;
    443 	m->tkey = 0;
    444 	m->rdclass_set = 0;
    445 	m->querytsig = NULL;
    446 	m->indent.string = "\t";
    447 	m->indent.count = 0;
    448 }
    449 
    450 static void
    451 msgresetnames(dns_message_t *msg, unsigned int first_section) {
    452 	unsigned int i;
    453 	dns_name_t *name, *next_name;
    454 	dns_rdataset_t *rds, *next_rds;
    455 
    456 	/*
    457 	 * Clean up name lists by calling the rdataset disassociate function.
    458 	 */
    459 	for (i = first_section; i < DNS_SECTION_MAX; i++) {
    460 		name = ISC_LIST_HEAD(msg->sections[i]);
    461 		while (name != NULL) {
    462 			next_name = ISC_LIST_NEXT(name, link);
    463 			ISC_LIST_UNLINK(msg->sections[i], name, link);
    464 
    465 			rds = ISC_LIST_HEAD(name->list);
    466 			while (rds != NULL) {
    467 				next_rds = ISC_LIST_NEXT(rds, link);
    468 				ISC_LIST_UNLINK(name->list, rds, link);
    469 
    470 				INSIST(dns_rdataset_isassociated(rds));
    471 				dns_rdataset_disassociate(rds);
    472 				isc_mempool_put(msg->rdspool, rds);
    473 				rds = next_rds;
    474 			}
    475 			dns_message_puttempname(msg, &name);
    476 			name = next_name;
    477 		}
    478 	}
    479 }
    480 
    481 static void
    482 msgresetopt(dns_message_t *msg) {
    483 	if (msg->opt != NULL) {
    484 		if (msg->opt_reserved > 0) {
    485 			dns_message_renderrelease(msg, msg->opt_reserved);
    486 			msg->opt_reserved = 0;
    487 		}
    488 		INSIST(dns_rdataset_isassociated(msg->opt));
    489 		dns_rdataset_disassociate(msg->opt);
    490 		isc_mempool_put(msg->rdspool, msg->opt);
    491 		msg->opt = NULL;
    492 		msg->cc_ok = 0;
    493 		msg->cc_bad = 0;
    494 	}
    495 }
    496 
    497 static void
    498 msgresetsigs(dns_message_t *msg, bool replying) {
    499 	if (msg->sig_reserved > 0) {
    500 		dns_message_renderrelease(msg, msg->sig_reserved);
    501 		msg->sig_reserved = 0;
    502 	}
    503 	if (msg->tsig != NULL) {
    504 		INSIST(dns_rdataset_isassociated(msg->tsig));
    505 		INSIST(msg->namepool != NULL);
    506 		if (replying) {
    507 			INSIST(msg->querytsig == NULL);
    508 			msg->querytsig = msg->tsig;
    509 		} else {
    510 			dns_rdataset_disassociate(msg->tsig);
    511 			isc_mempool_put(msg->rdspool, msg->tsig);
    512 			if (msg->querytsig != NULL) {
    513 				dns_rdataset_disassociate(msg->querytsig);
    514 				isc_mempool_put(msg->rdspool, msg->querytsig);
    515 			}
    516 		}
    517 		dns_message_puttempname(msg, &msg->tsigname);
    518 		msg->tsig = NULL;
    519 	} else if (msg->querytsig != NULL && !replying) {
    520 		dns_rdataset_disassociate(msg->querytsig);
    521 		isc_mempool_put(msg->rdspool, msg->querytsig);
    522 		msg->querytsig = NULL;
    523 	}
    524 	if (msg->sig0 != NULL) {
    525 		INSIST(dns_rdataset_isassociated(msg->sig0));
    526 		dns_rdataset_disassociate(msg->sig0);
    527 		isc_mempool_put(msg->rdspool, msg->sig0);
    528 		if (msg->sig0name != NULL) {
    529 			dns_message_puttempname(msg, &msg->sig0name);
    530 		}
    531 		msg->sig0 = NULL;
    532 		msg->sig0name = NULL;
    533 	}
    534 }
    535 
    536 /*
    537  * Free all but one (or everything) for this message.  This is used by
    538  * both dns_message_reset() and dns__message_destroy().
    539  */
    540 static void
    541 msgreset(dns_message_t *msg, bool everything) {
    542 	dns_msgblock_t *msgblock, *next_msgblock;
    543 	isc_buffer_t *dynbuf, *next_dynbuf;
    544 	dns_rdata_t *rdata;
    545 	dns_rdatalist_t *rdatalist;
    546 
    547 	msgresetnames(msg, 0);
    548 	msgresetopt(msg);
    549 	msgresetsigs(msg, false);
    550 
    551 	/*
    552 	 * Clean up linked lists.
    553 	 */
    554 
    555 	/*
    556 	 * Run through the free lists, and just unlink anything found there.
    557 	 * The memory isn't lost since these are part of message blocks we
    558 	 * have allocated.
    559 	 */
    560 	rdata = ISC_LIST_HEAD(msg->freerdata);
    561 	while (rdata != NULL) {
    562 		ISC_LIST_UNLINK(msg->freerdata, rdata, link);
    563 		rdata = ISC_LIST_HEAD(msg->freerdata);
    564 	}
    565 	rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
    566 	while (rdatalist != NULL) {
    567 		ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
    568 		rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
    569 	}
    570 
    571 	dynbuf = ISC_LIST_HEAD(msg->scratchpad);
    572 	INSIST(dynbuf != NULL);
    573 	if (!everything) {
    574 		isc_buffer_clear(dynbuf);
    575 		dynbuf = ISC_LIST_NEXT(dynbuf, link);
    576 	}
    577 	while (dynbuf != NULL) {
    578 		next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
    579 		ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
    580 		isc_buffer_free(&dynbuf);
    581 		dynbuf = next_dynbuf;
    582 	}
    583 
    584 	msgblock = ISC_LIST_HEAD(msg->rdatas);
    585 	if (!everything && msgblock != NULL) {
    586 		msgblock_reset(msgblock);
    587 		msgblock = ISC_LIST_NEXT(msgblock, link);
    588 	}
    589 	while (msgblock != NULL) {
    590 		next_msgblock = ISC_LIST_NEXT(msgblock, link);
    591 		ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
    592 		msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
    593 		msgblock = next_msgblock;
    594 	}
    595 
    596 	/*
    597 	 * rdatalists could be empty.
    598 	 */
    599 
    600 	msgblock = ISC_LIST_HEAD(msg->rdatalists);
    601 	if (!everything && msgblock != NULL) {
    602 		msgblock_reset(msgblock);
    603 		msgblock = ISC_LIST_NEXT(msgblock, link);
    604 	}
    605 	while (msgblock != NULL) {
    606 		next_msgblock = ISC_LIST_NEXT(msgblock, link);
    607 		ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
    608 		msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
    609 		msgblock = next_msgblock;
    610 	}
    611 
    612 	msgblock = ISC_LIST_HEAD(msg->offsets);
    613 	if (!everything && msgblock != NULL) {
    614 		msgblock_reset(msgblock);
    615 		msgblock = ISC_LIST_NEXT(msgblock, link);
    616 	}
    617 	while (msgblock != NULL) {
    618 		next_msgblock = ISC_LIST_NEXT(msgblock, link);
    619 		ISC_LIST_UNLINK(msg->offsets, msgblock, link);
    620 		msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
    621 		msgblock = next_msgblock;
    622 	}
    623 
    624 	if (msg->tsigkey != NULL) {
    625 		dns_tsigkey_detach(&msg->tsigkey);
    626 		msg->tsigkey = NULL;
    627 	}
    628 
    629 	if (msg->tsigctx != NULL) {
    630 		dst_context_destroy(&msg->tsigctx);
    631 	}
    632 
    633 	if (msg->query.base != NULL) {
    634 		if (msg->free_query != 0) {
    635 			isc_mem_put(msg->mctx, msg->query.base,
    636 				    msg->query.length);
    637 		}
    638 		msg->query.base = NULL;
    639 		msg->query.length = 0;
    640 	}
    641 
    642 	if (msg->saved.base != NULL) {
    643 		if (msg->free_saved != 0) {
    644 			isc_mem_put(msg->mctx, msg->saved.base,
    645 				    msg->saved.length);
    646 		}
    647 		msg->saved.base = NULL;
    648 		msg->saved.length = 0;
    649 	}
    650 
    651 	/*
    652 	 * cleanup the buffer cleanup list
    653 	 */
    654 	dynbuf = ISC_LIST_HEAD(msg->cleanup);
    655 	while (dynbuf != NULL) {
    656 		next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
    657 		ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
    658 		isc_buffer_free(&dynbuf);
    659 		dynbuf = next_dynbuf;
    660 	}
    661 
    662 	/*
    663 	 * Set other bits to normal default values.
    664 	 */
    665 	if (!everything) {
    666 		msginit(msg);
    667 	}
    668 
    669 	ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
    670 	ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
    671 }
    672 
    673 static unsigned int
    674 spacefortsig(dns_tsigkey_t *key, int otherlen) {
    675 	isc_region_t r1, r2;
    676 	unsigned int x;
    677 	isc_result_t result;
    678 
    679 	/*
    680 	 * The space required for an TSIG record is:
    681 	 *
    682 	 *	n1 bytes for the name
    683 	 *	2 bytes for the type
    684 	 *	2 bytes for the class
    685 	 *	4 bytes for the ttl
    686 	 *	2 bytes for the rdlength
    687 	 *	n2 bytes for the algorithm name
    688 	 *	6 bytes for the time signed
    689 	 *	2 bytes for the fudge
    690 	 *	2 bytes for the MAC size
    691 	 *	x bytes for the MAC
    692 	 *	2 bytes for the original id
    693 	 *	2 bytes for the error
    694 	 *	2 bytes for the other data length
    695 	 *	y bytes for the other data (at most)
    696 	 * ---------------------------------
    697 	 *     26 + n1 + n2 + x + y bytes
    698 	 */
    699 
    700 	dns_name_toregion(&key->name, &r1);
    701 	dns_name_toregion(key->algorithm, &r2);
    702 	if (key->key == NULL) {
    703 		x = 0;
    704 	} else {
    705 		result = dst_key_sigsize(key->key, &x);
    706 		if (result != ISC_R_SUCCESS) {
    707 			x = 0;
    708 		}
    709 	}
    710 	return (26 + r1.length + r2.length + x + otherlen);
    711 }
    712 
    713 void
    714 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) {
    715 	dns_message_t *m = NULL;
    716 	isc_buffer_t *dynbuf = NULL;
    717 	unsigned int i;
    718 
    719 	REQUIRE(mctx != NULL);
    720 	REQUIRE(msgp != NULL);
    721 	REQUIRE(*msgp == NULL);
    722 	REQUIRE(intent == DNS_MESSAGE_INTENTPARSE ||
    723 		intent == DNS_MESSAGE_INTENTRENDER);
    724 
    725 	m = isc_mem_get(mctx, sizeof(dns_message_t));
    726 	*m = (dns_message_t){ .from_to_wire = intent };
    727 	isc_mem_attach(mctx, &m->mctx);
    728 	msginit(m);
    729 
    730 	for (i = 0; i < DNS_SECTION_MAX; i++) {
    731 		ISC_LIST_INIT(m->sections[i]);
    732 	}
    733 
    734 	ISC_LIST_INIT(m->scratchpad);
    735 	ISC_LIST_INIT(m->cleanup);
    736 	ISC_LIST_INIT(m->rdatas);
    737 	ISC_LIST_INIT(m->rdatalists);
    738 	ISC_LIST_INIT(m->offsets);
    739 	ISC_LIST_INIT(m->freerdata);
    740 	ISC_LIST_INIT(m->freerdatalist);
    741 
    742 	isc_mempool_create(m->mctx, sizeof(dns_fixedname_t), &m->namepool);
    743 	isc_mempool_setfillcount(m->namepool, NAME_FILLCOUNT);
    744 	isc_mempool_setfreemax(m->namepool, NAME_FREEMAX);
    745 	isc_mempool_setname(m->namepool, "msg:names");
    746 
    747 	isc_mempool_create(m->mctx, sizeof(dns_rdataset_t), &m->rdspool);
    748 	isc_mempool_setfillcount(m->rdspool, RDATASET_FILLCOUNT);
    749 	isc_mempool_setfreemax(m->rdspool, RDATASET_FREEMAX);
    750 	isc_mempool_setname(m->rdspool, "msg:rdataset");
    751 
    752 	isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
    753 	ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
    754 
    755 	isc_refcount_init(&m->refcount, 1);
    756 	m->magic = DNS_MESSAGE_MAGIC;
    757 
    758 	*msgp = m;
    759 }
    760 
    761 void
    762 dns_message_reset(dns_message_t *msg, unsigned int intent) {
    763 	REQUIRE(DNS_MESSAGE_VALID(msg));
    764 	REQUIRE(intent == DNS_MESSAGE_INTENTPARSE ||
    765 		intent == DNS_MESSAGE_INTENTRENDER);
    766 
    767 	msgreset(msg, false);
    768 	msg->from_to_wire = intent;
    769 }
    770 
    771 static void
    772 dns__message_destroy(dns_message_t *msg) {
    773 	REQUIRE(msg != NULL);
    774 	REQUIRE(DNS_MESSAGE_VALID(msg));
    775 
    776 	msgreset(msg, true);
    777 	isc_mempool_destroy(&msg->namepool);
    778 	isc_mempool_destroy(&msg->rdspool);
    779 	isc_refcount_destroy(&msg->refcount);
    780 	msg->magic = 0;
    781 	isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t));
    782 }
    783 
    784 void
    785 dns_message_attach(dns_message_t *source, dns_message_t **target) {
    786 	REQUIRE(DNS_MESSAGE_VALID(source));
    787 
    788 	isc_refcount_increment(&source->refcount);
    789 	*target = source;
    790 }
    791 
    792 void
    793 dns_message_detach(dns_message_t **messagep) {
    794 	REQUIRE(messagep != NULL && DNS_MESSAGE_VALID(*messagep));
    795 	dns_message_t *msg = *messagep;
    796 	*messagep = NULL;
    797 
    798 	if (isc_refcount_decrement(&msg->refcount) == 1) {
    799 		dns__message_destroy(msg);
    800 	}
    801 }
    802 
    803 static isc_result_t
    804 findname(dns_name_t **foundname, const dns_name_t *target,
    805 	 dns_namelist_t *section) {
    806 	dns_name_t *curr;
    807 
    808 	for (curr = ISC_LIST_TAIL(*section); curr != NULL;
    809 	     curr = ISC_LIST_PREV(curr, link))
    810 	{
    811 		if (dns_name_equal(curr, target)) {
    812 			if (foundname != NULL) {
    813 				*foundname = curr;
    814 			}
    815 			return (ISC_R_SUCCESS);
    816 		}
    817 	}
    818 
    819 	return (ISC_R_NOTFOUND);
    820 }
    821 
    822 isc_result_t
    823 dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass,
    824 		 dns_rdatatype_t type, dns_rdatatype_t covers,
    825 		 dns_rdataset_t **rdataset) {
    826 	dns_rdataset_t *curr;
    827 
    828 	REQUIRE(name != NULL);
    829 	REQUIRE(rdataset == NULL || *rdataset == NULL);
    830 
    831 	for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
    832 	     curr = ISC_LIST_PREV(curr, link))
    833 	{
    834 		if (curr->rdclass == rdclass && curr->type == type &&
    835 		    curr->covers == covers)
    836 		{
    837 			if (rdataset != NULL) {
    838 				*rdataset = curr;
    839 			}
    840 			return (ISC_R_SUCCESS);
    841 		}
    842 	}
    843 
    844 	return (ISC_R_NOTFOUND);
    845 }
    846 
    847 isc_result_t
    848 dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type,
    849 		     dns_rdatatype_t covers, dns_rdataset_t **rdataset) {
    850 	dns_rdataset_t *curr;
    851 
    852 	REQUIRE(name != NULL);
    853 	REQUIRE(rdataset == NULL || *rdataset == NULL);
    854 
    855 	for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
    856 	     curr = ISC_LIST_PREV(curr, link))
    857 	{
    858 		if (curr->type == type && curr->covers == covers) {
    859 			if (ISC_UNLIKELY(rdataset != NULL)) {
    860 				*rdataset = curr;
    861 			}
    862 			return (ISC_R_SUCCESS);
    863 		}
    864 	}
    865 
    866 	return (ISC_R_NOTFOUND);
    867 }
    868 
    869 /*
    870  * Read a name from buffer "source".
    871  */
    872 static isc_result_t
    873 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
    874 	dns_decompress_t *dctx) {
    875 	isc_buffer_t *scratch;
    876 	isc_result_t result;
    877 	unsigned int tries;
    878 
    879 	scratch = currentbuffer(msg);
    880 
    881 	/*
    882 	 * First try:  use current buffer.
    883 	 * Second try:  allocate a new buffer and use that.
    884 	 */
    885 	tries = 0;
    886 	while (tries < 2) {
    887 		result = dns_name_fromwire(name, source, dctx, 0, scratch);
    888 
    889 		if (result == ISC_R_NOSPACE) {
    890 			tries++;
    891 
    892 			result = newbuffer(msg, SCRATCHPAD_SIZE);
    893 			if (result != ISC_R_SUCCESS) {
    894 				return (result);
    895 			}
    896 
    897 			scratch = currentbuffer(msg);
    898 			dns_name_reset(name);
    899 		} else {
    900 			return (result);
    901 		}
    902 	}
    903 
    904 	UNREACHABLE();
    905 }
    906 
    907 static isc_result_t
    908 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
    909 	 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
    910 	 unsigned int rdatalen, dns_rdata_t *rdata) {
    911 	isc_buffer_t *scratch;
    912 	isc_result_t result;
    913 	unsigned int tries;
    914 	unsigned int trysize;
    915 
    916 	scratch = currentbuffer(msg);
    917 
    918 	isc_buffer_setactive(source, rdatalen);
    919 
    920 	/*
    921 	 * First try:  use current buffer.
    922 	 * Second try:  allocate a new buffer of size
    923 	 *     max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
    924 	 *     (the data will fit if it was not more than 50% compressed)
    925 	 * Subsequent tries: double buffer size on each try.
    926 	 */
    927 	tries = 0;
    928 	trysize = 0;
    929 	/* XXX possibly change this to a while (tries < 2) loop */
    930 	for (;;) {
    931 		result = dns_rdata_fromwire(rdata, rdclass, rdtype, source,
    932 					    dctx, 0, scratch);
    933 
    934 		if (result == ISC_R_NOSPACE) {
    935 			if (tries == 0) {
    936 				trysize = 2 * rdatalen;
    937 				if (trysize < SCRATCHPAD_SIZE) {
    938 					trysize = SCRATCHPAD_SIZE;
    939 				}
    940 			} else {
    941 				INSIST(trysize != 0);
    942 				if (trysize >= 65535) {
    943 					return (ISC_R_NOSPACE);
    944 				}
    945 				/* XXX DNS_R_RRTOOLONG? */
    946 				trysize *= 2;
    947 			}
    948 			tries++;
    949 			result = newbuffer(msg, trysize);
    950 			if (result != ISC_R_SUCCESS) {
    951 				return (result);
    952 			}
    953 
    954 			scratch = currentbuffer(msg);
    955 		} else {
    956 			return (result);
    957 		}
    958 	}
    959 }
    960 
    961 #define DO_ERROR(r)                          \
    962 	do {                                 \
    963 		if (best_effort) {           \
    964 			seen_problem = true; \
    965 		} else {                     \
    966 			result = r;          \
    967 			goto cleanup;        \
    968 		}                            \
    969 	} while (0)
    970 
    971 static isc_result_t
    972 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
    973 	     unsigned int options) {
    974 	isc_region_t r;
    975 	unsigned int count;
    976 	dns_name_t *name = NULL;
    977 	dns_name_t *name2 = NULL;
    978 	dns_rdataset_t *rdataset = NULL;
    979 	dns_rdatalist_t *rdatalist = NULL;
    980 	isc_result_t result;
    981 	dns_rdatatype_t rdtype;
    982 	dns_rdataclass_t rdclass;
    983 	dns_namelist_t *section = &msg->sections[DNS_SECTION_QUESTION];
    984 	bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0);
    985 	bool seen_problem = false;
    986 	bool free_name = false;
    987 
    988 	for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
    989 		name = NULL;
    990 		result = dns_message_gettempname(msg, &name);
    991 		if (result != ISC_R_SUCCESS) {
    992 			goto cleanup;
    993 		}
    994 		name->offsets = (unsigned char *)newoffsets(msg);
    995 		free_name = true;
    996 
    997 		/*
    998 		 * Parse the name out of this packet.
    999 		 */
   1000 		isc_buffer_remainingregion(source, &r);
   1001 		isc_buffer_setactive(source, r.length);
   1002 		result = getname(name, source, msg, dctx);
   1003 		if (result != ISC_R_SUCCESS) {
   1004 			goto cleanup;
   1005 		}
   1006 
   1007 		/*
   1008 		 * Run through the section, looking to see if this name
   1009 		 * is already there.  If it is found, put back the allocated
   1010 		 * name since we no longer need it, and set our name pointer
   1011 		 * to point to the name we found.
   1012 		 */
   1013 		result = findname(&name2, name, section);
   1014 
   1015 		/*
   1016 		 * If it is the first name in the section, accept it.
   1017 		 *
   1018 		 * If it is not, but is not the same as the name already
   1019 		 * in the question section, append to the section.  Note that
   1020 		 * here in the question section this is illegal, so return
   1021 		 * FORMERR.  In the future, check the opcode to see if
   1022 		 * this should be legal or not.  In either case we no longer
   1023 		 * need this name pointer.
   1024 		 */
   1025 		if (result != ISC_R_SUCCESS) {
   1026 			if (!ISC_LIST_EMPTY(*section)) {
   1027 				DO_ERROR(DNS_R_FORMERR);
   1028 			}
   1029 			ISC_LIST_APPEND(*section, name, link);
   1030 			free_name = false;
   1031 		} else {
   1032 			dns_message_puttempname(msg, &name);
   1033 			name = name2;
   1034 			name2 = NULL;
   1035 			free_name = false;
   1036 		}
   1037 
   1038 		/*
   1039 		 * Get type and class.
   1040 		 */
   1041 		isc_buffer_remainingregion(source, &r);
   1042 		if (r.length < 4) {
   1043 			result = ISC_R_UNEXPECTEDEND;
   1044 			goto cleanup;
   1045 		}
   1046 		rdtype = isc_buffer_getuint16(source);
   1047 		rdclass = isc_buffer_getuint16(source);
   1048 
   1049 		/*
   1050 		 * If this class is different than the one we already read,
   1051 		 * this is an error.
   1052 		 */
   1053 		if (msg->rdclass_set == 0) {
   1054 			msg->rdclass = rdclass;
   1055 			msg->rdclass_set = 1;
   1056 		} else if (msg->rdclass != rdclass) {
   1057 			DO_ERROR(DNS_R_FORMERR);
   1058 		}
   1059 
   1060 		/*
   1061 		 * Is this a TKEY query?
   1062 		 */
   1063 		if (rdtype == dns_rdatatype_tkey) {
   1064 			msg->tkey = 1;
   1065 		}
   1066 
   1067 		/*
   1068 		 * Can't ask the same question twice.
   1069 		 */
   1070 		result = dns_message_find(name, rdclass, rdtype, 0, NULL);
   1071 		if (result == ISC_R_SUCCESS) {
   1072 			DO_ERROR(DNS_R_FORMERR);
   1073 		}
   1074 
   1075 		/*
   1076 		 * Allocate a new rdatalist.
   1077 		 */
   1078 		rdatalist = newrdatalist(msg);
   1079 		if (rdatalist == NULL) {
   1080 			result = ISC_R_NOMEMORY;
   1081 			goto cleanup;
   1082 		}
   1083 		rdataset = isc_mempool_get(msg->rdspool);
   1084 		if (rdataset == NULL) {
   1085 			result = ISC_R_NOMEMORY;
   1086 			goto cleanup;
   1087 		}
   1088 
   1089 		/*
   1090 		 * Convert rdatalist to rdataset, and attach the latter to
   1091 		 * the name.
   1092 		 */
   1093 		rdatalist->type = rdtype;
   1094 		rdatalist->rdclass = rdclass;
   1095 
   1096 		dns_rdataset_init(rdataset);
   1097 		result = dns_rdatalist_tordataset(rdatalist, rdataset);
   1098 		if (result != ISC_R_SUCCESS) {
   1099 			goto cleanup;
   1100 		}
   1101 
   1102 		rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
   1103 
   1104 		ISC_LIST_APPEND(name->list, rdataset, link);
   1105 		rdataset = NULL;
   1106 	}
   1107 
   1108 	if (seen_problem) {
   1109 		return (DNS_R_RECOVERABLE);
   1110 	}
   1111 	return (ISC_R_SUCCESS);
   1112 
   1113 cleanup:
   1114 	if (rdataset != NULL) {
   1115 		INSIST(!dns_rdataset_isassociated(rdataset));
   1116 		isc_mempool_put(msg->rdspool, rdataset);
   1117 	}
   1118 	if (free_name) {
   1119 		dns_message_puttempname(msg, &name);
   1120 	}
   1121 
   1122 	return (result);
   1123 }
   1124 
   1125 static bool
   1126 update(dns_section_t section, dns_rdataclass_t rdclass) {
   1127 	if (section == DNS_SECTION_PREREQUISITE) {
   1128 		return (rdclass == dns_rdataclass_any ||
   1129 			rdclass == dns_rdataclass_none);
   1130 	}
   1131 	if (section == DNS_SECTION_UPDATE) {
   1132 		return (rdclass == dns_rdataclass_any);
   1133 	}
   1134 	return (false);
   1135 }
   1136 
   1137 /*
   1138  * Check to confirm that all DNSSEC records (DS, NSEC, NSEC3) have
   1139  * covering RRSIGs.
   1140  */
   1141 static bool
   1142 auth_signed(dns_namelist_t *section) {
   1143 	dns_name_t *name;
   1144 
   1145 	for (name = ISC_LIST_HEAD(*section); name != NULL;
   1146 	     name = ISC_LIST_NEXT(name, link))
   1147 	{
   1148 		int auth_dnssec = 0, auth_rrsig = 0;
   1149 		dns_rdataset_t *rds;
   1150 
   1151 		for (rds = ISC_LIST_HEAD(name->list); rds != NULL;
   1152 		     rds = ISC_LIST_NEXT(rds, link))
   1153 		{
   1154 			switch (rds->type) {
   1155 			case dns_rdatatype_ds:
   1156 				auth_dnssec |= 0x1;
   1157 				break;
   1158 			case dns_rdatatype_nsec:
   1159 				auth_dnssec |= 0x2;
   1160 				break;
   1161 			case dns_rdatatype_nsec3:
   1162 				auth_dnssec |= 0x4;
   1163 				break;
   1164 			case dns_rdatatype_rrsig:
   1165 				break;
   1166 			default:
   1167 				continue;
   1168 			}
   1169 
   1170 			switch (rds->covers) {
   1171 			case dns_rdatatype_ds:
   1172 				auth_rrsig |= 0x1;
   1173 				break;
   1174 			case dns_rdatatype_nsec:
   1175 				auth_rrsig |= 0x2;
   1176 				break;
   1177 			case dns_rdatatype_nsec3:
   1178 				auth_rrsig |= 0x4;
   1179 				break;
   1180 			default:
   1181 				break;
   1182 			}
   1183 		}
   1184 
   1185 		if (auth_dnssec != auth_rrsig) {
   1186 			return (false);
   1187 		}
   1188 	}
   1189 
   1190 	return (true);
   1191 }
   1192 
   1193 static isc_result_t
   1194 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
   1195 	   dns_section_t sectionid, unsigned int options) {
   1196 	isc_region_t r;
   1197 	unsigned int count, rdatalen;
   1198 	dns_name_t *name = NULL;
   1199 	dns_name_t *name2 = NULL;
   1200 	dns_rdataset_t *rdataset = NULL;
   1201 	dns_rdatalist_t *rdatalist = NULL;
   1202 	isc_result_t result;
   1203 	dns_rdatatype_t rdtype, covers;
   1204 	dns_rdataclass_t rdclass;
   1205 	dns_rdata_t *rdata = NULL;
   1206 	dns_ttl_t ttl;
   1207 	dns_namelist_t *section = &msg->sections[sectionid];
   1208 	bool free_name = false, free_rdataset = false, seen_problem = false;
   1209 	bool preserve_order = ((options & DNS_MESSAGEPARSE_PRESERVEORDER) != 0);
   1210 	bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0);
   1211 	bool isedns, issigzero, istsig;
   1212 
   1213 	for (count = 0; count < msg->counts[sectionid]; count++) {
   1214 		int recstart = source->current;
   1215 		bool skip_name_search, skip_type_search;
   1216 
   1217 		skip_name_search = false;
   1218 		skip_type_search = false;
   1219 		free_rdataset = false;
   1220 		isedns = false;
   1221 		issigzero = false;
   1222 		istsig = false;
   1223 
   1224 		name = NULL;
   1225 		result = dns_message_gettempname(msg, &name);
   1226 		if (result != ISC_R_SUCCESS) {
   1227 			goto cleanup;
   1228 		}
   1229 		name->offsets = (unsigned char *)newoffsets(msg);
   1230 		free_name = true;
   1231 
   1232 		/*
   1233 		 * Parse the name out of this packet.
   1234 		 */
   1235 		isc_buffer_remainingregion(source, &r);
   1236 		isc_buffer_setactive(source, r.length);
   1237 		result = getname(name, source, msg, dctx);
   1238 		if (result != ISC_R_SUCCESS) {
   1239 			goto cleanup;
   1240 		}
   1241 
   1242 		/*
   1243 		 * Get type, class, ttl, and rdatalen.  Verify that at least
   1244 		 * rdatalen bytes remain.  (Some of this is deferred to
   1245 		 * later.)
   1246 		 */
   1247 		isc_buffer_remainingregion(source, &r);
   1248 		if (r.length < 2 + 2 + 4 + 2) {
   1249 			result = ISC_R_UNEXPECTEDEND;
   1250 			goto cleanup;
   1251 		}
   1252 		rdtype = isc_buffer_getuint16(source);
   1253 		rdclass = isc_buffer_getuint16(source);
   1254 
   1255 		/*
   1256 		 * If there was no question section, we may not yet have
   1257 		 * established a class.  Do so now.
   1258 		 */
   1259 		if (msg->rdclass_set == 0 &&
   1260 		    rdtype != dns_rdatatype_opt &&  /* class is UDP SIZE */
   1261 		    rdtype != dns_rdatatype_tsig && /* class is ANY */
   1262 		    rdtype != dns_rdatatype_tkey)
   1263 		{ /* class is undefined */
   1264 			msg->rdclass = rdclass;
   1265 			msg->rdclass_set = 1;
   1266 		}
   1267 
   1268 		/*
   1269 		 * If this class is different than the one in the question
   1270 		 * section, bail.
   1271 		 */
   1272 		if (msg->opcode != dns_opcode_update &&
   1273 		    rdtype != dns_rdatatype_tsig &&
   1274 		    rdtype != dns_rdatatype_opt &&
   1275 		    rdtype != dns_rdatatype_key &&  /* in a TKEY query */
   1276 		    rdtype != dns_rdatatype_sig &&  /* SIG(0) */
   1277 		    rdtype != dns_rdatatype_tkey && /* Win2000 TKEY */
   1278 		    msg->rdclass != dns_rdataclass_any &&
   1279 		    msg->rdclass != rdclass)
   1280 		{
   1281 			DO_ERROR(DNS_R_FORMERR);
   1282 		}
   1283 
   1284 		/*
   1285 		 * If this is not a TKEY query/response then the KEY
   1286 		 * record's class needs to match.
   1287 		 */
   1288 		if (msg->opcode != dns_opcode_update && !msg->tkey &&
   1289 		    rdtype == dns_rdatatype_key &&
   1290 		    msg->rdclass != dns_rdataclass_any &&
   1291 		    msg->rdclass != rdclass)
   1292 		{
   1293 			DO_ERROR(DNS_R_FORMERR);
   1294 		}
   1295 
   1296 		/*
   1297 		 * Special type handling for TSIG, OPT, and TKEY.
   1298 		 */
   1299 		if (rdtype == dns_rdatatype_tsig) {
   1300 			/*
   1301 			 * If it is a tsig, verify that it is in the
   1302 			 * additional data section.
   1303 			 */
   1304 			if (sectionid != DNS_SECTION_ADDITIONAL ||
   1305 			    rdclass != dns_rdataclass_any ||
   1306 			    count != msg->counts[sectionid] - 1)
   1307 			{
   1308 				DO_ERROR(DNS_R_BADTSIG);
   1309 			} else {
   1310 				skip_name_search = true;
   1311 				skip_type_search = true;
   1312 				istsig = true;
   1313 			}
   1314 		} else if (rdtype == dns_rdatatype_opt) {
   1315 			/*
   1316 			 * The name of an OPT record must be ".", it
   1317 			 * must be in the additional data section, and
   1318 			 * it must be the first OPT we've seen.
   1319 			 */
   1320 			if (!dns_name_equal(dns_rootname, name) ||
   1321 			    sectionid != DNS_SECTION_ADDITIONAL ||
   1322 			    msg->opt != NULL)
   1323 			{
   1324 				DO_ERROR(DNS_R_FORMERR);
   1325 			} else {
   1326 				skip_name_search = true;
   1327 				skip_type_search = true;
   1328 				isedns = true;
   1329 			}
   1330 		} else if (rdtype == dns_rdatatype_tkey) {
   1331 			/*
   1332 			 * A TKEY must be in the additional section if this
   1333 			 * is a query, and the answer section if this is a
   1334 			 * response.  Unless it's a Win2000 client.
   1335 			 *
   1336 			 * Its class is ignored.
   1337 			 */
   1338 			dns_section_t tkeysection;
   1339 
   1340 			if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0) {
   1341 				tkeysection = DNS_SECTION_ADDITIONAL;
   1342 			} else {
   1343 				tkeysection = DNS_SECTION_ANSWER;
   1344 			}
   1345 			if (sectionid != tkeysection &&
   1346 			    sectionid != DNS_SECTION_ANSWER)
   1347 			{
   1348 				DO_ERROR(DNS_R_FORMERR);
   1349 			}
   1350 		}
   1351 
   1352 		/*
   1353 		 * ... now get ttl and rdatalen, and check buffer.
   1354 		 */
   1355 		ttl = isc_buffer_getuint32(source);
   1356 		rdatalen = isc_buffer_getuint16(source);
   1357 		r.length -= (2 + 2 + 4 + 2);
   1358 		if (r.length < rdatalen) {
   1359 			result = ISC_R_UNEXPECTEDEND;
   1360 			goto cleanup;
   1361 		}
   1362 
   1363 		/*
   1364 		 * Read the rdata from the wire format.  Interpret the
   1365 		 * rdata according to its actual class, even if it had a
   1366 		 * DynDNS meta-class in the packet (unless this is a TSIG).
   1367 		 * Then put the meta-class back into the finished rdata.
   1368 		 */
   1369 		rdata = newrdata(msg);
   1370 		if (rdata == NULL) {
   1371 			result = ISC_R_NOMEMORY;
   1372 			goto cleanup;
   1373 		}
   1374 		if (msg->opcode == dns_opcode_update &&
   1375 		    update(sectionid, rdclass))
   1376 		{
   1377 			if (rdatalen != 0) {
   1378 				result = DNS_R_FORMERR;
   1379 				goto cleanup;
   1380 			}
   1381 			/*
   1382 			 * When the rdata is empty, the data pointer is
   1383 			 * never dereferenced, but it must still be non-NULL.
   1384 			 * Casting 1 rather than "" avoids warnings about
   1385 			 * discarding the const attribute of a string,
   1386 			 * for compilers that would warn about such things.
   1387 			 */
   1388 			rdata->data = (unsigned char *)1;
   1389 			rdata->length = 0;
   1390 			rdata->rdclass = rdclass;
   1391 			rdata->type = rdtype;
   1392 			rdata->flags = DNS_RDATA_UPDATE;
   1393 			result = ISC_R_SUCCESS;
   1394 		} else if (rdclass == dns_rdataclass_none &&
   1395 			   msg->opcode == dns_opcode_update &&
   1396 			   sectionid == DNS_SECTION_UPDATE)
   1397 		{
   1398 			result = getrdata(source, msg, dctx, msg->rdclass,
   1399 					  rdtype, rdatalen, rdata);
   1400 		} else {
   1401 			result = getrdata(source, msg, dctx, rdclass, rdtype,
   1402 					  rdatalen, rdata);
   1403 		}
   1404 		if (result != ISC_R_SUCCESS) {
   1405 			goto cleanup;
   1406 		}
   1407 		rdata->rdclass = rdclass;
   1408 		if (rdtype == dns_rdatatype_rrsig && rdata->flags == 0) {
   1409 			covers = dns_rdata_covers(rdata);
   1410 			if (covers == 0) {
   1411 				DO_ERROR(DNS_R_FORMERR);
   1412 			}
   1413 		} else if (rdtype == dns_rdatatype_sig /* SIG(0) */ &&
   1414 			   rdata->flags == 0)
   1415 		{
   1416 			covers = dns_rdata_covers(rdata);
   1417 			if (covers == 0) {
   1418 				if (sectionid != DNS_SECTION_ADDITIONAL ||
   1419 				    count != msg->counts[sectionid] - 1)
   1420 				{
   1421 					DO_ERROR(DNS_R_BADSIG0);
   1422 				} else {
   1423 					skip_name_search = true;
   1424 					skip_type_search = true;
   1425 					issigzero = true;
   1426 				}
   1427 			} else {
   1428 				if (msg->rdclass != dns_rdataclass_any &&
   1429 				    msg->rdclass != rdclass)
   1430 				{
   1431 					DO_ERROR(DNS_R_FORMERR);
   1432 				}
   1433 			}
   1434 		} else {
   1435 			covers = 0;
   1436 		}
   1437 
   1438 		/*
   1439 		 * Check the ownername of NSEC3 records
   1440 		 */
   1441 		if (rdtype == dns_rdatatype_nsec3 &&
   1442 		    !dns_rdata_checkowner(name, msg->rdclass, rdtype, false))
   1443 		{
   1444 			result = DNS_R_BADOWNERNAME;
   1445 			goto cleanup;
   1446 		}
   1447 
   1448 		/*
   1449 		 * If we are doing a dynamic update or this is a meta-type,
   1450 		 * don't bother searching for a name, just append this one
   1451 		 * to the end of the message.
   1452 		 */
   1453 		if (preserve_order || msg->opcode == dns_opcode_update ||
   1454 		    skip_name_search)
   1455 		{
   1456 			if (!isedns && !istsig && !issigzero) {
   1457 				ISC_LIST_APPEND(*section, name, link);
   1458 				free_name = false;
   1459 			}
   1460 		} else {
   1461 			/*
   1462 			 * Run through the section, looking to see if this name
   1463 			 * is already there.  If it is found, put back the
   1464 			 * allocated name since we no longer need it, and set
   1465 			 * our name pointer to point to the name we found.
   1466 			 */
   1467 			result = findname(&name2, name, section);
   1468 
   1469 			/*
   1470 			 * If it is a new name, append to the section.
   1471 			 */
   1472 			if (result == ISC_R_SUCCESS) {
   1473 				dns_message_puttempname(msg, &name);
   1474 				name = name2;
   1475 			} else {
   1476 				ISC_LIST_APPEND(*section, name, link);
   1477 			}
   1478 			free_name = false;
   1479 		}
   1480 
   1481 		/*
   1482 		 * Search name for the particular type and class.
   1483 		 * Skip this stage if in update mode or this is a meta-type.
   1484 		 */
   1485 		if (preserve_order || msg->opcode == dns_opcode_update ||
   1486 		    skip_type_search)
   1487 		{
   1488 			result = ISC_R_NOTFOUND;
   1489 		} else {
   1490 			/*
   1491 			 * If this is a type that can only occur in
   1492 			 * the question section, fail.
   1493 			 */
   1494 			if (dns_rdatatype_questiononly(rdtype)) {
   1495 				DO_ERROR(DNS_R_FORMERR);
   1496 			}
   1497 
   1498 			rdataset = NULL;
   1499 			result = dns_message_find(name, rdclass, rdtype, covers,
   1500 						  &rdataset);
   1501 		}
   1502 
   1503 		/*
   1504 		 * If we found an rdataset that matches, we need to
   1505 		 * append this rdata to that set.  If we did not, we need
   1506 		 * to create a new rdatalist, store the important bits there,
   1507 		 * convert it to an rdataset, and link the latter to the name.
   1508 		 * Yuck.  When appending, make certain that the type isn't
   1509 		 * a singleton type, such as SOA or CNAME.
   1510 		 *
   1511 		 * Note that this check will be bypassed when preserving order,
   1512 		 * the opcode is an update, or the type search is skipped.
   1513 		 */
   1514 		if (result == ISC_R_SUCCESS) {
   1515 			if (dns_rdatatype_issingleton(rdtype)) {
   1516 				dns_rdata_t *first;
   1517 				dns_rdatalist_fromrdataset(rdataset,
   1518 							   &rdatalist);
   1519 				first = ISC_LIST_HEAD(rdatalist->rdata);
   1520 				INSIST(first != NULL);
   1521 				if (dns_rdata_compare(rdata, first) != 0) {
   1522 					DO_ERROR(DNS_R_FORMERR);
   1523 				}
   1524 			}
   1525 		}
   1526 
   1527 		if (result == ISC_R_NOTFOUND) {
   1528 			rdataset = isc_mempool_get(msg->rdspool);
   1529 			if (rdataset == NULL) {
   1530 				result = ISC_R_NOMEMORY;
   1531 				goto cleanup;
   1532 			}
   1533 			free_rdataset = true;
   1534 
   1535 			rdatalist = newrdatalist(msg);
   1536 			if (rdatalist == NULL) {
   1537 				result = ISC_R_NOMEMORY;
   1538 				goto cleanup;
   1539 			}
   1540 
   1541 			rdatalist->type = rdtype;
   1542 			rdatalist->covers = covers;
   1543 			rdatalist->rdclass = rdclass;
   1544 			rdatalist->ttl = ttl;
   1545 
   1546 			dns_rdataset_init(rdataset);
   1547 			RUNTIME_CHECK(
   1548 				dns_rdatalist_tordataset(rdatalist, rdataset) ==
   1549 				ISC_R_SUCCESS);
   1550 			dns_rdataset_setownercase(rdataset, name);
   1551 
   1552 			if (!isedns && !istsig && !issigzero) {
   1553 				ISC_LIST_APPEND(name->list, rdataset, link);
   1554 				free_rdataset = false;
   1555 			}
   1556 		}
   1557 
   1558 		/*
   1559 		 * Minimize TTLs.
   1560 		 *
   1561 		 * Section 5.2 of RFC2181 says we should drop
   1562 		 * nonauthoritative rrsets where the TTLs differ, but we
   1563 		 * currently treat them the as if they were authoritative and
   1564 		 * minimize them.
   1565 		 */
   1566 		if (ttl != rdataset->ttl) {
   1567 			rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
   1568 			if (ttl < rdataset->ttl) {
   1569 				rdataset->ttl = ttl;
   1570 			}
   1571 		}
   1572 
   1573 		/* Append this rdata to the rdataset. */
   1574 		dns_rdatalist_fromrdataset(rdataset, &rdatalist);
   1575 		ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
   1576 
   1577 		/*
   1578 		 * If this is an OPT, SIG(0) or TSIG record, remember it.
   1579 		 * Also, set the extended rcode for TSIG.
   1580 		 *
   1581 		 * Note msg->opt, msg->sig0 and msg->tsig will only be
   1582 		 * already set if best-effort parsing is enabled otherwise
   1583 		 * there will only be at most one of each.
   1584 		 */
   1585 		if (isedns) {
   1586 			dns_rcode_t ercode;
   1587 
   1588 			msg->opt = rdataset;
   1589 			rdataset = NULL;
   1590 			free_rdataset = false;
   1591 			ercode = (dns_rcode_t)((msg->opt->ttl &
   1592 						DNS_MESSAGE_EDNSRCODE_MASK) >>
   1593 					       20);
   1594 			msg->rcode |= ercode;
   1595 			dns_message_puttempname(msg, &name);
   1596 			free_name = false;
   1597 		} else if (issigzero) {
   1598 			msg->sig0 = rdataset;
   1599 			msg->sig0name = name;
   1600 			msg->sigstart = recstart;
   1601 			rdataset = NULL;
   1602 			free_rdataset = false;
   1603 			free_name = false;
   1604 		} else if (istsig) {
   1605 			msg->tsig = rdataset;
   1606 			msg->tsigname = name;
   1607 			msg->sigstart = recstart;
   1608 			/*
   1609 			 * Windows doesn't like TSIG names to be compressed.
   1610 			 */
   1611 			msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
   1612 			rdataset = NULL;
   1613 			free_rdataset = false;
   1614 			free_name = false;
   1615 		}
   1616 
   1617 		if (seen_problem) {
   1618 			if (free_name) {
   1619 				dns_message_puttempname(msg, &name);
   1620 			}
   1621 			if (free_rdataset) {
   1622 				isc_mempool_put(msg->rdspool, rdataset);
   1623 			}
   1624 			free_name = free_rdataset = false;
   1625 		}
   1626 		INSIST(!free_name);
   1627 		INSIST(!free_rdataset);
   1628 	}
   1629 
   1630 	/*
   1631 	 * If any of DS, NSEC or NSEC3 appeared in the
   1632 	 * authority section of a query response without
   1633 	 * a covering RRSIG, FORMERR
   1634 	 */
   1635 	if (sectionid == DNS_SECTION_AUTHORITY &&
   1636 	    msg->opcode == dns_opcode_query &&
   1637 	    ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) &&
   1638 	    ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) && !preserve_order &&
   1639 	    !auth_signed(section))
   1640 	{
   1641 		DO_ERROR(DNS_R_FORMERR);
   1642 	}
   1643 
   1644 	if (seen_problem) {
   1645 		return (DNS_R_RECOVERABLE);
   1646 	}
   1647 	return (ISC_R_SUCCESS);
   1648 
   1649 cleanup:
   1650 	if (free_name) {
   1651 		dns_message_puttempname(msg, &name);
   1652 	}
   1653 	if (free_rdataset) {
   1654 		isc_mempool_put(msg->rdspool, rdataset);
   1655 	}
   1656 
   1657 	return (result);
   1658 }
   1659 
   1660 isc_result_t
   1661 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
   1662 		  unsigned int options) {
   1663 	isc_region_t r;
   1664 	dns_decompress_t dctx;
   1665 	isc_result_t ret;
   1666 	uint16_t tmpflags;
   1667 	isc_buffer_t origsource;
   1668 	bool seen_problem;
   1669 	bool ignore_tc;
   1670 
   1671 	REQUIRE(DNS_MESSAGE_VALID(msg));
   1672 	REQUIRE(source != NULL);
   1673 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
   1674 
   1675 	seen_problem = false;
   1676 	ignore_tc = ((options & DNS_MESSAGEPARSE_IGNORETRUNCATION) != 0);
   1677 
   1678 	origsource = *source;
   1679 
   1680 	msg->header_ok = 0;
   1681 	msg->question_ok = 0;
   1682 
   1683 	if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) {
   1684 		isc_buffer_usedregion(&origsource, &msg->saved);
   1685 	} else {
   1686 		msg->saved.length = isc_buffer_usedlength(&origsource);
   1687 		msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
   1688 		memmove(msg->saved.base, isc_buffer_base(&origsource),
   1689 			msg->saved.length);
   1690 		msg->free_saved = 1;
   1691 	}
   1692 
   1693 	isc_buffer_remainingregion(source, &r);
   1694 	if (r.length < DNS_MESSAGE_HEADERLEN) {
   1695 		return (ISC_R_UNEXPECTEDEND);
   1696 	}
   1697 
   1698 	msg->id = isc_buffer_getuint16(source);
   1699 	tmpflags = isc_buffer_getuint16(source);
   1700 	msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) >>
   1701 		       DNS_MESSAGE_OPCODE_SHIFT);
   1702 	msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
   1703 	msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
   1704 	msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
   1705 	msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
   1706 	msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
   1707 	msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
   1708 
   1709 	msg->header_ok = 1;
   1710 	msg->state = DNS_SECTION_QUESTION;
   1711 
   1712 	/*
   1713 	 * -1 means no EDNS.
   1714 	 */
   1715 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
   1716 
   1717 	dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
   1718 
   1719 	ret = getquestions(source, msg, &dctx, options);
   1720 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
   1721 		goto truncated;
   1722 	}
   1723 	if (ret == DNS_R_RECOVERABLE) {
   1724 		seen_problem = true;
   1725 		ret = ISC_R_SUCCESS;
   1726 	}
   1727 	if (ret != ISC_R_SUCCESS) {
   1728 		return (ret);
   1729 	}
   1730 	msg->question_ok = 1;
   1731 
   1732 	ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
   1733 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
   1734 		goto truncated;
   1735 	}
   1736 	if (ret == DNS_R_RECOVERABLE) {
   1737 		seen_problem = true;
   1738 		ret = ISC_R_SUCCESS;
   1739 	}
   1740 	if (ret != ISC_R_SUCCESS) {
   1741 		return (ret);
   1742 	}
   1743 
   1744 	ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
   1745 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
   1746 		goto truncated;
   1747 	}
   1748 	if (ret == DNS_R_RECOVERABLE) {
   1749 		seen_problem = true;
   1750 		ret = ISC_R_SUCCESS;
   1751 	}
   1752 	if (ret != ISC_R_SUCCESS) {
   1753 		return (ret);
   1754 	}
   1755 
   1756 	ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
   1757 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
   1758 		goto truncated;
   1759 	}
   1760 	if (ret == DNS_R_RECOVERABLE) {
   1761 		seen_problem = true;
   1762 		ret = ISC_R_SUCCESS;
   1763 	}
   1764 	if (ret != ISC_R_SUCCESS) {
   1765 		return (ret);
   1766 	}
   1767 
   1768 	isc_buffer_remainingregion(source, &r);
   1769 	if (r.length != 0) {
   1770 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
   1771 			      DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
   1772 			      "message has %u byte(s) of trailing garbage",
   1773 			      r.length);
   1774 	}
   1775 
   1776 truncated:
   1777 
   1778 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) {
   1779 		return (DNS_R_RECOVERABLE);
   1780 	}
   1781 	if (seen_problem) {
   1782 		return (DNS_R_RECOVERABLE);
   1783 	}
   1784 	return (ISC_R_SUCCESS);
   1785 }
   1786 
   1787 isc_result_t
   1788 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
   1789 			isc_buffer_t *buffer) {
   1790 	isc_region_t r;
   1791 
   1792 	REQUIRE(DNS_MESSAGE_VALID(msg));
   1793 	REQUIRE(buffer != NULL);
   1794 	REQUIRE(msg->buffer == NULL);
   1795 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
   1796 
   1797 	msg->cctx = cctx;
   1798 
   1799 	/*
   1800 	 * Erase the contents of this buffer.
   1801 	 */
   1802 	isc_buffer_clear(buffer);
   1803 
   1804 	/*
   1805 	 * Make certain there is enough for at least the header in this
   1806 	 * buffer.
   1807 	 */
   1808 	isc_buffer_availableregion(buffer, &r);
   1809 	if (r.length < DNS_MESSAGE_HEADERLEN) {
   1810 		return (ISC_R_NOSPACE);
   1811 	}
   1812 
   1813 	if (r.length - DNS_MESSAGE_HEADERLEN < msg->reserved) {
   1814 		return (ISC_R_NOSPACE);
   1815 	}
   1816 
   1817 	/*
   1818 	 * Reserve enough space for the header in this buffer.
   1819 	 */
   1820 	isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
   1821 
   1822 	msg->buffer = buffer;
   1823 
   1824 	return (ISC_R_SUCCESS);
   1825 }
   1826 
   1827 isc_result_t
   1828 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
   1829 	isc_region_t r, rn;
   1830 
   1831 	REQUIRE(DNS_MESSAGE_VALID(msg));
   1832 	REQUIRE(buffer != NULL);
   1833 	REQUIRE(msg->buffer != NULL);
   1834 
   1835 	/*
   1836 	 * Ensure that the new buffer is empty, and has enough space to
   1837 	 * hold the current contents.
   1838 	 */
   1839 	isc_buffer_clear(buffer);
   1840 
   1841 	isc_buffer_availableregion(buffer, &rn);
   1842 	isc_buffer_usedregion(msg->buffer, &r);
   1843 	REQUIRE(rn.length > r.length);
   1844 
   1845 	/*
   1846 	 * Copy the contents from the old to the new buffer.
   1847 	 */
   1848 	isc_buffer_add(buffer, r.length);
   1849 	memmove(rn.base, r.base, r.length);
   1850 
   1851 	msg->buffer = buffer;
   1852 
   1853 	return (ISC_R_SUCCESS);
   1854 }
   1855 
   1856 void
   1857 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
   1858 	REQUIRE(DNS_MESSAGE_VALID(msg));
   1859 	REQUIRE(space <= msg->reserved);
   1860 
   1861 	msg->reserved -= space;
   1862 }
   1863 
   1864 isc_result_t
   1865 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
   1866 	isc_region_t r;
   1867 
   1868 	REQUIRE(DNS_MESSAGE_VALID(msg));
   1869 
   1870 	if (msg->buffer != NULL) {
   1871 		isc_buffer_availableregion(msg->buffer, &r);
   1872 		if (r.length < (space + msg->reserved)) {
   1873 			return (ISC_R_NOSPACE);
   1874 		}
   1875 	}
   1876 
   1877 	msg->reserved += space;
   1878 
   1879 	return (ISC_R_SUCCESS);
   1880 }
   1881 
   1882 static bool
   1883 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
   1884 	int pass_needed;
   1885 
   1886 	/*
   1887 	 * If we are not rendering class IN, this ordering is bogus.
   1888 	 */
   1889 	if (rds->rdclass != dns_rdataclass_in) {
   1890 		return (false);
   1891 	}
   1892 
   1893 	switch (rds->type) {
   1894 	case dns_rdatatype_a:
   1895 	case dns_rdatatype_aaaa:
   1896 		if (preferred_glue == rds->type) {
   1897 			pass_needed = 4;
   1898 		} else {
   1899 			pass_needed = 3;
   1900 		}
   1901 		break;
   1902 	case dns_rdatatype_rrsig:
   1903 	case dns_rdatatype_dnskey:
   1904 		pass_needed = 2;
   1905 		break;
   1906 	default:
   1907 		pass_needed = 1;
   1908 	}
   1909 
   1910 	if (pass_needed >= pass) {
   1911 		return (false);
   1912 	}
   1913 
   1914 	return (true);
   1915 }
   1916 
   1917 static isc_result_t
   1918 renderset(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
   1919 	  dns_compress_t *cctx, isc_buffer_t *target, unsigned int reserved,
   1920 	  unsigned int options, unsigned int *countp) {
   1921 	isc_result_t result;
   1922 
   1923 	/*
   1924 	 * Shrink the space in the buffer by the reserved amount.
   1925 	 */
   1926 	if (target->length - target->used < reserved) {
   1927 		return (ISC_R_NOSPACE);
   1928 	}
   1929 
   1930 	target->length -= reserved;
   1931 	result = dns_rdataset_towire(rdataset, owner_name, cctx, target,
   1932 				     options, countp);
   1933 	target->length += reserved;
   1934 
   1935 	return (result);
   1936 }
   1937 
   1938 static void
   1939 maybe_clear_ad(dns_message_t *msg, dns_section_t sectionid) {
   1940 	if (msg->counts[sectionid] == 0 &&
   1941 	    (sectionid == DNS_SECTION_ANSWER ||
   1942 	     (sectionid == DNS_SECTION_AUTHORITY &&
   1943 	      msg->counts[DNS_SECTION_ANSWER] == 0)))
   1944 	{
   1945 		msg->flags &= ~DNS_MESSAGEFLAG_AD;
   1946 	}
   1947 }
   1948 
   1949 isc_result_t
   1950 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
   1951 			  unsigned int options) {
   1952 	dns_namelist_t *section;
   1953 	dns_name_t *name, *next_name;
   1954 	dns_rdataset_t *rdataset, *next_rdataset;
   1955 	unsigned int count, total;
   1956 	isc_result_t result;
   1957 	isc_buffer_t st; /* for rollbacks */
   1958 	int pass;
   1959 	bool partial = false;
   1960 	unsigned int rd_options;
   1961 	dns_rdatatype_t preferred_glue = 0;
   1962 
   1963 	REQUIRE(DNS_MESSAGE_VALID(msg));
   1964 	REQUIRE(msg->buffer != NULL);
   1965 	REQUIRE(VALID_NAMED_SECTION(sectionid));
   1966 
   1967 	section = &msg->sections[sectionid];
   1968 
   1969 	if ((sectionid == DNS_SECTION_ADDITIONAL) &&
   1970 	    (options & DNS_MESSAGERENDER_ORDERED) == 0)
   1971 	{
   1972 		if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
   1973 			preferred_glue = dns_rdatatype_a;
   1974 			pass = 4;
   1975 		} else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
   1976 			preferred_glue = dns_rdatatype_aaaa;
   1977 			pass = 4;
   1978 		} else {
   1979 			pass = 3;
   1980 		}
   1981 	} else {
   1982 		pass = 1;
   1983 	}
   1984 
   1985 	if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) {
   1986 		rd_options = 0;
   1987 	} else {
   1988 		rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
   1989 	}
   1990 
   1991 	/*
   1992 	 * Shrink the space in the buffer by the reserved amount.
   1993 	 */
   1994 	if (msg->buffer->length - msg->buffer->used < msg->reserved) {
   1995 		return (ISC_R_NOSPACE);
   1996 	}
   1997 	msg->buffer->length -= msg->reserved;
   1998 
   1999 	total = 0;
   2000 	if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) {
   2001 		partial = true;
   2002 	}
   2003 
   2004 	/*
   2005 	 * Render required glue first.  Set TC if it won't fit.
   2006 	 */
   2007 	name = ISC_LIST_HEAD(*section);
   2008 	if (name != NULL) {
   2009 		rdataset = ISC_LIST_HEAD(name->list);
   2010 		if (rdataset != NULL &&
   2011 		    (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) !=
   2012 			    0 &&
   2013 		    (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0)
   2014 		{
   2015 			const void *order_arg = &msg->order_arg;
   2016 			st = *(msg->buffer);
   2017 			count = 0;
   2018 			if (partial) {
   2019 				result = dns_rdataset_towirepartial(
   2020 					rdataset, name, msg->cctx, msg->buffer,
   2021 					msg->order, order_arg, rd_options,
   2022 					&count, NULL);
   2023 			} else {
   2024 				result = dns_rdataset_towiresorted(
   2025 					rdataset, name, msg->cctx, msg->buffer,
   2026 					msg->order, order_arg, rd_options,
   2027 					&count);
   2028 			}
   2029 			total += count;
   2030 			if (partial && result == ISC_R_NOSPACE) {
   2031 				msg->flags |= DNS_MESSAGEFLAG_TC;
   2032 				msg->buffer->length += msg->reserved;
   2033 				msg->counts[sectionid] += total;
   2034 				return (result);
   2035 			}
   2036 			if (result == ISC_R_NOSPACE) {
   2037 				msg->flags |= DNS_MESSAGEFLAG_TC;
   2038 			}
   2039 			if (result != ISC_R_SUCCESS) {
   2040 				INSIST(st.used < 65536);
   2041 				dns_compress_rollback(msg->cctx,
   2042 						      (uint16_t)st.used);
   2043 				*(msg->buffer) = st; /* rollback */
   2044 				msg->buffer->length += msg->reserved;
   2045 				msg->counts[sectionid] += total;
   2046 				return (result);
   2047 			}
   2048 			rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
   2049 		}
   2050 	}
   2051 
   2052 	do {
   2053 		name = ISC_LIST_HEAD(*section);
   2054 		if (name == NULL) {
   2055 			msg->buffer->length += msg->reserved;
   2056 			msg->counts[sectionid] += total;
   2057 			return (ISC_R_SUCCESS);
   2058 		}
   2059 
   2060 		while (name != NULL) {
   2061 			next_name = ISC_LIST_NEXT(name, link);
   2062 
   2063 			rdataset = ISC_LIST_HEAD(name->list);
   2064 			while (rdataset != NULL) {
   2065 				next_rdataset = ISC_LIST_NEXT(rdataset, link);
   2066 
   2067 				if ((rdataset->attributes &
   2068 				     DNS_RDATASETATTR_RENDERED) != 0)
   2069 				{
   2070 					goto next;
   2071 				}
   2072 
   2073 				if (((options & DNS_MESSAGERENDER_ORDERED) ==
   2074 				     0) &&
   2075 				    (sectionid == DNS_SECTION_ADDITIONAL) &&
   2076 				    wrong_priority(rdataset, pass,
   2077 						   preferred_glue))
   2078 				{
   2079 					goto next;
   2080 				}
   2081 
   2082 				st = *(msg->buffer);
   2083 
   2084 				count = 0;
   2085 				if (partial) {
   2086 					result = dns_rdataset_towirepartial(
   2087 						rdataset, name, msg->cctx,
   2088 						msg->buffer, msg->order,
   2089 						&msg->order_arg, rd_options,
   2090 						&count, NULL);
   2091 				} else {
   2092 					result = dns_rdataset_towiresorted(
   2093 						rdataset, name, msg->cctx,
   2094 						msg->buffer, msg->order,
   2095 						&msg->order_arg, rd_options,
   2096 						&count);
   2097 				}
   2098 
   2099 				total += count;
   2100 
   2101 				/*
   2102 				 * If out of space, record stats on what we
   2103 				 * rendered so far, and return that status.
   2104 				 *
   2105 				 * XXXMLG Need to change this when
   2106 				 * dns_rdataset_towire() can render partial
   2107 				 * sets starting at some arbitrary point in the
   2108 				 * set.  This will include setting a bit in the
   2109 				 * rdataset to indicate that a partial
   2110 				 * rendering was done, and some state saved
   2111 				 * somewhere (probably in the message struct)
   2112 				 * to indicate where to continue from.
   2113 				 */
   2114 				if (partial && result == ISC_R_NOSPACE) {
   2115 					msg->buffer->length += msg->reserved;
   2116 					msg->counts[sectionid] += total;
   2117 					return (result);
   2118 				}
   2119 				if (result != ISC_R_SUCCESS) {
   2120 					INSIST(st.used < 65536);
   2121 					dns_compress_rollback(
   2122 						msg->cctx, (uint16_t)st.used);
   2123 					*(msg->buffer) = st; /* rollback */
   2124 					msg->buffer->length += msg->reserved;
   2125 					msg->counts[sectionid] += total;
   2126 					maybe_clear_ad(msg, sectionid);
   2127 					return (result);
   2128 				}
   2129 
   2130 				/*
   2131 				 * If we have rendered non-validated data,
   2132 				 * ensure that the AD bit is not set.
   2133 				 */
   2134 				if (rdataset->trust != dns_trust_secure &&
   2135 				    (sectionid == DNS_SECTION_ANSWER ||
   2136 				     sectionid == DNS_SECTION_AUTHORITY))
   2137 				{
   2138 					msg->flags &= ~DNS_MESSAGEFLAG_AD;
   2139 				}
   2140 				if (OPTOUT(rdataset)) {
   2141 					msg->flags &= ~DNS_MESSAGEFLAG_AD;
   2142 				}
   2143 
   2144 				rdataset->attributes |=
   2145 					DNS_RDATASETATTR_RENDERED;
   2146 
   2147 			next:
   2148 				rdataset = next_rdataset;
   2149 			}
   2150 
   2151 			name = next_name;
   2152 		}
   2153 	} while (--pass != 0);
   2154 
   2155 	msg->buffer->length += msg->reserved;
   2156 	msg->counts[sectionid] += total;
   2157 
   2158 	return (ISC_R_SUCCESS);
   2159 }
   2160 
   2161 void
   2162 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
   2163 	uint16_t tmp;
   2164 	isc_region_t r;
   2165 
   2166 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2167 	REQUIRE(target != NULL);
   2168 
   2169 	isc_buffer_availableregion(target, &r);
   2170 	REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
   2171 
   2172 	isc_buffer_putuint16(target, msg->id);
   2173 
   2174 	tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) &
   2175 	       DNS_MESSAGE_OPCODE_MASK);
   2176 	tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
   2177 	tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
   2178 
   2179 	INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
   2180 	       msg->counts[DNS_SECTION_ANSWER] < 65536 &&
   2181 	       msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
   2182 	       msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
   2183 
   2184 	isc_buffer_putuint16(target, tmp);
   2185 	isc_buffer_putuint16(target,
   2186 			     (uint16_t)msg->counts[DNS_SECTION_QUESTION]);
   2187 	isc_buffer_putuint16(target, (uint16_t)msg->counts[DNS_SECTION_ANSWER]);
   2188 	isc_buffer_putuint16(target,
   2189 			     (uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
   2190 	isc_buffer_putuint16(target,
   2191 			     (uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
   2192 }
   2193 
   2194 isc_result_t
   2195 dns_message_renderend(dns_message_t *msg) {
   2196 	isc_buffer_t tmpbuf;
   2197 	isc_region_t r;
   2198 	int result;
   2199 	unsigned int count;
   2200 
   2201 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2202 	REQUIRE(msg->buffer != NULL);
   2203 
   2204 	if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
   2205 		/*
   2206 		 * We have an extended rcode but are not using EDNS.
   2207 		 */
   2208 		return (DNS_R_FORMERR);
   2209 	}
   2210 
   2211 	/*
   2212 	 * If we're adding a OPT, TSIG or SIG(0) to a truncated message,
   2213 	 * clear all rdatasets from the message except for the question
   2214 	 * before adding the OPT, TSIG or SIG(0).  If the question doesn't
   2215 	 * fit, don't include it.
   2216 	 */
   2217 	if ((msg->tsigkey != NULL || msg->sig0key != NULL || msg->opt) &&
   2218 	    (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
   2219 	{
   2220 		isc_buffer_t *buf;
   2221 
   2222 		msgresetnames(msg, DNS_SECTION_ANSWER);
   2223 		buf = msg->buffer;
   2224 		dns_message_renderreset(msg);
   2225 		msg->buffer = buf;
   2226 		isc_buffer_clear(msg->buffer);
   2227 		isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
   2228 		dns_compress_rollback(msg->cctx, 0);
   2229 		result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
   2230 						   0);
   2231 		if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) {
   2232 			return (result);
   2233 		}
   2234 	}
   2235 
   2236 	/*
   2237 	 * If we've got an OPT record, render it.
   2238 	 */
   2239 	if (msg->opt != NULL) {
   2240 		dns_message_renderrelease(msg, msg->opt_reserved);
   2241 		msg->opt_reserved = 0;
   2242 		/*
   2243 		 * Set the extended rcode.  Cast msg->rcode to dns_ttl_t
   2244 		 * so that we do a unsigned shift.
   2245 		 */
   2246 		msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
   2247 		msg->opt->ttl |= (((dns_ttl_t)(msg->rcode) << 20) &
   2248 				  DNS_MESSAGE_EDNSRCODE_MASK);
   2249 		/*
   2250 		 * Render.
   2251 		 */
   2252 		count = 0;
   2253 		result = renderset(msg->opt, dns_rootname, msg->cctx,
   2254 				   msg->buffer, msg->reserved, 0, &count);
   2255 		msg->counts[DNS_SECTION_ADDITIONAL] += count;
   2256 		if (result != ISC_R_SUCCESS) {
   2257 			return (result);
   2258 		}
   2259 	}
   2260 
   2261 	/*
   2262 	 * Deal with EDNS padding.
   2263 	 *
   2264 	 * padding_off is the length of the OPT with the 0-length PAD
   2265 	 * at the end.
   2266 	 */
   2267 	if (msg->padding_off > 0) {
   2268 		unsigned char *cp = isc_buffer_used(msg->buffer);
   2269 		unsigned int used, remaining;
   2270 		uint16_t len, padsize = 0;
   2271 
   2272 		/* Check PAD */
   2273 		if ((cp[-4] != 0) || (cp[-3] != DNS_OPT_PAD) || (cp[-2] != 0) ||
   2274 		    (cp[-1] != 0))
   2275 		{
   2276 			return (ISC_R_UNEXPECTED);
   2277 		}
   2278 
   2279 		/*
   2280 		 * Zero-fill the PAD to the computed size;
   2281 		 * patch PAD length and OPT rdlength
   2282 		 */
   2283 
   2284 		/* Aligned used length + reserved to padding block */
   2285 		used = isc_buffer_usedlength(msg->buffer);
   2286 		if (msg->padding != 0) {
   2287 			padsize = ((uint16_t)used + msg->reserved) %
   2288 				  msg->padding;
   2289 		}
   2290 		if (padsize != 0) {
   2291 			padsize = msg->padding - padsize;
   2292 		}
   2293 		/* Stay below the available length */
   2294 		remaining = isc_buffer_availablelength(msg->buffer);
   2295 		if (padsize > remaining) {
   2296 			padsize = remaining;
   2297 		}
   2298 
   2299 		isc_buffer_add(msg->buffer, padsize);
   2300 		memset(cp, 0, padsize);
   2301 		cp[-2] = (unsigned char)((padsize & 0xff00U) >> 8);
   2302 		cp[-1] = (unsigned char)(padsize & 0x00ffU);
   2303 		cp -= msg->padding_off;
   2304 		len = ((uint16_t)(cp[-2])) << 8;
   2305 		len |= ((uint16_t)(cp[-1]));
   2306 		len += padsize;
   2307 		cp[-2] = (unsigned char)((len & 0xff00U) >> 8);
   2308 		cp[-1] = (unsigned char)(len & 0x00ffU);
   2309 	}
   2310 
   2311 	/*
   2312 	 * If we're adding a TSIG record, generate and render it.
   2313 	 */
   2314 	if (msg->tsigkey != NULL) {
   2315 		dns_message_renderrelease(msg, msg->sig_reserved);
   2316 		msg->sig_reserved = 0;
   2317 		result = dns_tsig_sign(msg);
   2318 		if (result != ISC_R_SUCCESS) {
   2319 			return (result);
   2320 		}
   2321 		count = 0;
   2322 		result = renderset(msg->tsig, msg->tsigname, msg->cctx,
   2323 				   msg->buffer, msg->reserved, 0, &count);
   2324 		msg->counts[DNS_SECTION_ADDITIONAL] += count;
   2325 		if (result != ISC_R_SUCCESS) {
   2326 			return (result);
   2327 		}
   2328 	}
   2329 
   2330 	/*
   2331 	 * If we're adding a SIG(0) record, generate and render it.
   2332 	 */
   2333 	if (msg->sig0key != NULL) {
   2334 		dns_message_renderrelease(msg, msg->sig_reserved);
   2335 		msg->sig_reserved = 0;
   2336 		result = dns_dnssec_signmessage(msg, msg->sig0key);
   2337 		if (result != ISC_R_SUCCESS) {
   2338 			return (result);
   2339 		}
   2340 		count = 0;
   2341 		/*
   2342 		 * Note: dns_rootname is used here, not msg->sig0name, since
   2343 		 * the owner name of a SIG(0) is irrelevant, and will not
   2344 		 * be set in a message being rendered.
   2345 		 */
   2346 		result = renderset(msg->sig0, dns_rootname, msg->cctx,
   2347 				   msg->buffer, msg->reserved, 0, &count);
   2348 		msg->counts[DNS_SECTION_ADDITIONAL] += count;
   2349 		if (result != ISC_R_SUCCESS) {
   2350 			return (result);
   2351 		}
   2352 	}
   2353 
   2354 	isc_buffer_usedregion(msg->buffer, &r);
   2355 	isc_buffer_init(&tmpbuf, r.base, r.length);
   2356 
   2357 	dns_message_renderheader(msg, &tmpbuf);
   2358 
   2359 	msg->buffer = NULL; /* forget about this buffer only on success XXX */
   2360 
   2361 	return (ISC_R_SUCCESS);
   2362 }
   2363 
   2364 void
   2365 dns_message_renderreset(dns_message_t *msg) {
   2366 	unsigned int i;
   2367 	dns_name_t *name;
   2368 	dns_rdataset_t *rds;
   2369 
   2370 	/*
   2371 	 * Reset the message so that it may be rendered again.
   2372 	 */
   2373 
   2374 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2375 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
   2376 
   2377 	msg->buffer = NULL;
   2378 
   2379 	for (i = 0; i < DNS_SECTION_MAX; i++) {
   2380 		msg->cursors[i] = NULL;
   2381 		msg->counts[i] = 0;
   2382 		for (name = ISC_LIST_HEAD(msg->sections[i]); name != NULL;
   2383 		     name = ISC_LIST_NEXT(name, link))
   2384 		{
   2385 			for (rds = ISC_LIST_HEAD(name->list); rds != NULL;
   2386 			     rds = ISC_LIST_NEXT(rds, link))
   2387 			{
   2388 				rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
   2389 			}
   2390 		}
   2391 	}
   2392 	if (msg->tsigname != NULL) {
   2393 		dns_message_puttempname(msg, &msg->tsigname);
   2394 	}
   2395 	if (msg->tsig != NULL) {
   2396 		dns_rdataset_disassociate(msg->tsig);
   2397 		dns_message_puttemprdataset(msg, &msg->tsig);
   2398 	}
   2399 	if (msg->sig0 != NULL) {
   2400 		dns_rdataset_disassociate(msg->sig0);
   2401 		dns_message_puttemprdataset(msg, &msg->sig0);
   2402 	}
   2403 }
   2404 
   2405 isc_result_t
   2406 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
   2407 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2408 	REQUIRE(VALID_NAMED_SECTION(section));
   2409 
   2410 	msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
   2411 
   2412 	if (msg->cursors[section] == NULL) {
   2413 		return (ISC_R_NOMORE);
   2414 	}
   2415 
   2416 	return (ISC_R_SUCCESS);
   2417 }
   2418 
   2419 isc_result_t
   2420 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
   2421 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2422 	REQUIRE(VALID_NAMED_SECTION(section));
   2423 	REQUIRE(msg->cursors[section] != NULL);
   2424 
   2425 	msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
   2426 
   2427 	if (msg->cursors[section] == NULL) {
   2428 		return (ISC_R_NOMORE);
   2429 	}
   2430 
   2431 	return (ISC_R_SUCCESS);
   2432 }
   2433 
   2434 void
   2435 dns_message_currentname(dns_message_t *msg, dns_section_t section,
   2436 			dns_name_t **name) {
   2437 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2438 	REQUIRE(VALID_NAMED_SECTION(section));
   2439 	REQUIRE(name != NULL && *name == NULL);
   2440 	REQUIRE(msg->cursors[section] != NULL);
   2441 
   2442 	*name = msg->cursors[section];
   2443 }
   2444 
   2445 isc_result_t
   2446 dns_message_findname(dns_message_t *msg, dns_section_t section,
   2447 		     const dns_name_t *target, dns_rdatatype_t type,
   2448 		     dns_rdatatype_t covers, dns_name_t **name,
   2449 		     dns_rdataset_t **rdataset) {
   2450 	dns_name_t *foundname;
   2451 	isc_result_t result;
   2452 
   2453 	/*
   2454 	 * XXX These requirements are probably too intensive, especially
   2455 	 * where things can be NULL, but as they are they ensure that if
   2456 	 * something is NON-NULL, indicating that the caller expects it
   2457 	 * to be filled in, that we can in fact fill it in.
   2458 	 */
   2459 	REQUIRE(msg != NULL);
   2460 	REQUIRE(VALID_SECTION(section));
   2461 	REQUIRE(target != NULL);
   2462 	REQUIRE(name == NULL || *name == NULL);
   2463 
   2464 	if (type == dns_rdatatype_any) {
   2465 		REQUIRE(rdataset == NULL);
   2466 	} else {
   2467 		REQUIRE(rdataset == NULL || *rdataset == NULL);
   2468 	}
   2469 
   2470 	result = findname(&foundname, target, &msg->sections[section]);
   2471 
   2472 	if (result == ISC_R_NOTFOUND) {
   2473 		return (DNS_R_NXDOMAIN);
   2474 	} else if (result != ISC_R_SUCCESS) {
   2475 		return (result);
   2476 	}
   2477 
   2478 	if (name != NULL) {
   2479 		*name = foundname;
   2480 	}
   2481 
   2482 	/*
   2483 	 * And now look for the type.
   2484 	 */
   2485 	if (ISC_UNLIKELY(type == dns_rdatatype_any)) {
   2486 		return (ISC_R_SUCCESS);
   2487 	}
   2488 
   2489 	result = dns_message_findtype(foundname, type, covers, rdataset);
   2490 	if (result == ISC_R_NOTFOUND) {
   2491 		return (DNS_R_NXRRSET);
   2492 	}
   2493 
   2494 	return (result);
   2495 }
   2496 
   2497 void
   2498 dns_message_movename(dns_message_t *msg, dns_name_t *name,
   2499 		     dns_section_t fromsection, dns_section_t tosection) {
   2500 	REQUIRE(msg != NULL);
   2501 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
   2502 	REQUIRE(name != NULL);
   2503 	REQUIRE(VALID_NAMED_SECTION(fromsection));
   2504 	REQUIRE(VALID_NAMED_SECTION(tosection));
   2505 
   2506 	/*
   2507 	 * Unlink the name from the old section
   2508 	 */
   2509 	ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
   2510 	ISC_LIST_APPEND(msg->sections[tosection], name, link);
   2511 }
   2512 
   2513 void
   2514 dns_message_addname(dns_message_t *msg, dns_name_t *name,
   2515 		    dns_section_t section) {
   2516 	REQUIRE(msg != NULL);
   2517 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
   2518 	REQUIRE(name != NULL);
   2519 	REQUIRE(VALID_NAMED_SECTION(section));
   2520 
   2521 	ISC_LIST_APPEND(msg->sections[section], name, link);
   2522 }
   2523 
   2524 void
   2525 dns_message_removename(dns_message_t *msg, dns_name_t *name,
   2526 		       dns_section_t section) {
   2527 	REQUIRE(msg != NULL);
   2528 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
   2529 	REQUIRE(name != NULL);
   2530 	REQUIRE(VALID_NAMED_SECTION(section));
   2531 
   2532 	ISC_LIST_UNLINK(msg->sections[section], name, link);
   2533 }
   2534 
   2535 isc_result_t
   2536 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
   2537 	dns_fixedname_t *fn = NULL;
   2538 
   2539 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2540 	REQUIRE(item != NULL && *item == NULL);
   2541 
   2542 	fn = isc_mempool_get(msg->namepool);
   2543 	if (fn == NULL) {
   2544 		return (ISC_R_NOMEMORY);
   2545 	}
   2546 	*item = dns_fixedname_initname(fn);
   2547 
   2548 	return (ISC_R_SUCCESS);
   2549 }
   2550 
   2551 isc_result_t
   2552 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
   2553 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2554 	REQUIRE(item != NULL && *item == NULL);
   2555 
   2556 	*item = newrdata(msg);
   2557 	if (*item == NULL) {
   2558 		return (ISC_R_NOMEMORY);
   2559 	}
   2560 
   2561 	return (ISC_R_SUCCESS);
   2562 }
   2563 
   2564 isc_result_t
   2565 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
   2566 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2567 	REQUIRE(item != NULL && *item == NULL);
   2568 
   2569 	*item = isc_mempool_get(msg->rdspool);
   2570 	if (*item == NULL) {
   2571 		return (ISC_R_NOMEMORY);
   2572 	}
   2573 
   2574 	dns_rdataset_init(*item);
   2575 	return (ISC_R_SUCCESS);
   2576 }
   2577 
   2578 isc_result_t
   2579 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
   2580 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2581 	REQUIRE(item != NULL && *item == NULL);
   2582 
   2583 	*item = newrdatalist(msg);
   2584 	if (*item == NULL) {
   2585 		return (ISC_R_NOMEMORY);
   2586 	}
   2587 
   2588 	return (ISC_R_SUCCESS);
   2589 }
   2590 
   2591 void
   2592 dns_message_puttempname(dns_message_t *msg, dns_name_t **itemp) {
   2593 	dns_name_t *item = NULL;
   2594 
   2595 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2596 	REQUIRE(itemp != NULL && *itemp != NULL);
   2597 
   2598 	item = *itemp;
   2599 	*itemp = NULL;
   2600 
   2601 	REQUIRE(!ISC_LINK_LINKED(item, link));
   2602 	REQUIRE(ISC_LIST_HEAD(item->list) == NULL);
   2603 
   2604 	/*
   2605 	 * we need to check this in case dns_name_dup() was used.
   2606 	 */
   2607 	if (dns_name_dynamic(item)) {
   2608 		dns_name_free(item, msg->mctx);
   2609 	}
   2610 
   2611 	/*
   2612 	 * 'name' is the first field in dns_fixedname_t, so putting
   2613 	 * back the address of name is the same as putting back
   2614 	 * the fixedname.
   2615 	 */
   2616 	isc_mempool_put(msg->namepool, item);
   2617 }
   2618 
   2619 void
   2620 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
   2621 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2622 	REQUIRE(item != NULL && *item != NULL);
   2623 
   2624 	releaserdata(msg, *item);
   2625 	*item = NULL;
   2626 }
   2627 
   2628 void
   2629 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
   2630 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2631 	REQUIRE(item != NULL && *item != NULL);
   2632 
   2633 	REQUIRE(!dns_rdataset_isassociated(*item));
   2634 	isc_mempool_put(msg->rdspool, *item);
   2635 	*item = NULL;
   2636 }
   2637 
   2638 void
   2639 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
   2640 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2641 	REQUIRE(item != NULL && *item != NULL);
   2642 
   2643 	releaserdatalist(msg, *item);
   2644 	*item = NULL;
   2645 }
   2646 
   2647 isc_result_t
   2648 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
   2649 		       unsigned int *flagsp) {
   2650 	isc_region_t r;
   2651 	isc_buffer_t buffer;
   2652 	dns_messageid_t id;
   2653 	unsigned int flags;
   2654 
   2655 	REQUIRE(source != NULL);
   2656 
   2657 	buffer = *source;
   2658 
   2659 	isc_buffer_remainingregion(&buffer, &r);
   2660 	if (r.length < DNS_MESSAGE_HEADERLEN) {
   2661 		return (ISC_R_UNEXPECTEDEND);
   2662 	}
   2663 
   2664 	id = isc_buffer_getuint16(&buffer);
   2665 	flags = isc_buffer_getuint16(&buffer);
   2666 	flags &= DNS_MESSAGE_FLAG_MASK;
   2667 
   2668 	if (flagsp != NULL) {
   2669 		*flagsp = flags;
   2670 	}
   2671 	if (idp != NULL) {
   2672 		*idp = id;
   2673 	}
   2674 
   2675 	return (ISC_R_SUCCESS);
   2676 }
   2677 
   2678 isc_result_t
   2679 dns_message_reply(dns_message_t *msg, bool want_question_section) {
   2680 	unsigned int clear_from;
   2681 	isc_result_t result;
   2682 
   2683 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2684 	REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
   2685 
   2686 	if (!msg->header_ok) {
   2687 		return (DNS_R_FORMERR);
   2688 	}
   2689 	if (msg->opcode != dns_opcode_query && msg->opcode != dns_opcode_notify)
   2690 	{
   2691 		want_question_section = false;
   2692 	}
   2693 	if (msg->opcode == dns_opcode_update) {
   2694 		clear_from = DNS_SECTION_PREREQUISITE;
   2695 	} else if (want_question_section) {
   2696 		if (!msg->question_ok) {
   2697 			return (DNS_R_FORMERR);
   2698 		}
   2699 		clear_from = DNS_SECTION_ANSWER;
   2700 	} else {
   2701 		clear_from = DNS_SECTION_QUESTION;
   2702 	}
   2703 	msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
   2704 	msgresetnames(msg, clear_from);
   2705 	msgresetopt(msg);
   2706 	msgresetsigs(msg, true);
   2707 	msginitprivate(msg);
   2708 	/*
   2709 	 * We now clear most flags and then set QR, ensuring that the
   2710 	 * reply's flags will be in a reasonable state.
   2711 	 */
   2712 	if (msg->opcode == dns_opcode_query) {
   2713 		msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
   2714 	} else {
   2715 		msg->flags = 0;
   2716 	}
   2717 	msg->flags |= DNS_MESSAGEFLAG_QR;
   2718 
   2719 	/*
   2720 	 * This saves the query TSIG status, if the query was signed, and
   2721 	 * reserves space in the reply for the TSIG.
   2722 	 */
   2723 	if (msg->tsigkey != NULL) {
   2724 		unsigned int otherlen = 0;
   2725 		msg->querytsigstatus = msg->tsigstatus;
   2726 		msg->tsigstatus = dns_rcode_noerror;
   2727 		if (msg->querytsigstatus == dns_tsigerror_badtime) {
   2728 			otherlen = 6;
   2729 		}
   2730 		msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
   2731 		result = dns_message_renderreserve(msg, msg->sig_reserved);
   2732 		if (result != ISC_R_SUCCESS) {
   2733 			msg->sig_reserved = 0;
   2734 			return (result);
   2735 		}
   2736 	}
   2737 	if (msg->saved.base != NULL) {
   2738 		msg->query.base = msg->saved.base;
   2739 		msg->query.length = msg->saved.length;
   2740 		msg->free_query = msg->free_saved;
   2741 		msg->saved.base = NULL;
   2742 		msg->saved.length = 0;
   2743 		msg->free_saved = 0;
   2744 	}
   2745 
   2746 	return (ISC_R_SUCCESS);
   2747 }
   2748 
   2749 dns_rdataset_t *
   2750 dns_message_getopt(dns_message_t *msg) {
   2751 	/*
   2752 	 * Get the OPT record for 'msg'.
   2753 	 */
   2754 
   2755 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2756 
   2757 	return (msg->opt);
   2758 }
   2759 
   2760 isc_result_t
   2761 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
   2762 	isc_result_t result;
   2763 	dns_rdata_t rdata = DNS_RDATA_INIT;
   2764 
   2765 	/*
   2766 	 * Set the OPT record for 'msg'.
   2767 	 */
   2768 
   2769 	/*
   2770 	 * The space required for an OPT record is:
   2771 	 *
   2772 	 *	1 byte for the name
   2773 	 *	2 bytes for the type
   2774 	 *	2 bytes for the class
   2775 	 *	4 bytes for the ttl
   2776 	 *	2 bytes for the rdata length
   2777 	 * ---------------------------------
   2778 	 *     11 bytes
   2779 	 *
   2780 	 * plus the length of the rdata.
   2781 	 */
   2782 
   2783 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2784 	REQUIRE(opt->type == dns_rdatatype_opt);
   2785 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
   2786 	REQUIRE(msg->state == DNS_SECTION_ANY);
   2787 
   2788 	msgresetopt(msg);
   2789 
   2790 	result = dns_rdataset_first(opt);
   2791 	if (result != ISC_R_SUCCESS) {
   2792 		goto cleanup;
   2793 	}
   2794 	dns_rdataset_current(opt, &rdata);
   2795 	msg->opt_reserved = 11 + rdata.length;
   2796 	result = dns_message_renderreserve(msg, msg->opt_reserved);
   2797 	if (result != ISC_R_SUCCESS) {
   2798 		msg->opt_reserved = 0;
   2799 		goto cleanup;
   2800 	}
   2801 
   2802 	msg->opt = opt;
   2803 
   2804 	return (ISC_R_SUCCESS);
   2805 
   2806 cleanup:
   2807 	dns_rdataset_disassociate(opt);
   2808 	dns_message_puttemprdataset(msg, &opt);
   2809 	return (result);
   2810 }
   2811 
   2812 dns_rdataset_t *
   2813 dns_message_gettsig(dns_message_t *msg, const dns_name_t **owner) {
   2814 	/*
   2815 	 * Get the TSIG record and owner for 'msg'.
   2816 	 */
   2817 
   2818 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2819 	REQUIRE(owner == NULL || *owner == NULL);
   2820 
   2821 	if (owner != NULL) {
   2822 		*owner = msg->tsigname;
   2823 	}
   2824 	return (msg->tsig);
   2825 }
   2826 
   2827 isc_result_t
   2828 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
   2829 	isc_result_t result;
   2830 
   2831 	/*
   2832 	 * Set the TSIG key for 'msg'
   2833 	 */
   2834 
   2835 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2836 
   2837 	if (key == NULL && msg->tsigkey != NULL) {
   2838 		if (msg->sig_reserved != 0) {
   2839 			dns_message_renderrelease(msg, msg->sig_reserved);
   2840 			msg->sig_reserved = 0;
   2841 		}
   2842 		dns_tsigkey_detach(&msg->tsigkey);
   2843 	}
   2844 	if (key != NULL) {
   2845 		REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
   2846 		dns_tsigkey_attach(key, &msg->tsigkey);
   2847 		if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
   2848 			msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
   2849 			result = dns_message_renderreserve(msg,
   2850 							   msg->sig_reserved);
   2851 			if (result != ISC_R_SUCCESS) {
   2852 				dns_tsigkey_detach(&msg->tsigkey);
   2853 				msg->sig_reserved = 0;
   2854 				return (result);
   2855 			}
   2856 		}
   2857 	}
   2858 	return (ISC_R_SUCCESS);
   2859 }
   2860 
   2861 dns_tsigkey_t *
   2862 dns_message_gettsigkey(dns_message_t *msg) {
   2863 	/*
   2864 	 * Get the TSIG key for 'msg'
   2865 	 */
   2866 
   2867 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2868 
   2869 	return (msg->tsigkey);
   2870 }
   2871 
   2872 isc_result_t
   2873 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
   2874 	dns_rdata_t *rdata = NULL;
   2875 	dns_rdatalist_t *list = NULL;
   2876 	dns_rdataset_t *set = NULL;
   2877 	isc_buffer_t *buf = NULL;
   2878 	isc_region_t r;
   2879 	isc_result_t result;
   2880 
   2881 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2882 	REQUIRE(msg->querytsig == NULL);
   2883 
   2884 	if (querytsig == NULL) {
   2885 		return (ISC_R_SUCCESS);
   2886 	}
   2887 
   2888 	result = dns_message_gettemprdata(msg, &rdata);
   2889 	if (result != ISC_R_SUCCESS) {
   2890 		goto cleanup;
   2891 	}
   2892 
   2893 	result = dns_message_gettemprdatalist(msg, &list);
   2894 	if (result != ISC_R_SUCCESS) {
   2895 		goto cleanup;
   2896 	}
   2897 	result = dns_message_gettemprdataset(msg, &set);
   2898 	if (result != ISC_R_SUCCESS) {
   2899 		goto cleanup;
   2900 	}
   2901 
   2902 	isc_buffer_usedregion(querytsig, &r);
   2903 	isc_buffer_allocate(msg->mctx, &buf, r.length);
   2904 	isc_buffer_putmem(buf, r.base, r.length);
   2905 	isc_buffer_usedregion(buf, &r);
   2906 	dns_rdata_init(rdata);
   2907 	dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
   2908 	dns_message_takebuffer(msg, &buf);
   2909 	ISC_LIST_APPEND(list->rdata, rdata, link);
   2910 	result = dns_rdatalist_tordataset(list, set);
   2911 	if (result != ISC_R_SUCCESS) {
   2912 		goto cleanup;
   2913 	}
   2914 
   2915 	msg->querytsig = set;
   2916 
   2917 	return (result);
   2918 
   2919 cleanup:
   2920 	if (rdata != NULL) {
   2921 		dns_message_puttemprdata(msg, &rdata);
   2922 	}
   2923 	if (list != NULL) {
   2924 		dns_message_puttemprdatalist(msg, &list);
   2925 	}
   2926 	if (set != NULL) {
   2927 		dns_message_puttemprdataset(msg, &set);
   2928 	}
   2929 	return (ISC_R_NOMEMORY);
   2930 }
   2931 
   2932 isc_result_t
   2933 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
   2934 			 isc_buffer_t **querytsig) {
   2935 	isc_result_t result;
   2936 	dns_rdata_t rdata = DNS_RDATA_INIT;
   2937 	isc_region_t r;
   2938 
   2939 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2940 	REQUIRE(mctx != NULL);
   2941 	REQUIRE(querytsig != NULL && *querytsig == NULL);
   2942 
   2943 	if (msg->tsig == NULL) {
   2944 		return (ISC_R_SUCCESS);
   2945 	}
   2946 
   2947 	result = dns_rdataset_first(msg->tsig);
   2948 	if (result != ISC_R_SUCCESS) {
   2949 		return (result);
   2950 	}
   2951 	dns_rdataset_current(msg->tsig, &rdata);
   2952 	dns_rdata_toregion(&rdata, &r);
   2953 
   2954 	isc_buffer_allocate(mctx, querytsig, r.length);
   2955 	isc_buffer_putmem(*querytsig, r.base, r.length);
   2956 	return (ISC_R_SUCCESS);
   2957 }
   2958 
   2959 dns_rdataset_t *
   2960 dns_message_getsig0(dns_message_t *msg, const dns_name_t **owner) {
   2961 	/*
   2962 	 * Get the SIG(0) record for 'msg'.
   2963 	 */
   2964 
   2965 	REQUIRE(DNS_MESSAGE_VALID(msg));
   2966 	REQUIRE(owner == NULL || *owner == NULL);
   2967 
   2968 	if (msg->sig0 != NULL && owner != NULL) {
   2969 		/* If dns_message_getsig0 is called on a rendered message
   2970 		 * after the SIG(0) has been applied, we need to return the
   2971 		 * root name, not NULL.
   2972 		 */
   2973 		if (msg->sig0name == NULL) {
   2974 			*owner = dns_rootname;
   2975 		} else {
   2976 			*owner = msg->sig0name;
   2977 		}
   2978 	}
   2979 	return (msg->sig0);
   2980 }
   2981 
   2982 isc_result_t
   2983 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
   2984 	isc_region_t r;
   2985 	unsigned int x;
   2986 	isc_result_t result;
   2987 
   2988 	/*
   2989 	 * Set the SIG(0) key for 'msg'
   2990 	 */
   2991 
   2992 	/*
   2993 	 * The space required for an SIG(0) record is:
   2994 	 *
   2995 	 *	1 byte for the name
   2996 	 *	2 bytes for the type
   2997 	 *	2 bytes for the class
   2998 	 *	4 bytes for the ttl
   2999 	 *	2 bytes for the type covered
   3000 	 *	1 byte for the algorithm
   3001 	 *	1 bytes for the labels
   3002 	 *	4 bytes for the original ttl
   3003 	 *	4 bytes for the signature expiration
   3004 	 *	4 bytes for the signature inception
   3005 	 *	2 bytes for the key tag
   3006 	 *	n bytes for the signer's name
   3007 	 *	x bytes for the signature
   3008 	 * ---------------------------------
   3009 	 *     27 + n + x bytes
   3010 	 */
   3011 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3012 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
   3013 	REQUIRE(msg->state == DNS_SECTION_ANY);
   3014 
   3015 	if (key != NULL) {
   3016 		REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
   3017 		dns_name_toregion(dst_key_name(key), &r);
   3018 		result = dst_key_sigsize(key, &x);
   3019 		if (result != ISC_R_SUCCESS) {
   3020 			msg->sig_reserved = 0;
   3021 			return (result);
   3022 		}
   3023 		msg->sig_reserved = 27 + r.length + x;
   3024 		result = dns_message_renderreserve(msg, msg->sig_reserved);
   3025 		if (result != ISC_R_SUCCESS) {
   3026 			msg->sig_reserved = 0;
   3027 			return (result);
   3028 		}
   3029 		msg->sig0key = key;
   3030 	}
   3031 	return (ISC_R_SUCCESS);
   3032 }
   3033 
   3034 dst_key_t *
   3035 dns_message_getsig0key(dns_message_t *msg) {
   3036 	/*
   3037 	 * Get the SIG(0) key for 'msg'
   3038 	 */
   3039 
   3040 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3041 
   3042 	return (msg->sig0key);
   3043 }
   3044 
   3045 void
   3046 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
   3047 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3048 	REQUIRE(buffer != NULL);
   3049 	REQUIRE(ISC_BUFFER_VALID(*buffer));
   3050 
   3051 	ISC_LIST_APPEND(msg->cleanup, *buffer, link);
   3052 	*buffer = NULL;
   3053 }
   3054 
   3055 isc_result_t
   3056 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
   3057 	isc_result_t result = ISC_R_SUCCESS;
   3058 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3059 
   3060 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3061 	REQUIRE(signer != NULL);
   3062 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
   3063 
   3064 	if (msg->tsig == NULL && msg->sig0 == NULL) {
   3065 		return (ISC_R_NOTFOUND);
   3066 	}
   3067 
   3068 	if (msg->verify_attempted == 0) {
   3069 		return (DNS_R_NOTVERIFIEDYET);
   3070 	}
   3071 
   3072 	if (!dns_name_hasbuffer(signer)) {
   3073 		isc_buffer_t *dynbuf = NULL;
   3074 		isc_buffer_allocate(msg->mctx, &dynbuf, 512);
   3075 		dns_name_setbuffer(signer, dynbuf);
   3076 		dns_message_takebuffer(msg, &dynbuf);
   3077 	}
   3078 
   3079 	if (msg->sig0 != NULL) {
   3080 		dns_rdata_sig_t sig;
   3081 
   3082 		result = dns_rdataset_first(msg->sig0);
   3083 		INSIST(result == ISC_R_SUCCESS);
   3084 		dns_rdataset_current(msg->sig0, &rdata);
   3085 
   3086 		result = dns_rdata_tostruct(&rdata, &sig, NULL);
   3087 		if (result != ISC_R_SUCCESS) {
   3088 			return (result);
   3089 		}
   3090 
   3091 		if (msg->verified_sig && msg->sig0status == dns_rcode_noerror) {
   3092 			result = ISC_R_SUCCESS;
   3093 		} else {
   3094 			result = DNS_R_SIGINVALID;
   3095 		}
   3096 		dns_name_clone(&sig.signer, signer);
   3097 		dns_rdata_freestruct(&sig);
   3098 	} else {
   3099 		const dns_name_t *identity;
   3100 		dns_rdata_any_tsig_t tsig;
   3101 
   3102 		result = dns_rdataset_first(msg->tsig);
   3103 		INSIST(result == ISC_R_SUCCESS);
   3104 		dns_rdataset_current(msg->tsig, &rdata);
   3105 
   3106 		result = dns_rdata_tostruct(&rdata, &tsig, NULL);
   3107 		INSIST(result == ISC_R_SUCCESS);
   3108 		if (msg->verified_sig && msg->tsigstatus == dns_rcode_noerror &&
   3109 		    tsig.error == dns_rcode_noerror)
   3110 		{
   3111 			result = ISC_R_SUCCESS;
   3112 		} else if ((!msg->verified_sig) ||
   3113 			   (msg->tsigstatus != dns_rcode_noerror))
   3114 		{
   3115 			result = DNS_R_TSIGVERIFYFAILURE;
   3116 		} else {
   3117 			INSIST(tsig.error != dns_rcode_noerror);
   3118 			result = DNS_R_TSIGERRORSET;
   3119 		}
   3120 		dns_rdata_freestruct(&tsig);
   3121 
   3122 		if (msg->tsigkey == NULL) {
   3123 			/*
   3124 			 * If msg->tsigstatus & tsig.error are both
   3125 			 * dns_rcode_noerror, the message must have been
   3126 			 * verified, which means msg->tsigkey will be
   3127 			 * non-NULL.
   3128 			 */
   3129 			INSIST(result != ISC_R_SUCCESS);
   3130 		} else {
   3131 			identity = dns_tsigkey_identity(msg->tsigkey);
   3132 			if (identity == NULL) {
   3133 				if (result == ISC_R_SUCCESS) {
   3134 					result = DNS_R_NOIDENTITY;
   3135 				}
   3136 				identity = &msg->tsigkey->name;
   3137 			}
   3138 			dns_name_clone(identity, signer);
   3139 		}
   3140 	}
   3141 
   3142 	return (result);
   3143 }
   3144 
   3145 void
   3146 dns_message_resetsig(dns_message_t *msg) {
   3147 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3148 	msg->verified_sig = 0;
   3149 	msg->verify_attempted = 0;
   3150 	msg->tsigstatus = dns_rcode_noerror;
   3151 	msg->sig0status = dns_rcode_noerror;
   3152 	msg->timeadjust = 0;
   3153 	if (msg->tsigkey != NULL) {
   3154 		dns_tsigkey_detach(&msg->tsigkey);
   3155 		msg->tsigkey = NULL;
   3156 	}
   3157 }
   3158 
   3159 isc_result_t
   3160 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
   3161 	dns_message_resetsig(msg);
   3162 	return (dns_message_checksig(msg, view));
   3163 }
   3164 
   3165 #ifdef SKAN_MSG_DEBUG
   3166 void
   3167 dns_message_dumpsig(dns_message_t *msg, char *txt1) {
   3168 	dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
   3169 	dns_rdata_any_tsig_t querytsig;
   3170 	isc_result_t result;
   3171 
   3172 	if (msg->tsig != NULL) {
   3173 		result = dns_rdataset_first(msg->tsig);
   3174 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3175 		dns_rdataset_current(msg->tsig, &querytsigrdata);
   3176 		result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
   3177 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3178 		hexdump(txt1, "TSIG", querytsig.signature, querytsig.siglen);
   3179 	}
   3180 
   3181 	if (msg->querytsig != NULL) {
   3182 		result = dns_rdataset_first(msg->querytsig);
   3183 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3184 		dns_rdataset_current(msg->querytsig, &querytsigrdata);
   3185 		result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
   3186 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3187 		hexdump(txt1, "QUERYTSIG", querytsig.signature,
   3188 			querytsig.siglen);
   3189 	}
   3190 }
   3191 #endif /* ifdef SKAN_MSG_DEBUG */
   3192 
   3193 isc_result_t
   3194 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
   3195 	isc_buffer_t b, msgb;
   3196 
   3197 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3198 
   3199 	if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL) {
   3200 		return (ISC_R_SUCCESS);
   3201 	}
   3202 
   3203 	INSIST(msg->saved.base != NULL);
   3204 	isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
   3205 	isc_buffer_add(&msgb, msg->saved.length);
   3206 	if (msg->tsigkey != NULL || msg->tsig != NULL) {
   3207 #ifdef SKAN_MSG_DEBUG
   3208 		dns_message_dumpsig(msg, "dns_message_checksig#1");
   3209 #endif /* ifdef SKAN_MSG_DEBUG */
   3210 		if (view != NULL) {
   3211 			return (dns_view_checksig(view, &msgb, msg));
   3212 		} else {
   3213 			return (dns_tsig_verify(&msgb, msg, NULL, NULL));
   3214 		}
   3215 	} else {
   3216 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3217 		dns_rdata_sig_t sig;
   3218 		dns_rdataset_t keyset;
   3219 		isc_result_t result;
   3220 
   3221 		result = dns_rdataset_first(msg->sig0);
   3222 		INSIST(result == ISC_R_SUCCESS);
   3223 		dns_rdataset_current(msg->sig0, &rdata);
   3224 
   3225 		/*
   3226 		 * This can occur when the message is a dynamic update, since
   3227 		 * the rdata length checking is relaxed.  This should not
   3228 		 * happen in a well-formed message, since the SIG(0) is only
   3229 		 * looked for in the additional section, and the dynamic update
   3230 		 * meta-records are in the prerequisite and update sections.
   3231 		 */
   3232 		if (rdata.length == 0) {
   3233 			return (ISC_R_UNEXPECTEDEND);
   3234 		}
   3235 
   3236 		result = dns_rdata_tostruct(&rdata, &sig, NULL);
   3237 		if (result != ISC_R_SUCCESS) {
   3238 			return (result);
   3239 		}
   3240 
   3241 		dns_rdataset_init(&keyset);
   3242 		if (view == NULL) {
   3243 			result = DNS_R_KEYUNAUTHORIZED;
   3244 			goto freesig;
   3245 		}
   3246 		result = dns_view_simplefind(view, &sig.signer,
   3247 					     dns_rdatatype_key /* SIG(0) */, 0,
   3248 					     0, false, &keyset, NULL);
   3249 
   3250 		if (result != ISC_R_SUCCESS) {
   3251 			/* XXXBEW Should possibly create a fetch here */
   3252 			result = DNS_R_KEYUNAUTHORIZED;
   3253 			goto freesig;
   3254 		} else if (keyset.trust < dns_trust_secure) {
   3255 			/* XXXBEW Should call a validator here */
   3256 			result = DNS_R_KEYUNAUTHORIZED;
   3257 			goto freesig;
   3258 		}
   3259 		result = dns_rdataset_first(&keyset);
   3260 		INSIST(result == ISC_R_SUCCESS);
   3261 		for (; result == ISC_R_SUCCESS;
   3262 		     result = dns_rdataset_next(&keyset))
   3263 		{
   3264 			dst_key_t *key = NULL;
   3265 
   3266 			dns_rdata_reset(&rdata);
   3267 			dns_rdataset_current(&keyset, &rdata);
   3268 			isc_buffer_init(&b, rdata.data, rdata.length);
   3269 			isc_buffer_add(&b, rdata.length);
   3270 
   3271 			result = dst_key_fromdns(&sig.signer, rdata.rdclass, &b,
   3272 						 view->mctx, &key);
   3273 			if (result != ISC_R_SUCCESS) {
   3274 				continue;
   3275 			}
   3276 			if (dst_key_alg(key) != sig.algorithm ||
   3277 			    dst_key_id(key) != sig.keyid ||
   3278 			    !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
   3279 			      dst_key_proto(key) == DNS_KEYPROTO_ANY))
   3280 			{
   3281 				dst_key_free(&key);
   3282 				continue;
   3283 			}
   3284 			result = dns_dnssec_verifymessage(&msgb, msg, key);
   3285 			dst_key_free(&key);
   3286 			if (result == ISC_R_SUCCESS) {
   3287 				break;
   3288 			}
   3289 		}
   3290 		if (result == ISC_R_NOMORE) {
   3291 			result = DNS_R_KEYUNAUTHORIZED;
   3292 		}
   3293 
   3294 	freesig:
   3295 		if (dns_rdataset_isassociated(&keyset)) {
   3296 			dns_rdataset_disassociate(&keyset);
   3297 		}
   3298 		dns_rdata_freestruct(&sig);
   3299 		return (result);
   3300 	}
   3301 }
   3302 
   3303 #define INDENT(sp)                                                           \
   3304 	do {                                                                 \
   3305 		unsigned int __i;                                            \
   3306 		dns_masterstyle_flags_t __flags = dns_master_styleflags(sp); \
   3307 		if ((__flags & DNS_STYLEFLAG_INDENT) == 0ULL &&              \
   3308 		    (__flags & DNS_STYLEFLAG_YAML) == 0ULL)                  \
   3309 			break;                                               \
   3310 		for (__i = 0; __i < msg->indent.count; __i++) {              \
   3311 			ADD_STRING(target, msg->indent.string);              \
   3312 		}                                                            \
   3313 	} while (0)
   3314 
   3315 isc_result_t
   3316 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
   3317 			  const dns_master_style_t *style,
   3318 			  dns_messagetextflag_t flags, isc_buffer_t *target) {
   3319 	dns_name_t *name, empty_name;
   3320 	dns_rdataset_t *rdataset;
   3321 	isc_result_t result = ISC_R_SUCCESS;
   3322 	bool seensoa = false;
   3323 	size_t saved_count;
   3324 	dns_masterstyle_flags_t sflags;
   3325 
   3326 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3327 	REQUIRE(target != NULL);
   3328 	REQUIRE(VALID_SECTION(section));
   3329 
   3330 	saved_count = msg->indent.count;
   3331 
   3332 	if (ISC_LIST_EMPTY(msg->sections[section])) {
   3333 		goto cleanup;
   3334 	}
   3335 
   3336 	sflags = dns_master_styleflags(style);
   3337 
   3338 	INDENT(style);
   3339 	if ((sflags & DNS_STYLEFLAG_YAML) != 0) {
   3340 		if (msg->opcode != dns_opcode_update) {
   3341 			ADD_STRING(target, sectiontext[section]);
   3342 		} else {
   3343 			ADD_STRING(target, updsectiontext[section]);
   3344 		}
   3345 		ADD_STRING(target, "_SECTION:\n");
   3346 	} else if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
   3347 		ADD_STRING(target, ";; ");
   3348 		if (msg->opcode != dns_opcode_update) {
   3349 			ADD_STRING(target, sectiontext[section]);
   3350 		} else {
   3351 			ADD_STRING(target, updsectiontext[section]);
   3352 		}
   3353 		ADD_STRING(target, " SECTION:\n");
   3354 	}
   3355 
   3356 	dns_name_init(&empty_name, NULL);
   3357 	result = dns_message_firstname(msg, section);
   3358 	if (result != ISC_R_SUCCESS) {
   3359 		goto cleanup;
   3360 	}
   3361 	if ((sflags & DNS_STYLEFLAG_YAML) != 0) {
   3362 		msg->indent.count++;
   3363 	}
   3364 	do {
   3365 		name = NULL;
   3366 		dns_message_currentname(msg, section, &name);
   3367 		for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
   3368 		     rdataset = ISC_LIST_NEXT(rdataset, link))
   3369 		{
   3370 			if (section == DNS_SECTION_ANSWER &&
   3371 			    rdataset->type == dns_rdatatype_soa)
   3372 			{
   3373 				if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0)
   3374 				{
   3375 					continue;
   3376 				}
   3377 				if (seensoa &&
   3378 				    (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0)
   3379 				{
   3380 					continue;
   3381 				}
   3382 				seensoa = true;
   3383 			}
   3384 			if (section == DNS_SECTION_QUESTION) {
   3385 				INDENT(style);
   3386 				if ((sflags & DNS_STYLEFLAG_YAML) != 0) {
   3387 					ADD_STRING(target, "- ");
   3388 				} else {
   3389 					ADD_STRING(target, ";");
   3390 				}
   3391 				result = dns_master_questiontotext(
   3392 					name, rdataset, style, target);
   3393 			} else {
   3394 				result = dns_master_rdatasettotext(
   3395 					name, rdataset, style, &msg->indent,
   3396 					target);
   3397 			}
   3398 			if (result != ISC_R_SUCCESS) {
   3399 				goto cleanup;
   3400 			}
   3401 		}
   3402 		result = dns_message_nextname(msg, section);
   3403 	} while (result == ISC_R_SUCCESS);
   3404 	if ((sflags & DNS_STYLEFLAG_YAML) != 0) {
   3405 		msg->indent.count--;
   3406 	}
   3407 	if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
   3408 	    (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0 &&
   3409 	    (sflags & DNS_STYLEFLAG_YAML) == 0)
   3410 	{
   3411 		INDENT(style);
   3412 		ADD_STRING(target, "\n");
   3413 	}
   3414 	if (result == ISC_R_NOMORE) {
   3415 		result = ISC_R_SUCCESS;
   3416 	}
   3417 
   3418 cleanup:
   3419 	msg->indent.count = saved_count;
   3420 	return (result);
   3421 }
   3422 
   3423 static isc_result_t
   3424 render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) {
   3425 	int i;
   3426 	char addr[16], addr_text[64];
   3427 	uint16_t family;
   3428 	uint8_t addrlen, addrbytes, scopelen;
   3429 	isc_result_t result;
   3430 
   3431 	/*
   3432 	 * Note: This routine needs to handle malformed ECS options.
   3433 	 */
   3434 
   3435 	if (isc_buffer_remaininglength(ecsbuf) < 4) {
   3436 		return (DNS_R_OPTERR);
   3437 	}
   3438 	family = isc_buffer_getuint16(ecsbuf);
   3439 	addrlen = isc_buffer_getuint8(ecsbuf);
   3440 	scopelen = isc_buffer_getuint8(ecsbuf);
   3441 
   3442 	addrbytes = (addrlen + 7) / 8;
   3443 	if (isc_buffer_remaininglength(ecsbuf) < addrbytes) {
   3444 		return (DNS_R_OPTERR);
   3445 	}
   3446 
   3447 	if (addrbytes > sizeof(addr)) {
   3448 		return (DNS_R_OPTERR);
   3449 	}
   3450 
   3451 	memset(addr, 0, sizeof(addr));
   3452 	for (i = 0; i < addrbytes; i++) {
   3453 		addr[i] = isc_buffer_getuint8(ecsbuf);
   3454 	}
   3455 
   3456 	switch (family) {
   3457 	case 0:
   3458 		if (addrlen != 0U || scopelen != 0U) {
   3459 			return (DNS_R_OPTERR);
   3460 		}
   3461 		strlcpy(addr_text, "0", sizeof(addr_text));
   3462 		break;
   3463 	case 1:
   3464 		if (addrlen > 32 || scopelen > 32) {
   3465 			return (DNS_R_OPTERR);
   3466 		}
   3467 		inet_ntop(AF_INET, addr, addr_text, sizeof(addr_text));
   3468 		break;
   3469 	case 2:
   3470 		if (addrlen > 128 || scopelen > 128) {
   3471 			return (DNS_R_OPTERR);
   3472 		}
   3473 		inet_ntop(AF_INET6, addr, addr_text, sizeof(addr_text));
   3474 		break;
   3475 	default:
   3476 		return (DNS_R_OPTERR);
   3477 	}
   3478 
   3479 	ADD_STRING(target, " ");
   3480 	ADD_STRING(target, addr_text);
   3481 	snprintf(addr_text, sizeof(addr_text), "/%d/%d", addrlen, scopelen);
   3482 	ADD_STRING(target, addr_text);
   3483 
   3484 	result = ISC_R_SUCCESS;
   3485 
   3486 cleanup:
   3487 	return (result);
   3488 }
   3489 
   3490 static isc_result_t
   3491 render_llq(isc_buffer_t *optbuf, isc_buffer_t *target) {
   3492 	char buf[sizeof("18446744073709551615")]; /* 2^64-1 */
   3493 	isc_result_t result = ISC_R_SUCCESS;
   3494 	uint32_t u;
   3495 	uint64_t q;
   3496 
   3497 	u = isc_buffer_getuint16(optbuf);
   3498 	ADD_STRING(target, " Version: ");
   3499 	snprintf(buf, sizeof(buf), "%u", u);
   3500 	ADD_STRING(target, buf);
   3501 
   3502 	u = isc_buffer_getuint16(optbuf);
   3503 	ADD_STRING(target, ", Opcode: ");
   3504 	snprintf(buf, sizeof(buf), "%u", u);
   3505 	ADD_STRING(target, buf);
   3506 
   3507 	u = isc_buffer_getuint16(optbuf);
   3508 	ADD_STRING(target, ", Error: ");
   3509 	snprintf(buf, sizeof(buf), "%u", u);
   3510 	ADD_STRING(target, buf);
   3511 
   3512 	q = isc_buffer_getuint32(optbuf);
   3513 	q <<= 32;
   3514 	q |= isc_buffer_getuint32(optbuf);
   3515 	ADD_STRING(target, ", Identifier: ");
   3516 	snprintf(buf, sizeof(buf), "%" PRIu64, q);
   3517 	ADD_STRING(target, buf);
   3518 
   3519 	u = isc_buffer_getuint32(optbuf);
   3520 	ADD_STRING(target, ", Lifetime: ");
   3521 	snprintf(buf, sizeof(buf), "%u", u);
   3522 	ADD_STRING(target, buf);
   3523 cleanup:
   3524 	return (result);
   3525 }
   3526 
   3527 static isc_result_t
   3528 dns_message_pseudosectiontoyaml(dns_message_t *msg, dns_pseudosection_t section,
   3529 				const dns_master_style_t *style,
   3530 				dns_messagetextflag_t flags,
   3531 				isc_buffer_t *target) {
   3532 	dns_rdataset_t *ps = NULL;
   3533 	const dns_name_t *name = NULL;
   3534 	isc_result_t result = ISC_R_SUCCESS;
   3535 	char buf[sizeof("1234567890")];
   3536 	uint32_t mbz;
   3537 	dns_rdata_t rdata;
   3538 	isc_buffer_t optbuf;
   3539 	uint16_t optcode, optlen;
   3540 	size_t saved_count;
   3541 	unsigned char *optdata;
   3542 	unsigned int indent;
   3543 
   3544 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3545 	REQUIRE(target != NULL);
   3546 	REQUIRE(VALID_PSEUDOSECTION(section));
   3547 
   3548 	saved_count = msg->indent.count;
   3549 
   3550 	switch (section) {
   3551 	case DNS_PSEUDOSECTION_OPT:
   3552 		ps = dns_message_getopt(msg);
   3553 		if (ps == NULL) {
   3554 			goto cleanup;
   3555 		}
   3556 
   3557 		INDENT(style);
   3558 		ADD_STRING(target, "OPT_PSEUDOSECTION:\n");
   3559 		msg->indent.count++;
   3560 
   3561 		INDENT(style);
   3562 		ADD_STRING(target, "EDNS:\n");
   3563 		indent = ++msg->indent.count;
   3564 
   3565 		INDENT(style);
   3566 		ADD_STRING(target, "version: ");
   3567 		snprintf(buf, sizeof(buf), "%u",
   3568 			 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
   3569 		ADD_STRING(target, buf);
   3570 		ADD_STRING(target, "\n");
   3571 		INDENT(style);
   3572 		ADD_STRING(target, "flags:");
   3573 		if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) {
   3574 			ADD_STRING(target, " do");
   3575 		}
   3576 		ADD_STRING(target, "\n");
   3577 		mbz = ps->ttl & 0xffff;
   3578 		mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */
   3579 		if (mbz != 0) {
   3580 			INDENT(style);
   3581 			ADD_STRING(target, "MBZ: ");
   3582 			snprintf(buf, sizeof(buf), "0x%.4x", mbz);
   3583 			ADD_STRING(target, buf);
   3584 			ADD_STRING(target, "\n");
   3585 		}
   3586 		INDENT(style);
   3587 		ADD_STRING(target, "udp: ");
   3588 		snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
   3589 		ADD_STRING(target, buf);
   3590 		result = dns_rdataset_first(ps);
   3591 		if (result != ISC_R_SUCCESS) {
   3592 			result = ISC_R_SUCCESS;
   3593 			goto cleanup;
   3594 		}
   3595 
   3596 		/*
   3597 		 * Print EDNS info, if any.
   3598 		 *
   3599 		 * WARNING: The option contents may be malformed as
   3600 		 * dig +ednsopt=value:<content> does not perform validity
   3601 		 * checking.
   3602 		 */
   3603 		dns_rdata_init(&rdata);
   3604 		dns_rdataset_current(ps, &rdata);
   3605 
   3606 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
   3607 		isc_buffer_add(&optbuf, rdata.length);
   3608 		while (isc_buffer_remaininglength(&optbuf) != 0) {
   3609 			bool extra_text = false;
   3610 			msg->indent.count = indent;
   3611 			INSIST(isc_buffer_remaininglength(&optbuf) >= 4U);
   3612 			optcode = isc_buffer_getuint16(&optbuf);
   3613 			optlen = isc_buffer_getuint16(&optbuf);
   3614 			INSIST(isc_buffer_remaininglength(&optbuf) >= optlen);
   3615 
   3616 			if (optcode == DNS_OPT_LLQ) {
   3617 				INDENT(style);
   3618 				ADD_STRING(target, "LLQ:");
   3619 				if (optlen == 18U) {
   3620 					result = render_llq(&optbuf, target);
   3621 					if (result != ISC_R_SUCCESS) {
   3622 						goto cleanup;
   3623 					}
   3624 					ADD_STRING(target, "\n");
   3625 					continue;
   3626 				}
   3627 			} else if (optcode == DNS_OPT_NSID) {
   3628 				INDENT(style);
   3629 				ADD_STRING(target, "NSID:");
   3630 			} else if (optcode == DNS_OPT_COOKIE) {
   3631 				INDENT(style);
   3632 				ADD_STRING(target, "COOKIE:");
   3633 			} else if (optcode == DNS_OPT_CLIENT_SUBNET) {
   3634 				isc_buffer_t ecsbuf;
   3635 				INDENT(style);
   3636 				ADD_STRING(target, "CLIENT-SUBNET:");
   3637 				isc_buffer_init(&ecsbuf,
   3638 						isc_buffer_current(&optbuf),
   3639 						optlen);
   3640 				isc_buffer_add(&ecsbuf, optlen);
   3641 				result = render_ecs(&ecsbuf, target);
   3642 				if (result == ISC_R_NOSPACE) {
   3643 					goto cleanup;
   3644 				}
   3645 				if (result == ISC_R_SUCCESS) {
   3646 					isc_buffer_forward(&optbuf, optlen);
   3647 					ADD_STRING(target, "\n");
   3648 					continue;
   3649 				}
   3650 				ADD_STRING(target, "\n");
   3651 			} else if (optcode == DNS_OPT_EXPIRE) {
   3652 				INDENT(style);
   3653 				ADD_STRING(target, "EXPIRE:");
   3654 				if (optlen == 4) {
   3655 					uint32_t secs;
   3656 					secs = isc_buffer_getuint32(&optbuf);
   3657 					snprintf(buf, sizeof(buf), " %u", secs);
   3658 					ADD_STRING(target, buf);
   3659 					ADD_STRING(target, " (");
   3660 					result = dns_ttl_totext(secs, true,
   3661 								true, target);
   3662 					if (result != ISC_R_SUCCESS) {
   3663 						goto cleanup;
   3664 					}
   3665 					ADD_STRING(target, ")\n");
   3666 					continue;
   3667 				}
   3668 			} else if (optcode == DNS_OPT_TCP_KEEPALIVE) {
   3669 				if (optlen == 2) {
   3670 					unsigned int dsecs;
   3671 					dsecs = isc_buffer_getuint16(&optbuf);
   3672 					INDENT(style);
   3673 					ADD_STRING(target, "TCP-KEEPALIVE: ");
   3674 					snprintf(buf, sizeof(buf), "%u.%u",
   3675 						 dsecs / 10U, dsecs % 10U);
   3676 					ADD_STRING(target, buf);
   3677 					ADD_STRING(target, " secs\n");
   3678 					continue;
   3679 				}
   3680 				INDENT(style);
   3681 				ADD_STRING(target, "TCP-KEEPALIVE:");
   3682 			} else if (optcode == DNS_OPT_PAD) {
   3683 				INDENT(style);
   3684 				ADD_STRING(target, "PAD:");
   3685 			} else if (optcode == DNS_OPT_KEY_TAG) {
   3686 				INDENT(style);
   3687 				ADD_STRING(target, "KEY-TAG:");
   3688 				if (optlen > 0U && (optlen % 2U) == 0U) {
   3689 					const char *sep = "";
   3690 					uint16_t id;
   3691 					while (optlen > 0U) {
   3692 						id = isc_buffer_getuint16(
   3693 							&optbuf);
   3694 						snprintf(buf, sizeof(buf),
   3695 							 "%s %u", sep, id);
   3696 						ADD_STRING(target, buf);
   3697 						sep = ",";
   3698 						optlen -= 2;
   3699 					}
   3700 					ADD_STRING(target, "\n");
   3701 					continue;
   3702 				}
   3703 			} else if (optcode == DNS_OPT_EDE) {
   3704 				INDENT(style);
   3705 				ADD_STRING(target, "EDE:");
   3706 				if (optlen >= 2U) {
   3707 					uint16_t ede;
   3708 					ADD_STRING(target, "\n");
   3709 					msg->indent.count++;
   3710 					INDENT(style);
   3711 					ADD_STRING(target, "INFO-CODE:");
   3712 					ede = isc_buffer_getuint16(&optbuf);
   3713 					snprintf(buf, sizeof(buf), " %u", ede);
   3714 					ADD_STRING(target, buf);
   3715 					if (ede < ARRAY_SIZE(edetext)) {
   3716 						ADD_STRING(target, " (");
   3717 						ADD_STRING(target,
   3718 							   edetext[ede]);
   3719 						ADD_STRING(target, ")");
   3720 					}
   3721 					ADD_STRING(target, "\n");
   3722 					optlen -= 2;
   3723 					if (optlen != 0) {
   3724 						INDENT(style);
   3725 						ADD_STRING(target,
   3726 							   "EXTRA-TEXT:");
   3727 						extra_text = true;
   3728 					}
   3729 				}
   3730 			} else if (optcode == DNS_OPT_CLIENT_TAG) {
   3731 				uint16_t id;
   3732 				INDENT(style);
   3733 				ADD_STRING(target, "CLIENT-TAG:");
   3734 				if (optlen == 2U) {
   3735 					id = isc_buffer_getuint16(&optbuf);
   3736 					snprintf(buf, sizeof(buf), " %u\n", id);
   3737 					ADD_STRING(target, buf);
   3738 					optlen -= 2;
   3739 					POST(optlen);
   3740 					continue;
   3741 				}
   3742 			} else if (optcode == DNS_OPT_SERVER_TAG) {
   3743 				uint16_t id;
   3744 				INDENT(style);
   3745 				ADD_STRING(target, "SERVER-TAG:");
   3746 				if (optlen == 2U) {
   3747 					id = isc_buffer_getuint16(&optbuf);
   3748 					snprintf(buf, sizeof(buf), " %u\n", id);
   3749 					ADD_STRING(target, buf);
   3750 					optlen -= 2;
   3751 					POST(optlen);
   3752 					continue;
   3753 				}
   3754 			} else {
   3755 				INDENT(style);
   3756 				ADD_STRING(target, "OPT=");
   3757 				snprintf(buf, sizeof(buf), "%u:", optcode);
   3758 				ADD_STRING(target, buf);
   3759 			}
   3760 
   3761 			if (optlen != 0) {
   3762 				int i;
   3763 				bool utf8ok = false;
   3764 
   3765 				ADD_STRING(target, " ");
   3766 
   3767 				optdata = isc_buffer_current(&optbuf);
   3768 				if (extra_text) {
   3769 					utf8ok = isc_utf8_valid(optdata,
   3770 								optlen);
   3771 				}
   3772 				if (!utf8ok) {
   3773 					for (i = 0; i < optlen; i++) {
   3774 						const char *sep;
   3775 						switch (optcode) {
   3776 						case DNS_OPT_COOKIE:
   3777 							sep = "";
   3778 							break;
   3779 						default:
   3780 							sep = " ";
   3781 							break;
   3782 						}
   3783 						snprintf(buf, sizeof(buf),
   3784 							 "%02x%s", optdata[i],
   3785 							 sep);
   3786 						ADD_STRING(target, buf);
   3787 					}
   3788 				}
   3789 
   3790 				isc_buffer_forward(&optbuf, optlen);
   3791 
   3792 				if (optcode == DNS_OPT_COOKIE) {
   3793 					/*
   3794 					 * Valid server cookie?
   3795 					 */
   3796 					if (msg->cc_ok && optlen >= 16) {
   3797 						ADD_STRING(target, " (good)");
   3798 					}
   3799 					/*
   3800 					 * Server cookie is not valid but
   3801 					 * we had our cookie echoed back.
   3802 					 */
   3803 					if (msg->cc_ok && optlen < 16) {
   3804 						ADD_STRING(target, " (echoed)");
   3805 					}
   3806 					/*
   3807 					 * We didn't get our cookie echoed
   3808 					 * back.
   3809 					 */
   3810 					if (msg->cc_bad) {
   3811 						ADD_STRING(target, " (bad)");
   3812 					}
   3813 					ADD_STRING(target, "\n");
   3814 					continue;
   3815 				}
   3816 
   3817 				if (optcode == DNS_OPT_CLIENT_SUBNET) {
   3818 					ADD_STRING(target, "\n");
   3819 					continue;
   3820 				}
   3821 
   3822 				/*
   3823 				 * For non-COOKIE options, add a printable
   3824 				 * version
   3825 				 */
   3826 				if (!extra_text) {
   3827 					ADD_STRING(target, "(\"");
   3828 				} else {
   3829 					ADD_STRING(target, "\"");
   3830 				}
   3831 				if (isc_buffer_availablelength(target) < optlen)
   3832 				{
   3833 					result = ISC_R_NOSPACE;
   3834 					goto cleanup;
   3835 				}
   3836 				for (i = 0; i < optlen; i++) {
   3837 					if (isprint(optdata[i]) ||
   3838 					    (utf8ok && optdata[i] > 127))
   3839 					{
   3840 						isc_buffer_putmem(
   3841 							target, &optdata[i], 1);
   3842 					} else {
   3843 						isc_buffer_putstr(target, ".");
   3844 					}
   3845 				}
   3846 				if (!extra_text) {
   3847 					ADD_STRING(target, "\")");
   3848 				} else {
   3849 					ADD_STRING(target, "\"");
   3850 				}
   3851 			}
   3852 			ADD_STRING(target, "\n");
   3853 		}
   3854 		msg->indent.count = indent;
   3855 		result = ISC_R_SUCCESS;
   3856 		goto cleanup;
   3857 	case DNS_PSEUDOSECTION_TSIG:
   3858 		ps = dns_message_gettsig(msg, &name);
   3859 		if (ps == NULL) {
   3860 			result = ISC_R_SUCCESS;
   3861 			goto cleanup;
   3862 		}
   3863 		INDENT(style);
   3864 		ADD_STRING(target, "TSIG_PSEUDOSECTION:\n");
   3865 		result = dns_master_rdatasettotext(name, ps, style,
   3866 						   &msg->indent, target);
   3867 		ADD_STRING(target, "\n");
   3868 		goto cleanup;
   3869 	case DNS_PSEUDOSECTION_SIG0:
   3870 		ps = dns_message_getsig0(msg, &name);
   3871 		if (ps == NULL) {
   3872 			result = ISC_R_SUCCESS;
   3873 			goto cleanup;
   3874 		}
   3875 		INDENT(style);
   3876 		ADD_STRING(target, "SIG0_PSEUDOSECTION:\n");
   3877 		result = dns_master_rdatasettotext(name, ps, style,
   3878 						   &msg->indent, target);
   3879 		if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
   3880 		    (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
   3881 		{
   3882 			ADD_STRING(target, "\n");
   3883 		}
   3884 		goto cleanup;
   3885 	}
   3886 
   3887 	result = ISC_R_UNEXPECTED;
   3888 
   3889 cleanup:
   3890 	msg->indent.count = saved_count;
   3891 	return (result);
   3892 }
   3893 
   3894 isc_result_t
   3895 dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section,
   3896 				const dns_master_style_t *style,
   3897 				dns_messagetextflag_t flags,
   3898 				isc_buffer_t *target) {
   3899 	dns_rdataset_t *ps = NULL;
   3900 	const dns_name_t *name = NULL;
   3901 	isc_result_t result;
   3902 	char buf[sizeof(" (65000 bytes)")];
   3903 	uint32_t mbz;
   3904 	dns_rdata_t rdata;
   3905 	isc_buffer_t optbuf;
   3906 	uint16_t optcode, optlen;
   3907 	unsigned char *optdata;
   3908 
   3909 	REQUIRE(DNS_MESSAGE_VALID(msg));
   3910 	REQUIRE(target != NULL);
   3911 	REQUIRE(VALID_PSEUDOSECTION(section));
   3912 
   3913 	if ((dns_master_styleflags(style) & DNS_STYLEFLAG_YAML) != 0) {
   3914 		return (dns_message_pseudosectiontoyaml(msg, section, style,
   3915 							flags, target));
   3916 	}
   3917 
   3918 	switch (section) {
   3919 	case DNS_PSEUDOSECTION_OPT:
   3920 		ps = dns_message_getopt(msg);
   3921 		if (ps == NULL) {
   3922 			return (ISC_R_SUCCESS);
   3923 		}
   3924 		if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
   3925 			INDENT(style);
   3926 			ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
   3927 		}
   3928 
   3929 		INDENT(style);
   3930 		ADD_STRING(target, "; EDNS: version: ");
   3931 		snprintf(buf, sizeof(buf), "%u",
   3932 			 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
   3933 		ADD_STRING(target, buf);
   3934 		ADD_STRING(target, ", flags:");
   3935 		if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) {
   3936 			ADD_STRING(target, " do");
   3937 		}
   3938 		mbz = ps->ttl & 0xffff;
   3939 		mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */
   3940 		if (mbz != 0) {
   3941 			ADD_STRING(target, "; MBZ: ");
   3942 			snprintf(buf, sizeof(buf), "0x%.4x", mbz);
   3943 			ADD_STRING(target, buf);
   3944 			ADD_STRING(target, ", udp: ");
   3945 		} else {
   3946 			ADD_STRING(target, "; udp: ");
   3947 		}
   3948 		snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
   3949 		ADD_STRING(target, buf);
   3950 
   3951 		result = dns_rdataset_first(ps);
   3952 		if (result != ISC_R_SUCCESS) {
   3953 			return (ISC_R_SUCCESS);
   3954 		}
   3955 
   3956 		/*
   3957 		 * Print EDNS info, if any.
   3958 		 *
   3959 		 * WARNING: The option contents may be malformed as
   3960 		 * dig +ednsopt=value:<content> does no validity
   3961 		 * checking.
   3962 		 */
   3963 		dns_rdata_init(&rdata);
   3964 		dns_rdataset_current(ps, &rdata);
   3965 
   3966 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
   3967 		isc_buffer_add(&optbuf, rdata.length);
   3968 		while (isc_buffer_remaininglength(&optbuf) != 0) {
   3969 			INSIST(isc_buffer_remaininglength(&optbuf) >= 4U);
   3970 			optcode = isc_buffer_getuint16(&optbuf);
   3971 			optlen = isc_buffer_getuint16(&optbuf);
   3972 
   3973 			INSIST(isc_buffer_remaininglength(&optbuf) >= optlen);
   3974 
   3975 			INDENT(style);
   3976 
   3977 			if (optcode == DNS_OPT_LLQ) {
   3978 				ADD_STRING(target, "; LLQ:");
   3979 				if (optlen == 18U) {
   3980 					result = render_llq(&optbuf, target);
   3981 					if (result != ISC_R_SUCCESS) {
   3982 						return (result);
   3983 					}
   3984 					ADD_STRING(target, "\n");
   3985 					continue;
   3986 				}
   3987 			} else if (optcode == DNS_OPT_NSID) {
   3988 				ADD_STRING(target, "; NSID:");
   3989 			} else if (optcode == DNS_OPT_COOKIE) {
   3990 				ADD_STRING(target, "; COOKIE:");
   3991 			} else if (optcode == DNS_OPT_CLIENT_SUBNET) {
   3992 				isc_buffer_t ecsbuf;
   3993 
   3994 				ADD_STRING(target, "; CLIENT-SUBNET:");
   3995 				isc_buffer_init(&ecsbuf,
   3996 						isc_buffer_current(&optbuf),
   3997 						optlen);
   3998 				isc_buffer_add(&ecsbuf, optlen);
   3999 				result = render_ecs(&ecsbuf, target);
   4000 				if (result == ISC_R_NOSPACE) {
   4001 					return (result);
   4002 				}
   4003 				if (result == ISC_R_SUCCESS) {
   4004 					isc_buffer_forward(&optbuf, optlen);
   4005 					ADD_STRING(target, "\n");
   4006 					continue;
   4007 				}
   4008 			} else if (optcode == DNS_OPT_EXPIRE) {
   4009 				ADD_STRING(target, "; EXPIRE:");
   4010 				if (optlen == 4) {
   4011 					uint32_t secs;
   4012 					secs = isc_buffer_getuint32(&optbuf);
   4013 					snprintf(buf, sizeof(buf), " %u", secs);
   4014 					ADD_STRING(target, buf);
   4015 					ADD_STRING(target, " (");
   4016 					result = dns_ttl_totext(secs, true,
   4017 								true, target);
   4018 					if (result != ISC_R_SUCCESS) {
   4019 						return (result);
   4020 					}
   4021 					ADD_STRING(target, ")\n");
   4022 					continue;
   4023 				}
   4024 			} else if (optcode == DNS_OPT_TCP_KEEPALIVE) {
   4025 				ADD_STRING(target, "; TCP KEEPALIVE:");
   4026 				if (optlen == 2) {
   4027 					unsigned int dsecs;
   4028 					dsecs = isc_buffer_getuint16(&optbuf);
   4029 					snprintf(buf, sizeof(buf), " %u.%u",
   4030 						 dsecs / 10U, dsecs % 10U);
   4031 					ADD_STRING(target, buf);
   4032 					ADD_STRING(target, " secs\n");
   4033 					continue;
   4034 				}
   4035 			} else if (optcode == DNS_OPT_PAD) {
   4036 				ADD_STRING(target, "; PAD:");
   4037 				if (optlen > 0U) {
   4038 					snprintf(buf, sizeof(buf),
   4039 						 " (%u bytes)", optlen);
   4040 					ADD_STRING(target, buf);
   4041 					isc_buffer_forward(&optbuf, optlen);
   4042 				}
   4043 				ADD_STRING(target, "\n");
   4044 				continue;
   4045 			} else if (optcode == DNS_OPT_KEY_TAG) {
   4046 				ADD_STRING(target, "; KEY-TAG:");
   4047 				if (optlen > 0U && (optlen % 2U) == 0U) {
   4048 					const char *sep = "";
   4049 					uint16_t id;
   4050 					while (optlen > 0U) {
   4051 						id = isc_buffer_getuint16(
   4052 							&optbuf);
   4053 						snprintf(buf, sizeof(buf),
   4054 							 "%s %u", sep, id);
   4055 						ADD_STRING(target, buf);
   4056 						sep = ",";
   4057 						optlen -= 2;
   4058 					}
   4059 					ADD_STRING(target, "\n");
   4060 					continue;
   4061 				}
   4062 			} else if (optcode == DNS_OPT_EDE) {
   4063 				ADD_STRING(target, "; EDE:");
   4064 				if (optlen >= 2U) {
   4065 					uint16_t ede;
   4066 					ede = isc_buffer_getuint16(&optbuf);
   4067 					snprintf(buf, sizeof(buf), " %u", ede);
   4068 					ADD_STRING(target, buf);
   4069 					if (ede < ARRAY_SIZE(edetext)) {
   4070 						ADD_STRING(target, " (");
   4071 						ADD_STRING(target,
   4072 							   edetext[ede]);
   4073 						ADD_STRING(target, ")");
   4074 					}
   4075 					optlen -= 2;
   4076 					if (optlen != 0) {
   4077 						ADD_STRING(target, ":");
   4078 					}
   4079 				} else if (optlen == 1U) {
   4080 					/* Malformed */
   4081 					optdata = isc_buffer_current(&optbuf);
   4082 					snprintf(buf, sizeof(buf),
   4083 						 " %02x (\"%c\")\n", optdata[0],
   4084 						 isprint(optdata[0])
   4085 							 ? optdata[0]
   4086 							 : '.');
   4087 					isc_buffer_forward(&optbuf, optlen);
   4088 					ADD_STRING(target, buf);
   4089 					continue;
   4090 				}
   4091 			} else if (optcode == DNS_OPT_CLIENT_TAG) {
   4092 				uint16_t id;
   4093 				ADD_STRING(target, "; CLIENT-TAG:");
   4094 				if (optlen == 2U) {
   4095 					id = isc_buffer_getuint16(&optbuf);
   4096 					snprintf(buf, sizeof(buf), " %u\n", id);
   4097 					ADD_STRING(target, buf);
   4098 					optlen -= 2;
   4099 					POST(optlen);
   4100 					continue;
   4101 				}
   4102 			} else if (optcode == DNS_OPT_SERVER_TAG) {
   4103 				uint16_t id;
   4104 				ADD_STRING(target, "; SERVER-TAG:");
   4105 				if (optlen == 2U) {
   4106 					id = isc_buffer_getuint16(&optbuf);
   4107 					snprintf(buf, sizeof(buf), " %u\n", id);
   4108 					ADD_STRING(target, buf);
   4109 					optlen -= 2;
   4110 					POST(optlen);
   4111 					continue;
   4112 				}
   4113 			} else {
   4114 				ADD_STRING(target, "; OPT=");
   4115 				snprintf(buf, sizeof(buf), "%u:", optcode);
   4116 				ADD_STRING(target, buf);
   4117 			}
   4118 
   4119 			if (optlen != 0) {
   4120 				int i;
   4121 				bool utf8ok = false;
   4122 
   4123 				ADD_STRING(target, " ");
   4124 
   4125 				optdata = isc_buffer_current(&optbuf);
   4126 				if (optcode == DNS_OPT_EDE) {
   4127 					utf8ok = isc_utf8_valid(optdata,
   4128 								optlen);
   4129 				}
   4130 				if (!utf8ok) {
   4131 					for (i = 0; i < optlen; i++) {
   4132 						const char *sep;
   4133 						switch (optcode) {
   4134 						case DNS_OPT_COOKIE:
   4135 							sep = "";
   4136 							break;
   4137 						default:
   4138 							sep = " ";
   4139 							break;
   4140 						}
   4141 						snprintf(buf, sizeof(buf),
   4142 							 "%02x%s", optdata[i],
   4143 							 sep);
   4144 						ADD_STRING(target, buf);
   4145 					}
   4146 				}
   4147 
   4148 				isc_buffer_forward(&optbuf, optlen);
   4149 
   4150 				if (optcode == DNS_OPT_COOKIE) {
   4151 					/*
   4152 					 * Valid server cookie?
   4153 					 */
   4154 					if (msg->cc_ok && optlen >= 16) {
   4155 						ADD_STRING(target, " (good)");
   4156 					}
   4157 					/*
   4158 					 * Server cookie is not valid but
   4159 					 * we had our cookie echoed back.
   4160 					 */
   4161 					if (msg->cc_ok && optlen < 16) {
   4162 						ADD_STRING(target, " (echoed)");
   4163 					}
   4164 					/*
   4165 					 * We didn't get our cookie echoed
   4166 					 * back.
   4167 					 */
   4168 					if (msg->cc_bad) {
   4169 						ADD_STRING(target, " (bad)");
   4170 					}
   4171 					ADD_STRING(target, "\n");
   4172 					continue;
   4173 				}
   4174 
   4175 				if (optcode == DNS_OPT_CLIENT_SUBNET) {
   4176 					ADD_STRING(target, "\n");
   4177 					continue;
   4178 				}
   4179 
   4180 				/*
   4181 				 * For non-COOKIE options, add a printable
   4182 				 * version.
   4183 				 */
   4184 				if (optcode != DNS_OPT_EDE) {
   4185 					ADD_STRING(target, "(\"");
   4186 				} else {
   4187 					ADD_STRING(target, "(");
   4188 				}
   4189 				if (isc_buffer_availablelength(target) < optlen)
   4190 				{
   4191 					return (ISC_R_NOSPACE);
   4192 				}
   4193 				for (i = 0; i < optlen; i++) {
   4194 					if (isprint(optdata[i]) ||
   4195 					    (utf8ok && optdata[i] > 127))
   4196 					{
   4197 						isc_buffer_putmem(
   4198 							target, &optdata[i], 1);
   4199 					} else {
   4200 						isc_buffer_putstr(target, ".");
   4201 					}
   4202 				}
   4203 				if (optcode != DNS_OPT_EDE) {
   4204 					ADD_STRING(target, "\")");
   4205 				} else {
   4206 					ADD_STRING(target, ")");
   4207 				}
   4208 			}
   4209 			ADD_STRING(target, "\n");
   4210 		}
   4211 		return (ISC_R_SUCCESS);
   4212 	case DNS_PSEUDOSECTION_TSIG:
   4213 		ps = dns_message_gettsig(msg, &name);
   4214 		if (ps == NULL) {
   4215 			return (ISC_R_SUCCESS);
   4216 		}
   4217 		INDENT(style);
   4218 		if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
   4219 			ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
   4220 		}
   4221 		result = dns_master_rdatasettotext(name, ps, style,
   4222 						   &msg->indent, target);
   4223 		if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
   4224 		    (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
   4225 		{
   4226 			ADD_STRING(target, "\n");
   4227 		}
   4228 		return (result);
   4229 	case DNS_PSEUDOSECTION_SIG0:
   4230 		ps = dns_message_getsig0(msg, &name);
   4231 		if (ps == NULL) {
   4232 			return (ISC_R_SUCCESS);
   4233 		}
   4234 		INDENT(style);
   4235 		if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
   4236 			ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
   4237 		}
   4238 		result = dns_master_rdatasettotext(name, ps, style,
   4239 						   &msg->indent, target);
   4240 		if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
   4241 		    (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
   4242 		{
   4243 			ADD_STRING(target, "\n");
   4244 		}
   4245 		return (result);
   4246 	}
   4247 	result = ISC_R_UNEXPECTED;
   4248 cleanup:
   4249 	return (result);
   4250 }
   4251 
   4252 isc_result_t
   4253 dns_message_headertotext(dns_message_t *msg, const dns_master_style_t *style,
   4254 			 dns_messagetextflag_t flags, isc_buffer_t *target) {
   4255 	char buf[sizeof("1234567890")];
   4256 	isc_result_t result;
   4257 
   4258 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4259 	REQUIRE(target != NULL);
   4260 
   4261 	if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) != 0) {
   4262 		return (ISC_R_SUCCESS);
   4263 	}
   4264 
   4265 	if (dns_master_styleflags(style) & DNS_STYLEFLAG_YAML) {
   4266 		INDENT(style);
   4267 		ADD_STRING(target, "opcode: ");
   4268 		ADD_STRING(target, opcodetext[msg->opcode]);
   4269 		ADD_STRING(target, "\n");
   4270 		INDENT(style);
   4271 		ADD_STRING(target, "status: ");
   4272 		result = dns_rcode_totext(msg->rcode, target);
   4273 		if (result != ISC_R_SUCCESS) {
   4274 			return (result);
   4275 		}
   4276 		ADD_STRING(target, "\n");
   4277 		INDENT(style);
   4278 		ADD_STRING(target, "id: ");
   4279 		snprintf(buf, sizeof(buf), "%u", msg->id);
   4280 		ADD_STRING(target, buf);
   4281 		ADD_STRING(target, "\n");
   4282 		INDENT(style);
   4283 		ADD_STRING(target, "flags:");
   4284 		if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
   4285 			ADD_STRING(target, " qr");
   4286 		}
   4287 		if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
   4288 			ADD_STRING(target, " aa");
   4289 		}
   4290 		if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   4291 			ADD_STRING(target, " tc");
   4292 		}
   4293 		if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
   4294 			ADD_STRING(target, " rd");
   4295 		}
   4296 		if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
   4297 			ADD_STRING(target, " ra");
   4298 		}
   4299 		if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
   4300 			ADD_STRING(target, " ad");
   4301 		}
   4302 		if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
   4303 			ADD_STRING(target, " cd");
   4304 		}
   4305 		ADD_STRING(target, "\n");
   4306 		/*
   4307 		 * The final unnamed flag must be zero.
   4308 		 */
   4309 		if ((msg->flags & 0x0040U) != 0) {
   4310 			INDENT(style);
   4311 			ADD_STRING(target, "MBZ: 0x4");
   4312 			ADD_STRING(target, "\n");
   4313 		}
   4314 		if (msg->opcode != dns_opcode_update) {
   4315 			INDENT(style);
   4316 			ADD_STRING(target, "QUESTION: ");
   4317 		} else {
   4318 			INDENT(style);
   4319 			ADD_STRING(target, "ZONE: ");
   4320 		}
   4321 		snprintf(buf, sizeof(buf), "%1u",
   4322 			 msg->counts[DNS_SECTION_QUESTION]);
   4323 		ADD_STRING(target, buf);
   4324 		ADD_STRING(target, "\n");
   4325 		if (msg->opcode != dns_opcode_update) {
   4326 			INDENT(style);
   4327 			ADD_STRING(target, "ANSWER: ");
   4328 		} else {
   4329 			INDENT(style);
   4330 			ADD_STRING(target, "PREREQ: ");
   4331 		}
   4332 		snprintf(buf, sizeof(buf), "%1u",
   4333 			 msg->counts[DNS_SECTION_ANSWER]);
   4334 		ADD_STRING(target, buf);
   4335 		ADD_STRING(target, "\n");
   4336 		if (msg->opcode != dns_opcode_update) {
   4337 			INDENT(style);
   4338 			ADD_STRING(target, "AUTHORITY: ");
   4339 		} else {
   4340 			INDENT(style);
   4341 			ADD_STRING(target, "UPDATE: ");
   4342 		}
   4343 		snprintf(buf, sizeof(buf), "%1u",
   4344 			 msg->counts[DNS_SECTION_AUTHORITY]);
   4345 		ADD_STRING(target, buf);
   4346 		ADD_STRING(target, "\n");
   4347 		INDENT(style);
   4348 		ADD_STRING(target, "ADDITIONAL: ");
   4349 		snprintf(buf, sizeof(buf), "%1u",
   4350 			 msg->counts[DNS_SECTION_ADDITIONAL]);
   4351 		ADD_STRING(target, buf);
   4352 		ADD_STRING(target, "\n");
   4353 	} else {
   4354 		INDENT(style);
   4355 		ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
   4356 		ADD_STRING(target, opcodetext[msg->opcode]);
   4357 		ADD_STRING(target, ", status: ");
   4358 		result = dns_rcode_totext(msg->rcode, target);
   4359 		if (result != ISC_R_SUCCESS) {
   4360 			return (result);
   4361 		}
   4362 		ADD_STRING(target, ", id: ");
   4363 		snprintf(buf, sizeof(buf), "%6u", msg->id);
   4364 		ADD_STRING(target, buf);
   4365 		ADD_STRING(target, "\n");
   4366 		INDENT(style);
   4367 		ADD_STRING(target, ";; flags:");
   4368 		if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
   4369 			ADD_STRING(target, " qr");
   4370 		}
   4371 		if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
   4372 			ADD_STRING(target, " aa");
   4373 		}
   4374 		if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   4375 			ADD_STRING(target, " tc");
   4376 		}
   4377 		if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
   4378 			ADD_STRING(target, " rd");
   4379 		}
   4380 		if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
   4381 			ADD_STRING(target, " ra");
   4382 		}
   4383 		if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
   4384 			ADD_STRING(target, " ad");
   4385 		}
   4386 		if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
   4387 			ADD_STRING(target, " cd");
   4388 		}
   4389 		/*
   4390 		 * The final unnamed flag must be zero.
   4391 		 */
   4392 		if ((msg->flags & 0x0040U) != 0) {
   4393 			INDENT(style);
   4394 			ADD_STRING(target, "; MBZ: 0x4");
   4395 		}
   4396 		if (msg->opcode != dns_opcode_update) {
   4397 			INDENT(style);
   4398 			ADD_STRING(target, "; QUESTION: ");
   4399 		} else {
   4400 			INDENT(style);
   4401 			ADD_STRING(target, "; ZONE: ");
   4402 		}
   4403 		snprintf(buf, sizeof(buf), "%1u",
   4404 			 msg->counts[DNS_SECTION_QUESTION]);
   4405 		ADD_STRING(target, buf);
   4406 		if (msg->opcode != dns_opcode_update) {
   4407 			ADD_STRING(target, ", ANSWER: ");
   4408 		} else {
   4409 			ADD_STRING(target, ", PREREQ: ");
   4410 		}
   4411 		snprintf(buf, sizeof(buf), "%1u",
   4412 			 msg->counts[DNS_SECTION_ANSWER]);
   4413 		ADD_STRING(target, buf);
   4414 		if (msg->opcode != dns_opcode_update) {
   4415 			ADD_STRING(target, ", AUTHORITY: ");
   4416 		} else {
   4417 			ADD_STRING(target, ", UPDATE: ");
   4418 		}
   4419 		snprintf(buf, sizeof(buf), "%1u",
   4420 			 msg->counts[DNS_SECTION_AUTHORITY]);
   4421 		ADD_STRING(target, buf);
   4422 		ADD_STRING(target, ", ADDITIONAL: ");
   4423 		snprintf(buf, sizeof(buf), "%1u",
   4424 			 msg->counts[DNS_SECTION_ADDITIONAL]);
   4425 		ADD_STRING(target, buf);
   4426 		ADD_STRING(target, "\n");
   4427 	}
   4428 
   4429 cleanup:
   4430 	return (result);
   4431 }
   4432 
   4433 isc_result_t
   4434 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
   4435 		   dns_messagetextflag_t flags, isc_buffer_t *target) {
   4436 	isc_result_t result;
   4437 
   4438 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4439 	REQUIRE(target != NULL);
   4440 
   4441 	result = dns_message_headertotext(msg, style, flags, target);
   4442 	if (result != ISC_R_SUCCESS) {
   4443 		return (result);
   4444 	}
   4445 
   4446 	result = dns_message_pseudosectiontotext(msg, DNS_PSEUDOSECTION_OPT,
   4447 						 style, flags, target);
   4448 	if (result != ISC_R_SUCCESS) {
   4449 		return (result);
   4450 	}
   4451 
   4452 	result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, style,
   4453 					   flags, target);
   4454 	if (result != ISC_R_SUCCESS) {
   4455 		return (result);
   4456 	}
   4457 
   4458 	result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, style,
   4459 					   flags, target);
   4460 	if (result != ISC_R_SUCCESS) {
   4461 		return (result);
   4462 	}
   4463 
   4464 	result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, style,
   4465 					   flags, target);
   4466 	if (result != ISC_R_SUCCESS) {
   4467 		return (result);
   4468 	}
   4469 
   4470 	result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, style,
   4471 					   flags, target);
   4472 	if (result != ISC_R_SUCCESS) {
   4473 		return (result);
   4474 	}
   4475 
   4476 	result = dns_message_pseudosectiontotext(msg, DNS_PSEUDOSECTION_TSIG,
   4477 						 style, flags, target);
   4478 	if (result != ISC_R_SUCCESS) {
   4479 		return (result);
   4480 	}
   4481 
   4482 	result = dns_message_pseudosectiontotext(msg, DNS_PSEUDOSECTION_SIG0,
   4483 						 style, flags, target);
   4484 	return (result);
   4485 }
   4486 
   4487 isc_region_t *
   4488 dns_message_getrawmessage(dns_message_t *msg) {
   4489 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4490 	return (&msg->saved);
   4491 }
   4492 
   4493 void
   4494 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
   4495 			 dns_aclenv_t *env, const dns_acl_t *acl,
   4496 			 const dns_aclelement_t *elem) {
   4497 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4498 	REQUIRE((order == NULL) == (env == NULL));
   4499 	REQUIRE(env == NULL || (acl != NULL || elem != NULL));
   4500 
   4501 	msg->order = order;
   4502 	msg->order_arg.env = env;
   4503 	msg->order_arg.acl = acl;
   4504 	msg->order_arg.element = elem;
   4505 }
   4506 
   4507 void
   4508 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
   4509 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4510 	msg->timeadjust = timeadjust;
   4511 }
   4512 
   4513 int
   4514 dns_message_gettimeadjust(dns_message_t *msg) {
   4515 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4516 	return (msg->timeadjust);
   4517 }
   4518 
   4519 isc_result_t
   4520 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
   4521 	REQUIRE(opcode < 16);
   4522 
   4523 	if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode])) {
   4524 		return (ISC_R_NOSPACE);
   4525 	}
   4526 	isc_buffer_putstr(target, opcodetext[opcode]);
   4527 	return (ISC_R_SUCCESS);
   4528 }
   4529 
   4530 void
   4531 dns_message_logpacket(dns_message_t *message, const char *description,
   4532 		      const isc_sockaddr_t *address,
   4533 		      isc_logcategory_t *category, isc_logmodule_t *module,
   4534 		      int level, isc_mem_t *mctx) {
   4535 	REQUIRE(address != NULL);
   4536 
   4537 	logfmtpacket(message, description, address, category, module,
   4538 		     &dns_master_style_debug, level, mctx);
   4539 }
   4540 
   4541 void
   4542 dns_message_logfmtpacket(dns_message_t *message, const char *description,
   4543 			 const isc_sockaddr_t *address,
   4544 			 isc_logcategory_t *category, isc_logmodule_t *module,
   4545 			 const dns_master_style_t *style, int level,
   4546 			 isc_mem_t *mctx) {
   4547 	REQUIRE(address != NULL);
   4548 
   4549 	logfmtpacket(message, description, address, category, module, style,
   4550 		     level, mctx);
   4551 }
   4552 
   4553 static void
   4554 logfmtpacket(dns_message_t *message, const char *description,
   4555 	     const isc_sockaddr_t *address, isc_logcategory_t *category,
   4556 	     isc_logmodule_t *module, const dns_master_style_t *style,
   4557 	     int level, isc_mem_t *mctx) {
   4558 	char addrbuf[ISC_SOCKADDR_FORMATSIZE] = { 0 };
   4559 	const char *newline = "\n";
   4560 	const char *space = " ";
   4561 	isc_buffer_t buffer;
   4562 	char *buf = NULL;
   4563 	int len = 1024;
   4564 	isc_result_t result;
   4565 
   4566 	if (!isc_log_wouldlog(dns_lctx, level)) {
   4567 		return;
   4568 	}
   4569 
   4570 	/*
   4571 	 * Note that these are multiline debug messages.  We want a newline
   4572 	 * to appear in the log after each message.
   4573 	 */
   4574 
   4575 	if (address != NULL) {
   4576 		isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
   4577 	} else {
   4578 		newline = space = "";
   4579 	}
   4580 
   4581 	do {
   4582 		buf = isc_mem_get(mctx, len);
   4583 		isc_buffer_init(&buffer, buf, len);
   4584 		result = dns_message_totext(message, style, 0, &buffer);
   4585 		if (result == ISC_R_NOSPACE) {
   4586 			isc_mem_put(mctx, buf, len);
   4587 			len += 1024;
   4588 		} else if (result == ISC_R_SUCCESS) {
   4589 			isc_log_write(dns_lctx, category, module, level,
   4590 				      "%s%s%s%s%.*s", description, space,
   4591 				      addrbuf, newline,
   4592 				      (int)isc_buffer_usedlength(&buffer), buf);
   4593 		}
   4594 	} while (result == ISC_R_NOSPACE);
   4595 
   4596 	if (buf != NULL) {
   4597 		isc_mem_put(mctx, buf, len);
   4598 	}
   4599 }
   4600 
   4601 isc_result_t
   4602 dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
   4603 		     unsigned int version, uint16_t udpsize, unsigned int flags,
   4604 		     dns_ednsopt_t *ednsopts, size_t count) {
   4605 	dns_rdataset_t *rdataset = NULL;
   4606 	dns_rdatalist_t *rdatalist = NULL;
   4607 	dns_rdata_t *rdata = NULL;
   4608 	isc_result_t result;
   4609 	unsigned int len = 0, i;
   4610 
   4611 	REQUIRE(DNS_MESSAGE_VALID(message));
   4612 	REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
   4613 
   4614 	result = dns_message_gettemprdatalist(message, &rdatalist);
   4615 	if (result != ISC_R_SUCCESS) {
   4616 		return (result);
   4617 	}
   4618 	result = dns_message_gettemprdata(message, &rdata);
   4619 	if (result != ISC_R_SUCCESS) {
   4620 		goto cleanup;
   4621 	}
   4622 	result = dns_message_gettemprdataset(message, &rdataset);
   4623 	if (result != ISC_R_SUCCESS) {
   4624 		goto cleanup;
   4625 	}
   4626 
   4627 	rdatalist->type = dns_rdatatype_opt;
   4628 
   4629 	/*
   4630 	 * Set Maximum UDP buffer size.
   4631 	 */
   4632 	rdatalist->rdclass = udpsize;
   4633 
   4634 	/*
   4635 	 * Set EXTENDED-RCODE and Z to 0.
   4636 	 */
   4637 	rdatalist->ttl = (version << 16);
   4638 	rdatalist->ttl |= (flags & 0xffff);
   4639 
   4640 	/*
   4641 	 * Set EDNS options if applicable
   4642 	 */
   4643 	if (count != 0U) {
   4644 		isc_buffer_t *buf = NULL;
   4645 		bool seenpad = false;
   4646 		for (i = 0; i < count; i++) {
   4647 			len += ednsopts[i].length + 4;
   4648 		}
   4649 
   4650 		if (len > 0xffffU) {
   4651 			result = ISC_R_NOSPACE;
   4652 			goto cleanup;
   4653 		}
   4654 
   4655 		isc_buffer_allocate(message->mctx, &buf, len);
   4656 
   4657 		for (i = 0; i < count; i++) {
   4658 			if (ednsopts[i].code == DNS_OPT_PAD &&
   4659 			    ednsopts[i].length == 0U && !seenpad)
   4660 			{
   4661 				seenpad = true;
   4662 				continue;
   4663 			}
   4664 			isc_buffer_putuint16(buf, ednsopts[i].code);
   4665 			isc_buffer_putuint16(buf, ednsopts[i].length);
   4666 			if (ednsopts[i].length != 0) {
   4667 				isc_buffer_putmem(buf, ednsopts[i].value,
   4668 						  ednsopts[i].length);
   4669 			}
   4670 		}
   4671 
   4672 		/* Padding must be the final option */
   4673 		if (seenpad) {
   4674 			isc_buffer_putuint16(buf, DNS_OPT_PAD);
   4675 			isc_buffer_putuint16(buf, 0);
   4676 		}
   4677 		rdata->data = isc_buffer_base(buf);
   4678 		rdata->length = len;
   4679 		dns_message_takebuffer(message, &buf);
   4680 		if (seenpad) {
   4681 			message->padding_off = len;
   4682 		}
   4683 	} else {
   4684 		rdata->data = NULL;
   4685 		rdata->length = 0;
   4686 	}
   4687 
   4688 	rdata->rdclass = rdatalist->rdclass;
   4689 	rdata->type = rdatalist->type;
   4690 	rdata->flags = 0;
   4691 
   4692 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
   4693 	result = dns_rdatalist_tordataset(rdatalist, rdataset);
   4694 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4695 
   4696 	*rdatasetp = rdataset;
   4697 	return (ISC_R_SUCCESS);
   4698 
   4699 cleanup:
   4700 	if (rdata != NULL) {
   4701 		dns_message_puttemprdata(message, &rdata);
   4702 	}
   4703 	if (rdataset != NULL) {
   4704 		dns_message_puttemprdataset(message, &rdataset);
   4705 	}
   4706 	if (rdatalist != NULL) {
   4707 		dns_message_puttemprdatalist(message, &rdatalist);
   4708 	}
   4709 	return (result);
   4710 }
   4711 
   4712 void
   4713 dns_message_setclass(dns_message_t *msg, dns_rdataclass_t rdclass) {
   4714 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4715 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
   4716 	REQUIRE(msg->state == DNS_SECTION_ANY);
   4717 	REQUIRE(msg->rdclass_set == 0);
   4718 
   4719 	msg->rdclass = rdclass;
   4720 	msg->rdclass_set = 1;
   4721 }
   4722 
   4723 void
   4724 dns_message_setpadding(dns_message_t *msg, uint16_t padding) {
   4725 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4726 
   4727 	/* Avoid silly large padding */
   4728 	if (padding > 512) {
   4729 		padding = 512;
   4730 	}
   4731 	msg->padding = padding;
   4732 }
   4733 
   4734 void
   4735 dns_message_clonebuffer(dns_message_t *msg) {
   4736 	REQUIRE(DNS_MESSAGE_VALID(msg));
   4737 
   4738 	if (msg->free_saved == 0 && msg->saved.base != NULL) {
   4739 		msg->saved.base =
   4740 			memmove(isc_mem_get(msg->mctx, msg->saved.length),
   4741 				msg->saved.base, msg->saved.length);
   4742 		msg->free_saved = 1;
   4743 	}
   4744 	if (msg->free_query == 0 && msg->query.base != NULL) {
   4745 		msg->query.base =
   4746 			memmove(isc_mem_get(msg->mctx, msg->query.length),
   4747 				msg->query.base, msg->query.length);
   4748 		msg->free_query = 1;
   4749 	}
   4750 }
   4751