message.c revision 0e919917cce54d09407393499ea5c019b93750e2
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
75ec9bc9c7b4f2485647414330122e7b8e188097Andreas Gustafsson#define DNS_MESSAGE_OPCODE_MASK 0x7800U
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff#define DNS_MESSAGE_OPCODE_SHIFT 11
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff#define DNS_MESSAGE_RCODE_MASK 0x000fU
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff#define DNS_MESSAGE_FLAG_MASK 0x8ff0U
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.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * XXXMLG These should come from a config setting.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff#define SCRATCHPAD_SIZE 512
b02262cbcd550c63f85df76edc6fff556ea5e95dMichael Graff#define NAME_COUNT 8
b02262cbcd550c63f85df76edc6fff556ea5e95dMichael Graff#define RDATA_COUNT 8
b02262cbcd550c63f85df76edc6fff556ea5e95dMichael Graff#define RDATALIST_COUNT 8
b02262cbcd550c63f85df76edc6fff556ea5e95dMichael Graff#define RDATASET_COUNT RDATALIST_COUNT
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 {
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff unsigned int count;
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int remaining;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LINK(dns_msgblock_t) link;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}; /* dynamically sized */
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffstatic inline dns_msgblock_t *
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffmsgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffmsgblock_reset(dns_msgblock_t *);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffstatic inline void
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffmsgblock_free(isc_mem_t *, dns_msgblock_t *, 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)
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (NULL);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff block->count = count;
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
8c55a67a6d185de7036e39da30561a5c1637d22bAndreas Gustafsson if (block == NULL || 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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffmsgblock_reset(dns_msgblock_t *block)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff block->remaining = block->count;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff/*
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Release memory associated with a message block.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff */
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffmsgblock_free(isc_mem_t *mctx, dns_msgblock_t *block,
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff unsigned int sizeof_type)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff{
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff unsigned int length;
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff isc_mem_put(mctx, 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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff INSIST(dynbuf != NULL);
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{
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_PREPEND(msg->freename, name, link);
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
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff name = ISC_LIST_HEAD(msg->freename);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff if (name != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freename, name, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (name);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock = ISC_LIST_TAIL(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
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (name);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline void
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffreleaserdata(dns_message_t *msg, dns_rdata_t *rdata)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_PREPEND(msg->freerdata, rdata, link);
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
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdata = ISC_LIST_HEAD(msg->freerdata);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff if (rdata != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdata, rdata, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdata);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock = ISC_LIST_TAIL(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{
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
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
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff if (rdatalist != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdatalist);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock = ISC_LIST_TAIL(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{
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_PREPEND(msg->freerdataset, rdataset, link);
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
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdataset = ISC_LIST_HEAD(msg->freerdataset);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff if (rdataset != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdataset, rdataset, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (rdataset);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock = ISC_LIST_TAIL(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 Graffstatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleymsginitheader(dns_message_t *m)
f9df80f4348ef68043903efa08299480324f4823Michael 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;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleystatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleymsginitprivate(dns_message_t *m)
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley unsigned int i;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley for (i = 0; i < DNS_SECTION_MAX; i++) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff m->cursors[i] = NULL;
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff m->counts[i] = 0;
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff m->opt = NULL;
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff m->reserved = 0;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff m->buffer = NULL;
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff m->need_cctx_cleanup = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff/*
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * Init elements to default state. Used both when allocating a new element
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * and when resetting one.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleystatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleymsginit(dns_message_t *m)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msginitheader(m);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msginitprivate(m);
996028142c5f95492fcd42e69186b95641320c7bBob Halley m->header_ok = 0;
996028142c5f95492fcd42e69186b95641320c7bBob Halley m->question_ok = 0;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley}
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleystatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleymsgresetnames(dns_message_t *msg, unsigned int first_section) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int i;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_name_t *name, *next_name;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_rdataset_t *rds, *next_rds;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Clean up name lists by calling the rdataset disassociate function.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley for (i = first_section; 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 }
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley}
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley/*
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * Free all but one (or everything) for this message. This is used by
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * both dns_message_reset() and dns_message_parse().
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley */
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleystatic void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleymsgreset(dns_message_t *msg, isc_boolean_t everything)
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_msgblock_t *msgblock, *next_msgblock;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley isc_dynbuffer_t *dynbuf, *next_dynbuf;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_rdataset_t *rds;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_name_t *name;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_rdata_t *rdata;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_rdatalist_t *rdatalist;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msgresetnames(msg, 0);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Clean up linked lists.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
f9df80f4348ef68043903efa08299480324f4823Michael Graff
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff /*
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff * Run through the free lists, and just unlink anything found there.
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff * The memory isn't lost since these are part of message blocks we
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff * have allocated.
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff */
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff name = ISC_LIST_HEAD(msg->freename);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff while (name != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freename, name, link);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff name = ISC_LIST_HEAD(msg->freename);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff }
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdata = ISC_LIST_HEAD(msg->freerdata);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff while (rdata != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdata, rdata, link);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdata = ISC_LIST_HEAD(msg->freerdata);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff }
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff while (rdatalist != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff }
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rds = ISC_LIST_HEAD(msg->freerdataset);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff while (rds != NULL) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdataset, rds, link);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rds = ISC_LIST_HEAD(msg->freerdataset);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff }
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = ISC_LIST_HEAD(msg->scratchpad);
f9df80f4348ef68043903efa08299480324f4823Michael Graff INSIST(dynbuf != NULL);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (!everything) {
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (!everything) {
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_reset(msgblock);
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(msg->mctx, msgblock, sizeof(dns_name_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = next_msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatas);
f9df80f4348ef68043903efa08299480324f4823Michael Graff INSIST(msgblock != NULL);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (!everything) {
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_reset(msgblock);
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = next_msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = ISC_LIST_HEAD(msg->rdatasets);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff INSIST(msgblock != NULL);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (!everything) {
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_reset(msgblock);
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(msg->mctx, msgblock, sizeof(dns_rdataset_t));
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = next_msgblock;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff /*
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * rdatalists could be empty.
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff */
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff msgblock = ISC_LIST_HEAD(msg->rdatalists);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (!everything && msgblock != NULL) {
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_reset(msgblock);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff msgblock = ISC_LIST_NEXT(msgblock, link);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff }
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff while (msgblock != NULL) {
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff next_msgblock = ISC_LIST_NEXT(msgblock, link);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff msgblock = next_msgblock;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff if (msg->need_cctx_cleanup == 1)
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff dns_compress_invalidate(&msg->cctx);
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff /*
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Set other bits to normal default values.
f9df80f4348ef68043903efa08299480324f4823Michael Graff */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (!everything)
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msginit(msg);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleydns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
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);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(msgp != NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(*msgp == NULL);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff || intent == DNS_MESSAGE_INTENTRENDER);
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
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley m->magic = DNS_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);
454bea884d271ab2f8a13e924309e6b61b2775b4Andreas Gustafsson ISC_LIST_INIT(m->rdatasets);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->rdatalists);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_INIT(m->freename);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_INIT(m->freerdata);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_INIT(m->freerdataset);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_INIT(m->freerdatalist);
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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (intent == DNS_MESSAGE_INTENTPARSE) {
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
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *msgp = 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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(mctx, msgblock, sizeof(dns_rdataset_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff cleanup4:
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(m->rdatas);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(mctx, msgblock, sizeof(dns_rdata_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff cleanup3:
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(m->names);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(mctx, msgblock, sizeof(dns_name_t));
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
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleydns_message_reset(dns_message_t *msg, unsigned int intent)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley || intent == DNS_MESSAGE_INTENTRENDER);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->from_to_wire = intent;
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgreset(msg, ISC_FALSE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffvoid
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_destroy(dns_message_t **msgp)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_message_t *msg;
f9df80f4348ef68043903efa08299480324f4823Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(msgp != NULL);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(*msgp));
f9df80f4348ef68043903efa08299480324f4823Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff msg = *msgp;
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *msgp = 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
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (curr = ISC_LIST_TAIL(*section) ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr != NULL ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr = ISC_LIST_PREV(curr, link)) {
bd3ccd1c388bd914e6283c8d398c2d926c9005a3Michael Graff if (dns_name_equal(curr, target)) {
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 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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff /*
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * First try: use current buffer.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * Second try: allocate a new buffer and use that.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff tries = 0;
e223094b2248afa2697c531f75e6f84855638becMichael Graff while (tries < 2) {
b02262cbcd550c63f85df76edc6fff556ea5e95dMichael Graff dns_name_init(name, NULL);
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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff INSIST(0); /* Cannot get here... */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (DNS_R_UNEXPECTED);
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
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson /*
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * In dynamic update messages, the rdata can be empty.
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson */
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson if (msg->opcode == dns_opcode_update && rdatalen == 0) {
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson /*
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * When the rdata is empty, the data pointer is never
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * dereferenced, but it must still be non-NULL.
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson */
42a5f9c8f535fb2a6d1cbfaa38533176e1f1667aBob Halley rdata->data = (unsigned char *)"";
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson rdata->length = 0;
0e919917cce54d09407393499ea5c019b93750e2Bob Halley rdata->rdclass = rdclass;
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson rdata->type = rdtype;
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson return DNS_R_SUCCESS;
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson }
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff scratch = currentbuffer(msg);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_buffer_setactive(source, rdatalen);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_decompress_localinit(dctx, name, source);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff /*
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * First try: use current buffer.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * Second try: allocate a new buffer and use that.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael 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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff INSIST(0); /* Cannot get here... */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (DNS_R_UNEXPECTED);
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 /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If this class is different than the one we already 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;
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff msg->state = DNS_SECTION_QUESTION;
e223094b2248afa2697c531f75e6f84855638becMichael Graff } else if (msg->rdclass != rdclass)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_FORMERR);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * Can't ask the same question twice.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = findtype(NULL, name, rdtype);
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (rdatalist == NULL)
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (DNS_R_NOMEMORY);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdataset = newrdataset(msg);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (rdataset == NULL)
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (DNS_R_NOMEMORY);
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);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
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 for (count = 0 ; count < msg->counts[sectionid] ; count++) {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff section = &msg->sections[sectionid];
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
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 * Get type, class, ttl, and rdatalen. Verify that at least
e223094b2248afa2697c531f75e6f84855638becMichael Graff * rdatalen bytes remain. (Some of this is deferred to
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * later.)
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff isc_buffer_remaining(source, &r);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (r.length < 2 + 2 + 4 + 2)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_UNEXPECTEDEND);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdtype = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdclass = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson /*
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson * If there was no question section, we may not yet have
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson * established a class. Do so now.
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson */
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson if (msg->state == DNS_SECTION_ANY) {
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson if (rdclass == 0 || rdclass == dns_rdataclass_any)
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson return (DNS_R_FORMERR);
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson msg->rdclass = rdclass;
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson msg->state = DNS_SECTION_QUESTION;
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson }
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If this class is different than the one in the question
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * section, bail.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (msg->opcode != dns_opcode_update
991322a2ab96f2e2379e3bf8b2220cf89f494ad9Brian Wellington && rdtype != dns_rdatatype_tsig
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff && msg->rdclass != rdclass)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_FORMERR);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If it is a tsig, verify that it is in the additional data
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * section, and switch sections for the rest of this rdata.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (rdtype == dns_rdatatype_tsig) {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (sectionid != DNS_SECTION_ADDITIONAL)
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff return (DNS_R_FORMERR);
991322a2ab96f2e2379e3bf8b2220cf89f494ad9Brian Wellington if (rdclass != dns_rdataclass_any)
991322a2ab96f2e2379e3bf8b2220cf89f494ad9Brian Wellington return (DNS_R_FORMERR);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff section = &msg->sections[DNS_SECTION_TSIG];
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff }
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff r.length -= (2 + 2 + 4 + 2);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (r.length < rdatalen)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_UNEXPECTEDEND);
e223094b2248afa2697c531f75e6f84855638becMichael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If we are doing a dynamic update don't bother searching
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * for a name, just append this one to the end of the message.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (msg->opcode == dns_opcode_update
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff || rdtype == dns_rdatatype_tsig) {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff ISC_LIST_APPEND(*section, name, link);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff } else {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * Run through the section, looking to see if this name
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * is already there. If it is found, put back the
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * allocated name since we no longer need it, and set
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * our name pointer to point to the name we found.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff result = findname(&name2, name, section);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If it is a new name, append to the section.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (result == DNS_R_SUCCESS) {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff releasename(msg, name);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff name = name2;
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff } else {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff ISC_LIST_APPEND(*section, name, link);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff }
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff }
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If this is an OPT record, There Can Be Only One.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff#if 0 /* until there is a dns_rdatatype_opt XXXMLG */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (rdtype == dns_rdatatype_opt && msg->opt != NULL)
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff return (DNS_R_FORMERR);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff#endif
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Search name for the particular type and class.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * Skip this stage if in update mode, or this is a TSIG.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (msg->opcode == dns_opcode_update
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff || rdtype == dns_rdatatype_tsig)
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff result = DNS_R_NOTFOUND;
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff else
2726950412a5c598e123554e4d758fe66a2ebc21Michael 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 */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (result == DNS_R_NOTFOUND) {
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 /*
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * Read the rdata from the wire format. Interpret the
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * rdata according to its actual class, even if it had a
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * DynDNS meta-class in the packet. Then put the meta-class
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * back into the finished rdata.
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,
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson msg->rdclass, rdtype, rdatalen, rdata);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (result != DNS_R_SUCCESS)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (result);
0e919917cce54d09407393499ea5c019b93750e2Bob Halley rdata->rdclass = rdclass;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff /*
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * XXXMLG 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);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff /*
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If this is an OPT record, remember it.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff#if 0 /* until there is a dns_rdatatype_opt XXXMLG */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (rdtype == dns_rdatatype_opt)
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff msg->opt = rdata;
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff#endif
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
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff REQUIRE(source != NULL);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->header_ok = 0;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->question_ok = 0;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_buffer_remaining(source, &r);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (r.length < DNS_MESSAGE_HEADERLEN)
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);
b02262cbcd550c63f85df76edc6fff556ea5e95dMichael 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
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->header_ok = 1;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff /*
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * -1 means no EDNS.
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff */
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_decompress_init(&dctx, -1, ISC_FALSE);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff if (dns_decompress_edns(&dctx) > 1 || !dns_decompress_strict(&dctx))
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL);
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff else
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ret = getquestions(source, msg, &dctx);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (ret != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (ret);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->question_ok = 1;
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;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff dns_result_t result;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(buffer != NULL);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer == NULL);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff result = dns_compress_init(&msg->cctx, -1, msg->mctx);
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff if (result != DNS_R_SUCCESS)
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff return (result);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff msg->need_cctx_cleanup = 1;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff /*
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Reserve enough space for the header in this buffer.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff msg->buffer = buffer;
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael 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
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(rn.length > r.length);
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{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(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
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
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
a920f559c3689f52731519a9d5169ad5814866edMichael Graffdns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff unsigned int priority, unsigned int options)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
a920f559c3689f52731519a9d5169ad5814866edMichael Graff dns_namelist_t *section;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff dns_name_t *name, *next_name;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff dns_rdataset_t *rdataset, *next_rdataset;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff unsigned int count, total;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff dns_result_t result;
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff isc_buffer_t st; /* for rollbacks */
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff (void)priority; /* XXXMLG implement */
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff (void)options; /* XXXMLG implement */
a920f559c3689f52731519a9d5169ad5814866edMichael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
a920f559c3689f52731519a9d5169ad5814866edMichael Graff REQUIRE(VALID_NAMED_SECTION(sectionid));
a920f559c3689f52731519a9d5169ad5814866edMichael Graff
a920f559c3689f52731519a9d5169ad5814866edMichael Graff section = &msg->sections[sectionid];
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff name = ISC_LIST_HEAD(*section);
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff if (name == NULL)
1db717f2f36d45f0f545083a72189c68add162d0Bob Halley return (DNS_R_SUCCESS);
41cc03374dc7fd58d3b099d6c921f192a7bbb5f7Michael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff /*
bfbf3f2d770dc093ac5c74d5fd716ac9521e8715Michael Graff * Shrink the space in the buffer by the reserved amount.
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff */
bfbf3f2d770dc093ac5c74d5fd716ac9521e8715Michael Graff msg->buffer->length -= msg->reserved;
bfbf3f2d770dc093ac5c74d5fd716ac9521e8715Michael Graff
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff total = 0;
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff while (name != NULL) {
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff next_name = ISC_LIST_NEXT(name, link);
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff rdataset = ISC_LIST_HEAD(name->list);
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff while (rdataset != NULL) {
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff next_rdataset = ISC_LIST_NEXT(rdataset, link);
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff if (rdataset->attributes & DNS_RDATASETATTR_RENDERED) {
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff rdataset = next_rdataset;
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff continue;
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff }
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff st = *(msg->buffer);
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff count = 0;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff result = dns_rdataset_towire(rdataset, name,
8d6024e7cffbd84fa8d06ce50c60307d7b3b49c2Michael Graff &msg->cctx,
bfbf3f2d770dc093ac5c74d5fd716ac9521e8715Michael Graff msg->buffer, &count);
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff total += count;
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff /*
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff * If out of space, record stats on what we rendered
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff * so far, and return that status.
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff *
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * XXXMLG Need to change this when
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * dns_rdataset_towire() can render partial
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * sets starting at some arbitary point in the set.
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * This will include setting a bit in the
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * rdataset to indicate that a partial rendering
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * was done, and some state saved somewhere
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * (probably in the message struct)
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * to indicate where to continue from.
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff */
d070219e016b292a49f6f8ccd8975bcc18e46e40Michael Graff if (result != DNS_R_SUCCESS) {
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff dns_compress_rollback(&msg->cctx, st.used);
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff *(msg->buffer) = st; /* rollback */
bfbf3f2d770dc093ac5c74d5fd716ac9521e8715Michael Graff msg->buffer->length += msg->reserved;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff msg->counts[sectionid] += total;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff return (result);
d070219e016b292a49f6f8ccd8975bcc18e46e40Michael Graff }
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff rdataset = next_rdataset;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff }
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff name = next_name;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff
bfbf3f2d770dc093ac5c74d5fd716ac9521e8715Michael Graff msg->buffer->length += msg->reserved;
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff msg->counts[sectionid] += total;
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff
1db717f2f36d45f0f545083a72189c68add162d0Bob Halley return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graffdns_message_renderend(dns_message_t *msg)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_buffer_t tmpbuf;
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_region_t r;
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff isc_uint16_t tmp;
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff REQUIRE(msg->buffer != NULL);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_buffer_used(msg->buffer, &r);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_buffer_init(&tmpbuf, r.base, r.length, ISC_BUFFERTYPE_BINARY);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_buffer_putuint16(&tmpbuf, msg->id);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff & DNS_MESSAGE_OPCODE_MASK);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); /* XXX edns? */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff isc_buffer_putuint16(&tmpbuf, tmp);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_buffer_putuint16(&tmpbuf, msg->counts[DNS_SECTION_QUESTION]);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_buffer_putuint16(&tmpbuf, msg->counts[DNS_SECTION_ANSWER]);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff isc_buffer_putuint16(&tmpbuf, msg->counts[DNS_SECTION_AUTHORITY]);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp = msg->counts[DNS_SECTION_ADDITIONAL]
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff + msg->counts[DNS_SECTION_TSIG];
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff isc_buffer_putuint16(&tmpbuf, tmp);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff msg->buffer = NULL; /* forget about this buffer only on success XXX */
f9df80f4348ef68043903efa08299480324f4823Michael Graff
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff dns_compress_invalidate(&msg->cctx);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff msg->need_cctx_cleanup = 0;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_firstname(dns_message_t *msg, dns_section_t section)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_nextname(dns_message_t *msg, dns_section_t section)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(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
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff return (DNS_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{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(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{
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff dns_name_t *foundname;
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff dns_result_t result;
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
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff /*
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff * Search through, looking for the name.
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff */
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff result = findname(&foundname, target, &msg->sections[section]);
a920f559c3689f52731519a9d5169ad5814866edMichael Graff if (result == DNS_R_NOTFOUND)
a920f559c3689f52731519a9d5169ad5814866edMichael Graff return (DNS_R_NXDOMAIN);
a920f559c3689f52731519a9d5169ad5814866edMichael Graff else if (result != DNS_R_SUCCESS)
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff return (result);
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff if (name != NULL)
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff *name = foundname;
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff /*
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff * And now look for the type.
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff */
08d94b539a96857670540342df4d81ea55348d03Michael Graff if (type == dns_rdatatype_any)
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff return (DNS_R_SUCCESS);
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff result = findtype(rdataset, foundname, type);
a920f559c3689f52731519a9d5169ad5814866edMichael Graff if (result == DNS_R_NOTFOUND)
a920f559c3689f52731519a9d5169ad5814866edMichael Graff return (DNS_R_NXRDATASET);
a920f559c3689f52731519a9d5169ad5814866edMichael Graff
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff return (result);
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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(name != NULL);
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(fromsection));
f9df80f4348ef68043903efa08299480324f4823Michael Graff REQUIRE(VALID_NAMED_SECTION(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);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
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}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_result_t
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_gettempname(dns_message_t *msg, dns_name_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item == NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = newname(msg);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff if (*item == NULL)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_NOMEMORY);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_SUCCESS);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_result_t
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item == NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = newrdata(msg);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff if (*item == NULL)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_NOMEMORY);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_SUCCESS);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_result_t
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item == NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = newrdataset(msg);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff if (*item == NULL)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_NOMEMORY);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_SUCCESS);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_result_t
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item == NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = newrdatalist(msg);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff if (*item == NULL)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_NOMEMORY);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_SUCCESS);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffvoid
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_puttempname(dns_message_t *msg, dns_name_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item != NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff releasename(msg, *item);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = NULL;
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffvoid
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item != NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff releaserdata(msg, *item);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = NULL;
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffvoid
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item != NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff releaserdataset(msg, *item);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = NULL;
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffvoid
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graffdns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff{
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff REQUIRE(item != NULL && *item != NULL);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff releaserdatalist(msg, *item);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff *item = NULL;
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graffdns_result_t
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graffdns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff unsigned int *flagsp)
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff{
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff isc_region_t r;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff isc_buffer_t buffer;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff dns_messageid_t id;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff unsigned int flags;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff REQUIRE(source != NULL);
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff buffer = *source;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff isc_buffer_remaining(&buffer, &r);
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff if (r.length < DNS_MESSAGE_HEADERLEN)
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff return (DNS_R_UNEXPECTEDEND);
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff
5039f2cad30410b47330c14c0d7ce4ca493a8712Michael Graff id = isc_buffer_getuint16(&buffer);
5039f2cad30410b47330c14c0d7ce4ca493a8712Michael Graff flags = isc_buffer_getuint16(&buffer);
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff flags &= DNS_MESSAGE_FLAG_MASK;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff if (flagsp != NULL)
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff *flagsp = flags;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff if (idp != NULL)
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff *idp = id;
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff return (DNS_R_SUCCESS);
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff}
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleydns_result_t
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleydns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley unsigned int first_section;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley if (!msg->header_ok)
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley return (DNS_R_FORMERR);
a6ebd71eed266a08850b5300c2effb18bdb87c8cBob Halley if (msg->opcode != dns_opcode_query)
a6ebd71eed266a08850b5300c2effb18bdb87c8cBob Halley want_question_section = ISC_FALSE;
a6ebd71eed266a08850b5300c2effb18bdb87c8cBob Halley if (want_question_section) {
a6ebd71eed266a08850b5300c2effb18bdb87c8cBob Halley if (!msg->question_ok)
a6ebd71eed266a08850b5300c2effb18bdb87c8cBob Halley return (DNS_R_FORMERR);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley first_section = DNS_SECTION_ANSWER;
a6ebd71eed266a08850b5300c2effb18bdb87c8cBob Halley } else
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley first_section = DNS_SECTION_QUESTION;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msgresetnames(msg, first_section);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msginitprivate(msg);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley /*
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * We now clear most flags and then set QR, ensuring that the
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * reply's flags will be in a reasonable state.
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley */
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msg->flags |= DNS_MESSAGEFLAG_QR;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley return (DNS_R_SUCCESS);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley}