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