message.c 107 KB
Newer Older
Michael Graff's avatar
Michael Graff committed
1
/*
2
 * Copyright (C) 1999-2016  Internet Systems Consortium, Inc. ("ISC")
3
 *
4
5
6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
Michael Graff's avatar
Michael Graff committed
7
8
 */

9
/*! \file */
David Lawrence's avatar
David Lawrence committed
10

Michael Graff's avatar
Michael Graff committed
11
12
13
14
15
/***
 *** Imports
 ***/

#include <config.h>
16
#include <ctype.h>
Michael Graff's avatar
Michael Graff committed
17

Mark Andrews's avatar
Mark Andrews committed
18
#include <isc/buffer.h>
19
#include <isc/mem.h>
Mark Andrews's avatar
Mark Andrews committed
20
#include <isc/print.h>
21
#include <isc/string.h>		/* Required for HP/UX (and others?) */
Bob Halley's avatar
Bob Halley committed
22
#include <isc/util.h>
Michael Graff's avatar
Michael Graff committed
23

24
25
#include <dns/dnssec.h>
#include <dns/keyvalues.h>
26
#include <dns/log.h>
27
#include <dns/masterdump.h>
Michael Graff's avatar
Michael Graff committed
28
#include <dns/message.h>
29
#include <dns/opcode.h>
30
#include <dns/rcode.h>
Michael Graff's avatar
Michael Graff committed
31
32
#include <dns/rdata.h>
#include <dns/rdatalist.h>
33
#include <dns/rdataset.h>
34
#include <dns/rdatastruct.h>
35
#include <dns/result.h>
36
#include <dns/tsig.h>
Evan Hunt's avatar
Evan Hunt committed
37
#include <dns/ttl.h>
Brian Wellington's avatar
Brian Wellington committed
38
#include <dns/view.h>
Michael Graff's avatar
Michael Graff committed
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#ifdef SKAN_MSG_DEBUG
static void
hexdump(const char *msg, const char *msg2, void *base, size_t len) {
	unsigned char *p;
	unsigned int cnt;

	p = base;
	cnt = 0;

	printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);

	while (cnt < len) {
		if (cnt % 16 == 0)
			printf("%p: ", p);
		else if (cnt % 8 == 0)
			printf(" |");
		printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
		p++;
		cnt++;

		if (cnt % 16 == 0)
			printf("\n");
	}

	if (cnt % 16 != 0)
		printf("\n");
}
#endif

69
#define DNS_MESSAGE_OPCODE_MASK		0x7800U
Bob Halley's avatar
EDNS0    
Bob Halley committed
70
#define DNS_MESSAGE_OPCODE_SHIFT	11
Michael Graff's avatar
Michael Graff committed
71
72
#define DNS_MESSAGE_RCODE_MASK		0x000fU
#define DNS_MESSAGE_FLAG_MASK		0x8ff0U
Bob Halley's avatar
EDNS0    
Bob Halley committed
73
74
75
76
#define DNS_MESSAGE_EDNSRCODE_MASK	0xff000000U
#define DNS_MESSAGE_EDNSRCODE_SHIFT	24
#define DNS_MESSAGE_EDNSVERSION_MASK	0x00ff0000U
#define DNS_MESSAGE_EDNSVERSION_SHIFT	16
Michael Graff's avatar
Michael Graff committed
77
78
79
80
81

#define VALID_NAMED_SECTION(s)  (((s) > DNS_SECTION_ANY) \
				 && ((s) < DNS_SECTION_MAX))
#define VALID_SECTION(s)	(((s) >= DNS_SECTION_ANY) \
				 && ((s) < DNS_SECTION_MAX))
Brian Wellington's avatar
Brian Wellington committed
82
#define ADD_STRING(b, s)	{if (strlen(s) >= \
83
84
85
				   isc_buffer_availablelength(b)) { \
				       result = ISC_R_NOSPACE; \
				       goto cleanup; \
86
				 } else \
Brian Wellington's avatar
Brian Wellington committed
87
				       isc_buffer_putstr(b, s);}
88
89
#define VALID_PSEUDOSECTION(s)	(((s) >= DNS_PSEUDOSECTION_ANY) \
				 && ((s) < DNS_PSEUDOSECTION_MAX))
Michael Graff's avatar
Michael Graff committed
90

91
92
#define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)

93
/*%
Michael Graff's avatar
Michael Graff committed
94
95
 * This is the size of each individual scratchpad buffer, and the numbers
 * of various block allocations used within the server.
Michael Graff's avatar
Michael Graff committed
96
 * XXXMLG These should come from a config setting.
Michael Graff's avatar
Michael Graff committed
97
 */
Michael Graff's avatar
Michael Graff committed
98
#define SCRATCHPAD_SIZE		512
99
#define NAME_COUNT		  8
100
#define OFFSET_COUNT		  4
101
102
103
#define RDATA_COUNT		  8
#define RDATALIST_COUNT		  8
#define RDATASET_COUNT		 RDATALIST_COUNT
Michael Graff's avatar
Michael Graff committed
104

105
/*%
106
107
108
 * Text representation of the different items, for message_totext
 * functions.
 */
David Lawrence's avatar
David Lawrence committed
109
static const char *sectiontext[] = {
110
111
112
113
114
115
	"QUESTION",
	"ANSWER",
	"AUTHORITY",
	"ADDITIONAL"
};

116
117
118
119
120
121
122
static const char *updsectiontext[] = {
	"ZONE",
	"PREREQUISITE",
	"UPDATE",
	"ADDITIONAL"
};

David Lawrence's avatar
David Lawrence committed
123
static const char *opcodetext[] = {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
	"QUERY",
	"IQUERY",
	"STATUS",
	"RESERVED3",
	"NOTIFY",
	"UPDATE",
	"RESERVED6",
	"RESERVED7",
	"RESERVED8",
	"RESERVED9",
	"RESERVED10",
	"RESERVED11",
	"RESERVED12",
	"RESERVED13",
	"RESERVED14",
	"RESERVED15"
};

