1999-04-26 21:59:36 +00:00
|
|
|
/*
|
2000-02-03 23:50:32 +00:00
|
|
|
* Copyright (C) 1999, 2000 Internet Software Consortium.
|
1999-04-26 21:59:36 +00:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
|
|
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
|
|
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2000-06-23 20:47:23 +00:00
|
|
|
/* $Id: message.c,v 1.131 2000/06/23 20:47:23 mws Exp $ */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
1999-04-26 21:59:36 +00:00
|
|
|
/***
|
|
|
|
*** Imports
|
|
|
|
***/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/mem.h>
|
2000-05-08 19:23:32 +00:00
|
|
|
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
2000-05-15 17:49:57 +00:00
|
|
|
#include <isc/buffer.h>
|
1999-04-26 21:59:36 +00:00
|
|
|
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dns/dnssec.h>
|
|
|
|
#include <dns/keyvalues.h>
|
1999-04-26 21:59:36 +00:00
|
|
|
#include <dns/message.h>
|
1999-04-27 02:24:11 +00:00
|
|
|
#include <dns/rdata.h>
|
|
|
|
#include <dns/rdatalist.h>
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dns/rdataset.h>
|
2000-05-30 23:14:57 +00:00
|
|
|
#include <dns/rdatastruct.h>
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dns/result.h>
|
1999-08-20 18:56:24 +00:00
|
|
|
#include <dns/tsig.h>
|
2000-01-21 20:18:41 +00:00
|
|
|
#include <dns/view.h>
|
1999-04-26 21:59:36 +00:00
|
|
|
|
1999-06-09 12:06:21 +00:00
|
|
|
#define DNS_MESSAGE_OPCODE_MASK 0x7800U
|
1999-09-02 01:52:31 +00:00
|
|
|
#define DNS_MESSAGE_OPCODE_SHIFT 11
|
1999-05-14 17:52:11 +00:00
|
|
|
#define DNS_MESSAGE_RCODE_MASK 0x000fU
|
|
|
|
#define DNS_MESSAGE_FLAG_MASK 0x8ff0U
|
1999-09-02 01:52:31 +00:00
|
|
|
#define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
|
|
|
|
#define DNS_MESSAGE_EDNSRCODE_SHIFT 24
|
|
|
|
#define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
|
|
|
|
#define DNS_MESSAGE_EDNSVERSION_SHIFT 16
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
#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))
|
2000-05-15 17:49:57 +00:00
|
|
|
#define ADD_STRING(b, s) {if (strlen(s) >= \
|
|
|
|
isc_buffer_availablelength(b)) \
|
|
|
|
return(ISC_R_NOSPACE); else \
|
|
|
|
isc_buffer_putstr(b, s);}
|
2000-05-22 21:22:06 +00:00
|
|
|
#define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
|
|
|
|
&& ((s) < DNS_PSEUDOSECTION_MAX))
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the size of each individual scratchpad buffer, and the numbers
|
|
|
|
* of various block allocations used within the server.
|
1999-05-14 17:52:11 +00:00
|
|
|
* XXXMLG These should come from a config setting.
|
1999-04-27 02:24:11 +00:00
|
|
|
*/
|
1999-04-29 08:18:57 +00:00
|
|
|
#define SCRATCHPAD_SIZE 512
|
1999-05-01 17:18:47 +00:00
|
|
|
#define NAME_COUNT 8
|
|
|
|
#define RDATA_COUNT 8
|
|
|
|
#define RDATALIST_COUNT 8
|
|
|
|
#define RDATASET_COUNT RDATALIST_COUNT
|
1999-04-27 02:24:11 +00:00
|
|
|
|
2000-05-15 17:49:57 +00:00
|
|
|
/*
|
|
|
|
* Text representation of the different items, for message_totext
|
|
|
|
* functions.
|
|
|
|
*/
|
2000-06-01 18:26:56 +00:00
|
|
|
static const char *sectiontext[] = {
|
2000-05-15 17:49:57 +00:00
|
|
|
"QUESTION",
|
|
|
|
"ANSWER",
|
|
|
|
"AUTHORITY",
|
|
|
|
"ADDITIONAL"
|
|
|
|
};
|
|
|
|
|
2000-06-09 01:46:59 +00:00
|
|
|
static const char *updsectiontext[] = {
|
|
|
|
"ZONE",
|
|
|
|
"PREREQUISITE",
|
|
|
|
"UPDATE",
|
|
|
|
"ADDITIONAL"
|
|
|
|
};
|
|
|
|
|
2000-06-01 18:26:56 +00:00
|
|
|
static const char *opcodetext[] = {
|
2000-05-15 17:49:57 +00:00
|
|
|
"QUERY",
|
|
|
|
"IQUERY",
|
|
|
|
"STATUS",
|
|
|
|
"RESERVED3",
|
|
|
|
"NOTIFY",
|
|
|
|
"UPDATE",
|
|
|
|
"RESERVED6",
|
|
|
|
"RESERVED7",
|
|
|
|
"RESERVED8",
|
|
|
|
"RESERVED9",
|
|
|
|
"RESERVED10",
|
|
|
|
"RESERVED11",
|
|
|
|
"RESERVED12",
|
|
|
|
"RESERVED13",
|
|
|
|
"RESERVED14",
|
|
|
|
"RESERVED15"
|
|
|
|
};
|
|
|
|
|
2000-06-01 18:26:56 +00:00
|
|
|
static const char *rcodetext[] = {
|
2000-05-15 17:49:57 +00:00
|
|
|
"NOERROR",
|
|
|
|
"FORMERR",
|
|
|
|
"SERVFAIL",
|
|
|
|
"NXDOMAIN",
|
|
|
|
"NOTIMPL",
|
|
|
|
"REFUSED",
|
|
|
|
"YXDOMAIN",
|
|
|
|
"YXRRSET",
|
|
|
|
"NXRRSET",
|
|
|
|
"NOTAUTH",
|
|
|
|
"NOTZONE",
|
|
|
|
"RESERVED11",
|
|
|
|
"RESERVED12",
|
|
|
|
"RESERVED13",
|
|
|
|
"RESERVED14",
|
|
|
|
"RESERVED15",
|
|
|
|
"BADVERS"
|
|
|
|
};
|
|
|
|
|
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
/*
|
|
|
|
* "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
|
|
|
|
* size, or the allocated elements will not be alligned correctly.
|
|
|
|
*/
|
|
|
|
struct dns_msgblock {
|
1999-05-14 17:52:11 +00:00
|
|
|
unsigned int count;
|
1999-04-27 02:24:11 +00:00
|
|
|
unsigned int remaining;
|
|
|
|
ISC_LINK(dns_msgblock_t) link;
|
|
|
|
}; /* dynamically sized */
|
1999-04-26 21:59:36 +00:00
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
static inline dns_msgblock_t *
|
|
|
|
msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
|
1999-04-30 00:17:15 +00:00
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
#define msgblock_get(block, type) \
|
1999-04-28 03:19:58 +00:00
|
|
|
((type *)msgblock_internalget(block, sizeof(type)))
|
1999-04-26 21:59:36 +00:00
|
|
|
|
|
|
|
static inline void *
|
1999-04-27 02:24:11 +00:00
|
|
|
msgblock_internalget(dns_msgblock_t *, unsigned int);
|
|
|
|
|
|
|
|
static inline void
|
1999-05-14 17:52:11 +00:00
|
|
|
msgblock_reset(dns_msgblock_t *);
|
1999-04-26 21:59:36 +00:00
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
static inline void
|
|
|
|
msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
|
1999-04-26 21:59:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
|
|
|
|
* is free, return NULL.
|
|
|
|
*/
|
|
|
|
static inline dns_msgblock_t *
|
1999-04-27 02:24:11 +00:00
|
|
|
msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
|
|
|
|
unsigned int count)
|
1999-04-26 21:59:36 +00:00
|
|
|
{
|
|
|
|
dns_msgblock_t *block;
|
|
|
|
unsigned int length;
|
|
|
|
|
|
|
|
length = sizeof(dns_msgblock_t) + (sizeof_type * count);
|
|
|
|
|
|
|
|
block = isc_mem_get(mctx, length);
|
|
|
|
if (block == NULL)
|
1999-05-14 17:52:11 +00:00
|
|
|
return (NULL);
|
1999-04-26 21:59:36 +00:00
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
block->count = count;
|
1999-04-26 21:59:36 +00:00
|
|
|
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 *
|
2000-05-08 14:38:29 +00:00
|
|
|
msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
|
1999-04-26 21:59:36 +00:00
|
|
|
void *ptr;
|
|
|
|
|
1999-07-28 05:23:16 +00:00
|
|
|
if (block == NULL || block->remaining == 0)
|
1999-04-26 21:59:36 +00:00
|
|
|
return (NULL);
|
|
|
|
|
|
|
|
block->remaining--;
|
|
|
|
|
|
|
|
ptr = (((unsigned char *)block)
|
|
|
|
+ sizeof(dns_msgblock_t)
|
|
|
|
+ (sizeof_type * block->remaining));
|
|
|
|
|
|
|
|
return (ptr);
|
|
|
|
}
|
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
msgblock_reset(dns_msgblock_t *block) {
|
1999-05-14 17:52:11 +00:00
|
|
|
block->remaining = block->count;
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-04-26 21:59:36 +00:00
|
|
|
/*
|
|
|
|
* Release memory associated with a message block.
|
|
|
|
*/
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
|
1999-04-26 21:59:36 +00:00
|
|
|
{
|
1999-05-14 17:52:11 +00:00
|
|
|
unsigned int length;
|
|
|
|
|
|
|
|
length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
|
|
|
|
|
|
|
|
isc_mem_put(mctx, block, length);
|
1999-04-26 21:59:36 +00:00
|
|
|
}
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-04-28 03:19:58 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
*/
|
1999-12-23 00:09:04 +00:00
|
|
|
static inline isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
newbuffer(dns_message_t *msg, unsigned int size) {
|
1999-04-28 03:19:58 +00:00
|
|
|
isc_result_t result;
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_t *dynbuf;
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
dynbuf = NULL;
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
|
1999-04-28 03:19:58 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-28 03:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline isc_buffer_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
currentbuffer(dns_message_t *msg) {
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_t *dynbuf;
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
dynbuf = ISC_LIST_TAIL(msg->scratchpad);
|
1999-05-14 17:52:11 +00:00
|
|
|
INSIST(dynbuf != NULL);
|
1999-04-28 03:19:58 +00:00
|
|
|
|
1999-09-02 02:10:44 +00:00
|
|
|
return (dynbuf);
|
1999-04-28 03:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
|
1999-05-14 23:19:12 +00:00
|
|
|
ISC_LIST_PREPEND(msg->freerdata, rdata, link);
|
1999-04-28 03:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline dns_rdata_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
newrdata(dns_message_t *msg) {
|
1999-04-28 03:19:58 +00:00
|
|
|
dns_msgblock_t *msgblock;
|
|
|
|
dns_rdata_t *rdata;
|
|
|
|
|
1999-05-14 23:19:12 +00:00
|
|
|
rdata = ISC_LIST_HEAD(msg->freerdata);
|
|
|
|
if (rdata != NULL) {
|
|
|
|
ISC_LIST_UNLINK(msg->freerdata, rdata, link);
|
1999-04-28 03:19:58 +00:00
|
|
|
return (rdata);
|
|
|
|
}
|
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
msgblock = ISC_LIST_TAIL(msg->rdatas);
|
1999-04-28 03:19:58 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (rdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
|
1999-05-14 23:19:12 +00:00
|
|
|
ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
|
1999-04-28 03:19:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline dns_rdatalist_t *
|
2000-05-08 14:38:29 +00:00
|
|
|
newrdatalist(dns_message_t *msg) {
|
1999-04-28 03:19:58 +00:00
|
|
|
dns_msgblock_t *msgblock;
|
|
|
|
dns_rdatalist_t *rdatalist;
|
|
|
|
|
1999-05-14 23:19:12 +00:00
|
|
|
rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
|
|
|
|
if (rdatalist != NULL) {
|
|
|
|
ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
|
1999-04-28 03:19:58 +00:00
|
|
|
return (rdatalist);
|
|
|
|
}
|
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
msgblock = ISC_LIST_TAIL(msg->rdatalists);
|
1999-04-28 03:19:58 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (rdatalist);
|
|
|
|
}
|
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
msginitheader(dns_message_t *m) {
|
1999-04-27 02:24:11 +00:00
|
|
|
m->id = 0;
|
|
|
|
m->flags = 0;
|
|
|
|
m->rcode = 0;
|
|
|
|
m->opcode = 0;
|
1999-04-29 08:18:57 +00:00
|
|
|
m->rdclass = 0;
|
1999-07-24 01:09:04 +00:00
|
|
|
}
|
1999-04-28 03:19:58 +00:00
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
msginitprivate(dns_message_t *m) {
|
1999-07-24 01:09:04 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < DNS_SECTION_MAX; i++) {
|
1999-04-28 03:19:58 +00:00
|
|
|
m->cursors[i] = NULL;
|
1999-04-30 22:35:49 +00:00
|
|
|
m->counts[i] = 0;
|
1999-04-29 08:18:57 +00:00
|
|
|
}
|
1999-05-12 19:32:13 +00:00
|
|
|
m->opt = NULL;
|
2000-03-29 01:32:22 +00:00
|
|
|
m->sig0 = NULL;
|
2000-05-23 23:35:54 +00:00
|
|
|
m->sig0name = NULL;
|
2000-05-31 23:58:35 +00:00
|
|
|
m->tsig = NULL;
|
2000-03-29 01:32:22 +00:00
|
|
|
m->tsigname = NULL;
|
1999-04-27 02:24:11 +00:00
|
|
|
m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
|
1999-11-25 01:58:16 +00:00
|
|
|
m->opt_reserved = 0;
|
2000-05-30 23:14:57 +00:00
|
|
|
m->sig_reserved = 0;
|
1999-05-14 17:52:11 +00:00
|
|
|
m->reserved = 0;
|
1999-04-30 05:42:06 +00:00
|
|
|
m->buffer = NULL;
|
1999-05-14 23:19:12 +00:00
|
|
|
m->need_cctx_cleanup = 0;
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-08-20 18:56:24 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
msginittsig(dns_message_t *m) {
|
2000-05-30 23:14:57 +00:00
|
|
|
m->tsigstatus = dns_rcode_noerror;
|
|
|
|
m->querytsigstatus = dns_rcode_noerror;
|
1999-08-20 18:56:24 +00:00
|
|
|
m->tsigkey = NULL;
|
1999-09-10 14:54:10 +00:00
|
|
|
m->tsigctx = NULL;
|
1999-11-02 19:59:04 +00:00
|
|
|
m->sigstart = -1;
|
|
|
|
m->sig0key = NULL;
|
|
|
|
m->sig0status = dns_rcode_noerror;
|
|
|
|
m->query = NULL;
|
1999-11-02 22:58:29 +00:00
|
|
|
m->saved = NULL;
|
2000-05-31 23:58:35 +00:00
|
|
|
m->querytsig = NULL;
|
1999-08-20 18:56:24 +00:00
|
|
|
}
|
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
/*
|
1999-07-24 01:09:04 +00:00
|
|
|
* Init elements to default state. Used both when allocating a new element
|
|
|
|
* and when resetting one.
|
1999-04-27 02:24:11 +00:00
|
|
|
*/
|
1999-07-24 01:09:04 +00:00
|
|
|
static inline void
|
2000-05-08 14:38:29 +00:00
|
|
|
msginit(dns_message_t *m) {
|
1999-07-24 01:09:04 +00:00
|
|
|
msginitheader(m);
|
|
|
|
msginitprivate(m);
|
1999-08-20 18:56:24 +00:00
|
|
|
msginittsig(m);
|
1999-07-28 02:19:46 +00:00
|
|
|
m->header_ok = 0;
|
|
|
|
m->question_ok = 0;
|
1999-09-10 14:54:10 +00:00
|
|
|
m->tcp_continuation = 0;
|
2000-03-13 19:27:35 +00:00
|
|
|
m->verified_sig = 0;
|
|
|
|
m->verify_attempted = 0;
|
1999-07-24 01:09:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
msgresetnames(dns_message_t *msg, unsigned int first_section) {
|
1999-04-27 02:24:11 +00:00
|
|
|
unsigned int i;
|
1999-07-24 01:09:04 +00:00
|
|
|
dns_name_t *name, *next_name;
|
|
|
|
dns_rdataset_t *rds, *next_rds;
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Clean up name lists by calling the rdataset disassociate function.
|
|
|
|
*/
|
1999-07-24 01:09:04 +00:00
|
|
|
for (i = first_section; i < DNS_SECTION_MAX; i++) {
|
1999-04-27 02:24:11 +00:00
|
|
|
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);
|
|
|
|
|
1999-11-02 21:29:13 +00:00
|
|
|
INSIST(dns_rdataset_isassociated(rds));
|
1999-04-27 02:24:11 +00:00
|
|
|
dns_rdataset_disassociate(rds);
|
1999-09-11 01:35:55 +00:00
|
|
|
isc_mempool_put(msg->rdspool, rds);
|
1999-04-27 02:24:11 +00:00
|
|
|
rds = next_rds;
|
|
|
|
}
|
1999-09-10 02:48:32 +00:00
|
|
|
isc_mempool_put(msg->namepool, name);
|
1999-04-30 00:17:15 +00:00
|
|
|
name = next_name;
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
}
|
1999-07-24 01:09:04 +00:00
|
|
|
}
|
|
|
|
|
1999-11-25 01:58:16 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
static void
|
2000-05-30 23:14:57 +00:00
|
|
|
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;
|
|
|
|
}
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->tsig != NULL) {
|
|
|
|
INSIST(dns_rdataset_isassociated(msg->tsig));
|
2000-03-29 01:32:22 +00:00
|
|
|
INSIST(msg->namepool != NULL);
|
2000-05-30 23:14:57 +00:00
|
|
|
if (replying) {
|
2000-05-31 23:58:35 +00:00
|
|
|
INSIST(msg->querytsig == NULL);
|
|
|
|
msg->querytsig = msg->tsig;
|
2000-05-30 23:14:57 +00:00
|
|
|
} else {
|
2000-05-31 23:58:35 +00:00
|
|
|
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);
|
2000-05-30 23:14:57 +00:00
|
|
|
}
|
|
|
|
}
|
2000-03-29 01:32:22 +00:00
|
|
|
isc_mempool_put(msg->namepool, msg->tsigname);
|
2000-05-31 23:58:35 +00:00
|
|
|
msg->tsig = NULL;
|
2000-03-29 01:32:22 +00:00
|
|
|
msg->tsigname = NULL;
|
2000-06-23 02:07:58 +00:00
|
|
|
} else if (msg->querytsig != NULL) {
|
|
|
|
dns_rdataset_disassociate(msg->querytsig);
|
|
|
|
isc_mempool_put(msg->rdspool, msg->querytsig);
|
2000-03-29 01:32:22 +00:00
|
|
|
}
|
|
|
|
if (msg->sig0 != NULL) {
|
|
|
|
INSIST(dns_rdataset_isassociated(msg->sig0));
|
|
|
|
dns_rdataset_disassociate(msg->sig0);
|
|
|
|
isc_mempool_put(msg->rdspool, msg->sig0);
|
2000-05-23 23:35:54 +00:00
|
|
|
if (msg->sig0name != NULL)
|
|
|
|
isc_mempool_put(msg->namepool, msg->sig0name);
|
2000-03-29 01:32:22 +00:00
|
|
|
msg->sig0 = NULL;
|
2000-05-23 23:35:54 +00:00
|
|
|
msg->sig0name = NULL;
|
2000-03-29 01:32:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
/*
|
|
|
|
* Free all but one (or everything) for this message. This is used by
|
|
|
|
* both dns_message_reset() and dns_message_parse().
|
|
|
|
*/
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
msgreset(dns_message_t *msg, isc_boolean_t everything) {
|
1999-07-24 01:09:04 +00:00
|
|
|
dns_msgblock_t *msgblock, *next_msgblock;
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_t *dynbuf, *next_dynbuf;
|
1999-07-24 01:09:04 +00:00
|
|
|
dns_rdata_t *rdata;
|
|
|
|
dns_rdatalist_t *rdatalist;
|
|
|
|
|
|
|
|
msgresetnames(msg, 0);
|
1999-11-25 01:58:16 +00:00
|
|
|
msgresetopt(msg);
|
2000-05-30 23:14:57 +00:00
|
|
|
msgresetsigs(msg, ISC_FALSE);
|
1999-09-02 01:52:31 +00:00
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
/*
|
|
|
|
* Clean up linked lists.
|
|
|
|
*/
|
|
|
|
|
1999-05-14 23:19:12 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
dynbuf = ISC_LIST_HEAD(msg->scratchpad);
|
|
|
|
INSIST(dynbuf != NULL);
|
1999-05-14 17:52:11 +00:00
|
|
|
if (!everything) {
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_clear(dynbuf);
|
1999-04-27 02:24:11 +00:00
|
|
|
dynbuf = ISC_LIST_NEXT(dynbuf, link);
|
|
|
|
}
|
|
|
|
while (dynbuf != NULL) {
|
|
|
|
next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
|
|
|
|
ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_free(&dynbuf);
|
1999-04-27 02:24:11 +00:00
|
|
|
dynbuf = next_dynbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
msgblock = ISC_LIST_HEAD(msg->rdatas);
|
|
|
|
INSIST(msgblock != NULL);
|
1999-05-14 17:52:11 +00:00
|
|
|
if (!everything) {
|
|
|
|
msgblock_reset(msgblock);
|
1999-04-27 02:24:11 +00:00
|
|
|
msgblock = ISC_LIST_NEXT(msgblock, link);
|
|
|
|
}
|
|
|
|
while (msgblock != NULL) {
|
|
|
|
next_msgblock = ISC_LIST_NEXT(msgblock, link);
|
|
|
|
ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
|
1999-05-14 17:52:11 +00:00
|
|
|
msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
|
1999-04-27 02:24:11 +00:00
|
|
|
msgblock = next_msgblock;
|
|
|
|
}
|
|
|
|
|
1999-04-30 21:52:40 +00:00
|
|
|
/*
|
1999-05-14 17:52:11 +00:00
|
|
|
* rdatalists could be empty.
|
1999-04-30 21:52:40 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
msgblock = ISC_LIST_HEAD(msg->rdatalists);
|
1999-05-14 17:52:11 +00:00
|
|
|
if (!everything && msgblock != NULL) {
|
|
|
|
msgblock_reset(msgblock);
|
1999-04-30 21:52:40 +00:00
|
|
|
msgblock = ISC_LIST_NEXT(msgblock, link);
|
|
|
|
}
|
|
|
|
while (msgblock != NULL) {
|
|
|
|
next_msgblock = ISC_LIST_NEXT(msgblock, link);
|
|
|
|
ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
|
1999-05-14 17:52:11 +00:00
|
|
|
msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
|
1999-04-30 21:52:40 +00:00
|
|
|
msgblock = next_msgblock;
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-05-14 23:19:12 +00:00
|
|
|
if (msg->need_cctx_cleanup == 1)
|
1999-04-30 07:53:07 +00:00
|
|
|
dns_compress_invalidate(&msg->cctx);
|
|
|
|
|
1999-11-02 19:59:04 +00:00
|
|
|
if (msg->tsigkey != NULL) {
|
2000-05-26 00:16:46 +00:00
|
|
|
dns_tsigkey_detach(&msg->tsigkey);
|
1999-11-02 19:59:04 +00:00
|
|
|
msg->tsigkey = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg->query != NULL) {
|
|
|
|
isc_mem_put(msg->mctx, msg->query->base, msg->query->length);
|
|
|
|
isc_mem_put(msg->mctx, msg->query, sizeof(isc_region_t));
|
|
|
|
msg->query = NULL;
|
|
|
|
}
|
1999-08-20 18:56:24 +00:00
|
|
|
|
1999-11-02 22:58:29 +00:00
|
|
|
if (msg->saved != NULL) {
|
|
|
|
isc_mem_put(msg->mctx, msg->saved->base, msg->saved->length);
|
|
|
|
isc_mem_put(msg->mctx, msg->saved, sizeof(isc_region_t));
|
|
|
|
msg->saved = NULL;
|
|
|
|
}
|
|
|
|
|
1999-09-10 02:48:32 +00:00
|
|
|
/*
|
|
|
|
* cleanup the buffer cleanup list
|
|
|
|
*/
|
|
|
|
dynbuf = ISC_LIST_HEAD(msg->cleanup);
|
|
|
|
while (dynbuf != NULL) {
|
|
|
|
next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
|
1999-10-08 14:59:02 +00:00
|
|
|
ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
|
1999-09-10 02:48:32 +00:00
|
|
|
isc_buffer_free(&dynbuf);
|
|
|
|
dynbuf = next_dynbuf;
|
|
|
|
}
|
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
/*
|
|
|
|
* Set other bits to normal default values.
|
|
|
|
*/
|
1999-05-14 17:52:11 +00:00
|
|
|
if (!everything)
|
|
|
|
msginit(msg);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
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
|
|
|
|
* 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)
|
|
|
|
* ---------------------------------
|
|
|
|
* 30 + n1 + n2 + x + y bytes
|
|
|
|
*/
|
|
|
|
|
|
|
|
dns_name_toregion(&key->name, &r1);
|
|
|
|
dns_name_toregion(&key->algorithm, &r2);
|
|
|
|
if (key->key == NULL)
|
|
|
|
x = 0;
|
|
|
|
else {
|
|
|
|
result = dst_key_sigsize(key->key, &x);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
x = 0;
|
|
|
|
}
|
|
|
|
return (24 + r1.length + r2.length + x + otherlen);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-07-24 01:09:04 +00:00
|
|
|
dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
|
1999-04-27 02:24:11 +00:00
|
|
|
{
|
|
|
|
dns_message_t *m;
|
1999-09-10 02:48:32 +00:00
|
|
|
isc_result_t result;
|
1999-04-27 02:24:11 +00:00
|
|
|
dns_msgblock_t *msgblock;
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_t *dynbuf;
|
1999-04-27 02:24:11 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
REQUIRE(mctx != NULL);
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(msgp != NULL);
|
|
|
|
REQUIRE(*msgp == NULL);
|
1999-05-14 17:52:11 +00:00
|
|
|
REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
|
|
|
|
|| intent == DNS_MESSAGE_INTENTRENDER);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
m = isc_mem_get(mctx, sizeof(dns_message_t));
|
|
|
|
if (m == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-09-10 02:48:32 +00:00
|
|
|
/*
|
|
|
|
* No allocations until further notice. Just initialize all lists
|
|
|
|
* and other members that are freed in the cleanup phase here.
|
|
|
|
*/
|
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
m->magic = DNS_MESSAGE_MAGIC;
|
1999-04-27 02:24:11 +00:00
|
|
|
m->from_to_wire = intent;
|
|
|
|
msginit(m);
|
1999-09-10 02:48:32 +00:00
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
for (i = 0 ; i < DNS_SECTION_MAX ; i++)
|
|
|
|
ISC_LIST_INIT(m->sections[i]);
|
|
|
|
m->mctx = mctx;
|
1999-09-10 02:48:32 +00:00
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
ISC_LIST_INIT(m->scratchpad);
|
1999-09-10 02:48:32 +00:00
|
|
|
ISC_LIST_INIT(m->cleanup);
|
|
|
|
m->namepool = NULL;
|
1999-09-11 01:35:55 +00:00
|
|
|
m->rdspool = NULL;
|
1999-04-27 02:24:11 +00:00
|
|
|
ISC_LIST_INIT(m->rdatas);
|
|
|
|
ISC_LIST_INIT(m->rdatalists);
|
1999-05-14 23:19:12 +00:00
|
|
|
ISC_LIST_INIT(m->freerdata);
|
|
|
|
ISC_LIST_INIT(m->freerdatalist);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-09-10 02:48:32 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
isc_mempool_setfillcount(m->namepool, NAME_COUNT);
|
1999-10-27 19:33:49 +00:00
|
|
|
isc_mempool_setname(m->namepool, "msg:names");
|
1999-09-10 02:48:32 +00:00
|
|
|
|
1999-09-11 01:35:55 +00:00
|
|
|
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);
|
|
|
|
isc_mempool_setfillcount(m->rdspool, NAME_COUNT);
|
1999-10-27 19:33:49 +00:00
|
|
|
isc_mempool_setname(m->rdspool, "msg:rdataset");
|
1999-09-11 01:35:55 +00:00
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
dynbuf = NULL;
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
|
1999-09-10 02:48:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
1999-04-27 02:24:11 +00:00
|
|
|
ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
|
|
|
|
|
|
|
|
msgblock = msgblock_allocate(mctx, sizeof(dns_rdata_t),
|
|
|
|
RDATA_COUNT);
|
|
|
|
if (msgblock == NULL)
|
1999-09-10 02:48:32 +00:00
|
|
|
goto cleanup;
|
1999-04-27 02:24:11 +00:00
|
|
|
ISC_LIST_APPEND(m->rdatas, msgblock, link);
|
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
if (intent == DNS_MESSAGE_INTENTPARSE) {
|
1999-04-27 02:24:11 +00:00
|
|
|
msgblock = msgblock_allocate(mctx, sizeof(dns_rdatalist_t),
|
|
|
|
RDATALIST_COUNT);
|
|
|
|
if (msgblock == NULL)
|
1999-09-10 02:48:32 +00:00
|
|
|
goto cleanup;
|
1999-04-27 02:24:11 +00:00
|
|
|
ISC_LIST_APPEND(m->rdatalists, msgblock, link);
|
|
|
|
}
|
|
|
|
|
1999-05-14 22:22:49 +00:00
|
|
|
*msgp = m;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Cleanup for error returns.
|
|
|
|
*/
|
1999-09-10 02:48:32 +00:00
|
|
|
cleanup:
|
1999-04-27 02:24:11 +00:00
|
|
|
msgblock = ISC_LIST_HEAD(m->rdatas);
|
1999-09-10 02:48:32 +00:00
|
|
|
if (msgblock != NULL)
|
|
|
|
msgblock_free(mctx, msgblock, sizeof(dns_rdata_t));
|
1999-04-27 02:24:11 +00:00
|
|
|
dynbuf = ISC_LIST_HEAD(m->scratchpad);
|
1999-09-10 02:48:32 +00:00
|
|
|
if (dynbuf != NULL)
|
|
|
|
isc_buffer_free(&dynbuf);
|
|
|
|
if (m->namepool != NULL)
|
|
|
|
isc_mempool_destroy(&m->namepool);
|
1999-09-11 01:35:55 +00:00
|
|
|
if (m->rdspool != NULL)
|
|
|
|
isc_mempool_destroy(&m->rdspool);
|
1999-04-27 02:24:11 +00:00
|
|
|
m->magic = 0;
|
|
|
|
isc_mem_put(mctx, m, sizeof(dns_message_t));
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_reset(dns_message_t *msg, unsigned int intent) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
|
|
|
|
|| intent == DNS_MESSAGE_INTENTRENDER);
|
|
|
|
|
1999-04-27 02:24:11 +00:00
|
|
|
msgreset(msg, ISC_FALSE);
|
2000-05-19 22:11:20 +00:00
|
|
|
msg->from_to_wire = intent;
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_destroy(dns_message_t **msgp) {
|
1999-04-27 02:24:11 +00:00
|
|
|
dns_message_t *msg;
|
|
|
|
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(msgp != NULL);
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(*msgp));
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-05-14 22:22:49 +00:00
|
|
|
msg = *msgp;
|
|
|
|
*msgp = NULL;
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
msgreset(msg, ISC_TRUE);
|
1999-09-10 02:48:32 +00:00
|
|
|
isc_mempool_destroy(&msg->namepool);
|
1999-09-11 01:35:55 +00:00
|
|
|
isc_mempool_destroy(&msg->rdspool);
|
1999-04-27 02:24:11 +00:00
|
|
|
msg->magic = 0;
|
|
|
|
isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-10-17 19:20:20 +00:00
|
|
|
findname(dns_name_t **foundname, dns_name_t *target, unsigned int attributes,
|
|
|
|
dns_namelist_t *section)
|
1999-04-29 08:18:57 +00:00
|
|
|
{
|
|
|
|
dns_name_t *curr;
|
|
|
|
|
|
|
|
for (curr = ISC_LIST_TAIL(*section) ;
|
|
|
|
curr != NULL ;
|
|
|
|
curr = ISC_LIST_PREV(curr, link)) {
|
1999-10-17 19:20:20 +00:00
|
|
|
if (dns_name_equal(curr, target) &&
|
|
|
|
(curr->attributes & attributes) == attributes) {
|
1999-04-29 08:18:57 +00:00
|
|
|
if (foundname != NULL)
|
|
|
|
*foundname = curr;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-29 08:18:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
1999-04-29 08:18:57 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-09-09 01:10:53 +00:00
|
|
|
dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
|
|
|
|
dns_rdatatype_t covers, dns_rdataset_t **rdataset)
|
1999-04-29 08:18:57 +00:00
|
|
|
{
|
|
|
|
dns_rdataset_t *curr;
|
|
|
|
|
1999-09-09 01:10:53 +00:00
|
|
|
if (rdataset != NULL) {
|
|
|
|
REQUIRE(*rdataset == NULL);
|
|
|
|
}
|
|
|
|
|
1999-04-29 08:18:57 +00:00
|
|
|
for (curr = ISC_LIST_TAIL(name->list) ;
|
|
|
|
curr != NULL ;
|
|
|
|
curr = ISC_LIST_PREV(curr, link)) {
|
1999-08-31 22:14:06 +00:00
|
|
|
if (curr->type == type && curr->covers == covers) {
|
1999-04-29 08:18:57 +00:00
|
|
|
if (rdataset != NULL)
|
|
|
|
*rdataset = curr;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-29 08:18:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
1999-04-29 08:18:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a name from buffer "source".
|
|
|
|
*/
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-04-29 08:18:57 +00:00
|
|
|
getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
|
|
|
|
dns_decompress_t *dctx)
|
|
|
|
{
|
|
|
|
isc_buffer_t *scratch;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-04-29 08:18:57 +00:00
|
|
|
unsigned int tries;
|
|
|
|
|
|
|
|
scratch = currentbuffer(msg);
|
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
/*
|
|
|
|
* First try: use current buffer.
|
|
|
|
* Second try: allocate a new buffer and use that.
|
|
|
|
*/
|
1999-04-29 08:18:57 +00:00
|
|
|
tries = 0;
|
|
|
|
while (tries < 2) {
|
1999-05-01 17:18:47 +00:00
|
|
|
dns_name_init(name, NULL);
|
1999-04-29 08:18:57 +00:00
|
|
|
result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
|
|
|
|
scratch);
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOSPACE) {
|
1999-04-29 08:18:57 +00:00
|
|
|
tries++;
|
|
|
|
|
1999-08-20 06:08:39 +00:00
|
|
|
result = newbuffer(msg, SCRATCHPAD_SIZE);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-04-29 08:18:57 +00:00
|
|
|
return (result);
|
|
|
|
|
|
|
|
scratch = currentbuffer(msg);
|
|
|
|
} else {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
INSIST(0); /* Cannot get here... */
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-04-29 08:18:57 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2000-03-23 05:18:46 +00:00
|
|
|
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)
|
1999-04-30 00:17:15 +00:00
|
|
|
{
|
|
|
|
isc_buffer_t *scratch;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-04-30 00:17:15 +00:00
|
|
|
unsigned int tries;
|
1999-08-20 06:08:39 +00:00
|
|
|
unsigned int trysize;
|
1999-04-30 00:17:15 +00:00
|
|
|
|
1999-06-20 08:05:56 +00:00
|
|
|
/*
|
|
|
|
* In dynamic update messages, the rdata can be empty.
|
|
|
|
*/
|
|
|
|
if (msg->opcode == dns_opcode_update && rdatalen == 0) {
|
|
|
|
/*
|
|
|
|
* When the rdata is empty, the data pointer is never
|
2000-06-01 18:26:56 +00:00
|
|
|
* dereferenced, but it must still be non-NULL. Casting
|
|
|
|
* 1 rather than "" avoids warnings about discarding
|
|
|
|
* the const attribute of a string, for compilers that
|
|
|
|
* would warn about such things.
|
1999-06-20 08:05:56 +00:00
|
|
|
*/
|
2000-06-01 18:26:56 +00:00
|
|
|
rdata->data = (unsigned char *)1;
|
1999-06-20 08:05:56 +00:00
|
|
|
rdata->length = 0;
|
1999-08-02 22:19:30 +00:00
|
|
|
rdata->rdclass = rdclass;
|
1999-06-20 08:05:56 +00:00
|
|
|
rdata->type = rdtype;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-06-20 08:05:56 +00:00
|
|
|
}
|
2000-03-18 01:00:57 +00:00
|
|
|
|
1999-04-30 00:17:15 +00:00
|
|
|
scratch = currentbuffer(msg);
|
|
|
|
|
|
|
|
isc_buffer_setactive(source, rdatalen);
|
|
|
|
|
1999-05-14 17:52:11 +00:00
|
|
|
/*
|
|
|
|
* First try: use current buffer.
|
1999-08-20 06:08:39 +00:00
|
|
|
* 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.
|
1999-05-14 17:52:11 +00:00
|
|
|
*/
|
1999-04-30 00:17:15 +00:00
|
|
|
tries = 0;
|
1999-08-20 06:08:39 +00:00
|
|
|
trysize = 0;
|
2000-03-18 01:00:57 +00:00
|
|
|
/* XXX possibly change this to a while (tries < 2) loop */
|
1999-08-20 06:08:39 +00:00
|
|
|
for (;;) {
|
1999-04-30 00:17:15 +00:00
|
|
|
result = dns_rdata_fromwire(rdata, rdclass, rdtype,
|
|
|
|
source, dctx, ISC_FALSE,
|
|
|
|
scratch);
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOSPACE) {
|
1999-08-20 06:08:39 +00:00
|
|
|
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;
|
|
|
|
}
|
1999-04-30 00:17:15 +00:00
|
|
|
tries++;
|
1999-08-20 06:08:39 +00:00
|
|
|
result = newbuffer(msg, trysize);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-04-30 00:17:15 +00:00
|
|
|
return (result);
|
|
|
|
|
|
|
|
scratch = currentbuffer(msg);
|
|
|
|
} else {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-04-28 03:19:58 +00:00
|
|
|
getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx)
|
|
|
|
{
|
|
|
|
isc_region_t r;
|
|
|
|
unsigned int count;
|
|
|
|
dns_name_t *name;
|
|
|
|
dns_name_t *name2;
|
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
dns_rdatalist_t *rdatalist;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-04-29 08:18:57 +00:00
|
|
|
dns_rdatatype_t rdtype;
|
|
|
|
dns_rdataclass_t rdclass;
|
|
|
|
dns_namelist_t *section;
|
1999-09-11 01:35:55 +00:00
|
|
|
isc_boolean_t free_name;
|
1999-04-28 03:19:58 +00:00
|
|
|
|
1999-04-29 08:18:57 +00:00
|
|
|
section = &msg->sections[DNS_SECTION_QUESTION];
|
1999-04-28 03:19:58 +00:00
|
|
|
|
1999-09-11 01:35:55 +00:00
|
|
|
name = NULL;
|
|
|
|
rdataset = NULL;
|
|
|
|
rdatalist = NULL;
|
|
|
|
|
1999-04-29 08:18:57 +00:00
|
|
|
for (count = 0 ; count < msg->counts[DNS_SECTION_QUESTION] ; count++) {
|
1999-09-10 02:48:32 +00:00
|
|
|
name = isc_mempool_get(msg->namepool);
|
1999-04-28 03:19:58 +00:00
|
|
|
if (name == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-09-11 01:35:55 +00:00
|
|
|
free_name = ISC_TRUE;
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the name out of this packet.
|
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_remainingregion(source, &r);
|
1999-04-30 00:17:15 +00:00
|
|
|
isc_buffer_setactive(source, r.length);
|
1999-04-28 03:19:58 +00:00
|
|
|
result = getname(name, source, msg, dctx);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
1999-10-17 19:20:20 +00:00
|
|
|
result = findname(&name2, name, 0, section);
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
/*
|
1999-04-30 00:17:15 +00:00
|
|
|
* 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
|
1999-04-29 08:18:57 +00:00
|
|
|
* 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.
|
1999-04-28 03:19:58 +00:00
|
|
|
*/
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-04-30 00:17:15 +00:00
|
|
|
if (ISC_LIST_EMPTY(*section)) {
|
|
|
|
ISC_LIST_APPEND(*section, name, link);
|
1999-09-11 01:35:55 +00:00
|
|
|
free_name = ISC_FALSE;
|
1999-04-30 00:17:15 +00:00
|
|
|
} else {
|
1999-09-10 02:48:32 +00:00
|
|
|
result = DNS_R_FORMERR;
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-04-30 00:17:15 +00:00
|
|
|
}
|
|
|
|
} else {
|
1999-09-10 02:48:32 +00:00
|
|
|
isc_mempool_put(msg->namepool, name);
|
1999-04-30 00:17:15 +00:00
|
|
|
name = name2;
|
1999-09-10 02:48:32 +00:00
|
|
|
name2 = NULL;
|
1999-09-11 01:35:55 +00:00
|
|
|
free_name = ISC_FALSE;
|
1999-04-30 00:17:15 +00:00
|
|
|
}
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get type and class.
|
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_remainingregion(source, &r);
|
1999-09-10 02:48:32 +00:00
|
|
|
if (r.length < 4) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_UNEXPECTEDEND;
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-09-10 02:48:32 +00:00
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
rdtype = isc_buffer_getuint16(source);
|
|
|
|
rdclass = isc_buffer_getuint16(source);
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
/*
|
1999-05-12 19:32:13 +00:00
|
|
|
* If this class is different than the one we already read,
|
1999-04-29 08:18:57 +00:00
|
|
|
* this is an error.
|
1999-04-28 03:19:58 +00:00
|
|
|
*/
|
1999-04-29 08:18:57 +00:00
|
|
|
if (msg->state == DNS_SECTION_ANY) {
|
|
|
|
msg->state = DNS_SECTION_QUESTION;
|
|
|
|
msg->rdclass = rdclass;
|
1999-09-10 02:48:32 +00:00
|
|
|
} else if (msg->rdclass != rdclass) {
|
|
|
|
result = DNS_R_FORMERR;
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-09-10 02:48:32 +00:00
|
|
|
}
|
2000-04-14 20:13:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If this is a type that cannot occur in a question section,
|
|
|
|
* return failure.
|
|
|
|
*/
|
|
|
|
if (dns_rdatatype_notquestion(rdtype)) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2000-04-14 22:59:01 +00:00
|
|
|
|
1999-04-28 03:19:58 +00:00
|
|
|
/*
|
1999-05-14 17:52:11 +00:00
|
|
|
* Can't ask the same question twice.
|
1999-04-28 03:19:58 +00:00
|
|
|
*/
|
1999-09-09 01:10:53 +00:00
|
|
|
result = dns_message_findtype(name, rdtype, 0, NULL);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
1999-09-10 02:48:32 +00:00
|
|
|
result = DNS_R_FORMERR;
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-09-10 02:48:32 +00:00
|
|
|
}
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a new rdatalist.
|
|
|
|
*/
|
1999-04-29 08:18:57 +00:00
|
|
|
rdatalist = newrdatalist(msg);
|
1999-09-10 02:48:32 +00:00
|
|
|
if (rdatalist == NULL) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-09-10 02:48:32 +00:00
|
|
|
}
|
1999-09-11 01:35:55 +00:00
|
|
|
rdataset = isc_mempool_get(msg->rdspool);
|
1999-09-10 02:48:32 +00:00
|
|
|
if (rdataset == NULL) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-09-10 02:48:32 +00:00
|
|
|
}
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert rdatalist to rdataset, and attach the latter to
|
|
|
|
* the name.
|
|
|
|
*/
|
1999-04-29 08:18:57 +00:00
|
|
|
rdatalist->type = rdtype;
|
1999-12-15 02:25:35 +00:00
|
|
|
rdatalist->covers = 0;
|
1999-04-29 08:18:57 +00:00
|
|
|
rdatalist->rdclass = rdclass;
|
|
|
|
rdatalist->ttl = 0;
|
|
|
|
ISC_LIST_INIT(rdatalist->rdata);
|
|
|
|
|
1999-04-30 00:17:15 +00:00
|
|
|
dns_rdataset_init(rdataset);
|
1999-04-29 08:18:57 +00:00
|
|
|
result = dns_rdatalist_tordataset(rdatalist, rdataset);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-09-11 01:35:55 +00:00
|
|
|
goto cleanup;
|
1999-09-10 02:48:32 +00:00
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
|
1999-04-29 08:18:57 +00:00
|
|
|
|
|
|
|
ISC_LIST_APPEND(name->list, rdataset, link);
|
2000-04-28 23:48:49 +00:00
|
|
|
rdataset = NULL;
|
1999-04-28 03:19:58 +00:00
|
|
|
}
|
1999-09-10 02:48:32 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-09-10 02:48:32 +00:00
|
|
|
|
1999-09-11 01:35:55 +00:00
|
|
|
cleanup:
|
1999-11-02 21:29:13 +00:00
|
|
|
if (rdataset != NULL) {
|
|
|
|
INSIST(!dns_rdataset_isassociated(rdataset));
|
1999-09-11 01:35:55 +00:00
|
|
|
isc_mempool_put(msg->rdspool, rdataset);
|
1999-11-02 21:29:13 +00:00
|
|
|
}
|
1999-09-11 01:35:55 +00:00
|
|
|
#if 0
|
|
|
|
if (rdatalist != NULL)
|
|
|
|
isc_mempool_put(msg->rdlpool, rdatalist);
|
|
|
|
#endif
|
|
|
|
if (free_name)
|
|
|
|
isc_mempool_put(msg->namepool, name);
|
1999-09-10 02:48:32 +00:00
|
|
|
|
|
|
|
return (result);
|
1999-04-28 03:19:58 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-04-28 03:19:58 +00:00
|
|
|
getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
1999-08-20 06:08:39 +00:00
|
|
|
dns_section_t sectionid, isc_boolean_t preserve_order)
|
1999-04-28 03:19:58 +00:00
|
|
|
{
|
1999-04-29 08:18:57 +00:00
|
|
|
isc_region_t r;
|
1999-10-17 19:20:20 +00:00
|
|
|
unsigned int count, rdatalen, attributes;
|
1999-04-29 08:18:57 +00:00
|
|
|
dns_name_t *name;
|
|
|
|
dns_name_t *name2;
|
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
dns_rdatalist_t *rdatalist;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-31 22:14:06 +00:00
|
|
|
dns_rdatatype_t rdtype, covers;
|
1999-04-29 08:18:57 +00:00
|
|
|
dns_rdataclass_t rdclass;
|
1999-04-30 00:17:15 +00:00
|
|
|
dns_rdata_t *rdata;
|
1999-04-29 08:18:57 +00:00
|
|
|
dns_ttl_t ttl;
|
|
|
|
dns_namelist_t *section;
|
1999-11-09 05:39:45 +00:00
|
|
|
isc_boolean_t free_name, free_rdataset;
|
1999-04-29 08:18:57 +00:00
|
|
|
|
|
|
|
for (count = 0 ; count < msg->counts[sectionid] ; count++) {
|
1999-08-20 18:56:24 +00:00
|
|
|
int recstart = source->current;
|
1999-10-17 19:20:20 +00:00
|
|
|
isc_boolean_t skip_name_search, skip_type_search;
|
1999-11-09 05:39:45 +00:00
|
|
|
|
1999-05-12 19:32:13 +00:00
|
|
|
section = &msg->sections[sectionid];
|
|
|
|
|
1999-10-17 19:20:20 +00:00
|
|
|
skip_name_search = ISC_FALSE;
|
|
|
|
skip_type_search = ISC_FALSE;
|
1999-11-09 05:39:45 +00:00
|
|
|
free_name = ISC_FALSE;
|
|
|
|
free_rdataset = ISC_FALSE;
|
|
|
|
|
1999-09-10 02:48:32 +00:00
|
|
|
name = isc_mempool_get(msg->namepool);
|
1999-04-29 08:18:57 +00:00
|
|
|
if (name == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-11-09 05:39:45 +00:00
|
|
|
free_name = ISC_TRUE;
|
1999-04-29 08:18:57 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the name out of this packet.
|
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_remainingregion(source, &r);
|
1999-04-30 00:17:15 +00:00
|
|
|
isc_buffer_setactive(source, r.length);
|
1999-04-29 08:18:57 +00:00
|
|
|
result = getname(name, source, msg, dctx);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-11-09 05:39:45 +00:00
|
|
|
goto cleanup;
|
1999-04-29 08:18:57 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get type, class, ttl, and rdatalen. Verify that at least
|
|
|
|
* rdatalen bytes remain. (Some of this is deferred to
|
1999-05-14 17:52:11 +00:00
|
|
|
* later.)
|
1999-04-29 08:18:57 +00:00
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_remainingregion(source, &r);
|
1999-11-09 05:39:45 +00:00
|
|
|
if (r.length < 2 + 2 + 4 + 2) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_UNEXPECTEDEND;
|
1999-11-09 05:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
rdtype = isc_buffer_getuint16(source);
|
|
|
|
rdclass = isc_buffer_getuint16(source);
|
|
|
|
|
1999-07-30 13:33:14 +00:00
|
|
|
/*
|
|
|
|
* If there was no question section, we may not yet have
|
|
|
|
* established a class. Do so now.
|
|
|
|
*/
|
|
|
|
if (msg->state == DNS_SECTION_ANY) {
|
2000-06-23 20:47:23 +00:00
|
|
|
if ((msg->opcode != dns_opcode_update) &&
|
|
|
|
(rdclass == 0 || rdclass == dns_rdataclass_any)) {
|
1999-11-09 05:39:45 +00:00
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-07-30 13:33:14 +00:00
|
|
|
msg->rdclass = rdclass;
|
|
|
|
msg->state = DNS_SECTION_QUESTION;
|
|
|
|
}
|
|
|
|
|
1999-04-29 08:18:57 +00:00
|
|
|
/*
|
1999-05-12 19:32:13 +00:00
|
|
|
* If this class is different than the one in the question
|
|
|
|
* section, bail.
|
1999-04-29 08:18:57 +00:00
|
|
|
*/
|
1999-05-14 17:52:11 +00:00
|
|
|
if (msg->opcode != dns_opcode_update
|
1999-07-26 17:00:34 +00:00
|
|
|
&& rdtype != dns_rdatatype_tsig
|
1999-09-02 01:52:31 +00:00
|
|
|
&& rdtype != dns_rdatatype_opt
|
1999-10-25 21:07:01 +00:00
|
|
|
&& rdtype != dns_rdatatype_key /* XXX in a TKEY query */
|
1999-11-02 19:59:04 +00:00
|
|
|
&& rdtype != dns_rdatatype_sig /* XXX SIG(0) */
|
1999-11-09 05:39:45 +00:00
|
|
|
&& msg->rdclass != rdclass) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-05-12 19:32:13 +00:00
|
|
|
|
|
|
|
/*
|
1999-10-25 21:07:01 +00:00
|
|
|
* Special type handling for TSIG, OPT, and TKEY.
|
1999-05-12 19:32:13 +00:00
|
|
|
*/
|
|
|
|
if (rdtype == dns_rdatatype_tsig) {
|
1999-09-01 20:50:34 +00:00
|
|
|
/*
|
|
|
|
* If it is a tsig, verify that it is in the
|
|
|
|
* additional data section, and switch sections for
|
|
|
|
* the rest of this rdata.
|
|
|
|
*/
|
1999-11-09 05:39:45 +00:00
|
|
|
if ((sectionid != DNS_SECTION_ADDITIONAL)
|
|
|
|
|| (rdclass != dns_rdataclass_any)) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->tsig != NULL) {
|
2000-03-29 01:32:22 +00:00
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-11-02 19:59:04 +00:00
|
|
|
msg->sigstart = recstart;
|
1999-10-17 19:20:20 +00:00
|
|
|
skip_name_search = ISC_TRUE;
|
|
|
|
skip_type_search = ISC_TRUE;
|
1999-09-01 20:50:34 +00:00
|
|
|
} else if (rdtype == dns_rdatatype_opt) {
|
|
|
|
/*
|
|
|
|
* The name of an OPT record must be ".", it
|
|
|
|
* must be in the additional data section, and
|
|
|
|
* it must be the first OPT we've seen.
|
|
|
|
*/
|
|
|
|
if (!dns_name_equal(dns_rootname, name) ||
|
|
|
|
sectionid != DNS_SECTION_ADDITIONAL ||
|
1999-11-09 05:39:45 +00:00
|
|
|
msg->opt != NULL) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-10-17 19:20:20 +00:00
|
|
|
skip_name_search = ISC_TRUE;
|
|
|
|
skip_type_search = ISC_TRUE;
|
1999-10-25 21:07:01 +00:00
|
|
|
} else if (rdtype == dns_rdatatype_tkey) {
|
|
|
|
/*
|
2000-03-29 01:32:22 +00:00
|
|
|
* A TKEY must be in the additional section if this
|
|
|
|
* is a query, and the answer section if this is a
|
|
|
|
* response.
|
1999-10-25 21:07:01 +00:00
|
|
|
* Its class is ignored.
|
|
|
|
*/
|
2000-04-14 23:03:13 +00:00
|
|
|
dns_section_t tkeysection;
|
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
|
|
|
|
tkeysection = DNS_SECTION_ADDITIONAL;
|
|
|
|
else
|
|
|
|
tkeysection = DNS_SECTION_ANSWER;
|
|
|
|
if (sectionid != tkeysection) {
|
1999-11-09 05:39:45 +00:00
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-05-12 19:32:13 +00:00
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ... now get ttl and rdatalen, and check buffer.
|
|
|
|
*/
|
|
|
|
ttl = isc_buffer_getuint32(source);
|
|
|
|
rdatalen = isc_buffer_getuint16(source);
|
1999-05-14 17:52:11 +00:00
|
|
|
r.length -= (2 + 2 + 4 + 2);
|
1999-11-09 05:39:45 +00:00
|
|
|
if (r.length < rdatalen) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_UNEXPECTEDEND;
|
1999-11-09 05:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
|
1999-10-17 19:20:20 +00:00
|
|
|
/*
|
|
|
|
* Read the rdata from the wire format. Interpret the
|
|
|
|
* rdata according to its actual class, even if it had a
|
|
|
|
* DynDNS meta-class in the packet (unless this is a TSIG).
|
|
|
|
* Then put the meta-class back into the finished rdata.
|
|
|
|
*/
|
|
|
|
rdata = newrdata(msg);
|
1999-11-09 05:39:45 +00:00
|
|
|
if (rdata == NULL) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
1999-11-09 05:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-10-17 19:20:20 +00:00
|
|
|
attributes = 0;
|
|
|
|
if (rdtype != dns_rdatatype_tsig) {
|
|
|
|
if (rdtype == dns_rdatatype_cname) {
|
|
|
|
name->attributes |= DNS_NAMEATTR_CNAME;
|
|
|
|
attributes = DNS_NAMEATTR_CNAME;
|
|
|
|
skip_name_search = ISC_TRUE;
|
|
|
|
} else if (rdtype == dns_rdatatype_dname) {
|
|
|
|
name->attributes |= DNS_NAMEATTR_DNAME;
|
|
|
|
attributes = DNS_NAMEATTR_DNAME;
|
|
|
|
skip_name_search = ISC_TRUE;
|
|
|
|
}
|
2000-03-23 05:18:46 +00:00
|
|
|
result = getrdata(source, msg, dctx, msg->rdclass,
|
|
|
|
rdtype, rdatalen, rdata);
|
1999-10-17 19:20:20 +00:00
|
|
|
} else
|
2000-03-23 05:18:46 +00:00
|
|
|
result = getrdata(source, msg, dctx, rdclass,
|
|
|
|
rdtype, rdatalen, rdata);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-11-09 05:39:45 +00:00
|
|
|
goto cleanup;
|
1999-10-17 19:20:20 +00:00
|
|
|
rdata->rdclass = rdclass;
|
|
|
|
if (rdtype == dns_rdatatype_sig && rdata->length > 0) {
|
|
|
|
covers = dns_rdata_covers(rdata);
|
|
|
|
if (covers == dns_rdatatype_cname)
|
|
|
|
attributes = DNS_NAMEATTR_CNAME;
|
|
|
|
else if (covers == dns_rdatatype_dname)
|
|
|
|
attributes = DNS_NAMEATTR_DNAME;
|
2000-05-23 00:09:09 +00:00
|
|
|
else if (covers == 0 &&
|
|
|
|
sectionid == DNS_SECTION_ADDITIONAL)
|
|
|
|
{
|
2000-03-29 01:32:22 +00:00
|
|
|
if (msg->sig0 != NULL) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-11-02 19:59:04 +00:00
|
|
|
msg->sigstart = recstart;
|
2000-04-20 19:51:39 +00:00
|
|
|
skip_name_search = ISC_TRUE;
|
|
|
|
skip_type_search = ISC_TRUE;
|
1999-11-02 19:59:04 +00:00
|
|
|
}
|
1999-10-17 19:20:20 +00:00
|
|
|
} else
|
|
|
|
covers = 0;
|
|
|
|
|
1999-05-12 19:32:13 +00:00
|
|
|
/*
|
|
|
|
* If we are doing a dynamic update don't bother searching
|
|
|
|
* for a name, just append this one to the end of the message.
|
|
|
|
*/
|
1999-09-01 20:50:34 +00:00
|
|
|
if (preserve_order || msg->opcode == dns_opcode_update ||
|
1999-10-17 19:20:20 +00:00
|
|
|
skip_name_search) {
|
2000-03-29 01:32:22 +00:00
|
|
|
if (rdtype != dns_rdatatype_opt &&
|
|
|
|
rdtype != dns_rdatatype_tsig &&
|
2000-05-23 00:09:09 +00:00
|
|
|
!(rdtype == dns_rdatatype_sig && covers == 0 &&
|
|
|
|
sectionid == DNS_SECTION_ADDITIONAL))
|
2000-03-29 01:32:22 +00:00
|
|
|
{
|
1999-09-02 01:52:31 +00:00
|
|
|
ISC_LIST_APPEND(*section, name, link);
|
1999-11-09 05:39:45 +00:00
|
|
|
free_name = ISC_FALSE;
|
|
|
|
}
|
1999-05-12 19:32:13 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
1999-10-17 19:20:20 +00:00
|
|
|
result = findname(&name2, name, attributes, section);
|
1999-05-12 19:32:13 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If it is a new name, append to the section.
|
|
|
|
*/
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
1999-09-10 02:48:32 +00:00
|
|
|
isc_mempool_put(msg->namepool, name);
|
1999-05-12 19:32:13 +00:00
|
|
|
name = name2;
|
|
|
|
} else {
|
|
|
|
ISC_LIST_APPEND(*section, name, link);
|
|
|
|
}
|
1999-11-09 05:39:45 +00:00
|
|
|
free_name = ISC_FALSE;
|
1999-05-12 19:32:13 +00:00
|
|
|
}
|
|
|
|
|
1999-04-29 08:18:57 +00:00
|
|
|
/*
|
|
|
|
* Search name for the particular type and class.
|
1999-05-12 19:32:13 +00:00
|
|
|
* Skip this stage if in update mode, or this is a TSIG.
|
1999-04-29 08:18:57 +00:00
|
|
|
*/
|
1999-09-01 20:50:34 +00:00
|
|
|
if (preserve_order || msg->opcode == dns_opcode_update ||
|
1999-10-17 19:20:20 +00:00
|
|
|
skip_type_search)
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOTFOUND;
|
1999-09-09 01:10:53 +00:00
|
|
|
else {
|
2000-04-14 20:13:49 +00:00
|
|
|
/*
|
|
|
|
* If this is a type that can only occur in
|
|
|
|
* the question section, fail.
|
|
|
|
*/
|
|
|
|
if (dns_rdatatype_questiononly(rdtype)) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
1999-09-09 01:10:53 +00:00
|
|
|
rdataset = NULL;
|
|
|
|
result = dns_message_findtype(name, rdtype, covers,
|
|
|
|
&rdataset);
|
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
|
|
|
|
/*
|
1999-04-30 00:17:15 +00:00
|
|
|
* If we found an rdataset that matches, we need to
|
|
|
|
* append this rdata to that set. If we did not, we need
|
|
|
|
* to create a new rdatalist, store the important bits there,
|
|
|
|
* convert it to an rdataset, and link the latter to the name.
|
2000-04-14 18:36:45 +00:00
|
|
|
* Yuck. When appending, make certain that the type isn't
|
|
|
|
* a singleton type, such as SOA or CNAME.
|
1999-10-17 19:20:20 +00:00
|
|
|
*
|
2000-04-14 18:36:45 +00:00
|
|
|
* Note that this check will be bypassed when preserving order,
|
|
|
|
* the opcode is an update, or the type search is skipped.
|
1999-04-29 08:18:57 +00:00
|
|
|
*/
|
2000-04-14 18:36:45 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
if (dns_rdatatype_issingleton(rdtype)) {
|
|
|
|
result = DNS_R_FORMERR;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
1999-09-11 01:35:55 +00:00
|
|
|
rdataset = isc_mempool_get(msg->rdspool);
|
1999-11-09 05:39:45 +00:00
|
|
|
if (rdataset == NULL) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
1999-11-09 05:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
free_rdataset = ISC_TRUE;
|
|
|
|
|
1999-04-30 00:17:15 +00:00
|
|
|
rdatalist = newrdatalist(msg);
|
1999-11-09 05:39:45 +00:00
|
|
|
if (rdatalist == NULL) {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOMEMORY;
|
1999-11-09 05:39:45 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
|
1999-04-30 00:17:15 +00:00
|
|
|
rdatalist->type = rdtype;
|
1999-08-31 22:14:06 +00:00
|
|
|
rdatalist->covers = covers;
|
1999-04-30 00:17:15 +00:00
|
|
|
rdatalist->rdclass = rdclass;
|
|
|
|
rdatalist->ttl = ttl;
|
|
|
|
ISC_LIST_INIT(rdatalist->rdata);
|
1999-04-29 08:18:57 +00:00
|
|
|
|
1999-04-30 00:17:15 +00:00
|
|
|
dns_rdataset_init(rdataset);
|
|
|
|
dns_rdatalist_tordataset(rdatalist, rdataset);
|
|
|
|
|
1999-11-09 05:39:45 +00:00
|
|
|
if (rdtype != dns_rdatatype_opt) {
|
1999-09-02 01:52:31 +00:00
|
|
|
ISC_LIST_APPEND(name->list, rdataset, link);
|
1999-11-09 05:39:45 +00:00
|
|
|
free_rdataset = ISC_FALSE;
|
|
|
|
}
|
1999-04-30 00:17:15 +00:00
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
|
|
|
|
/*
|
1999-11-23 20:53:34 +00:00
|
|
|
* Minimize TTLs.
|
|
|
|
*
|
|
|
|
* Section 5.2 of RFC 2181 says we should drop
|
|
|
|
* nonauthoritative rrsets where the TTLs differ, but we
|
|
|
|
* currently treat them the as if they were authoritative and
|
|
|
|
* minimize them.
|
1999-04-29 08:18:57 +00:00
|
|
|
*/
|
1999-12-17 00:21:38 +00:00
|
|
|
if (ttl != rdataset->ttl) {
|
|
|
|
rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
|
|
|
|
if (ttl < rdataset->ttl)
|
|
|
|
rdataset->ttl = ttl;
|
|
|
|
}
|
1999-04-29 08:18:57 +00:00
|
|
|
|
1999-04-30 00:17:15 +00:00
|
|
|
/*
|
1999-05-21 00:48:59 +00:00
|
|
|
* XXXMLG Perform a totally ugly hack here to pull
|
1999-04-30 00:17:15 +00:00
|
|
|
* the rdatalist out of the private field in the rdataset,
|
|
|
|
* and append this rdata to the rdatalist's linked list
|
|
|
|
* of rdata.
|
|
|
|
*/
|
|
|
|
rdatalist = (dns_rdatalist_t *)(rdataset->private1);
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
|
1999-05-12 19:32:13 +00:00
|
|
|
|
|
|
|
/*
|
1999-09-02 01:52:31 +00:00
|
|
|
* If this is an OPT record, remember it. Also, set
|
|
|
|
* the extended rcode.
|
1999-05-12 19:32:13 +00:00
|
|
|
*/
|
1999-09-02 01:52:31 +00:00
|
|
|
if (rdtype == dns_rdatatype_opt) {
|
|
|
|
unsigned int ercode;
|
|
|
|
|
1999-09-01 20:50:34 +00:00
|
|
|
msg->opt = rdataset;
|
1999-11-09 05:39:45 +00:00
|
|
|
rdataset = NULL;
|
|
|
|
free_rdataset = ISC_FALSE;
|
1999-09-02 01:52:31 +00:00
|
|
|
ercode = (msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
|
|
|
|
>> 20;
|
|
|
|
msg->rcode |= ercode;
|
1999-09-14 23:48:27 +00:00
|
|
|
isc_mempool_put(msg->namepool, name);
|
1999-11-09 05:39:45 +00:00
|
|
|
free_name = ISC_FALSE;
|
1999-09-02 01:52:31 +00:00
|
|
|
}
|
1999-11-09 05:39:45 +00:00
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
/*
|
|
|
|
* If this is an SIG(0) or TSIG record, remember it.
|
|
|
|
*/
|
2000-05-23 00:09:09 +00:00
|
|
|
if (rdtype == dns_rdatatype_sig && covers == 0 &&
|
|
|
|
sectionid == DNS_SECTION_ADDITIONAL)
|
|
|
|
{
|
2000-03-29 01:32:22 +00:00
|
|
|
msg->sig0 = rdataset;
|
2000-05-23 23:35:54 +00:00
|
|
|
msg->sig0name = name;
|
2000-03-29 01:32:22 +00:00
|
|
|
rdataset = NULL;
|
|
|
|
free_rdataset = ISC_FALSE;
|
|
|
|
free_name = ISC_FALSE;
|
|
|
|
}
|
|
|
|
else if (rdtype == dns_rdatatype_tsig) {
|
2000-05-31 23:58:35 +00:00
|
|
|
msg->tsig = rdataset;
|
2000-03-29 01:32:22 +00:00
|
|
|
msg->tsigname = name;
|
|
|
|
rdataset = NULL;
|
|
|
|
free_rdataset = ISC_FALSE;
|
|
|
|
free_name = ISC_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-11-09 05:39:45 +00:00
|
|
|
INSIST(free_name == ISC_FALSE);
|
|
|
|
INSIST(free_rdataset == ISC_FALSE);
|
1999-04-29 08:18:57 +00:00
|
|
|
}
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-11-09 05:39:45 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (free_name)
|
|
|
|
isc_mempool_put(msg->namepool, name);
|
|
|
|
if (free_rdataset)
|
|
|
|
isc_mempool_put(msg->rdspool, rdataset);
|
|
|
|
|
|
|
|
return (result);
|
1999-04-28 03:19:58 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 06:08:39 +00:00
|
|
|
dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
|
|
|
|
isc_boolean_t preserve_order)
|
1999-04-27 02:24:11 +00:00
|
|
|
{
|
1999-04-28 03:19:58 +00:00
|
|
|
isc_region_t r;
|
|
|
|
dns_decompress_t dctx;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t ret;
|
1999-04-30 00:17:15 +00:00
|
|
|
isc_uint16_t tmpflags;
|
1999-11-02 19:59:04 +00:00
|
|
|
isc_buffer_t origsource;
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-28 03:19:58 +00:00
|
|
|
REQUIRE(source != NULL);
|
1999-05-14 17:52:11 +00:00
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-11-02 19:59:04 +00:00
|
|
|
origsource = *source;
|
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
msg->header_ok = 0;
|
|
|
|
msg->question_ok = 0;
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_remainingregion(source, &r);
|
1999-05-14 17:52:11 +00:00
|
|
|
if (r.length < DNS_MESSAGE_HEADERLEN)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTEDEND);
|
1999-04-28 03:19:58 +00:00
|
|
|
|
|
|
|
msg->id = isc_buffer_getuint16(source);
|
1999-04-30 00:17:15 +00:00
|
|
|
tmpflags = isc_buffer_getuint16(source);
|
|
|
|
msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
|
|
|
|
>> DNS_MESSAGE_OPCODE_SHIFT);
|
|
|
|
msg->rcode = (tmpflags & DNS_MESSAGE_RCODE_MASK);
|
1999-05-01 17:18:47 +00:00
|
|
|
msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
|
1999-04-29 08:18:57 +00:00
|
|
|
msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
|
|
|
|
msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
|
|
|
|
msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
|
|
|
|
msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
|
1999-04-28 03:19:58 +00:00
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
msg->header_ok = 1;
|
|
|
|
|
1999-05-21 00:48:59 +00:00
|
|
|
/*
|
|
|
|
* -1 means no EDNS.
|
|
|
|
*/
|
1999-04-28 03:19:58 +00:00
|
|
|
dns_decompress_init(&dctx, -1, ISC_FALSE);
|
|
|
|
|
2000-05-04 22:19:34 +00:00
|
|
|
dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
|
1999-05-21 00:48:59 +00:00
|
|
|
|
1999-04-28 03:19:58 +00:00
|
|
|
ret = getquestions(source, msg, &dctx);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (ret != ISC_R_SUCCESS)
|
1999-04-28 03:19:58 +00:00
|
|
|
return (ret);
|
1999-07-24 01:09:04 +00:00
|
|
|
msg->question_ok = 1;
|
1999-04-28 03:19:58 +00:00
|
|
|
|
1999-08-20 06:08:39 +00:00
|
|
|
ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER,
|
|
|
|
preserve_order);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (ret != ISC_R_SUCCESS)
|
1999-04-28 03:19:58 +00:00
|
|
|
return (ret);
|
|
|
|
|
1999-08-20 06:08:39 +00:00
|
|
|
ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY,
|
|
|
|
preserve_order);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (ret != ISC_R_SUCCESS)
|
1999-04-28 03:19:58 +00:00
|
|
|
return (ret);
|
|
|
|
|
1999-08-20 06:08:39 +00:00
|
|
|
ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL,
|
|
|
|
preserve_order);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (ret != ISC_R_SUCCESS)
|
1999-04-28 03:19:58 +00:00
|
|
|
return (ret);
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_remainingregion(source, &r);
|
1999-04-30 00:17:15 +00:00
|
|
|
if (r.length != 0)
|
|
|
|
return (DNS_R_FORMERR);
|
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->tsig != NULL || msg->tsigkey != NULL || msg->sig0 != NULL) {
|
1999-11-02 22:58:29 +00:00
|
|
|
msg->saved = isc_mem_get(msg->mctx, sizeof(isc_region_t));
|
|
|
|
if (msg->saved == NULL)
|
1999-11-02 19:59:04 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_usedregion(&origsource, &r);
|
1999-11-02 22:58:29 +00:00
|
|
|
msg->saved->length = r.length;
|
|
|
|
msg->saved->base = isc_mem_get(msg->mctx, msg->saved->length);
|
|
|
|
if (msg->saved->base == NULL) {
|
|
|
|
isc_mem_put(msg->mctx, msg->saved,
|
1999-11-02 19:59:04 +00:00
|
|
|
sizeof(isc_region_t));
|
1999-11-02 22:58:29 +00:00
|
|
|
msg->saved = NULL;
|
1999-11-02 19:59:04 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
}
|
1999-11-02 22:58:29 +00:00
|
|
|
memcpy(msg->saved->base, r.base, msg->saved->length);
|
1999-11-02 19:59:04 +00:00
|
|
|
}
|
1999-04-28 03:19:58 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_renderbegin(dns_message_t *msg, isc_buffer_t *buffer) {
|
1999-04-30 05:42:06 +00:00
|
|
|
isc_region_t r;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-04-30 05:42:06 +00:00
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-27 02:24:11 +00:00
|
|
|
REQUIRE(buffer != NULL);
|
1999-04-30 05:42:06 +00:00
|
|
|
REQUIRE(msg->buffer == NULL);
|
1999-05-14 17:52:11 +00:00
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-04-30 05:42:06 +00:00
|
|
|
/*
|
|
|
|
* Erase the contents of this buffer.
|
|
|
|
*/
|
|
|
|
isc_buffer_clear(buffer);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make certain there is enough for at least the header in this
|
|
|
|
* buffer.
|
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_availableregion(buffer, &r);
|
1999-05-14 17:52:11 +00:00
|
|
|
REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
|
1999-04-30 05:42:06 +00:00
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
if (r.length < msg->reserved)
|
|
|
|
return (ISC_R_NOSPACE);
|
|
|
|
|
1999-04-30 07:53:07 +00:00
|
|
|
result = dns_compress_init(&msg->cctx, -1, msg->mctx);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-04-30 07:53:07 +00:00
|
|
|
return (result);
|
1999-05-14 23:19:12 +00:00
|
|
|
msg->need_cctx_cleanup = 1;
|
1999-04-30 07:53:07 +00:00
|
|
|
|
1999-04-30 05:42:06 +00:00
|
|
|
/*
|
|
|
|
* Reserve enough space for the header in this buffer.
|
|
|
|
*/
|
1999-05-14 17:52:11 +00:00
|
|
|
isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
|
1999-04-30 05:42:06 +00:00
|
|
|
|
1999-04-30 21:52:40 +00:00
|
|
|
msg->buffer = buffer;
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-30 05:42:06 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
|
1999-04-30 05:42:06 +00:00
|
|
|
isc_region_t r, rn;
|
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-30 05:42:06 +00:00
|
|
|
REQUIRE(buffer != NULL);
|
|
|
|
REQUIRE(msg->buffer != NULL);
|
|
|
|
|
|
|
|
/*
|
2000-05-08 14:38:29 +00:00
|
|
|
* Ensure that the new buffer is empty, and has enough space to
|
1999-04-30 05:42:06 +00:00
|
|
|
* hold the current contents.
|
|
|
|
*/
|
|
|
|
isc_buffer_clear(buffer);
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_availableregion(buffer, &rn);
|
|
|
|
isc_buffer_usedregion(msg->buffer, &r);
|
1999-05-14 17:52:11 +00:00
|
|
|
REQUIRE(rn.length > r.length);
|
1999-04-30 05:42:06 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the contents from the old to the new buffer.
|
|
|
|
*/
|
|
|
|
isc_buffer_add(buffer, r.length);
|
|
|
|
memcpy(rn.base, r.base, r.length);
|
|
|
|
|
|
|
|
msg->buffer = buffer;
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-11-25 01:58:16 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-11-25 01:58:16 +00:00
|
|
|
REQUIRE(space <= msg->reserved);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
msg->reserved -= space;
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
|
1999-04-27 02:24:11 +00:00
|
|
|
isc_region_t r;
|
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-27 02:24:11 +00:00
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
if (msg->buffer != NULL) {
|
|
|
|
isc_buffer_availableregion(msg->buffer, &r);
|
|
|
|
if (r.length < (space + msg->reserved))
|
|
|
|
return (ISC_R_NOSPACE);
|
|
|
|
}
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
msg->reserved += space;
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-12-22 03:22:59 +00:00
|
|
|
static inline isc_boolean_t
|
2000-05-08 14:38:29 +00:00
|
|
|
wrong_priority(dns_rdataset_t *rds, int pass) {
|
1999-12-22 03:22:59 +00:00
|
|
|
int pass_needed;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we are not rendering class IN, this ordering is bogus.
|
|
|
|
*/
|
|
|
|
if (rds->rdclass != dns_rdataclass_in)
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
|
|
|
switch (rds->type) {
|
|
|
|
case dns_rdatatype_a:
|
|
|
|
case dns_rdatatype_aaaa:
|
|
|
|
case dns_rdatatype_a6:
|
|
|
|
pass_needed = 3;
|
|
|
|
break;
|
|
|
|
case dns_rdatatype_sig:
|
|
|
|
case dns_rdatatype_key:
|
|
|
|
pass_needed = 2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pass_needed = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pass_needed >= pass)
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
|
|
|
return (ISC_TRUE);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-04-30 06:37:35 +00:00
|
|
|
dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
|
1999-12-22 03:22:59 +00:00
|
|
|
unsigned int options)
|
1999-04-27 02:24:11 +00:00
|
|
|
{
|
1999-04-30 06:37:35 +00:00
|
|
|
dns_namelist_t *section;
|
1999-04-30 07:53:07 +00:00
|
|
|
dns_name_t *name, *next_name;
|
|
|
|
dns_rdataset_t *rdataset, *next_rdataset;
|
|
|
|
unsigned int count, total;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-05-21 00:48:59 +00:00
|
|
|
isc_buffer_t st; /* for rollbacks */
|
1999-12-22 03:22:59 +00:00
|
|
|
int pass;
|
1999-04-30 06:37:35 +00:00
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-30 05:42:06 +00:00
|
|
|
REQUIRE(msg->buffer != NULL);
|
1999-04-30 06:37:35 +00:00
|
|
|
REQUIRE(VALID_NAMED_SECTION(sectionid));
|
|
|
|
|
|
|
|
section = &msg->sections[sectionid];
|
1999-04-30 07:53:07 +00:00
|
|
|
|
1999-12-22 03:22:59 +00:00
|
|
|
if ((sectionid == DNS_SECTION_ADDITIONAL)
|
|
|
|
&& (options & DNS_MESSAGERENDER_ORDERED) == 0)
|
|
|
|
pass = 3;
|
|
|
|
else
|
|
|
|
pass = 1;
|
1999-04-30 23:37:23 +00:00
|
|
|
|
1999-04-30 07:53:07 +00:00
|
|
|
/*
|
1999-04-30 23:04:29 +00:00
|
|
|
* Shrink the space in the buffer by the reserved amount.
|
1999-04-30 07:53:07 +00:00
|
|
|
*/
|
1999-04-30 23:04:29 +00:00
|
|
|
msg->buffer->length -= msg->reserved;
|
|
|
|
|
1999-04-30 22:35:49 +00:00
|
|
|
total = 0;
|
|
|
|
|
1999-12-22 03:22:59 +00:00
|
|
|
do {
|
|
|
|
name = ISC_LIST_HEAD(*section);
|
2000-05-30 23:47:56 +00:00
|
|
|
if (name == NULL) {
|
|
|
|
msg->buffer->length += msg->reserved;
|
|
|
|
msg->counts[sectionid] += total;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-05-30 23:47:56 +00:00
|
|
|
}
|
1999-04-30 07:53:07 +00:00
|
|
|
|
1999-12-22 03:22:59 +00:00
|
|
|
while (name != NULL) {
|
|
|
|
next_name = ISC_LIST_NEXT(name, link);
|
1999-04-30 22:35:49 +00:00
|
|
|
|
1999-12-22 03:22:59 +00:00
|
|
|
rdataset = ISC_LIST_HEAD(name->list);
|
|
|
|
while (rdataset != NULL) {
|
|
|
|
next_rdataset = ISC_LIST_NEXT(rdataset, link);
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
if ((rdataset->attributes &
|
|
|
|
DNS_RDATASETATTR_RENDERED) != 0)
|
1999-12-22 03:22:59 +00:00
|
|
|
goto next;
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
if (((options & DNS_MESSAGERENDER_ORDERED)
|
|
|
|
== 0)
|
1999-12-22 03:22:59 +00:00
|
|
|
&& (sectionid == DNS_SECTION_ADDITIONAL)
|
|
|
|
&& wrong_priority(rdataset, pass))
|
|
|
|
goto next;
|
|
|
|
|
|
|
|
st = *(msg->buffer);
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
result = dns_rdataset_towire(rdataset, name,
|
|
|
|
&msg->cctx,
|
2000-05-08 14:38:29 +00:00
|
|
|
msg->buffer,
|
|
|
|
&count);
|
1999-12-22 03:22:59 +00:00
|
|
|
|
|
|
|
total += count;
|
|
|
|
|
|
|
|
/*
|
2000-05-08 14:38:29 +00:00
|
|
|
* If out of space, record stats on what we
|
|
|
|
* rendered so far, and return that status.
|
1999-12-22 03:22:59 +00:00
|
|
|
*
|
|
|
|
* XXXMLG Need to change this when
|
|
|
|
* dns_rdataset_towire() can render partial
|
2000-05-08 14:38:29 +00:00
|
|
|
* sets starting at some arbitary point in the
|
|
|
|
* set. This will include setting a bit in the
|
|
|
|
* rdataset to indicate that a partial
|
|
|
|
* rendering was done, and some state saved
|
|
|
|
* somewhere (probably in the message struct)
|
1999-12-22 03:22:59 +00:00
|
|
|
* to indicate where to continue from.
|
|
|
|
*/
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-12-22 03:22:59 +00:00
|
|
|
INSIST(st.used < 65536);
|
|
|
|
dns_compress_rollback(&msg->cctx,
|
2000-05-08 14:38:29 +00:00
|
|
|
(isc_uint16_t)st.used);
|
1999-12-22 03:22:59 +00:00
|
|
|
*(msg->buffer) = st; /* rollback */
|
|
|
|
msg->buffer->length += msg->reserved;
|
|
|
|
msg->counts[sectionid] += total;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-05-08 14:38:29 +00:00
|
|
|
* If we have rendered pending data, ensure
|
|
|
|
* that the AD bit is not set.
|
1999-12-22 03:22:59 +00:00
|
|
|
*/
|
2000-05-18 01:40:56 +00:00
|
|
|
if (rdataset->trust == dns_trust_pending &&
|
1999-12-22 03:22:59 +00:00
|
|
|
(sectionid == DNS_SECTION_ANSWER ||
|
|
|
|
sectionid == DNS_SECTION_AUTHORITY))
|
|
|
|
msg->flags &= ~DNS_MESSAGEFLAG_AD;
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
rdataset->attributes |=
|
|
|
|
DNS_RDATASETATTR_RENDERED;
|
1999-12-22 03:22:59 +00:00
|
|
|
|
|
|
|
next:
|
|
|
|
rdataset = next_rdataset;
|
1999-04-30 21:09:19 +00:00
|
|
|
}
|
1999-04-30 07:53:07 +00:00
|
|
|
|
1999-12-22 03:22:59 +00:00
|
|
|
name = next_name;
|
1999-04-30 07:53:07 +00:00
|
|
|
}
|
1999-12-22 03:22:59 +00:00
|
|
|
} while (--pass != 0);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-04-30 23:04:29 +00:00
|
|
|
msg->buffer->length += msg->reserved;
|
1999-04-30 21:52:40 +00:00
|
|
|
msg->counts[sectionid] += total;
|
1999-04-30 22:35:49 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-08-20 18:56:24 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
|
1999-05-12 19:32:13 +00:00
|
|
|
isc_uint16_t tmp;
|
1999-08-20 18:56:24 +00:00
|
|
|
isc_region_t r;
|
1999-04-30 21:52:40 +00:00
|
|
|
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-08-20 18:56:24 +00:00
|
|
|
REQUIRE(target != NULL);
|
1999-04-30 05:42:06 +00:00
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_availableregion(target, &r);
|
1999-08-20 18:56:24 +00:00
|
|
|
REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
|
1999-04-30 21:52:40 +00:00
|
|
|
|
1999-08-20 18:56:24 +00:00
|
|
|
isc_buffer_putuint16(target, msg->id);
|
1999-04-30 21:52:40 +00:00
|
|
|
|
1999-05-12 19:32:13 +00:00
|
|
|
tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
|
|
|
|
& DNS_MESSAGE_OPCODE_MASK);
|
1999-09-02 01:52:31 +00:00
|
|
|
tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
|
1999-05-12 19:32:13 +00:00
|
|
|
tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
|
1999-04-30 21:52:40 +00:00
|
|
|
|
1999-10-17 22:31:03 +00:00
|
|
|
INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
|
|
|
|
msg->counts[DNS_SECTION_ANSWER] < 65536 &&
|
|
|
|
msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
|
2000-03-29 01:32:22 +00:00
|
|
|
msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
|
1999-10-17 22:31:03 +00:00
|
|
|
|
1999-08-20 18:56:24 +00:00
|
|
|
isc_buffer_putuint16(target, tmp);
|
1999-10-17 22:31:03 +00:00
|
|
|
isc_buffer_putuint16(target,
|
2000-05-08 14:38:29 +00:00
|
|
|
(isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
|
1999-10-17 22:31:03 +00:00
|
|
|
isc_buffer_putuint16(target,
|
2000-05-08 14:38:29 +00:00
|
|
|
(isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
|
1999-10-17 22:31:03 +00:00
|
|
|
isc_buffer_putuint16(target,
|
2000-05-08 14:38:29 +00:00
|
|
|
(isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
|
2000-03-29 01:32:22 +00:00
|
|
|
isc_buffer_putuint16(target,
|
2000-05-08 14:38:29 +00:00
|
|
|
(isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
|
1999-08-20 18:56:24 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_renderend(dns_message_t *msg) {
|
1999-08-20 18:56:24 +00:00
|
|
|
isc_buffer_t tmpbuf;
|
|
|
|
isc_region_t r;
|
|
|
|
int result;
|
1999-09-02 01:52:31 +00:00
|
|
|
unsigned int count;
|
1999-08-20 18:56:24 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(msg->buffer != NULL);
|
|
|
|
|
1999-09-02 01:52:31 +00:00
|
|
|
if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
|
|
|
|
/*
|
|
|
|
* We have an extended rcode but are not using EDNS.
|
|
|
|
*/
|
|
|
|
return (DNS_R_FORMERR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we've got an OPT record, render it.
|
|
|
|
*/
|
|
|
|
if (msg->opt != NULL) {
|
1999-11-25 01:58:16 +00:00
|
|
|
dns_message_renderrelease(msg, msg->opt_reserved);
|
|
|
|
msg->opt_reserved = 0;
|
1999-09-02 01:52:31 +00:00
|
|
|
/*
|
|
|
|
* Set the extended rcode.
|
|
|
|
*/
|
|
|
|
msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
|
|
|
|
msg->opt->ttl |= ((msg->rcode << 20) &
|
|
|
|
DNS_MESSAGE_EDNSRCODE_MASK);
|
|
|
|
/*
|
|
|
|
* Render.
|
|
|
|
*/
|
|
|
|
count = 0;
|
|
|
|
result = dns_rdataset_towire(msg->opt, dns_rootname,
|
|
|
|
&msg->cctx, msg->buffer, &count);
|
|
|
|
msg->counts[DNS_SECTION_ADDITIONAL] += count;
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
/*
|
|
|
|
* If we're adding a TSIG or SIG(0) to a truncated message,
|
|
|
|
* clear all rdatasets from the message except for the question
|
|
|
|
* before adding the TSIG or SIG(0).
|
|
|
|
*/
|
|
|
|
if ((msg->tsigkey != NULL || msg->sig0key != NULL) &&
|
|
|
|
(msg->flags & DNS_MESSAGEFLAG_TC) != 0)
|
|
|
|
{
|
|
|
|
isc_buffer_t *buf;
|
|
|
|
|
|
|
|
msgresetnames(msg, DNS_SECTION_ANSWER);
|
|
|
|
buf = msg->buffer;
|
|
|
|
dns_message_renderreset(msg);
|
|
|
|
msg->buffer = buf;
|
|
|
|
isc_buffer_clear(msg->buffer);
|
|
|
|
isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
|
|
|
|
dns_compress_rollback(&msg->cctx, 0);
|
|
|
|
result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
|
|
|
|
0);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're adding a TSIG record, generate and render it.
|
|
|
|
*/
|
1999-11-02 19:59:04 +00:00
|
|
|
if (msg->tsigkey != NULL) {
|
2000-05-30 23:14:57 +00:00
|
|
|
dns_message_renderrelease(msg, msg->sig_reserved);
|
|
|
|
msg->sig_reserved = 0;
|
1999-08-20 18:56:24 +00:00
|
|
|
result = dns_tsig_sign(msg);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-08-20 18:56:24 +00:00
|
|
|
return (result);
|
2000-03-29 01:32:22 +00:00
|
|
|
count = 0;
|
2000-05-31 23:58:35 +00:00
|
|
|
result = dns_rdataset_towire(msg->tsig, msg->tsigname,
|
2000-03-29 01:32:22 +00:00
|
|
|
&msg->cctx, msg->buffer, &count);
|
|
|
|
msg->counts[DNS_SECTION_ADDITIONAL] += count;
|
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-11-02 19:59:04 +00:00
|
|
|
return (result);
|
2000-05-31 23:58:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're adding a SIG(0) record, generate and render it.
|
|
|
|
*/
|
|
|
|
if (msg->sig0key != NULL) {
|
2000-05-30 23:14:57 +00:00
|
|
|
dns_message_renderrelease(msg, msg->sig_reserved);
|
|
|
|
msg->sig_reserved = 0;
|
1999-11-02 19:59:04 +00:00
|
|
|
result = dns_dnssec_signmessage(msg, msg->sig0key);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-11-02 19:59:04 +00:00
|
|
|
return (result);
|
2000-03-29 01:32:22 +00:00
|
|
|
count = 0;
|
2000-05-23 23:35:54 +00:00
|
|
|
/*
|
|
|
|
* Note: dns_rootname is used here, not msg->sig0name, since
|
|
|
|
* the owner name of a SIG(0) is irrelevant, and will not
|
|
|
|
* be set in a message being rendered.
|
|
|
|
*/
|
2000-03-29 01:32:22 +00:00
|
|
|
result = dns_rdataset_towire(msg->sig0, dns_rootname,
|
|
|
|
&msg->cctx, msg->buffer, &count);
|
|
|
|
msg->counts[DNS_SECTION_ADDITIONAL] += count;
|
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-08-20 18:56:24 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_usedregion(msg->buffer, &r);
|
|
|
|
isc_buffer_init(&tmpbuf, r.base, r.length);
|
1999-08-20 18:56:24 +00:00
|
|
|
|
|
|
|
dns_message_renderheader(msg, &tmpbuf);
|
1999-04-30 21:52:40 +00:00
|
|
|
|
1999-04-30 05:42:06 +00:00
|
|
|
msg->buffer = NULL; /* forget about this buffer only on success XXX */
|
1999-04-27 02:24:11 +00:00
|
|
|
|
1999-04-30 07:53:07 +00:00
|
|
|
dns_compress_invalidate(&msg->cctx);
|
1999-05-14 23:19:12 +00:00
|
|
|
msg->need_cctx_cleanup = 0;
|
1999-04-30 07:53:07 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
2000-02-24 19:37:28 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_renderreset(dns_message_t *msg) {
|
2000-02-24 19:37:28 +00:00
|
|
|
unsigned int i;
|
|
|
|
dns_name_t *name;
|
|
|
|
dns_rdataset_t *rds;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reset the message so that it may be rendered again.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
|
|
|
|
|
2000-03-16 06:51:04 +00:00
|
|
|
msg->buffer = NULL;
|
|
|
|
|
2000-02-24 19:37:28 +00:00
|
|
|
for (i = 0; i < DNS_SECTION_MAX; i++) {
|
|
|
|
msg->cursors[i] = NULL;
|
|
|
|
msg->counts[i] = 0;
|
|
|
|
for (name = ISC_LIST_HEAD(msg->sections[i]);
|
|
|
|
name != NULL;
|
|
|
|
name = ISC_LIST_NEXT(name, link)) {
|
|
|
|
for (rds = ISC_LIST_HEAD(name->list);
|
|
|
|
rds != NULL;
|
|
|
|
rds = ISC_LIST_NEXT(rds, link)) {
|
|
|
|
rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_firstname(dns_message_t *msg, dns_section_t section) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-27 02:24:11 +00:00
|
|
|
REQUIRE(VALID_NAMED_SECTION(section));
|
|
|
|
|
|
|
|
msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
|
|
|
|
|
|
|
|
if (msg->cursors[section] == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMORE);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_nextname(dns_message_t *msg, dns_section_t section) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-27 02:24:11 +00:00
|
|
|
REQUIRE(VALID_NAMED_SECTION(section));
|
|
|
|
REQUIRE(msg->cursors[section] != NULL);
|
|
|
|
|
|
|
|
msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
|
|
|
|
|
|
|
|
if (msg->cursors[section] == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMORE);
|
1999-04-27 02:24:11 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_message_currentname(dns_message_t *msg, dns_section_t section,
|
|
|
|
dns_name_t **name)
|
|
|
|
{
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-04-27 02:24:11 +00:00
|
|
|
REQUIRE(VALID_NAMED_SECTION(section));
|
1999-04-30 00:17:15 +00:00
|
|
|
REQUIRE(name != NULL && *name == NULL);
|
1999-04-27 02:24:11 +00:00
|
|
|
REQUIRE(msg->cursors[section] != NULL);
|
|
|
|
|
|
|
|
*name = msg->cursors[section];
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-04-27 02:24:11 +00:00
|
|
|
dns_message_findname(dns_message_t *msg, dns_section_t section,
|
|
|
|
dns_name_t *target, dns_rdatatype_t type,
|
1999-08-31 22:14:06 +00:00
|
|
|
dns_rdatatype_t covers, dns_name_t **name,
|
|
|
|
dns_rdataset_t **rdataset)
|
1999-04-27 02:24:11 +00:00
|
|
|
{
|
1999-04-30 06:13:07 +00:00
|
|
|
dns_name_t *foundname;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-10-20 23:28:10 +00:00
|
|
|
unsigned int attributes;
|
|
|
|
dns_rdatatype_t atype;
|
1999-04-27 02:24:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX These requirements are probably too intensive, especially
|
|
|
|
* where things can be NULL, but as they are they ensure that if
|
|
|
|
* something is NON-NULL, indicating that the caller expects it
|
|
|
|
* to be filled in, that we can in fact fill it in.
|
|
|
|
*/
|
|
|
|
REQUIRE(msg != NULL);
|
|
|
|
REQUIRE(VALID_SECTION(section));
|
|
|
|
REQUIRE(target != NULL);
|
|
|
|
if (name != NULL)
|
|
|
|
REQUIRE(*name == NULL);
|
|
|
|
if (type == dns_rdatatype_any) {
|
|
|
|
REQUIRE(rdataset == NULL);
|
|
|
|
} else {
|
|
|
|
if (rdataset != NULL)
|
|
|
|
REQUIRE(*rdataset == NULL);
|
|
|
|
}
|
|
|
|
|
1999-10-20 23:28:10 +00:00
|
|
|
/*
|
|
|
|
* Figure out what attributes we should look for.
|
|
|
|
*/
|
|
|
|
if (type == dns_rdatatype_sig)
|
|
|
|
atype = covers;
|
|
|
|
else
|
|
|
|
atype = type;
|
|
|
|
attributes = 0;
|
|
|
|
if (atype == dns_rdatatype_cname)
|
|
|
|
attributes = DNS_NAMEATTR_CNAME;
|
|
|
|
else if (atype == dns_rdatatype_cname)
|
|
|
|
attributes = DNS_NAMEATTR_DNAME;
|
|
|
|
|
1999-04-30 06:13:07 +00:00
|
|
|
/*
|
|
|
|
* Search through, looking for the name.
|
|
|
|
*/
|
1999-10-20 23:28:10 +00:00
|
|
|
result = findname(&foundname, target, attributes,
|
|
|
|
&msg->sections[section]);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOTFOUND)
|
1999-04-30 06:37:35 +00:00
|
|
|
return (DNS_R_NXDOMAIN);
|
2000-04-06 22:03:35 +00:00
|
|
|
else if (result != ISC_R_SUCCESS)
|
1999-04-30 06:13:07 +00:00
|
|
|
return (result);
|
|
|
|
|
|
|
|
if (name != NULL)
|
|
|
|
*name = foundname;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* And now look for the type.
|
|
|
|
*/
|
1999-06-03 19:03:48 +00:00
|
|
|
if (type == dns_rdatatype_any)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-04-30 06:13:07 +00:00
|
|
|
|
1999-09-09 01:10:53 +00:00
|
|
|
result = dns_message_findtype(foundname, type, covers, rdataset);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOTFOUND)
|
|
|
|
return (DNS_R_NXRRSET);
|
1999-04-30 06:37:35 +00:00
|
|
|
|
1999-04-30 06:13:07 +00:00
|
|
|
return (result);
|
1999-04-27 02:24:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_message_movename(dns_message_t *msg, dns_name_t *name,
|
|
|
|
dns_section_t fromsection,
|
|
|
|
dns_section_t tosection)
|
|
|
|
{
|
|
|
|
REQUIRE(msg != NULL);
|
1999-05-14 17:52:11 +00:00
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
|
1999-04-27 02:24:11 +00:00
|
|
|
REQUIRE(name != NULL);
|
|
|
|
REQUIRE(VALID_NAMED_SECTION(fromsection));
|
|
|
|
REQUIRE(VALID_NAMED_SECTION(tosection));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unlink the name from the old section
|
|
|
|
*/
|
|
|
|
ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
|
|
|
|
ISC_LIST_APPEND(msg->sections[tosection], name, link);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_message_addname(dns_message_t *msg, dns_name_t *name,
|
|
|
|
dns_section_t section)
|
|
|
|
{
|
|
|
|
REQUIRE(msg != NULL);
|
1999-05-14 17:52:11 +00:00
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
|
1999-04-27 02:24:11 +00:00
|
|
|
REQUIRE(name != NULL);
|
|
|
|
REQUIRE(VALID_NAMED_SECTION(section));
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(msg->sections[section], name, link);
|
|
|
|
}
|
1999-05-14 22:22:49 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(item != NULL && *item == NULL);
|
|
|
|
|
1999-09-10 02:48:32 +00:00
|
|
|
*item = isc_mempool_get(msg->namepool);
|
1999-05-14 22:22:49 +00:00
|
|
|
if (*item == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-05-14 22:22:49 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-05-14 22:22:49 +00:00
|
|
|
}
|
|
|
|
|
1999-09-10 02:48:32 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
|
1999-09-10 02:48:32 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(item != NULL && *item != NULL);
|
|
|
|
|
|
|
|
isc_mempool_put(msg->namepool, *item);
|
|
|
|
*item = NULL;
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(item != NULL && *item == NULL);
|
|
|
|
|
|
|
|
*item = newrdata(msg);
|
|
|
|
if (*item == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-05-14 22:22:49 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-05-14 22:22:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(item != NULL && *item == NULL);
|
|
|
|
|
1999-09-11 01:35:55 +00:00
|
|
|
*item = isc_mempool_get(msg->rdspool);
|
1999-05-14 22:22:49 +00:00
|
|
|
if (*item == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-05-14 22:22:49 +00:00
|
|
|
|
1999-11-04 06:59:59 +00:00
|
|
|
dns_rdataset_init(*item);
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-05-14 22:22:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(item != NULL && *item == NULL);
|
|
|
|
|
|
|
|
*item = newrdatalist(msg);
|
|
|
|
if (*item == NULL)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1999-05-14 22:22:49 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-05-14 22:22:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(item != NULL && *item != NULL);
|
|
|
|
|
|
|
|
releaserdata(msg, *item);
|
|
|
|
*item = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(item != NULL && *item != NULL);
|
|
|
|
|
1999-11-02 21:29:13 +00:00
|
|
|
REQUIRE(!dns_rdataset_isassociated(*item));
|
1999-09-11 01:35:55 +00:00
|
|
|
isc_mempool_put(msg->rdspool, *item);
|
1999-05-14 22:22:49 +00:00
|
|
|
*item = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
|
1999-07-24 01:09:04 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
1999-05-14 22:22:49 +00:00
|
|
|
REQUIRE(item != NULL && *item != NULL);
|
|
|
|
|
|
|
|
releaserdatalist(msg, *item);
|
|
|
|
*item = NULL;
|
|
|
|
}
|
1999-06-25 01:05:27 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-06-25 01:05:27 +00:00
|
|
|
dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
|
|
|
|
unsigned int *flagsp)
|
|
|
|
{
|
|
|
|
isc_region_t r;
|
|
|
|
isc_buffer_t buffer;
|
|
|
|
dns_messageid_t id;
|
|
|
|
unsigned int flags;
|
|
|
|
|
|
|
|
REQUIRE(source != NULL);
|
|
|
|
|
|
|
|
buffer = *source;
|
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_remainingregion(&buffer, &r);
|
1999-06-25 01:05:27 +00:00
|
|
|
if (r.length < DNS_MESSAGE_HEADERLEN)
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTEDEND);
|
1999-06-25 01:05:27 +00:00
|
|
|
|
1999-07-12 23:46:37 +00:00
|
|
|
id = isc_buffer_getuint16(&buffer);
|
|
|
|
flags = isc_buffer_getuint16(&buffer);
|
1999-06-25 01:05:27 +00:00
|
|
|
flags &= DNS_MESSAGE_FLAG_MASK;
|
|
|
|
|
|
|
|
if (flagsp != NULL)
|
|
|
|
*flagsp = flags;
|
|
|
|
if (idp != NULL)
|
|
|
|
*idp = id;
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-06-25 01:05:27 +00:00
|
|
|
}
|
1999-07-24 01:09:04 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-07-24 01:09:04 +00:00
|
|
|
dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
|
|
|
|
unsigned int first_section;
|
2000-05-30 23:14:57 +00:00
|
|
|
isc_result_t result;
|
1999-07-24 01:09:04 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
|
|
|
|
|
|
|
|
if (!msg->header_ok)
|
|
|
|
return (DNS_R_FORMERR);
|
1999-12-15 07:28:51 +00:00
|
|
|
if (msg->opcode != dns_opcode_query &&
|
|
|
|
msg->opcode != dns_opcode_notify)
|
1999-07-29 01:26:53 +00:00
|
|
|
want_question_section = ISC_FALSE;
|
|
|
|
if (want_question_section) {
|
|
|
|
if (!msg->question_ok)
|
|
|
|
return (DNS_R_FORMERR);
|
1999-07-24 01:09:04 +00:00
|
|
|
first_section = DNS_SECTION_ANSWER;
|
1999-07-29 01:26:53 +00:00
|
|
|
} else
|
1999-07-24 01:09:04 +00:00
|
|
|
first_section = DNS_SECTION_QUESTION;
|
|
|
|
msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
|
|
|
|
msgresetnames(msg, first_section);
|
1999-11-25 01:58:16 +00:00
|
|
|
msgresetopt(msg);
|
2000-05-30 23:14:57 +00:00
|
|
|
msgresetsigs(msg, ISC_TRUE);
|
1999-07-24 01:09:04 +00:00
|
|
|
msginitprivate(msg);
|
|
|
|
/*
|
|
|
|
* We now clear most flags and then set QR, ensuring that the
|
|
|
|
* reply's flags will be in a reasonable state.
|
|
|
|
*/
|
|
|
|
msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
|
|
|
|
msg->flags |= DNS_MESSAGEFLAG_QR;
|
|
|
|
|
1999-08-20 18:56:24 +00:00
|
|
|
/*
|
2000-05-30 23:14:57 +00:00
|
|
|
* This saves the query TSIG status, if the query was signed, and
|
|
|
|
* reserves space in the reply for the TSIG.
|
1999-08-20 18:56:24 +00:00
|
|
|
*/
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->querytsig != NULL) {
|
2000-05-30 23:14:57 +00:00
|
|
|
unsigned int otherlen = 0;
|
1999-08-20 18:56:24 +00:00
|
|
|
msg->querytsigstatus = msg->tsigstatus;
|
|
|
|
msg->tsigstatus = dns_rcode_noerror;
|
2000-05-30 23:14:57 +00:00
|
|
|
if (msg->querytsigstatus == dns_tsigerror_badtime)
|
|
|
|
otherlen = 6;
|
|
|
|
msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
|
|
|
|
result = dns_message_renderreserve(msg, msg->sig_reserved);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
msg->sig_reserved = 0;
|
|
|
|
return (result);
|
|
|
|
}
|
1999-08-20 18:56:24 +00:00
|
|
|
}
|
1999-11-02 22:58:29 +00:00
|
|
|
if (msg->saved != NULL) {
|
|
|
|
msg->query = msg->saved;
|
|
|
|
msg->saved = NULL;
|
|
|
|
}
|
1999-08-20 18:56:24 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-07-24 01:09:04 +00:00
|
|
|
}
|
1999-09-02 01:52:31 +00:00
|
|
|
|
|
|
|
dns_rdataset_t *
|
|
|
|
dns_message_getopt(dns_message_t *msg) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the OPT record for 'msg'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
|
|
|
|
return (msg->opt);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-09-02 01:52:31 +00:00
|
|
|
dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-09-02 01:52:31 +00:00
|
|
|
dns_rdata_t rdata;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the OPT record for 'msg'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The space required for an OPT record is:
|
|
|
|
*
|
|
|
|
* 1 byte for the name
|
|
|
|
* 2 bytes for the type
|
|
|
|
* 2 bytes for the class
|
|
|
|
* 4 bytes for the ttl
|
|
|
|
* 2 bytes for the rdata length
|
|
|
|
* ---------------------------------
|
|
|
|
* 11 bytes
|
|
|
|
*
|
|
|
|
* plus the length of the rdata.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(opt->type == dns_rdatatype_opt);
|
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
|
|
|
|
REQUIRE(msg->buffer != NULL);
|
|
|
|
REQUIRE(msg->state == DNS_SECTION_ANY);
|
|
|
|
|
1999-11-25 01:58:16 +00:00
|
|
|
msgresetopt(msg);
|
1999-09-02 01:52:31 +00:00
|
|
|
|
|
|
|
result = dns_rdataset_first(opt);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
dns_rdataset_current(opt, &rdata);
|
1999-11-25 01:58:16 +00:00
|
|
|
msg->opt_reserved = 11 + rdata.length;
|
|
|
|
result = dns_message_renderreserve(msg, msg->opt_reserved);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
msg->opt_reserved = 0;
|
1999-09-02 01:52:31 +00:00
|
|
|
return (result);
|
1999-11-25 01:58:16 +00:00
|
|
|
}
|
1999-09-02 01:52:31 +00:00
|
|
|
|
|
|
|
msg->opt = opt;
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-09-02 01:52:31 +00:00
|
|
|
}
|
1999-09-10 02:48:32 +00:00
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
dns_rdataset_t *
|
|
|
|
dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the TSIG record and owner for 'msg'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
2000-06-01 01:30:55 +00:00
|
|
|
REQUIRE(owner == NULL || *owner == NULL);
|
2000-03-29 01:32:22 +00:00
|
|
|
|
2000-06-01 01:30:55 +00:00
|
|
|
if (owner != NULL)
|
|
|
|
*owner = msg->tsigname;
|
2000-05-31 23:58:35 +00:00
|
|
|
return (msg->tsig);
|
2000-03-29 01:32:22 +00:00
|
|
|
}
|
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
isc_result_t
|
2000-05-26 00:16:46 +00:00
|
|
|
dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
|
2000-05-30 23:14:57 +00:00
|
|
|
isc_result_t result;
|
2000-05-26 00:16:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the TSIG key for 'msg'
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
2000-05-30 23:14:57 +00:00
|
|
|
REQUIRE(msg->state == DNS_SECTION_ANY);
|
|
|
|
REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
|
2000-05-26 00:16:46 +00:00
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
if (key != NULL) {
|
2000-05-26 00:16:46 +00:00
|
|
|
dns_tsigkey_attach(key, &msg->tsigkey);
|
2000-05-30 23:14:57 +00:00
|
|
|
if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
|
|
|
|
msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
|
|
|
|
result = dns_message_renderreserve(msg,
|
|
|
|
msg->sig_reserved);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
msg->sig_reserved = 0;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
2000-05-26 00:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dns_tsigkey_t *
|
|
|
|
dns_message_gettsigkey(dns_message_t *msg) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the TSIG key for 'msg'
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
|
|
|
|
return (msg->tsigkey);
|
|
|
|
}
|
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
|
|
|
|
dns_rdata_t *rdata = NULL;
|
|
|
|
dns_rdatalist_t *list = NULL;
|
|
|
|
dns_rdataset_t *set = NULL;
|
|
|
|
isc_buffer_t *buf = NULL;
|
|
|
|
isc_region_t r;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
2000-05-31 23:58:35 +00:00
|
|
|
REQUIRE(msg->querytsig == NULL);
|
2000-05-30 23:14:57 +00:00
|
|
|
|
|
|
|
if (querytsig == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
result = dns_message_gettemprdata(msg, &rdata);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
result = dns_message_gettemprdatalist(msg, &list);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
result = dns_message_gettemprdataset(msg, &set);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
isc_buffer_usedregion(querytsig, &r);
|
|
|
|
result = isc_buffer_allocate(msg->mctx, &buf, r.length);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
isc_buffer_putmem(buf, r.base, r.length);
|
|
|
|
isc_buffer_usedregion(buf, &r);
|
|
|
|
dns_rdata_init(rdata);
|
|
|
|
dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
|
|
|
|
dns_message_takebuffer(msg, &buf);
|
|
|
|
ISC_LIST_INIT(list->rdata);
|
|
|
|
ISC_LIST_APPEND(list->rdata, rdata, link);
|
|
|
|
result = dns_rdatalist_tordataset(list, set);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto cleanup;
|
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
msg->querytsig = set;
|
2000-05-30 23:14:57 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (rdata != NULL)
|
|
|
|
dns_message_puttemprdata(msg, &rdata);
|
|
|
|
if (list != NULL)
|
|
|
|
dns_message_puttemprdatalist(msg, &list);
|
|
|
|
if (set != NULL)
|
|
|
|
dns_message_puttemprdataset(msg, &set);
|
|
|
|
return (ISC_R_NOMEMORY);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
|
|
|
|
isc_buffer_t **querytsig) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_t rdata;
|
|
|
|
isc_region_t r;
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(mctx != NULL);
|
|
|
|
REQUIRE(querytsig != NULL && *querytsig == NULL);
|
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->tsig == NULL)
|
2000-05-30 23:14:57 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
result = dns_rdataset_first(msg->tsig);
|
2000-05-30 23:14:57 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
2000-05-31 23:58:35 +00:00
|
|
|
dns_rdataset_current(msg->tsig, &rdata);
|
2000-05-30 23:14:57 +00:00
|
|
|
dns_rdata_toregion(&rdata, &r);
|
|
|
|
|
|
|
|
result = isc_buffer_allocate(mctx, querytsig, r.length);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
isc_buffer_putmem(*querytsig, r.base, r.length);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
dns_rdataset_t *
|
2000-05-23 23:35:54 +00:00
|
|
|
dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
|
2000-03-29 01:32:22 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the SIG(0) record for 'msg'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
2000-06-01 01:30:55 +00:00
|
|
|
REQUIRE(owner == NULL || *owner == NULL);
|
2000-03-29 01:32:22 +00:00
|
|
|
|
2000-06-01 01:30:55 +00:00
|
|
|
if (msg->sig0 != NULL && owner != NULL) {
|
2000-05-23 23:35:54 +00:00
|
|
|
/* If dns_message_getsig0 is called on a rendered message
|
|
|
|
* after the SIG(0) has been applied, we need to return the
|
|
|
|
* root name, not NULL.
|
|
|
|
*/
|
|
|
|
if (msg->sig0name == NULL)
|
|
|
|
*owner = dns_rootname;
|
|
|
|
else
|
|
|
|
*owner = msg->sig0name;
|
|
|
|
}
|
2000-06-01 01:30:55 +00:00
|
|
|
return (msg->sig0);
|
2000-03-29 01:32:22 +00:00
|
|
|
}
|
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
|
|
|
|
isc_region_t r;
|
|
|
|
unsigned int x;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the SIG(0) key for 'msg'
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The space required for an SIG(0) record is:
|
|
|
|
*
|
|
|
|
* 1 byte for the name
|
|
|
|
* 2 bytes for the type
|
|
|
|
* 2 bytes for the class
|
|
|
|
* 4 bytes for the ttl
|
|
|
|
* 2 bytes for the type covered
|
|
|
|
* 1 byte for the algorithm
|
|
|
|
* 1 bytes for the labels
|
|
|
|
* 4 bytes for the original ttl
|
|
|
|
* 4 bytes for the signature expiration
|
|
|
|
* 4 bytes for the signature inception
|
|
|
|
* 2 bytes for the key tag
|
|
|
|
* n bytes for the signer's name
|
|
|
|
* x bytes for the signature
|
|
|
|
* ---------------------------------
|
|
|
|
* 27 + n + x bytes
|
|
|
|
*/
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
|
|
|
|
REQUIRE(msg->buffer != NULL);
|
|
|
|
REQUIRE(msg->state == DNS_SECTION_ANY);
|
|
|
|
REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
|
|
|
|
|
|
|
|
msg->sig0key = key;
|
|
|
|
if (key != NULL) {
|
|
|
|
dns_name_toregion(dst_key_name(key), &r);
|
|
|
|
result = dst_key_sigsize(key, &x);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
msg->sig_reserved = 0;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
msg->sig_reserved = 27 + r.length + x;
|
|
|
|
result = dns_message_renderreserve(msg, msg->sig_reserved);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
msg->sig_reserved = 0;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
dst_key_t *
|
|
|
|
dns_message_getsig0key(dns_message_t *msg) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the SIG(0) key for 'msg'
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
|
|
|
|
return (msg->sig0key);
|
|
|
|
}
|
|
|
|
|
1999-09-10 02:48:32 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
|
1999-09-10 02:48:32 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(buffer != NULL);
|
|
|
|
REQUIRE(ISC_BUFFER_VALID(*buffer));
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(msg->cleanup, *buffer, link);
|
|
|
|
*buffer = NULL;
|
|
|
|
}
|
1999-10-27 22:25:55 +00:00
|
|
|
|
|
|
|
isc_result_t
|
1999-11-02 19:59:04 +00:00
|
|
|
dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
|
|
|
|
isc_region_t r;
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
2000-05-30 23:14:57 +00:00
|
|
|
dns_rdata_t rdata;
|
1999-10-28 14:18:52 +00:00
|
|
|
|
1999-10-27 22:25:55 +00:00
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(signer != NULL);
|
1999-11-02 19:59:04 +00:00
|
|
|
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
|
1999-10-27 22:25:55 +00:00
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->tsig == NULL && msg->sig0 == NULL)
|
1999-10-27 22:25:55 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
1999-10-28 14:18:52 +00:00
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
if (msg->verify_attempted == 0)
|
|
|
|
return (DNS_R_NOTVERIFIEDYET);
|
|
|
|
|
1999-11-02 19:59:04 +00:00
|
|
|
if (!dns_name_hasbuffer(signer)) {
|
|
|
|
isc_buffer_t *dynbuf = NULL;
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
|
1999-11-02 19:59:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
dns_name_setbuffer(signer, dynbuf);
|
|
|
|
dns_message_takebuffer(msg, &dynbuf);
|
|
|
|
}
|
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
if (msg->sig0 != NULL) {
|
2000-04-28 02:08:37 +00:00
|
|
|
dns_rdata_sig_t sig;
|
1999-11-02 19:59:04 +00:00
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
result = dns_rdataset_first(msg->sig0);
|
2000-04-20 19:51:39 +00:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
2000-03-29 01:32:22 +00:00
|
|
|
dns_rdataset_current(msg->sig0, &rdata);
|
1999-11-02 19:59:04 +00:00
|
|
|
|
2000-05-30 23:14:57 +00:00
|
|
|
result = dns_rdata_tostruct(&rdata, &sig, NULL);
|
1999-11-02 19:59:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2000-03-29 01:32:22 +00:00
|
|
|
if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
|
1999-11-02 19:59:04 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2000-03-13 19:27:35 +00:00
|
|
|
else
|
|
|
|
result = DNS_R_SIGINVALID;
|
1999-11-02 19:59:04 +00:00
|
|
|
dns_name_toregion(&sig.signer, &r);
|
|
|
|
dns_name_fromregion(signer, &r);
|
|
|
|
dns_rdata_freestruct(&sig);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dns_name_t *identity;
|
2000-05-30 23:14:57 +00:00
|
|
|
dns_rdata_any_tsig_t tsig;
|
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
result = dns_rdataset_first(msg->tsig);
|
2000-05-30 23:14:57 +00:00
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
2000-05-31 23:58:35 +00:00
|
|
|
dns_rdataset_current(msg->tsig, &rdata);
|
2000-05-30 23:14:57 +00:00
|
|
|
|
|
|
|
result = dns_rdata_tostruct(&rdata, &tsig, NULL);
|
2000-03-29 01:32:22 +00:00
|
|
|
if (msg->tsigstatus != dns_rcode_noerror)
|
1999-11-02 19:59:04 +00:00
|
|
|
result = DNS_R_TSIGVERIFYFAILURE;
|
2000-05-30 23:14:57 +00:00
|
|
|
else if (tsig.error != dns_rcode_noerror)
|
1999-11-02 19:59:04 +00:00
|
|
|
result = DNS_R_TSIGERRORSET;
|
|
|
|
else
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
identity = dns_tsigkey_identity(msg->tsigkey);
|
|
|
|
if (identity == NULL) {
|
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
result = DNS_R_NOIDENTITY;
|
|
|
|
identity = &msg->tsigkey->name;
|
|
|
|
}
|
|
|
|
dns_name_toregion(identity, &r);
|
|
|
|
dns_name_fromregion(signer, &r);
|
2000-05-30 23:14:57 +00:00
|
|
|
dns_rdata_freestruct(&tsig);
|
1999-11-02 19:59:04 +00:00
|
|
|
}
|
|
|
|
|
1999-10-28 14:18:52 +00:00
|
|
|
return (result);
|
1999-10-27 22:25:55 +00:00
|
|
|
}
|
2000-01-21 20:18:41 +00:00
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
|
2000-04-20 19:51:39 +00:00
|
|
|
isc_buffer_t b, msgb;
|
2000-01-21 20:18:41 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(view != NULL);
|
|
|
|
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
|
2000-01-21 20:18:41 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-04-20 19:51:39 +00:00
|
|
|
INSIST(msg->saved != NULL);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&msgb, msg->saved->base, msg->saved->length);
|
2000-04-20 19:51:39 +00:00
|
|
|
isc_buffer_add(&msgb, msg->saved->length);
|
2000-05-31 23:58:35 +00:00
|
|
|
if (msg->tsigkey != NULL || msg->tsig != NULL)
|
2000-04-20 19:51:39 +00:00
|
|
|
return (dns_view_checksig(view, &msgb, msg));
|
|
|
|
else {
|
|
|
|
dns_rdata_t rdata;
|
2000-04-28 02:08:37 +00:00
|
|
|
dns_rdata_sig_t sig;
|
2000-04-20 19:51:39 +00:00
|
|
|
dns_rdataset_t keyset;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
result = dns_rdataset_first(msg->sig0);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
dns_rdataset_current(msg->sig0, &rdata);
|
|
|
|
|
2000-05-23 00:23:42 +00:00
|
|
|
/*
|
|
|
|
* This can occur when the message is a dynamic update, since
|
|
|
|
* the rdata length checking is relaxed. This should not
|
|
|
|
* happen in a well-formed message, since the SIG(0) is only
|
|
|
|
* looked for in the additional section, and the dynamic update
|
|
|
|
* meta-records are in the prerequisite and update sections.
|
|
|
|
*/
|
2000-05-23 00:09:09 +00:00
|
|
|
if (rdata.length == 0)
|
|
|
|
return (ISC_R_UNEXPECTEDEND);
|
2000-05-23 00:23:42 +00:00
|
|
|
|
2000-04-20 19:51:39 +00:00
|
|
|
result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
dns_rdataset_init(&keyset);
|
|
|
|
result = dns_view_simplefind(view, &sig.signer,
|
|
|
|
dns_rdatatype_key, 0, 0,
|
|
|
|
ISC_FALSE, &keyset, NULL);
|
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
/* XXXBEW Should possibly create a fetch here */
|
|
|
|
result = DNS_R_KEYUNAUTHORIZED;
|
|
|
|
goto freesig;
|
|
|
|
} else if (keyset.trust < dns_trust_secure) {
|
|
|
|
/* XXXBEW Should call a validator here */
|
|
|
|
result = DNS_R_KEYUNAUTHORIZED;
|
|
|
|
goto freesig;
|
|
|
|
}
|
|
|
|
result = dns_rdataset_first(&keyset);
|
|
|
|
INSIST(result == ISC_R_SUCCESS);
|
|
|
|
for (;
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = dns_rdataset_next(&keyset))
|
|
|
|
{
|
|
|
|
dst_key_t *key = NULL;
|
|
|
|
|
|
|
|
dns_rdataset_current(&keyset, &rdata);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&b, rdata.data, rdata.length);
|
2000-04-20 19:51:39 +00:00
|
|
|
isc_buffer_add(&b, rdata.length);
|
|
|
|
|
2000-05-24 23:13:32 +00:00
|
|
|
result = dst_key_fromdns(&sig.signer, &b, view->mctx,
|
|
|
|
&key);
|
2000-04-20 19:51:39 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
continue;
|
|
|
|
if (dst_key_alg(key) != sig.algorithm ||
|
|
|
|
dst_key_id(key) != sig.keyid ||
|
|
|
|
!(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
|
|
|
|
dst_key_proto(key) == DNS_KEYPROTO_ANY))
|
|
|
|
{
|
2000-05-19 00:20:59 +00:00
|
|
|
dst_key_free(&key);
|
2000-04-20 19:51:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
result = dns_dnssec_verifymessage(&msgb, msg, key);
|
2000-05-19 00:20:59 +00:00
|
|
|
dst_key_free(&key);
|
2000-04-20 19:51:39 +00:00
|
|
|
if (result == ISC_R_SUCCESS)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (result == ISC_R_NOMORE)
|
|
|
|
result = DNS_R_KEYUNAUTHORIZED;
|
|
|
|
|
|
|
|
freesig:
|
2000-05-20 02:00:29 +00:00
|
|
|
if (dns_rdataset_isassociated(&keyset))
|
|
|
|
dns_rdataset_disassociate(&keyset);
|
2000-04-20 19:51:39 +00:00
|
|
|
dns_rdata_freestruct(&sig);
|
|
|
|
return (result);
|
|
|
|
}
|
2000-01-21 20:18:41 +00:00
|
|
|
}
|
2000-05-15 17:49:57 +00:00
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
|
2000-05-24 18:17:53 +00:00
|
|
|
dns_messagetextflag_t flags,
|
2000-05-15 17:49:57 +00:00
|
|
|
isc_buffer_t *target) {
|
|
|
|
dns_name_t *name, empty_name;
|
|
|
|
dns_rdataset_t *rdataset;
|
|
|
|
isc_result_t result;
|
2000-05-20 02:00:29 +00:00
|
|
|
isc_boolean_t no_rdata;
|
2000-05-24 18:17:53 +00:00
|
|
|
isc_boolean_t omit_final_dot;
|
2000-05-15 17:49:57 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(target != NULL);
|
|
|
|
REQUIRE(VALID_SECTION(section));
|
|
|
|
|
2000-05-24 18:17:53 +00:00
|
|
|
omit_final_dot = ISC_TF((flags & DNS_MESSAGETEXTFLAG_OMITDOT) != 0);
|
|
|
|
|
2000-05-22 21:22:06 +00:00
|
|
|
if (ISC_LIST_EMPTY(msg->sections[section]))
|
|
|
|
return ISC_R_SUCCESS;
|
|
|
|
|
2000-05-20 02:00:29 +00:00
|
|
|
if (section == DNS_SECTION_QUESTION)
|
|
|
|
no_rdata = ISC_TRUE;
|
|
|
|
else
|
|
|
|
no_rdata = ISC_FALSE;
|
|
|
|
|
2000-05-24 18:17:53 +00:00
|
|
|
if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
|
2000-05-15 17:49:57 +00:00
|
|
|
ADD_STRING(target, ";; ");
|
2000-06-09 01:46:59 +00:00
|
|
|
if (msg->opcode != dns_opcode_update) {
|
|
|
|
ADD_STRING(target, sectiontext[section]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ADD_STRING(target, updsectiontext[section]);
|
|
|
|
}
|
2000-05-15 17:49:57 +00:00
|
|
|
ADD_STRING(target, " SECTION:\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
dns_name_init(&empty_name, NULL);
|
|
|
|
result = dns_message_firstname(msg, section);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-05-20 02:00:29 +00:00
|
|
|
return (result);
|
2000-05-15 17:49:57 +00:00
|
|
|
}
|
|
|
|
do {
|
|
|
|
name = NULL;
|
|
|
|
dns_message_currentname(msg, section, &name);
|
|
|
|
for (rdataset = ISC_LIST_HEAD(name->list);
|
|
|
|
rdataset != NULL;
|
|
|
|
rdataset = ISC_LIST_NEXT(rdataset, link)) {
|
2000-05-20 02:00:29 +00:00
|
|
|
if (no_rdata)
|
|
|
|
ADD_STRING(target, ";");
|
|
|
|
result = dns_rdataset_totext(rdataset, name,
|
|
|
|
omit_final_dot,
|
|
|
|
no_rdata,
|
|
|
|
target);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
2000-05-15 17:49:57 +00:00
|
|
|
}
|
|
|
|
result = dns_message_nextname(msg, section);
|
|
|
|
} while (result == ISC_R_SUCCESS);
|
2000-05-24 19:28:31 +00:00
|
|
|
if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0)
|
|
|
|
ADD_STRING(target, "\n");
|
2000-05-15 17:49:57 +00:00
|
|
|
if (result == ISC_R_NOMORE)
|
|
|
|
result = ISC_R_SUCCESS;
|
2000-05-20 02:00:29 +00:00
|
|
|
return (result);
|
2000-05-15 17:49:57 +00:00
|
|
|
}
|
|
|
|
|
2000-05-22 21:22:06 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_message_pseudosectiontotext(dns_message_t *msg,
|
|
|
|
dns_pseudosection_t section,
|
2000-05-24 18:17:53 +00:00
|
|
|
dns_messagetextflag_t flags,
|
2000-05-22 21:22:06 +00:00
|
|
|
isc_buffer_t *target) {
|
|
|
|
dns_rdataset_t *ps = NULL;
|
|
|
|
dns_name_t *name = NULL;
|
|
|
|
isc_result_t result;
|
2000-05-22 22:41:24 +00:00
|
|
|
char buf[sizeof("1234567890")];
|
2000-05-24 18:17:53 +00:00
|
|
|
isc_boolean_t omit_final_dot;
|
2000-05-22 21:22:06 +00:00
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(target != NULL);
|
|
|
|
REQUIRE(VALID_PSEUDOSECTION(section));
|
|
|
|
|
2000-05-24 18:17:53 +00:00
|
|
|
omit_final_dot = ISC_TF((flags & DNS_MESSAGETEXTFLAG_OMITDOT) != 0);
|
|
|
|
|
2000-05-22 21:22:06 +00:00
|
|
|
switch (section) {
|
|
|
|
case DNS_PSEUDOSECTION_OPT:
|
|
|
|
ps = dns_message_getopt(msg);
|
|
|
|
if (ps == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
2000-05-24 18:17:53 +00:00
|
|
|
if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
|
2000-05-22 21:22:06 +00:00
|
|
|
ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
|
|
|
|
ADD_STRING(target, "; EDNS: version: ");
|
|
|
|
sprintf(buf, "%4u",
|
|
|
|
(unsigned int)((ps->ttl &
|
|
|
|
0x00ff0000 >> 16)));
|
|
|
|
ADD_STRING(target, buf);
|
|
|
|
ADD_STRING(target, ", udp=");
|
|
|
|
sprintf(buf, "%7u\n",
|
|
|
|
(unsigned int)ps->rdclass);
|
|
|
|
ADD_STRING(target, buf);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
case DNS_PSEUDOSECTION_TSIG:
|
|
|
|
ps = dns_message_gettsig(msg, &name);
|
|
|
|
if (ps == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
2000-05-24 18:17:53 +00:00
|
|
|
if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
|
2000-05-22 21:22:06 +00:00
|
|
|
ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
|
|
|
|
result = dns_rdataset_totext(ps, name, omit_final_dot,
|
|
|
|
ISC_FALSE, target);
|
|
|
|
ADD_STRING(target, "\n");
|
|
|
|
return (result);
|
|
|
|
case DNS_PSEUDOSECTION_SIG0:
|
2000-05-23 23:35:54 +00:00
|
|
|
ps = dns_message_getsig0(msg, &name);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (ps == NULL)
|
|
|
|
return (ISC_R_SUCCESS);
|
2000-05-24 18:17:53 +00:00
|
|
|
if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
|
2000-05-22 21:22:06 +00:00
|
|
|
ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
|
2000-05-23 23:35:54 +00:00
|
|
|
result = dns_rdataset_totext(ps, name, omit_final_dot,
|
2000-05-22 21:22:06 +00:00
|
|
|
ISC_FALSE, target);
|
2000-05-24 19:28:31 +00:00
|
|
|
if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0)
|
|
|
|
ADD_STRING(target, "\n");
|
2000-05-22 21:22:06 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
return (ISC_R_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
2000-05-15 17:49:57 +00:00
|
|
|
isc_result_t
|
2000-05-24 18:17:53 +00:00
|
|
|
dns_message_totext(dns_message_t *msg, dns_messagetextflag_t flags,
|
2000-05-15 17:49:57 +00:00
|
|
|
isc_buffer_t *target) {
|
|
|
|
char buf[sizeof "1234567890"];
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
REQUIRE(DNS_MESSAGE_VALID(msg));
|
|
|
|
REQUIRE(target != NULL);
|
|
|
|
|
2000-05-24 18:17:53 +00:00
|
|
|
if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
|
2000-05-15 17:49:57 +00:00
|
|
|
ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
|
|
|
|
ADD_STRING(target, opcodetext[msg->opcode]);
|
|
|
|
ADD_STRING(target, ", status: ");
|
|
|
|
ADD_STRING(target, rcodetext[msg->rcode]);
|
|
|
|
ADD_STRING(target, ", id: ");
|
|
|
|
sprintf(buf, "%6u", msg->id);
|
|
|
|
ADD_STRING(target, buf);
|
|
|
|
ADD_STRING(target, "\n;; flags: ");
|
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
|
|
|
|
ADD_STRING(target, "qr ");
|
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
|
|
|
|
ADD_STRING(target, "aa ");
|
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
|
|
|
|
ADD_STRING(target, "tc ");
|
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
|
|
|
|
ADD_STRING(target, "rd ");
|
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
|
|
|
|
ADD_STRING(target, "ra ");
|
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
|
|
|
|
ADD_STRING(target, "ad ");
|
|
|
|
if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
|
|
|
|
ADD_STRING(target, "cd ");
|
2000-06-16 18:48:41 +00:00
|
|
|
if (msg->opcode != dns_opcode_update) {
|
|
|
|
ADD_STRING(target, "; QUESTION: ");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ADD_STRING(target, "; ZONE: ");
|
|
|
|
}
|
|
|
|
sprintf(buf, "%1u", msg->counts[DNS_SECTION_QUESTION]);
|
2000-05-15 17:49:57 +00:00
|
|
|
ADD_STRING(target, buf);
|
2000-06-16 18:48:41 +00:00
|
|
|
if (msg->opcode != dns_opcode_update) {
|
|
|
|
ADD_STRING(target, ", ANSWER: ");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ADD_STRING(target, ", PREREQ: ");
|
|
|
|
}
|
|
|
|
sprintf(buf, "%1u", msg->counts[DNS_SECTION_ANSWER]);
|
2000-05-15 17:49:57 +00:00
|
|
|
ADD_STRING(target, buf);
|
2000-06-16 18:48:41 +00:00
|
|
|
if (msg->opcode != dns_opcode_update) {
|
|
|
|
ADD_STRING(target, ", AUTHORITY: ");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ADD_STRING(target, ", UPDATE: ");
|
|
|
|
}
|
|
|
|
sprintf(buf, "%1u", msg->counts[DNS_SECTION_AUTHORITY]);
|
2000-05-15 17:49:57 +00:00
|
|
|
ADD_STRING(target, buf);
|
|
|
|
ADD_STRING(target, ", ADDITIONAL: ");
|
2000-06-16 18:48:41 +00:00
|
|
|
sprintf(buf, "%1u", msg->counts[DNS_SECTION_ADDITIONAL]);
|
2000-05-15 17:49:57 +00:00
|
|
|
ADD_STRING(target, buf);
|
|
|
|
ADD_STRING(target, "\n");
|
|
|
|
}
|
2000-05-22 21:22:06 +00:00
|
|
|
result = dns_message_pseudosectiontotext(msg,
|
|
|
|
DNS_PSEUDOSECTION_OPT,
|
2000-05-24 18:17:53 +00:00
|
|
|
flags, target);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
|
2000-05-24 18:17:53 +00:00
|
|
|
flags, target);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
|
2000-05-24 18:17:53 +00:00
|
|
|
flags, target);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
|
2000-05-24 18:17:53 +00:00
|
|
|
flags, target);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
|
2000-05-24 18:17:53 +00:00
|
|
|
flags, target);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
result = dns_message_pseudosectiontotext(msg,
|
|
|
|
DNS_PSEUDOSECTION_TSIG,
|
2000-05-24 18:17:53 +00:00
|
|
|
flags, target);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
result = dns_message_pseudosectiontotext(msg,
|
|
|
|
DNS_PSEUDOSECTION_SIG0,
|
2000-05-24 18:17:53 +00:00
|
|
|
flags, target);
|
2000-05-22 21:22:06 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2000-05-20 02:00:29 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2000-05-15 17:49:57 +00:00
|
|
|
}
|