message.c revision 2871292a5674f7dcf300b3dc25969bb6e9656020
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff/*
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999, 2000 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>
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington#include <dns/tsig.h>
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington#include <dns/dnssec.h>
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington#include <dns/view.h>
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff
75ec9bc9c7b4f2485647414330122e7b8e188097Andreas Gustafsson#define DNS_MESSAGE_OPCODE_MASK 0x7800U
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley#define DNS_MESSAGE_OPCODE_SHIFT 11
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff#define DNS_MESSAGE_RCODE_MASK 0x000fU
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff#define DNS_MESSAGE_FLAG_MASK 0x8ff0U
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley#define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley#define DNS_MESSAGE_EDNSRCODE_SHIFT 24
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley#define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley#define DNS_MESSAGE_EDNSVERSION_SHIFT 16
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 */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic inline isc_result_t
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafssonnewbuffer(dns_message_t *msg, unsigned int size)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_result_t result;
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff isc_buffer_t *dynbuf;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dynbuf = NULL;
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff result = isc_buffer_allocate(msg->mctx, &dynbuf, 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{
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff isc_buffer_t *dynbuf;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dynbuf = ISC_LIST_TAIL(msg->scratchpad);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff INSIST(dynbuf != NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff return (dynbuf);
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
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 */
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley m->opt_reserved = 0;
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff m->reserved = 0;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff m->buffer = NULL;
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff m->need_cctx_cleanup = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonstatic inline void
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonmsginittsig(dns_message_t *m)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington{
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington m->tsigstatus = m->querytsigstatus = dns_rcode_noerror;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington m->tsig = m->querytsig = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington m->tsigkey = NULL;
24694ab18a48bcc9c50304bd8b7eb6b9c7650129Brian Wellington m->tsigctx = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington m->sigstart = -1;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington m->sig0key = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington m->sig0status = dns_rcode_noerror;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington m->query = NULL;
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington m->saved = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
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);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington msginittsig(m);
996028142c5f95492fcd42e69186b95641320c7bBob Halley m->header_ok = 0;
996028142c5f95492fcd42e69186b95641320c7bBob Halley m->question_ok = 0;
24694ab18a48bcc9c50304bd8b7eb6b9c7650129Brian Wellington m->tcp_continuation = 0;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington m->verified_sig0 = 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
f2762b0d99a9f1cc43f57f713aa632f6abe37892Michael Graff INSIST(dns_rdataset_isassociated(rds));
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_rdataset_disassociate(rds);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_put(msg->rdspool, rds);
f9df80f4348ef68043903efa08299480324f4823Michael Graff rds = next_rds;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_put(msg->namepool, name);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff name = next_name;
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
f9df80f4348ef68043903efa08299480324f4823Michael Graff }
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley}
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halleystatic void
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halleymsgresetopt(dns_message_t *msg)
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley{
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley if (msg->opt != NULL) {
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley if (msg->opt_reserved > 0) {
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley dns_message_renderrelease(msg, msg->opt_reserved);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msg->opt_reserved = 0;
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley }
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley INSIST(dns_rdataset_isassociated(msg->opt));
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley dns_rdataset_disassociate(msg->opt);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley isc_mempool_put(msg->rdspool, msg->opt);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msg->opt = NULL;
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley }
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley}
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob 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;
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff isc_buffer_t *dynbuf, *next_dynbuf;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_rdata_t *rdata;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley dns_rdatalist_t *rdatalist;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley msgresetnames(msg, 0);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msgresetopt(msg);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
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 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
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = ISC_LIST_HEAD(msg->scratchpad);
f9df80f4348ef68043903efa08299480324f4823Michael Graff INSIST(dynbuf != NULL);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (!everything) {
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff isc_buffer_clear(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);
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff isc_buffer_free(&dynbuf);
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = next_dynbuf;
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
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
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (msg->tsig != NULL) {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_rdata_freestruct(msg->tsig);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley isc_mem_put(msg->mctx, msg->tsig,
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley sizeof(dns_rdata_any_tsig_t));
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->tsig = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (msg->querytsig != NULL) {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_rdata_freestruct(msg->querytsig);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_mem_put(msg->mctx, msg->querytsig,
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington sizeof(dns_rdata_any_tsig_t));
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->querytsig = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (msg->tsigkey != NULL) {
b6666e61dc9b91f4ac6af3aa1172bfd8a5f2d6ffBrian Wellington dns_tsigkey_free(&msg->tsigkey);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->tsigkey = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (msg->query != NULL) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_mem_put(msg->mctx, msg->query->base, msg->query->length);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_mem_put(msg->mctx, msg->query, sizeof(isc_region_t));
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->query = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington if (msg->saved != NULL) {
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington isc_mem_put(msg->mctx, msg->saved->base, msg->saved->length);
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington isc_mem_put(msg->mctx, msg->saved, sizeof(isc_region_t));
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved = NULL;
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington }
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff /*
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * cleanup the buffer cleanup list
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff */
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff dynbuf = ISC_LIST_HEAD(msg->cleanup);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff while (dynbuf != NULL) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
069104dd6a1bba610d0c3a413459accf73f3921bBrian Wellington ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_buffer_free(&dynbuf);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff dynbuf = next_dynbuf;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff }
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael 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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_result_t result;
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_msgblock_t *msgblock;
4556681e191b7c1654639895ce719d98f2822ee2Michael Graff isc_buffer_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
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff /*
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * No allocations until further notice. Just initialize all lists
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * and other members that are freed in the cleanup phase here.
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff */
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley m->magic = DNS_MESSAGE_MAGIC;
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->from_to_wire = intent;
f9df80f4348ef68043903efa08299480324f4823Michael Graff msginit(m);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff for (i = 0 ; i < DNS_SECTION_MAX ; i++)
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->sections[i]);
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->mctx = mctx;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->scratchpad);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff ISC_LIST_INIT(m->cleanup);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff m->namepool = NULL;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff m->rdspool = NULL;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->rdatas);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_INIT(m->rdatalists);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_INIT(m->freerdata);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_INIT(m->freerdatalist);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff /*
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * Ok, it is safe to allocate (and then "goto cleanup" if failure)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff */
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (result != ISC_R_SUCCESS)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff goto cleanup;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_setfreemax(m->namepool, NAME_COUNT);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_setfillcount(m->namepool, NAME_COUNT);
0583bf2d0affe0a90ca2284cc27840b160029ff9Michael Graff isc_mempool_setname(m->namepool, "msg:names");
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff &m->rdspool);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff if (result != ISC_R_SUCCESS)
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_setfillcount(m->rdspool, NAME_COUNT);
0583bf2d0affe0a90ca2284cc27840b160029ff9Michael Graff isc_mempool_setname(m->rdspool, "msg:rdataset");
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = NULL;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE,
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff ISC_BUFFERTYPE_BINARY);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (result != ISC_R_SUCCESS)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff goto cleanup;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = msgblock_allocate(mctx, sizeof(dns_rdata_t),
f9df80f4348ef68043903efa08299480324f4823Michael Graff RDATA_COUNT);
f9df80f4348ef68043903efa08299480324f4823Michael Graff if (msgblock == NULL)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff goto cleanup;
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(m->rdatas, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael 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)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff goto cleanup;
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 */
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff cleanup:
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = ISC_LIST_HEAD(m->rdatas);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (msgblock != NULL)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff msgblock_free(mctx, msgblock, sizeof(dns_rdata_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff dynbuf = ISC_LIST_HEAD(m->scratchpad);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (dynbuf != NULL)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_buffer_free(&dynbuf);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (m->namepool != NULL)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_destroy(&m->namepool);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff if (m->rdspool != NULL)
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_destroy(&m->rdspool);
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);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_destroy(&msg->namepool);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_destroy(&msg->rdspool);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->magic = 0;
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic isc_result_t
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halleyfindname(dns_name_t **foundname, dns_name_t *target, unsigned int attributes,
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley 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)) {
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (dns_name_equal(curr, target) &&
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley (curr->attributes & attributes) == attributes) {
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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graffdns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff dns_rdatatype_t covers, dns_rdataset_t **rdataset)
e223094b2248afa2697c531f75e6f84855638becMichael Graff{
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataset_t *curr;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff if (rdataset != NULL) {
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff REQUIRE(*rdataset == NULL);
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff }
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (curr = ISC_LIST_TAIL(name->list) ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr != NULL ;
e223094b2248afa2697c531f75e6f84855638becMichael Graff curr = ISC_LIST_PREV(curr, link)) {
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley if (curr->type == type && curr->covers == covers) {
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 */
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic isc_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;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_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
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson result = newbuffer(msg, SCRATCHPAD_SIZE);
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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic isc_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;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff unsigned int tries;
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson unsigned int trysize;
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.
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * Second try: allocate a new buffer of size
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * (the data will fit if it was not more than 50% compressed)
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * Subsequent tries: double buffer size on each try.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff tries = 0;
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson trysize = 0;
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson for (;;) {
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) {
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson if (tries == 0) {
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson trysize = 2 * rdatalen;
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson if (trysize < SCRATCHPAD_SIZE)
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson trysize = SCRATCHPAD_SIZE;
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson } else {
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson INSIST(trysize != 0);
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson if (trysize >= 65535)
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson return (ISC_R_NOSPACE);
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson /* XXX DNS_R_RRTOOLONG? */
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson trysize *= 2;
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson }
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff tries++;
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson result = newbuffer(msg, trysize);
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}
e223094b2248afa2697c531f75e6f84855638becMichael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic isc_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;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdatatype_t rdtype;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataclass_t rdclass;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_namelist_t *section;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_boolean_t free_name;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff section = &msg->sections[DNS_SECTION_QUESTION];
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff name = NULL;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff rdataset = NULL;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff rdatalist = NULL;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (count = 0 ; count < msg->counts[DNS_SECTION_QUESTION] ; count++) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff name = isc_mempool_get(msg->namepool);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (name == NULL)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_NOMEMORY);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff free_name = ISC_TRUE;
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)
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
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 */
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley result = findname(&name2, name, 0, 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);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff free_name = ISC_FALSE;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff } else {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = DNS_R_FORMERR;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff } else {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_put(msg->namepool, name);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff name = name2;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff name2 = NULL;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff free_name = ISC_FALSE;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Get type and class.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff isc_buffer_remaining(source, &r);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (r.length < 4) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = DNS_R_UNEXPECTEDEND;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff }
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;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff } else if (msg->rdclass != rdclass) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = DNS_R_FORMERR;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * Can't ask the same question twice.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff result = dns_message_findtype(name, rdtype, 0, NULL);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (result == DNS_R_SUCCESS) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = DNS_R_FORMERR;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff /*
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Allocate a new rdatalist.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff */
e223094b2248afa2697c531f75e6f84855638becMichael Graff rdatalist = newrdatalist(msg);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (rdatalist == NULL) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = DNS_R_NOMEMORY;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff }
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff rdataset = isc_mempool_get(msg->rdspool);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff if (rdataset == NULL) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = DNS_R_NOMEMORY;
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff }
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;
8b791b4ee85d7926170438752aae9c76f35a056fMark Andrews rdatalist->covers = 0;
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)
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff goto cleanup;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff ISC_LIST_APPEND(name->list, rdataset, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff }
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_SUCCESS);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff cleanup:
f2762b0d99a9f1cc43f57f713aa632f6abe37892Michael Graff if (rdataset != NULL) {
f2762b0d99a9f1cc43f57f713aa632f6abe37892Michael Graff INSIST(!dns_rdataset_isassociated(rdataset));
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_put(msg->rdspool, rdataset);
f2762b0d99a9f1cc43f57f713aa632f6abe37892Michael Graff }
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff#if 0
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff if (rdatalist != NULL)
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_put(msg->rdlpool, rdatalist);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff#endif
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff if (free_name)
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_put(msg->namepool, name);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff return (result);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffstatic isc_result_t
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffgetsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson dns_section_t sectionid, isc_boolean_t preserve_order)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff{
e223094b2248afa2697c531f75e6f84855638becMichael Graff isc_region_t r;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley unsigned int count, rdatalen, attributes;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_name_t *name;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_name_t *name2;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataset_t *rdataset;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdatalist_t *rdatalist;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley dns_rdatatype_t rdtype, covers;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_rdataclass_t rdclass;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_rdata_t *rdata;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_ttl_t ttl;
e223094b2248afa2697c531f75e6f84855638becMichael Graff dns_namelist_t *section;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff isc_boolean_t free_name, free_rdataset;
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (count = 0 ; count < msg->counts[sectionid] ; count++) {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington int recstart = source->current;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley isc_boolean_t skip_name_search, skip_type_search;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff section = &msg->sections[sectionid];
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_name_search = ISC_FALSE;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_type_search = ISC_FALSE;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_name = ISC_FALSE;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_rdataset = ISC_FALSE;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff name = isc_mempool_get(msg->namepool);
e223094b2248afa2697c531f75e6f84855638becMichael Graff if (name == NULL)
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_NOMEMORY);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_name = ISC_TRUE;
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)
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
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);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (r.length < 2 + 2 + 4 + 2) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_UNEXPECTEDEND;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
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) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (rdclass == 0 || rdclass == dns_rdataclass_any) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_FORMERR;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
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
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley && rdtype != dns_rdatatype_opt
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington && rdtype != dns_rdatatype_key /* XXX in a TKEY query */
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington && rdtype != dns_rdatatype_sig /* XXX SIG(0) */
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff && msg->rdclass != rdclass) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_FORMERR;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff /*
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington * Special type handling for TSIG, OPT, and TKEY.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff if (rdtype == dns_rdatatype_tsig) {
bf555703f27295798de30fa8c04d727410788f66Bob Halley /*
bf555703f27295798de30fa8c04d727410788f66Bob Halley * If it is a tsig, verify that it is in the
bf555703f27295798de30fa8c04d727410788f66Bob Halley * additional data section, and switch sections for
bf555703f27295798de30fa8c04d727410788f66Bob Halley * the rest of this rdata.
bf555703f27295798de30fa8c04d727410788f66Bob Halley */
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if ((sectionid != DNS_SECTION_ADDITIONAL)
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff || (rdclass != dns_rdataclass_any)) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_FORMERR;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff section = &msg->sections[DNS_SECTION_TSIG];
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->sigstart = recstart;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_name_search = ISC_TRUE;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_type_search = ISC_TRUE;
bf555703f27295798de30fa8c04d727410788f66Bob Halley } else if (rdtype == dns_rdatatype_opt) {
bf555703f27295798de30fa8c04d727410788f66Bob Halley /*
bf555703f27295798de30fa8c04d727410788f66Bob Halley * The name of an OPT record must be ".", it
bf555703f27295798de30fa8c04d727410788f66Bob Halley * must be in the additional data section, and
bf555703f27295798de30fa8c04d727410788f66Bob Halley * it must be the first OPT we've seen.
bf555703f27295798de30fa8c04d727410788f66Bob Halley */
bf555703f27295798de30fa8c04d727410788f66Bob Halley if (!dns_name_equal(dns_rootname, name) ||
bf555703f27295798de30fa8c04d727410788f66Bob Halley sectionid != DNS_SECTION_ADDITIONAL ||
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff msg->opt != NULL) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_FORMERR;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_name_search = ISC_TRUE;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_type_search = ISC_TRUE;
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington } else if (rdtype == dns_rdatatype_tkey) {
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington /*
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington * A TKEY must be in the additional section.
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington * Its class is ignored.
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington */
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (sectionid != DNS_SECTION_ADDITIONAL) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_FORMERR;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
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);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (r.length < rdatalen) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_UNEXPECTEDEND;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley /*
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * Read the rdata from the wire format. Interpret the
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * rdata according to its actual class, even if it had a
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * DynDNS meta-class in the packet (unless this is a TSIG).
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * Then put the meta-class back into the finished rdata.
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley */
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley rdata = newrdata(msg);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (rdata == NULL) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_NOMEMORY;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley attributes = 0;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (rdtype != dns_rdatatype_tsig) {
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (rdtype == dns_rdatatype_cname) {
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley name->attributes |= DNS_NAMEATTR_CNAME;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley attributes = DNS_NAMEATTR_CNAME;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_name_search = ISC_TRUE;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley } else if (rdtype == dns_rdatatype_dname) {
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley name->attributes |= DNS_NAMEATTR_DNAME;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley attributes = DNS_NAMEATTR_DNAME;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_name_search = ISC_TRUE;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley }
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley result = getrdata(name, source, msg, dctx,
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley msg->rdclass, rdtype,
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley rdatalen, rdata);
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley } else
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley result = getrdata(name, source, msg, dctx,
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley rdclass, rdtype, rdatalen, rdata);
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (result != DNS_R_SUCCESS)
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley rdata->rdclass = rdclass;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (rdtype == dns_rdatatype_sig && rdata->length > 0) {
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley covers = dns_rdata_covers(rdata);
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (covers == dns_rdatatype_cname)
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley attributes = DNS_NAMEATTR_CNAME;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley else if (covers == dns_rdatatype_dname)
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley attributes = DNS_NAMEATTR_DNAME;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else if (covers == 0) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->sigstart = recstart;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington section = &msg->sections[DNS_SECTION_SIG0];
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley } else
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley covers = 0;
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley
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 */
bf555703f27295798de30fa8c04d727410788f66Bob Halley if (preserve_order || msg->opcode == dns_opcode_update ||
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_name_search) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (rdtype != dns_rdatatype_opt) {
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley ISC_LIST_APPEND(*section, name, link);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_name = ISC_FALSE;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
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 */
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley result = findname(&name2, name, attributes, 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) {
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_put(msg->namepool, name);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff name = name2;
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff } else {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff ISC_LIST_APPEND(*section, name, link);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff }
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_name = ISC_FALSE;
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff }
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 */
bf555703f27295798de30fa8c04d727410788f66Bob Halley if (preserve_order || msg->opcode == dns_opcode_update ||
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley skip_type_search)
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff result = DNS_R_NOTFOUND;
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff else {
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff rdataset = NULL;
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff result = dns_message_findtype(name, rdtype, covers,
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff &rdataset);
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff }
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.
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley *
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * XXXRTH Check for attempts to create multi-record RRsets
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * for singleton RR types.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff if (result == DNS_R_NOTFOUND) {
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff rdataset = isc_mempool_get(msg->rdspool);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (rdataset == NULL) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_NOMEMORY;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_rdataset = ISC_TRUE;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist = newrdatalist(msg);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (rdatalist == NULL) {
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff result = DNS_R_NOMEMORY;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff goto cleanup;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist->type = rdtype;
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley rdatalist->covers = covers;
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
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (rdtype != dns_rdatatype_opt) {
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley ISC_LIST_APPEND(name->list, rdataset, link);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_rdataset = ISC_FALSE;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff }
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff /*
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * Minimize TTLs.
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley *
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * Section 5.2 of RFC 2181 says we should drop
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * nonauthoritative rrsets where the TTLs differ, but we
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * currently treat them the as if they were authoritative and
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * minimize them.
e223094b2248afa2697c531f75e6f84855638becMichael Graff */
59602a44858a55fce25565491d4fec6d2cdcca19Michael Graff if (ttl != rdataset->ttl) {
59602a44858a55fce25565491d4fec6d2cdcca19Michael Graff rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
59602a44858a55fce25565491d4fec6d2cdcca19Michael Graff if (ttl < rdataset->ttl)
59602a44858a55fce25565491d4fec6d2cdcca19Michael Graff rdataset->ttl = ttl;
59602a44858a55fce25565491d4fec6d2cdcca19Michael Graff }
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 /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * If this is an OPT record, remember it. Also, set
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * the extended rcode.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley if (rdtype == dns_rdatatype_opt) {
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley unsigned int ercode;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
bf555703f27295798de30fa8c04d727410788f66Bob Halley msg->opt = rdataset;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff rdataset = NULL;
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_rdataset = ISC_FALSE;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley ercode = (msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley >> 20;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley msg->rcode |= ercode;
7153a32ae99388656620b200e6f4ba6e170a208cMichael Graff isc_mempool_put(msg->namepool, name);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff free_name = ISC_FALSE;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley }
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff INSIST(free_name == ISC_FALSE);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff INSIST(free_rdataset == ISC_FALSE);
e223094b2248afa2697c531f75e6f84855638becMichael Graff }
e223094b2248afa2697c531f75e6f84855638becMichael Graff
e223094b2248afa2697c531f75e6f84855638becMichael Graff return (DNS_R_SUCCESS);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff cleanup:
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (free_name)
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff isc_mempool_put(msg->namepool, name);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (free_rdataset)
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff isc_mempool_put(msg->rdspool, rdataset);
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff return (result);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff}
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafssondns_message_parse(dns_message_t *msg, isc_buffer_t *source,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson isc_boolean_t preserve_order)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff isc_region_t r;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff dns_decompress_t dctx;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t ret;
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff isc_uint16_t tmpflags;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_buffer_t origsource;
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
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington origsource = *source;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
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
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson preserve_order);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (ret != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (ret);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson preserve_order);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff if (ret != DNS_R_SUCCESS)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (ret);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson preserve_order);
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
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_TSIG]) ||
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington !ISC_LIST_EMPTY(msg->sections[DNS_SECTION_SIG0]))
24694ab18a48bcc9c50304bd8b7eb6b9c7650129Brian Wellington {
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved = isc_mem_get(msg->mctx, sizeof(isc_region_t));
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington if (msg->saved == NULL)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (ISC_R_NOMEMORY);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_buffer_used(&origsource, &r);
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved->length = r.length;
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved->base = isc_mem_get(msg->mctx, msg->saved->length);
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington if (msg->saved->base == NULL) {
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington isc_mem_put(msg->mctx, msg->saved,
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington sizeof(isc_region_t));
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (ISC_R_NOMEMORY);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington memcpy(msg->saved->base, r.base, msg->saved->length);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff return (DNS_R_SUCCESS);
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_renderbegin(dns_message_t *msg, isc_buffer_t *buffer)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff isc_region_t r;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halleyvoid
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);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley REQUIRE(space <= msg->reserved);
f9df80f4348ef68043903efa08299480324f4823Michael Graff
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->reserved -= space;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}
f9df80f4348ef68043903efa08299480324f4823Michael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graffstatic inline isc_boolean_t
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graffwrong_priority(dns_rdataset_t *rds, int pass)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff{
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff int pass_needed;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff /*
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * If we are not rendering class IN, this ordering is bogus.
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff */
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if (rds->rdclass != dns_rdataclass_in)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff return (ISC_FALSE);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff switch (rds->type) {
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff case dns_rdatatype_a:
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff case dns_rdatatype_aaaa:
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff case dns_rdatatype_a6:
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff pass_needed = 3;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff break;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff case dns_rdatatype_sig:
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff case dns_rdatatype_key:
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff pass_needed = 2;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff break;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff default:
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff pass_needed = 1;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff }
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if (pass_needed >= pass)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff return (ISC_FALSE);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff return (ISC_TRUE);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff}
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
a920f559c3689f52731519a9d5169ad5814866edMichael Graffdns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff 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;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff isc_buffer_t st; /* for rollbacks */
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff int pass;
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
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if ((sectionid == DNS_SECTION_ADDITIONAL)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff && (options & DNS_MESSAGERENDER_ORDERED) == 0)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff pass = 3;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff else
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff pass = 1;
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
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff do {
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff name = ISC_LIST_HEAD(*section);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if (name == NULL)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff return (DNS_R_SUCCESS);
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff while (name != NULL) {
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff next_name = ISC_LIST_NEXT(name, link);
823e45c1273512a8048cd5e7e57f31f58c964f7fMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff rdataset = ISC_LIST_HEAD(name->list);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff while (rdataset != NULL) {
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff next_rdataset = ISC_LIST_NEXT(rdataset, link);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if (rdataset->attributes & DNS_RDATASETATTR_RENDERED)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff goto next;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if (((options & DNS_MESSAGERENDER_ORDERED) == 0)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff && (sectionid == DNS_SECTION_ADDITIONAL)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff && wrong_priority(rdataset, pass))
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff goto next;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff st = *(msg->buffer);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff count = 0;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff result = dns_rdataset_towire(rdataset, name,
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff &msg->cctx,
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff msg->buffer, &count);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff total += count;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff /*
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * If out of space, record stats on what we rendered
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * so far, and return that status.
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff *
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * XXXMLG Need to change this when
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * dns_rdataset_towire() can render partial
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * sets starting at some arbitary point in the set.
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * This will include setting a bit in the
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * rdataset to indicate that a partial rendering
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * was done, and some state saved somewhere
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * (probably in the message struct)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * to indicate where to continue from.
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff */
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if (result != DNS_R_SUCCESS) {
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff INSIST(st.used < 65536);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff dns_compress_rollback(&msg->cctx,
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff (isc_uint16_t)st.used);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff *(msg->buffer) = st; /* rollback */
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff msg->buffer->length += msg->reserved;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff msg->counts[sectionid] += total;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff return (result);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff }
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff /*
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * If we have rendered pending data, ensure that the
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * AD bit is not set.
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff */
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff if (rdataset->trust == dns_trust_pending &&
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff (sectionid == DNS_SECTION_ANSWER ||
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff sectionid == DNS_SECTION_AUTHORITY))
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff msg->flags &= ~DNS_MESSAGEFLAG_AD;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff next:
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff rdataset = next_rdataset;
d070219e016b292a49f6f8ccd8975bcc18e46e40Michael Graff }
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff name = next_name;
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff }
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff } while (--pass != 0);
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
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonvoid
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtondns_message_renderheader(dns_message_t *msg, isc_buffer_t *target)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff isc_uint16_t tmp;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_region_t r;
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(target != NULL);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_available(target, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_putuint16(target, msg->id);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff & DNS_MESSAGE_OPCODE_MASK);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence msg->counts[DNS_SECTION_ANSWER] < 65536 &&
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence (msg->counts[DNS_SECTION_ADDITIONAL] +
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->counts[DNS_SECTION_TSIG] +
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington msg->counts[DNS_SECTION_SIG0]) < 65536);
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_putuint16(target, tmp);
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence isc_buffer_putuint16(target,
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence isc_buffer_putuint16(target,
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence isc_buffer_putuint16(target,
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp = msg->counts[DNS_SECTION_ADDITIONAL]
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington + msg->counts[DNS_SECTION_TSIG]
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington + msg->counts[DNS_SECTION_SIG0];
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_putuint16(target, tmp);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington}
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtondns_message_renderend(dns_message_t *msg)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington{
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_t tmpbuf;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_region_t r;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington int result;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley unsigned int count;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(DNS_MESSAGE_VALID(msg));
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(msg->buffer != NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * We have an extended rcode but are not using EDNS.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley return (DNS_R_FORMERR);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley }
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * If we've got an OPT record, render it.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley if (msg->opt != NULL) {
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley dns_message_renderrelease(msg, msg->opt_reserved);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msg->opt_reserved = 0;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * Set the extended rcode.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley msg->opt->ttl |= ((msg->rcode << 20) &
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley DNS_MESSAGE_EDNSRCODE_MASK);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * Render.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley count = 0;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley result = dns_rdataset_towire(msg->opt, dns_rootname,
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley &msg->cctx, msg->buffer, &count);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley msg->counts[DNS_SECTION_ADDITIONAL] += count;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley if (result != ISC_R_SUCCESS)
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley return (result);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley }
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (msg->tsigkey != NULL) {
2871292a5674f7dcf300b3dc25969bb6e9656020Brian Wellington REQUIRE(msg->tsig == NULL);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington result = dns_tsig_sign(msg);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (result != DNS_R_SUCCESS)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (result);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff result = dns_message_rendersection(msg, DNS_SECTION_TSIG, 0);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (result != DNS_R_SUCCESS)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (result);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else if (msg->sig0key != NULL) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_dnssec_signmessage(msg, msg->sig0key);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (result != DNS_R_SUCCESS)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (result);
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff result = dns_message_rendersection(msg, DNS_SECTION_SIG0, 0);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (result != DNS_R_SUCCESS)
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington return (result);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_used(msg->buffer, &r);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington isc_buffer_init(&tmpbuf, r.base, r.length, ISC_BUFFERTYPE_BINARY);
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington dns_message_renderheader(msg, &tmpbuf);
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
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halleyvoid
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halleydns_message_renderreset(dns_message_t *msg)
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley{
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley unsigned int i;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley dns_name_t *name;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley dns_rdataset_t *rds;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley /*
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley * Reset the message so that it may be rendered again.
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley */
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley for (i = 0; i < DNS_SECTION_MAX; i++) {
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley msg->cursors[i] = NULL;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley msg->counts[i] = 0;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley for (name = ISC_LIST_HEAD(msg->sections[i]);
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley name != NULL;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley name = ISC_LIST_NEXT(name, link)) {
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley for (rds = ISC_LIST_HEAD(name->list);
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley rds != NULL;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley rds = ISC_LIST_NEXT(rds, link)) {
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley }
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley }
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley }
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley}
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_findname(dns_message_t *msg, dns_section_t section,
f9df80f4348ef68043903efa08299480324f4823Michael Graff dns_name_t *target, dns_rdatatype_t type,
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley dns_rdatatype_t covers, dns_name_t **name,
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley dns_rdataset_t **rdataset)
f9df80f4348ef68043903efa08299480324f4823Michael Graff{
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff dns_name_t *foundname;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley unsigned int attributes;
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley dns_rdatatype_t atype;
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
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley /*
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley * Figure out what attributes we should look for.
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley */
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley if (type == dns_rdatatype_sig)
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley atype = covers;
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley else
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley atype = type;
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley attributes = 0;
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley if (atype == dns_rdatatype_cname)
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley attributes = DNS_NAMEATTR_CNAME;
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley else if (atype == dns_rdatatype_cname)
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley attributes = DNS_NAMEATTR_DNAME;
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff /*
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff * Search through, looking for the name.
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff */
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley result = findname(&foundname, target, attributes,
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley &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
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff result = dns_message_findtype(foundname, type, covers, rdataset);
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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff *item = isc_mempool_get(msg->namepool);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff if (*item == NULL)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_NOMEMORY);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_SUCCESS);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graffvoid
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graffdns_message_puttempname(dns_message_t *msg, dns_name_t **item)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff{
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff REQUIRE(DNS_MESSAGE_VALID(msg));
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff REQUIRE(item != NULL && *item != NULL);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_put(msg->namepool, *item);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff *item = NULL;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff}
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff *item = isc_mempool_get(msg->rdspool);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff if (*item == NULL)
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_NOMEMORY);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
499371d17c34a5770af022f4aa15e764e957a803Michael Graff dns_rdataset_init(*item);
499371d17c34a5770af022f4aa15e764e957a803Michael Graff
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff return (DNS_R_SUCCESS);
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff}
438d7099d1d6109c2df35d5e6f168fb6c40093f6Michael Graff
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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_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
f2762b0d99a9f1cc43f57f713aa632f6abe37892Michael Graff REQUIRE(!dns_rdataset_isassociated(*item));
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_put(msg->rdspool, *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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_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);
271154eafd1111455030abc2997120228be55ef9Mark Andrews if (msg->opcode != dns_opcode_query &&
271154eafd1111455030abc2997120228be55ef9Mark Andrews msg->opcode != dns_opcode_notify)
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);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msgresetopt(msg);
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
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington /*
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * This saves the query TSIG information for later use, if there is
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * any. This only happens once - that is, if dns_message_reply
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * has already moved the variables, this has no effect.
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington if (msg->tsig != NULL) {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington msg->querytsig = msg->tsig;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington msg->tsig = NULL;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington msg->querytsigstatus = msg->tsigstatus;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington msg->tsigstatus = dns_rcode_noerror;
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington }
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington if (msg->saved != NULL) {
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->query = msg->saved;
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved = NULL;
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington }
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley return (DNS_R_SUCCESS);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley}
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halleydns_rdataset_t *
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halleydns_message_getopt(dns_message_t *msg) {
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * Get the OPT record for 'msg'.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley return (msg->opt);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley}
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halleydns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley dns_rdata_t rdata;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * Set the OPT record for 'msg'.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley /*
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * The space required for an OPT record is:
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley *
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 1 byte for the name
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 2 bytes for the type
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 2 bytes for the class
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 4 bytes for the ttl
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 2 bytes for the rdata length
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * ---------------------------------
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 11 bytes
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley *
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * plus the length of the rdata.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley */
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley REQUIRE(DNS_MESSAGE_VALID(msg));
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley REQUIRE(opt->type == dns_rdatatype_opt);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley REQUIRE(msg->buffer != NULL);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley REQUIRE(msg->state == DNS_SECTION_ANY);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msgresetopt(msg);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley result = dns_rdataset_first(opt);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley if (result != ISC_R_SUCCESS)
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley return (result);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley dns_rdataset_current(opt, &rdata);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msg->opt_reserved = 11 + rdata.length;
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley result = dns_message_renderreserve(msg, msg->opt_reserved);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley if (result != ISC_R_SUCCESS) {
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley msg->opt_reserved = 0;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley return (result);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley }
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley msg->opt = opt;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley return (DNS_R_SUCCESS);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley}
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graffvoid
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graffdns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff{
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff REQUIRE(DNS_MESSAGE_VALID(msg));
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff REQUIRE(buffer != NULL);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff REQUIRE(ISC_BUFFER_VALID(*buffer));
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff ISC_LIST_APPEND(msg->cleanup, *buffer, link);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff *buffer = NULL;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff}
e5c75445501bb0459753f55cf3a9529b3cb794dfBrian Wellington
e5c75445501bb0459753f55cf3a9529b3cb794dfBrian Wellingtonisc_result_t
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellingtondns_message_signer(dns_message_t *msg, dns_name_t *signer) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_region_t r;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_result_t result = ISC_R_SUCCESS;
06f9d6486eab16895ab1538f5530445cb665ba9cBrian Wellington
e5c75445501bb0459753f55cf3a9529b3cb794dfBrian Wellington REQUIRE(DNS_MESSAGE_VALID(msg));
e5c75445501bb0459753f55cf3a9529b3cb794dfBrian Wellington REQUIRE(signer != NULL);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
e5c75445501bb0459753f55cf3a9529b3cb794dfBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if ((msg->tsig == NULL || msg->tsigkey == NULL) &&
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington ISC_LIST_EMPTY(msg->sections[DNS_SECTION_SIG0]))
e5c75445501bb0459753f55cf3a9529b3cb794dfBrian Wellington return (ISC_R_NOTFOUND);
06f9d6486eab16895ab1538f5530445cb665ba9cBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (!dns_name_hasbuffer(signer)) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_buffer_t *dynbuf = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = isc_buffer_allocate(msg->mctx, &dynbuf, 512,
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington ISC_BUFFERTYPE_BINARY);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (result != ISC_R_SUCCESS)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (result);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_name_setbuffer(signer, dynbuf);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_message_takebuffer(msg, &dynbuf);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_SIG0])) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_rdataset_t *dataset;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_rdata_t rdata;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_name_t *sig0name;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_rdata_generic_sig_t sig;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_message_firstname(msg, DNS_SECTION_SIG0);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (result != ISC_R_SUCCESS)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (ISC_R_NOTFOUND);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington sig0name = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_message_currentname(msg, DNS_SECTION_SIG0, &sig0name);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dataset = NULL;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_message_findtype(sig0name, dns_rdatatype_sig, 0,
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington &dataset);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (result != ISC_R_SUCCESS)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (result);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_rdataset_first(dataset);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_rdataset_current(dataset, &rdata);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (result != ISC_R_SUCCESS)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington return (result);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (msg->sig0status != dns_rcode_noerror)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = DNS_R_SIGINVALID;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else if (msg->verified_sig0 == 0)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = DNS_R_NOTVERIFIEDYET;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = ISC_R_SUCCESS;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_name_toregion(&sig.signer, &r);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_name_fromregion(signer, &r);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_rdata_freestruct(&sig);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_name_t *identity;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (msg->tsigstatus != dns_rcode_noerror)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = DNS_R_TSIGVERIFYFAILURE;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else if (msg->tsig->error != dns_rcode_noerror)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = DNS_R_TSIGERRORSET;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = ISC_R_SUCCESS;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington identity = dns_tsigkey_identity(msg->tsigkey);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (identity == NULL) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington if (result == ISC_R_SUCCESS)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = DNS_R_NOIDENTITY;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington identity = &msg->tsigkey->name;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_name_toregion(identity, &r);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington dns_name_fromregion(signer, &r);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington }
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington
06f9d6486eab16895ab1538f5530445cb665ba9cBrian Wellington return (result);
e5c75445501bb0459753f55cf3a9529b3cb794dfBrian Wellington}
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtonisc_result_t
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtondns_message_checksig(dns_message_t *msg, dns_view_t *view) {
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington isc_buffer_t b;
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington REQUIRE(DNS_MESSAGE_VALID(msg));
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington REQUIRE(view != NULL);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington if (msg->tsigkey == NULL &&
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington ISC_LIST_EMPTY(msg->sections[DNS_SECTION_TSIG]))
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington return (ISC_R_SUCCESS);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington if (msg->saved == NULL)
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington return (DNS_R_EXPECTEDTSIG);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington isc_buffer_init(&b, msg->saved->base, msg->saved->length,
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington ISC_BUFFERTYPE_BINARY);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington isc_buffer_add(&b, msg->saved->length);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington return dns_view_checksig(view, &b, msg);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellington}