message.c revision b66b333f59cf51ef87f973084a5023acd9317fb2
45c5f403619029a363cf089e0a4b1bb44425dd84Tinderbox User * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * Copyright (C) 1999-2003 Internet Software Consortium.
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Permission to use, copy, modify, and/or distribute this software for any
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * purpose with or without fee is hereby granted, provided that the above
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * copyright notice and this permission notice appear in all copies.
2f4561bc9cd5e5cdc58e29e600303c812f6902eeAutomatic Updater * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * PERFORMANCE OF THIS SOFTWARE.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#include <isc/string.h> /* Required for HP/UX (and others?) */
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunthexdump(const char *msg, const char *msg2, void *base, size_t len) {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt unsigned char *p;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt unsigned int cnt;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt#define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt return(ISC_R_NOSPACE); else \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt#define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * This is the size of each individual scratchpad buffer, and the numbers
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * of various block allocations used within the server.
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt * XXXMLG These should come from a config setting.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * Text representation of the different items, for message_totext
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt * functions.
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntstatic const char *sectiontext[] = {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "AUTHORITY",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "ADDITIONAL"
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntstatic const char *updsectiontext[] = {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "PREREQUISITE",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "ADDITIONAL"
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntstatic const char *opcodetext[] = {
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "RESERVED3",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "RESERVED6",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED7",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "RESERVED8",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "RESERVED9",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "RESERVED10",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "RESERVED11",
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Hunt "RESERVED12",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED13",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED14",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED15"
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Huntstatic const char *rcodetext[] = {
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED11",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED12",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED13",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED14",
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt "RESERVED15",
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews * "helper" type, which consists of a block of some type, and is linkable.
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
2c089bf6d24936de631a57b4958ba6b8b5e3b23dMark Andrews * size, or the allocated elements will not be aligned correctly.
5ae2eac4c16bdbbef032544bd9fc86f47e7bdc2cMark Andrews unsigned int count;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt unsigned int remaining;
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Hunt}; /* dynamically sized */
e11a0c114cdaf8f7e7832e9f1a011138248093a6Evan Huntstatic inline dns_msgblock_t *
75b8de87879ad017c9cd2ffc328e5d2391d16e99Evan Huntmsgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Hunt ((type *)msgblock_internalget(block, sizeof(type)))
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Huntstatic inline void *
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Huntmsgblock_internalget(dns_msgblock_t *, unsigned int);
bbedadf76ab670b01887fb9b41097120ea4fdf14Evan Huntstatic inline void
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntstatic inline void
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntmsgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntlogfmtpacket(dns_message_t *message, const char *description,
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt isc_sockaddr_t *address, isc_logcategory_t *category,
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt isc_logmodule_t *module, const dns_master_style_t *style,
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt * is free, return NULL.
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntstatic inline dns_msgblock_t *
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Huntmsgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int count)
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt unsigned int length;
61bcc232038f0a2cb77ed6269675fdc288f5ec98Evan Hunt length = sizeof(dns_msgblock_t) + (sizeof_type * count);
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Hunt * Return an element from the msgblock. If no more are available, return
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Huntstatic inline void *
b47c020d5c635b662ac57e5485d266fd62c796c0Evan Huntmsgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrewsstatic inline void
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews * Release memory associated with a message block.
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrewsstatic inline void
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrewsmsgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews unsigned int length;
0d6328ce5f6b799f8e7c6cbbb3b965cf29bfb7baMark Andrews length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
677f507de7c546c187c1505c48bc7b440545485cMark Andrews * Allocate a new dynamic buffer, and attach it to this message as the
677f507de7c546c187c1505c48bc7b440545485cMark Andrews * "current" buffer. (which is always the last on the list, for our
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrewsnewbuffer(dns_message_t *msg, unsigned int size) {
e01ef6f01c7e8f80122cd80a2e011425a0135489Mark Andrews result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static inline isc_buffer_t *
return (dynbuf);
static inline dns_rdata_t *
return (rdata);
return (NULL);
return (rdata);
static inline dns_rdatalist_t *
goto out;
sizeof(dns_rdatalist_t),
return (NULL);
out:
return (rdatalist);
static inline dns_offsets_t *
sizeof(dns_offsets_t),
return (NULL);
return (offsets);
m->id = 0;
m->flags = 0;
m->rcode = 0;
m->opcode = 0;
m->rdclass = 0;
for (i = 0; i < DNS_SECTION_MAX; i++) {
m->counts[i] = 0;
m->opt_reserved = 0;
m->sig_reserved = 0;
m->reserved = 0;
m->timeadjust = 0;
msginitheader(m);
msginitprivate(m);
msginittsig(m);
m->header_ok = 0;
m->question_ok = 0;
m->tcp_continuation = 0;
m->verified_sig = 0;
m->verify_attempted = 0;
m->free_query = 0;
m->free_saved = 0;
m->cc_ok = 0;
m->cc_bad = 0;
if (replying) {
if (!everything) {
if (!everything)
dns_message_t *m;
if (m == NULL)
return (ISC_R_NOMEMORY);
msginit(m);
for (i = 0; i < DNS_SECTION_MAX; i++)
goto cleanup;
&m->rdspool);
goto cleanup;
goto cleanup;
*msgp = m;
return (ISC_R_SUCCESS);
m->magic = 0;
return (ISC_R_NOMEMORY);
static isc_result_t
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
static isc_result_t
unsigned int tries;
tries = 0;
scratch);
tries++;
return (result);
return (result);
return (ISC_R_UNEXPECTED);
static isc_result_t
unsigned int tries;
unsigned int trysize;
tries = 0;
trysize = 0;
scratch);
if (tries == 0) {
return (ISC_R_NOSPACE);
tries++;
return (result);
return (result);
#define DO_FORMERR \
if (best_effort) \
goto cleanup; \
static isc_result_t
unsigned int options)
isc_region_t r;
unsigned int count;
return (ISC_R_NOMEMORY);
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
if (seen_problem)
return (DNS_R_RECOVERABLE);
return (ISC_R_SUCCESS);
if (free_name)
return (result);
static isc_boolean_t
return (ISC_FALSE);
static isc_result_t
isc_region_t r;
return (ISC_R_NOMEMORY);
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
if (rdatalen != 0) {
goto cleanup;
goto cleanup;
if (covers == 0)
if (covers == 0) {
covers = 0;
ISC_FALSE)) {
goto cleanup;
&rdatalist);
goto cleanup;
goto cleanup;
== ISC_R_SUCCESS);
if (seen_problem) {
if (free_name)
if (free_rdataset)
if (seen_problem)
return (DNS_R_RECOVERABLE);
return (ISC_R_SUCCESS);
if (free_name)
if (free_rdataset)
return (result);
unsigned int options)
isc_region_t r;
return (ISC_R_UNEXPECTEDEND);
goto truncated;
return (ret);
goto truncated;
return (ret);
goto truncated;
return (ret);
goto truncated;
return (ret);
if (r.length != 0) {
r.length);
return (ISC_R_NOMEMORY);
return (DNS_R_RECOVERABLE);
return (DNS_R_RECOVERABLE);
return (ISC_R_SUCCESS);
isc_region_t r;
return (ISC_R_NOSPACE);
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
isc_region_t r;
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
static inline isc_boolean_t
int pass_needed;
return (ISC_FALSE);
case dns_rdatatype_a:
case dns_rdatatype_aaaa:
case dns_rdatatype_rrsig:
case dns_rdatatype_dnskey:
return (ISC_FALSE);
return (ISC_TRUE);
#ifdef ALLOW_FILTER_AAAA
static inline isc_boolean_t
return (ISC_FALSE);
case dns_rdatatype_ns:
return (ISC_FALSE);
case dns_rdatatype_aaaa:
return (ISC_FALSE);
case dns_rdatatype_rrsig:
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_TRUE);
unsigned int options)
int pass;
unsigned int rd_options;
rd_options = 0;
total = 0;
count = 0;
if (partial)
name,
&count,
NULL);
name,
&count);
return (result);
return (result);
return (ISC_R_SUCCESS);
DNS_RDATASETATTR_RENDERED) != 0)
goto next;
goto next;
#ifdef ALLOW_FILTER_AAAA
goto next;
count = 0;
if (partial)
name,
&count,
NULL);
name,
&count);
return (result);
return (result);
next:
} while (--pass != 0);
return (ISC_R_SUCCESS);
isc_region_t r;
isc_region_t r;
int result;
unsigned int count;
return (DNS_R_FORMERR);
return (result);
count = 0;
&count);
return (result);
return (result);
count = 0;
&count);
return (result);
return (result);
count = 0;
&count);
return (result);
return (ISC_R_SUCCESS);
for (i = 0; i < DNS_SECTION_MAX; i++) {
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
return (ISC_R_NOMORE);
return (ISC_R_SUCCESS);
return (DNS_R_NXDOMAIN);
return (result);
return (ISC_R_SUCCESS);
return (DNS_R_NXRRSET);
return (result);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
unsigned int *flagsp)
isc_region_t r;
unsigned int flags;
return (ISC_R_UNEXPECTEDEND);
return (ISC_R_SUCCESS);
unsigned int clear_from;
return (DNS_R_FORMERR);
else if (want_question_section) {
return (DNS_R_FORMERR);
unsigned int otherlen = 0;
return (result);
return (ISC_R_SUCCESS);
goto cleanup;
goto cleanup;
return (ISC_R_SUCCESS);
return (result);
return (result);
return (ISC_R_SUCCESS);
isc_region_t r;
return (ISC_R_SUCCESS);
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
return (result);
return (ISC_R_NOMEMORY);
isc_region_t r;
return (ISC_R_SUCCESS);
return (result);
return (result);
return (ISC_R_SUCCESS);
isc_region_t r;
return (result);
return (result);
return (ISC_R_SUCCESS);
return (ISC_R_NOTFOUND);
return (DNS_R_NOTVERIFIEDYET);
return (result);
return (result);
return (result);
#ifdef SKAN_MSG_DEBUG
return (ISC_R_SUCCESS);
#ifdef SKAN_MSG_DEBUG
return (ISC_R_UNEXPECTEDEND);
return (result);
return (DNS_R_KEYUNAUTHORIZED);
goto freesig;
goto freesig;
return (result);
return (ISC_R_SUCCESS);
return (result);
if (seensoa &&
target);
target);
return (result);
return (result);
static isc_result_t
return (DNS_R_OPTERR);
return (DNS_R_OPTERR);
for (i = 0; i < addrbytes; i ++)
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
unsigned char *optdata;
switch (section) {
case DNS_PSEUDOSECTION_OPT:
return (ISC_R_SUCCESS);
if (mbz != 0) {
return (ISC_R_SUCCESS);
if (optlen != 0) {
for (i = 0; i < optlen; i++) {
const char *sep;
switch (optcode) {
case DNS_OPT_COOKIE:
return (ISC_R_NOSPACE);
for (i = 0; i < optlen; i++) {
&optdata[i],
return (ISC_R_SUCCESS);
case DNS_PSEUDOSECTION_TSIG:
return (ISC_R_SUCCESS);
return (result);
case DNS_PSEUDOSECTION_SIG0:
return (ISC_R_SUCCESS);
return (result);
return (ISC_R_UNEXPECTED);
return (result);
return (result);
return (result);
return (result);
return (result);
return (result);
return (result);
return (ISC_R_SUCCESS);
const void *order_arg)
return (ISC_R_NOSPACE);
return (ISC_R_SUCCESS);
buf);
unsigned int len = 0, i;
return (result);
goto cleanup;
goto cleanup;
if (count != 0U) {
for (i = 0; i < count; i++)
goto cleanup;
goto cleanup;
for (i = 0; i < count; i++) {
return (ISC_R_SUCCESS);
return (result);