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