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