142
/*%
Michael Graff's avatar
Michael Graff committed
143
144
 * "helper" type, which consists of a block of some type, and is linkable.
 * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
Francis Dupont's avatar
Francis Dupont committed
145
 * size, or the allocated elements will not be aligned correctly.
Michael Graff's avatar
Michael Graff committed
146
147
 */
struct dns_msgblock {
Michael Graff's avatar
Michael Graff committed
148
	unsigned int			count;
Michael Graff's avatar
Michael Graff committed
149
150
151
	unsigned int			remaining;
	ISC_LINK(dns_msgblock_t)	link;
}; /* dynamically sized */
Michael Graff's avatar
Michael Graff committed
152

Michael Graff's avatar
Michael Graff committed
153
154
static inline dns_msgblock_t *
msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
155

Michael Graff's avatar
Michael Graff committed
156
#define msgblock_get(block, type) \
Michael Graff's avatar
Michael Graff committed
157
	((type *)msgblock_internalget(block, sizeof(type)))
Michael Graff's avatar
Michael Graff committed
158
159

static inline void *
Michael Graff's avatar
Michael Graff committed
160
161
162
msgblock_internalget(dns_msgblock_t *, unsigned int);

static inline void
Michael Graff's avatar
Michael Graff committed
163
msgblock_reset(dns_msgblock_t *);
Michael Graff's avatar
Michael Graff committed
164

Michael Graff's avatar
Michael Graff committed
165
166
static inline void
msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
Michael Graff's avatar
Michael Graff committed
167

168
169
170
171
172
173
static void
logfmtpacket(dns_message_t *message, const char *description,
	     isc_sockaddr_t *address, isc_logcategory_t *category,
	     isc_logmodule_t *module, const dns_master_style_t *style,
	     int level, isc_mem_t *mctx);

Michael Graff's avatar
Michael Graff committed
174
175
176
177
178
/*
 * Allocate a new dns_msgblock_t, and return a pointer to it.  If no memory
 * is free, return NULL.
 */
static inline dns_msgblock_t *
Michael Graff's avatar
Michael Graff committed
179
180
msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
		  unsigned int count)
Michael Graff's avatar
Michael Graff committed
181
182
183
184
185
186
187
188
{
	dns_msgblock_t *block;
	unsigned int length;

	length = sizeof(dns_msgblock_t) + (sizeof_type * count);

	block = isc_mem_get(mctx, length);
	if (block == NULL)
Michael Graff's avatar
Michael Graff committed
189
		return (NULL);
Michael Graff's avatar
Michael Graff committed
190

Michael Graff's avatar
Michael Graff committed
191
	block->count = count;
Michael Graff's avatar
Michael Graff committed
192
193
194
195
196
197
198
199
200
201
202
203
	block->remaining = count;

	ISC_LINK_INIT(block, link);

	return (block);
}

/*
 * Return an element from the msgblock.  If no more are available, return
 * NULL.
 */
static inline void *
204
msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
Michael Graff's avatar
Michael Graff committed
205
206
	void *ptr;

Andreas Gustafsson's avatar
Andreas Gustafsson committed
207
	if (block == NULL || block->remaining == 0)
Michael Graff's avatar
Michael Graff committed
208
209
210
211
212
213
214
215
216
217
218
		return (NULL);

	block->remaining--;

	ptr = (((unsigned char *)block)
	       + sizeof(dns_msgblock_t)
	       + (sizeof_type * block->remaining));

	return (ptr);
}

Michael Graff's avatar
Michael Graff committed
219
static inline void
220
msgblock_reset(dns_msgblock_t *block) {
Michael Graff's avatar
Michael Graff committed
221
	block->remaining = block->count;
Michael Graff's avatar
Michael Graff committed
222
223
}

Michael Graff's avatar
Michael Graff committed
224
225
226
227
/*
 * Release memory associated with a message block.
 */
static inline void
228
msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
Michael Graff's avatar
Michael Graff committed
229
{
Michael Graff's avatar
Michael Graff committed
230
231
232
233
234
	unsigned int length;

	length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);

	isc_mem_put(mctx, block, length);
Michael Graff's avatar
Michael Graff committed
235
}
Michael Graff's avatar
Michael Graff committed
236

Michael Graff's avatar
Michael Graff committed
237
238
239
240
241
/*
 * Allocate a new dynamic buffer, and attach it to this message as the
 * "current" buffer.  (which is always the last on the list, for our
 * uses)
 */
242
static inline isc_result_t
243
newbuffer(dns_message_t *msg, unsigned int size) {
Michael Graff's avatar
Michael Graff committed
244
	isc_result_t result;
245
	isc_buffer_t *dynbuf;
Michael Graff's avatar
Michael Graff committed
246
247

	dynbuf = NULL;
248
	result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
Michael Graff's avatar
Michael Graff committed
249
	if (result != ISC_R_SUCCESS)
250
		return (ISC_R_NOMEMORY);
Michael Graff's avatar
Michael Graff committed
251
252

	ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
253
	return (ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
254
255
256
}

static inline isc_buffer_t *
257
currentbuffer(dns_message_t *msg) {
258
	isc_buffer_t *dynbuf;
Michael Graff's avatar
Michael Graff committed
259
260

	dynbuf = ISC_LIST_TAIL(msg->scratchpad);
Michael Graff's avatar
Michael Graff committed
261
	INSIST(dynbuf != NULL);
Michael Graff's avatar
Michael Graff committed
262

263
	return (dynbuf);
Michael Graff's avatar
Michael Graff committed
264
265
266
}

static inline void
267
releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
268
	ISC_LIST_PREPEND(msg->freerdata, rdata, link);
Michael Graff's avatar
Michael Graff committed
269
270
271
}

