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