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