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