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