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