static inline dns_rdata_t *
272
newrdata(dns_message_t *msg) {
Michael Graff's avatar
Michael Graff committed
273
274
275
	dns_msgblock_t *msgblock;
	dns_rdata_t *rdata;

276
277
278
	rdata = ISC_LIST_HEAD(msg->freerdata);
	if (rdata != NULL) {
		ISC_LIST_UNLINK(msg->freerdata, rdata, link);
Michael Graff's avatar
Michael Graff committed
279
280
281
		return (rdata);
	}

Michael Graff's avatar
Michael Graff committed
282
	msgblock = ISC_LIST_TAIL(msg->rdatas);
Michael Graff's avatar
Michael Graff committed
283
284
285
286
287
288
289
290
291
292
293
294
	rdata = msgblock_get(msgblock, dns_rdata_t);
	if (rdata == NULL) {
		msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
					     RDATA_COUNT);
		if (msgblock == NULL)
			return (NULL);

		ISC_LIST_APPEND(msg->rdatas, msgblock, link);

		rdata = msgblock_get(msgblock, dns_rdata_t);
	}

295
	dns_rdata_init(rdata);
Michael Graff's avatar
Michael Graff committed
296
297
298
299
	return (rdata);
}

static inline void
300
releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
301
	ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
Michael Graff's avatar
Michael Graff committed
302
303
304
}

static inline dns_rdatalist_t *
305
newrdatalist(dns_message_t *msg) {
Michael Graff's avatar
Michael Graff committed
306
307
308
	dns_msgblock_t *msgblock;
	dns_rdatalist_t *rdatalist;

309
310
311
	rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
	if (rdatalist != NULL) {
		ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
312
		goto out;
Michael Graff's avatar
Michael Graff committed
313
314
	}

Michael Graff's avatar
Michael Graff committed
315
	msgblock = ISC_LIST_TAIL(msg->rdatalists);
Michael Graff's avatar
Michael Graff committed
316
317
318
319
320
321
322
323
324
325
326
327
	rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
	if (rdatalist == NULL) {
		msgblock = msgblock_allocate(msg->mctx,
					     sizeof(dns_rdatalist_t),
					     RDATALIST_COUNT);
		if (msgblock == NULL)
			return (NULL);

		ISC_LIST_APPEND(msg->rdatalists, msgblock, link);

		rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
	}
328
 out:
329
330
	if (rdatalist != NULL)
		dns_rdatalist_init(rdatalist);
Michael Graff's avatar
Michael Graff committed
331
332
333
334

	return (rdatalist);
}

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
static inline dns_offsets_t *
newoffsets(dns_message_t *msg) {
	dns_msgblock_t *msgblock;
	dns_offsets_t *offsets;

	msgblock = ISC_LIST_TAIL(msg->offsets);
	offsets = msgblock_get(msgblock, dns_offsets_t);
	if (offsets == NULL) {
		msgblock = msgblock_allocate(msg->mctx,
					     sizeof(dns_offsets_t),
					     OFFSET_COUNT);
		if (msgblock == NULL)
			return (NULL);

		ISC_LIST_APPEND(msg->offsets, msgblock, link);

		offsets = msgblock_get(msgblock, dns_offsets_t);
	}

	return (offsets);
}

Michael Graff's avatar
Michael Graff committed
357
static inline void
358
msginitheader(dns_message_t *m) {
Michael Graff's avatar
Michael Graff committed
359
360
361
362
	m->id = 0;
	m->flags = 0;
	m->rcode = 0;
	m->opcode = 0;
Michael Graff's avatar
Michael Graff committed
363
	m->rdclass = 0;
364
}
Michael Graff's avatar
Michael Graff committed
365

366
static inline void
367
msginitprivate(dns_message_t *m) {
368
369
370
	unsigned int i;

	for (i = 0; i < DNS_SECTION_MAX; i++) {
Michael Graff's avatar
Michael Graff committed
371
		m->cursors[i] = NULL;
Michael Graff's avatar
Michael Graff committed
372
		m->counts[i] = 0;
Michael Graff's avatar
Michael Graff committed
373
	}
374
	m->opt = NULL;
375
	m->sig0 = NULL;
376
	m->sig0name = NULL;
377
	m->tsig = NULL;
378
	m->tsigname = NULL;
Michael Graff's avatar
Michael Graff committed
379
	m->state = DNS_SECTION_ANY;  /* indicate nothing parsed or rendered */
380
	m->opt_reserved = 0;
381
	m->sig_reserved = 0;
Michael Graff's avatar
Michael Graff committed
382
	m->reserved = 0;
383
	m->buffer = NULL;
Michael Graff's avatar
Michael Graff committed
384
385
}

386
static inline void
387
msginittsig(dns_message_t *m) {
388
389
	m->tsigstatus = dns_rcode_noerror;
	m->querytsigstatus = dns_rcode_noerror;
390
	m->tsigkey = NULL;
391
	m->tsigctx = NULL;
392
393
394
	m->sigstart = -1;
	m->sig0key = NULL;
	m->sig0status = dns_rcode_noerror;
395
	m->timeadjust = 0;
396
397
}

Michael Graff's avatar
Michael Graff committed
398
/*
399
400
 * Init elements to default state.  Used both when allocating a new element
 * and when resetting one.
Michael Graff's avatar
Michael Graff committed
401
 */
