message.c revision be3458c3da0e36d1ef8afc74362af9537359a1e4
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff/*
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Copyright (C) 1999 Internet Software Consortium.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff *
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Permission to use, copy, modify, and distribute this software for any
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * purpose with or without fee is hereby granted, provided that the above
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * copyright notice and this permission notice appear in all copies.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff *
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * SOFTWARE.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff */
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff/***
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff *** Imports
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff ***/
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff#include <config.h>
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff#include <stddef.h>
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff#include <string.h>
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff#include <isc/assertions.h>
f9df80f4348ef68043903efa08299480324f4823Michael Graff#include <isc/boolean.h>
f9df80f4348ef68043903efa08299480324f4823Michael Graff#include <isc/region.h>
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff#include <isc/types.h>
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff#include <dns/message.h>
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff#include <dns/rdataset.h>
f9df80f4348ef68043903efa08299480324f4823Michael Graff#include <dns/rdata.h>
f9df80f4348ef68043903efa08299480324f4823Michael Graff#include <dns/rdataclass.h>
f9df80f4348ef68043903efa08299480324f4823Michael Graff#include <dns/rdatatype.h>
f9df80f4348ef68043903efa08299480324f4823Michael Graff#include <dns/rdatalist.h>
f9df80f4348ef68043903efa08299480324f4823Michael Graff#include <dns/compress.h>
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff#define MESSAGE_MAGIC 0x4d534740U /* MSG@ */
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define VALID_MESSAGE(msg) (((msg)->magic) == MESSAGE_MAGIC)
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
f9df80f4348ef68043903efa08299480324f4823Michael Graff && ((s) < DNS_SECTION_MAX))
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
f9df80f4348ef68043903efa08299480324f4823Michael Graff && ((s) < DNS_SECTION_MAX))
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff/*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * This is the size of each individual scratchpad buffer, and the numbers
f9df80f4348ef68043903efa08299480324f4823Michael Graff * of various block allocations used within the server.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff#define SCRATCHPAD_SIZE 512
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define NAME_COUNT 16
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define RDATA_COUNT 32
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff#define RDATALIST_COUNT 32 /* should match RDATASET_COUNT */
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff#define RDATASET_COUNT 32
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff/*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * "helper" type, which consists of a block of some type, and is linkable.
f9df80f4348ef68043903efa08299480324f4823Michael Graff * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
f9df80f4348ef68043903efa08299480324f4823Michael Graff * size, or the allocated elements will not be alligned correctly.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graffstruct dns_msgblock {
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int length;
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int remaining;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LINK(dns_msgblock_t) link;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}; /* dynamically sized */
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_free(isc_mem_t *, dns_msgblock_t *);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define msgblock_get(block, type) \
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ((type *)msgblock_internalget(block, sizeof(type)))
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void *
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_internalget(dns_msgblock_t *, unsigned int);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffstatic inline void
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_reset(dns_msgblock_t *, unsigned int);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline dns_msgblock_t *
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff/*
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * is free, return NULL.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff */
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline dns_msgblock_t *
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int count)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff{
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff dns_msgblock_t *block;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff unsigned int length;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff length = sizeof(dns_msgblock_t) + (sizeof_type * count);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff block = isc_mem_get(mctx, length);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff if (block == NULL)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff return NULL;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff block->length = length;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff block->remaining = count;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff ISC_LINK_INIT(block, link);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff return (block);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff}
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff/*
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Return an element from the msgblock. If no more are available, return
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * NULL.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff */
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void *
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff{
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff void *ptr;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff if (block->remaining == 0)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff return (NULL);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff block->remaining--;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff ptr = (((unsigned char *)block)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff + sizeof(dns_msgblock_t)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff + (sizeof_type * block->remaining));
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff return (ptr);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff}
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffstatic inline void
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_reset(dns_msgblock_t *block, unsigned int count)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff block->remaining = count;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff/*
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Release memory associated with a message block.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff */
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_free(isc_mem_t *mctx, dns_msgblock_t *block)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff{
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff isc_mem_put(mctx, block, block->length);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff/*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Allocate a new dynamic buffer, and attach it to this message as the
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * "current" buffer. (which is always the last on the list, for our
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * uses)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline dns_result_t
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffnewbuffer(dns_message_t *msg)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_result_t result;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_dynbuffer_t *dynbuf;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dynbuf = NULL;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff result = isc_dynbuffer_allocate(msg->mctx, &dynbuf, SCRATCHPAD_SIZE,
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_BUFFERTYPE_BINARY);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (result != ISC_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_NOMEMORY);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_SUCCESS);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline isc_buffer_t *
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffcurrentbuffer(dns_message_t *msg)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_dynbuffer_t *dynbuf;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dynbuf = ISC_LIST_TAIL(msg->scratchpad);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (&dynbuf->buffer);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline void
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffreleasename(dns_message_t *msg, dns_name_t *name)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextname = name;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline dns_name_t *
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffnewname(dns_message_t *msg)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_msgblock_t *msgblock;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_name_t *name;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msg->nextname != NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff name = msg->nextname;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextname = NULL;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_name_init(name, NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (name);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_HEAD(msg->names);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff name = msgblock_get(msgblock, dns_name_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (name == NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = msgblock_allocate(msg->mctx, sizeof(dns_name_t),
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff NAME_COUNT);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msgblock == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_APPEND(msg->names, msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff name = msgblock_get(msgblock, dns_name_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_name_init(name, NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (name);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline void
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffreleaserdata(dns_message_t *msg, dns_rdata_t *rdata)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextrdata = rdata;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline dns_rdata_t *
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffnewrdata(dns_message_t *msg)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_msgblock_t *msgblock;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_rdata_t *rdata;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msg->nextrdata != NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdata = msg->nextrdata;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextrdata = NULL;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdata);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatas);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdata = msgblock_get(msgblock, dns_rdata_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (rdata == NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff RDATA_COUNT);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msgblock == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_APPEND(msg->rdatas, msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdata = msgblock_get(msgblock, dns_rdata_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdata);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline void
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffreleaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextrdatalist = rdatalist;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline dns_rdatalist_t *
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffnewrdatalist(dns_message_t *msg)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_msgblock_t *msgblock;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_rdatalist_t *rdatalist;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msg->nextrdatalist != NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdatalist = msg->nextrdatalist;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextrdatalist = NULL;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdatalist);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatalists);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (rdatalist == NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = msgblock_allocate(msg->mctx,
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff sizeof(dns_rdatalist_t),
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff RDATALIST_COUNT);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msgblock == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdatalist);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline void
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffreleaserdataset(dns_message_t *msg, dns_rdataset_t *rdataset)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextrdataset = rdataset;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline dns_rdataset_t *
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffnewrdataset(dns_message_t *msg)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_msgblock_t *msgblock;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_rdataset_t *rdataset;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msg->nextrdataset != NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdataset = msg->nextrdataset;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->nextrdataset = NULL;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdataset);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatasets);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdataset = msgblock_get(msgblock, dns_rdataset_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (rdataset == NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdataset_t),
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff RDATASET_COUNT);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msgblock == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_APPEND(msg->rdatasets, msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdataset = msgblock_get(msgblock, dns_rdataset_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdataset);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff/*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Init elements to default state. Used both when allocating a new element
f9df80f4348ef68043903efa08299480324f4823Michael Graff * and when resetting one.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graffstatic inline void
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsginit(dns_message_t *m)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff unsigned int i;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->id = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->flags = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->rcode = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->opcode = 0;
e223094b2248afa2697c531f75e6f84855638becMichael Graff m->rdclass = 0;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (i = 0 ; i < DNS_SECTION_MAX ; i++) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff m->cursors[i] = NULL;
e223094b2248afa2697c531f75e6f84855638becMichael Graff m->counts[i] = NULL;
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff m->nextname = NULL;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff m->nextrdata = NULL;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff m->nextrdataset = NULL;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff m->nextrdatalist = NULL;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff m->buffer = NULL;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff/*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Free all but one (or everything) for this message. This is used by
f9df80f4348ef68043903efa08299480324f4823Michael Graff * both dns_message_reset() and dns_message_parse().
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graffstatic void
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgreset(dns_message_t *msg, isc_boolean_t everything)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_msgblock_t *msgblock, *next_msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_dynbuffer_t *dynbuf, *next_dynbuf;
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_rdataset_t *rds, *next_rds;
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_name_t *name, *next_name;
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int i;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Clean up name lists by calling the rdataset disassociate function.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graff for (i = 0 ; i < DNS_SECTION_MAX ; i++) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff name = ISC_LIST_HEAD(msg->sections[i]);
f9df80f4348ef68043903efa08299480324f4823Michael Graff while (name != NULL) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff next_name = ISC_LIST_NEXT(name, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->sections[i], name, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff rds = ISC_LIST_HEAD(name->list);
f9df80f4348ef68043903efa08299480324f4823Michael Graff while (rds != NULL) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff next_rds = ISC_LIST_NEXT(rds, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(name->list, rds, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_rdataset_disassociate(rds);
f9df80f4348ef68043903efa08299480324f4823Michael Graff rds = next_rds;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff name = next_name;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Clean up linked lists.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = ISC_LIST_HEAD(msg->scratchpad);
f9df80f4348ef68043903efa08299480324f4823Michael Graff INSIST(dynbuf != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (everything == ISC_FALSE) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_dynbuffer_reset(dynbuf);
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = ISC_LIST_NEXT(dynbuf, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff while (dynbuf != NULL) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_dynbuffer_free(msg->mctx, &dynbuf);
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = next_dynbuf;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(msg->names);
f9df80f4348ef68043903efa08299480324f4823Michael Graff INSIST(msgblock != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (everything == ISC_FALSE) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_reset(msgblock, NAME_COUNT);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_NEXT(msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff while (msgblock != NULL) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff next_msgblock = ISC_LIST_NEXT(msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->names, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_free(msg->mctx, msgblock);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = next_msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatas);
f9df80f4348ef68043903efa08299480324f4823Michael Graff INSIST(msgblock != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (everything == ISC_FALSE) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_reset(msgblock, RDATA_COUNT);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_NEXT(msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff while (msgblock != NULL) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff next_msgblock = ISC_LIST_NEXT(msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_free(msg->mctx, msgblock);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = next_msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatasets);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff INSIST(msgblock != NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (everything == ISC_FALSE) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock_reset(msgblock, RDATASET_COUNT);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_NEXT(msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff while (msgblock != NULL) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff next_msgblock = ISC_LIST_NEXT(msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_UNLINK(msg->rdatasets, msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock_free(msg->mctx, msgblock);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = next_msgblock;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msg->from_to_wire == DNS_MESSAGE_INTENT_PARSE) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatalists);
f9df80f4348ef68043903efa08299480324f4823Michael Graff INSIST(msgblock != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (everything == ISC_FALSE) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_reset(msgblock, RDATALIST_COUNT);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_NEXT(msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff while (msgblock != NULL) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff next_msgblock = ISC_LIST_NEXT(msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_free(msg->mctx, msgblock);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = next_msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Set other bits to normal default values.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graff msginit(msg);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_create(isc_mem_t *mctx, dns_message_t **msg, unsigned int intent)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_message_t *m;
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_result_t iresult;
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_msgblock_t *msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_dynbuffer_t *dynbuf;
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int i;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(mctx != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(msg != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(*msg == NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(intent == DNS_MESSAGE_INTENT_PARSE
f9df80f4348ef68043903efa08299480324f4823Michael Graff || intent == DNS_MESSAGE_INTENT_RENDER);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff m = isc_mem_get(mctx, sizeof(dns_message_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (m == NULL)
f9df80f4348ef68043903efa08299480324f4823Michael Graff return(DNS_R_NOMEMORY);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->magic = MESSAGE_MAGIC;
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->from_to_wire = intent;
f9df80f4348ef68043903efa08299480324f4823Michael Graff msginit(m);
f9df80f4348ef68043903efa08299480324f4823Michael Graff for (i = 0 ; i < DNS_SECTION_MAX ; i++)
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->sections[i]);
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->mctx = mctx;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->scratchpad);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->names);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->rdatas);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->rdatalists);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = NULL;
f9df80f4348ef68043903efa08299480324f4823Michael Graff iresult = isc_dynbuffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE,
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_BUFFERTYPE_BINARY);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (iresult != ISC_R_SUCCESS)
f9df80f4348ef68043903efa08299480324f4823Michael Graff goto cleanup1;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = msgblock_allocate(mctx, sizeof(dns_name_t),
f9df80f4348ef68043903efa08299480324f4823Michael Graff NAME_COUNT);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msgblock == NULL)
f9df80f4348ef68043903efa08299480324f4823Michael Graff goto cleanup2;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(m->names, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = msgblock_allocate(mctx, sizeof(dns_rdata_t),
f9df80f4348ef68043903efa08299480324f4823Michael Graff RDATA_COUNT);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msgblock == NULL)
f9df80f4348ef68043903efa08299480324f4823Michael Graff goto cleanup3;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(m->rdatas, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = msgblock_allocate(mctx, sizeof(dns_rdataset_t),
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff RDATASET_COUNT);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (msgblock == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff goto cleanup4;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff ISC_LIST_APPEND(m->rdatasets, msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (intent == DNS_MESSAGE_INTENT_PARSE) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = msgblock_allocate(mctx, sizeof(dns_rdatalist_t),
f9df80f4348ef68043903efa08299480324f4823Michael Graff RDATALIST_COUNT);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msgblock == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff goto cleanup5;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(m->rdatalists, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff *msg = m;
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Cleanup for error returns.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff cleanup5:
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_HEAD(m->rdatasets);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock_free(mctx, msgblock);
f9df80f4348ef68043903efa08299480324f4823Michael Graff cleanup4:
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(m->rdatas);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_free(mctx, msgblock);
f9df80f4348ef68043903efa08299480324f4823Michael Graff cleanup3:
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(m->names);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock_free(mctx, msgblock);
f9df80f4348ef68043903efa08299480324f4823Michael Graff cleanup2:
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = ISC_LIST_HEAD(m->scratchpad);
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_dynbuffer_free(mctx, &dynbuf);
f9df80f4348ef68043903efa08299480324f4823Michael Graff cleanup1:
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->magic = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_mem_put(mctx, m, sizeof(dns_message_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_NOMEMORY);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffvoid
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_reset(dns_message_t *msg)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgreset(msg, ISC_FALSE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffvoid
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_destroy(dns_message_t **xmsg)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_message_t *msg;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(xmsg != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(*xmsg));
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg = *xmsg;
f9df80f4348ef68043903efa08299480324f4823Michael Graff *xmsg = NULL;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgreset(msg, ISC_TRUE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->magic = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graffstatic dns_result_t
e223094b2248afa2697c531f75e6f84855638becMichael Grafffindname(dns_name_t **foundname, dns_name_t *target, dns_namelist_t *section)
e223094b2248afa2697c531f75e6f84855638becMichael Graff{
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_name_t *curr;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff printf("-----\n");
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (curr = ISC_LIST_TAIL(*section) ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr != NULL ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr = ISC_LIST_PREV(curr, link)) {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff printf("curr = %p\n", curr);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (dns_name_compare(curr, target) == 0) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (foundname != NULL)
e223094b2248afa2697c531f75e6f84855638becMichael Graff *foundname = curr;
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_SUCCESS);
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_NOTFOUND);
e223094b2248afa2697c531f75e6f84855638becMichael Graff}
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graffstatic dns_result_t
e223094b2248afa2697c531f75e6f84855638becMichael Grafffindtype(dns_rdataset_t **rdataset, dns_name_t *name, dns_rdatatype_t type)
e223094b2248afa2697c531f75e6f84855638becMichael Graff{
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataset_t *curr;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (curr = ISC_LIST_TAIL(name->list) ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr != NULL ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr = ISC_LIST_PREV(curr, link)) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (curr->type == type) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (rdataset != NULL)
e223094b2248afa2697c531f75e6f84855638becMichael Graff *rdataset = curr;
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_SUCCESS);
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_NOTFOUND);
e223094b2248afa2697c531f75e6f84855638becMichael Graff}
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff/*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Read a name from buffer "source".
e223094b2248afa2697c531f75e6f84855638becMichael Graff *
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Assumes dns_name_init() was already called on this name.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graffstatic dns_result_t
e223094b2248afa2697c531f75e6f84855638becMichael Graffgetname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_decompress_t *dctx)
e223094b2248afa2697c531f75e6f84855638becMichael Graff{
e223094b2248afa2697c531f75e6f84855638becMichael Graff isc_buffer_t *scratch;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_result_t result;
e223094b2248afa2697c531f75e6f84855638becMichael Graff unsigned int tries;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff scratch = currentbuffer(msg);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (dns_decompress_edns(dctx) > 1 || !dns_decompress_strict(dctx))
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL);
e223094b2248afa2697c531f75e6f84855638becMichael Graff else
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff tries = 0;
e223094b2248afa2697c531f75e6f84855638becMichael Graff while (tries < 2) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
e223094b2248afa2697c531f75e6f84855638becMichael Graff scratch);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result == DNS_R_NOSPACE) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff tries++;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = newbuffer(msg);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result != DNS_R_SUCCESS)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (result);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff scratch = currentbuffer(msg);
e223094b2248afa2697c531f75e6f84855638becMichael Graff } else {
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (result);
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_UNEXPECTED); /* should never get here... XXXMLG */
e223094b2248afa2697c531f75e6f84855638becMichael Graff}
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graffstatic dns_result_t
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graffgetrdata(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_decompress_t *dctx, dns_rdataclass_t rdclass,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_rdatatype_t rdtype, unsigned int rdatalen, dns_rdata_t *rdata)
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff{
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_t *scratch;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_result_t result;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff unsigned int tries;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff scratch = currentbuffer(msg);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_setactive(source, rdatalen);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_decompress_localinit(dctx, name, source);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff tries = 0;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff while (tries < 2) {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff result = dns_rdata_fromwire(rdata, rdclass, rdtype,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff source, dctx, ISC_FALSE,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff scratch);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (result == DNS_R_NOSPACE) {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff tries++;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff result = newbuffer(msg);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (result != DNS_R_SUCCESS)
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff return (result);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff scratch = currentbuffer(msg);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff } else {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff return (result);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff return (DNS_R_UNEXPECTED); /* should never get here... XXXMLG */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff}
e223094b2248afa2697c531f75e6f84855638becMichael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic dns_result_t
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffgetquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_region_t r;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff unsigned int count;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_name_t *name;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_name_t *name2;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_rdataset_t *rdataset;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_rdatalist_t *rdatalist;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_result_t result;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdatatype_t rdtype;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataclass_t rdclass;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_namelist_t *section;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff section = &msg->sections[DNS_SECTION_QUESTION];
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (count = 0 ; count < msg->counts[DNS_SECTION_QUESTION] ; count++) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff name = newname(msg);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (name == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_NOMEMORY);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Parse the name out of this packet.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_remaining(source, &r);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_setactive(source, r.length);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff result = getname(name, source, msg, dctx);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (result != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (result);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Run through the section, looking to see if this name
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * is already there. If it is found, put back the allocated
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * name since we no longer need it, and set our name pointer
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * to point to the name we found.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = findname(&name2, name, section);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * If it is the first name in the section, accept it.
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff *
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * If it is not, but is not the same as the name already
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * in the question section, append to the section. Note that
e223094b2248afa2697c531f75e6f84855638becMichael Graff * here in the question section this is illegal, so return
e223094b2248afa2697c531f75e6f84855638becMichael Graff * FORMERR. In the future, check the opcode to see if
e223094b2248afa2697c531f75e6f84855638becMichael Graff * this should be legal or not. In either case we no longer
e223094b2248afa2697c531f75e6f84855638becMichael Graff * need this name pointer.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (result != DNS_R_SUCCESS) {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (ISC_LIST_EMPTY(*section)) {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff ISC_LIST_APPEND(*section, name, link);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff } else {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff return (DNS_R_FORMERR);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff } else {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff name = name2;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Get type and class.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff isc_buffer_remaining(source, &r);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (r.length < 4)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_UNEXPECTEDEND);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdtype = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdclass = isc_buffer_getuint16(source);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * If this class is different than the one we alrady read,
e223094b2248afa2697c531f75e6f84855638becMichael Graff * this is an error.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (msg->state == DNS_SECTION_ANY) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->state = DNS_SECTION_QUESTION;
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->rdclass = rdclass;
e223094b2248afa2697c531f75e6f84855638becMichael Graff } else if (msg->rdclass != rdclass)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_FORMERR);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Search name for the particular type and class.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * If it was found, this is an error, return FORMERR.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = findtype(NULL, name, rdtype);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result == DNS_R_SUCCESS)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_FORMERR);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Allocate a new rdatalist.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdatalist = newrdatalist(msg);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdataset = newrdataset(msg);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Convert rdatalist to rdataset, and attach the latter to
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * the name.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdatalist->type = rdtype;
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdatalist->rdclass = rdclass;
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdatalist->ttl = 0;
e223094b2248afa2697c531f75e6f84855638becMichael Graff ISC_LIST_INIT(rdatalist->rdata);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_rdataset_init(rdataset);
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = dns_rdatalist_tordataset(rdatalist, rdataset);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result != DNS_R_SUCCESS)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (result);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff ISC_LIST_APPEND(name->list, rdataset, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_SUCCESS);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic dns_result_t
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffgetsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_section_t sectionid)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
e223094b2248afa2697c531f75e6f84855638becMichael Graff isc_region_t r;
e223094b2248afa2697c531f75e6f84855638becMichael Graff unsigned int count;
1d11db66fa23e276074858091407734de40584acMichael Graff unsigned int rdatalen;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_name_t *name;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_name_t *name2;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataset_t *rdataset;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdatalist_t *rdatalist;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_result_t result;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdatatype_t rdtype;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataclass_t rdclass;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_rdata_t *rdata;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_ttl_t ttl;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_namelist_t *section;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff section = &msg->sections[sectionid];
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (count = 0 ; count < msg->counts[sectionid] ; count++) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff name = newname(msg);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (name == NULL)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_NOMEMORY);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Parse the name out of this packet.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_remaining(source, &r);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_setactive(source, r.length);
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = getname(name, source, msg, dctx);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result != DNS_R_SUCCESS)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (result);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Run through the section, looking to see if this name
e223094b2248afa2697c531f75e6f84855638becMichael Graff * is already there. If it is found, put back the allocated
e223094b2248afa2697c531f75e6f84855638becMichael Graff * name since we no longer need it, and set our name pointer
e223094b2248afa2697c531f75e6f84855638becMichael Graff * to point to the name we found.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = findname(&name2, name, section);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * If it is a new name, append to the section.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result == DNS_R_SUCCESS) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff releasename(msg, name);
e223094b2248afa2697c531f75e6f84855638becMichael Graff name = name2;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff } else {
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff ISC_LIST_APPEND(*section, name, link);
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Get type, class, ttl, and rdatalen. Verify that at least
e223094b2248afa2697c531f75e6f84855638becMichael Graff * rdatalen bytes remain. (Some of this is deferred to
e223094b2248afa2697c531f75e6f84855638becMichael Graff * later.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff isc_buffer_remaining(source, &r);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (r.length < 10)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_UNEXPECTEDEND);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdtype = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdclass = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * If this class is different than the one we already read,
e223094b2248afa2697c531f75e6f84855638becMichael Graff * this is an error.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (msg->state == DNS_SECTION_ANY) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->state = sectionid;
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->rdclass = rdclass;
e223094b2248afa2697c531f75e6f84855638becMichael Graff } else if (msg->rdclass != rdclass)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_FORMERR);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * ... now get ttl and rdatalen, and check buffer.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff ttl = isc_buffer_getuint32(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdatalen = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff r.length -= 10;
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (r.length < rdatalen)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_UNEXPECTEDEND);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Search name for the particular type and class.
e223094b2248afa2697c531f75e6f84855638becMichael Graff * If it was found, this is an error, return FORMERR.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = findtype(&rdataset, name, rdtype);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * If we found an rdataset that matches, we need to
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * append this rdata to that set. If we did not, we need
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * to create a new rdatalist, store the important bits there,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * convert it to an rdataset, and link the latter to the name.
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * Yuck.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result != DNS_R_SUCCESS) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdataset = newrdataset(msg);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (rdataset == NULL)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_NOMEMORY);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist = newrdatalist(msg);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (rdatalist == NULL)
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff return (DNS_R_NOMEMORY);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist->type = rdtype;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist->rdclass = rdclass;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist->ttl = ttl;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff ISC_LIST_INIT(rdatalist->rdata);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_rdataset_init(rdataset);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_rdatalist_tordataset(rdatalist, rdataset);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff ISC_LIST_APPEND(name->list, rdataset, link);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * Read the rdata from the wire format.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdata = newrdata(msg);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (rdata == NULL)
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff return (DNS_R_NOMEMORY);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff result = getrdata(name, source, msg, dctx,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdclass, rdtype, rdatalen, rdata);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result != DNS_R_SUCCESS)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (result);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff /*
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * XXX Perform a totally ugly hack here to pull
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * the rdatalist out of the private field in the rdataset,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * and append this rdata to the rdatalist's linked list
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * of rdata.
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist = (dns_rdatalist_t *)(rdataset->private1);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_SUCCESS);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffdns_message_parse(dns_message_t *msg, isc_buffer_t *source)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_region_t r;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_decompress_t dctx;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_result_t ret;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_uint16_t tmpflags;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff REQUIRE(source != NULL);
be3458c3da0e36d1ef8afc74362af9537359a1e4Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENT_PARSE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_buffer_remaining(source, &r);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (r.length < DNS_MESSAGE_HEADER_LEN)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_UNEXPECTEDEND);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msg->id = isc_buffer_getuint16(source);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff tmpflags = isc_buffer_getuint16(source);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff >> DNS_MESSAGE_OPCODE_SHIFT);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff msg->rcode = (tmpflags & DNS_MESSAGE_RCODE_MASK);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff msg->flags = (tmpflags & ~DNS_MESSAGE_FLAG_MASK);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_decompress_init(&dctx, -1, ISC_FALSE);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ret = getquestions(source, msg, &dctx);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (ret != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (ret);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (ret != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (ret);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (ret != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (ret);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (ret != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (ret);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_remaining(source, &r);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff if (r.length != 0)
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff return (DNS_R_FORMERR);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * XXXMLG Need to check the tsig(s) here...
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_renderbegin(dns_message_t *msg, isc_buffer_t *buffer)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_region_t r;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(buffer != NULL);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer == NULL);
be3458c3da0e36d1ef8afc74362af9537359a1e4Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENT_RENDER);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff /*
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Erase the contents of this buffer.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff */
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_clear(buffer);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff /*
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Make certain there is enough for at least the header in this
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * buffer.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff */
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_available(buffer, &r);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff if (r.length < DNS_MESSAGE_HEADER_LEN)
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff return (DNS_R_NOSPACE);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff /*
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Reserve enough space for the header in this buffer.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff */
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_add(buffer, DNS_MESSAGE_HEADER_LEN);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff return (DNS_R_SUCCESS);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff}
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graffdns_result_t
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graffdns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer)
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff{
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_region_t r, rn;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(VALID_MESSAGE(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(buffer != NULL);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff /*
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * ensure that the new buffer is empty, and has enough space to
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * hold the current contents.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff */
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_clear(buffer);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_available(buffer, &rn);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_used(msg->buffer, &r);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff if (rn.length < r.length)
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff return (DNS_R_NOSPACE);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff /*
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Copy the contents from the old to the new buffer.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff */
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_add(buffer, r.length);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff memcpy(rn.base, r.base, r.length);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff msg->buffer = buffer;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_renderrelease(dns_message_t *msg, unsigned int space)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msg->reserved < space)
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_NOSPACE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->reserved -= space;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graffdns_message_renderreserve(dns_message_t *msg, unsigned int space)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_region_t r;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * "space" can be positive or negative. If it is negative we are
f9df80f4348ef68043903efa08299480324f4823Michael Graff * removing our reservation of space. If it is positive, we are
f9df80f4348ef68043903efa08299480324f4823Michael Graff * requesting more space to be reserved.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_buffer_available(msg->buffer, &r);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (r.length < (space + msg->reserved))
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_NOSPACE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->reserved += space;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graffdns_message_rendersection(dns_message_t *msg, dns_section_t section,
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff unsigned int priority, unsigned int flags)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(section));
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /* XXX implement */
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (ISC_R_NOTIMPLEMENTED);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graffdns_message_renderend(dns_message_t *msg)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff msg->buffer = NULL; /* forget about this buffer only on success XXX */
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /* XXX implement */
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (ISC_R_NOTIMPLEMENTED);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_firstname(dns_message_t *msg, dns_section_t section)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(section));
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msg->cursors[section] == NULL)
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_NOMORE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (ISC_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_nextname(dns_message_t *msg, dns_section_t section)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(section));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(msg->cursors[section] != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msg->cursors[section] == NULL)
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (DNS_R_NOMORE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (ISC_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffvoid
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_currentname(dns_message_t *msg, dns_section_t section,
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_name_t **name)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_MESSAGE(msg));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(section));
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff REQUIRE(name != NULL && *name == NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(msg->cursors[section] != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff *name = msg->cursors[section];
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_findname(dns_message_t *msg, dns_section_t section,
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_name_t *target, dns_rdatatype_t type,
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_name_t **name, dns_rdataset_t **rdataset)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * XXX These requirements are probably too intensive, especially
f9df80f4348ef68043903efa08299480324f4823Michael Graff * where things can be NULL, but as they are they ensure that if
f9df80f4348ef68043903efa08299480324f4823Michael Graff * something is NON-NULL, indicating that the caller expects it
f9df80f4348ef68043903efa08299480324f4823Michael Graff * to be filled in, that we can in fact fill it in.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(msg != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_SECTION(section));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(target != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (name != NULL)
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(*name == NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (type == dns_rdatatype_any) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(rdataset == NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff } else {
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (rdataset != NULL)
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(*rdataset == NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff return (ISC_R_NOTIMPLEMENTED);
f9df80f4348ef68043903efa08299480324f4823Michael Graff /* XXX implement */
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffvoid
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_movename(dns_message_t *msg, dns_name_t *name,
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_section_t fromsection,
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_section_t tosection)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(msg != NULL);
be3458c3da0e36d1ef8afc74362af9537359a1e4Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENT_RENDER);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(name != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(fromsection));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(tosection));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(fromsection != tosection);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Unlink the name from the old section
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(msg->sections[tosection], name, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffvoid
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_addname(dns_message_t *msg, dns_name_t *name,
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_section_t section)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(msg != NULL);
be3458c3da0e36d1ef8afc74362af9537359a1e4Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENT_RENDER);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(name != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(section));
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(msg->sections[section], name, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}