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