402
static inline void
403
msginit(dns_message_t *m) {
404
405
	msginitheader(m);
	msginitprivate(m);
406
	msginittsig(m);
Bob Halley's avatar
Bob Halley committed
407
408
	m->header_ok = 0;
	m->question_ok = 0;
409
	m->tcp_continuation = 0;
410
411
	m->verified_sig = 0;
	m->verify_attempted = 0;
412
413
	m->order = NULL;
	m->order_arg = NULL;
414
415
416
417
418
419
	m->query.base = NULL;
	m->query.length = 0;
	m->free_query = 0;
	m->saved.base = NULL;
	m->saved.length = 0;
	m->free_saved = 0;
420
421
	m->cc_ok = 0;
	m->cc_bad = 0;
422
423
	m->tkey = 0;
	m->rdclass_set = 0;
424
	m->querytsig = NULL;
425
426
427
428
}

static inline void
msgresetnames(dns_message_t *msg, unsigned int first_section) {
Michael Graff's avatar
Michael Graff committed
429
	unsigned int i;
430
431
	dns_name_t *name, *next_name;
	dns_rdataset_t *rds, *next_rds;
Michael Graff's avatar
Michael Graff committed
432
433
434
435

	/*
	 * Clean up name lists by calling the rdataset disassociate function.
	 */
436
	for (i = first_section; i < DNS_SECTION_MAX; i++) {
Michael Graff's avatar
Michael Graff committed
437
438
439
440
441
442
443
444
445
446
		name = ISC_LIST_HEAD(msg->sections[i]);
		while (name != NULL) {
			next_name = ISC_LIST_NEXT(name, link);
			ISC_LIST_UNLINK(msg->sections[i], name, link);

			rds = ISC_LIST_HEAD(name->list);
			while (rds != NULL) {
				next_rds = ISC_LIST_NEXT(rds, link);
				ISC_LIST_UNLINK(name->list, rds, link);

447
				INSIST(dns_rdataset_isassociated(rds));
Michael Graff's avatar
Michael Graff committed
448
				dns_rdataset_disassociate(rds);
449
				isc_mempool_put(msg->rdspool, rds);
Michael Graff's avatar
Michael Graff committed
450
451
				rds = next_rds;
			}
452
453
			if (dns_name_dynamic(name))
				dns_name_free(name, msg->mctx);
454
			isc_mempool_put(msg->namepool, name);
455
			name = next_name;
Michael Graff's avatar
Michael Graff committed
456
457
		}
	}
458
459
}

460
461
462
463
464
465
466
467
468
469
470
471
static void
msgresetopt(dns_message_t *msg)
{
	if (msg->opt != NULL) {
		if (msg->opt_reserved > 0) {
			dns_message_renderrelease(msg, msg->opt_reserved);
			msg->opt_reserved = 0;
		}
		INSIST(dns_rdataset_isassociated(msg->opt));
		dns_rdataset_disassociate(msg->opt);
		isc_mempool_put(msg->rdspool, msg->opt);
		msg->opt = NULL;
472
473
		msg->cc_ok = 0;
		msg->cc_bad = 0;
474
475
476
	}
}

477
static void
478
479
480
481
482
msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
	if (msg->sig_reserved > 0) {
		dns_message_renderrelease(msg, msg->sig_reserved);
		msg->sig_reserved = 0;
	}
483
484
	if (msg->tsig != NULL) {
		INSIST(dns_rdataset_isassociated(msg->tsig));
485
		INSIST(msg->namepool != NULL);
486
		if (replying) {
487
488
			INSIST(msg->querytsig == NULL);
			msg->querytsig = msg->tsig;
489
		} else {
490
491
492
493
494
			dns_rdataset_disassociate(msg->tsig);
			isc_mempool_put(msg->rdspool, msg->tsig);
			if (msg->querytsig != NULL) {
				dns_rdataset_disassociate(msg->querytsig);
				isc_mempool_put(msg->rdspool, msg->querytsig);
495
496
			}
		}
497
498
		if (dns_name_dynamic(msg->tsigname))
			dns_name_free(msg->tsigname, msg->mctx);
499
		isc_mempool_put(msg->namepool, msg->tsigname);
500
		msg->tsig = NULL;
501
		msg->tsigname = NULL;
502
	} else if (msg->querytsig != NULL && !replying) {
503
504
		dns_rdataset_disassociate(msg->querytsig);
		isc_mempool_put(msg->rdspool, msg->querytsig);
505
		msg->querytsig = NULL;
506
507
508
509
510
	}
	if (msg->sig0 != NULL) {
		INSIST(dns_rdataset_isassociated(msg->sig0));
		dns_rdataset_disassociate(msg->sig0);
		isc_mempool_put(msg->rdspool, msg->sig0);
511
512
513
		if (msg->sig0name != NULL) {
			if (dns_name_dynamic(msg->sig0name))
				dns_name_free(msg->sig0name, msg->mctx);
514
			isc_mempool_put(msg->namepool, msg->sig0name);
515
		}
516
		msg->sig0 = NULL;
517
		msg->sig0name = NULL;
518
519
520
	}
}

521
522
/*
 * Free all but one (or everything) for this message.  This is used by
523
 * both dns_message_reset() and dns_message_destroy().
524
525
 */
