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