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