static void
526
msgreset(dns_message_t *msg, isc_boolean_t everything) {
527
	dns_msgblock_t *msgblock, *next_msgblock;
528
	isc_buffer_t *dynbuf, *next_dynbuf;
529
530
531
532
	dns_rdata_t *rdata;
	dns_rdatalist_t *rdatalist;

	msgresetnames(msg, 0);
533
	msgresetopt(msg);
534
	msgresetsigs(msg, ISC_FALSE);
Bob Halley's avatar
EDNS0    
Bob Halley committed
535

Michael Graff's avatar
Michael Graff committed
536
537
538
539
	/*
	 * Clean up linked lists.
	 */

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
	/*
	 * Run through the free lists, and just unlink anything found there.
	 * The memory isn't lost since these are part of message blocks we
	 * have allocated.
	 */
	rdata = ISC_LIST_HEAD(msg->freerdata);
	while (rdata != NULL) {
		ISC_LIST_UNLINK(msg->freerdata, rdata, link);
		rdata = ISC_LIST_HEAD(msg->freerdata);
	}
	rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
	while (rdatalist != NULL) {
		ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
		rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
	}

Michael Graff's avatar
Michael Graff committed
556
557
	dynbuf = ISC_LIST_HEAD(msg->scratchpad);
	INSIST(dynbuf != NULL);
Michael Graff's avatar
Michael Graff committed
558
	if (!everything) {
559
		isc_buffer_clear(dynbuf);
Michael Graff's avatar
Michael Graff committed
560
561
562
563
564
		dynbuf = ISC_LIST_NEXT(dynbuf, link);
	}
	while (dynbuf != NULL) {
		next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
		ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
565
		isc_buffer_free(&dynbuf);
Michael Graff's avatar
Michael Graff committed
566
567
568
569
		dynbuf = next_dynbuf;
	}

	msgblock = ISC_LIST_HEAD(msg->rdatas);
570
	if (!everything && msgblock != NULL) {
Michael Graff's avatar
Michael Graff committed
571
		msgblock_reset(msgblock);
Michael Graff's avatar
Michael Graff committed
572
573
574
575
576
		msgblock = ISC_LIST_NEXT(msgblock, link);
	}
	while (msgblock != NULL) {
		next_msgblock = ISC_LIST_NEXT(msgblock, link);
		ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
Michael Graff's avatar
Michael Graff committed
577
		msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
Michael Graff's avatar
Michael Graff committed
578
579
580
		msgblock = next_msgblock;
	}

Michael Graff's avatar
Michael Graff committed
581
	/*
Michael Graff's avatar
Michael Graff committed
582
	 * rdatalists could be empty.
Michael Graff's avatar
Michael Graff committed
583
584
585
	 */

	msgblock = ISC_LIST_HEAD(msg->rdatalists);
Michael Graff's avatar
Michael Graff committed
586
587
	if (!everything && msgblock != NULL) {
		msgblock_reset(msgblock);
Michael Graff's avatar
Michael Graff committed
588
589
590
591
592
		msgblock = ISC_LIST_NEXT(msgblock, link);
	}
	while (msgblock != NULL) {
		next_msgblock = ISC_LIST_NEXT(msgblock, link);
		ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
Michael Graff's avatar
Michael Graff committed
593
		msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
Michael Graff's avatar
Michael Graff committed
594
		msgblock = next_msgblock;
Michael Graff's avatar
Michael Graff committed
595
596
	}

597
	msgblock = ISC_LIST_HEAD(msg->offsets);
598
	if (!everything && msgblock != NULL) {
599
600
601
602
603
604
605
606
607
608
		msgblock_reset(msgblock);
		msgblock = ISC_LIST_NEXT(msgblock, link);
	}
	while (msgblock != NULL) {
		next_msgblock = ISC_LIST_NEXT(msgblock, link);
		ISC_LIST_UNLINK(msg->offsets, msgblock, link);
		msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
		msgblock = next_msgblock;
	}

609
	if (msg->tsigkey != NULL) {
610
		dns_tsigkey_detach(&msg->tsigkey);
611
612
613
		msg->tsigkey = NULL;
	}

614
615
616
	if (msg->tsigctx != NULL)
		dst_context_destroy(&msg->tsigctx);

617
	if (msg->query.base != NULL) {
618
619
620
		if (msg->free_query != 0)
			isc_mem_put(msg->mctx, msg->query.base,
				    msg->query.length);
621
622
		msg->query.base = NULL;
		msg->query.length = 0;
623
	}
624

625
	if (msg->saved.base != NULL) {
626
627
628
		if (msg->free_saved != 0)
			isc_mem_put(msg->mctx, msg->saved.base,
				    msg->saved.length);
629
630
		msg->saved.base = NULL;
		msg->saved.length = 0;
Brian Wellington's avatar
Brian Wellington committed
631
632
	}

633
634
635
636
637
638
	/*
	 * cleanup the buffer cleanup list
	 */
	dynbuf = ISC_LIST_HEAD(msg->cleanup);
	while (dynbuf != NULL) {
		next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
639
		ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
640
641
642
643
		isc_buffer_free(&dynbuf);
		dynbuf = next_dynbuf;
	}

Michael Graff's avatar
Michael Graff committed
644
645
646
	/*
	 * Set other bits to normal default values.
	 */
Michael Graff's avatar
Michael Graff committed
647
648
	if (!everything)
		msginit(msg);
649
650
651

	ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
	ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
Michael Graff's avatar
Michael Graff committed
652
653
}

654
655
656
657
658
659
660
661
662
663
664
665
666
static unsigned int
spacefortsig(dns_tsigkey_t *key, int otherlen) {
	isc_region_t r1, r2;
	unsigned int x;
	isc_result_t result;

	/*
	 * The space required for an TSIG record is:
	 *
	 *	n1 bytes for the name
	 *	2 bytes for the type
	 *	2 bytes for the class
	 *	4 bytes for the ttl
667
668
	 *	2 bytes for the rdlength
	 *	n2 bytes for the algorithm name
669
670
671
672
673
674
675
676
677
	 *	6 bytes for the time signed
	 *	2 bytes for the fudge
	 *	2 bytes for the MAC size
	 *	x bytes for the MAC
	 *	2 bytes for the original id
	 *	2 bytes for the error
	 *	2 bytes for the other data length
	 *	y bytes for the other data (at most)
	 * ---------------------------------
678
	 *     26 + n1 + n2 + x + y bytes
679
680
681
	 */

	dns_name_toregion(&key->name, &r1);
Brian Wellington's avatar
Brian Wellington committed
682
	dns_name_toregion(key->algorithm, &r2);
683
684
685
686
687
688
689
	if (key->key == NULL)
		x = 0;
	else {
		result = dst_key_sigsize(key->key, &x);
		if (result != ISC_R_SUCCESS)
			x = 0;
	}
690
	return (26 + r1.length + r2.length + x + otherlen);
691
692
}

