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