message.c revision 224092
165285Siwasaki/* 265285Siwasaki * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") 365285Siwasaki * Copyright (C) 1999-2003 Internet Software Consortium. 465285Siwasaki * 565285Siwasaki * Permission to use, copy, modify, and/or distribute this software for any 665285Siwasaki * purpose with or without fee is hereby granted, provided that the above 765285Siwasaki * copyright notice and this permission notice appear in all copies. 865285Siwasaki * 965285Siwasaki * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 1065285Siwasaki * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1165285Siwasaki * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 1265285Siwasaki * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 1365285Siwasaki * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 1465285Siwasaki * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 1565285Siwasaki * PERFORMANCE OF THIS SOFTWARE. 1665285Siwasaki */ 1765285Siwasaki 1865285Siwasaki/* $Id: message.c,v 1.254.186.3 2011-06-21 20:15:47 each Exp $ */ 1965285Siwasaki 2065285Siwasaki/*! \file */ 2165285Siwasaki 2265285Siwasaki/*** 2365285Siwasaki *** Imports 2465285Siwasaki ***/ 2565285Siwasaki 2665285Siwasaki#include <config.h> 2765285Siwasaki#include <ctype.h> 2865285Siwasaki 2965285Siwasaki#include <isc/buffer.h> 30119515Snjl#include <isc/mem.h> 3165285Siwasaki#include <isc/print.h> 3265285Siwasaki#include <isc/string.h> /* Required for HP/UX (and others?) */ 33119515Snjl#include <isc/util.h> 3465285Siwasaki 3565285Siwasaki#include <dns/dnssec.h> 3665285Siwasaki#include <dns/keyvalues.h> 3765285Siwasaki#include <dns/log.h> 38119515Snjl#include <dns/masterdump.h> 3965285Siwasaki#include <dns/message.h> 4065285Siwasaki#include <dns/opcode.h> 4165285Siwasaki#include <dns/rdata.h> 4265285Siwasaki#include <dns/rdatalist.h> 4385323Siwasaki#include <dns/rdataset.h> 4485323Siwasaki#include <dns/rdatastruct.h> 4585323Siwasaki#include <dns/result.h> 46119515Snjl#include <dns/tsig.h> 47119912Snjl#include <dns/view.h> 48119912Snjl 49119515Snjl#ifdef SKAN_MSG_DEBUG 50119515Snjlstatic void 51119515Snjlhexdump(const char *msg, const char *msg2, void *base, size_t len) { 52119515Snjl unsigned char *p; 53119515Snjl unsigned int cnt; 54119515Snjl 55119515Snjl p = base; 56119515Snjl cnt = 0; 57119515Snjl 58119515Snjl printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base); 59119515Snjl 60119912Snjl while (cnt < len) { 61119912Snjl if (cnt % 16 == 0) 62119515Snjl printf("%p: ", p); 63119515Snjl else if (cnt % 8 == 0) 64119515Snjl printf(" |"); 65119515Snjl printf(" %02x %c", *p, (isprint(*p) ? *p : ' ')); 66119515Snjl p++; 6785323Siwasaki cnt++; 6865285Siwasaki 6965285Siwasaki if (cnt % 16 == 0) 7065285Siwasaki printf("\n"); 7165285Siwasaki } 7265285Siwasaki 7365285Siwasaki if (cnt % 16 != 0) 7465285Siwasaki printf("\n"); 7565285Siwasaki} 7665285Siwasaki#endif 7765285Siwasaki 7865285Siwasaki#define DNS_MESSAGE_OPCODE_MASK 0x7800U 7965285Siwasaki#define DNS_MESSAGE_OPCODE_SHIFT 11 8065285Siwasaki#define DNS_MESSAGE_RCODE_MASK 0x000fU 8165285Siwasaki#define DNS_MESSAGE_FLAG_MASK 0x8ff0U 8265285Siwasaki#define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U 8365285Siwasaki#define DNS_MESSAGE_EDNSRCODE_SHIFT 24 84119912Snjl#define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U 8565285Siwasaki#define DNS_MESSAGE_EDNSVERSION_SHIFT 16 86119912Snjl 87119912Snjl#define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \ 88119912Snjl && ((s) < DNS_SECTION_MAX)) 89119912Snjl#define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \ 90119912Snjl && ((s) < DNS_SECTION_MAX)) 91119912Snjl#define ADD_STRING(b, s) {if (strlen(s) >= \ 92119912Snjl isc_buffer_availablelength(b)) \ 93119912Snjl return(ISC_R_NOSPACE); else \ 94119912Snjl isc_buffer_putstr(b, s);} 95119912Snjl#define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \ 96119912Snjl && ((s) < DNS_PSEUDOSECTION_MAX)) 97119912Snjl 98119912Snjl#define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0) 99119912Snjl 100119912Snjl/*% 101119912Snjl * This is the size of each individual scratchpad buffer, and the numbers 102119912Snjl * of various block allocations used within the server. 103119912Snjl * XXXMLG These should come from a config setting. 104119912Snjl */ 105119912Snjl#define SCRATCHPAD_SIZE 512 106119912Snjl#define NAME_COUNT 8 107119912Snjl#define OFFSET_COUNT 4 108119912Snjl#define RDATA_COUNT 8 109119912Snjl#define RDATALIST_COUNT 8 110119912Snjl#define RDATASET_COUNT RDATALIST_COUNT 111119912Snjl 112119912Snjl/*% 113119912Snjl * Text representation of the different items, for message_totext 114119912Snjl * functions. 11565285Siwasaki */ 116119912Snjlstatic const char *sectiontext[] = { 117119912Snjl "QUESTION", 118119912Snjl "ANSWER", 119119912Snjl "AUTHORITY", 120119912Snjl "ADDITIONAL" 121119912Snjl}; 122119912Snjl 123119912Snjlstatic const char *updsectiontext[] = { 124119912Snjl "ZONE", 125119912Snjl "PREREQUISITE", 126119912Snjl "UPDATE", 127119912Snjl "ADDITIONAL" 128119912Snjl}; 129119912Snjl 13065285Siwasakistatic const char *opcodetext[] = { 131119515Snjl "QUERY", 132119515Snjl "IQUERY", 13365285Siwasaki "STATUS", 13465285Siwasaki "RESERVED3", 13585323Siwasaki "NOTIFY", 136108967Sjhb "UPDATE", 137108967Sjhb "RESERVED6", 138108967Sjhb "RESERVED7", 139108967Sjhb "RESERVED8", 140108967Sjhb "RESERVED9", 141108967Sjhb "RESERVED10", 142108967Sjhb "RESERVED11", 143108967Sjhb "RESERVED12", 144108967Sjhb "RESERVED13", 145108967Sjhb "RESERVED14", 146108967Sjhb "RESERVED15" 147108967Sjhb}; 148108967Sjhb 149108967Sjhbstatic const char *rcodetext[] = { 150108967Sjhb "NOERROR", 151108967Sjhb "FORMERR", 152108967Sjhb "SERVFAIL", 153108967Sjhb "NXDOMAIN", 154108967Sjhb "NOTIMP", 155108967Sjhb "REFUSED", 156108967Sjhb "YXDOMAIN", 157108967Sjhb "YXRRSET", 158108967Sjhb "NXRRSET", 159108967Sjhb "NOTAUTH", 160108967Sjhb "NOTZONE", 161108967Sjhb "RESERVED11", 162108967Sjhb "RESERVED12", 163108967Sjhb "RESERVED13", 164119515Snjl "RESERVED14", 165108967Sjhb "RESERVED15", 166108967Sjhb "BADVERS" 167108967Sjhb}; 168108967Sjhb 169108967Sjhb 170108967Sjhb/*% 171108967Sjhb * "helper" type, which consists of a block of some type, and is linkable. 172108967Sjhb * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer 173108967Sjhb * size, or the allocated elements will not be aligned correctly. 174108967Sjhb */ 175108967Sjhbstruct dns_msgblock { 176108967Sjhb unsigned int count; 177108967Sjhb unsigned int remaining; 178108967Sjhb ISC_LINK(dns_msgblock_t) link; 179108967Sjhb}; /* dynamically sized */ 180108967Sjhb 181108967Sjhbstatic inline dns_msgblock_t * 182108967Sjhbmsgblock_allocate(isc_mem_t *, unsigned int, unsigned int); 183108967Sjhb 184108967Sjhb#define msgblock_get(block, type) \ 185108967Sjhb ((type *)msgblock_internalget(block, sizeof(type))) 186108967Sjhb 187108967Sjhbstatic inline void * 188108967Sjhbmsgblock_internalget(dns_msgblock_t *, unsigned int); 189108967Sjhb 190108967Sjhbstatic inline void 191108967Sjhbmsgblock_reset(dns_msgblock_t *); 192108967Sjhb 193108967Sjhbstatic inline void 194108967Sjhbmsgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int); 195108967Sjhb 196108967Sjhb/* 197108967Sjhb * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory 198108967Sjhb * is free, return NULL. 199108967Sjhb */ 200108967Sjhbstatic inline dns_msgblock_t * 201108967Sjhbmsgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type, 202108967Sjhb unsigned int count) 203108967Sjhb{ 204108967Sjhb dns_msgblock_t *block; 205108967Sjhb unsigned int length; 206108967Sjhb 207108967Sjhb length = sizeof(dns_msgblock_t) + (sizeof_type * count); 208108967Sjhb 209108967Sjhb block = isc_mem_get(mctx, length); 210108967Sjhb if (block == NULL) 211108967Sjhb return (NULL); 212108967Sjhb 213108967Sjhb block->count = count; 214108967Sjhb block->remaining = count; 215108967Sjhb 216108967Sjhb ISC_LINK_INIT(block, link); 217108967Sjhb 218108967Sjhb return (block); 219108967Sjhb} 220108967Sjhb 221108967Sjhb/* 222108967Sjhb * Return an element from the msgblock. If no more are available, return 223108967Sjhb * NULL. 224108967Sjhb */ 225108967Sjhbstatic inline void * 226108967Sjhbmsgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) { 227108967Sjhb void *ptr; 228108967Sjhb 229108967Sjhb if (block == NULL || block->remaining == 0) 230108967Sjhb return (NULL); 231108967Sjhb 232108967Sjhb block->remaining--; 233108967Sjhb 234108967Sjhb ptr = (((unsigned char *)block) 235108967Sjhb + sizeof(dns_msgblock_t) 236108967Sjhb + (sizeof_type * block->remaining)); 237108967Sjhb 238108967Sjhb return (ptr); 239108967Sjhb} 240108967Sjhb 241108967Sjhbstatic inline void 242108967Sjhbmsgblock_reset(dns_msgblock_t *block) { 243108967Sjhb block->remaining = block->count; 244108967Sjhb} 245108967Sjhb 246108967Sjhb/* 247119515Snjl * Release memory associated with a message block. 248119515Snjl */ 249108967Sjhbstatic inline void 250108967Sjhbmsgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type) 251108967Sjhb{ 252108967Sjhb unsigned int length; 253108967Sjhb 254108967Sjhb length = sizeof(dns_msgblock_t) + (sizeof_type * block->count); 255108967Sjhb 256108967Sjhb isc_mem_put(mctx, block, length); 257108967Sjhb} 258108967Sjhb 259108967Sjhb/* 260108967Sjhb * Allocate a new dynamic buffer, and attach it to this message as the 261108967Sjhb * "current" buffer. (which is always the last on the list, for our 262108967Sjhb * uses) 263108967Sjhb */ 264108967Sjhbstatic inline isc_result_t 265108967Sjhbnewbuffer(dns_message_t *msg, unsigned int size) { 266108967Sjhb isc_result_t result; 267108967Sjhb isc_buffer_t *dynbuf; 268108967Sjhb 269108967Sjhb dynbuf = NULL; 270108967Sjhb result = isc_buffer_allocate(msg->mctx, &dynbuf, size); 271108967Sjhb if (result != ISC_R_SUCCESS) 272119515Snjl return (ISC_R_NOMEMORY); 273108967Sjhb 274108967Sjhb ISC_LIST_APPEND(msg->scratchpad, dynbuf, link); 275108967Sjhb return (ISC_R_SUCCESS); 276108967Sjhb} 277108967Sjhb 278108967Sjhbstatic inline isc_buffer_t * 279108967Sjhbcurrentbuffer(dns_message_t *msg) { 280108967Sjhb isc_buffer_t *dynbuf; 281108967Sjhb 282119515Snjl dynbuf = ISC_LIST_TAIL(msg->scratchpad); 283108967Sjhb INSIST(dynbuf != NULL); 284108967Sjhb 285108967Sjhb return (dynbuf); 286108967Sjhb} 287108967Sjhb 288108967Sjhbstatic inline void 289119515Snjlreleaserdata(dns_message_t *msg, dns_rdata_t *rdata) { 290108967Sjhb ISC_LIST_PREPEND(msg->freerdata, rdata, link); 291108967Sjhb} 292108967Sjhb 293108967Sjhbstatic inline dns_rdata_t * 294108967Sjhbnewrdata(dns_message_t *msg) { 295108967Sjhb dns_msgblock_t *msgblock; 296108967Sjhb dns_rdata_t *rdata; 297108967Sjhb 298108967Sjhb rdata = ISC_LIST_HEAD(msg->freerdata); 299108967Sjhb if (rdata != NULL) { 300118334Speter ISC_LIST_UNLINK(msg->freerdata, rdata, link); 301118334Speter return (rdata); 302118334Speter } 303118334Speter 304119515Snjl msgblock = ISC_LIST_TAIL(msg->rdatas); 305118334Speter rdata = msgblock_get(msgblock, dns_rdata_t); 306118334Speter if (rdata == NULL) { 307118334Speter msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t), 308118334Speter RDATA_COUNT); 309118334Speter if (msgblock == NULL) 310118334Speter return (NULL); 311118334Speter 312118334Speter ISC_LIST_APPEND(msg->rdatas, msgblock, link); 313118334Speter 314118334Speter rdata = msgblock_get(msgblock, dns_rdata_t); 315118334Speter } 316118334Speter 317118335Speter dns_rdata_init(rdata); 318118334Speter return (rdata); 319118334Speter} 320118334Speter 321118334Speterstatic inline void 322119515Snjlreleaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) { 32385323Siwasaki ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link); 324119515Snjl} 32565285Siwasaki 32685323Siwasakistatic inline dns_rdatalist_t * 32765285Siwasakinewrdatalist(dns_message_t *msg) { 32865285Siwasaki dns_msgblock_t *msgblock; 32965285Siwasaki dns_rdatalist_t *rdatalist; 33065285Siwasaki 33165285Siwasaki rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 33265285Siwasaki if (rdatalist != NULL) { 33365285Siwasaki ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 33465285Siwasaki return (rdatalist); 33565285Siwasaki } 336119515Snjl 337119515Snjl msgblock = ISC_LIST_TAIL(msg->rdatalists); 33865285Siwasaki rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 33965285Siwasaki if (rdatalist == NULL) { 340119515Snjl msgblock = msgblock_allocate(msg->mctx, 34165285Siwasaki sizeof(dns_rdatalist_t), 34265285Siwasaki RDATALIST_COUNT); 34365285Siwasaki if (msgblock == NULL) 34465285Siwasaki return (NULL); 345119515Snjl 34665285Siwasaki ISC_LIST_APPEND(msg->rdatalists, msgblock, link); 34765285Siwasaki 34865285Siwasaki rdatalist = msgblock_get(msgblock, dns_rdatalist_t); 34965285Siwasaki } 35065285Siwasaki 35165285Siwasaki return (rdatalist); 35265285Siwasaki} 35365285Siwasaki 35485323Siwasakistatic inline dns_offsets_t * 35565285Siwasakinewoffsets(dns_message_t *msg) { 35665285Siwasaki dns_msgblock_t *msgblock; 357119912Snjl dns_offsets_t *offsets; 358119912Snjl 359119912Snjl msgblock = ISC_LIST_TAIL(msg->offsets); 360119912Snjl offsets = msgblock_get(msgblock, dns_offsets_t); 361119912Snjl if (offsets == NULL) { 362119515Snjl msgblock = msgblock_allocate(msg->mctx, 363119912Snjl sizeof(dns_offsets_t), 36465285Siwasaki OFFSET_COUNT); 365119912Snjl if (msgblock == NULL) 366119912Snjl return (NULL); 36765285Siwasaki 36885323Siwasaki ISC_LIST_APPEND(msg->offsets, msgblock, link); 369119912Snjl 370119912Snjl offsets = msgblock_get(msgblock, dns_offsets_t); 371119912Snjl } 372119912Snjl 373119912Snjl return (offsets); 374119912Snjl} 375119912Snjl 376119912Snjlstatic inline void 377119912Snjlmsginitheader(dns_message_t *m) { 378119912Snjl m->id = 0; 379119912Snjl m->flags = 0; 380119912Snjl m->rcode = 0; 381119912Snjl m->opcode = 0; 382119912Snjl m->rdclass = 0; 383119912Snjl} 38465285Siwasaki 385119912Snjlstatic inline void 386119912Snjlmsginitprivate(dns_message_t *m) { 387119912Snjl unsigned int i; 38865285Siwasaki 389119912Snjl for (i = 0; i < DNS_SECTION_MAX; i++) { 390119912Snjl m->cursors[i] = NULL; 391119912Snjl m->counts[i] = 0; 39265285Siwasaki } 393119912Snjl m->opt = NULL; 394119912Snjl m->sig0 = NULL; 395119912Snjl m->sig0name = NULL; 39665285Siwasaki m->tsig = NULL; 397119912Snjl m->tsigname = NULL; 398119912Snjl m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */ 399119912Snjl m->opt_reserved = 0; 40065285Siwasaki m->sig_reserved = 0; 401119912Snjl m->reserved = 0; 402119912Snjl m->buffer = NULL; 403119912Snjl} 40465285Siwasaki 405119912Snjlstatic inline void 406119912Snjlmsginittsig(dns_message_t *m) { 407119912Snjl m->tsigstatus = dns_rcode_noerror; 408119912Snjl m->querytsigstatus = dns_rcode_noerror; 409119912Snjl m->tsigkey = NULL; 410119912Snjl m->tsigctx = NULL; 411119912Snjl m->sigstart = -1; 412119912Snjl m->sig0key = NULL; 413119912Snjl m->sig0status = dns_rcode_noerror; 414119912Snjl m->timeadjust = 0; 415119912Snjl} 416119912Snjl 417119912Snjl/* 41865285Siwasaki * Init elements to default state. Used both when allocating a new element 419119912Snjl * and when resetting one. 42065285Siwasaki */ 421119912Snjlstatic inline void 42265285Siwasakimsginit(dns_message_t *m) { 423119912Snjl msginitheader(m); 42465285Siwasaki msginitprivate(m); 425119912Snjl msginittsig(m); 42665285Siwasaki m->header_ok = 0; 427119912Snjl m->question_ok = 0; 428119912Snjl m->tcp_continuation = 0; 429119912Snjl m->verified_sig = 0; 430119912Snjl m->verify_attempted = 0; 43165285Siwasaki m->order = NULL; 43265285Siwasaki m->order_arg = NULL; 433119912Snjl m->query.base = NULL; 434119912Snjl m->query.length = 0; 435119912Snjl m->free_query = 0; 436119912Snjl m->saved.base = NULL; 437119912Snjl m->saved.length = 0; 43865285Siwasaki m->free_saved = 0; 439119912Snjl m->querytsig = NULL; 440119912Snjl} 441119912Snjl 442119912Snjlstatic inline void 443119912Snjlmsgresetnames(dns_message_t *msg, unsigned int first_section) { 444119912Snjl unsigned int i; 445119912Snjl dns_name_t *name, *next_name; 446119912Snjl dns_rdataset_t *rds, *next_rds; 447119912Snjl 448119912Snjl /* 449119912Snjl * Clean up name lists by calling the rdataset disassociate function. 450119912Snjl */ 451119912Snjl for (i = first_section; i < DNS_SECTION_MAX; i++) { 452119912Snjl name = ISC_LIST_HEAD(msg->sections[i]); 453119912Snjl while (name != NULL) { 454119912Snjl next_name = ISC_LIST_NEXT(name, link); 455119912Snjl ISC_LIST_UNLINK(msg->sections[i], name, link); 456119912Snjl 45765285Siwasaki rds = ISC_LIST_HEAD(name->list); 45865285Siwasaki while (rds != NULL) { 459119912Snjl next_rds = ISC_LIST_NEXT(rds, link); 460119912Snjl ISC_LIST_UNLINK(name->list, rds, link); 461119912Snjl 462119912Snjl INSIST(dns_rdataset_isassociated(rds)); 463119912Snjl dns_rdataset_disassociate(rds); 464119912Snjl isc_mempool_put(msg->rdspool, rds); 465119912Snjl rds = next_rds; 466119912Snjl } 467119912Snjl if (dns_name_dynamic(name)) 468119912Snjl dns_name_free(name, msg->mctx); 469119912Snjl isc_mempool_put(msg->namepool, name); 470119912Snjl name = next_name; 471119912Snjl } 472119912Snjl } 473119912Snjl} 474119912Snjl 475119912Snjlstatic void 476119912Snjlmsgresetopt(dns_message_t *msg) 477119912Snjl{ 478119912Snjl if (msg->opt != NULL) { 479119912Snjl if (msg->opt_reserved > 0) { 480119912Snjl dns_message_renderrelease(msg, msg->opt_reserved); 481119912Snjl msg->opt_reserved = 0; 482119912Snjl } 48365285Siwasaki INSIST(dns_rdataset_isassociated(msg->opt)); 484119912Snjl dns_rdataset_disassociate(msg->opt); 485119912Snjl isc_mempool_put(msg->rdspool, msg->opt); 486119912Snjl msg->opt = NULL; 487119912Snjl } 488119912Snjl} 489119912Snjl 490119912Snjlstatic void 491119912Snjlmsgresetsigs(dns_message_t *msg, isc_boolean_t replying) { 492119912Snjl if (msg->sig_reserved > 0) { 493119912Snjl dns_message_renderrelease(msg, msg->sig_reserved); 494119912Snjl msg->sig_reserved = 0; 49585323Siwasaki } 49665285Siwasaki if (msg->tsig != NULL) { 49765285Siwasaki INSIST(dns_rdataset_isassociated(msg->tsig)); 498119515Snjl INSIST(msg->namepool != NULL); 49965285Siwasaki if (replying) { 50065285Siwasaki INSIST(msg->querytsig == NULL); 501119515Snjl msg->querytsig = msg->tsig; 50265285Siwasaki } else { 50365285Siwasaki dns_rdataset_disassociate(msg->tsig); 50465285Siwasaki isc_mempool_put(msg->rdspool, msg->tsig); 50565285Siwasaki if (msg->querytsig != NULL) { 50665285Siwasaki dns_rdataset_disassociate(msg->querytsig); 50765285Siwasaki isc_mempool_put(msg->rdspool, msg->querytsig); 50865285Siwasaki } 50965285Siwasaki } 51065285Siwasaki if (dns_name_dynamic(msg->tsigname)) 51165285Siwasaki dns_name_free(msg->tsigname, msg->mctx); 51265285Siwasaki isc_mempool_put(msg->namepool, msg->tsigname); 51365285Siwasaki msg->tsig = NULL; 51465285Siwasaki msg->tsigname = NULL; 51565285Siwasaki } else if (msg->querytsig != NULL && !replying) { 51665285Siwasaki dns_rdataset_disassociate(msg->querytsig); 51765285Siwasaki isc_mempool_put(msg->rdspool, msg->querytsig); 518119515Snjl msg->querytsig = NULL; 51965285Siwasaki } 52065285Siwasaki if (msg->sig0 != NULL) { 52165285Siwasaki INSIST(dns_rdataset_isassociated(msg->sig0)); 52265285Siwasaki dns_rdataset_disassociate(msg->sig0); 52365285Siwasaki isc_mempool_put(msg->rdspool, msg->sig0); 52465285Siwasaki if (msg->sig0name != NULL) { 52565285Siwasaki if (dns_name_dynamic(msg->sig0name)) 52665285Siwasaki dns_name_free(msg->sig0name, msg->mctx); 52765285Siwasaki isc_mempool_put(msg->namepool, msg->sig0name); 528119515Snjl } 52965285Siwasaki msg->sig0 = NULL; 53065285Siwasaki msg->sig0name = NULL; 53165285Siwasaki } 53285323Siwasaki} 533119515Snjl 53465285Siwasaki/* 535108082Smarcel * Free all but one (or everything) for this message. This is used by 53685323Siwasaki * both dns_message_reset() and dns_message_destroy(). 53765285Siwasaki */ 53865285Siwasakistatic void 539119515Snjlmsgreset(dns_message_t *msg, isc_boolean_t everything) { 54065285Siwasaki dns_msgblock_t *msgblock, *next_msgblock; 54165285Siwasaki isc_buffer_t *dynbuf, *next_dynbuf; 54265285Siwasaki dns_rdata_t *rdata; 54365285Siwasaki dns_rdatalist_t *rdatalist; 54465285Siwasaki 54565285Siwasaki msgresetnames(msg, 0); 54665285Siwasaki msgresetopt(msg); 54765285Siwasaki msgresetsigs(msg, ISC_FALSE); 54865285Siwasaki 549119515Snjl /* 55065285Siwasaki * Clean up linked lists. 551119515Snjl */ 552119515Snjl 553119912Snjl /* 554119515Snjl * Run through the free lists, and just unlink anything found there. 555108967Sjhb * The memory isn't lost since these are part of message blocks we 556119515Snjl * have allocated. 557118334Speter */ 558119515Snjl rdata = ISC_LIST_HEAD(msg->freerdata); 559119515Snjl while (rdata != NULL) { 56065285Siwasaki ISC_LIST_UNLINK(msg->freerdata, rdata, link); 56165285Siwasaki rdata = ISC_LIST_HEAD(msg->freerdata); 56285323Siwasaki } 563119515Snjl rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 564119515Snjl while (rdatalist != NULL) { 56585323Siwasaki ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); 566119515Snjl rdatalist = ISC_LIST_HEAD(msg->freerdatalist); 567119515Snjl } 56885323Siwasaki 569119515Snjl dynbuf = ISC_LIST_HEAD(msg->scratchpad); 570119515Snjl INSIST(dynbuf != NULL); 571119515Snjl if (!everything) { 572119515Snjl isc_buffer_clear(dynbuf); 573119515Snjl dynbuf = ISC_LIST_NEXT(dynbuf, link); 574119515Snjl } 575119515Snjl while (dynbuf != NULL) { 576119515Snjl next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 577119515Snjl ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link); 578119515Snjl isc_buffer_free(&dynbuf); 579119515Snjl dynbuf = next_dynbuf; 580119515Snjl } 58185323Siwasaki 58285323Siwasaki msgblock = ISC_LIST_HEAD(msg->rdatas); 583119515Snjl if (!everything && msgblock != NULL) { 584119515Snjl msgblock_reset(msgblock); 58585323Siwasaki msgblock = ISC_LIST_NEXT(msgblock, link); 586119515Snjl } 587119515Snjl while (msgblock != NULL) { 58885323Siwasaki next_msgblock = ISC_LIST_NEXT(msgblock, link); 589119515Snjl ISC_LIST_UNLINK(msg->rdatas, msgblock, link); 590119515Snjl msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t)); 591119515Snjl msgblock = next_msgblock; 592119515Snjl } 593119515Snjl 594119515Snjl /* 595119515Snjl * rdatalists could be empty. 596119515Snjl */ 597119515Snjl 598119515Snjl msgblock = ISC_LIST_HEAD(msg->rdatalists); 59985323Siwasaki if (!everything && msgblock != NULL) { 60085323Siwasaki msgblock_reset(msgblock); 601119515Snjl msgblock = ISC_LIST_NEXT(msgblock, link); 602119515Snjl } 60385323Siwasaki while (msgblock != NULL) { 604119515Snjl next_msgblock = ISC_LIST_NEXT(msgblock, link); 605119515Snjl ISC_LIST_UNLINK(msg->rdatalists, msgblock, link); 606119515Snjl msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t)); 60785323Siwasaki msgblock = next_msgblock; 608119515Snjl } 609119515Snjl 610119515Snjl msgblock = ISC_LIST_HEAD(msg->offsets); 611119515Snjl if (!everything && msgblock != NULL) { 612119515Snjl msgblock_reset(msgblock); 613119515Snjl msgblock = ISC_LIST_NEXT(msgblock, link); 614119515Snjl } 615119515Snjl while (msgblock != NULL) { 616119515Snjl next_msgblock = ISC_LIST_NEXT(msgblock, link); 617119515Snjl ISC_LIST_UNLINK(msg->offsets, msgblock, link); 618119515Snjl msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t)); 619119515Snjl msgblock = next_msgblock; 620119515Snjl } 621119515Snjl 622119515Snjl if (msg->tsigkey != NULL) { 623119515Snjl dns_tsigkey_detach(&msg->tsigkey); 624119515Snjl msg->tsigkey = NULL; 625119515Snjl } 626119515Snjl 627119515Snjl if (msg->tsigctx != NULL) 628119515Snjl dst_context_destroy(&msg->tsigctx); 629119515Snjl 630119515Snjl if (msg->query.base != NULL) { 631119515Snjl if (msg->free_query != 0) 632119515Snjl isc_mem_put(msg->mctx, msg->query.base, 633119515Snjl msg->query.length); 634119515Snjl msg->query.base = NULL; 635119515Snjl msg->query.length = 0; 636119515Snjl } 637119515Snjl 638119515Snjl if (msg->saved.base != NULL) { 639119515Snjl if (msg->free_saved != 0) 640119515Snjl isc_mem_put(msg->mctx, msg->saved.base, 641119515Snjl msg->saved.length); 64285323Siwasaki msg->saved.base = NULL; 64385323Siwasaki msg->saved.length = 0; 644119515Snjl } 645119515Snjl 64685323Siwasaki /* 647119515Snjl * cleanup the buffer cleanup list 64885323Siwasaki */ 64985323Siwasaki dynbuf = ISC_LIST_HEAD(msg->cleanup); 650119515Snjl while (dynbuf != NULL) { 651119515Snjl next_dynbuf = ISC_LIST_NEXT(dynbuf, link); 652119515Snjl ISC_LIST_UNLINK(msg->cleanup, dynbuf, link); 65385323Siwasaki isc_buffer_free(&dynbuf); 654119515Snjl dynbuf = next_dynbuf; 655119515Snjl } 656119515Snjl 65785323Siwasaki /* 658119515Snjl * Set other bits to normal default values. 659119515Snjl */ 660119515Snjl if (!everything) 661119515Snjl msginit(msg); 662119515Snjl 663119515Snjl ENSURE(isc_mempool_getallocated(msg->namepool) == 0); 664119515Snjl ENSURE(isc_mempool_getallocated(msg->rdspool) == 0); 665119515Snjl} 666119515Snjl 667119515Snjlstatic unsigned int 66885323Siwasakispacefortsig(dns_tsigkey_t *key, int otherlen) { 66985323Siwasaki isc_region_t r1, r2; 670119515Snjl unsigned int x; 671119912Snjl isc_result_t result; 67285323Siwasaki 673119515Snjl /* 67485323Siwasaki * The space required for an TSIG record is: 675119912Snjl * 676119515Snjl * n1 bytes for the name 677119515Snjl * 2 bytes for the type 678119515Snjl * 2 bytes for the class 67985323Siwasaki * 4 bytes for the ttl 680 * 2 bytes for the rdlength 681 * n2 bytes for the algorithm name 682 * 6 bytes for the time signed 683 * 2 bytes for the fudge 684 * 2 bytes for the MAC size 685 * x bytes for the MAC 686 * 2 bytes for the original id 687 * 2 bytes for the error 688 * 2 bytes for the other data length 689 * y bytes for the other data (at most) 690 * --------------------------------- 691 * 26 + n1 + n2 + x + y bytes 692 */ 693 694 dns_name_toregion(&key->name, &r1); 695 dns_name_toregion(key->algorithm, &r2); 696 if (key->key == NULL) 697 x = 0; 698 else { 699 result = dst_key_sigsize(key->key, &x); 700 if (result != ISC_R_SUCCESS) 701 x = 0; 702 } 703 return (26 + r1.length + r2.length + x + otherlen); 704} 705 706isc_result_t 707dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp) 708{ 709 dns_message_t *m; 710 isc_result_t result; 711 isc_buffer_t *dynbuf; 712 unsigned int i; 713 714 REQUIRE(mctx != NULL); 715 REQUIRE(msgp != NULL); 716 REQUIRE(*msgp == NULL); 717 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE 718 || intent == DNS_MESSAGE_INTENTRENDER); 719 720 m = isc_mem_get(mctx, sizeof(dns_message_t)); 721 if (m == NULL) 722 return (ISC_R_NOMEMORY); 723 724 /* 725 * No allocations until further notice. Just initialize all lists 726 * and other members that are freed in the cleanup phase here. 727 */ 728 729 m->magic = DNS_MESSAGE_MAGIC; 730 m->from_to_wire = intent; 731 msginit(m); 732 733 for (i = 0; i < DNS_SECTION_MAX; i++) 734 ISC_LIST_INIT(m->sections[i]); 735 m->mctx = mctx; 736 737 ISC_LIST_INIT(m->scratchpad); 738 ISC_LIST_INIT(m->cleanup); 739 m->namepool = NULL; 740 m->rdspool = NULL; 741 ISC_LIST_INIT(m->rdatas); 742 ISC_LIST_INIT(m->rdatalists); 743 ISC_LIST_INIT(m->offsets); 744 ISC_LIST_INIT(m->freerdata); 745 ISC_LIST_INIT(m->freerdatalist); 746 747 /* 748 * Ok, it is safe to allocate (and then "goto cleanup" if failure) 749 */ 750 751 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool); 752 if (result != ISC_R_SUCCESS) 753 goto cleanup; 754 isc_mempool_setfreemax(m->namepool, NAME_COUNT); 755 isc_mempool_setname(m->namepool, "msg:names"); 756 757 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t), 758 &m->rdspool); 759 if (result != ISC_R_SUCCESS) 760 goto cleanup; 761 isc_mempool_setfreemax(m->rdspool, NAME_COUNT); 762 isc_mempool_setname(m->rdspool, "msg:rdataset"); 763 764 dynbuf = NULL; 765 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE); 766 if (result != ISC_R_SUCCESS) 767 goto cleanup; 768 ISC_LIST_APPEND(m->scratchpad, dynbuf, link); 769 770 m->cctx = NULL; 771 772 *msgp = m; 773 return (ISC_R_SUCCESS); 774 775 /* 776 * Cleanup for error returns. 777 */ 778 cleanup: 779 dynbuf = ISC_LIST_HEAD(m->scratchpad); 780 if (dynbuf != NULL) { 781 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link); 782 isc_buffer_free(&dynbuf); 783 } 784 if (m->namepool != NULL) 785 isc_mempool_destroy(&m->namepool); 786 if (m->rdspool != NULL) 787 isc_mempool_destroy(&m->rdspool); 788 m->magic = 0; 789 isc_mem_put(mctx, m, sizeof(dns_message_t)); 790 791 return (ISC_R_NOMEMORY); 792} 793 794void 795dns_message_reset(dns_message_t *msg, unsigned int intent) { 796 REQUIRE(DNS_MESSAGE_VALID(msg)); 797 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE 798 || intent == DNS_MESSAGE_INTENTRENDER); 799 800 msgreset(msg, ISC_FALSE); 801 msg->from_to_wire = intent; 802} 803 804void 805dns_message_destroy(dns_message_t **msgp) { 806 dns_message_t *msg; 807 808 REQUIRE(msgp != NULL); 809 REQUIRE(DNS_MESSAGE_VALID(*msgp)); 810 811 msg = *msgp; 812 *msgp = NULL; 813 814 msgreset(msg, ISC_TRUE); 815 isc_mempool_destroy(&msg->namepool); 816 isc_mempool_destroy(&msg->rdspool); 817 msg->magic = 0; 818 isc_mem_put(msg->mctx, msg, sizeof(dns_message_t)); 819} 820 821static isc_result_t 822findname(dns_name_t **foundname, dns_name_t *target, 823 dns_namelist_t *section) 824{ 825 dns_name_t *curr; 826 827 for (curr = ISC_LIST_TAIL(*section); 828 curr != NULL; 829 curr = ISC_LIST_PREV(curr, link)) { 830 if (dns_name_equal(curr, target)) { 831 if (foundname != NULL) 832 *foundname = curr; 833 return (ISC_R_SUCCESS); 834 } 835 } 836 837 return (ISC_R_NOTFOUND); 838} 839 840isc_result_t 841dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass, 842 dns_rdatatype_t type, dns_rdatatype_t covers, 843 dns_rdataset_t **rdataset) 844{ 845 dns_rdataset_t *curr; 846 847 if (rdataset != NULL) { 848 REQUIRE(*rdataset == NULL); 849 } 850 851 for (curr = ISC_LIST_TAIL(name->list); 852 curr != NULL; 853 curr = ISC_LIST_PREV(curr, link)) { 854 if (curr->rdclass == rdclass && 855 curr->type == type && curr->covers == covers) { 856 if (rdataset != NULL) 857 *rdataset = curr; 858 return (ISC_R_SUCCESS); 859 } 860 } 861 862 return (ISC_R_NOTFOUND); 863} 864 865isc_result_t 866dns_message_findtype(dns_name_t *name, dns_rdatatype_t type, 867 dns_rdatatype_t covers, dns_rdataset_t **rdataset) 868{ 869 dns_rdataset_t *curr; 870 871 REQUIRE(name != NULL); 872 if (rdataset != NULL) { 873 REQUIRE(*rdataset == NULL); 874 } 875 876 for (curr = ISC_LIST_TAIL(name->list); 877 curr != NULL; 878 curr = ISC_LIST_PREV(curr, link)) { 879 if (curr->type == type && curr->covers == covers) { 880 if (rdataset != NULL) 881 *rdataset = curr; 882 return (ISC_R_SUCCESS); 883 } 884 } 885 886 return (ISC_R_NOTFOUND); 887} 888 889/* 890 * Read a name from buffer "source". 891 */ 892static isc_result_t 893getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, 894 dns_decompress_t *dctx) 895{ 896 isc_buffer_t *scratch; 897 isc_result_t result; 898 unsigned int tries; 899 900 scratch = currentbuffer(msg); 901 902 /* 903 * First try: use current buffer. 904 * Second try: allocate a new buffer and use that. 905 */ 906 tries = 0; 907 while (tries < 2) { 908 result = dns_name_fromwire(name, source, dctx, ISC_FALSE, 909 scratch); 910 911 if (result == ISC_R_NOSPACE) { 912 tries++; 913 914 result = newbuffer(msg, SCRATCHPAD_SIZE); 915 if (result != ISC_R_SUCCESS) 916 return (result); 917 918 scratch = currentbuffer(msg); 919 dns_name_reset(name); 920 } else { 921 return (result); 922 } 923 } 924 925 INSIST(0); /* Cannot get here... */ 926 return (ISC_R_UNEXPECTED); 927} 928 929static isc_result_t 930getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 931 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype, 932 unsigned int rdatalen, dns_rdata_t *rdata) 933{ 934 isc_buffer_t *scratch; 935 isc_result_t result; 936 unsigned int tries; 937 unsigned int trysize; 938 939 scratch = currentbuffer(msg); 940 941 isc_buffer_setactive(source, rdatalen); 942 943 /* 944 * First try: use current buffer. 945 * Second try: allocate a new buffer of size 946 * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen) 947 * (the data will fit if it was not more than 50% compressed) 948 * Subsequent tries: double buffer size on each try. 949 */ 950 tries = 0; 951 trysize = 0; 952 /* XXX possibly change this to a while (tries < 2) loop */ 953 for (;;) { 954 result = dns_rdata_fromwire(rdata, rdclass, rdtype, 955 source, dctx, 0, 956 scratch); 957 958 if (result == ISC_R_NOSPACE) { 959 if (tries == 0) { 960 trysize = 2 * rdatalen; 961 if (trysize < SCRATCHPAD_SIZE) 962 trysize = SCRATCHPAD_SIZE; 963 } else { 964 INSIST(trysize != 0); 965 if (trysize >= 65535) 966 return (ISC_R_NOSPACE); 967 /* XXX DNS_R_RRTOOLONG? */ 968 trysize *= 2; 969 } 970 tries++; 971 result = newbuffer(msg, trysize); 972 if (result != ISC_R_SUCCESS) 973 return (result); 974 975 scratch = currentbuffer(msg); 976 } else { 977 return (result); 978 } 979 } 980} 981 982#define DO_FORMERR \ 983 do { \ 984 if (best_effort) \ 985 seen_problem = ISC_TRUE; \ 986 else { \ 987 result = DNS_R_FORMERR; \ 988 goto cleanup; \ 989 } \ 990 } while (0) 991 992static isc_result_t 993getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 994 unsigned int options) 995{ 996 isc_region_t r; 997 unsigned int count; 998 dns_name_t *name; 999 dns_name_t *name2; 1000 dns_offsets_t *offsets; 1001 dns_rdataset_t *rdataset; 1002 dns_rdatalist_t *rdatalist; 1003 isc_result_t result; 1004 dns_rdatatype_t rdtype; 1005 dns_rdataclass_t rdclass; 1006 dns_namelist_t *section; 1007 isc_boolean_t free_name; 1008 isc_boolean_t best_effort; 1009 isc_boolean_t seen_problem; 1010 1011 section = &msg->sections[DNS_SECTION_QUESTION]; 1012 1013 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); 1014 seen_problem = ISC_FALSE; 1015 1016 name = NULL; 1017 rdataset = NULL; 1018 rdatalist = NULL; 1019 1020 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { 1021 name = isc_mempool_get(msg->namepool); 1022 if (name == NULL) 1023 return (ISC_R_NOMEMORY); 1024 free_name = ISC_TRUE; 1025 1026 offsets = newoffsets(msg); 1027 if (offsets == NULL) { 1028 result = ISC_R_NOMEMORY; 1029 goto cleanup; 1030 } 1031 dns_name_init(name, *offsets); 1032 1033 /* 1034 * Parse the name out of this packet. 1035 */ 1036 isc_buffer_remainingregion(source, &r); 1037 isc_buffer_setactive(source, r.length); 1038 result = getname(name, source, msg, dctx); 1039 if (result != ISC_R_SUCCESS) 1040 goto cleanup; 1041 1042 /* 1043 * Run through the section, looking to see if this name 1044 * is already there. If it is found, put back the allocated 1045 * name since we no longer need it, and set our name pointer 1046 * to point to the name we found. 1047 */ 1048 result = findname(&name2, name, section); 1049 1050 /* 1051 * If it is the first name in the section, accept it. 1052 * 1053 * If it is not, but is not the same as the name already 1054 * in the question section, append to the section. Note that 1055 * here in the question section this is illegal, so return 1056 * FORMERR. In the future, check the opcode to see if 1057 * this should be legal or not. In either case we no longer 1058 * need this name pointer. 1059 */ 1060 if (result != ISC_R_SUCCESS) { 1061 if (!ISC_LIST_EMPTY(*section)) 1062 DO_FORMERR; 1063 ISC_LIST_APPEND(*section, name, link); 1064 free_name = ISC_FALSE; 1065 } else { 1066 isc_mempool_put(msg->namepool, name); 1067 name = name2; 1068 name2 = NULL; 1069 free_name = ISC_FALSE; 1070 } 1071 1072 /* 1073 * Get type and class. 1074 */ 1075 isc_buffer_remainingregion(source, &r); 1076 if (r.length < 4) { 1077 result = ISC_R_UNEXPECTEDEND; 1078 goto cleanup; 1079 } 1080 rdtype = isc_buffer_getuint16(source); 1081 rdclass = isc_buffer_getuint16(source); 1082 1083 /* 1084 * If this class is different than the one we already read, 1085 * this is an error. 1086 */ 1087 if (msg->state == DNS_SECTION_ANY) { 1088 msg->state = DNS_SECTION_QUESTION; 1089 msg->rdclass = rdclass; 1090 } else if (msg->rdclass != rdclass) 1091 DO_FORMERR; 1092 1093 /* 1094 * Can't ask the same question twice. 1095 */ 1096 result = dns_message_find(name, rdclass, rdtype, 0, NULL); 1097 if (result == ISC_R_SUCCESS) 1098 DO_FORMERR; 1099 1100 /* 1101 * Allocate a new rdatalist. 1102 */ 1103 rdatalist = newrdatalist(msg); 1104 if (rdatalist == NULL) { 1105 result = ISC_R_NOMEMORY; 1106 goto cleanup; 1107 } 1108 rdataset = isc_mempool_get(msg->rdspool); 1109 if (rdataset == NULL) { 1110 result = ISC_R_NOMEMORY; 1111 goto cleanup; 1112 } 1113 1114 /* 1115 * Convert rdatalist to rdataset, and attach the latter to 1116 * the name. 1117 */ 1118 rdatalist->type = rdtype; 1119 rdatalist->covers = 0; 1120 rdatalist->rdclass = rdclass; 1121 rdatalist->ttl = 0; 1122 ISC_LIST_INIT(rdatalist->rdata); 1123 1124 dns_rdataset_init(rdataset); 1125 result = dns_rdatalist_tordataset(rdatalist, rdataset); 1126 if (result != ISC_R_SUCCESS) 1127 goto cleanup; 1128 1129 rdataset->attributes |= DNS_RDATASETATTR_QUESTION; 1130 1131 ISC_LIST_APPEND(name->list, rdataset, link); 1132 rdataset = NULL; 1133 } 1134 1135 if (seen_problem) 1136 return (DNS_R_RECOVERABLE); 1137 return (ISC_R_SUCCESS); 1138 1139 cleanup: 1140 if (rdataset != NULL) { 1141 INSIST(!dns_rdataset_isassociated(rdataset)); 1142 isc_mempool_put(msg->rdspool, rdataset); 1143 } 1144#if 0 1145 if (rdatalist != NULL) 1146 isc_mempool_put(msg->rdlpool, rdatalist); 1147#endif 1148 if (free_name) 1149 isc_mempool_put(msg->namepool, name); 1150 1151 return (result); 1152} 1153 1154static isc_boolean_t 1155update(dns_section_t section, dns_rdataclass_t rdclass) { 1156 if (section == DNS_SECTION_PREREQUISITE) 1157 return (ISC_TF(rdclass == dns_rdataclass_any || 1158 rdclass == dns_rdataclass_none)); 1159 if (section == DNS_SECTION_UPDATE) 1160 return (ISC_TF(rdclass == dns_rdataclass_any)); 1161 return (ISC_FALSE); 1162} 1163 1164static isc_result_t 1165getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, 1166 dns_section_t sectionid, unsigned int options) 1167{ 1168 isc_region_t r; 1169 unsigned int count, rdatalen; 1170 dns_name_t *name; 1171 dns_name_t *name2; 1172 dns_offsets_t *offsets; 1173 dns_rdataset_t *rdataset; 1174 dns_rdatalist_t *rdatalist; 1175 isc_result_t result; 1176 dns_rdatatype_t rdtype, covers; 1177 dns_rdataclass_t rdclass; 1178 dns_rdata_t *rdata; 1179 dns_ttl_t ttl; 1180 dns_namelist_t *section; 1181 isc_boolean_t free_name, free_rdataset; 1182 isc_boolean_t preserve_order, best_effort, seen_problem; 1183 isc_boolean_t issigzero; 1184 1185 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER); 1186 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); 1187 seen_problem = ISC_FALSE; 1188 1189 for (count = 0; count < msg->counts[sectionid]; count++) { 1190 int recstart = source->current; 1191 isc_boolean_t skip_name_search, skip_type_search; 1192 1193 section = &msg->sections[sectionid]; 1194 1195 skip_name_search = ISC_FALSE; 1196 skip_type_search = ISC_FALSE; 1197 free_name = ISC_FALSE; 1198 free_rdataset = ISC_FALSE; 1199 1200 name = isc_mempool_get(msg->namepool); 1201 if (name == NULL) 1202 return (ISC_R_NOMEMORY); 1203 free_name = ISC_TRUE; 1204 1205 offsets = newoffsets(msg); 1206 if (offsets == NULL) { 1207 result = ISC_R_NOMEMORY; 1208 goto cleanup; 1209 } 1210 dns_name_init(name, *offsets); 1211 1212 /* 1213 * Parse the name out of this packet. 1214 */ 1215 isc_buffer_remainingregion(source, &r); 1216 isc_buffer_setactive(source, r.length); 1217 result = getname(name, source, msg, dctx); 1218 if (result != ISC_R_SUCCESS) 1219 goto cleanup; 1220 1221 /* 1222 * Get type, class, ttl, and rdatalen. Verify that at least 1223 * rdatalen bytes remain. (Some of this is deferred to 1224 * later.) 1225 */ 1226 isc_buffer_remainingregion(source, &r); 1227 if (r.length < 2 + 2 + 4 + 2) { 1228 result = ISC_R_UNEXPECTEDEND; 1229 goto cleanup; 1230 } 1231 rdtype = isc_buffer_getuint16(source); 1232 rdclass = isc_buffer_getuint16(source); 1233 1234 /* 1235 * If there was no question section, we may not yet have 1236 * established a class. Do so now. 1237 */ 1238 if (msg->state == DNS_SECTION_ANY && 1239 rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ 1240 rdtype != dns_rdatatype_tsig && /* class is ANY */ 1241 rdtype != dns_rdatatype_tkey) { /* class is undefined */ 1242 msg->rdclass = rdclass; 1243 msg->state = DNS_SECTION_QUESTION; 1244 } 1245 1246 /* 1247 * If this class is different than the one in the question 1248 * section, bail. 1249 */ 1250 if (msg->opcode != dns_opcode_update 1251 && rdtype != dns_rdatatype_tsig 1252 && rdtype != dns_rdatatype_opt 1253 && rdtype != dns_rdatatype_dnskey /* in a TKEY query */ 1254 && rdtype != dns_rdatatype_sig /* SIG(0) */ 1255 && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */ 1256 && msg->rdclass != dns_rdataclass_any 1257 && msg->rdclass != rdclass) 1258 DO_FORMERR; 1259 1260 /* 1261 * Special type handling for TSIG, OPT, and TKEY. 1262 */ 1263 if (rdtype == dns_rdatatype_tsig) { 1264 /* 1265 * If it is a tsig, verify that it is in the 1266 * additional data section. 1267 */ 1268 if (sectionid != DNS_SECTION_ADDITIONAL || 1269 rdclass != dns_rdataclass_any || 1270 count != msg->counts[sectionid] - 1) 1271 DO_FORMERR; 1272 msg->sigstart = recstart; 1273 skip_name_search = ISC_TRUE; 1274 skip_type_search = ISC_TRUE; 1275 } else if (rdtype == dns_rdatatype_opt) { 1276 /* 1277 * The name of an OPT record must be ".", it 1278 * must be in the additional data section, and 1279 * it must be the first OPT we've seen. 1280 */ 1281 if (!dns_name_equal(dns_rootname, name) || 1282 msg->opt != NULL) 1283 DO_FORMERR; 1284 skip_name_search = ISC_TRUE; 1285 skip_type_search = ISC_TRUE; 1286 } else if (rdtype == dns_rdatatype_tkey) { 1287 /* 1288 * A TKEY must be in the additional section if this 1289 * is a query, and the answer section if this is a 1290 * response. Unless it's a Win2000 client. 1291 * 1292 * Its class is ignored. 1293 */ 1294 dns_section_t tkeysection; 1295 1296 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0) 1297 tkeysection = DNS_SECTION_ADDITIONAL; 1298 else 1299 tkeysection = DNS_SECTION_ANSWER; 1300 if (sectionid != tkeysection && 1301 sectionid != DNS_SECTION_ANSWER) 1302 DO_FORMERR; 1303 } 1304 1305 /* 1306 * ... now get ttl and rdatalen, and check buffer. 1307 */ 1308 ttl = isc_buffer_getuint32(source); 1309 rdatalen = isc_buffer_getuint16(source); 1310 r.length -= (2 + 2 + 4 + 2); 1311 if (r.length < rdatalen) { 1312 result = ISC_R_UNEXPECTEDEND; 1313 goto cleanup; 1314 } 1315 1316 /* 1317 * Read the rdata from the wire format. Interpret the 1318 * rdata according to its actual class, even if it had a 1319 * DynDNS meta-class in the packet (unless this is a TSIG). 1320 * Then put the meta-class back into the finished rdata. 1321 */ 1322 rdata = newrdata(msg); 1323 if (rdata == NULL) { 1324 result = ISC_R_NOMEMORY; 1325 goto cleanup; 1326 } 1327 if (msg->opcode == dns_opcode_update && 1328 update(sectionid, rdclass)) { 1329 if (rdatalen != 0) { 1330 result = DNS_R_FORMERR; 1331 goto cleanup; 1332 } 1333 /* 1334 * When the rdata is empty, the data pointer is 1335 * never dereferenced, but it must still be non-NULL. 1336 * Casting 1 rather than "" avoids warnings about 1337 * discarding the const attribute of a string, 1338 * for compilers that would warn about such things. 1339 */ 1340 rdata->data = (unsigned char *)1; 1341 rdata->length = 0; 1342 rdata->rdclass = rdclass; 1343 rdata->type = rdtype; 1344 rdata->flags = DNS_RDATA_UPDATE; 1345 result = ISC_R_SUCCESS; 1346 } else if (rdclass == dns_rdataclass_none && 1347 msg->opcode == dns_opcode_update && 1348 sectionid == DNS_SECTION_UPDATE) { 1349 result = getrdata(source, msg, dctx, msg->rdclass, 1350 rdtype, rdatalen, rdata); 1351 } else 1352 result = getrdata(source, msg, dctx, rdclass, 1353 rdtype, rdatalen, rdata); 1354 if (result != ISC_R_SUCCESS) 1355 goto cleanup; 1356 rdata->rdclass = rdclass; 1357 issigzero = ISC_FALSE; 1358 if (rdtype == dns_rdatatype_rrsig && 1359 rdata->flags == 0) { 1360 covers = dns_rdata_covers(rdata); 1361 if (covers == 0) 1362 DO_FORMERR; 1363 } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ && 1364 rdata->flags == 0) { 1365 covers = dns_rdata_covers(rdata); 1366 if (covers == 0) { 1367 if (sectionid != DNS_SECTION_ADDITIONAL || 1368 count != msg->counts[sectionid] - 1) 1369 DO_FORMERR; 1370 msg->sigstart = recstart; 1371 skip_name_search = ISC_TRUE; 1372 skip_type_search = ISC_TRUE; 1373 issigzero = ISC_TRUE; 1374 } 1375 } else 1376 covers = 0; 1377 1378 /* 1379 * If we are doing a dynamic update or this is a meta-type, 1380 * don't bother searching for a name, just append this one 1381 * to the end of the message. 1382 */ 1383 if (preserve_order || msg->opcode == dns_opcode_update || 1384 skip_name_search) { 1385 if (rdtype != dns_rdatatype_opt && 1386 rdtype != dns_rdatatype_tsig && 1387 !issigzero) 1388 { 1389 ISC_LIST_APPEND(*section, name, link); 1390 free_name = ISC_FALSE; 1391 } 1392 } else { 1393 /* 1394 * Run through the section, looking to see if this name 1395 * is already there. If it is found, put back the 1396 * allocated name since we no longer need it, and set 1397 * our name pointer to point to the name we found. 1398 */ 1399 result = findname(&name2, name, section); 1400 1401 /* 1402 * If it is a new name, append to the section. 1403 */ 1404 if (result == ISC_R_SUCCESS) { 1405 isc_mempool_put(msg->namepool, name); 1406 name = name2; 1407 } else { 1408 ISC_LIST_APPEND(*section, name, link); 1409 } 1410 free_name = ISC_FALSE; 1411 } 1412 1413 /* 1414 * Search name for the particular type and class. 1415 * Skip this stage if in update mode or this is a meta-type. 1416 */ 1417 if (preserve_order || msg->opcode == dns_opcode_update || 1418 skip_type_search) 1419 result = ISC_R_NOTFOUND; 1420 else { 1421 /* 1422 * If this is a type that can only occur in 1423 * the question section, fail. 1424 */ 1425 if (dns_rdatatype_questiononly(rdtype)) 1426 DO_FORMERR; 1427 1428 rdataset = NULL; 1429 result = dns_message_find(name, rdclass, rdtype, 1430 covers, &rdataset); 1431 } 1432 1433 /* 1434 * If we found an rdataset that matches, we need to 1435 * append this rdata to that set. If we did not, we need 1436 * to create a new rdatalist, store the important bits there, 1437 * convert it to an rdataset, and link the latter to the name. 1438 * Yuck. When appending, make certain that the type isn't 1439 * a singleton type, such as SOA or CNAME. 1440 * 1441 * Note that this check will be bypassed when preserving order, 1442 * the opcode is an update, or the type search is skipped. 1443 */ 1444 if (result == ISC_R_SUCCESS) { 1445 if (dns_rdatatype_issingleton(rdtype)) 1446 DO_FORMERR; 1447 } 1448 1449 if (result == ISC_R_NOTFOUND) { 1450 rdataset = isc_mempool_get(msg->rdspool); 1451 if (rdataset == NULL) { 1452 result = ISC_R_NOMEMORY; 1453 goto cleanup; 1454 } 1455 free_rdataset = ISC_TRUE; 1456 1457 rdatalist = newrdatalist(msg); 1458 if (rdatalist == NULL) { 1459 result = ISC_R_NOMEMORY; 1460 goto cleanup; 1461 } 1462 1463 rdatalist->type = rdtype; 1464 rdatalist->covers = covers; 1465 rdatalist->rdclass = rdclass; 1466 rdatalist->ttl = ttl; 1467 ISC_LIST_INIT(rdatalist->rdata); 1468 1469 dns_rdataset_init(rdataset); 1470 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, 1471 rdataset) 1472 == ISC_R_SUCCESS); 1473 1474 if (rdtype != dns_rdatatype_opt && 1475 rdtype != dns_rdatatype_tsig && 1476 !issigzero) 1477 { 1478 ISC_LIST_APPEND(name->list, rdataset, link); 1479 free_rdataset = ISC_FALSE; 1480 } 1481 } 1482 1483 /* 1484 * Minimize TTLs. 1485 * 1486 * Section 5.2 of RFC2181 says we should drop 1487 * nonauthoritative rrsets where the TTLs differ, but we 1488 * currently treat them the as if they were authoritative and 1489 * minimize them. 1490 */ 1491 if (ttl != rdataset->ttl) { 1492 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED; 1493 if (ttl < rdataset->ttl) 1494 rdataset->ttl = ttl; 1495 } 1496 1497 /* Append this rdata to the rdataset. */ 1498 dns_rdatalist_fromrdataset(rdataset, &rdatalist); 1499 ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1500 1501 /* 1502 * If this is an OPT record, remember it. Also, set 1503 * the extended rcode. Note that msg->opt will only be set 1504 * if best-effort parsing is enabled. 1505 */ 1506 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) { 1507 dns_rcode_t ercode; 1508 1509 msg->opt = rdataset; 1510 rdataset = NULL; 1511 free_rdataset = ISC_FALSE; 1512 ercode = (dns_rcode_t) 1513 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) 1514 >> 20); 1515 msg->rcode |= ercode; 1516 isc_mempool_put(msg->namepool, name); 1517 free_name = ISC_FALSE; 1518 } 1519 1520 /* 1521 * If this is an SIG(0) or TSIG record, remember it. Note 1522 * that msg->sig0 or msg->tsig will only be set if best-effort 1523 * parsing is enabled. 1524 */ 1525 if (issigzero && msg->sig0 == NULL) { 1526 msg->sig0 = rdataset; 1527 msg->sig0name = name; 1528 rdataset = NULL; 1529 free_rdataset = ISC_FALSE; 1530 free_name = ISC_FALSE; 1531 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) { 1532 msg->tsig = rdataset; 1533 msg->tsigname = name; 1534 /* Windows doesn't like TSIG names to be compressed. */ 1535 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; 1536 rdataset = NULL; 1537 free_rdataset = ISC_FALSE; 1538 free_name = ISC_FALSE; 1539 } 1540 1541 if (seen_problem) { 1542 if (free_name) 1543 isc_mempool_put(msg->namepool, name); 1544 if (free_rdataset) 1545 isc_mempool_put(msg->rdspool, rdataset); 1546 free_name = free_rdataset = ISC_FALSE; 1547 } 1548 INSIST(free_name == ISC_FALSE); 1549 INSIST(free_rdataset == ISC_FALSE); 1550 } 1551 1552 if (seen_problem) 1553 return (DNS_R_RECOVERABLE); 1554 return (ISC_R_SUCCESS); 1555 1556 cleanup: 1557 if (free_name) 1558 isc_mempool_put(msg->namepool, name); 1559 if (free_rdataset) 1560 isc_mempool_put(msg->rdspool, rdataset); 1561 1562 return (result); 1563} 1564 1565isc_result_t 1566dns_message_parse(dns_message_t *msg, isc_buffer_t *source, 1567 unsigned int options) 1568{ 1569 isc_region_t r; 1570 dns_decompress_t dctx; 1571 isc_result_t ret; 1572 isc_uint16_t tmpflags; 1573 isc_buffer_t origsource; 1574 isc_boolean_t seen_problem; 1575 isc_boolean_t ignore_tc; 1576 1577 REQUIRE(DNS_MESSAGE_VALID(msg)); 1578 REQUIRE(source != NULL); 1579 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 1580 1581 seen_problem = ISC_FALSE; 1582 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION); 1583 1584 origsource = *source; 1585 1586 msg->header_ok = 0; 1587 msg->question_ok = 0; 1588 1589 isc_buffer_remainingregion(source, &r); 1590 if (r.length < DNS_MESSAGE_HEADERLEN) 1591 return (ISC_R_UNEXPECTEDEND); 1592 1593 msg->id = isc_buffer_getuint16(source); 1594 tmpflags = isc_buffer_getuint16(source); 1595 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK) 1596 >> DNS_MESSAGE_OPCODE_SHIFT); 1597 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK); 1598 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK); 1599 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source); 1600 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source); 1601 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source); 1602 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source); 1603 1604 msg->header_ok = 1; 1605 1606 /* 1607 * -1 means no EDNS. 1608 */ 1609 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY); 1610 1611 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14); 1612 1613 ret = getquestions(source, msg, &dctx, options); 1614 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1615 goto truncated; 1616 if (ret == DNS_R_RECOVERABLE) { 1617 seen_problem = ISC_TRUE; 1618 ret = ISC_R_SUCCESS; 1619 } 1620 if (ret != ISC_R_SUCCESS) 1621 return (ret); 1622 msg->question_ok = 1; 1623 1624 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options); 1625 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1626 goto truncated; 1627 if (ret == DNS_R_RECOVERABLE) { 1628 seen_problem = ISC_TRUE; 1629 ret = ISC_R_SUCCESS; 1630 } 1631 if (ret != ISC_R_SUCCESS) 1632 return (ret); 1633 1634 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options); 1635 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1636 goto truncated; 1637 if (ret == DNS_R_RECOVERABLE) { 1638 seen_problem = ISC_TRUE; 1639 ret = ISC_R_SUCCESS; 1640 } 1641 if (ret != ISC_R_SUCCESS) 1642 return (ret); 1643 1644 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options); 1645 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1646 goto truncated; 1647 if (ret == DNS_R_RECOVERABLE) { 1648 seen_problem = ISC_TRUE; 1649 ret = ISC_R_SUCCESS; 1650 } 1651 if (ret != ISC_R_SUCCESS) 1652 return (ret); 1653 1654 isc_buffer_remainingregion(source, &r); 1655 if (r.length != 0) { 1656 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL, 1657 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), 1658 "message has %u byte(s) of trailing garbage", 1659 r.length); 1660 } 1661 1662 truncated: 1663 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) 1664 isc_buffer_usedregion(&origsource, &msg->saved); 1665 else { 1666 msg->saved.length = isc_buffer_usedlength(&origsource); 1667 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); 1668 if (msg->saved.base == NULL) 1669 return (ISC_R_NOMEMORY); 1670 memcpy(msg->saved.base, isc_buffer_base(&origsource), 1671 msg->saved.length); 1672 msg->free_saved = 1; 1673 } 1674 1675 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) 1676 return (DNS_R_RECOVERABLE); 1677 if (seen_problem == ISC_TRUE) 1678 return (DNS_R_RECOVERABLE); 1679 return (ISC_R_SUCCESS); 1680} 1681 1682isc_result_t 1683dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, 1684 isc_buffer_t *buffer) 1685{ 1686 isc_region_t r; 1687 1688 REQUIRE(DNS_MESSAGE_VALID(msg)); 1689 REQUIRE(buffer != NULL); 1690 REQUIRE(msg->buffer == NULL); 1691 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 1692 1693 msg->cctx = cctx; 1694 1695 /* 1696 * Erase the contents of this buffer. 1697 */ 1698 isc_buffer_clear(buffer); 1699 1700 /* 1701 * Make certain there is enough for at least the header in this 1702 * buffer. 1703 */ 1704 isc_buffer_availableregion(buffer, &r); 1705 if (r.length < DNS_MESSAGE_HEADERLEN) 1706 return (ISC_R_NOSPACE); 1707 1708 if (r.length < msg->reserved) 1709 return (ISC_R_NOSPACE); 1710 1711 /* 1712 * Reserve enough space for the header in this buffer. 1713 */ 1714 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); 1715 1716 msg->buffer = buffer; 1717 1718 return (ISC_R_SUCCESS); 1719} 1720 1721isc_result_t 1722dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { 1723 isc_region_t r, rn; 1724 1725 REQUIRE(DNS_MESSAGE_VALID(msg)); 1726 REQUIRE(buffer != NULL); 1727 REQUIRE(msg->buffer != NULL); 1728 1729 /* 1730 * Ensure that the new buffer is empty, and has enough space to 1731 * hold the current contents. 1732 */ 1733 isc_buffer_clear(buffer); 1734 1735 isc_buffer_availableregion(buffer, &rn); 1736 isc_buffer_usedregion(msg->buffer, &r); 1737 REQUIRE(rn.length > r.length); 1738 1739 /* 1740 * Copy the contents from the old to the new buffer. 1741 */ 1742 isc_buffer_add(buffer, r.length); 1743 memcpy(rn.base, r.base, r.length); 1744 1745 msg->buffer = buffer; 1746 1747 return (ISC_R_SUCCESS); 1748} 1749 1750void 1751dns_message_renderrelease(dns_message_t *msg, unsigned int space) { 1752 REQUIRE(DNS_MESSAGE_VALID(msg)); 1753 REQUIRE(space <= msg->reserved); 1754 1755 msg->reserved -= space; 1756} 1757 1758isc_result_t 1759dns_message_renderreserve(dns_message_t *msg, unsigned int space) { 1760 isc_region_t r; 1761 1762 REQUIRE(DNS_MESSAGE_VALID(msg)); 1763 1764 if (msg->buffer != NULL) { 1765 isc_buffer_availableregion(msg->buffer, &r); 1766 if (r.length < (space + msg->reserved)) 1767 return (ISC_R_NOSPACE); 1768 } 1769 1770 msg->reserved += space; 1771 1772 return (ISC_R_SUCCESS); 1773} 1774 1775static inline isc_boolean_t 1776wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { 1777 int pass_needed; 1778 1779 /* 1780 * If we are not rendering class IN, this ordering is bogus. 1781 */ 1782 if (rds->rdclass != dns_rdataclass_in) 1783 return (ISC_FALSE); 1784 1785 switch (rds->type) { 1786 case dns_rdatatype_a: 1787 case dns_rdatatype_aaaa: 1788 if (preferred_glue == rds->type) 1789 pass_needed = 4; 1790 else 1791 pass_needed = 3; 1792 break; 1793 case dns_rdatatype_rrsig: 1794 case dns_rdatatype_dnskey: 1795 pass_needed = 2; 1796 break; 1797 default: 1798 pass_needed = 1; 1799 } 1800 1801 if (pass_needed >= pass) 1802 return (ISC_FALSE); 1803 1804 return (ISC_TRUE); 1805} 1806 1807#ifdef ALLOW_FILTER_AAAA_ON_V4 1808/* 1809 * Decide whether to not answer with an AAAA record and its RRSIG 1810 */ 1811static inline isc_boolean_t 1812norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) 1813{ 1814 switch (rdataset->type) { 1815 case dns_rdatatype_aaaa: 1816 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0) 1817 return (ISC_FALSE); 1818 break; 1819 1820 case dns_rdatatype_rrsig: 1821 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 || 1822 rdataset->covers != dns_rdatatype_aaaa) 1823 return (ISC_FALSE); 1824 break; 1825 1826 default: 1827 return (ISC_FALSE); 1828 } 1829 1830 if (rdataset->rdclass != dns_rdataclass_in) 1831 return (ISC_FALSE); 1832 1833 return (ISC_TRUE); 1834} 1835 1836#endif 1837isc_result_t 1838dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, 1839 unsigned int options) 1840{ 1841 dns_namelist_t *section; 1842 dns_name_t *name, *next_name; 1843 dns_rdataset_t *rdataset, *next_rdataset; 1844 unsigned int count, total; 1845 isc_result_t result; 1846 isc_buffer_t st; /* for rollbacks */ 1847 int pass; 1848 isc_boolean_t partial = ISC_FALSE; 1849 unsigned int rd_options; 1850 dns_rdatatype_t preferred_glue = 0; 1851 1852 REQUIRE(DNS_MESSAGE_VALID(msg)); 1853 REQUIRE(msg->buffer != NULL); 1854 REQUIRE(VALID_NAMED_SECTION(sectionid)); 1855 1856 section = &msg->sections[sectionid]; 1857 1858 if ((sectionid == DNS_SECTION_ADDITIONAL) 1859 && (options & DNS_MESSAGERENDER_ORDERED) == 0) { 1860 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) { 1861 preferred_glue = dns_rdatatype_a; 1862 pass = 4; 1863 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) { 1864 preferred_glue = dns_rdatatype_aaaa; 1865 pass = 4; 1866 } else 1867 pass = 3; 1868 } else 1869 pass = 1; 1870 1871 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) 1872 rd_options = 0; 1873 else 1874 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC; 1875 1876 /* 1877 * Shrink the space in the buffer by the reserved amount. 1878 */ 1879 msg->buffer->length -= msg->reserved; 1880 1881 total = 0; 1882 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) 1883 partial = ISC_TRUE; 1884 1885 /* 1886 * Render required glue first. Set TC if it won't fit. 1887 */ 1888 name = ISC_LIST_HEAD(*section); 1889 if (name != NULL) { 1890 rdataset = ISC_LIST_HEAD(name->list); 1891 if (rdataset != NULL && 1892 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 && 1893 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) { 1894 const void *order_arg = msg->order_arg; 1895 st = *(msg->buffer); 1896 count = 0; 1897 if (partial) 1898 result = dns_rdataset_towirepartial(rdataset, 1899 name, 1900 msg->cctx, 1901 msg->buffer, 1902 msg->order, 1903 order_arg, 1904 rd_options, 1905 &count, 1906 NULL); 1907 else 1908 result = dns_rdataset_towiresorted(rdataset, 1909 name, 1910 msg->cctx, 1911 msg->buffer, 1912 msg->order, 1913 order_arg, 1914 rd_options, 1915 &count); 1916 total += count; 1917 if (partial && result == ISC_R_NOSPACE) { 1918 msg->flags |= DNS_MESSAGEFLAG_TC; 1919 msg->buffer->length += msg->reserved; 1920 msg->counts[sectionid] += total; 1921 return (result); 1922 } 1923 if (result == ISC_R_NOSPACE) 1924 msg->flags |= DNS_MESSAGEFLAG_TC; 1925 if (result != ISC_R_SUCCESS) { 1926 INSIST(st.used < 65536); 1927 dns_compress_rollback(msg->cctx, 1928 (isc_uint16_t)st.used); 1929 *(msg->buffer) = st; /* rollback */ 1930 msg->buffer->length += msg->reserved; 1931 msg->counts[sectionid] += total; 1932 return (result); 1933 } 1934 rdataset->attributes |= DNS_RDATASETATTR_RENDERED; 1935 } 1936 } 1937 1938 do { 1939 name = ISC_LIST_HEAD(*section); 1940 if (name == NULL) { 1941 msg->buffer->length += msg->reserved; 1942 msg->counts[sectionid] += total; 1943 return (ISC_R_SUCCESS); 1944 } 1945 1946 while (name != NULL) { 1947 next_name = ISC_LIST_NEXT(name, link); 1948 1949 rdataset = ISC_LIST_HEAD(name->list); 1950 while (rdataset != NULL) { 1951 next_rdataset = ISC_LIST_NEXT(rdataset, link); 1952 1953 if ((rdataset->attributes & 1954 DNS_RDATASETATTR_RENDERED) != 0) 1955 goto next; 1956 1957 if (((options & DNS_MESSAGERENDER_ORDERED) 1958 == 0) 1959 && (sectionid == DNS_SECTION_ADDITIONAL) 1960 && wrong_priority(rdataset, pass, 1961 preferred_glue)) 1962 goto next; 1963 1964#ifdef ALLOW_FILTER_AAAA_ON_V4 1965 /* 1966 * Suppress AAAAs if asked and we are 1967 * not doing DNSSEC or are breaking DNSSEC. 1968 * Say so in the AD bit if we break DNSSEC. 1969 */ 1970 if (norender_rdataset(rdataset, options) && 1971 sectionid != DNS_SECTION_QUESTION) { 1972 if (sectionid == DNS_SECTION_ANSWER || 1973 sectionid == DNS_SECTION_AUTHORITY) 1974 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1975 if (OPTOUT(rdataset)) 1976 msg->flags &= ~DNS_MESSAGEFLAG_AD; 1977 goto next; 1978 } 1979 1980#endif 1981 st = *(msg->buffer); 1982 1983 count = 0; 1984 if (partial) 1985 result = dns_rdataset_towirepartial( 1986 rdataset, 1987 name, 1988 msg->cctx, 1989 msg->buffer, 1990 msg->order, 1991 msg->order_arg, 1992 rd_options, 1993 &count, 1994 NULL); 1995 else 1996 result = dns_rdataset_towiresorted( 1997 rdataset, 1998 name, 1999 msg->cctx, 2000 msg->buffer, 2001 msg->order, 2002 msg->order_arg, 2003 rd_options, 2004 &count); 2005 2006 total += count; 2007 2008 /* 2009 * If out of space, record stats on what we 2010 * rendered so far, and return that status. 2011 * 2012 * XXXMLG Need to change this when 2013 * dns_rdataset_towire() can render partial 2014 * sets starting at some arbitrary point in the 2015 * set. This will include setting a bit in the 2016 * rdataset to indicate that a partial 2017 * rendering was done, and some state saved 2018 * somewhere (probably in the message struct) 2019 * to indicate where to continue from. 2020 */ 2021 if (partial && result == ISC_R_NOSPACE) { 2022 msg->buffer->length += msg->reserved; 2023 msg->counts[sectionid] += total; 2024 return (result); 2025 } 2026 if (result != ISC_R_SUCCESS) { 2027 INSIST(st.used < 65536); 2028 dns_compress_rollback(msg->cctx, 2029 (isc_uint16_t)st.used); 2030 *(msg->buffer) = st; /* rollback */ 2031 msg->buffer->length += msg->reserved; 2032 msg->counts[sectionid] += total; 2033 return (result); 2034 } 2035 2036 /* 2037 * If we have rendered non-validated data, 2038 * ensure that the AD bit is not set. 2039 */ 2040 if (rdataset->trust != dns_trust_secure && 2041 (sectionid == DNS_SECTION_ANSWER || 2042 sectionid == DNS_SECTION_AUTHORITY)) 2043 msg->flags &= ~DNS_MESSAGEFLAG_AD; 2044 if (OPTOUT(rdataset)) 2045 msg->flags &= ~DNS_MESSAGEFLAG_AD; 2046 2047 rdataset->attributes |= 2048 DNS_RDATASETATTR_RENDERED; 2049 2050 next: 2051 rdataset = next_rdataset; 2052 } 2053 2054 name = next_name; 2055 } 2056 } while (--pass != 0); 2057 2058 msg->buffer->length += msg->reserved; 2059 msg->counts[sectionid] += total; 2060 2061 return (ISC_R_SUCCESS); 2062} 2063 2064void 2065dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { 2066 isc_uint16_t tmp; 2067 isc_region_t r; 2068 2069 REQUIRE(DNS_MESSAGE_VALID(msg)); 2070 REQUIRE(target != NULL); 2071 2072 isc_buffer_availableregion(target, &r); 2073 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); 2074 2075 isc_buffer_putuint16(target, msg->id); 2076 2077 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) 2078 & DNS_MESSAGE_OPCODE_MASK); 2079 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); 2080 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); 2081 2082 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && 2083 msg->counts[DNS_SECTION_ANSWER] < 65536 && 2084 msg->counts[DNS_SECTION_AUTHORITY] < 65536 && 2085 msg->counts[DNS_SECTION_ADDITIONAL] < 65536); 2086 2087 isc_buffer_putuint16(target, tmp); 2088 isc_buffer_putuint16(target, 2089 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]); 2090 isc_buffer_putuint16(target, 2091 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]); 2092 isc_buffer_putuint16(target, 2093 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); 2094 isc_buffer_putuint16(target, 2095 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]); 2096} 2097 2098isc_result_t 2099dns_message_renderend(dns_message_t *msg) { 2100 isc_buffer_t tmpbuf; 2101 isc_region_t r; 2102 int result; 2103 unsigned int count; 2104 2105 REQUIRE(DNS_MESSAGE_VALID(msg)); 2106 REQUIRE(msg->buffer != NULL); 2107 2108 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { 2109 /* 2110 * We have an extended rcode but are not using EDNS. 2111 */ 2112 return (DNS_R_FORMERR); 2113 } 2114 2115 /* 2116 * If we've got an OPT record, render it. 2117 */ 2118 if (msg->opt != NULL) { 2119 dns_message_renderrelease(msg, msg->opt_reserved); 2120 msg->opt_reserved = 0; 2121 /* 2122 * Set the extended rcode. 2123 */ 2124 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; 2125 msg->opt->ttl |= ((msg->rcode << 20) & 2126 DNS_MESSAGE_EDNSRCODE_MASK); 2127 /* 2128 * Render. 2129 */ 2130 count = 0; 2131 result = dns_rdataset_towire(msg->opt, dns_rootname, 2132 msg->cctx, msg->buffer, 0, 2133 &count); 2134 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2135 if (result != ISC_R_SUCCESS) 2136 return (result); 2137 } 2138 2139 /* 2140 * If we're adding a TSIG or SIG(0) to a truncated message, 2141 * clear all rdatasets from the message except for the question 2142 * before adding the TSIG or SIG(0). If the question doesn't fit, 2143 * don't include it. 2144 */ 2145 if ((msg->tsigkey != NULL || msg->sig0key != NULL) && 2146 (msg->flags & DNS_MESSAGEFLAG_TC) != 0) 2147 { 2148 isc_buffer_t *buf; 2149 2150 msgresetnames(msg, DNS_SECTION_ANSWER); 2151 buf = msg->buffer; 2152 dns_message_renderreset(msg); 2153 msg->buffer = buf; 2154 isc_buffer_clear(msg->buffer); 2155 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); 2156 dns_compress_rollback(msg->cctx, 0); 2157 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 2158 0); 2159 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) 2160 return (result); 2161 } 2162 2163 /* 2164 * If we're adding a TSIG record, generate and render it. 2165 */ 2166 if (msg->tsigkey != NULL) { 2167 dns_message_renderrelease(msg, msg->sig_reserved); 2168 msg->sig_reserved = 0; 2169 result = dns_tsig_sign(msg); 2170 if (result != ISC_R_SUCCESS) 2171 return (result); 2172 count = 0; 2173 result = dns_rdataset_towire(msg->tsig, msg->tsigname, 2174 msg->cctx, msg->buffer, 0, 2175 &count); 2176 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2177 if (result != ISC_R_SUCCESS) 2178 return (result); 2179 } 2180 2181 /* 2182 * If we're adding a SIG(0) record, generate and render it. 2183 */ 2184 if (msg->sig0key != NULL) { 2185 dns_message_renderrelease(msg, msg->sig_reserved); 2186 msg->sig_reserved = 0; 2187 result = dns_dnssec_signmessage(msg, msg->sig0key); 2188 if (result != ISC_R_SUCCESS) 2189 return (result); 2190 count = 0; 2191 /* 2192 * Note: dns_rootname is used here, not msg->sig0name, since 2193 * the owner name of a SIG(0) is irrelevant, and will not 2194 * be set in a message being rendered. 2195 */ 2196 result = dns_rdataset_towire(msg->sig0, dns_rootname, 2197 msg->cctx, msg->buffer, 0, 2198 &count); 2199 msg->counts[DNS_SECTION_ADDITIONAL] += count; 2200 if (result != ISC_R_SUCCESS) 2201 return (result); 2202 } 2203 2204 isc_buffer_usedregion(msg->buffer, &r); 2205 isc_buffer_init(&tmpbuf, r.base, r.length); 2206 2207 dns_message_renderheader(msg, &tmpbuf); 2208 2209 msg->buffer = NULL; /* forget about this buffer only on success XXX */ 2210 2211 return (ISC_R_SUCCESS); 2212} 2213 2214void 2215dns_message_renderreset(dns_message_t *msg) { 2216 unsigned int i; 2217 dns_name_t *name; 2218 dns_rdataset_t *rds; 2219 2220 /* 2221 * Reset the message so that it may be rendered again. 2222 */ 2223 2224 REQUIRE(DNS_MESSAGE_VALID(msg)); 2225 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2226 2227 msg->buffer = NULL; 2228 2229 for (i = 0; i < DNS_SECTION_MAX; i++) { 2230 msg->cursors[i] = NULL; 2231 msg->counts[i] = 0; 2232 for (name = ISC_LIST_HEAD(msg->sections[i]); 2233 name != NULL; 2234 name = ISC_LIST_NEXT(name, link)) { 2235 for (rds = ISC_LIST_HEAD(name->list); 2236 rds != NULL; 2237 rds = ISC_LIST_NEXT(rds, link)) { 2238 rds->attributes &= ~DNS_RDATASETATTR_RENDERED; 2239 } 2240 } 2241 } 2242 if (msg->tsigname != NULL) 2243 dns_message_puttempname(msg, &msg->tsigname); 2244 if (msg->tsig != NULL) { 2245 dns_rdataset_disassociate(msg->tsig); 2246 dns_message_puttemprdataset(msg, &msg->tsig); 2247 } 2248 if (msg->sig0 != NULL) { 2249 dns_rdataset_disassociate(msg->sig0); 2250 dns_message_puttemprdataset(msg, &msg->sig0); 2251 } 2252} 2253 2254isc_result_t 2255dns_message_firstname(dns_message_t *msg, dns_section_t section) { 2256 REQUIRE(DNS_MESSAGE_VALID(msg)); 2257 REQUIRE(VALID_NAMED_SECTION(section)); 2258 2259 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); 2260 2261 if (msg->cursors[section] == NULL) 2262 return (ISC_R_NOMORE); 2263 2264 return (ISC_R_SUCCESS); 2265} 2266 2267isc_result_t 2268dns_message_nextname(dns_message_t *msg, dns_section_t section) { 2269 REQUIRE(DNS_MESSAGE_VALID(msg)); 2270 REQUIRE(VALID_NAMED_SECTION(section)); 2271 REQUIRE(msg->cursors[section] != NULL); 2272 2273 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); 2274 2275 if (msg->cursors[section] == NULL) 2276 return (ISC_R_NOMORE); 2277 2278 return (ISC_R_SUCCESS); 2279} 2280 2281void 2282dns_message_currentname(dns_message_t *msg, dns_section_t section, 2283 dns_name_t **name) 2284{ 2285 REQUIRE(DNS_MESSAGE_VALID(msg)); 2286 REQUIRE(VALID_NAMED_SECTION(section)); 2287 REQUIRE(name != NULL && *name == NULL); 2288 REQUIRE(msg->cursors[section] != NULL); 2289 2290 *name = msg->cursors[section]; 2291} 2292 2293isc_result_t 2294dns_message_findname(dns_message_t *msg, dns_section_t section, 2295 dns_name_t *target, dns_rdatatype_t type, 2296 dns_rdatatype_t covers, dns_name_t **name, 2297 dns_rdataset_t **rdataset) 2298{ 2299 dns_name_t *foundname; 2300 isc_result_t result; 2301 2302 /* 2303 * XXX These requirements are probably too intensive, especially 2304 * where things can be NULL, but as they are they ensure that if 2305 * something is NON-NULL, indicating that the caller expects it 2306 * to be filled in, that we can in fact fill it in. 2307 */ 2308 REQUIRE(msg != NULL); 2309 REQUIRE(VALID_SECTION(section)); 2310 REQUIRE(target != NULL); 2311 if (name != NULL) 2312 REQUIRE(*name == NULL); 2313 if (type == dns_rdatatype_any) { 2314 REQUIRE(rdataset == NULL); 2315 } else { 2316 if (rdataset != NULL) 2317 REQUIRE(*rdataset == NULL); 2318 } 2319 2320 result = findname(&foundname, target, 2321 &msg->sections[section]); 2322 2323 if (result == ISC_R_NOTFOUND) 2324 return (DNS_R_NXDOMAIN); 2325 else if (result != ISC_R_SUCCESS) 2326 return (result); 2327 2328 if (name != NULL) 2329 *name = foundname; 2330 2331 /* 2332 * And now look for the type. 2333 */ 2334 if (type == dns_rdatatype_any) 2335 return (ISC_R_SUCCESS); 2336 2337 result = dns_message_findtype(foundname, type, covers, rdataset); 2338 if (result == ISC_R_NOTFOUND) 2339 return (DNS_R_NXRRSET); 2340 2341 return (result); 2342} 2343 2344void 2345dns_message_movename(dns_message_t *msg, dns_name_t *name, 2346 dns_section_t fromsection, 2347 dns_section_t tosection) 2348{ 2349 REQUIRE(msg != NULL); 2350 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2351 REQUIRE(name != NULL); 2352 REQUIRE(VALID_NAMED_SECTION(fromsection)); 2353 REQUIRE(VALID_NAMED_SECTION(tosection)); 2354 2355 /* 2356 * Unlink the name from the old section 2357 */ 2358 ISC_LIST_UNLINK(msg->sections[fromsection], name, link); 2359 ISC_LIST_APPEND(msg->sections[tosection], name, link); 2360} 2361 2362void 2363dns_message_addname(dns_message_t *msg, dns_name_t *name, 2364 dns_section_t section) 2365{ 2366 REQUIRE(msg != NULL); 2367 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2368 REQUIRE(name != NULL); 2369 REQUIRE(VALID_NAMED_SECTION(section)); 2370 2371 ISC_LIST_APPEND(msg->sections[section], name, link); 2372} 2373 2374void 2375dns_message_removename(dns_message_t *msg, dns_name_t *name, 2376 dns_section_t section) 2377{ 2378 REQUIRE(msg != NULL); 2379 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2380 REQUIRE(name != NULL); 2381 REQUIRE(VALID_NAMED_SECTION(section)); 2382 2383 ISC_LIST_UNLINK(msg->sections[section], name, link); 2384} 2385 2386isc_result_t 2387dns_message_gettempname(dns_message_t *msg, dns_name_t **item) { 2388 REQUIRE(DNS_MESSAGE_VALID(msg)); 2389 REQUIRE(item != NULL && *item == NULL); 2390 2391 *item = isc_mempool_get(msg->namepool); 2392 if (*item == NULL) 2393 return (ISC_R_NOMEMORY); 2394 dns_name_init(*item, NULL); 2395 2396 return (ISC_R_SUCCESS); 2397} 2398 2399isc_result_t 2400dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) { 2401 REQUIRE(DNS_MESSAGE_VALID(msg)); 2402 REQUIRE(item != NULL && *item == NULL); 2403 2404 *item = newoffsets(msg); 2405 if (*item == NULL) 2406 return (ISC_R_NOMEMORY); 2407 2408 return (ISC_R_SUCCESS); 2409} 2410 2411isc_result_t 2412dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) { 2413 REQUIRE(DNS_MESSAGE_VALID(msg)); 2414 REQUIRE(item != NULL && *item == NULL); 2415 2416 *item = newrdata(msg); 2417 if (*item == NULL) 2418 return (ISC_R_NOMEMORY); 2419 2420 return (ISC_R_SUCCESS); 2421} 2422 2423isc_result_t 2424dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2425 REQUIRE(DNS_MESSAGE_VALID(msg)); 2426 REQUIRE(item != NULL && *item == NULL); 2427 2428 *item = isc_mempool_get(msg->rdspool); 2429 if (*item == NULL) 2430 return (ISC_R_NOMEMORY); 2431 2432 dns_rdataset_init(*item); 2433 2434 return (ISC_R_SUCCESS); 2435} 2436 2437isc_result_t 2438dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2439 REQUIRE(DNS_MESSAGE_VALID(msg)); 2440 REQUIRE(item != NULL && *item == NULL); 2441 2442 *item = newrdatalist(msg); 2443 if (*item == NULL) 2444 return (ISC_R_NOMEMORY); 2445 2446 return (ISC_R_SUCCESS); 2447} 2448 2449void 2450dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { 2451 REQUIRE(DNS_MESSAGE_VALID(msg)); 2452 REQUIRE(item != NULL && *item != NULL); 2453 2454 if (dns_name_dynamic(*item)) 2455 dns_name_free(*item, msg->mctx); 2456 isc_mempool_put(msg->namepool, *item); 2457 *item = NULL; 2458} 2459 2460void 2461dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { 2462 REQUIRE(DNS_MESSAGE_VALID(msg)); 2463 REQUIRE(item != NULL && *item != NULL); 2464 2465 releaserdata(msg, *item); 2466 *item = NULL; 2467} 2468 2469void 2470dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { 2471 REQUIRE(DNS_MESSAGE_VALID(msg)); 2472 REQUIRE(item != NULL && *item != NULL); 2473 2474 REQUIRE(!dns_rdataset_isassociated(*item)); 2475 isc_mempool_put(msg->rdspool, *item); 2476 *item = NULL; 2477} 2478 2479void 2480dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) { 2481 REQUIRE(DNS_MESSAGE_VALID(msg)); 2482 REQUIRE(item != NULL && *item != NULL); 2483 2484 releaserdatalist(msg, *item); 2485 *item = NULL; 2486} 2487 2488isc_result_t 2489dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp, 2490 unsigned int *flagsp) 2491{ 2492 isc_region_t r; 2493 isc_buffer_t buffer; 2494 dns_messageid_t id; 2495 unsigned int flags; 2496 2497 REQUIRE(source != NULL); 2498 2499 buffer = *source; 2500 2501 isc_buffer_remainingregion(&buffer, &r); 2502 if (r.length < DNS_MESSAGE_HEADERLEN) 2503 return (ISC_R_UNEXPECTEDEND); 2504 2505 id = isc_buffer_getuint16(&buffer); 2506 flags = isc_buffer_getuint16(&buffer); 2507 flags &= DNS_MESSAGE_FLAG_MASK; 2508 2509 if (flagsp != NULL) 2510 *flagsp = flags; 2511 if (idp != NULL) 2512 *idp = id; 2513 2514 return (ISC_R_SUCCESS); 2515} 2516 2517isc_result_t 2518dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) { 2519 unsigned int clear_after; 2520 isc_result_t result; 2521 2522 REQUIRE(DNS_MESSAGE_VALID(msg)); 2523 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0); 2524 2525 if (!msg->header_ok) 2526 return (DNS_R_FORMERR); 2527 if (msg->opcode != dns_opcode_query && 2528 msg->opcode != dns_opcode_notify) 2529 want_question_section = ISC_FALSE; 2530 if (msg->opcode == dns_opcode_update) 2531 clear_after = DNS_SECTION_PREREQUISITE; 2532 else if (want_question_section) { 2533 if (!msg->question_ok) 2534 return (DNS_R_FORMERR); 2535 clear_after = DNS_SECTION_ANSWER; 2536 } else 2537 clear_after = DNS_SECTION_QUESTION; 2538 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER; 2539 msgresetnames(msg, clear_after); 2540 msgresetopt(msg); 2541 msgresetsigs(msg, ISC_TRUE); 2542 msginitprivate(msg); 2543 /* 2544 * We now clear most flags and then set QR, ensuring that the 2545 * reply's flags will be in a reasonable state. 2546 */ 2547 msg->flags &= DNS_MESSAGE_REPLYPRESERVE; 2548 msg->flags |= DNS_MESSAGEFLAG_QR; 2549 2550 /* 2551 * This saves the query TSIG status, if the query was signed, and 2552 * reserves space in the reply for the TSIG. 2553 */ 2554 if (msg->tsigkey != NULL) { 2555 unsigned int otherlen = 0; 2556 msg->querytsigstatus = msg->tsigstatus; 2557 msg->tsigstatus = dns_rcode_noerror; 2558 if (msg->querytsigstatus == dns_tsigerror_badtime) 2559 otherlen = 6; 2560 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen); 2561 result = dns_message_renderreserve(msg, msg->sig_reserved); 2562 if (result != ISC_R_SUCCESS) { 2563 msg->sig_reserved = 0; 2564 return (result); 2565 } 2566 } 2567 if (msg->saved.base != NULL) { 2568 msg->query.base = msg->saved.base; 2569 msg->query.length = msg->saved.length; 2570 msg->free_query = msg->free_saved; 2571 msg->saved.base = NULL; 2572 msg->saved.length = 0; 2573 msg->free_saved = 0; 2574 } 2575 2576 return (ISC_R_SUCCESS); 2577} 2578 2579dns_rdataset_t * 2580dns_message_getopt(dns_message_t *msg) { 2581 2582 /* 2583 * Get the OPT record for 'msg'. 2584 */ 2585 2586 REQUIRE(DNS_MESSAGE_VALID(msg)); 2587 2588 return (msg->opt); 2589} 2590 2591isc_result_t 2592dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { 2593 isc_result_t result; 2594 dns_rdata_t rdata = DNS_RDATA_INIT; 2595 2596 /* 2597 * Set the OPT record for 'msg'. 2598 */ 2599 2600 /* 2601 * The space required for an OPT record is: 2602 * 2603 * 1 byte for the name 2604 * 2 bytes for the type 2605 * 2 bytes for the class 2606 * 4 bytes for the ttl 2607 * 2 bytes for the rdata length 2608 * --------------------------------- 2609 * 11 bytes 2610 * 2611 * plus the length of the rdata. 2612 */ 2613 2614 REQUIRE(DNS_MESSAGE_VALID(msg)); 2615 REQUIRE(opt->type == dns_rdatatype_opt); 2616 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2617 REQUIRE(msg->state == DNS_SECTION_ANY); 2618 2619 msgresetopt(msg); 2620 2621 result = dns_rdataset_first(opt); 2622 if (result != ISC_R_SUCCESS) 2623 goto cleanup; 2624 dns_rdataset_current(opt, &rdata); 2625 msg->opt_reserved = 11 + rdata.length; 2626 result = dns_message_renderreserve(msg, msg->opt_reserved); 2627 if (result != ISC_R_SUCCESS) { 2628 msg->opt_reserved = 0; 2629 goto cleanup; 2630 } 2631 2632 msg->opt = opt; 2633 2634 return (ISC_R_SUCCESS); 2635 2636 cleanup: 2637 dns_message_puttemprdataset(msg, &opt); 2638 return (result); 2639 2640} 2641 2642dns_rdataset_t * 2643dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) { 2644 2645 /* 2646 * Get the TSIG record and owner for 'msg'. 2647 */ 2648 2649 REQUIRE(DNS_MESSAGE_VALID(msg)); 2650 REQUIRE(owner == NULL || *owner == NULL); 2651 2652 if (owner != NULL) 2653 *owner = msg->tsigname; 2654 return (msg->tsig); 2655} 2656 2657isc_result_t 2658dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) { 2659 isc_result_t result; 2660 2661 /* 2662 * Set the TSIG key for 'msg' 2663 */ 2664 2665 REQUIRE(DNS_MESSAGE_VALID(msg)); 2666 REQUIRE(msg->state == DNS_SECTION_ANY); 2667 2668 if (key == NULL && msg->tsigkey != NULL) { 2669 if (msg->sig_reserved != 0) { 2670 dns_message_renderrelease(msg, msg->sig_reserved); 2671 msg->sig_reserved = 0; 2672 } 2673 dns_tsigkey_detach(&msg->tsigkey); 2674 } 2675 if (key != NULL) { 2676 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL); 2677 dns_tsigkey_attach(key, &msg->tsigkey); 2678 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) { 2679 msg->sig_reserved = spacefortsig(msg->tsigkey, 0); 2680 result = dns_message_renderreserve(msg, 2681 msg->sig_reserved); 2682 if (result != ISC_R_SUCCESS) { 2683 dns_tsigkey_detach(&msg->tsigkey); 2684 msg->sig_reserved = 0; 2685 return (result); 2686 } 2687 } 2688 } 2689 return (ISC_R_SUCCESS); 2690} 2691 2692dns_tsigkey_t * 2693dns_message_gettsigkey(dns_message_t *msg) { 2694 2695 /* 2696 * Get the TSIG key for 'msg' 2697 */ 2698 2699 REQUIRE(DNS_MESSAGE_VALID(msg)); 2700 2701 return (msg->tsigkey); 2702} 2703 2704isc_result_t 2705dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) { 2706 dns_rdata_t *rdata = NULL; 2707 dns_rdatalist_t *list = NULL; 2708 dns_rdataset_t *set = NULL; 2709 isc_buffer_t *buf = NULL; 2710 isc_region_t r; 2711 isc_result_t result; 2712 2713 REQUIRE(DNS_MESSAGE_VALID(msg)); 2714 REQUIRE(msg->querytsig == NULL); 2715 2716 if (querytsig == NULL) 2717 return (ISC_R_SUCCESS); 2718 2719 result = dns_message_gettemprdata(msg, &rdata); 2720 if (result != ISC_R_SUCCESS) 2721 goto cleanup; 2722 2723 result = dns_message_gettemprdatalist(msg, &list); 2724 if (result != ISC_R_SUCCESS) 2725 goto cleanup; 2726 result = dns_message_gettemprdataset(msg, &set); 2727 if (result != ISC_R_SUCCESS) 2728 goto cleanup; 2729 2730 isc_buffer_usedregion(querytsig, &r); 2731 result = isc_buffer_allocate(msg->mctx, &buf, r.length); 2732 if (result != ISC_R_SUCCESS) 2733 goto cleanup; 2734 isc_buffer_putmem(buf, r.base, r.length); 2735 isc_buffer_usedregion(buf, &r); 2736 dns_rdata_init(rdata); 2737 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r); 2738 dns_message_takebuffer(msg, &buf); 2739 ISC_LIST_INIT(list->rdata); 2740 ISC_LIST_APPEND(list->rdata, rdata, link); 2741 result = dns_rdatalist_tordataset(list, set); 2742 if (result != ISC_R_SUCCESS) 2743 goto cleanup; 2744 2745 msg->querytsig = set; 2746 2747 return (result); 2748 2749 cleanup: 2750 if (rdata != NULL) 2751 dns_message_puttemprdata(msg, &rdata); 2752 if (list != NULL) 2753 dns_message_puttemprdatalist(msg, &list); 2754 if (set != NULL) 2755 dns_message_puttemprdataset(msg, &set); 2756 return (ISC_R_NOMEMORY); 2757} 2758 2759isc_result_t 2760dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx, 2761 isc_buffer_t **querytsig) { 2762 isc_result_t result; 2763 dns_rdata_t rdata = DNS_RDATA_INIT; 2764 isc_region_t r; 2765 2766 REQUIRE(DNS_MESSAGE_VALID(msg)); 2767 REQUIRE(mctx != NULL); 2768 REQUIRE(querytsig != NULL && *querytsig == NULL); 2769 2770 if (msg->tsig == NULL) 2771 return (ISC_R_SUCCESS); 2772 2773 result = dns_rdataset_first(msg->tsig); 2774 if (result != ISC_R_SUCCESS) 2775 return (result); 2776 dns_rdataset_current(msg->tsig, &rdata); 2777 dns_rdata_toregion(&rdata, &r); 2778 2779 result = isc_buffer_allocate(mctx, querytsig, r.length); 2780 if (result != ISC_R_SUCCESS) 2781 return (result); 2782 isc_buffer_putmem(*querytsig, r.base, r.length); 2783 return (ISC_R_SUCCESS); 2784} 2785 2786dns_rdataset_t * 2787dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) { 2788 2789 /* 2790 * Get the SIG(0) record for 'msg'. 2791 */ 2792 2793 REQUIRE(DNS_MESSAGE_VALID(msg)); 2794 REQUIRE(owner == NULL || *owner == NULL); 2795 2796 if (msg->sig0 != NULL && owner != NULL) { 2797 /* If dns_message_getsig0 is called on a rendered message 2798 * after the SIG(0) has been applied, we need to return the 2799 * root name, not NULL. 2800 */ 2801 if (msg->sig0name == NULL) 2802 *owner = dns_rootname; 2803 else 2804 *owner = msg->sig0name; 2805 } 2806 return (msg->sig0); 2807} 2808 2809isc_result_t 2810dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) { 2811 isc_region_t r; 2812 unsigned int x; 2813 isc_result_t result; 2814 2815 /* 2816 * Set the SIG(0) key for 'msg' 2817 */ 2818 2819 /* 2820 * The space required for an SIG(0) record is: 2821 * 2822 * 1 byte for the name 2823 * 2 bytes for the type 2824 * 2 bytes for the class 2825 * 4 bytes for the ttl 2826 * 2 bytes for the type covered 2827 * 1 byte for the algorithm 2828 * 1 bytes for the labels 2829 * 4 bytes for the original ttl 2830 * 4 bytes for the signature expiration 2831 * 4 bytes for the signature inception 2832 * 2 bytes for the key tag 2833 * n bytes for the signer's name 2834 * x bytes for the signature 2835 * --------------------------------- 2836 * 27 + n + x bytes 2837 */ 2838 REQUIRE(DNS_MESSAGE_VALID(msg)); 2839 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); 2840 REQUIRE(msg->state == DNS_SECTION_ANY); 2841 2842 if (key != NULL) { 2843 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL); 2844 dns_name_toregion(dst_key_name(key), &r); 2845 result = dst_key_sigsize(key, &x); 2846 if (result != ISC_R_SUCCESS) { 2847 msg->sig_reserved = 0; 2848 return (result); 2849 } 2850 msg->sig_reserved = 27 + r.length + x; 2851 result = dns_message_renderreserve(msg, msg->sig_reserved); 2852 if (result != ISC_R_SUCCESS) { 2853 msg->sig_reserved = 0; 2854 return (result); 2855 } 2856 msg->sig0key = key; 2857 } 2858 return (ISC_R_SUCCESS); 2859} 2860 2861dst_key_t * 2862dns_message_getsig0key(dns_message_t *msg) { 2863 2864 /* 2865 * Get the SIG(0) key for 'msg' 2866 */ 2867 2868 REQUIRE(DNS_MESSAGE_VALID(msg)); 2869 2870 return (msg->sig0key); 2871} 2872 2873void 2874dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) { 2875 REQUIRE(DNS_MESSAGE_VALID(msg)); 2876 REQUIRE(buffer != NULL); 2877 REQUIRE(ISC_BUFFER_VALID(*buffer)); 2878 2879 ISC_LIST_APPEND(msg->cleanup, *buffer, link); 2880 *buffer = NULL; 2881} 2882 2883isc_result_t 2884dns_message_signer(dns_message_t *msg, dns_name_t *signer) { 2885 isc_result_t result = ISC_R_SUCCESS; 2886 dns_rdata_t rdata = DNS_RDATA_INIT; 2887 2888 REQUIRE(DNS_MESSAGE_VALID(msg)); 2889 REQUIRE(signer != NULL); 2890 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE); 2891 2892 if (msg->tsig == NULL && msg->sig0 == NULL) 2893 return (ISC_R_NOTFOUND); 2894 2895 if (msg->verify_attempted == 0) 2896 return (DNS_R_NOTVERIFIEDYET); 2897 2898 if (!dns_name_hasbuffer(signer)) { 2899 isc_buffer_t *dynbuf = NULL; 2900 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512); 2901 if (result != ISC_R_SUCCESS) 2902 return (result); 2903 dns_name_setbuffer(signer, dynbuf); 2904 dns_message_takebuffer(msg, &dynbuf); 2905 } 2906 2907 if (msg->sig0 != NULL) { 2908 dns_rdata_sig_t sig; 2909 2910 result = dns_rdataset_first(msg->sig0); 2911 INSIST(result == ISC_R_SUCCESS); 2912 dns_rdataset_current(msg->sig0, &rdata); 2913 2914 result = dns_rdata_tostruct(&rdata, &sig, NULL); 2915 if (result != ISC_R_SUCCESS) 2916 return (result); 2917 2918 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror) 2919 result = ISC_R_SUCCESS; 2920 else 2921 result = DNS_R_SIGINVALID; 2922 dns_name_clone(&sig.signer, signer); 2923 dns_rdata_freestruct(&sig); 2924 } else { 2925 dns_name_t *identity; 2926 dns_rdata_any_tsig_t tsig; 2927 2928 result = dns_rdataset_first(msg->tsig); 2929 INSIST(result == ISC_R_SUCCESS); 2930 dns_rdataset_current(msg->tsig, &rdata); 2931 2932 result = dns_rdata_tostruct(&rdata, &tsig, NULL); 2933 if (msg->tsigstatus != dns_rcode_noerror) 2934 result = DNS_R_TSIGVERIFYFAILURE; 2935 else if (tsig.error != dns_rcode_noerror) 2936 result = DNS_R_TSIGERRORSET; 2937 else 2938 result = ISC_R_SUCCESS; 2939 dns_rdata_freestruct(&tsig); 2940 2941 if (msg->tsigkey == NULL) { 2942 /* 2943 * If msg->tsigstatus & tsig.error are both 2944 * dns_rcode_noerror, the message must have been 2945 * verified, which means msg->tsigkey will be 2946 * non-NULL. 2947 */ 2948 INSIST(result != ISC_R_SUCCESS); 2949 } else { 2950 identity = dns_tsigkey_identity(msg->tsigkey); 2951 if (identity == NULL) { 2952 if (result == ISC_R_SUCCESS) 2953 result = DNS_R_NOIDENTITY; 2954 identity = &msg->tsigkey->name; 2955 } 2956 dns_name_clone(identity, signer); 2957 } 2958 } 2959 2960 return (result); 2961} 2962 2963void 2964dns_message_resetsig(dns_message_t *msg) { 2965 REQUIRE(DNS_MESSAGE_VALID(msg)); 2966 msg->verified_sig = 0; 2967 msg->verify_attempted = 0; 2968 msg->tsigstatus = dns_rcode_noerror; 2969 msg->sig0status = dns_rcode_noerror; 2970 msg->timeadjust = 0; 2971 if (msg->tsigkey != NULL) { 2972 dns_tsigkey_detach(&msg->tsigkey); 2973 msg->tsigkey = NULL; 2974 } 2975} 2976 2977isc_result_t 2978dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) { 2979 dns_message_resetsig(msg); 2980 return (dns_message_checksig(msg, view)); 2981} 2982 2983#ifdef SKAN_MSG_DEBUG 2984void 2985dns_message_dumpsig(dns_message_t *msg, char *txt1) { 2986 dns_rdata_t querytsigrdata = DNS_RDATA_INIT; 2987 dns_rdata_any_tsig_t querytsig; 2988 isc_result_t result; 2989 2990 if (msg->tsig != NULL) { 2991 result = dns_rdataset_first(msg->tsig); 2992 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2993 dns_rdataset_current(msg->tsig, &querytsigrdata); 2994 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 2995 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2996 hexdump(txt1, "TSIG", querytsig.signature, 2997 querytsig.siglen); 2998 } 2999 3000 if (msg->querytsig != NULL) { 3001 result = dns_rdataset_first(msg->querytsig); 3002 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3003 dns_rdataset_current(msg->querytsig, &querytsigrdata); 3004 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); 3005 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3006 hexdump(txt1, "QUERYTSIG", querytsig.signature, 3007 querytsig.siglen); 3008 } 3009} 3010#endif 3011 3012isc_result_t 3013dns_message_checksig(dns_message_t *msg, dns_view_t *view) { 3014 isc_buffer_t b, msgb; 3015 3016 REQUIRE(DNS_MESSAGE_VALID(msg)); 3017 3018 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL) 3019 return (ISC_R_SUCCESS); 3020 3021 INSIST(msg->saved.base != NULL); 3022 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length); 3023 isc_buffer_add(&msgb, msg->saved.length); 3024 if (msg->tsigkey != NULL || msg->tsig != NULL) { 3025#ifdef SKAN_MSG_DEBUG 3026 dns_message_dumpsig(msg, "dns_message_checksig#1"); 3027#endif 3028 if (view != NULL) 3029 return (dns_view_checksig(view, &msgb, msg)); 3030 else 3031 return (dns_tsig_verify(&msgb, msg, NULL, NULL)); 3032 } else { 3033 dns_rdata_t rdata = DNS_RDATA_INIT; 3034 dns_rdata_sig_t sig; 3035 dns_rdataset_t keyset; 3036 isc_result_t result; 3037 3038 result = dns_rdataset_first(msg->sig0); 3039 INSIST(result == ISC_R_SUCCESS); 3040 dns_rdataset_current(msg->sig0, &rdata); 3041 3042 /* 3043 * This can occur when the message is a dynamic update, since 3044 * the rdata length checking is relaxed. This should not 3045 * happen in a well-formed message, since the SIG(0) is only 3046 * looked for in the additional section, and the dynamic update 3047 * meta-records are in the prerequisite and update sections. 3048 */ 3049 if (rdata.length == 0) 3050 return (ISC_R_UNEXPECTEDEND); 3051 3052 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx); 3053 if (result != ISC_R_SUCCESS) 3054 return (result); 3055 3056 dns_rdataset_init(&keyset); 3057 if (view == NULL) 3058 return (DNS_R_KEYUNAUTHORIZED); 3059 result = dns_view_simplefind(view, &sig.signer, 3060 dns_rdatatype_key /* SIG(0) */, 3061 0, 0, ISC_FALSE, &keyset, NULL); 3062 3063 if (result != ISC_R_SUCCESS) { 3064 /* XXXBEW Should possibly create a fetch here */ 3065 result = DNS_R_KEYUNAUTHORIZED; 3066 goto freesig; 3067 } else if (keyset.trust < dns_trust_secure) { 3068 /* XXXBEW Should call a validator here */ 3069 result = DNS_R_KEYUNAUTHORIZED; 3070 goto freesig; 3071 } 3072 result = dns_rdataset_first(&keyset); 3073 INSIST(result == ISC_R_SUCCESS); 3074 for (; 3075 result == ISC_R_SUCCESS; 3076 result = dns_rdataset_next(&keyset)) 3077 { 3078 dst_key_t *key = NULL; 3079 3080 dns_rdata_reset(&rdata); 3081 dns_rdataset_current(&keyset, &rdata); 3082 isc_buffer_init(&b, rdata.data, rdata.length); 3083 isc_buffer_add(&b, rdata.length); 3084 3085 result = dst_key_fromdns(&sig.signer, rdata.rdclass, 3086 &b, view->mctx, &key); 3087 if (result != ISC_R_SUCCESS) 3088 continue; 3089 if (dst_key_alg(key) != sig.algorithm || 3090 dst_key_id(key) != sig.keyid || 3091 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC || 3092 dst_key_proto(key) == DNS_KEYPROTO_ANY)) 3093 { 3094 dst_key_free(&key); 3095 continue; 3096 } 3097 result = dns_dnssec_verifymessage(&msgb, msg, key); 3098 dst_key_free(&key); 3099 if (result == ISC_R_SUCCESS) 3100 break; 3101 } 3102 if (result == ISC_R_NOMORE) 3103 result = DNS_R_KEYUNAUTHORIZED; 3104 3105 freesig: 3106 if (dns_rdataset_isassociated(&keyset)) 3107 dns_rdataset_disassociate(&keyset); 3108 dns_rdata_freestruct(&sig); 3109 return (result); 3110 } 3111} 3112 3113isc_result_t 3114dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, 3115 const dns_master_style_t *style, 3116 dns_messagetextflag_t flags, 3117 isc_buffer_t *target) { 3118 dns_name_t *name, empty_name; 3119 dns_rdataset_t *rdataset; 3120 isc_result_t result; 3121 isc_boolean_t seensoa = ISC_FALSE; 3122 3123 REQUIRE(DNS_MESSAGE_VALID(msg)); 3124 REQUIRE(target != NULL); 3125 REQUIRE(VALID_SECTION(section)); 3126 3127 if (ISC_LIST_EMPTY(msg->sections[section])) 3128 return (ISC_R_SUCCESS); 3129 3130 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { 3131 ADD_STRING(target, ";; "); 3132 if (msg->opcode != dns_opcode_update) { 3133 ADD_STRING(target, sectiontext[section]); 3134 } else { 3135 ADD_STRING(target, updsectiontext[section]); 3136 } 3137 ADD_STRING(target, " SECTION:\n"); 3138 } 3139 3140 dns_name_init(&empty_name, NULL); 3141 result = dns_message_firstname(msg, section); 3142 if (result != ISC_R_SUCCESS) { 3143 return (result); 3144 } 3145 do { 3146 name = NULL; 3147 dns_message_currentname(msg, section, &name); 3148 for (rdataset = ISC_LIST_HEAD(name->list); 3149 rdataset != NULL; 3150 rdataset = ISC_LIST_NEXT(rdataset, link)) { 3151 if (section == DNS_SECTION_ANSWER && 3152 rdataset->type == dns_rdatatype_soa) { 3153 if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0) 3154 continue; 3155 if (seensoa && 3156 (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0) 3157 continue; 3158 seensoa = ISC_TRUE; 3159 } 3160 if (section == DNS_SECTION_QUESTION) { 3161 ADD_STRING(target, ";"); 3162 result = dns_master_questiontotext(name, 3163 rdataset, 3164 style, 3165 target); 3166 } else { 3167 result = dns_master_rdatasettotext(name, 3168 rdataset, 3169 style, 3170 target); 3171 } 3172 if (result != ISC_R_SUCCESS) 3173 return (result); 3174 } 3175 result = dns_message_nextname(msg, section); 3176 } while (result == ISC_R_SUCCESS); 3177 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3178 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3179 ADD_STRING(target, "\n"); 3180 if (result == ISC_R_NOMORE) 3181 result = ISC_R_SUCCESS; 3182 return (result); 3183} 3184 3185isc_result_t 3186dns_message_pseudosectiontotext(dns_message_t *msg, 3187 dns_pseudosection_t section, 3188 const dns_master_style_t *style, 3189 dns_messagetextflag_t flags, 3190 isc_buffer_t *target) { 3191 dns_rdataset_t *ps = NULL; 3192 dns_name_t *name = NULL; 3193 isc_result_t result; 3194 char buf[sizeof("1234567890")]; 3195 isc_uint32_t mbz; 3196 dns_rdata_t rdata; 3197 isc_buffer_t optbuf; 3198 isc_uint16_t optcode, optlen; 3199 unsigned char *optdata; 3200 3201 REQUIRE(DNS_MESSAGE_VALID(msg)); 3202 REQUIRE(target != NULL); 3203 REQUIRE(VALID_PSEUDOSECTION(section)); 3204 3205 switch (section) { 3206 case DNS_PSEUDOSECTION_OPT: 3207 ps = dns_message_getopt(msg); 3208 if (ps == NULL) 3209 return (ISC_R_SUCCESS); 3210 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3211 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); 3212 ADD_STRING(target, "; EDNS: version: "); 3213 snprintf(buf, sizeof(buf), "%u", 3214 (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); 3215 ADD_STRING(target, buf); 3216 ADD_STRING(target, ", flags:"); 3217 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) 3218 ADD_STRING(target, " do"); 3219 mbz = ps->ttl & 0xffff; 3220 mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ 3221 if (mbz != 0) { 3222 ADD_STRING(target, "; MBZ: "); 3223 snprintf(buf, sizeof(buf), "%.4x ", mbz); 3224 ADD_STRING(target, buf); 3225 ADD_STRING(target, ", udp: "); 3226 } else 3227 ADD_STRING(target, "; udp: "); 3228 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); 3229 ADD_STRING(target, buf); 3230 3231 result = dns_rdataset_first(ps); 3232 if (result != ISC_R_SUCCESS) 3233 return (ISC_R_SUCCESS); 3234 3235 /* Print EDNS info, if any */ 3236 dns_rdata_init(&rdata); 3237 dns_rdataset_current(ps, &rdata); 3238 3239 isc_buffer_init(&optbuf, rdata.data, rdata.length); 3240 isc_buffer_add(&optbuf, rdata.length); 3241 while (isc_buffer_remaininglength(&optbuf) != 0) { 3242 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U); 3243 optcode = isc_buffer_getuint16(&optbuf); 3244 optlen = isc_buffer_getuint16(&optbuf); 3245 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); 3246 3247 if (optcode == DNS_OPT_NSID) { 3248 ADD_STRING(target, "; NSID"); 3249 } else { 3250 ADD_STRING(target, "; OPT="); 3251 sprintf(buf, "%u", optcode); 3252 ADD_STRING(target, buf); 3253 } 3254 3255 if (optlen != 0) { 3256 int i; 3257 ADD_STRING(target, ": "); 3258 3259 optdata = isc_buffer_current(&optbuf); 3260 for (i = 0; i < optlen; i++) { 3261 sprintf(buf, "%02x ", optdata[i]); 3262 ADD_STRING(target, buf); 3263 } 3264 for (i = 0; i < optlen; i++) { 3265 ADD_STRING(target, " ("); 3266 if (isprint(optdata[i])) 3267 isc_buffer_putmem(target, 3268 &optdata[i], 3269 1); 3270 else 3271 isc_buffer_putstr(target, "."); 3272 ADD_STRING(target, ")"); 3273 } 3274 isc_buffer_forward(&optbuf, optlen); 3275 } 3276 ADD_STRING(target, "\n"); 3277 } 3278 return (ISC_R_SUCCESS); 3279 case DNS_PSEUDOSECTION_TSIG: 3280 ps = dns_message_gettsig(msg, &name); 3281 if (ps == NULL) 3282 return (ISC_R_SUCCESS); 3283 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3284 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); 3285 result = dns_master_rdatasettotext(name, ps, style, target); 3286 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3287 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3288 ADD_STRING(target, "\n"); 3289 return (result); 3290 case DNS_PSEUDOSECTION_SIG0: 3291 ps = dns_message_getsig0(msg, &name); 3292 if (ps == NULL) 3293 return (ISC_R_SUCCESS); 3294 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3295 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); 3296 result = dns_master_rdatasettotext(name, ps, style, target); 3297 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && 3298 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) 3299 ADD_STRING(target, "\n"); 3300 return (result); 3301 } 3302 return (ISC_R_UNEXPECTED); 3303} 3304 3305isc_result_t 3306dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, 3307 dns_messagetextflag_t flags, isc_buffer_t *target) { 3308 char buf[sizeof("1234567890")]; 3309 isc_result_t result; 3310 3311 REQUIRE(DNS_MESSAGE_VALID(msg)); 3312 REQUIRE(target != NULL); 3313 3314 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) { 3315 ADD_STRING(target, ";; ->>HEADER<<- opcode: "); 3316 ADD_STRING(target, opcodetext[msg->opcode]); 3317 ADD_STRING(target, ", status: "); 3318 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 3319 ADD_STRING(target, rcodetext[msg->rcode]); 3320 } else { 3321 snprintf(buf, sizeof(buf), "%4u", msg->rcode); 3322 ADD_STRING(target, buf); 3323 } 3324 ADD_STRING(target, ", id: "); 3325 snprintf(buf, sizeof(buf), "%6u", msg->id); 3326 ADD_STRING(target, buf); 3327 ADD_STRING(target, "\n;; flags:"); 3328 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) 3329 ADD_STRING(target, " qr"); 3330 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) 3331 ADD_STRING(target, " aa"); 3332 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) 3333 ADD_STRING(target, " tc"); 3334 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) 3335 ADD_STRING(target, " rd"); 3336 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) 3337 ADD_STRING(target, " ra"); 3338 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) 3339 ADD_STRING(target, " ad"); 3340 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) 3341 ADD_STRING(target, " cd"); 3342 /* 3343 * The final unnamed flag must be zero. 3344 */ 3345 if ((msg->flags & 0x0040U) != 0) 3346 ADD_STRING(target, "; MBZ: 0x4"); 3347 if (msg->opcode != dns_opcode_update) { 3348 ADD_STRING(target, "; QUESTION: "); 3349 } else { 3350 ADD_STRING(target, "; ZONE: "); 3351 } 3352 snprintf(buf, sizeof(buf), "%1u", 3353 msg->counts[DNS_SECTION_QUESTION]); 3354 ADD_STRING(target, buf); 3355 if (msg->opcode != dns_opcode_update) { 3356 ADD_STRING(target, ", ANSWER: "); 3357 } else { 3358 ADD_STRING(target, ", PREREQ: "); 3359 } 3360 snprintf(buf, sizeof(buf), "%1u", 3361 msg->counts[DNS_SECTION_ANSWER]); 3362 ADD_STRING(target, buf); 3363 if (msg->opcode != dns_opcode_update) { 3364 ADD_STRING(target, ", AUTHORITY: "); 3365 } else { 3366 ADD_STRING(target, ", UPDATE: "); 3367 } 3368 snprintf(buf, sizeof(buf), "%1u", 3369 msg->counts[DNS_SECTION_AUTHORITY]); 3370 ADD_STRING(target, buf); 3371 ADD_STRING(target, ", ADDITIONAL: "); 3372 snprintf(buf, sizeof(buf), "%1u", 3373 msg->counts[DNS_SECTION_ADDITIONAL]); 3374 ADD_STRING(target, buf); 3375 ADD_STRING(target, "\n"); 3376 } 3377 result = dns_message_pseudosectiontotext(msg, 3378 DNS_PSEUDOSECTION_OPT, 3379 style, flags, target); 3380 if (result != ISC_R_SUCCESS) 3381 return (result); 3382 3383 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION, 3384 style, flags, target); 3385 if (result != ISC_R_SUCCESS) 3386 return (result); 3387 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER, 3388 style, flags, target); 3389 if (result != ISC_R_SUCCESS) 3390 return (result); 3391 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY, 3392 style, flags, target); 3393 if (result != ISC_R_SUCCESS) 3394 return (result); 3395 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL, 3396 style, flags, target); 3397 if (result != ISC_R_SUCCESS) 3398 return (result); 3399 3400 result = dns_message_pseudosectiontotext(msg, 3401 DNS_PSEUDOSECTION_TSIG, 3402 style, flags, target); 3403 if (result != ISC_R_SUCCESS) 3404 return (result); 3405 3406 result = dns_message_pseudosectiontotext(msg, 3407 DNS_PSEUDOSECTION_SIG0, 3408 style, flags, target); 3409 if (result != ISC_R_SUCCESS) 3410 return (result); 3411 3412 return (ISC_R_SUCCESS); 3413} 3414 3415isc_region_t * 3416dns_message_getrawmessage(dns_message_t *msg) { 3417 REQUIRE(DNS_MESSAGE_VALID(msg)); 3418 return (&msg->saved); 3419} 3420 3421void 3422dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order, 3423 const void *order_arg) 3424{ 3425 REQUIRE(DNS_MESSAGE_VALID(msg)); 3426 msg->order = order; 3427 msg->order_arg = order_arg; 3428} 3429 3430void 3431dns_message_settimeadjust(dns_message_t *msg, int timeadjust) { 3432 REQUIRE(DNS_MESSAGE_VALID(msg)); 3433 msg->timeadjust = timeadjust; 3434} 3435 3436int 3437dns_message_gettimeadjust(dns_message_t *msg) { 3438 REQUIRE(DNS_MESSAGE_VALID(msg)); 3439 return (msg->timeadjust); 3440} 3441 3442isc_result_t 3443dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) { 3444 3445 REQUIRE(opcode < 16); 3446 3447 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode])) 3448 return (ISC_R_NOSPACE); 3449 isc_buffer_putstr(target, opcodetext[opcode]); 3450 return (ISC_R_SUCCESS); 3451} 3452