693
isc_result_t
694
dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
Michael Graff's avatar
Michael Graff committed
695
696
{
	dns_message_t *m;
697
	isc_result_t result;
698
	isc_buffer_t *dynbuf;
Michael Graff's avatar
Michael Graff committed
699
700
701
	unsigned int i;

	REQUIRE(mctx != NULL);
702
703
	REQUIRE(msgp != NULL);
	REQUIRE(*msgp == NULL);
Michael Graff's avatar
Michael Graff committed
704
705
	REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
		|| intent == DNS_MESSAGE_INTENTRENDER);
Michael Graff's avatar
Michael Graff committed
706
707
708

	m = isc_mem_get(mctx, sizeof(dns_message_t));
	if (m == NULL)
709
		return (ISC_R_NOMEMORY);
Michael Graff's avatar
Michael Graff committed
710

711
712
713
714
715
	/*
	 * No allocations until further notice.  Just initialize all lists
	 * and other members that are freed in the cleanup phase here.
	 */

716
	m->magic = DNS_MESSAGE_MAGIC;
Michael Graff's avatar
Michael Graff committed
717
718
	m->from_to_wire = intent;
	msginit(m);
719

720
	for (i = 0; i < DNS_SECTION_MAX; i++)
Michael Graff's avatar
Michael Graff committed
721
		ISC_LIST_INIT(m->sections[i]);
722
723
724

	m->mctx = NULL;
	isc_mem_attach(mctx, &m->mctx);
725

Michael Graff's avatar
Michael Graff committed
726
	ISC_LIST_INIT(m->scratchpad);
727
728
	ISC_LIST_INIT(m->cleanup);
	m->namepool = NULL;
729
	m->rdspool = NULL;
Michael Graff's avatar
Michael Graff committed
730
731
	ISC_LIST_INIT(m->rdatas);
	ISC_LIST_INIT(m->rdatalists);
732
	ISC_LIST_INIT(m->offsets);
733
734
	ISC_LIST_INIT(m->freerdata);
	ISC_LIST_INIT(m->freerdatalist);
Michael Graff's avatar
Michael Graff committed
735

736
737
738
739
740
741
742
743
	/*
	 * Ok, it is safe to allocate (and then "goto cleanup" if failure)
	 */

	result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	isc_mempool_setfreemax(m->namepool, NAME_COUNT);
Michael Graff's avatar
Michael Graff committed
744
	isc_mempool_setname(m->namepool, "msg:names");
745

746
747
748
749
750
	result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
				    &m->rdspool);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
Michael Graff's avatar
Michael Graff committed
751
	isc_mempool_setname(m->rdspool, "msg:rdataset");
752

Michael Graff's avatar
Michael Graff committed
753
	dynbuf = NULL;
754
	result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
755
756
	if (result != ISC_R_SUCCESS)
		goto cleanup;
Michael Graff's avatar
Michael Graff committed
757
758
	ISC_LIST_APPEND(m->scratchpad, dynbuf, link);

759
760
	m->cctx = NULL;

761
	*msgp = m;
762
	return (ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
763
764
765
766

	/*
	 * Cleanup for error returns.
	 */
767
 cleanup:
Michael Graff's avatar
Michael Graff committed
768
	dynbuf = ISC_LIST_HEAD(m->scratchpad);
769
770
	if (dynbuf != NULL) {
		ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
771
		isc_buffer_free(&dynbuf);
772
	}
773
774
	if (m->namepool != NULL)
		isc_mempool_destroy(&m->namepool);
775
776
	if (m->rdspool != NULL)
		isc_mempool_destroy(&m->rdspool);
Michael Graff's avatar
Michael Graff committed
777
	m->magic = 0;
778
	isc_mem_putanddetach(&mctx, m, sizeof(dns_message_t));
Michael Graff's avatar
Michael Graff committed
779

780
	return (ISC_R_NOMEMORY);
Michael Graff's avatar
Michael Graff committed
781
782
783
}

void
784
dns_message_reset(dns_message_t *msg, unsigned int intent) {
785
786
787
788
	REQUIRE(DNS_MESSAGE_VALID(msg));
	REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
		|| intent == DNS_MESSAGE_INTENTRENDER);

Michael Graff's avatar
Michael Graff committed
789
	msgreset(msg, ISC_FALSE);
790
	msg->from_to_wire = intent;
Michael Graff's avatar
Michael Graff committed
791
792
793
}

void
794
dns_message_destroy(dns_message_t **msgp) {
Michael Graff's avatar
Michael Graff committed
795
796
	dns_message_t *msg;

797
	REQUIRE(msgp != NULL);
798
	REQUIRE(DNS_MESSAGE_VALID(*msgp));
Michael Graff's avatar
Michael Graff committed
799

800
801
	msg = *msgp;
	*msgp = NULL;
Michael Graff's avatar
Michael Graff committed
802
803

	msgreset(msg, ISC_TRUE);
804
	isc_mempool_destroy(&msg->namepool);
805
	isc_mempool_destroy(&msg->rdspool);
Michael Graff's avatar
Michael Graff committed
806
	msg->magic = 0;
807
	isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t));
Michael Graff's avatar
Michael Graff committed
808
809
}

810
static isc_result_t
811
findname(dns_name_t **foundname, dns_name_t *target,
812
813
814
815
	 dns_namelist_t *section)
{
	dns_name_t *curr;

816
817
	for (curr = ISC_LIST_TAIL(*section);
	     curr != NULL;
818
819
820
821
822
823
824
825
826
827
828
	     curr = ISC_LIST_PREV(curr, link)) {
		if (dns_name_equal(curr, target)) {
			if (foundname != NULL)
				*foundname = curr;
			return (ISC_R_SUCCESS);
		}
	}

	return (ISC_R_NOTFOUND);
}

