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