1 /* 2 * util/data/msgreply.c - store message and reply data. 3 * 4 * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /** 37 * \file 38 * 39 * This file contains a data structure to store a message and its reply. 40 */ 41 42 #include "config.h" 43 #include "util/data/msgreply.h" 44 #include "util/storage/lookup3.h" 45 #include "util/log.h" 46 #include "util/alloc.h" 47 #include "util/netevent.h" 48 #include "util/net_help.h" 49 #include "util/data/dname.h" 50 #include "util/regional.h" 51 #include "util/data/msgparse.h" 52 #include "util/data/msgencode.h" 53 #include "sldns/sbuffer.h" 54 #include "sldns/wire2str.h" 55 56 /** MAX TTL default for messages and rrsets */ 57 time_t MAX_TTL = 3600 * 24 * 10; /* ten days */ 58 /** MIN TTL default for messages and rrsets */ 59 time_t MIN_TTL = 0; 60 /** MAX Negative TTL, for SOA records in authority section */ 61 time_t MAX_NEG_TTL = 3600; /* one hour */ 62 63 /** allocate qinfo, return 0 on error */ 64 static int 65 parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg, 66 struct query_info* qinf, struct regional* region) 67 { 68 if(msg->qname) { 69 if(region) 70 qinf->qname = (uint8_t*)regional_alloc(region, 71 msg->qname_len); 72 else qinf->qname = (uint8_t*)malloc(msg->qname_len); 73 if(!qinf->qname) return 0; 74 dname_pkt_copy(pkt, qinf->qname, msg->qname); 75 } else qinf->qname = 0; 76 qinf->qname_len = msg->qname_len; 77 qinf->qtype = msg->qtype; 78 qinf->qclass = msg->qclass; 79 return 1; 80 } 81 82 /** constructor for replyinfo */ 83 struct reply_info* 84 construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, 85 time_t ttl, time_t prettl, size_t an, size_t ns, size_t ar, 86 size_t total, enum sec_status sec) 87 { 88 struct reply_info* rep; 89 /* rrset_count-1 because the first ref is part of the struct. */ 90 size_t s = sizeof(struct reply_info) - sizeof(struct rrset_ref) + 91 sizeof(struct ub_packed_rrset_key*) * total; 92 if(total >= RR_COUNT_MAX) return NULL; /* sanity check on numRRS*/ 93 if(region) 94 rep = (struct reply_info*)regional_alloc(region, s); 95 else rep = (struct reply_info*)malloc(s + 96 sizeof(struct rrset_ref) * (total)); 97 if(!rep) 98 return NULL; 99 rep->flags = flags; 100 rep->qdcount = qd; 101 rep->ttl = ttl; 102 rep->prefetch_ttl = prettl; 103 rep->an_numrrsets = an; 104 rep->ns_numrrsets = ns; 105 rep->ar_numrrsets = ar; 106 rep->rrset_count = total; 107 rep->security = sec; 108 rep->authoritative = 0; 109 /* array starts after the refs */ 110 if(region) 111 rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[0]); 112 else rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[total]); 113 /* zero the arrays to assist cleanup in case of malloc failure */ 114 memset( rep->rrsets, 0, sizeof(struct ub_packed_rrset_key*) * total); 115 if(!region) 116 memset( &rep->ref[0], 0, sizeof(struct rrset_ref) * total); 117 return rep; 118 } 119 120 /** allocate replyinfo, return 0 on error */ 121 static int 122 parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep, 123 struct regional* region) 124 { 125 *rep = construct_reply_info_base(region, msg->flags, msg->qdcount, 0, 126 0, msg->an_rrsets, msg->ns_rrsets, msg->ar_rrsets, 127 msg->rrset_count, sec_status_unchecked); 128 if(!*rep) 129 return 0; 130 return 1; 131 } 132 133 /** allocate (special) rrset keys, return 0 on error */ 134 static int 135 repinfo_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, 136 struct regional* region) 137 { 138 size_t i; 139 for(i=0; i<rep->rrset_count; i++) { 140 if(region) { 141 rep->rrsets[i] = (struct ub_packed_rrset_key*) 142 regional_alloc(region, 143 sizeof(struct ub_packed_rrset_key)); 144 if(rep->rrsets[i]) { 145 memset(rep->rrsets[i], 0, 146 sizeof(struct ub_packed_rrset_key)); 147 rep->rrsets[i]->entry.key = rep->rrsets[i]; 148 } 149 } 150 else rep->rrsets[i] = alloc_special_obtain(alloc); 151 if(!rep->rrsets[i]) 152 return 0; 153 rep->rrsets[i]->entry.data = NULL; 154 } 155 return 1; 156 } 157 158 /** find the minimumttl in the rdata of SOA record */ 159 static time_t 160 soa_find_minttl(struct rr_parse* rr) 161 { 162 uint16_t rlen = sldns_read_uint16(rr->ttl_data+4); 163 if(rlen < 20) 164 return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */ 165 /* minimum TTL is the last 32bit value in the rdata of the record */ 166 /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/ 167 return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4); 168 } 169 170 /** do the rdata copy */ 171 static int 172 rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, 173 struct rr_parse* rr, time_t* rr_ttl, uint16_t type, 174 sldns_pkt_section section) 175 { 176 uint16_t pkt_len; 177 const sldns_rr_descriptor* desc; 178 179 *rr_ttl = sldns_read_uint32(rr->ttl_data); 180 /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ 181 if(*rr_ttl & 0x80000000U) 182 *rr_ttl = 0; 183 if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) { 184 /* negative response. see if TTL of SOA record larger than the 185 * minimum-ttl in the rdata of the SOA record */ 186 if(*rr_ttl > soa_find_minttl(rr)) 187 *rr_ttl = soa_find_minttl(rr); 188 if(*rr_ttl > MAX_NEG_TTL) 189 *rr_ttl = MAX_NEG_TTL; 190 } 191 if(*rr_ttl < MIN_TTL) 192 *rr_ttl = MIN_TTL; 193 if(*rr_ttl < data->ttl) 194 data->ttl = *rr_ttl; 195 196 if(rr->outside_packet) { 197 /* uncompressed already, only needs copy */ 198 memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size); 199 return 1; 200 } 201 202 sldns_buffer_set_position(pkt, (size_t) 203 (rr->ttl_data - sldns_buffer_begin(pkt) + sizeof(uint32_t))); 204 /* insert decompressed size into rdata len stored in memory */ 205 /* -2 because rdatalen bytes are not included. */ 206 pkt_len = htons(rr->size - 2); 207 memmove(to, &pkt_len, sizeof(uint16_t)); 208 to += 2; 209 /* read packet rdata len */ 210 pkt_len = sldns_buffer_read_u16(pkt); 211 if(sldns_buffer_remaining(pkt) < pkt_len) 212 return 0; 213 desc = sldns_rr_descript(type); 214 if(pkt_len > 0 && desc && desc->_dname_count > 0) { 215 int count = (int)desc->_dname_count; 216 int rdf = 0; 217 size_t len; 218 size_t oldpos; 219 /* decompress dnames. */ 220 while(pkt_len > 0 && count) { 221 switch(desc->_wireformat[rdf]) { 222 case LDNS_RDF_TYPE_DNAME: 223 oldpos = sldns_buffer_position(pkt); 224 dname_pkt_copy(pkt, to, 225 sldns_buffer_current(pkt)); 226 to += pkt_dname_len(pkt); 227 pkt_len -= sldns_buffer_position(pkt)-oldpos; 228 count--; 229 len = 0; 230 break; 231 case LDNS_RDF_TYPE_STR: 232 len = sldns_buffer_current(pkt)[0] + 1; 233 break; 234 default: 235 len = get_rdf_size(desc->_wireformat[rdf]); 236 break; 237 } 238 if(len) { 239 memmove(to, sldns_buffer_current(pkt), len); 240 to += len; 241 sldns_buffer_skip(pkt, (ssize_t)len); 242 log_assert(len <= pkt_len); 243 pkt_len -= len; 244 } 245 rdf++; 246 } 247 } 248 /* copy remaining rdata */ 249 if(pkt_len > 0) 250 memmove(to, sldns_buffer_current(pkt), pkt_len); 251 252 return 1; 253 } 254 255 /** copy over the data into packed rrset */ 256 static int 257 parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset, 258 struct packed_rrset_data* data) 259 { 260 size_t i; 261 struct rr_parse* rr = pset->rr_first; 262 uint8_t* nextrdata; 263 size_t total = pset->rr_count + pset->rrsig_count; 264 data->ttl = MAX_TTL; 265 data->count = pset->rr_count; 266 data->rrsig_count = pset->rrsig_count; 267 data->trust = rrset_trust_none; 268 data->security = sec_status_unchecked; 269 /* layout: struct - rr_len - rr_data - rr_ttl - rdata - rrsig */ 270 data->rr_len = (size_t*)((uint8_t*)data + 271 sizeof(struct packed_rrset_data)); 272 data->rr_data = (uint8_t**)&(data->rr_len[total]); 273 data->rr_ttl = (time_t*)&(data->rr_data[total]); 274 nextrdata = (uint8_t*)&(data->rr_ttl[total]); 275 for(i=0; i<data->count; i++) { 276 data->rr_len[i] = rr->size; 277 data->rr_data[i] = nextrdata; 278 nextrdata += rr->size; 279 if(!rdata_copy(pkt, data, data->rr_data[i], rr, 280 &data->rr_ttl[i], pset->type, pset->section)) 281 return 0; 282 rr = rr->next; 283 } 284 /* if rrsig, its rdata is at nextrdata */ 285 rr = pset->rrsig_first; 286 for(i=data->count; i<total; i++) { 287 data->rr_len[i] = rr->size; 288 data->rr_data[i] = nextrdata; 289 nextrdata += rr->size; 290 if(!rdata_copy(pkt, data, data->rr_data[i], rr, 291 &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG, pset->section)) 292 return 0; 293 rr = rr->next; 294 } 295 return 1; 296 } 297 298 /** create rrset return 0 on failure */ 299 static int 300 parse_create_rrset(sldns_buffer* pkt, struct rrset_parse* pset, 301 struct packed_rrset_data** data, struct regional* region) 302 { 303 /* allocate */ 304 size_t s; 305 if(pset->rr_count > RR_COUNT_MAX || pset->rrsig_count > RR_COUNT_MAX || 306 pset->size > RR_COUNT_MAX) 307 return 0; /* protect against integer overflow */ 308 s = sizeof(struct packed_rrset_data) + 309 (pset->rr_count + pset->rrsig_count) * 310 (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)) + 311 pset->size; 312 if(region) 313 *data = regional_alloc(region, s); 314 else *data = malloc(s); 315 if(!*data) 316 return 0; 317 /* copy & decompress */ 318 if(!parse_rr_copy(pkt, pset, *data)) { 319 if(!region) free(*data); 320 return 0; 321 } 322 return 1; 323 } 324 325 /** get trust value for rrset */ 326 static enum rrset_trust 327 get_rrset_trust(struct msg_parse* msg, struct rrset_parse* rrset) 328 { 329 uint16_t AA = msg->flags & BIT_AA; 330 if(rrset->section == LDNS_SECTION_ANSWER) { 331 if(AA) { 332 /* RFC2181 says remainder of CNAME chain is nonauth*/ 333 if(msg->rrset_first && 334 msg->rrset_first->section==LDNS_SECTION_ANSWER 335 && msg->rrset_first->type==LDNS_RR_TYPE_CNAME){ 336 if(rrset == msg->rrset_first) 337 return rrset_trust_ans_AA; 338 else return rrset_trust_ans_noAA; 339 } 340 if(msg->rrset_first && 341 msg->rrset_first->section==LDNS_SECTION_ANSWER 342 && msg->rrset_first->type==LDNS_RR_TYPE_DNAME){ 343 if(rrset == msg->rrset_first || 344 rrset == msg->rrset_first->rrset_all_next) 345 return rrset_trust_ans_AA; 346 else return rrset_trust_ans_noAA; 347 } 348 return rrset_trust_ans_AA; 349 } 350 else return rrset_trust_ans_noAA; 351 } else if(rrset->section == LDNS_SECTION_AUTHORITY) { 352 if(AA) return rrset_trust_auth_AA; 353 else return rrset_trust_auth_noAA; 354 } else { 355 /* addit section */ 356 if(AA) return rrset_trust_add_AA; 357 else return rrset_trust_add_noAA; 358 } 359 /* NOTREACHED */ 360 return rrset_trust_none; 361 } 362 363 int 364 parse_copy_decompress_rrset(sldns_buffer* pkt, struct msg_parse* msg, 365 struct rrset_parse *pset, struct regional* region, 366 struct ub_packed_rrset_key* pk) 367 { 368 struct packed_rrset_data* data; 369 pk->rk.flags = pset->flags; 370 pk->rk.dname_len = pset->dname_len; 371 if(region) 372 pk->rk.dname = (uint8_t*)regional_alloc( 373 region, pset->dname_len); 374 else pk->rk.dname = 375 (uint8_t*)malloc(pset->dname_len); 376 if(!pk->rk.dname) 377 return 0; 378 /** copy & decompress dname */ 379 dname_pkt_copy(pkt, pk->rk.dname, pset->dname); 380 /** copy over type and class */ 381 pk->rk.type = htons(pset->type); 382 pk->rk.rrset_class = pset->rrset_class; 383 /** read data part. */ 384 if(!parse_create_rrset(pkt, pset, &data, region)) 385 return 0; 386 pk->entry.data = (void*)data; 387 pk->entry.key = (void*)pk; 388 pk->entry.hash = pset->hash; 389 data->trust = get_rrset_trust(msg, pset); 390 return 1; 391 } 392 393 /** 394 * Copy and decompress rrs 395 * @param pkt: the packet for compression pointer resolution. 396 * @param msg: the parsed message 397 * @param rep: reply info to put rrs into. 398 * @param region: if not NULL, used for allocation. 399 * @return 0 on failure. 400 */ 401 static int 402 parse_copy_decompress(sldns_buffer* pkt, struct msg_parse* msg, 403 struct reply_info* rep, struct regional* region) 404 { 405 size_t i; 406 struct rrset_parse *pset = msg->rrset_first; 407 struct packed_rrset_data* data; 408 log_assert(rep); 409 rep->ttl = MAX_TTL; 410 rep->security = sec_status_unchecked; 411 if(rep->rrset_count == 0) 412 rep->ttl = NORR_TTL; 413 414 for(i=0; i<rep->rrset_count; i++) { 415 if(!parse_copy_decompress_rrset(pkt, msg, pset, region, 416 rep->rrsets[i])) 417 return 0; 418 data = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; 419 if(data->ttl < rep->ttl) 420 rep->ttl = data->ttl; 421 422 pset = pset->rrset_all_next; 423 } 424 rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl); 425 return 1; 426 } 427 428 int 429 parse_create_msg(sldns_buffer* pkt, struct msg_parse* msg, 430 struct alloc_cache* alloc, struct query_info* qinf, 431 struct reply_info** rep, struct regional* region) 432 { 433 log_assert(pkt && msg); 434 if(!parse_create_qinfo(pkt, msg, qinf, region)) 435 return 0; 436 if(!parse_create_repinfo(msg, rep, region)) 437 return 0; 438 if(!repinfo_alloc_rrset_keys(*rep, alloc, region)) 439 return 0; 440 if(!parse_copy_decompress(pkt, msg, *rep, region)) 441 return 0; 442 return 1; 443 } 444 445 int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc, 446 struct query_info* qinf, struct reply_info** rep, 447 struct regional* region, struct edns_data* edns) 448 { 449 /* use scratch pad region-allocator during parsing. */ 450 struct msg_parse* msg; 451 int ret; 452 453 qinf->qname = NULL; 454 *rep = NULL; 455 if(!(msg = regional_alloc(region, sizeof(*msg)))) { 456 return LDNS_RCODE_SERVFAIL; 457 } 458 memset(msg, 0, sizeof(*msg)); 459 460 sldns_buffer_set_position(pkt, 0); 461 if((ret = parse_packet(pkt, msg, region)) != 0) { 462 return ret; 463 } 464 if((ret = parse_extract_edns(msg, edns)) != 0) 465 return ret; 466 467 /* parse OK, allocate return structures */ 468 /* this also performs dname decompression */ 469 if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) { 470 query_info_clear(qinf); 471 reply_info_parsedelete(*rep, alloc); 472 *rep = NULL; 473 return LDNS_RCODE_SERVFAIL; 474 } 475 return 0; 476 } 477 478 /** helper compare function to sort in lock order */ 479 static int 480 reply_info_sortref_cmp(const void* a, const void* b) 481 { 482 struct rrset_ref* x = (struct rrset_ref*)a; 483 struct rrset_ref* y = (struct rrset_ref*)b; 484 if(x->key < y->key) return -1; 485 if(x->key > y->key) return 1; 486 return 0; 487 } 488 489 void 490 reply_info_sortref(struct reply_info* rep) 491 { 492 qsort(&rep->ref[0], rep->rrset_count, sizeof(struct rrset_ref), 493 reply_info_sortref_cmp); 494 } 495 496 void 497 reply_info_set_ttls(struct reply_info* rep, time_t timenow) 498 { 499 size_t i, j; 500 rep->ttl += timenow; 501 rep->prefetch_ttl += timenow; 502 for(i=0; i<rep->rrset_count; i++) { 503 struct packed_rrset_data* data = (struct packed_rrset_data*) 504 rep->ref[i].key->entry.data; 505 if(i>0 && rep->ref[i].key == rep->ref[i-1].key) 506 continue; 507 data->ttl += timenow; 508 for(j=0; j<data->count + data->rrsig_count; j++) { 509 data->rr_ttl[j] += timenow; 510 } 511 } 512 } 513 514 void 515 reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc) 516 { 517 size_t i; 518 if(!rep) 519 return; 520 /* no need to lock, since not shared in hashtables. */ 521 for(i=0; i<rep->rrset_count; i++) { 522 ub_packed_rrset_parsedelete(rep->rrsets[i], alloc); 523 } 524 free(rep); 525 } 526 527 int 528 query_info_parse(struct query_info* m, sldns_buffer* query) 529 { 530 uint8_t* q = sldns_buffer_begin(query); 531 /* minimum size: header + \0 + qtype + qclass */ 532 if(sldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5) 533 return 0; 534 if(LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY || 535 LDNS_QDCOUNT(q) != 1 || sldns_buffer_position(query) != 0) 536 return 0; 537 sldns_buffer_skip(query, LDNS_HEADER_SIZE); 538 m->qname = sldns_buffer_current(query); 539 if((m->qname_len = query_dname_len(query)) == 0) 540 return 0; /* parse error */ 541 if(sldns_buffer_remaining(query) < 4) 542 return 0; /* need qtype, qclass */ 543 m->qtype = sldns_buffer_read_u16(query); 544 m->qclass = sldns_buffer_read_u16(query); 545 return 1; 546 } 547 548 /** tiny subroutine for msgreply_compare */ 549 #define COMPARE_IT(x, y) \ 550 if( (x) < (y) ) return -1; \ 551 else if( (x) > (y) ) return +1; \ 552 log_assert( (x) == (y) ); 553 554 int 555 query_info_compare(void* m1, void* m2) 556 { 557 struct query_info* msg1 = (struct query_info*)m1; 558 struct query_info* msg2 = (struct query_info*)m2; 559 int mc; 560 /* from most different to least different for speed */ 561 COMPARE_IT(msg1->qtype, msg2->qtype); 562 if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0) 563 return mc; 564 log_assert(msg1->qname_len == msg2->qname_len); 565 COMPARE_IT(msg1->qclass, msg2->qclass); 566 return 0; 567 #undef COMPARE_IT 568 } 569 570 void 571 query_info_clear(struct query_info* m) 572 { 573 free(m->qname); 574 m->qname = NULL; 575 } 576 577 size_t 578 msgreply_sizefunc(void* k, void* d) 579 { 580 struct msgreply_entry* q = (struct msgreply_entry*)k; 581 struct reply_info* r = (struct reply_info*)d; 582 size_t s = sizeof(struct msgreply_entry) + sizeof(struct reply_info) 583 + q->key.qname_len + lock_get_mem(&q->entry.lock) 584 - sizeof(struct rrset_ref); 585 s += r->rrset_count * sizeof(struct rrset_ref); 586 s += r->rrset_count * sizeof(struct ub_packed_rrset_key*); 587 return s; 588 } 589 590 void 591 query_entry_delete(void *k, void* ATTR_UNUSED(arg)) 592 { 593 struct msgreply_entry* q = (struct msgreply_entry*)k; 594 lock_rw_destroy(&q->entry.lock); 595 query_info_clear(&q->key); 596 free(q); 597 } 598 599 void 600 reply_info_delete(void* d, void* ATTR_UNUSED(arg)) 601 { 602 struct reply_info* r = (struct reply_info*)d; 603 free(r); 604 } 605 606 hashvalue_t 607 query_info_hash(struct query_info *q, uint16_t flags) 608 { 609 hashvalue_t h = 0xab; 610 h = hashlittle(&q->qtype, sizeof(q->qtype), h); 611 if(q->qtype == LDNS_RR_TYPE_AAAA && (flags&BIT_CD)) 612 h++; 613 h = hashlittle(&q->qclass, sizeof(q->qclass), h); 614 h = dname_query_hash(q->qname, h); 615 return h; 616 } 617 618 struct msgreply_entry* 619 query_info_entrysetup(struct query_info* q, struct reply_info* r, 620 hashvalue_t h) 621 { 622 struct msgreply_entry* e = (struct msgreply_entry*)malloc( 623 sizeof(struct msgreply_entry)); 624 if(!e) return NULL; 625 memcpy(&e->key, q, sizeof(*q)); 626 e->entry.hash = h; 627 e->entry.key = e; 628 e->entry.data = r; 629 lock_rw_init(&e->entry.lock); 630 lock_protect(&e->entry.lock, &e->key, sizeof(e->key)); 631 lock_protect(&e->entry.lock, &e->entry.hash, sizeof(e->entry.hash) + 632 sizeof(e->entry.key) + sizeof(e->entry.data)); 633 lock_protect(&e->entry.lock, e->key.qname, e->key.qname_len); 634 q->qname = NULL; 635 return e; 636 } 637 638 /** copy rrsets from replyinfo to dest replyinfo */ 639 static int 640 repinfo_copy_rrsets(struct reply_info* dest, struct reply_info* from, 641 struct regional* region) 642 { 643 size_t i, s; 644 struct packed_rrset_data* fd, *dd; 645 struct ub_packed_rrset_key* fk, *dk; 646 for(i=0; i<dest->rrset_count; i++) { 647 fk = from->rrsets[i]; 648 dk = dest->rrsets[i]; 649 fd = (struct packed_rrset_data*)fk->entry.data; 650 dk->entry.hash = fk->entry.hash; 651 dk->rk = fk->rk; 652 if(region) { 653 dk->id = fk->id; 654 dk->rk.dname = (uint8_t*)regional_alloc_init(region, 655 fk->rk.dname, fk->rk.dname_len); 656 } else 657 dk->rk.dname = (uint8_t*)memdup(fk->rk.dname, 658 fk->rk.dname_len); 659 if(!dk->rk.dname) 660 return 0; 661 s = packed_rrset_sizeof(fd); 662 if(region) 663 dd = (struct packed_rrset_data*)regional_alloc_init( 664 region, fd, s); 665 else dd = (struct packed_rrset_data*)memdup(fd, s); 666 if(!dd) 667 return 0; 668 packed_rrset_ptr_fixup(dd); 669 dk->entry.data = (void*)dd; 670 } 671 return 1; 672 } 673 674 struct reply_info* 675 reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc, 676 struct regional* region) 677 { 678 struct reply_info* cp; 679 cp = construct_reply_info_base(region, rep->flags, rep->qdcount, 680 rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, 681 rep->ns_numrrsets, rep->ar_numrrsets, rep->rrset_count, 682 rep->security); 683 if(!cp) 684 return NULL; 685 /* allocate ub_key structures special or not */ 686 if(!repinfo_alloc_rrset_keys(cp, alloc, region)) { 687 if(!region) 688 reply_info_parsedelete(cp, alloc); 689 return NULL; 690 } 691 if(!repinfo_copy_rrsets(cp, rep, region)) { 692 if(!region) 693 reply_info_parsedelete(cp, alloc); 694 return NULL; 695 } 696 return cp; 697 } 698 699 uint8_t* 700 reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep) 701 { 702 uint8_t* sname = qinfo->qname; 703 size_t snamelen = qinfo->qname_len; 704 size_t i; 705 for(i=0; i<rep->an_numrrsets; i++) { 706 struct ub_packed_rrset_key* s = rep->rrsets[i]; 707 /* follow CNAME chain (if any) */ 708 if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 709 ntohs(s->rk.rrset_class) == qinfo->qclass && 710 snamelen == s->rk.dname_len && 711 query_dname_compare(sname, s->rk.dname) == 0) { 712 get_cname_target(s, &sname, &snamelen); 713 } 714 } 715 if(sname != qinfo->qname) 716 return sname; 717 return NULL; 718 } 719 720 struct ub_packed_rrset_key* 721 reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep) 722 { 723 uint8_t* sname = qinfo->qname; 724 size_t snamelen = qinfo->qname_len; 725 size_t i; 726 for(i=0; i<rep->an_numrrsets; i++) { 727 struct ub_packed_rrset_key* s = rep->rrsets[i]; 728 /* first match type, for query of qtype cname */ 729 if(ntohs(s->rk.type) == qinfo->qtype && 730 ntohs(s->rk.rrset_class) == qinfo->qclass && 731 snamelen == s->rk.dname_len && 732 query_dname_compare(sname, s->rk.dname) == 0) { 733 return s; 734 } 735 /* follow CNAME chain (if any) */ 736 if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 737 ntohs(s->rk.rrset_class) == qinfo->qclass && 738 snamelen == s->rk.dname_len && 739 query_dname_compare(sname, s->rk.dname) == 0) { 740 get_cname_target(s, &sname, &snamelen); 741 } 742 } 743 return NULL; 744 } 745 746 struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, 747 uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) 748 { 749 size_t i; 750 for(i=0; i<rep->an_numrrsets; i++) { 751 struct ub_packed_rrset_key* s = rep->rrsets[i]; 752 if(ntohs(s->rk.type) == type && 753 ntohs(s->rk.rrset_class) == dclass && 754 namelen == s->rk.dname_len && 755 query_dname_compare(name, s->rk.dname) == 0) { 756 return s; 757 } 758 } 759 return NULL; 760 } 761 762 struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, 763 uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) 764 { 765 size_t i; 766 for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) { 767 struct ub_packed_rrset_key* s = rep->rrsets[i]; 768 if(ntohs(s->rk.type) == type && 769 ntohs(s->rk.rrset_class) == dclass && 770 namelen == s->rk.dname_len && 771 query_dname_compare(name, s->rk.dname) == 0) { 772 return s; 773 } 774 } 775 return NULL; 776 } 777 778 struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, 779 uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) 780 { 781 size_t i; 782 for(i=0; i<rep->rrset_count; i++) { 783 struct ub_packed_rrset_key* s = rep->rrsets[i]; 784 if(ntohs(s->rk.type) == type && 785 ntohs(s->rk.rrset_class) == dclass && 786 namelen == s->rk.dname_len && 787 query_dname_compare(name, s->rk.dname) == 0) { 788 return s; 789 } 790 } 791 return NULL; 792 } 793 794 void 795 log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep) 796 { 797 /* not particularly fast but flexible, make wireformat and print */ 798 sldns_buffer* buf = sldns_buffer_new(65535); 799 struct regional* region = regional_create(); 800 if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, 801 region, 65535, 1)) { 802 log_info("%s: log_dns_msg: out of memory", str); 803 } else { 804 char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf), 805 sldns_buffer_limit(buf)); 806 if(!s) { 807 log_info("%s: log_dns_msg: ldns tostr failed", str); 808 } else { 809 log_info("%s %s", str, s); 810 } 811 free(s); 812 } 813 sldns_buffer_free(buf); 814 regional_destroy(region); 815 } 816 817 void 818 log_query_info(enum verbosity_value v, const char* str, 819 struct query_info* qinf) 820 { 821 log_nametypeclass(v, str, qinf->qname, qinf->qtype, qinf->qclass); 822 } 823 824 int 825 reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep) 826 { 827 /* check only answer section rrs for matching cname chain. 828 * the cache may return changed rdata, but owner names are untouched.*/ 829 size_t i; 830 uint8_t* sname = qinfo->qname; 831 size_t snamelen = qinfo->qname_len; 832 for(i=0; i<rep->an_numrrsets; i++) { 833 uint16_t t = ntohs(rep->rrsets[i]->rk.type); 834 if(t == LDNS_RR_TYPE_DNAME) 835 continue; /* skip dnames; note TTL 0 not cached */ 836 /* verify that owner matches current sname */ 837 if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){ 838 /* cname chain broken */ 839 return 0; 840 } 841 /* if this is a cname; move on */ 842 if(t == LDNS_RR_TYPE_CNAME) { 843 get_cname_target(rep->rrsets[i], &sname, &snamelen); 844 } 845 } 846 return 1; 847 } 848 849 int 850 reply_all_rrsets_secure(struct reply_info* rep) 851 { 852 size_t i; 853 for(i=0; i<rep->rrset_count; i++) { 854 if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) 855 ->security != sec_status_secure ) 856 return 0; 857 } 858 return 1; 859 } 860