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