829
830
831
832
833
834
835
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)
{
	dns_rdataset_t *curr;

Mukund Sivaraman's avatar
Mukund Sivaraman committed
836
837
	REQUIRE(name != NULL);
	REQUIRE(rdataset == NULL || *rdataset == NULL);
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852

	for (curr = ISC_LIST_TAIL(name->list);
	     curr != NULL;
	     curr = ISC_LIST_PREV(curr, link)) {
		if (curr->rdclass == rdclass &&
		    curr->type == type && curr->covers == covers) {
			if (rdataset != NULL)
				*rdataset = curr;
			return (ISC_R_SUCCESS);
		}
	}

	return (ISC_R_NOTFOUND);
}

853
isc_result_t
854
855
dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
		     dns_rdatatype_t covers, dns_rdataset_t **rdataset)
Michael Graff's avatar
Michael Graff committed
856
857
858
{
	dns_rdataset_t *curr;

859
	REQUIRE(name != NULL);
Mukund Sivaraman's avatar
Mukund Sivaraman committed
860
	REQUIRE(rdataset == NULL || *rdataset == NULL);
861

862
863
	for (curr = ISC_LIST_TAIL(name->list);
	     curr != NULL;
Michael Graff's avatar
Michael Graff committed
864
	     curr = ISC_LIST_PREV(curr, link)) {
Bob Halley's avatar
Bob Halley committed
865
		if (curr->type == type && curr->covers == covers) {
Mukund Sivaraman's avatar
Mukund Sivaraman committed
866
			if (ISC_UNLIKELY(rdataset != NULL))
Michael Graff's avatar
Michael Graff committed
867
				*rdataset = curr;
868
			return (ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
869
870
871
		}
	}

872
	return (ISC_R_NOTFOUND);
Michael Graff's avatar
Michael Graff committed
873
874
875
876
877
}

/*
 * Read a name from buffer "source".
 */
878
static isc_result_t
Michael Graff's avatar
Michael Graff committed
879
880
881
882
getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
	dns_decompress_t *dctx)
{
	isc_buffer_t *scratch;
883
	isc_result_t result;
Michael Graff's avatar
Michael Graff committed
884
885
886
887
	unsigned int tries;

	scratch = currentbuffer(msg);

Michael Graff's avatar
Michael Graff committed
888
889
890
891
	/*
	 * First try:  use current buffer.
	 * Second try:  allocate a new buffer and use that.
	 */
Michael Graff's avatar
Michael Graff committed
892
893
894
895
896
	tries = 0;
	while (tries < 2) {
		result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
					   scratch);

897
		if (result == ISC_R_NOSPACE) {
Michael Graff's avatar
Michael Graff committed
898
899
			tries++;

900
			result = newbuffer(msg, SCRATCHPAD_SIZE);
901
			if (result != ISC_R_SUCCESS)
Michael Graff's avatar
Michael Graff committed
902
903
904
				return (result);

			scratch = currentbuffer(msg);
905
			dns_name_reset(name);
Michael Graff's avatar
Michael Graff committed
906
907
908
909
910
		} else {
			return (result);
		}
	}

Michael Graff's avatar
Michael Graff committed
911
	INSIST(0);  /* Cannot get here... */
912
	return (ISC_R_UNEXPECTED);
Michael Graff's avatar
Michael Graff committed
913
914
}

915
static isc_result_t
David Lawrence's avatar
David Lawrence committed
916
917
918
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)
919
920
{
	isc_buffer_t *scratch;
921
	isc_result_t result;
922
	unsigned int tries;
923
	unsigned int trysize;
924
925
926
927
928

	scratch = currentbuffer(msg);

	isc_buffer_setactive(source, rdatalen);

Michael Graff's avatar
Michael Graff committed
929
930
	/*
	 * First try:  use current buffer.
931
932
933
934
	 * Second try:  allocate a new buffer of size
	 *     max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
	 *     (the data will fit if it was not more than 50% compressed)
	 * Subsequent tries: double buffer size on each try.
Michael Graff's avatar
Michael Graff committed
935
	 */
936
	tries = 0;
937
	trysize = 0;
938
	/* XXX possibly change this to a while (tries < 2) loop */
939
	for (;;) {
940
		result = dns_rdata_fromwire(rdata, rdclass, rdtype,
941
					    source, dctx, 0,
942
943
					    scratch);

944
		if (result == ISC_R_NOSPACE) {
945
946
947
948
949
950
951
952
953
954
955
			if (tries == 0) {
				trysize = 2 * rdatalen;
				if (trysize < SCRATCHPAD_SIZE)
					trysize = SCRATCHPAD_SIZE;
			} else {
				INSIST(trysize != 0);
				if (trysize >= 65535)
					return (ISC_R_NOSPACE);
					/* XXX DNS_R_RRTOOLONG? */
				trysize *= 2;
			}
956
			tries++;
957
			result = newbuffer(msg, trysize);
958
			if (result != ISC_R_SUCCESS)
959
960
961
962
963
964
965
966
				return (result);

			scratch = currentbuffer(msg);
		} else {
			return (result);
		}
	}
}
Michael Graff's avatar
Michael Graff committed
967

968
#define DO_ERROR(r)					\
969
970
971
972
	do {						\
		if (best_effort)			\
			seen_problem = ISC_TRUE;	\
		else {					\
973
			result = r;			\
974
975
976
977
			goto cleanup;			\
		}					\
	} while (0)

978
static isc_result_t
979
980
getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
	     unsigned int options)
