xref: /minix/external/bsd/bind/dist/lib/dns/message.c (revision 00b67f09)
1 /*	$NetBSD: message.c,v 1.15 2015/07/08 17:28:58 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1999-2003  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id */
21 
22 /*! \file */
23 
24 /***
25  *** Imports
26  ***/
27 
28 #include <config.h>
29 #include <ctype.h>
30 
31 #include <isc/buffer.h>
32 #include <isc/mem.h>
33 #include <isc/print.h>
34 #include <isc/string.h>		/* Required for HP/UX (and others?) */
35 #include <isc/util.h>
36 
37 #include <dns/dnssec.h>
38 #include <dns/keyvalues.h>
39 #include <dns/log.h>
40 #include <dns/masterdump.h>
41 #include <dns/message.h>
42 #include <dns/opcode.h>
43 #include <dns/rdata.h>
44 #include <dns/rdatalist.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/result.h>
48 #include <dns/tsig.h>
49 #include <dns/ttl.h>
50 #include <dns/view.h>
51 
52 #ifdef SKAN_MSG_DEBUG
53 static void
hexdump(const char * msg,const char * msg2,void * base,size_t len)54 hexdump(const char *msg, const char *msg2, void *base, size_t len) {
55 	unsigned char *p;
56 	unsigned int cnt;
57 
58 	p = base;
59 	cnt = 0;
60 
61 	printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);
62 
63 	while (cnt < len) {
64 		if (cnt % 16 == 0)
65 			printf("%p: ", p);
66 		else if (cnt % 8 == 0)
67 			printf(" |");
68 		printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
69 		p++;
70 		cnt++;
71 
72 		if (cnt % 16 == 0)
73 			printf("\n");
74 	}
75 
76 	if (cnt % 16 != 0)
77 		printf("\n");
78 }
79 #endif
80 
81 #define DNS_MESSAGE_OPCODE_MASK		0x7800U
82 #define DNS_MESSAGE_OPCODE_SHIFT	11
83 #define DNS_MESSAGE_RCODE_MASK		0x000fU
84 #define DNS_MESSAGE_FLAG_MASK		0x8ff0U
85 #define DNS_MESSAGE_EDNSRCODE_MASK	0xff000000U
86 #define DNS_MESSAGE_EDNSRCODE_SHIFT	24
87 #define DNS_MESSAGE_EDNSVERSION_MASK	0x00ff0000U
88 #define DNS_MESSAGE_EDNSVERSION_SHIFT	16
89 
90 #define VALID_NAMED_SECTION(s)  (((s) > DNS_SECTION_ANY) \
91 				 && ((s) < DNS_SECTION_MAX))
92 #define VALID_SECTION(s)	(((s) >= DNS_SECTION_ANY) \
93 				 && ((s) < DNS_SECTION_MAX))
94 #define ADD_STRING(b, s)	{if (strlen(s) >= \
95 				   isc_buffer_availablelength(b)) \
96 				       return(ISC_R_NOSPACE); else \
97 				       isc_buffer_putstr(b, s);}
98 #define VALID_PSEUDOSECTION(s)	(((s) >= DNS_PSEUDOSECTION_ANY) \
99 				 && ((s) < DNS_PSEUDOSECTION_MAX))
100 
101 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
102 
103 /*%
104  * This is the size of each individual scratchpad buffer, and the numbers
105  * of various block allocations used within the server.
106  * XXXMLG These should come from a config setting.
107  */
108 #define SCRATCHPAD_SIZE		512
109 #define NAME_COUNT		  8
110 #define OFFSET_COUNT		  4
111 #define RDATA_COUNT		  8
112 #define RDATALIST_COUNT		  8
113 #define RDATASET_COUNT		 RDATALIST_COUNT
114 
115 /*%
116  * Text representation of the different items, for message_totext
117  * functions.
118  */
119 static const char *sectiontext[] = {
120 	"QUESTION",
121 	"ANSWER",
122 	"AUTHORITY",
123 	"ADDITIONAL"
124 };
125 
126 static const char *updsectiontext[] = {
127 	"ZONE",
128 	"PREREQUISITE",
129 	"UPDATE",
130 	"ADDITIONAL"
131 };
132 
133 static const char *opcodetext[] = {
134 	"QUERY",
135 	"IQUERY",
136 	"STATUS",
137 	"RESERVED3",
138 	"NOTIFY",
139 	"UPDATE",
140 	"RESERVED6",
141 	"RESERVED7",
142 	"RESERVED8",
143 	"RESERVED9",
144 	"RESERVED10",
145 	"RESERVED11",
146 	"RESERVED12",
147 	"RESERVED13",
148 	"RESERVED14",
149 	"RESERVED15"
150 };
151 
152 static const char *rcodetext[] = {
153 	"NOERROR",
154 	"FORMERR",
155 	"SERVFAIL",
156 	"NXDOMAIN",
157 	"NOTIMP",
158 	"REFUSED",
159 	"YXDOMAIN",
160 	"YXRRSET",
161 	"NXRRSET",
162 	"NOTAUTH",
163 	"NOTZONE",
164 	"RESERVED11",
165 	"RESERVED12",
166 	"RESERVED13",
167 	"RESERVED14",
168 	"RESERVED15",
169 	"BADVERS"
170 };
171 
172 
173 /*%
174  * "helper" type, which consists of a block of some type, and is linkable.
175  * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
176  * size, or the allocated elements will not be aligned correctly.
177  */
178 struct dns_msgblock {
179 	unsigned int			count;
180 	unsigned int			remaining;
181 	ISC_LINK(dns_msgblock_t)	link;
182 }; /* dynamically sized */
183 
184 static inline dns_msgblock_t *
185 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
186 
187 #define msgblock_get(block, type) \
188 	((type *)msgblock_internalget(block, sizeof(type)))
189 
190 static inline void *
191 msgblock_internalget(dns_msgblock_t *, unsigned int);
192 
193 static inline void
194 msgblock_reset(dns_msgblock_t *);
195 
196 static inline void
197 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
198 
199 /*
200  * Allocate a new dns_msgblock_t, and return a pointer to it.  If no memory
201  * is free, return NULL.
202  */
203 static inline dns_msgblock_t *
msgblock_allocate(isc_mem_t * mctx,unsigned int sizeof_type,unsigned int count)204 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
205 		  unsigned int count)
206 {
207 	dns_msgblock_t *block;
208 	unsigned int length;
209 
210 	length = sizeof(dns_msgblock_t) + (sizeof_type * count);
211 
212 	block = isc_mem_get(mctx, length);
213 	if (block == NULL)
214 		return (NULL);
215 
216 	block->count = count;
217 	block->remaining = count;
218 
219 	ISC_LINK_INIT(block, link);
220 
221 	return (block);
222 }
223 
224 /*
225  * Return an element from the msgblock.  If no more are available, return
226  * NULL.
227  */
228 static inline void *
msgblock_internalget(dns_msgblock_t * block,unsigned int sizeof_type)229 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
230 	void *ptr;
231 
232 	if (block == NULL || block->remaining == 0)
233 		return (NULL);
234 
235 	block->remaining--;
236 
237 	ptr = (((unsigned char *)block)
238 	       + sizeof(dns_msgblock_t)
239 	       + (sizeof_type * block->remaining));
240 
241 	return (ptr);
242 }
243 
244 static inline void
msgblock_reset(dns_msgblock_t * block)245 msgblock_reset(dns_msgblock_t *block) {
246 	block->remaining = block->count;
247 }
248 
249 /*
250  * Release memory associated with a message block.
251  */
252 static inline void
msgblock_free(isc_mem_t * mctx,dns_msgblock_t * block,unsigned int sizeof_type)253 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
254 {
255 	unsigned int length;
256 
257 	length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
258 
259 	isc_mem_put(mctx, block, length);
260 }
261 
262 /*
263  * Allocate a new dynamic buffer, and attach it to this message as the
264  * "current" buffer.  (which is always the last on the list, for our
265  * uses)
266  */
267 static inline isc_result_t
newbuffer(dns_message_t * msg,unsigned int size)268 newbuffer(dns_message_t *msg, unsigned int size) {
269 	isc_result_t result;
270 	isc_buffer_t *dynbuf;
271 
272 	dynbuf = NULL;
273 	result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
274 	if (result != ISC_R_SUCCESS)
275 		return (ISC_R_NOMEMORY);
276 
277 	ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
278 	return (ISC_R_SUCCESS);
279 }
280 
281 static inline isc_buffer_t *
currentbuffer(dns_message_t * msg)282 currentbuffer(dns_message_t *msg) {
283 	isc_buffer_t *dynbuf;
284 
285 	dynbuf = ISC_LIST_TAIL(msg->scratchpad);
286 	INSIST(dynbuf != NULL);
287 
288 	return (dynbuf);
289 }
290 
291 static inline void
releaserdata(dns_message_t * msg,dns_rdata_t * rdata)292 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
293 	ISC_LIST_PREPEND(msg->freerdata, rdata, link);
294 }
295 
296 static inline dns_rdata_t *
newrdata(dns_message_t * msg)297 newrdata(dns_message_t *msg) {
298 	dns_msgblock_t *msgblock;
299 	dns_rdata_t *rdata;
300 
301 	rdata = ISC_LIST_HEAD(msg->freerdata);
302 	if (rdata != NULL) {
303 		ISC_LIST_UNLINK(msg->freerdata, rdata, link);
304 		return (rdata);
305 	}
306 
307 	msgblock = ISC_LIST_TAIL(msg->rdatas);
308 	rdata = msgblock_get(msgblock, dns_rdata_t);
309 	if (rdata == NULL) {
310 		msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
311 					     RDATA_COUNT);
312 		if (msgblock == NULL)
313 			return (NULL);
314 
315 		ISC_LIST_APPEND(msg->rdatas, msgblock, link);
316 
317 		rdata = msgblock_get(msgblock, dns_rdata_t);
318 	}
319 
320 	dns_rdata_init(rdata);
321 	return (rdata);
322 }
323 
324 static inline void
releaserdatalist(dns_message_t * msg,dns_rdatalist_t * rdatalist)325 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
326 	ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
327 }
328 
329 static inline dns_rdatalist_t *
newrdatalist(dns_message_t * msg)330 newrdatalist(dns_message_t *msg) {
331 	dns_msgblock_t *msgblock;
332 	dns_rdatalist_t *rdatalist;
333 
334 	rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
335 	if (rdatalist != NULL) {
336 		ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
337 		return (rdatalist);
338 	}
339 
340 	msgblock = ISC_LIST_TAIL(msg->rdatalists);
341 	rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
342 	if (rdatalist == NULL) {
343 		msgblock = msgblock_allocate(msg->mctx,
344 					     sizeof(dns_rdatalist_t),
345 					     RDATALIST_COUNT);
346 		if (msgblock == NULL)
347 			return (NULL);
348 
349 		ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
350 
351 		rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
352 	}
353 
354 	return (rdatalist);
355 }
356 
357 static inline dns_offsets_t *
newoffsets(dns_message_t * msg)358 newoffsets(dns_message_t *msg) {
359 	dns_msgblock_t *msgblock;
360 	dns_offsets_t *offsets;
361 
362 	msgblock = ISC_LIST_TAIL(msg->offsets);
363 	offsets = msgblock_get(msgblock, dns_offsets_t);
364 	if (offsets == NULL) {
365 		msgblock = msgblock_allocate(msg->mctx,
366 					     sizeof(dns_offsets_t),
367 					     OFFSET_COUNT);
368 		if (msgblock == NULL)
369 			return (NULL);
370 
371 		ISC_LIST_APPEND(msg->offsets, msgblock, link);
372 
373 		offsets = msgblock_get(msgblock, dns_offsets_t);
374 	}
375 
376 	return (offsets);
377 }
378 
379 static inline void
msginitheader(dns_message_t * m)380 msginitheader(dns_message_t *m) {
381 	m->id = 0;
382 	m->flags = 0;
383 	m->rcode = 0;
384 	m->opcode = 0;
385 	m->rdclass = 0;
386 }
387 
388 static inline void
msginitprivate(dns_message_t * m)389 msginitprivate(dns_message_t *m) {
390 	unsigned int i;
391 
392 	for (i = 0; i < DNS_SECTION_MAX; i++) {
393 		m->cursors[i] = NULL;
394 		m->counts[i] = 0;
395 	}
396 	m->opt = NULL;
397 	m->sig0 = NULL;
398 	m->sig0name = NULL;
399 	m->tsig = NULL;
400 	m->tsigname = NULL;
401 	m->state = DNS_SECTION_ANY;  /* indicate nothing parsed or rendered */
402 	m->opt_reserved = 0;
403 	m->sig_reserved = 0;
404 	m->reserved = 0;
405 	m->buffer = NULL;
406 }
407 
408 static inline void
msginittsig(dns_message_t * m)409 msginittsig(dns_message_t *m) {
410 	m->tsigstatus = dns_rcode_noerror;
411 	m->querytsigstatus = dns_rcode_noerror;
412 	m->tsigkey = NULL;
413 	m->tsigctx = NULL;
414 	m->sigstart = -1;
415 	m->sig0key = NULL;
416 	m->sig0status = dns_rcode_noerror;
417 	m->timeadjust = 0;
418 }
419 
420 /*
421  * Init elements to default state.  Used both when allocating a new element
422  * and when resetting one.
423  */
424 static inline void
msginit(dns_message_t * m)425 msginit(dns_message_t *m) {
426 	msginitheader(m);
427 	msginitprivate(m);
428 	msginittsig(m);
429 	m->header_ok = 0;
430 	m->question_ok = 0;
431 	m->tcp_continuation = 0;
432 	m->verified_sig = 0;
433 	m->verify_attempted = 0;
434 	m->order = NULL;
435 	m->order_arg = NULL;
436 	m->query.base = NULL;
437 	m->query.length = 0;
438 	m->free_query = 0;
439 	m->saved.base = NULL;
440 	m->saved.length = 0;
441 	m->free_saved = 0;
442 	m->sitok = 0;
443 	m->sitbad = 0;
444 	m->querytsig = NULL;
445 }
446 
447 static inline void
msgresetnames(dns_message_t * msg,unsigned int first_section)448 msgresetnames(dns_message_t *msg, unsigned int first_section) {
449 	unsigned int i;
450 	dns_name_t *name, *next_name;
451 	dns_rdataset_t *rds, *next_rds;
452 
453 	/*
454 	 * Clean up name lists by calling the rdataset disassociate function.
455 	 */
456 	for (i = first_section; i < DNS_SECTION_MAX; i++) {
457 		name = ISC_LIST_HEAD(msg->sections[i]);
458 		while (name != NULL) {
459 			next_name = ISC_LIST_NEXT(name, link);
460 			ISC_LIST_UNLINK(msg->sections[i], name, link);
461 
462 			rds = ISC_LIST_HEAD(name->list);
463 			while (rds != NULL) {
464 				next_rds = ISC_LIST_NEXT(rds, link);
465 				ISC_LIST_UNLINK(name->list, rds, link);
466 
467 				INSIST(dns_rdataset_isassociated(rds));
468 				dns_rdataset_disassociate(rds);
469 				isc_mempool_put(msg->rdspool, rds);
470 				rds = next_rds;
471 			}
472 			if (dns_name_dynamic(name))
473 				dns_name_free(name, msg->mctx);
474 			isc_mempool_put(msg->namepool, name);
475 			name = next_name;
476 		}
477 	}
478 }
479 
480 static void
msgresetopt(dns_message_t * msg)481 msgresetopt(dns_message_t *msg)
482 {
483 	if (msg->opt != NULL) {
484 		if (msg->opt_reserved > 0) {
485 			dns_message_renderrelease(msg, msg->opt_reserved);
486 			msg->opt_reserved = 0;
487 		}
488 		INSIST(dns_rdataset_isassociated(msg->opt));
489 		dns_rdataset_disassociate(msg->opt);
490 		isc_mempool_put(msg->rdspool, msg->opt);
491 		msg->opt = NULL;
492 		msg->sitok = 0;
493 		msg->sitbad = 0;
494 	}
495 }
496 
497 static void
msgresetsigs(dns_message_t * msg,isc_boolean_t replying)498 msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
499 	if (msg->sig_reserved > 0) {
500 		dns_message_renderrelease(msg, msg->sig_reserved);
501 		msg->sig_reserved = 0;
502 	}
503 	if (msg->tsig != NULL) {
504 		INSIST(dns_rdataset_isassociated(msg->tsig));
505 		INSIST(msg->namepool != NULL);
506 		if (replying) {
507 			INSIST(msg->querytsig == NULL);
508 			msg->querytsig = msg->tsig;
509 		} else {
510 			dns_rdataset_disassociate(msg->tsig);
511 			isc_mempool_put(msg->rdspool, msg->tsig);
512 			if (msg->querytsig != NULL) {
513 				dns_rdataset_disassociate(msg->querytsig);
514 				isc_mempool_put(msg->rdspool, msg->querytsig);
515 			}
516 		}
517 		if (dns_name_dynamic(msg->tsigname))
518 			dns_name_free(msg->tsigname, msg->mctx);
519 		isc_mempool_put(msg->namepool, msg->tsigname);
520 		msg->tsig = NULL;
521 		msg->tsigname = NULL;
522 	} else if (msg->querytsig != NULL && !replying) {
523 		dns_rdataset_disassociate(msg->querytsig);
524 		isc_mempool_put(msg->rdspool, msg->querytsig);
525 		msg->querytsig = NULL;
526 	}
527 	if (msg->sig0 != NULL) {
528 		INSIST(dns_rdataset_isassociated(msg->sig0));
529 		dns_rdataset_disassociate(msg->sig0);
530 		isc_mempool_put(msg->rdspool, msg->sig0);
531 		if (msg->sig0name != NULL) {
532 			if (dns_name_dynamic(msg->sig0name))
533 				dns_name_free(msg->sig0name, msg->mctx);
534 			isc_mempool_put(msg->namepool, msg->sig0name);
535 		}
536 		msg->sig0 = NULL;
537 		msg->sig0name = NULL;
538 	}
539 }
540 
541 /*
542  * Free all but one (or everything) for this message.  This is used by
543  * both dns_message_reset() and dns_message_destroy().
544  */
545 static void
msgreset(dns_message_t * msg,isc_boolean_t everything)546 msgreset(dns_message_t *msg, isc_boolean_t everything) {
547 	dns_msgblock_t *msgblock, *next_msgblock;
548 	isc_buffer_t *dynbuf, *next_dynbuf;
549 	dns_rdata_t *rdata;
550 	dns_rdatalist_t *rdatalist;
551 
552 	msgresetnames(msg, 0);
553 	msgresetopt(msg);
554 	msgresetsigs(msg, ISC_FALSE);
555 
556 	/*
557 	 * Clean up linked lists.
558 	 */
559 
560 	/*
561 	 * Run through the free lists, and just unlink anything found there.
562 	 * The memory isn't lost since these are part of message blocks we
563 	 * have allocated.
564 	 */
565 	rdata = ISC_LIST_HEAD(msg->freerdata);
566 	while (rdata != NULL) {
567 		ISC_LIST_UNLINK(msg->freerdata, rdata, link);
568 		rdata = ISC_LIST_HEAD(msg->freerdata);
569 	}
570 	rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
571 	while (rdatalist != NULL) {
572 		ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
573 		rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
574 	}
575 
576 	dynbuf = ISC_LIST_HEAD(msg->scratchpad);
577 	INSIST(dynbuf != NULL);
578 	if (!everything) {
579 		isc_buffer_clear(dynbuf);
580 		dynbuf = ISC_LIST_NEXT(dynbuf, link);
581 	}
582 	while (dynbuf != NULL) {
583 		next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
584 		ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
585 		isc_buffer_free(&dynbuf);
586 		dynbuf = next_dynbuf;
587 	}
588 
589 	msgblock = ISC_LIST_HEAD(msg->rdatas);
590 	if (!everything && msgblock != NULL) {
591 		msgblock_reset(msgblock);
592 		msgblock = ISC_LIST_NEXT(msgblock, link);
593 	}
594 	while (msgblock != NULL) {
595 		next_msgblock = ISC_LIST_NEXT(msgblock, link);
596 		ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
597 		msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
598 		msgblock = next_msgblock;
599 	}
600 
601 	/*
602 	 * rdatalists could be empty.
603 	 */
604 
605 	msgblock = ISC_LIST_HEAD(msg->rdatalists);
606 	if (!everything && msgblock != NULL) {
607 		msgblock_reset(msgblock);
608 		msgblock = ISC_LIST_NEXT(msgblock, link);
609 	}
610 	while (msgblock != NULL) {
611 		next_msgblock = ISC_LIST_NEXT(msgblock, link);
612 		ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
613 		msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
614 		msgblock = next_msgblock;
615 	}
616 
617 	msgblock = ISC_LIST_HEAD(msg->offsets);
618 	if (!everything && msgblock != NULL) {
619 		msgblock_reset(msgblock);
620 		msgblock = ISC_LIST_NEXT(msgblock, link);
621 	}
622 	while (msgblock != NULL) {
623 		next_msgblock = ISC_LIST_NEXT(msgblock, link);
624 		ISC_LIST_UNLINK(msg->offsets, msgblock, link);
625 		msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
626 		msgblock = next_msgblock;
627 	}
628 
629 	if (msg->tsigkey != NULL) {
630 		dns_tsigkey_detach(&msg->tsigkey);
631 		msg->tsigkey = NULL;
632 	}
633 
634 	if (msg->tsigctx != NULL)
635 		dst_context_destroy(&msg->tsigctx);
636 
637 	if (msg->query.base != NULL) {
638 		if (msg->free_query != 0)
639 			isc_mem_put(msg->mctx, msg->query.base,
640 				    msg->query.length);
641 		msg->query.base = NULL;
642 		msg->query.length = 0;
643 	}
644 
645 	if (msg->saved.base != NULL) {
646 		if (msg->free_saved != 0)
647 			isc_mem_put(msg->mctx, msg->saved.base,
648 				    msg->saved.length);
649 		msg->saved.base = NULL;
650 		msg->saved.length = 0;
651 	}
652 
653 	/*
654 	 * cleanup the buffer cleanup list
655 	 */
656 	dynbuf = ISC_LIST_HEAD(msg->cleanup);
657 	while (dynbuf != NULL) {
658 		next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
659 		ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
660 		isc_buffer_free(&dynbuf);
661 		dynbuf = next_dynbuf;
662 	}
663 
664 	/*
665 	 * Set other bits to normal default values.
666 	 */
667 	if (!everything)
668 		msginit(msg);
669 
670 	ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
671 	ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
672 }
673 
674 static unsigned int
spacefortsig(dns_tsigkey_t * key,int otherlen)675 spacefortsig(dns_tsigkey_t *key, int otherlen) {
676 	isc_region_t r1, r2;
677 	unsigned int x;
678 	isc_result_t result;
679 
680 	/*
681 	 * The space required for an TSIG record is:
682 	 *
683 	 *	n1 bytes for the name
684 	 *	2 bytes for the type
685 	 *	2 bytes for the class
686 	 *	4 bytes for the ttl
687 	 *	2 bytes for the rdlength
688 	 *	n2 bytes for the algorithm name
689 	 *	6 bytes for the time signed
690 	 *	2 bytes for the fudge
691 	 *	2 bytes for the MAC size
692 	 *	x bytes for the MAC
693 	 *	2 bytes for the original id
694 	 *	2 bytes for the error
695 	 *	2 bytes for the other data length
696 	 *	y bytes for the other data (at most)
697 	 * ---------------------------------
698 	 *     26 + n1 + n2 + x + y bytes
699 	 */
700 
701 	dns_name_toregion(&key->name, &r1);
702 	dns_name_toregion(key->algorithm, &r2);
703 	if (key->key == NULL)
704 		x = 0;
705 	else {
706 		result = dst_key_sigsize(key->key, &x);
707 		if (result != ISC_R_SUCCESS)
708 			x = 0;
709 	}
710 	return (26 + r1.length + r2.length + x + otherlen);
711 }
712 
713 isc_result_t
dns_message_create(isc_mem_t * mctx,unsigned int intent,dns_message_t ** msgp)714 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
715 {
716 	dns_message_t *m;
717 	isc_result_t result;
718 	isc_buffer_t *dynbuf;
719 	unsigned int i;
720 
721 	REQUIRE(mctx != NULL);
722 	REQUIRE(msgp != NULL);
723 	REQUIRE(*msgp == NULL);
724 	REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
725 		|| intent == DNS_MESSAGE_INTENTRENDER);
726 
727 	m = isc_mem_get(mctx, sizeof(dns_message_t));
728 	if (m == NULL)
729 		return (ISC_R_NOMEMORY);
730 
731 	/*
732 	 * No allocations until further notice.  Just initialize all lists
733 	 * and other members that are freed in the cleanup phase here.
734 	 */
735 
736 	m->magic = DNS_MESSAGE_MAGIC;
737 	m->from_to_wire = intent;
738 	msginit(m);
739 
740 	for (i = 0; i < DNS_SECTION_MAX; i++)
741 		ISC_LIST_INIT(m->sections[i]);
742 
743 	m->mctx = NULL;
744 	isc_mem_attach(mctx, &m->mctx);
745 
746 	ISC_LIST_INIT(m->scratchpad);
747 	ISC_LIST_INIT(m->cleanup);
748 	m->namepool = NULL;
749 	m->rdspool = NULL;
750 	ISC_LIST_INIT(m->rdatas);
751 	ISC_LIST_INIT(m->rdatalists);
752 	ISC_LIST_INIT(m->offsets);
753 	ISC_LIST_INIT(m->freerdata);
754 	ISC_LIST_INIT(m->freerdatalist);
755 
756 	/*
757 	 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
758 	 */
759 
760 	result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
761 	if (result != ISC_R_SUCCESS)
762 		goto cleanup;
763 	isc_mempool_setfreemax(m->namepool, NAME_COUNT);
764 	isc_mempool_setname(m->namepool, "msg:names");
765 
766 	result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
767 				    &m->rdspool);
768 	if (result != ISC_R_SUCCESS)
769 		goto cleanup;
770 	isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
771 	isc_mempool_setname(m->rdspool, "msg:rdataset");
772 
773 	dynbuf = NULL;
774 	result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
775 	if (result != ISC_R_SUCCESS)
776 		goto cleanup;
777 	ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
778 
779 	m->cctx = NULL;
780 
781 	*msgp = m;
782 	return (ISC_R_SUCCESS);
783 
784 	/*
785 	 * Cleanup for error returns.
786 	 */
787  cleanup:
788 	dynbuf = ISC_LIST_HEAD(m->scratchpad);
789 	if (dynbuf != NULL) {
790 		ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
791 		isc_buffer_free(&dynbuf);
792 	}
793 	if (m->namepool != NULL)
794 		isc_mempool_destroy(&m->namepool);
795 	if (m->rdspool != NULL)
796 		isc_mempool_destroy(&m->rdspool);
797 	m->magic = 0;
798 	isc_mem_putanddetach(&mctx, m, sizeof(dns_message_t));
799 
800 	return (ISC_R_NOMEMORY);
801 }
802 
803 void
dns_message_reset(dns_message_t * msg,unsigned int intent)804 dns_message_reset(dns_message_t *msg, unsigned int intent) {
805 	REQUIRE(DNS_MESSAGE_VALID(msg));
806 	REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
807 		|| intent == DNS_MESSAGE_INTENTRENDER);
808 
809 	msgreset(msg, ISC_FALSE);
810 	msg->from_to_wire = intent;
811 }
812 
813 void
dns_message_destroy(dns_message_t ** msgp)814 dns_message_destroy(dns_message_t **msgp) {
815 	dns_message_t *msg;
816 
817 	REQUIRE(msgp != NULL);
818 	REQUIRE(DNS_MESSAGE_VALID(*msgp));
819 
820 	msg = *msgp;
821 	*msgp = NULL;
822 
823 	msgreset(msg, ISC_TRUE);
824 	isc_mempool_destroy(&msg->namepool);
825 	isc_mempool_destroy(&msg->rdspool);
826 	msg->magic = 0;
827 	isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t));
828 }
829 
830 static isc_result_t
findname(dns_name_t ** foundname,dns_name_t * target,dns_namelist_t * section)831 findname(dns_name_t **foundname, dns_name_t *target,
832 	 dns_namelist_t *section)
833 {
834 	dns_name_t *curr;
835 
836 	for (curr = ISC_LIST_TAIL(*section);
837 	     curr != NULL;
838 	     curr = ISC_LIST_PREV(curr, link)) {
839 		if (dns_name_equal(curr, target)) {
840 			if (foundname != NULL)
841 				*foundname = curr;
842 			return (ISC_R_SUCCESS);
843 		}
844 	}
845 
846 	return (ISC_R_NOTFOUND);
847 }
848 
849 isc_result_t
dns_message_find(dns_name_t * name,dns_rdataclass_t rdclass,dns_rdatatype_t type,dns_rdatatype_t covers,dns_rdataset_t ** rdataset)850 dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
851 		 dns_rdatatype_t type, dns_rdatatype_t covers,
852 		 dns_rdataset_t **rdataset)
853 {
854 	dns_rdataset_t *curr;
855 
856 	if (rdataset != NULL) {
857 		REQUIRE(*rdataset == NULL);
858 	}
859 
860 	for (curr = ISC_LIST_TAIL(name->list);
861 	     curr != NULL;
862 	     curr = ISC_LIST_PREV(curr, link)) {
863 		if (curr->rdclass == rdclass &&
864 		    curr->type == type && curr->covers == covers) {
865 			if (rdataset != NULL)
866 				*rdataset = curr;
867 			return (ISC_R_SUCCESS);
868 		}
869 	}
870 
871 	return (ISC_R_NOTFOUND);
872 }
873 
874 isc_result_t
dns_message_findtype(dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,dns_rdataset_t ** rdataset)875 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
876 		     dns_rdatatype_t covers, dns_rdataset_t **rdataset)
877 {
878 	dns_rdataset_t *curr;
879 
880 	REQUIRE(name != NULL);
881 	if (rdataset != NULL) {
882 		REQUIRE(*rdataset == NULL);
883 	}
884 
885 	for (curr = ISC_LIST_TAIL(name->list);
886 	     curr != NULL;
887 	     curr = ISC_LIST_PREV(curr, link)) {
888 		if (curr->type == type && curr->covers == covers) {
889 			if (rdataset != NULL)
890 				*rdataset = curr;
891 			return (ISC_R_SUCCESS);
892 		}
893 	}
894 
895 	return (ISC_R_NOTFOUND);
896 }
897 
898 /*
899  * Read a name from buffer "source".
900  */
901 static isc_result_t
getname(dns_name_t * name,isc_buffer_t * source,dns_message_t * msg,dns_decompress_t * dctx)902 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
903 	dns_decompress_t *dctx)
904 {
905 	isc_buffer_t *scratch;
906 	isc_result_t result;
907 	unsigned int tries;
908 
909 	scratch = currentbuffer(msg);
910 
911 	/*
912 	 * First try:  use current buffer.
913 	 * Second try:  allocate a new buffer and use that.
914 	 */
915 	tries = 0;
916 	while (tries < 2) {
917 		result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
918 					   scratch);
919 
920 		if (result == ISC_R_NOSPACE) {
921 			tries++;
922 
923 			result = newbuffer(msg, SCRATCHPAD_SIZE);
924 			if (result != ISC_R_SUCCESS)
925 				return (result);
926 
927 			scratch = currentbuffer(msg);
928 			dns_name_reset(name);
929 		} else {
930 			return (result);
931 		}
932 	}
933 
934 	INSIST(0);  /* Cannot get here... */
935 	return (ISC_R_UNEXPECTED);
936 }
937 
938 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)939 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
940 	 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
941 	 unsigned int rdatalen, dns_rdata_t *rdata)
942 {
943 	isc_buffer_t *scratch;
944 	isc_result_t result;
945 	unsigned int tries;
946 	unsigned int trysize;
947 
948 	scratch = currentbuffer(msg);
949 
950 	isc_buffer_setactive(source, rdatalen);
951 
952 	/*
953 	 * First try:  use current buffer.
954 	 * Second try:  allocate a new buffer of size
955 	 *     max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
956 	 *     (the data will fit if it was not more than 50% compressed)
957 	 * Subsequent tries: double buffer size on each try.
958 	 */
959 	tries = 0;
960 	trysize = 0;
961 	/* XXX possibly change this to a while (tries < 2) loop */
962 	for (;;) {
963 		result = dns_rdata_fromwire(rdata, rdclass, rdtype,
964 					    source, dctx, 0,
965 					    scratch);
966 
967 		if (result == ISC_R_NOSPACE) {
968 			if (tries == 0) {
969 				trysize = 2 * rdatalen;
970 				if (trysize < SCRATCHPAD_SIZE)
971 					trysize = SCRATCHPAD_SIZE;
972 			} else {
973 				INSIST(trysize != 0);
974 				if (trysize >= 65535)
975 					return (ISC_R_NOSPACE);
976 					/* XXX DNS_R_RRTOOLONG? */
977 				trysize *= 2;
978 			}
979 			tries++;
980 			result = newbuffer(msg, trysize);
981 			if (result != ISC_R_SUCCESS)
982 				return (result);
983 
984 			scratch = currentbuffer(msg);
985 		} else {
986 			return (result);
987 		}
988 	}
989 }
990 
991 #define DO_FORMERR					\
992 	do {						\
993 		if (best_effort)			\
994 			seen_problem = ISC_TRUE;	\
995 		else {					\
996 			result = DNS_R_FORMERR;		\
997 			goto cleanup;			\
998 		}					\
999 	} while (/*CONSTCOND*/0)
1000 
1001 static isc_result_t
getquestions(isc_buffer_t * source,dns_message_t * msg,dns_decompress_t * dctx,unsigned int options)1002 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
1003 	     unsigned int options)
1004 {
1005 	isc_region_t r;
1006 	unsigned int count;
1007 	dns_name_t *name;
1008 	dns_name_t *name2;
1009 	dns_offsets_t *offsets;
1010 	dns_rdataset_t *rdataset;
1011 	dns_rdatalist_t *rdatalist;
1012 	isc_result_t result;
1013 	dns_rdatatype_t rdtype;
1014 	dns_rdataclass_t rdclass;
1015 	dns_namelist_t *section;
1016 	isc_boolean_t free_name;
1017 	isc_boolean_t best_effort;
1018 	isc_boolean_t seen_problem;
1019 
1020 	section = &msg->sections[DNS_SECTION_QUESTION];
1021 
1022 	best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1023 	seen_problem = ISC_FALSE;
1024 
1025 	name = NULL;
1026 	rdataset = NULL;
1027 	rdatalist = NULL;
1028 
1029 	for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
1030 		name = isc_mempool_get(msg->namepool);
1031 		if (name == NULL)
1032 			return (ISC_R_NOMEMORY);
1033 		free_name = ISC_TRUE;
1034 
1035 		offsets = newoffsets(msg);
1036 		if (offsets == NULL) {
1037 			result = ISC_R_NOMEMORY;
1038 			goto cleanup;
1039 		}
1040 		dns_name_init(name, *offsets);
1041 
1042 		/*
1043 		 * Parse the name out of this packet.
1044 		 */
1045 		isc_buffer_remainingregion(source, &r);
1046 		isc_buffer_setactive(source, r.length);
1047 		result = getname(name, source, msg, dctx);
1048 		if (result != ISC_R_SUCCESS)
1049 			goto cleanup;
1050 
1051 		/*
1052 		 * Run through the section, looking to see if this name
1053 		 * is already there.  If it is found, put back the allocated
1054 		 * name since we no longer need it, and set our name pointer
1055 		 * to point to the name we found.
1056 		 */
1057 		result = findname(&name2, name, section);
1058 
1059 		/*
1060 		 * If it is the first name in the section, accept it.
1061 		 *
1062 		 * If it is not, but is not the same as the name already
1063 		 * in the question section, append to the section.  Note that
1064 		 * here in the question section this is illegal, so return
1065 		 * FORMERR.  In the future, check the opcode to see if
1066 		 * this should be legal or not.  In either case we no longer
1067 		 * need this name pointer.
1068 		 */
1069 		if (result != ISC_R_SUCCESS) {
1070 			if (!ISC_LIST_EMPTY(*section))
1071 				DO_FORMERR;
1072 			ISC_LIST_APPEND(*section, name, link);
1073 			free_name = ISC_FALSE;
1074 		} else {
1075 			isc_mempool_put(msg->namepool, name);
1076 			name = name2;
1077 			name2 = NULL;
1078 			free_name = ISC_FALSE;
1079 		}
1080 
1081 		/*
1082 		 * Get type and class.
1083 		 */
1084 		isc_buffer_remainingregion(source, &r);
1085 		if (r.length < 4) {
1086 			result = ISC_R_UNEXPECTEDEND;
1087 			goto cleanup;
1088 		}
1089 		rdtype = isc_buffer_getuint16(source);
1090 		rdclass = isc_buffer_getuint16(source);
1091 
1092 		/*
1093 		 * If this class is different than the one we already read,
1094 		 * this is an error.
1095 		 */
1096 		if (msg->state == DNS_SECTION_ANY) {
1097 			msg->state = DNS_SECTION_QUESTION;
1098 			msg->rdclass = rdclass;
1099 		} else if (msg->rdclass != rdclass)
1100 			DO_FORMERR;
1101 
1102 		/*
1103 		 * Can't ask the same question twice.
1104 		 */
1105 		result = dns_message_find(name, rdclass, rdtype, 0, NULL);
1106 		if (result == ISC_R_SUCCESS)
1107 			DO_FORMERR;
1108 
1109 		/*
1110 		 * Allocate a new rdatalist.
1111 		 */
1112 		rdatalist = newrdatalist(msg);
1113 		if (rdatalist == NULL) {
1114 			result = ISC_R_NOMEMORY;
1115 			goto cleanup;
1116 		}
1117 		rdataset =  isc_mempool_get(msg->rdspool);
1118 		if (rdataset == NULL) {
1119 			result = ISC_R_NOMEMORY;
1120 			goto cleanup;
1121 		}
1122 
1123 		/*
1124 		 * Convert rdatalist to rdataset, and attach the latter to
1125 		 * the name.
1126 		 */
1127 		rdatalist->type = rdtype;
1128 		rdatalist->covers = 0;
1129 		rdatalist->rdclass = rdclass;
1130 		rdatalist->ttl = 0;
1131 		ISC_LIST_INIT(rdatalist->rdata);
1132 
1133 		dns_rdataset_init(rdataset);
1134 		result = dns_rdatalist_tordataset(rdatalist, rdataset);
1135 		if (result != ISC_R_SUCCESS)
1136 			goto cleanup;
1137 
1138 		rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
1139 
1140 		ISC_LIST_APPEND(name->list, rdataset, link);
1141 		rdataset = NULL;
1142 	}
1143 
1144 	if (seen_problem)
1145 		return (DNS_R_RECOVERABLE);
1146 	return (ISC_R_SUCCESS);
1147 
1148  cleanup:
1149 	if (rdataset != NULL) {
1150 		INSIST(!dns_rdataset_isassociated(rdataset));
1151 		isc_mempool_put(msg->rdspool, rdataset);
1152 	}
1153 #if 0
1154 	if (rdatalist != NULL)
1155 		isc_mempool_put(msg->rdlpool, rdatalist);
1156 #endif
1157 	if (free_name)
1158 		isc_mempool_put(msg->namepool, name);
1159 
1160 	return (result);
1161 }
1162 
1163 static isc_boolean_t
update(dns_section_t section,dns_rdataclass_t rdclass)1164 update(dns_section_t section, dns_rdataclass_t rdclass) {
1165 	if (section == DNS_SECTION_PREREQUISITE)
1166 		return (ISC_TF(rdclass == dns_rdataclass_any ||
1167 			       rdclass == dns_rdataclass_none));
1168 	if (section == DNS_SECTION_UPDATE)
1169 		return (ISC_TF(rdclass == dns_rdataclass_any));
1170 	return (ISC_FALSE);
1171 }
1172 
1173 static isc_result_t
getsection(isc_buffer_t * source,dns_message_t * msg,dns_decompress_t * dctx,dns_section_t sectionid,unsigned int options)1174 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
1175 	   dns_section_t sectionid, unsigned int options)
1176 {
1177 	isc_region_t r;
1178 	unsigned int count, rdatalen;
1179 	dns_name_t *name;
1180 	dns_name_t *name2;
1181 	dns_offsets_t *offsets;
1182 	dns_rdataset_t *rdataset = NULL;
1183 	dns_rdatalist_t *rdatalist;
1184 	isc_result_t result;
1185 	dns_rdatatype_t rdtype, covers;
1186 	dns_rdataclass_t rdclass;
1187 	dns_rdata_t *rdata;
1188 	dns_ttl_t ttl;
1189 	dns_namelist_t *section;
1190 	isc_boolean_t free_name, free_rdataset;
1191 	isc_boolean_t preserve_order, best_effort, seen_problem;
1192 	isc_boolean_t issigzero;
1193 
1194 	preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
1195 	best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1196 	seen_problem = ISC_FALSE;
1197 
1198 	for (count = 0; count < msg->counts[sectionid]; count++) {
1199 		int recstart = source->current;
1200 		isc_boolean_t skip_name_search, skip_type_search;
1201 
1202 		section = &msg->sections[sectionid];
1203 
1204 		skip_name_search = ISC_FALSE;
1205 		skip_type_search = ISC_FALSE;
1206 		free_rdataset = ISC_FALSE;
1207 
1208 		name = isc_mempool_get(msg->namepool);
1209 		if (name == NULL)
1210 			return (ISC_R_NOMEMORY);
1211 		free_name = ISC_TRUE;
1212 
1213 		offsets = newoffsets(msg);
1214 		if (offsets == NULL) {
1215 			result = ISC_R_NOMEMORY;
1216 			goto cleanup;
1217 		}
1218 		dns_name_init(name, *offsets);
1219 
1220 		/*
1221 		 * Parse the name out of this packet.
1222 		 */
1223 		isc_buffer_remainingregion(source, &r);
1224 		isc_buffer_setactive(source, r.length);
1225 		result = getname(name, source, msg, dctx);
1226 		if (result != ISC_R_SUCCESS)
1227 			goto cleanup;
1228 
1229 		/*
1230 		 * Get type, class, ttl, and rdatalen.  Verify that at least
1231 		 * rdatalen bytes remain.  (Some of this is deferred to
1232 		 * later.)
1233 		 */
1234 		isc_buffer_remainingregion(source, &r);
1235 		if (r.length < 2 + 2 + 4 + 2) {
1236 			result = ISC_R_UNEXPECTEDEND;
1237 			goto cleanup;
1238 		}
1239 		rdtype = isc_buffer_getuint16(source);
1240 		rdclass = isc_buffer_getuint16(source);
1241 
1242 		/*
1243 		 * If there was no question section, we may not yet have
1244 		 * established a class.  Do so now.
1245 		 */
1246 		if (msg->state == DNS_SECTION_ANY &&
1247 		    rdtype != dns_rdatatype_opt &&	/* class is UDP SIZE */
1248 		    rdtype != dns_rdatatype_tsig &&	/* class is ANY */
1249 		    rdtype != dns_rdatatype_tkey) {	/* class is undefined */
1250 			msg->rdclass = rdclass;
1251 			msg->state = DNS_SECTION_QUESTION;
1252 		}
1253 
1254 		/*
1255 		 * If this class is different than the one in the question
1256 		 * section, bail.
1257 		 */
1258 		if (msg->opcode != dns_opcode_update
1259 		    && rdtype != dns_rdatatype_tsig
1260 		    && rdtype != dns_rdatatype_opt
1261 		    && rdtype != dns_rdatatype_dnskey /* in a TKEY query */
1262 		    && rdtype != dns_rdatatype_sig /* SIG(0) */
1263 		    && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
1264 		    && msg->rdclass != dns_rdataclass_any
1265 		    && msg->rdclass != rdclass)
1266 			DO_FORMERR;
1267 
1268 		/*
1269 		 * Special type handling for TSIG, OPT, and TKEY.
1270 		 */
1271 		if (rdtype == dns_rdatatype_tsig) {
1272 			/*
1273 			 * If it is a tsig, verify that it is in the
1274 			 * additional data section.
1275 			 */
1276 			if (sectionid != DNS_SECTION_ADDITIONAL ||
1277 			    rdclass != dns_rdataclass_any ||
1278 			    count != msg->counts[sectionid]  - 1)
1279 				DO_FORMERR;
1280 			msg->sigstart = recstart;
1281 			skip_name_search = ISC_TRUE;
1282 			skip_type_search = ISC_TRUE;
1283 		} else if (rdtype == dns_rdatatype_opt) {
1284 			/*
1285 			 * The name of an OPT record must be ".", it
1286 			 * must be in the additional data section, and
1287 			 * it must be the first OPT we've seen.
1288 			 */
1289 			if (!dns_name_equal(dns_rootname, name) ||
1290 			    msg->opt != NULL)
1291 				DO_FORMERR;
1292 			skip_name_search = ISC_TRUE;
1293 			skip_type_search = ISC_TRUE;
1294 		} else if (rdtype == dns_rdatatype_tkey) {
1295 			/*
1296 			 * A TKEY must be in the additional section if this
1297 			 * is a query, and the answer section if this is a
1298 			 * response.  Unless it's a Win2000 client.
1299 			 *
1300 			 * Its class is ignored.
1301 			 */
1302 			dns_section_t tkeysection;
1303 
1304 			if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
1305 				tkeysection = DNS_SECTION_ADDITIONAL;
1306 			else
1307 				tkeysection = DNS_SECTION_ANSWER;
1308 			if (sectionid != tkeysection &&
1309 			    sectionid != DNS_SECTION_ANSWER)
1310 				DO_FORMERR;
1311 		}
1312 
1313 		/*
1314 		 * ... now get ttl and rdatalen, and check buffer.
1315 		 */
1316 		ttl = isc_buffer_getuint32(source);
1317 		rdatalen = isc_buffer_getuint16(source);
1318 		r.length -= (2 + 2 + 4 + 2);
1319 		if (r.length < rdatalen) {
1320 			result = ISC_R_UNEXPECTEDEND;
1321 			goto cleanup;
1322 		}
1323 
1324 		/*
1325 		 * Read the rdata from the wire format.  Interpret the
1326 		 * rdata according to its actual class, even if it had a
1327 		 * DynDNS meta-class in the packet (unless this is a TSIG).
1328 		 * Then put the meta-class back into the finished rdata.
1329 		 */
1330 		rdata = newrdata(msg);
1331 		if (rdata == NULL) {
1332 			result = ISC_R_NOMEMORY;
1333 			goto cleanup;
1334 		}
1335 		if (msg->opcode == dns_opcode_update &&
1336 		    update(sectionid, rdclass)) {
1337 			if (rdatalen != 0) {
1338 				result = DNS_R_FORMERR;
1339 				goto cleanup;
1340 			}
1341 			/*
1342 			 * When the rdata is empty, the data pointer is
1343 			 * never dereferenced, but it must still be non-NULL.
1344 			 * Casting 1 rather than "" avoids warnings about
1345 			 * discarding the const attribute of a string,
1346 			 * for compilers that would warn about such things.
1347 			 */
1348 			rdata->data = (unsigned char *)1;
1349 			rdata->length = 0;
1350 			rdata->rdclass = rdclass;
1351 			rdata->type = rdtype;
1352 			rdata->flags = DNS_RDATA_UPDATE;
1353 			result = ISC_R_SUCCESS;
1354 		} else if (rdclass == dns_rdataclass_none &&
1355 			   msg->opcode == dns_opcode_update &&
1356 			   sectionid == DNS_SECTION_UPDATE) {
1357 			result = getrdata(source, msg, dctx, msg->rdclass,
1358 					  rdtype, rdatalen, rdata);
1359 		} else
1360 			result = getrdata(source, msg, dctx, rdclass,
1361 					  rdtype, rdatalen, rdata);
1362 		if (result != ISC_R_SUCCESS)
1363 			goto cleanup;
1364 		rdata->rdclass = rdclass;
1365 		issigzero = ISC_FALSE;
1366 		if (rdtype == dns_rdatatype_rrsig  &&
1367 		    rdata->flags == 0) {
1368 			covers = dns_rdata_covers(rdata);
1369 			if (covers == 0)
1370 				DO_FORMERR;
1371 		} else if (rdtype == dns_rdatatype_sig /* SIG(0) */ &&
1372 			   rdata->flags == 0) {
1373 			covers = dns_rdata_covers(rdata);
1374 			if (covers == 0) {
1375 				if (sectionid != DNS_SECTION_ADDITIONAL ||
1376 				    count != msg->counts[sectionid]  - 1)
1377 					DO_FORMERR;
1378 				msg->sigstart = recstart;
1379 				skip_name_search = ISC_TRUE;
1380 				skip_type_search = ISC_TRUE;
1381 				issigzero = ISC_TRUE;
1382 			}
1383 		} else
1384 			covers = 0;
1385 
1386 		/*
1387 		 * Check the ownername of NSEC3 records
1388 		 */
1389 		if (rdtype == dns_rdatatype_nsec3 &&
1390 		    !dns_rdata_checkowner(name, msg->rdclass, rdtype,
1391 					  ISC_FALSE)) {
1392 			result = DNS_R_BADOWNERNAME;
1393 			goto cleanup;
1394 		}
1395 
1396 		/*
1397 		 * If we are doing a dynamic update or this is a meta-type,
1398 		 * don't bother searching for a name, just append this one
1399 		 * to the end of the message.
1400 		 */
1401 		if (preserve_order || msg->opcode == dns_opcode_update ||
1402 		    skip_name_search) {
1403 			if (rdtype != dns_rdatatype_opt &&
1404 			    rdtype != dns_rdatatype_tsig &&
1405 			    !issigzero)
1406 			{
1407 				ISC_LIST_APPEND(*section, name, link);
1408 				free_name = ISC_FALSE;
1409 			}
1410 		} else {
1411 			/*
1412 			 * Run through the section, looking to see if this name
1413 			 * is already there.  If it is found, put back the
1414 			 * allocated name since we no longer need it, and set
1415 			 * our name pointer to point to the name we found.
1416 			 */
1417 			result = findname(&name2, name, section);
1418 
1419 			/*
1420 			 * If it is a new name, append to the section.
1421 			 */
1422 			if (result == ISC_R_SUCCESS) {
1423 				isc_mempool_put(msg->namepool, name);
1424 				name = name2;
1425 			} else {
1426 				ISC_LIST_APPEND(*section, name, link);
1427 			}
1428 			free_name = ISC_FALSE;
1429 		}
1430 
1431 		/*
1432 		 * Search name for the particular type and class.
1433 		 * Skip this stage if in update mode or this is a meta-type.
1434 		 */
1435 		if (preserve_order || msg->opcode == dns_opcode_update ||
1436 		    skip_type_search)
1437 			result = ISC_R_NOTFOUND;
1438 		else {
1439 			/*
1440 			 * If this is a type that can only occur in
1441 			 * the question section, fail.
1442 			 */
1443 			if (dns_rdatatype_questiononly(rdtype))
1444 				DO_FORMERR;
1445 
1446 			rdataset = NULL;
1447 			result = dns_message_find(name, rdclass, rdtype,
1448 						   covers, &rdataset);
1449 		}
1450 
1451 		/*
1452 		 * If we found an rdataset that matches, we need to
1453 		 * append this rdata to that set.  If we did not, we need
1454 		 * to create a new rdatalist, store the important bits there,
1455 		 * convert it to an rdataset, and link the latter to the name.
1456 		 * Yuck.  When appending, make certain that the type isn't
1457 		 * a singleton type, such as SOA or CNAME.
1458 		 *
1459 		 * Note that this check will be bypassed when preserving order,
1460 		 * the opcode is an update, or the type search is skipped.
1461 		 */
1462 		if (result == ISC_R_SUCCESS) {
1463 			if (dns_rdatatype_issingleton(rdtype)) {
1464 				dns_rdata_t *first;
1465 				dns_rdatalist_fromrdataset(rdataset,
1466 							   &rdatalist);
1467 				first = ISC_LIST_HEAD(rdatalist->rdata);
1468 				INSIST(first != NULL);
1469 				if (dns_rdata_compare(rdata, first) != 0)
1470 					DO_FORMERR;
1471 			}
1472 		}
1473 
1474 		if (result == ISC_R_NOTFOUND) {
1475 			rdataset = isc_mempool_get(msg->rdspool);
1476 			if (rdataset == NULL) {
1477 				result = ISC_R_NOMEMORY;
1478 				goto cleanup;
1479 			}
1480 			free_rdataset = ISC_TRUE;
1481 
1482 			rdatalist = newrdatalist(msg);
1483 			if (rdatalist == NULL) {
1484 				result = ISC_R_NOMEMORY;
1485 				goto cleanup;
1486 			}
1487 
1488 			rdatalist->type = rdtype;
1489 			rdatalist->covers = covers;
1490 			rdatalist->rdclass = rdclass;
1491 			rdatalist->ttl = ttl;
1492 			ISC_LIST_INIT(rdatalist->rdata);
1493 
1494 			dns_rdataset_init(rdataset);
1495 			RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist,
1496 							       rdataset)
1497 				      == ISC_R_SUCCESS);
1498 
1499 			if (rdtype != dns_rdatatype_opt &&
1500 			    rdtype != dns_rdatatype_tsig &&
1501 			    !issigzero)
1502 			{
1503 				ISC_LIST_APPEND(name->list, rdataset, link);
1504 				free_rdataset = ISC_FALSE;
1505 			}
1506 		}
1507 
1508 		/*
1509 		 * Minimize TTLs.
1510 		 *
1511 		 * Section 5.2 of RFC2181 says we should drop
1512 		 * nonauthoritative rrsets where the TTLs differ, but we
1513 		 * currently treat them the as if they were authoritative and
1514 		 * minimize them.
1515 		 */
1516 		if (ttl != rdataset->ttl) {
1517 			rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
1518 			if (ttl < rdataset->ttl)
1519 				rdataset->ttl = ttl;
1520 		}
1521 
1522 		/* Append this rdata to the rdataset. */
1523 		dns_rdatalist_fromrdataset(rdataset, &rdatalist);
1524 		ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1525 
1526 		/*
1527 		 * If this is an OPT record, remember it.  Also, set
1528 		 * the extended rcode.  Note that msg->opt will only be set
1529 		 * if best-effort parsing is enabled.
1530 		 */
1531 		if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
1532 			dns_rcode_t ercode;
1533 
1534 			msg->opt = rdataset;
1535 			rdataset = NULL;
1536 			free_rdataset = ISC_FALSE;
1537 			ercode = (dns_rcode_t)
1538 				((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
1539 				 >> 20);
1540 			msg->rcode |= ercode;
1541 			isc_mempool_put(msg->namepool, name);
1542 			free_name = ISC_FALSE;
1543 		}
1544 
1545 		/*
1546 		 * If this is an SIG(0) or TSIG record, remember it.  Note
1547 		 * that msg->sig0 or msg->tsig will only be set if best-effort
1548 		 * parsing is enabled.
1549 		 */
1550 		if (issigzero && msg->sig0 == NULL) {
1551 			msg->sig0 = rdataset;
1552 			msg->sig0name = name;
1553 			rdataset = NULL;
1554 			free_rdataset = ISC_FALSE;
1555 			free_name = ISC_FALSE;
1556 		} else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
1557 			msg->tsig = rdataset;
1558 			msg->tsigname = name;
1559 			/* Windows doesn't like TSIG names to be compressed. */
1560 			msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
1561 			rdataset = NULL;
1562 			free_rdataset = ISC_FALSE;
1563 			free_name = ISC_FALSE;
1564 		}
1565 
1566 		if (seen_problem) {
1567 			if (free_name)
1568 				isc_mempool_put(msg->namepool, name);
1569 			if (free_rdataset)
1570 				isc_mempool_put(msg->rdspool, rdataset);
1571 			free_name = free_rdataset = ISC_FALSE;
1572 		}
1573 		INSIST(free_name == ISC_FALSE);
1574 		INSIST(free_rdataset == ISC_FALSE);
1575 	}
1576 
1577 	if (seen_problem)
1578 		return (DNS_R_RECOVERABLE);
1579 	return (ISC_R_SUCCESS);
1580 
1581  cleanup:
1582 	if (free_name)
1583 		isc_mempool_put(msg->namepool, name);
1584 	if (free_rdataset)
1585 		isc_mempool_put(msg->rdspool, rdataset);
1586 
1587 	return (result);
1588 }
1589 
1590 isc_result_t
dns_message_parse(dns_message_t * msg,isc_buffer_t * source,unsigned int options)1591 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
1592 		  unsigned int options)
1593 {
1594 	isc_region_t r;
1595 	dns_decompress_t dctx;
1596 	isc_result_t ret;
1597 	isc_uint16_t tmpflags;
1598 	isc_buffer_t origsource;
1599 	isc_boolean_t seen_problem;
1600 	isc_boolean_t ignore_tc;
1601 
1602 	REQUIRE(DNS_MESSAGE_VALID(msg));
1603 	REQUIRE(source != NULL);
1604 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
1605 
1606 	seen_problem = ISC_FALSE;
1607 	ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
1608 
1609 	origsource = *source;
1610 
1611 	msg->header_ok = 0;
1612 	msg->question_ok = 0;
1613 
1614 	isc_buffer_remainingregion(source, &r);
1615 	if (r.length < DNS_MESSAGE_HEADERLEN)
1616 		return (ISC_R_UNEXPECTEDEND);
1617 
1618 	msg->id = isc_buffer_getuint16(source);
1619 	tmpflags = isc_buffer_getuint16(source);
1620 	msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
1621 		       >> DNS_MESSAGE_OPCODE_SHIFT);
1622 	msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
1623 	msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
1624 	msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
1625 	msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
1626 	msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
1627 	msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
1628 
1629 	msg->header_ok = 1;
1630 
1631 	/*
1632 	 * -1 means no EDNS.
1633 	 */
1634 	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
1635 
1636 	dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
1637 
1638 	ret = getquestions(source, msg, &dctx, options);
1639 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1640 		goto truncated;
1641 	if (ret == DNS_R_RECOVERABLE) {
1642 		seen_problem = ISC_TRUE;
1643 		ret = ISC_R_SUCCESS;
1644 	}
1645 	if (ret != ISC_R_SUCCESS)
1646 		return (ret);
1647 	msg->question_ok = 1;
1648 
1649 	ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
1650 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1651 		goto truncated;
1652 	if (ret == DNS_R_RECOVERABLE) {
1653 		seen_problem = ISC_TRUE;
1654 		ret = ISC_R_SUCCESS;
1655 	}
1656 	if (ret != ISC_R_SUCCESS)
1657 		return (ret);
1658 
1659 	ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
1660 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1661 		goto truncated;
1662 	if (ret == DNS_R_RECOVERABLE) {
1663 		seen_problem = ISC_TRUE;
1664 		ret = ISC_R_SUCCESS;
1665 	}
1666 	if (ret != ISC_R_SUCCESS)
1667 		return (ret);
1668 
1669 	ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
1670 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1671 		goto truncated;
1672 	if (ret == DNS_R_RECOVERABLE) {
1673 		seen_problem = ISC_TRUE;
1674 		ret = ISC_R_SUCCESS;
1675 	}
1676 	if (ret != ISC_R_SUCCESS)
1677 		return (ret);
1678 
1679 	isc_buffer_remainingregion(source, &r);
1680 	if (r.length != 0) {
1681 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1682 			      DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
1683 			      "message has %u byte(s) of trailing garbage",
1684 			      r.length);
1685 	}
1686 
1687  truncated:
1688 	if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
1689 		isc_buffer_usedregion(&origsource, &msg->saved);
1690 	else {
1691 		msg->saved.length = isc_buffer_usedlength(&origsource);
1692 		msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
1693 		if (msg->saved.base == NULL)
1694 			return (ISC_R_NOMEMORY);
1695 		memmove(msg->saved.base, isc_buffer_base(&origsource),
1696 			msg->saved.length);
1697 		msg->free_saved = 1;
1698 	}
1699 
1700 	if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
1701 		return (DNS_R_RECOVERABLE);
1702 	if (seen_problem == ISC_TRUE)
1703 		return (DNS_R_RECOVERABLE);
1704 	return (ISC_R_SUCCESS);
1705 }
1706 
1707 isc_result_t
dns_message_renderbegin(dns_message_t * msg,dns_compress_t * cctx,isc_buffer_t * buffer)1708 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
1709 			isc_buffer_t *buffer)
1710 {
1711 	isc_region_t r;
1712 
1713 	REQUIRE(DNS_MESSAGE_VALID(msg));
1714 	REQUIRE(buffer != NULL);
1715 	REQUIRE(msg->buffer == NULL);
1716 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
1717 
1718 	msg->cctx = cctx;
1719 
1720 	/*
1721 	 * Erase the contents of this buffer.
1722 	 */
1723 	isc_buffer_clear(buffer);
1724 
1725 	/*
1726 	 * Make certain there is enough for at least the header in this
1727 	 * buffer.
1728 	 */
1729 	isc_buffer_availableregion(buffer, &r);
1730 	if (r.length < DNS_MESSAGE_HEADERLEN)
1731 		return (ISC_R_NOSPACE);
1732 
1733 	if (r.length < msg->reserved)
1734 		return (ISC_R_NOSPACE);
1735 
1736 	/*
1737 	 * Reserve enough space for the header in this buffer.
1738 	 */
1739 	isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
1740 
1741 	msg->buffer = buffer;
1742 
1743 	return (ISC_R_SUCCESS);
1744 }
1745 
1746 isc_result_t
dns_message_renderchangebuffer(dns_message_t * msg,isc_buffer_t * buffer)1747 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
1748 	isc_region_t r, rn;
1749 
1750 	REQUIRE(DNS_MESSAGE_VALID(msg));
1751 	REQUIRE(buffer != NULL);
1752 	REQUIRE(msg->buffer != NULL);
1753 
1754 	/*
1755 	 * Ensure that the new buffer is empty, and has enough space to
1756 	 * hold the current contents.
1757 	 */
1758 	isc_buffer_clear(buffer);
1759 
1760 	isc_buffer_availableregion(buffer, &rn);
1761 	isc_buffer_usedregion(msg->buffer, &r);
1762 	REQUIRE(rn.length > r.length);
1763 
1764 	/*
1765 	 * Copy the contents from the old to the new buffer.
1766 	 */
1767 	isc_buffer_add(buffer, r.length);
1768 	memmove(rn.base, r.base, r.length);
1769 
1770 	msg->buffer = buffer;
1771 
1772 	return (ISC_R_SUCCESS);
1773 }
1774 
1775 void
dns_message_renderrelease(dns_message_t * msg,unsigned int space)1776 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
1777 	REQUIRE(DNS_MESSAGE_VALID(msg));
1778 	REQUIRE(space <= msg->reserved);
1779 
1780 	msg->reserved -= space;
1781 }
1782 
1783 isc_result_t
dns_message_renderreserve(dns_message_t * msg,unsigned int space)1784 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
1785 	isc_region_t r;
1786 
1787 	REQUIRE(DNS_MESSAGE_VALID(msg));
1788 
1789 	if (msg->buffer != NULL) {
1790 		isc_buffer_availableregion(msg->buffer, &r);
1791 		if (r.length < (space + msg->reserved))
1792 			return (ISC_R_NOSPACE);
1793 	}
1794 
1795 	msg->reserved += space;
1796 
1797 	return (ISC_R_SUCCESS);
1798 }
1799 
1800 static inline isc_boolean_t
wrong_priority(dns_rdataset_t * rds,int pass,dns_rdatatype_t preferred_glue)1801 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
1802 	int pass_needed;
1803 
1804 	/*
1805 	 * If we are not rendering class IN, this ordering is bogus.
1806 	 */
1807 	if (rds->rdclass != dns_rdataclass_in)
1808 		return (ISC_FALSE);
1809 
1810 	switch (rds->type) {
1811 	case dns_rdatatype_a:
1812 	case dns_rdatatype_aaaa:
1813 		if (preferred_glue == rds->type)
1814 			pass_needed = 4;
1815 		else
1816 			pass_needed = 3;
1817 		break;
1818 	case dns_rdatatype_rrsig:
1819 	case dns_rdatatype_dnskey:
1820 		pass_needed = 2;
1821 		break;
1822 	default:
1823 		pass_needed = 1;
1824 	}
1825 
1826 	if (pass_needed >= pass)
1827 		return (ISC_FALSE);
1828 
1829 	return (ISC_TRUE);
1830 }
1831 
1832 #ifdef ALLOW_FILTER_AAAA
1833 /*
1834  * Decide whether to not answer with an AAAA record and its RRSIG
1835  */
1836 static inline isc_boolean_t
norender_rdataset(const dns_rdataset_t * rdataset,unsigned int options)1837 norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options)
1838 {
1839 	switch (rdataset->type) {
1840 	case dns_rdatatype_aaaa:
1841 		if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0)
1842 			return (ISC_FALSE);
1843 		break;
1844 
1845 	case dns_rdatatype_rrsig:
1846 		if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 ||
1847 		    rdataset->covers != dns_rdatatype_aaaa)
1848 			return (ISC_FALSE);
1849 		break;
1850 
1851 	default:
1852 		return (ISC_FALSE);
1853 	}
1854 
1855 	if (rdataset->rdclass != dns_rdataclass_in)
1856 		return (ISC_FALSE);
1857 
1858 	return (ISC_TRUE);
1859 }
1860 
1861 #endif
1862 isc_result_t
dns_message_rendersection(dns_message_t * msg,dns_section_t sectionid,unsigned int options)1863 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
1864 			  unsigned int options)
1865 {
1866 	dns_namelist_t *section;
1867 	dns_name_t *name, *next_name;
1868 	dns_rdataset_t *rdataset, *next_rdataset;
1869 	unsigned int count, total;
1870 	isc_result_t result;
1871 	isc_buffer_t st; /* for rollbacks */
1872 	int pass;
1873 	isc_boolean_t partial = ISC_FALSE;
1874 	unsigned int rd_options;
1875 	dns_rdatatype_t preferred_glue = 0;
1876 
1877 	REQUIRE(DNS_MESSAGE_VALID(msg));
1878 	REQUIRE(msg->buffer != NULL);
1879 	REQUIRE(VALID_NAMED_SECTION(sectionid));
1880 
1881 	section = &msg->sections[sectionid];
1882 
1883 	if ((sectionid == DNS_SECTION_ADDITIONAL)
1884 	    && (options & DNS_MESSAGERENDER_ORDERED) == 0) {
1885 		if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
1886 			preferred_glue = dns_rdatatype_a;
1887 			pass = 4;
1888 		} else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
1889 			preferred_glue = dns_rdatatype_aaaa;
1890 			pass = 4;
1891 		} else
1892 			pass = 3;
1893 	} else
1894 		pass = 1;
1895 
1896 	if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0)
1897 		rd_options = 0;
1898 	else
1899 		rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
1900 
1901 	/*
1902 	 * Shrink the space in the buffer by the reserved amount.
1903 	 */
1904 	msg->buffer->length -= msg->reserved;
1905 
1906 	total = 0;
1907 	if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
1908 		partial = ISC_TRUE;
1909 
1910 	/*
1911 	 * Render required glue first.  Set TC if it won't fit.
1912 	 */
1913 	name = ISC_LIST_HEAD(*section);
1914 	if (name != NULL) {
1915 		rdataset = ISC_LIST_HEAD(name->list);
1916 		if (rdataset != NULL &&
1917 		    (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
1918 		    (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
1919 			const void *order_arg = msg->order_arg;
1920 			st = *(msg->buffer);
1921 			count = 0;
1922 			if (partial)
1923 				result = dns_rdataset_towirepartial(rdataset,
1924 								    name,
1925 								    msg->cctx,
1926 								    msg->buffer,
1927 								    msg->order,
1928 								    order_arg,
1929 								    rd_options,
1930 								    &count,
1931 								    NULL);
1932 			else
1933 				result = dns_rdataset_towiresorted(rdataset,
1934 								   name,
1935 								   msg->cctx,
1936 								   msg->buffer,
1937 								   msg->order,
1938 								   order_arg,
1939 								   rd_options,
1940 								   &count);
1941 			total += count;
1942 			if (partial && result == ISC_R_NOSPACE) {
1943 				msg->flags |= DNS_MESSAGEFLAG_TC;
1944 				msg->buffer->length += msg->reserved;
1945 				msg->counts[sectionid] += total;
1946 				return (result);
1947 			}
1948 			if (result == ISC_R_NOSPACE)
1949 				msg->flags |= DNS_MESSAGEFLAG_TC;
1950 			if (result != ISC_R_SUCCESS) {
1951 				INSIST(st.used < 65536);
1952 				dns_compress_rollback(msg->cctx,
1953 						      (isc_uint16_t)st.used);
1954 				*(msg->buffer) = st;  /* rollback */
1955 				msg->buffer->length += msg->reserved;
1956 				msg->counts[sectionid] += total;
1957 				return (result);
1958 			}
1959 			rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
1960 		}
1961 	}
1962 
1963 	do {
1964 		name = ISC_LIST_HEAD(*section);
1965 		if (name == NULL) {
1966 			msg->buffer->length += msg->reserved;
1967 			msg->counts[sectionid] += total;
1968 			return (ISC_R_SUCCESS);
1969 		}
1970 
1971 		while (name != NULL) {
1972 			next_name = ISC_LIST_NEXT(name, link);
1973 
1974 			rdataset = ISC_LIST_HEAD(name->list);
1975 			while (rdataset != NULL) {
1976 				next_rdataset = ISC_LIST_NEXT(rdataset, link);
1977 
1978 				if ((rdataset->attributes &
1979 				     DNS_RDATASETATTR_RENDERED) != 0)
1980 					goto next;
1981 
1982 				if (((options & DNS_MESSAGERENDER_ORDERED)
1983 				     == 0)
1984 				    && (sectionid == DNS_SECTION_ADDITIONAL)
1985 				    && wrong_priority(rdataset, pass,
1986 						      preferred_glue))
1987 					goto next;
1988 
1989 #ifdef ALLOW_FILTER_AAAA
1990 				/*
1991 				 * Suppress AAAAs if asked and we are
1992 				 * not doing DNSSEC or are breaking DNSSEC.
1993 				 * Say so in the AD bit if we break DNSSEC.
1994 				 */
1995 				if (norender_rdataset(rdataset, options) &&
1996 				    sectionid != DNS_SECTION_QUESTION) {
1997 					if (sectionid == DNS_SECTION_ANSWER ||
1998 					    sectionid == DNS_SECTION_AUTHORITY)
1999 					    msg->flags &= ~DNS_MESSAGEFLAG_AD;
2000 					if (OPTOUT(rdataset))
2001 					    msg->flags &= ~DNS_MESSAGEFLAG_AD;
2002 					goto next;
2003 				}
2004 
2005 #endif
2006 				st = *(msg->buffer);
2007 
2008 				count = 0;
2009 				if (partial)
2010 					result = dns_rdataset_towirepartial(
2011 							  rdataset,
2012 							  name,
2013 							  msg->cctx,
2014 							  msg->buffer,
2015 							  msg->order,
2016 							  msg->order_arg,
2017 							  rd_options,
2018 							  &count,
2019 							  NULL);
2020 				else
2021 					result = dns_rdataset_towiresorted(
2022 							  rdataset,
2023 							  name,
2024 							  msg->cctx,
2025 							  msg->buffer,
2026 							  msg->order,
2027 							  msg->order_arg,
2028 							  rd_options,
2029 							  &count);
2030 
2031 				total += count;
2032 
2033 				/*
2034 				 * If out of space, record stats on what we
2035 				 * rendered so far, and return that status.
2036 				 *
2037 				 * XXXMLG Need to change this when
2038 				 * dns_rdataset_towire() can render partial
2039 				 * sets starting at some arbitrary point in the
2040 				 * set.  This will include setting a bit in the
2041 				 * rdataset to indicate that a partial
2042 				 * rendering was done, and some state saved
2043 				 * somewhere (probably in the message struct)
2044 				 * to indicate where to continue from.
2045 				 */
2046 				if (partial && result == ISC_R_NOSPACE) {
2047 					msg->buffer->length += msg->reserved;
2048 					msg->counts[sectionid] += total;
2049 					return (result);
2050 				}
2051 				if (result != ISC_R_SUCCESS) {
2052 					INSIST(st.used < 65536);
2053 					dns_compress_rollback(msg->cctx,
2054 							(isc_uint16_t)st.used);
2055 					*(msg->buffer) = st;  /* rollback */
2056 					msg->buffer->length += msg->reserved;
2057 					msg->counts[sectionid] += total;
2058 					return (result);
2059 				}
2060 
2061 				/*
2062 				 * If we have rendered non-validated data,
2063 				 * ensure that the AD bit is not set.
2064 				 */
2065 				if (rdataset->trust != dns_trust_secure &&
2066 				    (sectionid == DNS_SECTION_ANSWER ||
2067 				     sectionid == DNS_SECTION_AUTHORITY))
2068 					msg->flags &= ~DNS_MESSAGEFLAG_AD;
2069 				if (OPTOUT(rdataset))
2070 					msg->flags &= ~DNS_MESSAGEFLAG_AD;
2071 
2072 				rdataset->attributes |=
2073 					DNS_RDATASETATTR_RENDERED;
2074 
2075 			next:
2076 				rdataset = next_rdataset;
2077 			}
2078 
2079 			name = next_name;
2080 		}
2081 	} while (--pass != 0);
2082 
2083 	msg->buffer->length += msg->reserved;
2084 	msg->counts[sectionid] += total;
2085 
2086 	return (ISC_R_SUCCESS);
2087 }
2088 
2089 void
dns_message_renderheader(dns_message_t * msg,isc_buffer_t * target)2090 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
2091 	isc_uint16_t tmp;
2092 	isc_region_t r;
2093 
2094 	REQUIRE(DNS_MESSAGE_VALID(msg));
2095 	REQUIRE(target != NULL);
2096 
2097 	isc_buffer_availableregion(target, &r);
2098 	REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
2099 
2100 	isc_buffer_putuint16(target, msg->id);
2101 
2102 	tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
2103 	       & DNS_MESSAGE_OPCODE_MASK);
2104 	tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
2105 	tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
2106 
2107 	INSIST(msg->counts[DNS_SECTION_QUESTION]  < 65536 &&
2108 	       msg->counts[DNS_SECTION_ANSWER]    < 65536 &&
2109 	       msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
2110 	       msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
2111 
2112 	isc_buffer_putuint16(target, tmp);
2113 	isc_buffer_putuint16(target,
2114 			    (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
2115 	isc_buffer_putuint16(target,
2116 			    (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
2117 	isc_buffer_putuint16(target,
2118 			    (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
2119 	isc_buffer_putuint16(target,
2120 			    (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
2121 }
2122 
2123 isc_result_t
dns_message_renderend(dns_message_t * msg)2124 dns_message_renderend(dns_message_t *msg) {
2125 	isc_buffer_t tmpbuf;
2126 	isc_region_t r;
2127 	int result;
2128 	unsigned int count;
2129 
2130 	REQUIRE(DNS_MESSAGE_VALID(msg));
2131 	REQUIRE(msg->buffer != NULL);
2132 
2133 	if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
2134 		/*
2135 		 * We have an extended rcode but are not using EDNS.
2136 		 */
2137 		return (DNS_R_FORMERR);
2138 	}
2139 
2140 	/*
2141 	 * If we're adding a OPT, TSIG or SIG(0) to a truncated message,
2142 	 * clear all rdatasets from the message except for the question
2143 	 * before adding the OPT, TSIG or SIG(0).  If the question doesn't
2144 	 * fit, don't include it.
2145 	 */
2146 	if ((msg->tsigkey != NULL || msg->sig0key != NULL || msg->opt) &&
2147 	    (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
2148 	{
2149 		isc_buffer_t *buf;
2150 
2151 		msgresetnames(msg, DNS_SECTION_ANSWER);
2152 		buf = msg->buffer;
2153 		dns_message_renderreset(msg);
2154 		msg->buffer = buf;
2155 		isc_buffer_clear(msg->buffer);
2156 		isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
2157 		dns_compress_rollback(msg->cctx, 0);
2158 		result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
2159 						   0);
2160 		if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
2161 			return (result);
2162 	}
2163 
2164 	/*
2165 	 * If we've got an OPT record, render it.
2166 	 */
2167 	if (msg->opt != NULL) {
2168 		dns_message_renderrelease(msg, msg->opt_reserved);
2169 		msg->opt_reserved = 0;
2170 		/*
2171 		 * Set the extended rcode.
2172 		 */
2173 		msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
2174 		msg->opt->ttl |= ((msg->rcode << 20) &
2175 				  DNS_MESSAGE_EDNSRCODE_MASK);
2176 		/*
2177 		 * Render.
2178 		 */
2179 		count = 0;
2180 		result = dns_rdataset_towire(msg->opt, dns_rootname,
2181 					     msg->cctx, msg->buffer, 0,
2182 					     &count);
2183 		msg->counts[DNS_SECTION_ADDITIONAL] += count;
2184 		if (result != ISC_R_SUCCESS)
2185 			return (result);
2186 	}
2187 
2188 	/*
2189 	 * If we're adding a TSIG record, generate and render it.
2190 	 */
2191 	if (msg->tsigkey != NULL) {
2192 		dns_message_renderrelease(msg, msg->sig_reserved);
2193 		msg->sig_reserved = 0;
2194 		result = dns_tsig_sign(msg);
2195 		if (result != ISC_R_SUCCESS)
2196 			return (result);
2197 		count = 0;
2198 		result = dns_rdataset_towire(msg->tsig, msg->tsigname,
2199 					     msg->cctx, msg->buffer, 0,
2200 					     &count);
2201 		msg->counts[DNS_SECTION_ADDITIONAL] += count;
2202 		if (result != ISC_R_SUCCESS)
2203 			return (result);
2204 	}
2205 
2206 	/*
2207 	 * If we're adding a SIG(0) record, generate and render it.
2208 	 */
2209 	if (msg->sig0key != NULL) {
2210 		dns_message_renderrelease(msg, msg->sig_reserved);
2211 		msg->sig_reserved = 0;
2212 		result = dns_dnssec_signmessage(msg, msg->sig0key);
2213 		if (result != ISC_R_SUCCESS)
2214 			return (result);
2215 		count = 0;
2216 		/*
2217 		 * Note: dns_rootname is used here, not msg->sig0name, since
2218 		 * the owner name of a SIG(0) is irrelevant, and will not
2219 		 * be set in a message being rendered.
2220 		 */
2221 		result = dns_rdataset_towire(msg->sig0, dns_rootname,
2222 					     msg->cctx, msg->buffer, 0,
2223 					     &count);
2224 		msg->counts[DNS_SECTION_ADDITIONAL] += count;
2225 		if (result != ISC_R_SUCCESS)
2226 			return (result);
2227 	}
2228 
2229 	isc_buffer_usedregion(msg->buffer, &r);
2230 	isc_buffer_init(&tmpbuf, r.base, r.length);
2231 
2232 	dns_message_renderheader(msg, &tmpbuf);
2233 
2234 	msg->buffer = NULL;  /* forget about this buffer only on success XXX */
2235 
2236 	return (ISC_R_SUCCESS);
2237 }
2238 
2239 void
dns_message_renderreset(dns_message_t * msg)2240 dns_message_renderreset(dns_message_t *msg) {
2241 	unsigned int i;
2242 	dns_name_t *name;
2243 	dns_rdataset_t *rds;
2244 
2245 	/*
2246 	 * Reset the message so that it may be rendered again.
2247 	 */
2248 
2249 	REQUIRE(DNS_MESSAGE_VALID(msg));
2250 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2251 
2252 	msg->buffer = NULL;
2253 
2254 	for (i = 0; i < DNS_SECTION_MAX; i++) {
2255 		msg->cursors[i] = NULL;
2256 		msg->counts[i] = 0;
2257 		for (name = ISC_LIST_HEAD(msg->sections[i]);
2258 		     name != NULL;
2259 		     name = ISC_LIST_NEXT(name, link)) {
2260 			for (rds = ISC_LIST_HEAD(name->list);
2261 			     rds != NULL;
2262 			     rds = ISC_LIST_NEXT(rds, link)) {
2263 				rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
2264 			}
2265 		}
2266 	}
2267 	if (msg->tsigname != NULL)
2268 		dns_message_puttempname(msg, &msg->tsigname);
2269 	if (msg->tsig != NULL) {
2270 		dns_rdataset_disassociate(msg->tsig);
2271 		dns_message_puttemprdataset(msg, &msg->tsig);
2272 	}
2273 	if (msg->sig0 != NULL) {
2274 		dns_rdataset_disassociate(msg->sig0);
2275 		dns_message_puttemprdataset(msg, &msg->sig0);
2276 	}
2277 }
2278 
2279 isc_result_t
dns_message_firstname(dns_message_t * msg,dns_section_t section)2280 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
2281 	REQUIRE(DNS_MESSAGE_VALID(msg));
2282 	REQUIRE(VALID_NAMED_SECTION(section));
2283 
2284 	msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
2285 
2286 	if (msg->cursors[section] == NULL)
2287 		return (ISC_R_NOMORE);
2288 
2289 	return (ISC_R_SUCCESS);
2290 }
2291 
2292 isc_result_t
dns_message_nextname(dns_message_t * msg,dns_section_t section)2293 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
2294 	REQUIRE(DNS_MESSAGE_VALID(msg));
2295 	REQUIRE(VALID_NAMED_SECTION(section));
2296 	REQUIRE(msg->cursors[section] != NULL);
2297 
2298 	msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
2299 
2300 	if (msg->cursors[section] == NULL)
2301 		return (ISC_R_NOMORE);
2302 
2303 	return (ISC_R_SUCCESS);
2304 }
2305 
2306 void
dns_message_currentname(dns_message_t * msg,dns_section_t section,dns_name_t ** name)2307 dns_message_currentname(dns_message_t *msg, dns_section_t section,
2308 			dns_name_t **name)
2309 {
2310 	REQUIRE(DNS_MESSAGE_VALID(msg));
2311 	REQUIRE(VALID_NAMED_SECTION(section));
2312 	REQUIRE(name != NULL && *name == NULL);
2313 	REQUIRE(msg->cursors[section] != NULL);
2314 
2315 	*name = msg->cursors[section];
2316 }
2317 
2318 isc_result_t
dns_message_findname(dns_message_t * msg,dns_section_t section,dns_name_t * target,dns_rdatatype_t type,dns_rdatatype_t covers,dns_name_t ** name,dns_rdataset_t ** rdataset)2319 dns_message_findname(dns_message_t *msg, dns_section_t section,
2320 		     dns_name_t *target, dns_rdatatype_t type,
2321 		     dns_rdatatype_t covers, dns_name_t **name,
2322 		     dns_rdataset_t **rdataset)
2323 {
2324 	dns_name_t *foundname;
2325 	isc_result_t result;
2326 
2327 	/*
2328 	 * XXX These requirements are probably too intensive, especially
2329 	 * where things can be NULL, but as they are they ensure that if
2330 	 * something is NON-NULL, indicating that the caller expects it
2331 	 * to be filled in, that we can in fact fill it in.
2332 	 */
2333 	REQUIRE(msg != NULL);
2334 	REQUIRE(VALID_SECTION(section));
2335 	REQUIRE(target != NULL);
2336 	if (name != NULL)
2337 		REQUIRE(*name == NULL);
2338 	if (type == dns_rdatatype_any) {
2339 		REQUIRE(rdataset == NULL);
2340 	} else {
2341 		if (rdataset != NULL)
2342 			REQUIRE(*rdataset == NULL);
2343 	}
2344 
2345 	result = findname(&foundname, target,
2346 			  &msg->sections[section]);
2347 
2348 	if (result == ISC_R_NOTFOUND)
2349 		return (DNS_R_NXDOMAIN);
2350 	else if (result != ISC_R_SUCCESS)
2351 		return (result);
2352 
2353 	if (name != NULL)
2354 		*name = foundname;
2355 
2356 	/*
2357 	 * And now look for the type.
2358 	 */
2359 	if (type == dns_rdatatype_any)
2360 		return (ISC_R_SUCCESS);
2361 
2362 	result = dns_message_findtype(foundname, type, covers, rdataset);
2363 	if (result == ISC_R_NOTFOUND)
2364 		return (DNS_R_NXRRSET);
2365 
2366 	return (result);
2367 }
2368 
2369 void
dns_message_movename(dns_message_t * msg,dns_name_t * name,dns_section_t fromsection,dns_section_t tosection)2370 dns_message_movename(dns_message_t *msg, dns_name_t *name,
2371 		     dns_section_t fromsection,
2372 		     dns_section_t tosection)
2373 {
2374 	REQUIRE(msg != NULL);
2375 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2376 	REQUIRE(name != NULL);
2377 	REQUIRE(VALID_NAMED_SECTION(fromsection));
2378 	REQUIRE(VALID_NAMED_SECTION(tosection));
2379 
2380 	/*
2381 	 * Unlink the name from the old section
2382 	 */
2383 	ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
2384 	ISC_LIST_APPEND(msg->sections[tosection], name, link);
2385 }
2386 
2387 void
dns_message_addname(dns_message_t * msg,dns_name_t * name,dns_section_t section)2388 dns_message_addname(dns_message_t *msg, dns_name_t *name,
2389 		    dns_section_t section)
2390 {
2391 	REQUIRE(msg != NULL);
2392 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2393 	REQUIRE(name != NULL);
2394 	REQUIRE(VALID_NAMED_SECTION(section));
2395 
2396 	ISC_LIST_APPEND(msg->sections[section], name, link);
2397 }
2398 
2399 void
dns_message_removename(dns_message_t * msg,dns_name_t * name,dns_section_t section)2400 dns_message_removename(dns_message_t *msg, dns_name_t *name,
2401 		       dns_section_t section)
2402 {
2403 	REQUIRE(msg != NULL);
2404 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2405 	REQUIRE(name != NULL);
2406 	REQUIRE(VALID_NAMED_SECTION(section));
2407 
2408 	ISC_LIST_UNLINK(msg->sections[section], name, link);
2409 }
2410 
2411 isc_result_t
dns_message_gettempname(dns_message_t * msg,dns_name_t ** item)2412 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
2413 	REQUIRE(DNS_MESSAGE_VALID(msg));
2414 	REQUIRE(item != NULL && *item == NULL);
2415 
2416 	*item = isc_mempool_get(msg->namepool);
2417 	if (*item == NULL)
2418 		return (ISC_R_NOMEMORY);
2419 	dns_name_init(*item, NULL);
2420 
2421 	return (ISC_R_SUCCESS);
2422 }
2423 
2424 isc_result_t
dns_message_gettempoffsets(dns_message_t * msg,dns_offsets_t ** item)2425 dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
2426 	REQUIRE(DNS_MESSAGE_VALID(msg));
2427 	REQUIRE(item != NULL && *item == NULL);
2428 
2429 	*item = newoffsets(msg);
2430 	if (*item == NULL)
2431 		return (ISC_R_NOMEMORY);
2432 
2433 	return (ISC_R_SUCCESS);
2434 }
2435 
2436 isc_result_t
dns_message_gettemprdata(dns_message_t * msg,dns_rdata_t ** item)2437 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
2438 	REQUIRE(DNS_MESSAGE_VALID(msg));
2439 	REQUIRE(item != NULL && *item == NULL);
2440 
2441 	*item = newrdata(msg);
2442 	if (*item == NULL)
2443 		return (ISC_R_NOMEMORY);
2444 
2445 	return (ISC_R_SUCCESS);
2446 }
2447 
2448 isc_result_t
dns_message_gettemprdataset(dns_message_t * msg,dns_rdataset_t ** item)2449 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2450 	REQUIRE(DNS_MESSAGE_VALID(msg));
2451 	REQUIRE(item != NULL && *item == NULL);
2452 
2453 	*item = isc_mempool_get(msg->rdspool);
2454 	if (*item == NULL)
2455 		return (ISC_R_NOMEMORY);
2456 
2457 	dns_rdataset_init(*item);
2458 
2459 	return (ISC_R_SUCCESS);
2460 }
2461 
2462 isc_result_t
dns_message_gettemprdatalist(dns_message_t * msg,dns_rdatalist_t ** item)2463 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2464 	REQUIRE(DNS_MESSAGE_VALID(msg));
2465 	REQUIRE(item != NULL && *item == NULL);
2466 
2467 	*item = newrdatalist(msg);
2468 	if (*item == NULL)
2469 		return (ISC_R_NOMEMORY);
2470 
2471 	return (ISC_R_SUCCESS);
2472 }
2473 
2474 void
dns_message_puttempname(dns_message_t * msg,dns_name_t ** item)2475 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
2476 	REQUIRE(DNS_MESSAGE_VALID(msg));
2477 	REQUIRE(item != NULL && *item != NULL);
2478 
2479 	if (dns_name_dynamic(*item))
2480 		dns_name_free(*item, msg->mctx);
2481 	isc_mempool_put(msg->namepool, *item);
2482 	*item = NULL;
2483 }
2484 
2485 void
dns_message_puttemprdata(dns_message_t * msg,dns_rdata_t ** item)2486 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
2487 	REQUIRE(DNS_MESSAGE_VALID(msg));
2488 	REQUIRE(item != NULL && *item != NULL);
2489 
2490 	releaserdata(msg, *item);
2491 	*item = NULL;
2492 }
2493 
2494 void
dns_message_puttemprdataset(dns_message_t * msg,dns_rdataset_t ** item)2495 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
2496 	REQUIRE(DNS_MESSAGE_VALID(msg));
2497 	REQUIRE(item != NULL && *item != NULL);
2498 
2499 	REQUIRE(!dns_rdataset_isassociated(*item));
2500 	isc_mempool_put(msg->rdspool, *item);
2501 	*item = NULL;
2502 }
2503 
2504 void
dns_message_puttemprdatalist(dns_message_t * msg,dns_rdatalist_t ** item)2505 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
2506 	REQUIRE(DNS_MESSAGE_VALID(msg));
2507 	REQUIRE(item != NULL && *item != NULL);
2508 
2509 	releaserdatalist(msg, *item);
2510 	*item = NULL;
2511 }
2512 
2513 isc_result_t
dns_message_peekheader(isc_buffer_t * source,dns_messageid_t * idp,unsigned int * flagsp)2514 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
2515 		       unsigned int *flagsp)
2516 {
2517 	isc_region_t r;
2518 	isc_buffer_t buffer;
2519 	dns_messageid_t id;
2520 	unsigned int flags;
2521 
2522 	REQUIRE(source != NULL);
2523 
2524 	buffer = *source;
2525 
2526 	isc_buffer_remainingregion(&buffer, &r);
2527 	if (r.length < DNS_MESSAGE_HEADERLEN)
2528 		return (ISC_R_UNEXPECTEDEND);
2529 
2530 	id = isc_buffer_getuint16(&buffer);
2531 	flags = isc_buffer_getuint16(&buffer);
2532 	flags &= DNS_MESSAGE_FLAG_MASK;
2533 
2534 	if (flagsp != NULL)
2535 		*flagsp = flags;
2536 	if (idp != NULL)
2537 		*idp = id;
2538 
2539 	return (ISC_R_SUCCESS);
2540 }
2541 
2542 isc_result_t
dns_message_reply(dns_message_t * msg,isc_boolean_t want_question_section)2543 dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
2544 	unsigned int clear_after;
2545 	isc_result_t result;
2546 
2547 	REQUIRE(DNS_MESSAGE_VALID(msg));
2548 	REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
2549 
2550 	if (!msg->header_ok)
2551 		return (DNS_R_FORMERR);
2552 	if (msg->opcode != dns_opcode_query &&
2553 	    msg->opcode != dns_opcode_notify)
2554 		want_question_section = ISC_FALSE;
2555 	if (msg->opcode == dns_opcode_update)
2556 		clear_after = DNS_SECTION_PREREQUISITE;
2557 	else if (want_question_section) {
2558 		if (!msg->question_ok)
2559 			return (DNS_R_FORMERR);
2560 		clear_after = DNS_SECTION_ANSWER;
2561 	} else
2562 		clear_after = DNS_SECTION_QUESTION;
2563 	msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
2564 	msgresetnames(msg, clear_after);
2565 	msgresetopt(msg);
2566 	msgresetsigs(msg, ISC_TRUE);
2567 	msginitprivate(msg);
2568 	/*
2569 	 * We now clear most flags and then set QR, ensuring that the
2570 	 * reply's flags will be in a reasonable state.
2571 	 */
2572 	msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
2573 	msg->flags |= DNS_MESSAGEFLAG_QR;
2574 
2575 	/*
2576 	 * This saves the query TSIG status, if the query was signed, and
2577 	 * reserves space in the reply for the TSIG.
2578 	 */
2579 	if (msg->tsigkey != NULL) {
2580 		unsigned int otherlen = 0;
2581 		msg->querytsigstatus = msg->tsigstatus;
2582 		msg->tsigstatus = dns_rcode_noerror;
2583 		if (msg->querytsigstatus == dns_tsigerror_badtime)
2584 			otherlen = 6;
2585 		msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
2586 		result = dns_message_renderreserve(msg, msg->sig_reserved);
2587 		if (result != ISC_R_SUCCESS) {
2588 			msg->sig_reserved = 0;
2589 			return (result);
2590 		}
2591 	}
2592 	if (msg->saved.base != NULL) {
2593 		msg->query.base = msg->saved.base;
2594 		msg->query.length = msg->saved.length;
2595 		msg->free_query = msg->free_saved;
2596 		msg->saved.base = NULL;
2597 		msg->saved.length = 0;
2598 		msg->free_saved = 0;
2599 	}
2600 
2601 	return (ISC_R_SUCCESS);
2602 }
2603 
2604 dns_rdataset_t *
dns_message_getopt(dns_message_t * msg)2605 dns_message_getopt(dns_message_t *msg) {
2606 
2607 	/*
2608 	 * Get the OPT record for 'msg'.
2609 	 */
2610 
2611 	REQUIRE(DNS_MESSAGE_VALID(msg));
2612 
2613 	return (msg->opt);
2614 }
2615 
2616 isc_result_t
dns_message_setopt(dns_message_t * msg,dns_rdataset_t * opt)2617 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
2618 	isc_result_t result;
2619 	dns_rdata_t rdata = DNS_RDATA_INIT;
2620 
2621 	/*
2622 	 * Set the OPT record for 'msg'.
2623 	 */
2624 
2625 	/*
2626 	 * The space required for an OPT record is:
2627 	 *
2628 	 *	1 byte for the name
2629 	 *	2 bytes for the type
2630 	 *	2 bytes for the class
2631 	 *	4 bytes for the ttl
2632 	 *	2 bytes for the rdata length
2633 	 * ---------------------------------
2634 	 *     11 bytes
2635 	 *
2636 	 * plus the length of the rdata.
2637 	 */
2638 
2639 	REQUIRE(DNS_MESSAGE_VALID(msg));
2640 	REQUIRE(opt->type == dns_rdatatype_opt);
2641 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2642 	REQUIRE(msg->state == DNS_SECTION_ANY);
2643 
2644 	msgresetopt(msg);
2645 
2646 	result = dns_rdataset_first(opt);
2647 	if (result != ISC_R_SUCCESS)
2648 		goto cleanup;
2649 	dns_rdataset_current(opt, &rdata);
2650 	msg->opt_reserved = 11 + rdata.length;
2651 	result = dns_message_renderreserve(msg, msg->opt_reserved);
2652 	if (result != ISC_R_SUCCESS) {
2653 		msg->opt_reserved = 0;
2654 		goto cleanup;
2655 	}
2656 
2657 	msg->opt = opt;
2658 
2659 	return (ISC_R_SUCCESS);
2660 
2661  cleanup:
2662 	dns_rdataset_disassociate(opt);
2663 	dns_message_puttemprdataset(msg, &opt);
2664 	return (result);
2665 }
2666 
2667 dns_rdataset_t *
dns_message_gettsig(dns_message_t * msg,dns_name_t ** owner)2668 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
2669 
2670 	/*
2671 	 * Get the TSIG record and owner for 'msg'.
2672 	 */
2673 
2674 	REQUIRE(DNS_MESSAGE_VALID(msg));
2675 	REQUIRE(owner == NULL || *owner == NULL);
2676 
2677 	if (owner != NULL)
2678 		*owner = msg->tsigname;
2679 	return (msg->tsig);
2680 }
2681 
2682 isc_result_t
dns_message_settsigkey(dns_message_t * msg,dns_tsigkey_t * key)2683 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
2684 	isc_result_t result;
2685 
2686 	/*
2687 	 * Set the TSIG key for 'msg'
2688 	 */
2689 
2690 	REQUIRE(DNS_MESSAGE_VALID(msg));
2691 	REQUIRE(msg->state == DNS_SECTION_ANY);
2692 
2693 	if (key == NULL && msg->tsigkey != NULL) {
2694 		if (msg->sig_reserved != 0) {
2695 			dns_message_renderrelease(msg, msg->sig_reserved);
2696 			msg->sig_reserved = 0;
2697 		}
2698 		dns_tsigkey_detach(&msg->tsigkey);
2699 	}
2700 	if (key != NULL) {
2701 		REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
2702 		dns_tsigkey_attach(key, &msg->tsigkey);
2703 		if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
2704 			msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
2705 			result = dns_message_renderreserve(msg,
2706 							   msg->sig_reserved);
2707 			if (result != ISC_R_SUCCESS) {
2708 				dns_tsigkey_detach(&msg->tsigkey);
2709 				msg->sig_reserved = 0;
2710 				return (result);
2711 			}
2712 		}
2713 	}
2714 	return (ISC_R_SUCCESS);
2715 }
2716 
2717 dns_tsigkey_t *
dns_message_gettsigkey(dns_message_t * msg)2718 dns_message_gettsigkey(dns_message_t *msg) {
2719 
2720 	/*
2721 	 * Get the TSIG key for 'msg'
2722 	 */
2723 
2724 	REQUIRE(DNS_MESSAGE_VALID(msg));
2725 
2726 	return (msg->tsigkey);
2727 }
2728 
2729 isc_result_t
dns_message_setquerytsig(dns_message_t * msg,isc_buffer_t * querytsig)2730 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
2731 	dns_rdata_t *rdata = NULL;
2732 	dns_rdatalist_t *list = NULL;
2733 	dns_rdataset_t *set = NULL;
2734 	isc_buffer_t *buf = NULL;
2735 	isc_region_t r;
2736 	isc_result_t result;
2737 
2738 	REQUIRE(DNS_MESSAGE_VALID(msg));
2739 	REQUIRE(msg->querytsig == NULL);
2740 
2741 	if (querytsig == NULL)
2742 		return (ISC_R_SUCCESS);
2743 
2744 	result = dns_message_gettemprdata(msg, &rdata);
2745 	if (result != ISC_R_SUCCESS)
2746 		goto cleanup;
2747 
2748 	result = dns_message_gettemprdatalist(msg, &list);
2749 	if (result != ISC_R_SUCCESS)
2750 		goto cleanup;
2751 	result = dns_message_gettemprdataset(msg, &set);
2752 	if (result != ISC_R_SUCCESS)
2753 		goto cleanup;
2754 
2755 	isc_buffer_usedregion(querytsig, &r);
2756 	result = isc_buffer_allocate(msg->mctx, &buf, r.length);
2757 	if (result != ISC_R_SUCCESS)
2758 		goto cleanup;
2759 	isc_buffer_putmem(buf, r.base, r.length);
2760 	isc_buffer_usedregion(buf, &r);
2761 	dns_rdata_init(rdata);
2762 	dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
2763 	dns_message_takebuffer(msg, &buf);
2764 	ISC_LIST_INIT(list->rdata);
2765 	ISC_LIST_APPEND(list->rdata, rdata, link);
2766 	result = dns_rdatalist_tordataset(list, set);
2767 	if (result != ISC_R_SUCCESS)
2768 		goto cleanup;
2769 
2770 	msg->querytsig = set;
2771 
2772 	return (result);
2773 
2774  cleanup:
2775 	if (rdata != NULL)
2776 		dns_message_puttemprdata(msg, &rdata);
2777 	if (list != NULL)
2778 		dns_message_puttemprdatalist(msg, &list);
2779 	if (set != NULL)
2780 		dns_message_puttemprdataset(msg, &set);
2781 	return (ISC_R_NOMEMORY);
2782 }
2783 
2784 isc_result_t
dns_message_getquerytsig(dns_message_t * msg,isc_mem_t * mctx,isc_buffer_t ** querytsig)2785 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
2786 			 isc_buffer_t **querytsig) {
2787 	isc_result_t result;
2788 	dns_rdata_t rdata = DNS_RDATA_INIT;
2789 	isc_region_t r;
2790 
2791 	REQUIRE(DNS_MESSAGE_VALID(msg));
2792 	REQUIRE(mctx != NULL);
2793 	REQUIRE(querytsig != NULL && *querytsig == NULL);
2794 
2795 	if (msg->tsig == NULL)
2796 		return (ISC_R_SUCCESS);
2797 
2798 	result = dns_rdataset_first(msg->tsig);
2799 	if (result != ISC_R_SUCCESS)
2800 		return (result);
2801 	dns_rdataset_current(msg->tsig, &rdata);
2802 	dns_rdata_toregion(&rdata, &r);
2803 
2804 	result = isc_buffer_allocate(mctx, querytsig, r.length);
2805 	if (result != ISC_R_SUCCESS)
2806 		return (result);
2807 	isc_buffer_putmem(*querytsig, r.base, r.length);
2808 	return (ISC_R_SUCCESS);
2809 }
2810 
2811 dns_rdataset_t *
dns_message_getsig0(dns_message_t * msg,dns_name_t ** owner)2812 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
2813 
2814 	/*
2815 	 * Get the SIG(0) record for 'msg'.
2816 	 */
2817 
2818 	REQUIRE(DNS_MESSAGE_VALID(msg));
2819 	REQUIRE(owner == NULL || *owner == NULL);
2820 
2821 	if (msg->sig0 != NULL && owner != NULL) {
2822 		/* If dns_message_getsig0 is called on a rendered message
2823 		 * after the SIG(0) has been applied, we need to return the
2824 		 * root name, not NULL.
2825 		 */
2826 		if (msg->sig0name == NULL)
2827 			*owner = dns_rootname;
2828 		else
2829 			*owner = msg->sig0name;
2830 	}
2831 	return (msg->sig0);
2832 }
2833 
2834 isc_result_t
dns_message_setsig0key(dns_message_t * msg,dst_key_t * key)2835 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
2836 	isc_region_t r;
2837 	unsigned int x;
2838 	isc_result_t result;
2839 
2840 	/*
2841 	 * Set the SIG(0) key for 'msg'
2842 	 */
2843 
2844 	/*
2845 	 * The space required for an SIG(0) record is:
2846 	 *
2847 	 *	1 byte for the name
2848 	 *	2 bytes for the type
2849 	 *	2 bytes for the class
2850 	 *	4 bytes for the ttl
2851 	 *	2 bytes for the type covered
2852 	 *	1 byte for the algorithm
2853 	 *	1 bytes for the labels
2854 	 *	4 bytes for the original ttl
2855 	 *	4 bytes for the signature expiration
2856 	 *	4 bytes for the signature inception
2857 	 *	2 bytes for the key tag
2858 	 *	n bytes for the signer's name
2859 	 *	x bytes for the signature
2860 	 * ---------------------------------
2861 	 *     27 + n + x bytes
2862 	 */
2863 	REQUIRE(DNS_MESSAGE_VALID(msg));
2864 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
2865 	REQUIRE(msg->state == DNS_SECTION_ANY);
2866 
2867 	if (key != NULL) {
2868 		REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
2869 		dns_name_toregion(dst_key_name(key), &r);
2870 		result = dst_key_sigsize(key, &x);
2871 		if (result != ISC_R_SUCCESS) {
2872 			msg->sig_reserved = 0;
2873 			return (result);
2874 		}
2875 		msg->sig_reserved = 27 + r.length + x;
2876 		result = dns_message_renderreserve(msg, msg->sig_reserved);
2877 		if (result != ISC_R_SUCCESS) {
2878 			msg->sig_reserved = 0;
2879 			return (result);
2880 		}
2881 		msg->sig0key = key;
2882 	}
2883 	return (ISC_R_SUCCESS);
2884 }
2885 
2886 dst_key_t *
dns_message_getsig0key(dns_message_t * msg)2887 dns_message_getsig0key(dns_message_t *msg) {
2888 
2889 	/*
2890 	 * Get the SIG(0) key for 'msg'
2891 	 */
2892 
2893 	REQUIRE(DNS_MESSAGE_VALID(msg));
2894 
2895 	return (msg->sig0key);
2896 }
2897 
2898 void
dns_message_takebuffer(dns_message_t * msg,isc_buffer_t ** buffer)2899 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
2900 	REQUIRE(DNS_MESSAGE_VALID(msg));
2901 	REQUIRE(buffer != NULL);
2902 	REQUIRE(ISC_BUFFER_VALID(*buffer));
2903 
2904 	ISC_LIST_APPEND(msg->cleanup, *buffer, link);
2905 	*buffer = NULL;
2906 }
2907 
2908 isc_result_t
dns_message_signer(dns_message_t * msg,dns_name_t * signer)2909 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
2910 	isc_result_t result = ISC_R_SUCCESS;
2911 	dns_rdata_t rdata = DNS_RDATA_INIT;
2912 
2913 	REQUIRE(DNS_MESSAGE_VALID(msg));
2914 	REQUIRE(signer != NULL);
2915 	REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
2916 
2917 	if (msg->tsig == NULL && msg->sig0 == NULL)
2918 		return (ISC_R_NOTFOUND);
2919 
2920 	if (msg->verify_attempted == 0)
2921 		return (DNS_R_NOTVERIFIEDYET);
2922 
2923 	if (!dns_name_hasbuffer(signer)) {
2924 		isc_buffer_t *dynbuf = NULL;
2925 		result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
2926 		if (result != ISC_R_SUCCESS)
2927 			return (result);
2928 		dns_name_setbuffer(signer, dynbuf);
2929 		dns_message_takebuffer(msg, &dynbuf);
2930 	}
2931 
2932 	if (msg->sig0 != NULL) {
2933 		dns_rdata_sig_t sig;
2934 
2935 		result = dns_rdataset_first(msg->sig0);
2936 		INSIST(result == ISC_R_SUCCESS);
2937 		dns_rdataset_current(msg->sig0, &rdata);
2938 
2939 		result = dns_rdata_tostruct(&rdata, &sig, NULL);
2940 		if (result != ISC_R_SUCCESS)
2941 			return (result);
2942 
2943 		if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
2944 			result = ISC_R_SUCCESS;
2945 		else
2946 			result = DNS_R_SIGINVALID;
2947 		dns_name_clone(&sig.signer, signer);
2948 		dns_rdata_freestruct(&sig);
2949 	} else {
2950 		dns_name_t *identity;
2951 		dns_rdata_any_tsig_t tsig;
2952 
2953 		result = dns_rdataset_first(msg->tsig);
2954 		INSIST(result == ISC_R_SUCCESS);
2955 		dns_rdataset_current(msg->tsig, &rdata);
2956 
2957 		result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2958 		INSIST(result == ISC_R_SUCCESS);
2959 		if (msg->tsigstatus != dns_rcode_noerror)
2960 			result = DNS_R_TSIGVERIFYFAILURE;
2961 		else if (tsig.error != dns_rcode_noerror)
2962 			result = DNS_R_TSIGERRORSET;
2963 		else
2964 			result = ISC_R_SUCCESS;
2965 		dns_rdata_freestruct(&tsig);
2966 
2967 		if (msg->tsigkey == NULL) {
2968 			/*
2969 			 * If msg->tsigstatus & tsig.error are both
2970 			 * dns_rcode_noerror, the message must have been
2971 			 * verified, which means msg->tsigkey will be
2972 			 * non-NULL.
2973 			 */
2974 			INSIST(result != ISC_R_SUCCESS);
2975 		} else {
2976 			identity = dns_tsigkey_identity(msg->tsigkey);
2977 			if (identity == NULL) {
2978 				if (result == ISC_R_SUCCESS)
2979 					result = DNS_R_NOIDENTITY;
2980 				identity = &msg->tsigkey->name;
2981 			}
2982 			dns_name_clone(identity, signer);
2983 		}
2984 	}
2985 
2986 	return (result);
2987 }
2988 
2989 void
dns_message_resetsig(dns_message_t * msg)2990 dns_message_resetsig(dns_message_t *msg) {
2991 	REQUIRE(DNS_MESSAGE_VALID(msg));
2992 	msg->verified_sig = 0;
2993 	msg->verify_attempted = 0;
2994 	msg->tsigstatus = dns_rcode_noerror;
2995 	msg->sig0status = dns_rcode_noerror;
2996 	msg->timeadjust = 0;
2997 	if (msg->tsigkey != NULL) {
2998 		dns_tsigkey_detach(&msg->tsigkey);
2999 		msg->tsigkey = NULL;
3000 	}
3001 }
3002 
3003 isc_result_t
dns_message_rechecksig(dns_message_t * msg,dns_view_t * view)3004 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
3005 	dns_message_resetsig(msg);
3006 	return (dns_message_checksig(msg, view));
3007 }
3008 
3009 #ifdef SKAN_MSG_DEBUG
3010 void
dns_message_dumpsig(dns_message_t * msg,char * txt1)3011 dns_message_dumpsig(dns_message_t *msg, char *txt1) {
3012 	dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
3013 	dns_rdata_any_tsig_t querytsig;
3014 	isc_result_t result;
3015 
3016 	if (msg->tsig != NULL) {
3017 		result = dns_rdataset_first(msg->tsig);
3018 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3019 		dns_rdataset_current(msg->tsig, &querytsigrdata);
3020 		result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
3021 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3022 		hexdump(txt1, "TSIG", querytsig.signature,
3023 			querytsig.siglen);
3024 	}
3025 
3026 	if (msg->querytsig != NULL) {
3027 		result = dns_rdataset_first(msg->querytsig);
3028 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3029 		dns_rdataset_current(msg->querytsig, &querytsigrdata);
3030 		result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
3031 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3032 		hexdump(txt1, "QUERYTSIG", querytsig.signature,
3033 			querytsig.siglen);
3034 	}
3035 }
3036 #endif
3037 
3038 isc_result_t
dns_message_checksig(dns_message_t * msg,dns_view_t * view)3039 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
3040 	isc_buffer_t b, msgb;
3041 
3042 	REQUIRE(DNS_MESSAGE_VALID(msg));
3043 
3044 	if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
3045 		return (ISC_R_SUCCESS);
3046 
3047 	INSIST(msg->saved.base != NULL);
3048 	isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
3049 	isc_buffer_add(&msgb, msg->saved.length);
3050 	if (msg->tsigkey != NULL || msg->tsig != NULL) {
3051 #ifdef SKAN_MSG_DEBUG
3052 		dns_message_dumpsig(msg, "dns_message_checksig#1");
3053 #endif
3054 		if (view != NULL)
3055 			return (dns_view_checksig(view, &msgb, msg));
3056 		else
3057 			return (dns_tsig_verify(&msgb, msg, NULL, NULL));
3058 	} else {
3059 		dns_rdata_t rdata = DNS_RDATA_INIT;
3060 		dns_rdata_sig_t sig;
3061 		dns_rdataset_t keyset;
3062 		isc_result_t result;
3063 
3064 		result = dns_rdataset_first(msg->sig0);
3065 		INSIST(result == ISC_R_SUCCESS);
3066 		dns_rdataset_current(msg->sig0, &rdata);
3067 
3068 		/*
3069 		 * This can occur when the message is a dynamic update, since
3070 		 * the rdata length checking is relaxed.  This should not
3071 		 * happen in a well-formed message, since the SIG(0) is only
3072 		 * looked for in the additional section, and the dynamic update
3073 		 * meta-records are in the prerequisite and update sections.
3074 		 */
3075 		if (rdata.length == 0)
3076 			return (ISC_R_UNEXPECTEDEND);
3077 
3078 		result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
3079 		if (result != ISC_R_SUCCESS)
3080 			return (result);
3081 
3082 		dns_rdataset_init(&keyset);
3083 		if (view == NULL)
3084 			return (DNS_R_KEYUNAUTHORIZED);
3085 		result = dns_view_simplefind(view, &sig.signer,
3086 					     dns_rdatatype_key /* SIG(0) */,
3087 					     0, 0, ISC_FALSE, &keyset, NULL);
3088 
3089 		if (result != ISC_R_SUCCESS) {
3090 			/* XXXBEW Should possibly create a fetch here */
3091 			result = DNS_R_KEYUNAUTHORIZED;
3092 			goto freesig;
3093 		} else if (keyset.trust < dns_trust_secure) {
3094 			/* XXXBEW Should call a validator here */
3095 			result = DNS_R_KEYUNAUTHORIZED;
3096 			goto freesig;
3097 		}
3098 		result = dns_rdataset_first(&keyset);
3099 		INSIST(result == ISC_R_SUCCESS);
3100 		for (;
3101 		     result == ISC_R_SUCCESS;
3102 		     result = dns_rdataset_next(&keyset))
3103 		{
3104 			dst_key_t *key = NULL;
3105 
3106 			dns_rdata_reset(&rdata);
3107 			dns_rdataset_current(&keyset, &rdata);
3108 			isc_buffer_init(&b, rdata.data, rdata.length);
3109 			isc_buffer_add(&b, rdata.length);
3110 
3111 			result = dst_key_fromdns(&sig.signer, rdata.rdclass,
3112 						 &b, view->mctx, &key);
3113 			if (result != ISC_R_SUCCESS)
3114 				continue;
3115 			if (dst_key_alg(key) != sig.algorithm ||
3116 			    dst_key_id(key) != sig.keyid ||
3117 			    !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
3118 			      dst_key_proto(key) == DNS_KEYPROTO_ANY))
3119 			{
3120 				dst_key_free(&key);
3121 				continue;
3122 			}
3123 			result = dns_dnssec_verifymessage(&msgb, msg, key);
3124 			dst_key_free(&key);
3125 			if (result == ISC_R_SUCCESS)
3126 				break;
3127 		}
3128 		if (result == ISC_R_NOMORE)
3129 			result = DNS_R_KEYUNAUTHORIZED;
3130 
3131  freesig:
3132 		if (dns_rdataset_isassociated(&keyset))
3133 			dns_rdataset_disassociate(&keyset);
3134 		dns_rdata_freestruct(&sig);
3135 		return (result);
3136 	}
3137 }
3138 
3139 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)3140 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
3141 			  const dns_master_style_t *style,
3142 			  dns_messagetextflag_t flags,
3143 			  isc_buffer_t *target) {
3144 	dns_name_t *name, empty_name;
3145 	dns_rdataset_t *rdataset;
3146 	isc_result_t result;
3147 	isc_boolean_t seensoa = ISC_FALSE;
3148 
3149 	REQUIRE(DNS_MESSAGE_VALID(msg));
3150 	REQUIRE(target != NULL);
3151 	REQUIRE(VALID_SECTION(section));
3152 
3153 	if (ISC_LIST_EMPTY(msg->sections[section]))
3154 		return (ISC_R_SUCCESS);
3155 
3156 	if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
3157 		ADD_STRING(target, ";; ");
3158 		if (msg->opcode != dns_opcode_update) {
3159 			ADD_STRING(target, sectiontext[section]);
3160 		} else {
3161 			ADD_STRING(target, updsectiontext[section]);
3162 		}
3163 		ADD_STRING(target, " SECTION:\n");
3164 	}
3165 
3166 	dns_name_init(&empty_name, NULL);
3167 	result = dns_message_firstname(msg, section);
3168 	if (result != ISC_R_SUCCESS) {
3169 		return (result);
3170 	}
3171 	do {
3172 		name = NULL;
3173 		dns_message_currentname(msg, section, &name);
3174 		for (rdataset = ISC_LIST_HEAD(name->list);
3175 		     rdataset != NULL;
3176 		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
3177 			if (section == DNS_SECTION_ANSWER &&
3178 			    rdataset->type == dns_rdatatype_soa) {
3179 				if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0)
3180 					continue;
3181 				if (seensoa &&
3182 				    (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0)
3183 					continue;
3184 				seensoa = ISC_TRUE;
3185 			}
3186 			if (section == DNS_SECTION_QUESTION) {
3187 				ADD_STRING(target, ";");
3188 				result = dns_master_questiontotext(name,
3189 								   rdataset,
3190 								   style,
3191 								   target);
3192 			} else {
3193 				result = dns_master_rdatasettotext(name,
3194 								   rdataset,
3195 								   style,
3196 								   target);
3197 			}
3198 			if (result != ISC_R_SUCCESS)
3199 				return (result);
3200 		}
3201 		result = dns_message_nextname(msg, section);
3202 	} while (result == ISC_R_SUCCESS);
3203 	if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3204 	    (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3205 		ADD_STRING(target, "\n");
3206 	if (result == ISC_R_NOMORE)
3207 		result = ISC_R_SUCCESS;
3208 	return (result);
3209 }
3210 
3211 static isc_result_t
render_ecs(isc_buffer_t * optbuf,isc_buffer_t * target)3212 render_ecs(isc_buffer_t *optbuf, isc_buffer_t *target) {
3213 	int i;
3214 	char addr[16], addr_text[64];
3215 	isc_uint16_t family;
3216 	isc_uint8_t addrlen, addrbytes, scopelen;
3217 
3218 	INSIST(isc_buffer_remaininglength(optbuf) >= 4);
3219 	family = isc_buffer_getuint16(optbuf);
3220 	addrlen = isc_buffer_getuint8(optbuf);
3221 	scopelen = isc_buffer_getuint8(optbuf);
3222 
3223 	addrbytes = (addrlen + 7) / 8;
3224 	INSIST(isc_buffer_remaininglength(optbuf) >= addrbytes);
3225 
3226 	memset(addr, 0, sizeof(addr));
3227 	for (i = 0; i < addrbytes; i ++)
3228 		addr[i] = isc_buffer_getuint8(optbuf);
3229 
3230 	if (family == 1)
3231 		inet_ntop(AF_INET, addr, addr_text, sizeof(addr_text));
3232 	else if (family == 2)
3233 		inet_ntop(AF_INET6, addr, addr_text, sizeof(addr_text));
3234 	else {
3235 		snprintf(addr_text, sizeof(addr_text),
3236 			 "Unsupported family %u", family);
3237 		ADD_STRING(target, addr_text);
3238 		return (ISC_R_SUCCESS);
3239 	}
3240 
3241 	ADD_STRING(target, addr_text);
3242 	snprintf(addr_text, sizeof(addr_text), "/%d/%d", addrlen, scopelen);
3243 	ADD_STRING(target, addr_text);
3244 	return (ISC_R_SUCCESS);
3245 }
3246 
3247 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)3248 dns_message_pseudosectiontotext(dns_message_t *msg,
3249 				dns_pseudosection_t section,
3250 				const dns_master_style_t *style,
3251 				dns_messagetextflag_t flags,
3252 				isc_buffer_t *target)
3253 {
3254 	dns_rdataset_t *ps = NULL;
3255 	dns_name_t *name = NULL;
3256 	isc_result_t result;
3257 	char buf[sizeof("1234567890")];
3258 	isc_uint32_t mbz;
3259 	dns_rdata_t rdata;
3260 	isc_buffer_t optbuf;
3261 	isc_uint16_t optcode, optlen;
3262 	unsigned char *optdata;
3263 
3264 	REQUIRE(DNS_MESSAGE_VALID(msg));
3265 	REQUIRE(target != NULL);
3266 	REQUIRE(VALID_PSEUDOSECTION(section));
3267 
3268 	switch (section) {
3269 	case DNS_PSEUDOSECTION_OPT:
3270 		ps = dns_message_getopt(msg);
3271 		if (ps == NULL)
3272 			return (ISC_R_SUCCESS);
3273 		if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3274 			ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
3275 		ADD_STRING(target, "; EDNS: version: ");
3276 		snprintf(buf, sizeof(buf), "%u",
3277 			 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
3278 		ADD_STRING(target, buf);
3279 		ADD_STRING(target, ", flags:");
3280 		if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
3281 			ADD_STRING(target, " do");
3282 		mbz = ps->ttl & 0xffff;
3283 		mbz &= ~DNS_MESSAGEEXTFLAG_DO;		/* Known Flags. */
3284 		if (mbz != 0) {
3285 			ADD_STRING(target, "; MBZ: ");
3286 			snprintf(buf, sizeof(buf), "%.4x ", mbz);
3287 			ADD_STRING(target, buf);
3288 			ADD_STRING(target, ", udp: ");
3289 		} else
3290 			ADD_STRING(target, "; udp: ");
3291 		snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
3292 		ADD_STRING(target, buf);
3293 
3294 		result = dns_rdataset_first(ps);
3295 		if (result != ISC_R_SUCCESS)
3296 			return (ISC_R_SUCCESS);
3297 
3298 		/* Print EDNS info, if any */
3299 		dns_rdata_init(&rdata);
3300 		dns_rdataset_current(ps, &rdata);
3301 
3302 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
3303 		isc_buffer_add(&optbuf, rdata.length);
3304 		while (isc_buffer_remaininglength(&optbuf) != 0) {
3305 			INSIST(isc_buffer_remaininglength(&optbuf) >= 4U);
3306 			optcode = isc_buffer_getuint16(&optbuf);
3307 			optlen = isc_buffer_getuint16(&optbuf);
3308 			INSIST(isc_buffer_remaininglength(&optbuf) >= optlen);
3309 
3310 			if (optcode == DNS_OPT_NSID) {
3311 				ADD_STRING(target, "; NSID");
3312 			} else if (optcode == DNS_OPT_SIT) {
3313 				ADD_STRING(target, "; SIT");
3314 			} else if (optcode == DNS_OPT_CLIENT_SUBNET) {
3315 				ADD_STRING(target, "; CLIENT-SUBNET: ");
3316 				render_ecs(&optbuf, target);
3317 				ADD_STRING(target, "\n");
3318 				continue;
3319 			} else if (optcode == DNS_OPT_EXPIRE) {
3320 				if (optlen == 4) {
3321 					isc_uint32_t secs;
3322 					secs = isc_buffer_getuint32(&optbuf);
3323 					ADD_STRING(target, "; EXPIRE: ");
3324 					snprintf(buf, sizeof(buf), "%u", secs);
3325 					ADD_STRING(target, buf);
3326 					ADD_STRING(target, " (");
3327 					dns_ttl_totext(secs, ISC_TRUE, target);
3328 					ADD_STRING(target, ")\n");
3329 					continue;
3330 				}
3331 				ADD_STRING(target, "; EXPIRE");
3332 			} else {
3333 				ADD_STRING(target, "; OPT=");
3334 				snprintf(buf, sizeof(buf), "%u", optcode);
3335 				ADD_STRING(target, buf);
3336 			}
3337 
3338 			if (optlen != 0) {
3339 				int i;
3340 				ADD_STRING(target, ": ");
3341 
3342 				optdata = isc_buffer_current(&optbuf);
3343 				for (i = 0; i < optlen; i++) {
3344 					const char *sep;
3345 					switch (optcode) {
3346 					case DNS_OPT_SIT:
3347 						sep = "";
3348 						break;
3349 					default:
3350 						sep = " ";
3351 						break;
3352 					}
3353 					snprintf(buf, sizeof(buf), "%02x%s",
3354 						 optdata[i], sep);
3355 					ADD_STRING(target, buf);
3356 				}
3357 
3358 				isc_buffer_forward(&optbuf, optlen);
3359 
3360 				if (optcode == DNS_OPT_SIT) {
3361 					if (msg->sitok)
3362 						ADD_STRING(target, " (good)");
3363 					if (msg->sitbad)
3364 						ADD_STRING(target, " (bad)");
3365 					ADD_STRING(target, "\n");
3366 					continue;
3367 				}
3368 
3369 				/*
3370 				 * For non-SIT options, add a printable
3371 				 * version
3372 				 */
3373 				ADD_STRING(target, "(\"");
3374 				if (isc_buffer_availablelength(target) < optlen)
3375 					return (ISC_R_NOSPACE);
3376 				for (i = 0; i < optlen; i++) {
3377 					if (isprint(optdata[i]))
3378 						isc_buffer_putmem(target,
3379 								  &optdata[i],
3380 								  1);
3381 					else
3382 						isc_buffer_putstr(target, ".");
3383 				}
3384 				ADD_STRING(target, "\")");
3385 			}
3386 			ADD_STRING(target, "\n");
3387 		}
3388 		return (ISC_R_SUCCESS);
3389 	case DNS_PSEUDOSECTION_TSIG:
3390 		ps = dns_message_gettsig(msg, &name);
3391 		if (ps == NULL)
3392 			return (ISC_R_SUCCESS);
3393 		if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3394 			ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
3395 		result = dns_master_rdatasettotext(name, ps, style, target);
3396 		if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3397 		    (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3398 			ADD_STRING(target, "\n");
3399 		return (result);
3400 	case DNS_PSEUDOSECTION_SIG0:
3401 		ps = dns_message_getsig0(msg, &name);
3402 		if (ps == NULL)
3403 			return (ISC_R_SUCCESS);
3404 		if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3405 			ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
3406 		result = dns_master_rdatasettotext(name, ps, style, target);
3407 		if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
3408 		    (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
3409 			ADD_STRING(target, "\n");
3410 		return (result);
3411 	}
3412 	return (ISC_R_UNEXPECTED);
3413 }
3414 
3415 isc_result_t
dns_message_totext(dns_message_t * msg,const dns_master_style_t * style,dns_messagetextflag_t flags,isc_buffer_t * target)3416 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
3417 		   dns_messagetextflag_t flags, isc_buffer_t *target) {
3418 	char buf[sizeof("1234567890")];
3419 	isc_result_t result;
3420 
3421 	REQUIRE(DNS_MESSAGE_VALID(msg));
3422 	REQUIRE(target != NULL);
3423 
3424 	if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
3425 		ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
3426 		ADD_STRING(target, opcodetext[msg->opcode]);
3427 		ADD_STRING(target, ", status: ");
3428 		if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
3429 			ADD_STRING(target, rcodetext[msg->rcode]);
3430 		} else {
3431 			snprintf(buf, sizeof(buf), "%4u", msg->rcode);
3432 			ADD_STRING(target, buf);
3433 		}
3434 		ADD_STRING(target, ", id: ");
3435 		snprintf(buf, sizeof(buf), "%6u", msg->id);
3436 		ADD_STRING(target, buf);
3437 		ADD_STRING(target, "\n;; flags:");
3438 		if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
3439 			ADD_STRING(target, " qr");
3440 		if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
3441 			ADD_STRING(target, " aa");
3442 		if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
3443 			ADD_STRING(target, " tc");
3444 		if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
3445 			ADD_STRING(target, " rd");
3446 		if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
3447 			ADD_STRING(target, " ra");
3448 		if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
3449 			ADD_STRING(target, " ad");
3450 		if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
3451 			ADD_STRING(target, " cd");
3452 		/*
3453 		 * The final unnamed flag must be zero.
3454 		 */
3455 		if ((msg->flags & 0x0040U) != 0)
3456 			ADD_STRING(target, "; MBZ: 0x4");
3457 		if (msg->opcode != dns_opcode_update) {
3458 			ADD_STRING(target, "; QUESTION: ");
3459 		} else {
3460 			ADD_STRING(target, "; ZONE: ");
3461 		}
3462 		snprintf(buf, sizeof(buf), "%1u",
3463 			 msg->counts[DNS_SECTION_QUESTION]);
3464 		ADD_STRING(target, buf);
3465 		if (msg->opcode != dns_opcode_update) {
3466 			ADD_STRING(target, ", ANSWER: ");
3467 		} else {
3468 			ADD_STRING(target, ", PREREQ: ");
3469 		}
3470 		snprintf(buf, sizeof(buf), "%1u",
3471 			 msg->counts[DNS_SECTION_ANSWER]);
3472 		ADD_STRING(target, buf);
3473 		if (msg->opcode != dns_opcode_update) {
3474 			ADD_STRING(target, ", AUTHORITY: ");
3475 		} else {
3476 			ADD_STRING(target, ", UPDATE: ");
3477 		}
3478 		snprintf(buf, sizeof(buf), "%1u",
3479 			msg->counts[DNS_SECTION_AUTHORITY]);
3480 		ADD_STRING(target, buf);
3481 		ADD_STRING(target, ", ADDITIONAL: ");
3482 		snprintf(buf, sizeof(buf), "%1u",
3483 			msg->counts[DNS_SECTION_ADDITIONAL]);
3484 		ADD_STRING(target, buf);
3485 		ADD_STRING(target, "\n");
3486 	}
3487 	result = dns_message_pseudosectiontotext(msg,
3488 						 DNS_PSEUDOSECTION_OPT,
3489 						 style, flags, target);
3490 	if (result != ISC_R_SUCCESS)
3491 		return (result);
3492 
3493 	result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
3494 					   style, flags, target);
3495 	if (result != ISC_R_SUCCESS)
3496 		return (result);
3497 	result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
3498 					   style, flags, target);
3499 	if (result != ISC_R_SUCCESS)
3500 		return (result);
3501 	result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
3502 					   style, flags, target);
3503 	if (result != ISC_R_SUCCESS)
3504 		return (result);
3505 	result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
3506 					   style, flags, target);
3507 	if (result != ISC_R_SUCCESS)
3508 		return (result);
3509 
3510 	result = dns_message_pseudosectiontotext(msg,
3511 						 DNS_PSEUDOSECTION_TSIG,
3512 						 style, flags, target);
3513 	if (result != ISC_R_SUCCESS)
3514 		return (result);
3515 
3516 	result = dns_message_pseudosectiontotext(msg,
3517 						 DNS_PSEUDOSECTION_SIG0,
3518 						 style, flags, target);
3519 	if (result != ISC_R_SUCCESS)
3520 		return (result);
3521 
3522 	return (ISC_R_SUCCESS);
3523 }
3524 
3525 isc_region_t *
dns_message_getrawmessage(dns_message_t * msg)3526 dns_message_getrawmessage(dns_message_t *msg) {
3527 	REQUIRE(DNS_MESSAGE_VALID(msg));
3528 	return (&msg->saved);
3529 }
3530 
3531 void
dns_message_setsortorder(dns_message_t * msg,dns_rdatasetorderfunc_t order,const void * order_arg)3532 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
3533 			 const void *order_arg)
3534 {
3535 	REQUIRE(DNS_MESSAGE_VALID(msg));
3536 	msg->order = order;
3537 	msg->order_arg = order_arg;
3538 }
3539 
3540 void
dns_message_settimeadjust(dns_message_t * msg,int timeadjust)3541 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
3542 	REQUIRE(DNS_MESSAGE_VALID(msg));
3543 	msg->timeadjust = timeadjust;
3544 }
3545 
3546 int
dns_message_gettimeadjust(dns_message_t * msg)3547 dns_message_gettimeadjust(dns_message_t *msg) {
3548 	REQUIRE(DNS_MESSAGE_VALID(msg));
3549 	return (msg->timeadjust);
3550 }
3551 
3552 isc_result_t
dns_opcode_totext(dns_opcode_t opcode,isc_buffer_t * target)3553 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
3554 
3555 	REQUIRE(opcode < 16);
3556 
3557 	if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode]))
3558 		return (ISC_R_NOSPACE);
3559 	isc_buffer_putstr(target, opcodetext[opcode]);
3560 	return (ISC_R_SUCCESS);
3561 }
3562 
3563 void
dns_message_logpacket(dns_message_t * message,const char * description,isc_logcategory_t * category,isc_logmodule_t * module,int level,isc_mem_t * mctx)3564 dns_message_logpacket(dns_message_t *message, const char *description,
3565 		      isc_logcategory_t *category, isc_logmodule_t *module,
3566 		      int level, isc_mem_t *mctx)
3567 {
3568 	dns_message_logfmtpacket(message, description, category, module,
3569 				 &dns_master_style_debug, level, mctx);
3570 }
3571 
3572 void
dns_message_logfmtpacket(dns_message_t * message,const char * description,isc_logcategory_t * category,isc_logmodule_t * module,const dns_master_style_t * style,int level,isc_mem_t * mctx)3573 dns_message_logfmtpacket(dns_message_t *message, const char *description,
3574 			 isc_logcategory_t *category, isc_logmodule_t *module,
3575 			 const dns_master_style_t *style, int level,
3576 			 isc_mem_t *mctx)
3577 {
3578 	isc_buffer_t buffer;
3579 	char *buf = NULL;
3580 	int len = 1024;
3581 	isc_result_t result;
3582 
3583 	if (! isc_log_wouldlog(dns_lctx, level))
3584 		return;
3585 
3586 	/*
3587 	 * Note that these are multiline debug messages.  We want a newline
3588 	 * to appear in the log after each message.
3589 	 */
3590 
3591 	do {
3592 		buf = isc_mem_get(mctx, len);
3593 		if (buf == NULL)
3594 			break;
3595 		isc_buffer_init(&buffer, buf, len);
3596 		result = dns_message_totext(message, style, 0, &buffer);
3597 		if (result == ISC_R_NOSPACE) {
3598 			isc_mem_put(mctx, buf, len);
3599 			len += 1024;
3600 		} else if (result == ISC_R_SUCCESS)
3601 			isc_log_write(dns_lctx, category, module, level,
3602 				      "%s%.*s", description,
3603 				      (int)isc_buffer_usedlength(&buffer),
3604 				      buf);
3605 	} while (result == ISC_R_NOSPACE);
3606 
3607 	if (buf != NULL)
3608 		isc_mem_put(mctx, buf, len);
3609 }
3610 
3611 isc_result_t
dns_message_buildopt(dns_message_t * message,dns_rdataset_t ** rdatasetp,unsigned int version,isc_uint16_t udpsize,unsigned int flags,dns_ednsopt_t * ednsopts,size_t count)3612 dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
3613 		     unsigned int version, isc_uint16_t udpsize,
3614 		     unsigned int flags, dns_ednsopt_t *ednsopts, size_t count)
3615 {
3616 	dns_rdataset_t *rdataset = NULL;
3617 	dns_rdatalist_t *rdatalist = NULL;
3618 	dns_rdata_t *rdata = NULL;
3619 	isc_result_t result;
3620 	unsigned int len = 0, i;
3621 
3622 	REQUIRE(DNS_MESSAGE_VALID(message));
3623 	REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
3624 
3625 	result = dns_message_gettemprdatalist(message, &rdatalist);
3626 	if (result != ISC_R_SUCCESS)
3627 		return (result);
3628 	result = dns_message_gettemprdata(message, &rdata);
3629 	if (result != ISC_R_SUCCESS)
3630 		goto cleanup;
3631 	result = dns_message_gettemprdataset(message, &rdataset);
3632 	if (result != ISC_R_SUCCESS)
3633 		goto cleanup;
3634 
3635 	rdatalist->type = dns_rdatatype_opt;
3636 	rdatalist->covers = 0;
3637 
3638 	/*
3639 	 * Set Maximum UDP buffer size.
3640 	 */
3641 	rdatalist->rdclass = udpsize;
3642 
3643 	/*
3644 	 * Set EXTENDED-RCODE and Z to 0.
3645 	 */
3646 	rdatalist->ttl = (version << 16);
3647 	rdatalist->ttl |= (flags & 0xffff);
3648 
3649 	/*
3650 	 * Set EDNS options if applicable
3651 	 */
3652 	if (count != 0U) {
3653 		isc_buffer_t *buf = NULL;
3654 		for (i = 0; i < count; i++)
3655 			len += ednsopts[i].length + 4;
3656 
3657 		if (len > 0xffffU) {
3658 			result = ISC_R_NOSPACE;
3659 			goto cleanup;
3660 		}
3661 
3662 		result = isc_buffer_allocate(message->mctx, &buf, len);
3663 		if (result != ISC_R_SUCCESS)
3664 			goto cleanup;
3665 
3666 		for (i = 0; i < count; i++)  {
3667 			isc_buffer_putuint16(buf, ednsopts[i].code);
3668 			isc_buffer_putuint16(buf, ednsopts[i].length);
3669 			isc_buffer_putmem(buf, ednsopts[i].value,
3670 					  ednsopts[i].length);
3671 		}
3672 		rdata->data = isc_buffer_base(buf);
3673 		rdata->length = len;
3674 		dns_message_takebuffer(message, &buf);
3675 	} else {
3676 		rdata->data = NULL;
3677 		rdata->length = 0;
3678 	}
3679 
3680 	rdata->rdclass = rdatalist->rdclass;
3681 	rdata->type = rdatalist->type;
3682 	rdata->flags = 0;
3683 
3684 	ISC_LIST_INIT(rdatalist->rdata);
3685 	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
3686 	result = dns_rdatalist_tordataset(rdatalist, rdataset);
3687 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
3688 
3689 	*rdatasetp = rdataset;
3690 	return (ISC_R_SUCCESS);
3691 
3692  cleanup:
3693 	if (rdata != NULL)
3694 		dns_message_puttemprdata(message, &rdata);
3695 	if (rdataset != NULL)
3696 		dns_message_puttemprdataset(message, &rdataset);
3697 	if (rdatalist != NULL)
3698 		dns_message_puttemprdatalist(message, &rdatalist);
3699 	return (result);
3700 }
3701