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