Michael Graff's avatar
Michael Graff committed
981
982
983
984
985
{
	isc_region_t r;
	unsigned int count;
	dns_name_t *name;
	dns_name_t *name2;
986
	dns_offsets_t *offsets;
Michael Graff's avatar
Michael Graff committed
987
988
	dns_rdataset_t *rdataset;
	dns_rdatalist_t *rdatalist;
989
	isc_result_t result;
Michael Graff's avatar
Michael Graff committed
990
991
992
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	dns_namelist_t *section;
993
	isc_boolean_t free_name;
994
995
	isc_boolean_t best_effort;
	isc_boolean_t seen_problem;
Michael Graff's avatar
Michael Graff committed
996

Michael Graff's avatar
Michael Graff committed
997
	section = &msg->sections[DNS_SECTION_QUESTION];
Michael Graff's avatar
Michael Graff committed
998

999
	best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
1000
	seen_problem = ISC_FALSE;
1001

1002
1003
1004
1005
	name = NULL;
	rdataset = NULL;
	rdatalist = NULL;

1006
	for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
1007
		name = isc_mempool_get(msg->namepool);
Michael Graff's avatar
Michael Graff committed
1008
		if (name == NULL)
1009
			return (ISC_R_NOMEMORY);
1010
		free_name = ISC_TRUE;
Automatic Updater's avatar
Automatic Updater committed
1011

1012
		offsets = newoffsets(msg);
1013
1014
		if (offsets == NULL) {
			result = ISC_R_NOMEMORY;
1015
			goto cleanup;
1016
		}
1017
		dns_name_init(name, *offsets);
Michael Graff's avatar
Michael Graff committed
1018
1019
1020
1021

		/*
		 * Parse the name out of this packet.
		 */
1022
		isc_buffer_remainingregion(source, &r);
1023
		isc_buffer_setactive(source, r.length);
Michael Graff's avatar
Michael Graff committed
1024
		result = getname(name, source, msg, dctx);
1025
		if (result != ISC_R_SUCCESS)
1026
			goto cleanup;
Michael Graff's avatar
Michael Graff committed
1027
1028
1029
1030
1031
1032
1033

		/*
		 * Run through the section, looking to see if this name
		 * is already there.  If it is found, put back the allocated
		 * name since we no longer need it, and set our name pointer
		 * to point to the name we found.
		 */
1034
		result = findname(&name2, name, section);
Michael Graff's avatar
Michael Graff committed
1035
1036

		/*
1037
1038
1039
1040
		 * If it is the first name in the section, accept it.
		 *
		 * If it is not, but is not the same as the name already
		 * in the question section, append to the section.  Note that
Michael Graff's avatar
Michael Graff committed
1041
1042
1043
1044
		 * here in the question section this is illegal, so return
		 * FORMERR.  In the future, check the opcode to see if
		 * this should be legal or not.  In either case we no longer
		 * need this name pointer.
Michael Graff's avatar
Michael Graff committed
1045
		 */
1046
		if (result != ISC_R_SUCCESS) {
1047
			if (!ISC_LIST_EMPTY(*section))
1048
				DO_ERROR(DNS_R_FORMERR);
1049
1050
			ISC_LIST_APPEND(*section, name, link);
			free_name = ISC_FALSE;
1051
		} else {
1052
			isc_mempool_put(msg->namepool, name);
1053
			name = name2;
1054
			name2 = NULL;
1055
			free_name = ISC_FALSE;
1056
		}
Michael Graff's avatar
Michael Graff committed
1057
1058
1059
1060

		/*
		 * Get type and class.
		 */
1061
		isc_buffer_remainingregion(source, &r);
1062
		if (r.length < 4) {
1063
			result = ISC_R_UNEXPECTEDEND;
1064
			goto cleanup;
1065
		}
Michael Graff's avatar
Michael Graff committed
1066
1067
		rdtype = isc_buffer_getuint16(source);
		rdclass = isc_buffer_getuint16(source);
Michael Graff's avatar
Michael Graff committed
1068
1069

		/*
1070
		 * If this class is different than the one we already read,
Michael Graff's avatar
Michael Graff committed
1071
		 * this is an error.
Michael Graff's avatar
Michael Graff committed
1072
		 */
1073
		if (msg->rdclass_set == 0) {
Michael Graff's avatar
Michael Graff committed
1074
			msg->rdclass = rdclass;
1075
			msg->rdclass_set = 1;
1076
		} else if (msg->rdclass != rdclass)
1077
			DO_ERROR(DNS_R_FORMERR);
1078

1079
1080
1081
1082
1083
1084
		/*
		 * Is this a TKEY query?
		 */
		if (rdtype == dns_rdatatype_tkey)
			msg->tkey = 1;

Michael Graff's avatar
Michael Graff committed
1085
		/*
Michael Graff's avatar
Michael Graff committed
1086
		 * Can't ask the same question twice.
Michael Graff's avatar
Michael Graff committed
1087
		 */
1088
		result = dns_message_find(name, rdclass, rdtype, 0, NULL);
1089
		if (result == ISC_R_SUCCESS)
1090
			DO_ERROR(DNS_R_FORMERR);
Michael Graff's avatar
Michael Graff committed
1091
1092
1093
1094

		/*
		 * Allocate a new rdatalist.
		 */
Michael Graff's avatar
Michael Graff committed
1095
		rdatalist = newrdatalist(msg);
1096
		if (rdatalist == NULL) {
1097
			result = ISC_R_NOMEMORY;
1098
			goto cleanup;
1099
		}
1100
		rdataset =  isc_mempool_get(msg->rdspool);
1101
		if (rdataset == NULL) {
1102
			result = ISC_R_NOMEMORY;
1103
			goto cleanup;
1104
		}
Michael Graff's avatar
Michael Graff committed
1105
1106
1107
1108
1109

		/*
		 * Convert rdatalist to rdataset, and attach the latter to
		 * the name.
		 */
Michael Graff's avatar
Michael Graff committed
1110
1111