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 #include "util/module.h" 56 #include "util/fptr_wlist.h" 57 58 /** MAX TTL default for messages and rrsets */ 59 time_t MAX_TTL = 3600 * 24 * 10; /* ten days */ 60 /** MIN TTL default for messages and rrsets */ 61 time_t MIN_TTL = 0; 62 /** MAX Negative TTL, for SOA records in authority section */ 63 time_t MAX_NEG_TTL = 3600; /* one hour */ 64 65 /** allocate qinfo, return 0 on error */ 66 static int 67 parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg, 68 struct query_info* qinf, struct regional* region) 69 { 70 if(msg->qname) { 71 if(region) 72 qinf->qname = (uint8_t*)regional_alloc(region, 73 msg->qname_len); 74 else qinf->qname = (uint8_t*)malloc(msg->qname_len); 75 if(!qinf->qname) return 0; 76 dname_pkt_copy(pkt, qinf->qname, msg->qname); 77 } else qinf->qname = 0; 78 qinf->qname_len = msg->qname_len; 79 qinf->qtype = msg->qtype; 80 qinf->qclass = msg->qclass; 81 qinf->local_alias = NULL; 82 return 1; 83 } 84 85 /** constructor for replyinfo */ 86 struct reply_info* 87 construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, 88 time_t ttl, time_t prettl, size_t an, size_t ns, size_t ar, 89 size_t total, enum sec_status sec) 90 { 91 struct reply_info* rep; 92 /* rrset_count-1 because the first ref is part of the struct. */ 93 size_t s = sizeof(struct reply_info) - sizeof(struct rrset_ref) + 94 sizeof(struct ub_packed_rrset_key*) * total; 95 if(total >= RR_COUNT_MAX) return NULL; /* sanity check on numRRS*/ 96 if(region) 97 rep = (struct reply_info*)regional_alloc(region, s); 98 else rep = (struct reply_info*)malloc(s + 99 sizeof(struct rrset_ref) * (total)); 100 if(!rep) 101 return NULL; 102 rep->flags = flags; 103 rep->qdcount = qd; 104 rep->ttl = ttl; 105 rep->prefetch_ttl = prettl; 106 rep->an_numrrsets = an; 107 rep->ns_numrrsets = ns; 108 rep->ar_numrrsets = ar; 109 rep->rrset_count = total; 110 rep->security = sec; 111 rep->authoritative = 0; 112 /* array starts after the refs */ 113 if(region) 114 rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[0]); 115 else rep->rrsets = (struct ub_packed_rrset_key**)&(rep->ref[total]); 116 /* zero the arrays to assist cleanup in case of malloc failure */ 117 memset( rep->rrsets, 0, sizeof(struct ub_packed_rrset_key*) * total); 118 if(!region) 119 memset( &rep->ref[0], 0, sizeof(struct rrset_ref) * total); 120 return rep; 121 } 122 123 /** allocate replyinfo, return 0 on error */ 124 static int 125 parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep, 126 struct regional* region) 127 { 128 *rep = construct_reply_info_base(region, msg->flags, msg->qdcount, 0, 129 0, msg->an_rrsets, msg->ns_rrsets, msg->ar_rrsets, 130 msg->rrset_count, sec_status_unchecked); 131 if(!*rep) 132 return 0; 133 return 1; 134 } 135 136 int 137 reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, 138 struct regional* region) 139 { 140 size_t i; 141 for(i=0; i<rep->rrset_count; i++) { 142 if(region) { 143 rep->rrsets[i] = (struct ub_packed_rrset_key*) 144 regional_alloc(region, 145 sizeof(struct ub_packed_rrset_key)); 146 if(rep->rrsets[i]) { 147 memset(rep->rrsets[i], 0, 148 sizeof(struct ub_packed_rrset_key)); 149 rep->rrsets[i]->entry.key = rep->rrsets[i]; 150 } 151 } 152 else rep->rrsets[i] = alloc_special_obtain(alloc); 153 if(!rep->rrsets[i]) 154 return 0; 155 rep->rrsets[i]->entry.data = NULL; 156 } 157 return 1; 158 } 159 160 /** find the minimumttl in the rdata of SOA record */ 161 static time_t 162 soa_find_minttl(struct rr_parse* rr) 163 { 164 uint16_t rlen = sldns_read_uint16(rr->ttl_data+4); 165 if(rlen < 20) 166 return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */ 167 /* minimum TTL is the last 32bit value in the rdata of the record */ 168 /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/ 169 return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4); 170 } 171 172 /** do the rdata copy */ 173 static int 174 rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, 175 struct rr_parse* rr, time_t* rr_ttl, uint16_t type, 176 sldns_pkt_section section) 177 { 178 uint16_t pkt_len; 179 const sldns_rr_descriptor* desc; 180 181 *rr_ttl = sldns_read_uint32(rr->ttl_data); 182 /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ 183 if(*rr_ttl & 0x80000000U) 184 *rr_ttl = 0; 185 if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) { 186 /* negative response. see if TTL of SOA record larger than the 187 * minimum-ttl in the rdata of the SOA record */ 188 if(*rr_ttl > soa_find_minttl(rr)) 189 *rr_ttl = soa_find_minttl(rr); 190 if(*rr_ttl > MAX_NEG_TTL) 191 *rr_ttl = MAX_NEG_TTL; 192 } 193 if(*rr_ttl < MIN_TTL) 194 *rr_ttl = MIN_TTL; 195 if(*rr_ttl < data->ttl) 196 data->ttl = *rr_ttl; 197 198 if(rr->outside_packet) { 199 /* uncompressed already, only needs copy */ 200 memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size); 201 return 1; 202 } 203 204 sldns_buffer_set_position(pkt, (size_t) 205 (rr->ttl_data - sldns_buffer_begin(pkt) + sizeof(uint32_t))); 206 /* insert decompressed size into rdata len stored in memory */ 207 /* -2 because rdatalen bytes are not included. */ 208 pkt_len = htons(rr->size - 2); 209 memmove(to, &pkt_len, sizeof(uint16_t)); 210 to += 2; 211 /* read packet rdata len */ 212 pkt_len = sldns_buffer_read_u16(pkt); 213 if(sldns_buffer_remaining(pkt) < pkt_len) 214 return 0; 215 desc = sldns_rr_descript(type); 216 if(pkt_len > 0 && desc && desc->_dname_count > 0) { 217 int count = (int)desc->_dname_count; 218 int rdf = 0; 219 size_t len; 220 size_t oldpos; 221 /* decompress dnames. */ 222 while(pkt_len > 0 && count) { 223 switch(desc->_wireformat[rdf]) { 224 case LDNS_RDF_TYPE_DNAME: 225 oldpos = sldns_buffer_position(pkt); 226 dname_pkt_copy(pkt, to, 227 sldns_buffer_current(pkt)); 228 to += pkt_dname_len(pkt); 229 pkt_len -= sldns_buffer_position(pkt)-oldpos; 230 count--; 231 len = 0; 232 break; 233 case LDNS_RDF_TYPE_STR: 234 len = sldns_buffer_current(pkt)[0] + 1; 235 break; 236 default: 237 len = get_rdf_size(desc->_wireformat[rdf]); 238 break; 239 } 240 if(len) { 241 memmove(to, sldns_buffer_current(pkt), len); 242 to += len; 243 sldns_buffer_skip(pkt, (ssize_t)len); 244 log_assert(len <= pkt_len); 245 pkt_len -= len; 246 } 247 rdf++; 248 } 249 } 250 /* copy remaining rdata */ 251 if(pkt_len > 0) 252 memmove(to, sldns_buffer_current(pkt), pkt_len); 253 254 return 1; 255 } 256 257 /** copy over the data into packed rrset */ 258 static int 259 parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset, 260 struct packed_rrset_data* data) 261 { 262 size_t i; 263 struct rr_parse* rr = pset->rr_first; 264 uint8_t* nextrdata; 265 size_t total = pset->rr_count + pset->rrsig_count; 266 data->ttl = MAX_TTL; 267 data->count = pset->rr_count; 268 data->rrsig_count = pset->rrsig_count; 269 data->trust = rrset_trust_none; 270 data->security = sec_status_unchecked; 271 /* layout: struct - rr_len - rr_data - rr_ttl - rdata - rrsig */ 272 data->rr_len = (size_t*)((uint8_t*)data + 273 sizeof(struct packed_rrset_data)); 274 data->rr_data = (uint8_t**)&(data->rr_len[total]); 275 data->rr_ttl = (time_t*)&(data->rr_data[total]); 276 nextrdata = (uint8_t*)&(data->rr_ttl[total]); 277 for(i=0; i<data->count; i++) { 278 data->rr_len[i] = rr->size; 279 data->rr_data[i] = nextrdata; 280 nextrdata += rr->size; 281 if(!rdata_copy(pkt, data, data->rr_data[i], rr, 282 &data->rr_ttl[i], pset->type, pset->section)) 283 return 0; 284 rr = rr->next; 285 } 286 /* if rrsig, its rdata is at nextrdata */ 287 rr = pset->rrsig_first; 288 for(i=data->count; i<total; i++) { 289 data->rr_len[i] = rr->size; 290 data->rr_data[i] = nextrdata; 291 nextrdata += rr->size; 292 if(!rdata_copy(pkt, data, data->rr_data[i], rr, 293 &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG, pset->section)) 294 return 0; 295 rr = rr->next; 296 } 297 return 1; 298 } 299 300 /** create rrset return 0 on failure */ 301 static int 302 parse_create_rrset(sldns_buffer* pkt, struct rrset_parse* pset, 303 struct packed_rrset_data** data, struct regional* region) 304 { 305 /* allocate */ 306 size_t s; 307 if(pset->rr_count > RR_COUNT_MAX || pset->rrsig_count > RR_COUNT_MAX || 308 pset->size > RR_COUNT_MAX) 309 return 0; /* protect against integer overflow */ 310 s = sizeof(struct packed_rrset_data) + 311 (pset->rr_count + pset->rrsig_count) * 312 (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)) + 313 pset->size; 314 if(region) 315 *data = regional_alloc(region, s); 316 else *data = malloc(s); 317 if(!*data) 318 return 0; 319 /* copy & decompress */ 320 if(!parse_rr_copy(pkt, pset, *data)) { 321 if(!region) free(*data); 322 return 0; 323 } 324 return 1; 325 } 326 327 /** get trust value for rrset */ 328 static enum rrset_trust 329 get_rrset_trust(struct msg_parse* msg, struct rrset_parse* rrset) 330 { 331 uint16_t AA = msg->flags & BIT_AA; 332 if(rrset->section == LDNS_SECTION_ANSWER) { 333 if(AA) { 334 /* RFC2181 says remainder of CNAME chain is nonauth*/ 335 if(msg->rrset_first && 336 msg->rrset_first->section==LDNS_SECTION_ANSWER 337 && msg->rrset_first->type==LDNS_RR_TYPE_CNAME){ 338 if(rrset == msg->rrset_first) 339 return rrset_trust_ans_AA; 340 else return rrset_trust_ans_noAA; 341 } 342 if(msg->rrset_first && 343 msg->rrset_first->section==LDNS_SECTION_ANSWER 344 && msg->rrset_first->type==LDNS_RR_TYPE_DNAME){ 345 if(rrset == msg->rrset_first || 346 rrset == msg->rrset_first->rrset_all_next) 347 return rrset_trust_ans_AA; 348 else return rrset_trust_ans_noAA; 349 } 350 return rrset_trust_ans_AA; 351 } 352 else return rrset_trust_ans_noAA; 353 } else if(rrset->section == LDNS_SECTION_AUTHORITY) { 354 if(AA) return rrset_trust_auth_AA; 355 else return rrset_trust_auth_noAA; 356 } else { 357 /* addit section */ 358 if(AA) return rrset_trust_add_AA; 359 else return rrset_trust_add_noAA; 360 } 361 /* NOTREACHED */ 362 return rrset_trust_none; 363 } 364 365 int 366 parse_copy_decompress_rrset(sldns_buffer* pkt, struct msg_parse* msg, 367 struct rrset_parse *pset, struct regional* region, 368 struct ub_packed_rrset_key* pk) 369 { 370 struct packed_rrset_data* data; 371 pk->rk.flags = pset->flags; 372 pk->rk.dname_len = pset->dname_len; 373 if(region) 374 pk->rk.dname = (uint8_t*)regional_alloc( 375 region, pset->dname_len); 376 else pk->rk.dname = 377 (uint8_t*)malloc(pset->dname_len); 378 if(!pk->rk.dname) 379 return 0; 380 /** copy & decompress dname */ 381 dname_pkt_copy(pkt, pk->rk.dname, pset->dname); 382 /** copy over type and class */ 383 pk->rk.type = htons(pset->type); 384 pk->rk.rrset_class = pset->rrset_class; 385 /** read data part. */ 386 if(!parse_create_rrset(pkt, pset, &data, region)) 387 return 0; 388 pk->entry.data = (void*)data; 389 pk->entry.key = (void*)pk; 390 pk->entry.hash = pset->hash; 391 data->trust = get_rrset_trust(msg, pset); 392 return 1; 393 } 394 395 /** 396 * Copy and decompress rrs 397 * @param pkt: the packet for compression pointer resolution. 398 * @param msg: the parsed message 399 * @param rep: reply info to put rrs into. 400 * @param region: if not NULL, used for allocation. 401 * @return 0 on failure. 402 */ 403 static int 404 parse_copy_decompress(sldns_buffer* pkt, struct msg_parse* msg, 405 struct reply_info* rep, struct regional* region) 406 { 407 size_t i; 408 struct rrset_parse *pset = msg->rrset_first; 409 struct packed_rrset_data* data; 410 log_assert(rep); 411 rep->ttl = MAX_TTL; 412 rep->security = sec_status_unchecked; 413 if(rep->rrset_count == 0) 414 rep->ttl = NORR_TTL; 415 416 for(i=0; i<rep->rrset_count; i++) { 417 if(!parse_copy_decompress_rrset(pkt, msg, pset, region, 418 rep->rrsets[i])) 419 return 0; 420 data = (struct packed_rrset_data*)rep->rrsets[i]->entry.data; 421 if(data->ttl < rep->ttl) 422 rep->ttl = data->ttl; 423 424 pset = pset->rrset_all_next; 425 } 426 rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl); 427 return 1; 428 } 429 430 int 431 parse_create_msg(sldns_buffer* pkt, struct msg_parse* msg, 432 struct alloc_cache* alloc, struct query_info* qinf, 433 struct reply_info** rep, struct regional* region) 434 { 435 log_assert(pkt && msg); 436 if(!parse_create_qinfo(pkt, msg, qinf, region)) 437 return 0; 438 if(!parse_create_repinfo(msg, rep, region)) 439 return 0; 440 if(!reply_info_alloc_rrset_keys(*rep, alloc, region)) 441 return 0; 442 if(!parse_copy_decompress(pkt, msg, *rep, region)) 443 return 0; 444 return 1; 445 } 446 447 int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc, 448 struct query_info* qinf, struct reply_info** rep, 449 struct regional* region, struct edns_data* edns) 450 { 451 /* use scratch pad region-allocator during parsing. */ 452 struct msg_parse* msg; 453 int ret; 454 455 qinf->qname = NULL; 456 qinf->local_alias = NULL; 457 *rep = NULL; 458 if(!(msg = regional_alloc(region, sizeof(*msg)))) { 459 return LDNS_RCODE_SERVFAIL; 460 } 461 memset(msg, 0, sizeof(*msg)); 462 463 sldns_buffer_set_position(pkt, 0); 464 if((ret = parse_packet(pkt, msg, region)) != 0) { 465 return ret; 466 } 467 if((ret = parse_extract_edns(msg, edns, region)) != 0) 468 return ret; 469 470 /* parse OK, allocate return structures */ 471 /* this also performs dname decompression */ 472 if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) { 473 query_info_clear(qinf); 474 reply_info_parsedelete(*rep, alloc); 475 *rep = NULL; 476 return LDNS_RCODE_SERVFAIL; 477 } 478 return 0; 479 } 480 481 /** helper compare function to sort in lock order */ 482 static int 483 reply_info_sortref_cmp(const void* a, const void* b) 484 { 485 struct rrset_ref* x = (struct rrset_ref*)a; 486 struct rrset_ref* y = (struct rrset_ref*)b; 487 if(x->key < y->key) return -1; 488 if(x->key > y->key) return 1; 489 return 0; 490 } 491 492 void 493 reply_info_sortref(struct reply_info* rep) 494 { 495 qsort(&rep->ref[0], rep->rrset_count, sizeof(struct rrset_ref), 496 reply_info_sortref_cmp); 497 } 498 499 void 500 reply_info_set_ttls(struct reply_info* rep, time_t timenow) 501 { 502 size_t i, j; 503 rep->ttl += timenow; 504 rep->prefetch_ttl += timenow; 505 for(i=0; i<rep->rrset_count; i++) { 506 struct packed_rrset_data* data = (struct packed_rrset_data*) 507 rep->ref[i].key->entry.data; 508 if(i>0 && rep->ref[i].key == rep->ref[i-1].key) 509 continue; 510 data->ttl += timenow; 511 for(j=0; j<data->count + data->rrsig_count; j++) { 512 data->rr_ttl[j] += timenow; 513 } 514 } 515 } 516 517 void 518 reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc) 519 { 520 size_t i; 521 if(!rep) 522 return; 523 /* no need to lock, since not shared in hashtables. */ 524 for(i=0; i<rep->rrset_count; i++) { 525 ub_packed_rrset_parsedelete(rep->rrsets[i], alloc); 526 } 527 free(rep); 528 } 529 530 int 531 query_info_parse(struct query_info* m, sldns_buffer* query) 532 { 533 uint8_t* q = sldns_buffer_begin(query); 534 /* minimum size: header + \0 + qtype + qclass */ 535 if(sldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5) 536 return 0; 537 if((LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY && LDNS_OPCODE_WIRE(q) != 538 LDNS_PACKET_NOTIFY) || LDNS_QDCOUNT(q) != 1 || 539 sldns_buffer_position(query) != 0) 540 return 0; 541 sldns_buffer_skip(query, LDNS_HEADER_SIZE); 542 m->qname = sldns_buffer_current(query); 543 if((m->qname_len = query_dname_len(query)) == 0) 544 return 0; /* parse error */ 545 if(sldns_buffer_remaining(query) < 4) 546 return 0; /* need qtype, qclass */ 547 m->qtype = sldns_buffer_read_u16(query); 548 m->qclass = sldns_buffer_read_u16(query); 549 m->local_alias = NULL; 550 return 1; 551 } 552 553 /** tiny subroutine for msgreply_compare */ 554 #define COMPARE_IT(x, y) \ 555 if( (x) < (y) ) return -1; \ 556 else if( (x) > (y) ) return +1; \ 557 log_assert( (x) == (y) ); 558 559 int 560 query_info_compare(void* m1, void* m2) 561 { 562 struct query_info* msg1 = (struct query_info*)m1; 563 struct query_info* msg2 = (struct query_info*)m2; 564 int mc; 565 /* from most different to least different for speed */ 566 COMPARE_IT(msg1->qtype, msg2->qtype); 567 if((mc = query_dname_compare(msg1->qname, msg2->qname)) != 0) 568 return mc; 569 log_assert(msg1->qname_len == msg2->qname_len); 570 COMPARE_IT(msg1->qclass, msg2->qclass); 571 return 0; 572 #undef COMPARE_IT 573 } 574 575 void 576 query_info_clear(struct query_info* m) 577 { 578 free(m->qname); 579 m->qname = NULL; 580 } 581 582 size_t 583 msgreply_sizefunc(void* k, void* d) 584 { 585 struct msgreply_entry* q = (struct msgreply_entry*)k; 586 struct reply_info* r = (struct reply_info*)d; 587 size_t s = sizeof(struct msgreply_entry) + sizeof(struct reply_info) 588 + q->key.qname_len + lock_get_mem(&q->entry.lock) 589 - sizeof(struct rrset_ref); 590 s += r->rrset_count * sizeof(struct rrset_ref); 591 s += r->rrset_count * sizeof(struct ub_packed_rrset_key*); 592 return s; 593 } 594 595 void 596 query_entry_delete(void *k, void* ATTR_UNUSED(arg)) 597 { 598 struct msgreply_entry* q = (struct msgreply_entry*)k; 599 lock_rw_destroy(&q->entry.lock); 600 query_info_clear(&q->key); 601 free(q); 602 } 603 604 void 605 reply_info_delete(void* d, void* ATTR_UNUSED(arg)) 606 { 607 struct reply_info* r = (struct reply_info*)d; 608 free(r); 609 } 610 611 hashvalue_type 612 query_info_hash(struct query_info *q, uint16_t flags) 613 { 614 hashvalue_type h = 0xab; 615 h = hashlittle(&q->qtype, sizeof(q->qtype), h); 616 if(q->qtype == LDNS_RR_TYPE_AAAA && (flags&BIT_CD)) 617 h++; 618 h = hashlittle(&q->qclass, sizeof(q->qclass), h); 619 h = dname_query_hash(q->qname, h); 620 return h; 621 } 622 623 struct msgreply_entry* 624 query_info_entrysetup(struct query_info* q, struct reply_info* r, 625 hashvalue_type h) 626 { 627 struct msgreply_entry* e = (struct msgreply_entry*)malloc( 628 sizeof(struct msgreply_entry)); 629 if(!e) return NULL; 630 memcpy(&e->key, q, sizeof(*q)); 631 e->entry.hash = h; 632 e->entry.key = e; 633 e->entry.data = r; 634 lock_rw_init(&e->entry.lock); 635 lock_protect(&e->entry.lock, &e->key.qname, sizeof(e->key.qname)); 636 lock_protect(&e->entry.lock, &e->key.qname_len, sizeof(e->key.qname_len)); 637 lock_protect(&e->entry.lock, &e->key.qtype, sizeof(e->key.qtype)); 638 lock_protect(&e->entry.lock, &e->key.qclass, sizeof(e->key.qclass)); 639 lock_protect(&e->entry.lock, &e->key.local_alias, sizeof(e->key.local_alias)); 640 lock_protect(&e->entry.lock, &e->entry.hash, sizeof(e->entry.hash)); 641 lock_protect(&e->entry.lock, &e->entry.key, sizeof(e->entry.key)); 642 lock_protect(&e->entry.lock, &e->entry.data, sizeof(e->entry.data)); 643 lock_protect(&e->entry.lock, e->key.qname, e->key.qname_len); 644 q->qname = NULL; 645 return e; 646 } 647 648 /** copy rrsets from replyinfo to dest replyinfo */ 649 static int 650 repinfo_copy_rrsets(struct reply_info* dest, struct reply_info* from, 651 struct regional* region) 652 { 653 size_t i, s; 654 struct packed_rrset_data* fd, *dd; 655 struct ub_packed_rrset_key* fk, *dk; 656 for(i=0; i<dest->rrset_count; i++) { 657 fk = from->rrsets[i]; 658 dk = dest->rrsets[i]; 659 fd = (struct packed_rrset_data*)fk->entry.data; 660 dk->entry.hash = fk->entry.hash; 661 dk->rk = fk->rk; 662 if(region) { 663 dk->id = fk->id; 664 dk->rk.dname = (uint8_t*)regional_alloc_init(region, 665 fk->rk.dname, fk->rk.dname_len); 666 } else 667 dk->rk.dname = (uint8_t*)memdup(fk->rk.dname, 668 fk->rk.dname_len); 669 if(!dk->rk.dname) 670 return 0; 671 s = packed_rrset_sizeof(fd); 672 if(region) 673 dd = (struct packed_rrset_data*)regional_alloc_init( 674 region, fd, s); 675 else dd = (struct packed_rrset_data*)memdup(fd, s); 676 if(!dd) 677 return 0; 678 packed_rrset_ptr_fixup(dd); 679 dk->entry.data = (void*)dd; 680 } 681 return 1; 682 } 683 684 struct reply_info* 685 reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc, 686 struct regional* region) 687 { 688 struct reply_info* cp; 689 cp = construct_reply_info_base(region, rep->flags, rep->qdcount, 690 rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, 691 rep->ns_numrrsets, rep->ar_numrrsets, rep->rrset_count, 692 rep->security); 693 if(!cp) 694 return NULL; 695 /* allocate ub_key structures special or not */ 696 if(!reply_info_alloc_rrset_keys(cp, alloc, region)) { 697 if(!region) 698 reply_info_parsedelete(cp, alloc); 699 return NULL; 700 } 701 if(!repinfo_copy_rrsets(cp, rep, region)) { 702 if(!region) 703 reply_info_parsedelete(cp, alloc); 704 return NULL; 705 } 706 return cp; 707 } 708 709 uint8_t* 710 reply_find_final_cname_target(struct query_info* qinfo, struct reply_info* rep) 711 { 712 uint8_t* sname = qinfo->qname; 713 size_t snamelen = qinfo->qname_len; 714 size_t i; 715 for(i=0; i<rep->an_numrrsets; i++) { 716 struct ub_packed_rrset_key* s = rep->rrsets[i]; 717 /* follow CNAME chain (if any) */ 718 if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 719 ntohs(s->rk.rrset_class) == qinfo->qclass && 720 snamelen == s->rk.dname_len && 721 query_dname_compare(sname, s->rk.dname) == 0) { 722 get_cname_target(s, &sname, &snamelen); 723 } 724 } 725 if(sname != qinfo->qname) 726 return sname; 727 return NULL; 728 } 729 730 struct ub_packed_rrset_key* 731 reply_find_answer_rrset(struct query_info* qinfo, struct reply_info* rep) 732 { 733 uint8_t* sname = qinfo->qname; 734 size_t snamelen = qinfo->qname_len; 735 size_t i; 736 for(i=0; i<rep->an_numrrsets; i++) { 737 struct ub_packed_rrset_key* s = rep->rrsets[i]; 738 /* first match type, for query of qtype cname */ 739 if(ntohs(s->rk.type) == qinfo->qtype && 740 ntohs(s->rk.rrset_class) == qinfo->qclass && 741 snamelen == s->rk.dname_len && 742 query_dname_compare(sname, s->rk.dname) == 0) { 743 return s; 744 } 745 /* follow CNAME chain (if any) */ 746 if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 747 ntohs(s->rk.rrset_class) == qinfo->qclass && 748 snamelen == s->rk.dname_len && 749 query_dname_compare(sname, s->rk.dname) == 0) { 750 get_cname_target(s, &sname, &snamelen); 751 } 752 } 753 return NULL; 754 } 755 756 struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep, 757 uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) 758 { 759 size_t i; 760 for(i=0; i<rep->an_numrrsets; i++) { 761 struct ub_packed_rrset_key* s = rep->rrsets[i]; 762 if(ntohs(s->rk.type) == type && 763 ntohs(s->rk.rrset_class) == dclass && 764 namelen == s->rk.dname_len && 765 query_dname_compare(name, s->rk.dname) == 0) { 766 return s; 767 } 768 } 769 return NULL; 770 } 771 772 struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep, 773 uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) 774 { 775 size_t i; 776 for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++) { 777 struct ub_packed_rrset_key* s = rep->rrsets[i]; 778 if(ntohs(s->rk.type) == type && 779 ntohs(s->rk.rrset_class) == dclass && 780 namelen == s->rk.dname_len && 781 query_dname_compare(name, s->rk.dname) == 0) { 782 return s; 783 } 784 } 785 return NULL; 786 } 787 788 struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep, 789 uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass) 790 { 791 size_t i; 792 for(i=0; i<rep->rrset_count; i++) { 793 struct ub_packed_rrset_key* s = rep->rrsets[i]; 794 if(ntohs(s->rk.type) == type && 795 ntohs(s->rk.rrset_class) == dclass && 796 namelen == s->rk.dname_len && 797 query_dname_compare(name, s->rk.dname) == 0) { 798 return s; 799 } 800 } 801 return NULL; 802 } 803 804 void 805 log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep) 806 { 807 /* not particularly fast but flexible, make wireformat and print */ 808 sldns_buffer* buf = sldns_buffer_new(65535); 809 struct regional* region = regional_create(); 810 if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, 811 region, 65535, 1)) { 812 log_info("%s: log_dns_msg: out of memory", str); 813 } else { 814 char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf), 815 sldns_buffer_limit(buf)); 816 if(!s) { 817 log_info("%s: log_dns_msg: ldns tostr failed", str); 818 } else { 819 log_info("%s %s", str, s); 820 } 821 free(s); 822 } 823 sldns_buffer_free(buf); 824 regional_destroy(region); 825 } 826 827 void 828 log_reply_info(enum verbosity_value v, struct query_info *qinf, 829 struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur, 830 int cached, struct sldns_buffer *rmsg) 831 { 832 char qname_buf[LDNS_MAX_DOMAINLEN+1]; 833 char clientip_buf[128]; 834 char rcode_buf[16]; 835 char type_buf[16]; 836 char class_buf[16]; 837 size_t pktlen; 838 uint16_t rcode = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(rmsg, 2)); 839 840 if(verbosity < v) 841 return; 842 843 sldns_wire2str_rcode_buf((int)rcode, rcode_buf, sizeof(rcode_buf)); 844 addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf)); 845 if(rcode == LDNS_RCODE_FORMERR) 846 { 847 log_info("%s - - - %s - - - ", clientip_buf, rcode_buf); 848 } else { 849 if(qinf->qname) 850 dname_str(qinf->qname, qname_buf); 851 else snprintf(qname_buf, sizeof(qname_buf), "null"); 852 pktlen = sldns_buffer_limit(rmsg); 853 sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf)); 854 sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf)); 855 log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d", 856 clientip_buf, qname_buf, type_buf, class_buf, 857 rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen); 858 } 859 } 860 861 void 862 log_query_info(enum verbosity_value v, const char* str, 863 struct query_info* qinf) 864 { 865 log_nametypeclass(v, str, qinf->qname, qinf->qtype, qinf->qclass); 866 } 867 868 int 869 reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep) 870 { 871 /* check only answer section rrs for matching cname chain. 872 * the cache may return changed rdata, but owner names are untouched.*/ 873 size_t i; 874 uint8_t* sname = qinfo->qname; 875 size_t snamelen = qinfo->qname_len; 876 for(i=0; i<rep->an_numrrsets; i++) { 877 uint16_t t = ntohs(rep->rrsets[i]->rk.type); 878 if(t == LDNS_RR_TYPE_DNAME) 879 continue; /* skip dnames; note TTL 0 not cached */ 880 /* verify that owner matches current sname */ 881 if(query_dname_compare(sname, rep->rrsets[i]->rk.dname) != 0){ 882 /* cname chain broken */ 883 return 0; 884 } 885 /* if this is a cname; move on */ 886 if(t == LDNS_RR_TYPE_CNAME) { 887 get_cname_target(rep->rrsets[i], &sname, &snamelen); 888 } 889 } 890 return 1; 891 } 892 893 int 894 reply_all_rrsets_secure(struct reply_info* rep) 895 { 896 size_t i; 897 for(i=0; i<rep->rrset_count; i++) { 898 if( ((struct packed_rrset_data*)rep->rrsets[i]->entry.data) 899 ->security != sec_status_secure ) 900 return 0; 901 } 902 return 1; 903 } 904 905 struct reply_info* 906 parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region, 907 struct query_info* qi) 908 { 909 struct reply_info* rep; 910 struct msg_parse* msg; 911 if(!(msg = regional_alloc(region, sizeof(*msg)))) { 912 return NULL; 913 } 914 memset(msg, 0, sizeof(*msg)); 915 sldns_buffer_set_position(pkt, 0); 916 if(parse_packet(pkt, msg, region) != 0) 917 return 0; 918 if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) { 919 return 0; 920 } 921 return rep; 922 } 923 924 int edns_opt_append(struct edns_data* edns, struct regional* region, 925 uint16_t code, size_t len, uint8_t* data) 926 { 927 struct edns_option** prevp; 928 struct edns_option* opt; 929 930 /* allocate new element */ 931 opt = (struct edns_option*)regional_alloc(region, sizeof(*opt)); 932 if(!opt) 933 return 0; 934 opt->next = NULL; 935 opt->opt_code = code; 936 opt->opt_len = len; 937 opt->opt_data = NULL; 938 if(len > 0) { 939 opt->opt_data = regional_alloc_init(region, data, len); 940 if(!opt->opt_data) 941 return 0; 942 } 943 944 /* append at end of list */ 945 prevp = &edns->opt_list; 946 while(*prevp != NULL) 947 prevp = &((*prevp)->next); 948 *prevp = opt; 949 return 1; 950 } 951 952 int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, 953 uint8_t* data, struct regional* region) 954 { 955 struct edns_option** prevp; 956 struct edns_option* opt; 957 958 /* allocate new element */ 959 opt = (struct edns_option*)regional_alloc(region, sizeof(*opt)); 960 if(!opt) 961 return 0; 962 opt->next = NULL; 963 opt->opt_code = code; 964 opt->opt_len = len; 965 opt->opt_data = NULL; 966 if(len > 0) { 967 opt->opt_data = regional_alloc_init(region, data, len); 968 if(!opt->opt_data) 969 return 0; 970 } 971 972 /* append at end of list */ 973 prevp = list; 974 while(*prevp != NULL) { 975 prevp = &((*prevp)->next); 976 } 977 *prevp = opt; 978 return 1; 979 } 980 981 int edns_opt_list_remove(struct edns_option** list, uint16_t code) 982 { 983 /* The list should already be allocated in a region. Freeing the 984 * allocated space in a region is not possible. We just unlink the 985 * required elements and they will be freed together with the region. */ 986 987 struct edns_option* prev; 988 struct edns_option* curr; 989 if(!list || !(*list)) return 0; 990 991 /* Unlink and repoint if the element(s) are first in list */ 992 while(list && *list && (*list)->opt_code == code) { 993 *list = (*list)->next; 994 } 995 996 if(!list || !(*list)) return 1; 997 /* Unlink elements and reattach the list */ 998 prev = *list; 999 curr = (*list)->next; 1000 while(curr != NULL) { 1001 if(curr->opt_code == code) { 1002 prev->next = curr->next; 1003 curr = curr->next; 1004 } else { 1005 prev = curr; 1006 curr = curr->next; 1007 } 1008 } 1009 return 1; 1010 } 1011 1012 static int inplace_cb_reply_call_generic( 1013 struct inplace_cb* callback_list, enum inplace_cb_list_type type, 1014 struct query_info* qinfo, struct module_qstate* qstate, 1015 struct reply_info* rep, int rcode, struct edns_data* edns, 1016 struct regional* region) 1017 { 1018 struct inplace_cb* cb; 1019 struct edns_option* opt_list_out = NULL; 1020 #if defined(EXPORT_ALL_SYMBOLS) 1021 (void)type; /* param not used when fptr_ok disabled */ 1022 #endif 1023 if(qstate) 1024 opt_list_out = qstate->edns_opts_front_out; 1025 for(cb=callback_list; cb; cb=cb->next) { 1026 fptr_ok(fptr_whitelist_inplace_cb_reply_generic( 1027 (inplace_cb_reply_func_type*)cb->cb, type)); 1028 (void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep, 1029 rcode, edns, &opt_list_out, region, cb->id, cb->cb_arg); 1030 } 1031 edns->opt_list = opt_list_out; 1032 return 1; 1033 } 1034 1035 int inplace_cb_reply_call(struct module_env* env, struct query_info* qinfo, 1036 struct module_qstate* qstate, struct reply_info* rep, int rcode, 1037 struct edns_data* edns, struct regional* region) 1038 { 1039 return inplace_cb_reply_call_generic( 1040 env->inplace_cb_lists[inplace_cb_reply], inplace_cb_reply, qinfo, 1041 qstate, rep, rcode, edns, region); 1042 } 1043 1044 int inplace_cb_reply_cache_call(struct module_env* env, 1045 struct query_info* qinfo, struct module_qstate* qstate, 1046 struct reply_info* rep, int rcode, struct edns_data* edns, 1047 struct regional* region) 1048 { 1049 return inplace_cb_reply_call_generic( 1050 env->inplace_cb_lists[inplace_cb_reply_cache], inplace_cb_reply_cache, 1051 qinfo, qstate, rep, rcode, edns, region); 1052 } 1053 1054 int inplace_cb_reply_local_call(struct module_env* env, 1055 struct query_info* qinfo, struct module_qstate* qstate, 1056 struct reply_info* rep, int rcode, struct edns_data* edns, 1057 struct regional* region) 1058 { 1059 return inplace_cb_reply_call_generic( 1060 env->inplace_cb_lists[inplace_cb_reply_local], inplace_cb_reply_local, 1061 qinfo, qstate, rep, rcode, edns, region); 1062 } 1063 1064 int inplace_cb_reply_servfail_call(struct module_env* env, 1065 struct query_info* qinfo, struct module_qstate* qstate, 1066 struct reply_info* rep, int rcode, struct edns_data* edns, 1067 struct regional* region) 1068 { 1069 /* We are going to servfail. Remove any potential edns options. */ 1070 if(qstate) 1071 qstate->edns_opts_front_out = NULL; 1072 return inplace_cb_reply_call_generic( 1073 env->inplace_cb_lists[inplace_cb_reply_servfail], 1074 inplace_cb_reply_servfail, qinfo, qstate, rep, rcode, edns, region); 1075 } 1076 1077 int inplace_cb_query_call(struct module_env* env, struct query_info* qinfo, 1078 uint16_t flags, struct sockaddr_storage* addr, socklen_t addrlen, 1079 uint8_t* zone, size_t zonelen, struct module_qstate* qstate, 1080 struct regional* region) 1081 { 1082 struct inplace_cb* cb = env->inplace_cb_lists[inplace_cb_query]; 1083 for(; cb; cb=cb->next) { 1084 fptr_ok(fptr_whitelist_inplace_cb_query( 1085 (inplace_cb_query_func_type*)cb->cb)); 1086 (void)(*(inplace_cb_query_func_type*)cb->cb)(qinfo, flags, 1087 qstate, addr, addrlen, zone, zonelen, region, 1088 cb->id, cb->cb_arg); 1089 } 1090 return 1; 1091 } 1092 1093 int inplace_cb_edns_back_parsed_call(struct module_env* env, 1094 struct module_qstate* qstate) 1095 { 1096 struct inplace_cb* cb = 1097 env->inplace_cb_lists[inplace_cb_edns_back_parsed]; 1098 for(; cb; cb=cb->next) { 1099 fptr_ok(fptr_whitelist_inplace_cb_edns_back_parsed( 1100 (inplace_cb_edns_back_parsed_func_type*)cb->cb)); 1101 (void)(*(inplace_cb_edns_back_parsed_func_type*)cb->cb)(qstate, 1102 cb->id, cb->cb_arg); 1103 } 1104 return 1; 1105 } 1106 1107 int inplace_cb_query_response_call(struct module_env* env, 1108 struct module_qstate* qstate, struct dns_msg* response) { 1109 struct inplace_cb* cb = 1110 env->inplace_cb_lists[inplace_cb_query_response]; 1111 for(; cb; cb=cb->next) { 1112 fptr_ok(fptr_whitelist_inplace_cb_query_response( 1113 (inplace_cb_query_response_func_type*)cb->cb)); 1114 (void)(*(inplace_cb_query_response_func_type*)cb->cb)(qstate, 1115 response, cb->id, cb->cb_arg); 1116 } 1117 return 1; 1118 } 1119 1120 struct edns_option* edns_opt_copy_region(struct edns_option* list, 1121 struct regional* region) 1122 { 1123 struct edns_option* result = NULL, *cur = NULL, *s; 1124 while(list) { 1125 /* copy edns option structure */ 1126 s = regional_alloc_init(region, list, sizeof(*list)); 1127 if(!s) return NULL; 1128 s->next = NULL; 1129 1130 /* copy option data */ 1131 if(s->opt_data) { 1132 s->opt_data = regional_alloc_init(region, s->opt_data, 1133 s->opt_len); 1134 if(!s->opt_data) 1135 return NULL; 1136 } 1137 1138 /* link into list */ 1139 if(cur) 1140 cur->next = s; 1141 else result = s; 1142 cur = s; 1143 1144 /* examine next element */ 1145 list = list->next; 1146 } 1147 return result; 1148 } 1149 1150 int edns_opt_compare(struct edns_option* p, struct edns_option* q) 1151 { 1152 if(!p && !q) return 0; 1153 if(!p) return -1; 1154 if(!q) return 1; 1155 log_assert(p && q); 1156 if(p->opt_code != q->opt_code) 1157 return (int)q->opt_code - (int)p->opt_code; 1158 if(p->opt_len != q->opt_len) 1159 return (int)q->opt_len - (int)p->opt_len; 1160 if(p->opt_len != 0) 1161 return memcmp(p->opt_data, q->opt_data, p->opt_len); 1162 return 0; 1163 } 1164 1165 int edns_opt_list_compare(struct edns_option* p, struct edns_option* q) 1166 { 1167 int r; 1168 while(p && q) { 1169 r = edns_opt_compare(p, q); 1170 if(r != 0) 1171 return r; 1172 p = p->next; 1173 q = q->next; 1174 } 1175 if(p || q) { 1176 /* uneven length lists */ 1177 if(p) return 1; 1178 if(q) return -1; 1179 } 1180 return 0; 1181 } 1182 1183 void edns_opt_list_free(struct edns_option* list) 1184 { 1185 struct edns_option* n; 1186 while(list) { 1187 free(list->opt_data); 1188 n = list->next; 1189 free(list); 1190 list = n; 1191 } 1192 } 1193 1194 struct edns_option* edns_opt_copy_alloc(struct edns_option* list) 1195 { 1196 struct edns_option* result = NULL, *cur = NULL, *s; 1197 while(list) { 1198 /* copy edns option structure */ 1199 s = memdup(list, sizeof(*list)); 1200 if(!s) { 1201 edns_opt_list_free(result); 1202 return NULL; 1203 } 1204 s->next = NULL; 1205 1206 /* copy option data */ 1207 if(s->opt_data) { 1208 s->opt_data = memdup(s->opt_data, s->opt_len); 1209 if(!s->opt_data) { 1210 free(s); 1211 edns_opt_list_free(result); 1212 return NULL; 1213 } 1214 } 1215 1216 /* link into list */ 1217 if(cur) 1218 cur->next = s; 1219 else result = s; 1220 cur = s; 1221 1222 /* examine next element */ 1223 list = list->next; 1224 } 1225 return result; 1226 } 1227 1228 struct edns_option* edns_opt_list_find(struct edns_option* list, uint16_t code) 1229 { 1230 struct edns_option* p; 1231 for(p=list; p; p=p->next) { 1232 if(p->opt_code == code) 1233 return p; 1234 } 1235 return NULL; 1236 } 1237