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