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