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