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