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