1 /* 2 * iterator/iter_delegpt.c - delegation point with NS and address information. 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 implements the Delegation Point. It contains a list of name servers 40 * and their addresses if known. 41 */ 42 #include "config.h" 43 #include "iterator/iter_delegpt.h" 44 #include "services/cache/dns.h" 45 #include "util/regional.h" 46 #include "util/data/dname.h" 47 #include "util/data/packed_rrset.h" 48 #include "util/data/msgreply.h" 49 #include "util/net_help.h" 50 #include "sldns/rrdef.h" 51 #include "sldns/sbuffer.h" 52 53 struct delegpt* 54 delegpt_create(struct regional* region) 55 { 56 struct delegpt* dp=(struct delegpt*)regional_alloc( 57 region, sizeof(*dp)); 58 if(!dp) 59 return NULL; 60 memset(dp, 0, sizeof(*dp)); 61 return dp; 62 } 63 64 struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) 65 { 66 struct delegpt* copy = delegpt_create(region); 67 struct delegpt_ns* ns; 68 struct delegpt_addr* a; 69 if(!copy) 70 return NULL; 71 if(!delegpt_set_name(copy, region, dp->name)) 72 return NULL; 73 copy->bogus = dp->bogus; 74 copy->has_parent_side_NS = dp->has_parent_side_NS; 75 copy->ssl_upstream = dp->ssl_upstream; 76 copy->tcp_upstream = dp->tcp_upstream; 77 for(ns = dp->nslist; ns; ns = ns->next) { 78 if(!delegpt_add_ns(copy, region, ns->name, ns->lame, 79 ns->tls_auth_name, ns->port)) 80 return NULL; 81 copy->nslist->cache_lookup_count = ns->cache_lookup_count; 82 copy->nslist->resolved = ns->resolved; 83 copy->nslist->got4 = ns->got4; 84 copy->nslist->got6 = ns->got6; 85 copy->nslist->done_pside4 = ns->done_pside4; 86 copy->nslist->done_pside6 = ns->done_pside6; 87 } 88 for(a = dp->target_list; a; a = a->next_target) { 89 if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, 90 a->bogus, a->lame, a->tls_auth_name, -1, NULL)) 91 return NULL; 92 } 93 return copy; 94 } 95 96 int 97 delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name) 98 { 99 log_assert(!dp->dp_type_mlc); 100 dp->namelabs = dname_count_size_labels(name, &dp->namelen); 101 dp->name = regional_alloc_init(region, name, dp->namelen); 102 return dp->name != 0; 103 } 104 105 int 106 delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, 107 uint8_t lame, char* tls_auth_name, int port) 108 { 109 struct delegpt_ns* ns; 110 size_t len; 111 (void)dname_count_size_labels(name, &len); 112 log_assert(!dp->dp_type_mlc); 113 /* slow check for duplicates to avoid counting failures when 114 * adding the same server as a dependency twice */ 115 if(delegpt_find_ns(dp, name, len)) 116 return 1; 117 ns = (struct delegpt_ns*)regional_alloc(region, 118 sizeof(struct delegpt_ns)); 119 if(!ns) 120 return 0; 121 ns->namelen = len; 122 ns->name = regional_alloc_init(region, name, ns->namelen); 123 if(!ns->name) 124 return 0; 125 ns->cache_lookup_count = 0; 126 ns->resolved = 0; 127 ns->got4 = 0; 128 ns->got6 = 0; 129 ns->lame = lame; 130 ns->done_pside4 = 0; 131 ns->done_pside6 = 0; 132 ns->port = port; 133 if(tls_auth_name) { 134 ns->tls_auth_name = regional_strdup(region, tls_auth_name); 135 if(!ns->tls_auth_name) 136 return 0; 137 } else { 138 ns->tls_auth_name = NULL; 139 } 140 ns->next = dp->nslist; 141 dp->nslist = ns; 142 return 1; 143 } 144 145 struct delegpt_ns* 146 delegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen) 147 { 148 struct delegpt_ns* p = dp->nslist; 149 while(p) { 150 if(namelen == p->namelen && 151 query_dname_compare(name, p->name) == 0) { 152 return p; 153 } 154 p = p->next; 155 } 156 return NULL; 157 } 158 159 struct delegpt_addr* 160 delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, 161 socklen_t addrlen) 162 { 163 struct delegpt_addr* p = dp->target_list; 164 while(p) { 165 if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0 166 && ((struct sockaddr_in*)addr)->sin_port == 167 ((struct sockaddr_in*)&p->addr)->sin_port) { 168 return p; 169 } 170 p = p->next_target; 171 } 172 return NULL; 173 } 174 175 int 176 delegpt_add_target(struct delegpt* dp, struct regional* region, 177 uint8_t* name, size_t namelen, struct sockaddr_storage* addr, 178 socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions) 179 { 180 struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); 181 log_assert(!dp->dp_type_mlc); 182 if(!ns) { 183 /* ignore it */ 184 return 1; 185 } 186 if(!lame) { 187 if(addr_is_ip6(addr, addrlen)) 188 ns->got6 = 1; 189 else ns->got4 = 1; 190 if(ns->got4 && ns->got6) 191 ns->resolved = 1; 192 } else { 193 if(addr_is_ip6(addr, addrlen)) 194 ns->done_pside6 = 1; 195 else ns->done_pside4 = 1; 196 } 197 log_assert(ns->port>0); 198 return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, 199 ns->tls_auth_name, ns->port, additions); 200 } 201 202 int 203 delegpt_add_addr(struct delegpt* dp, struct regional* region, 204 struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, 205 uint8_t lame, char* tls_auth_name, int port, int* additions) 206 { 207 struct delegpt_addr* a; 208 log_assert(!dp->dp_type_mlc); 209 if(port != -1) { 210 log_assert(port>0); 211 sockaddr_store_port(addr, addrlen, port); 212 } 213 /* check for duplicates */ 214 if((a = delegpt_find_addr(dp, addr, addrlen))) { 215 if(bogus) 216 a->bogus = bogus; 217 if(!lame) 218 a->lame = 0; 219 return 1; 220 } 221 if(additions) 222 *additions = 1; 223 224 a = (struct delegpt_addr*)regional_alloc(region, 225 sizeof(struct delegpt_addr)); 226 if(!a) 227 return 0; 228 a->next_result = 0; 229 memcpy(&a->addr, addr, addrlen); 230 a->addrlen = addrlen; 231 a->attempts = 0; 232 a->bogus = bogus; 233 a->lame = lame; 234 a->dnsseclame = 0; 235 if(tls_auth_name) { 236 a->tls_auth_name = regional_strdup(region, tls_auth_name); 237 if(!a->tls_auth_name) 238 return 0; 239 } else { 240 a->tls_auth_name = NULL; 241 } 242 a->next_target = dp->target_list; 243 dp->target_list = a; 244 a->next_usable = dp->usable_list; 245 dp->usable_list = a; 246 return 1; 247 } 248 249 void 250 delegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing) 251 { 252 struct delegpt_ns* ns; 253 *numns = 0; 254 *missing = 0; 255 for(ns = dp->nslist; ns; ns = ns->next) { 256 (*numns)++; 257 if(!ns->resolved) 258 (*missing)++; 259 } 260 } 261 262 void 263 delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, 264 size_t* numavail) 265 { 266 struct delegpt_addr* a; 267 *numaddr = 0; 268 *numres = 0; 269 *numavail = 0; 270 for(a = dp->target_list; a; a = a->next_target) { 271 (*numaddr)++; 272 } 273 for(a = dp->result_list; a; a = a->next_result) { 274 (*numres)++; 275 } 276 for(a = dp->usable_list; a; a = a->next_usable) { 277 (*numavail)++; 278 } 279 } 280 281 void delegpt_log(enum verbosity_value v, struct delegpt* dp) 282 { 283 char buf[LDNS_MAX_DOMAINLEN]; 284 struct delegpt_ns* ns; 285 struct delegpt_addr* a; 286 size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0; 287 if(verbosity < v) 288 return; 289 dname_str(dp->name, buf); 290 if(dp->nslist == NULL && dp->target_list == NULL) { 291 log_info("DelegationPoint<%s>: empty", buf); 292 return; 293 } 294 delegpt_count_ns(dp, &numns, &missing); 295 delegpt_count_addr(dp, &numaddr, &numres, &numavail); 296 log_info("DelegationPoint<%s>: %u names (%u missing), " 297 "%u addrs (%u result, %u avail)%s", 298 buf, (unsigned)numns, (unsigned)missing, 299 (unsigned)numaddr, (unsigned)numres, (unsigned)numavail, 300 (dp->has_parent_side_NS?" parentNS":" cacheNS")); 301 if(verbosity >= VERB_ALGO) { 302 for(ns = dp->nslist; ns; ns = ns->next) { 303 dname_str(ns->name, buf); 304 log_info(" %s %s%s%s%s%s%s%s", buf, 305 (ns->resolved?"*":""), 306 (ns->got4?" A":""), (ns->got6?" AAAA":""), 307 (dp->bogus?" BOGUS":""), (ns->lame?" PARENTSIDE":""), 308 (ns->done_pside4?" PSIDE_A":""), 309 (ns->done_pside6?" PSIDE_AAAA":"")); 310 } 311 for(a = dp->target_list; a; a = a->next_target) { 312 char s[128]; 313 const char* str = " "; 314 if(a->bogus && a->lame) str = " BOGUS ADDR_LAME "; 315 else if(a->bogus) str = " BOGUS "; 316 else if(a->lame) str = " ADDR_LAME "; 317 if(a->tls_auth_name) 318 snprintf(s, sizeof(s), "%s[%s]", str, 319 a->tls_auth_name); 320 else snprintf(s, sizeof(s), "%s", str); 321 log_addr(VERB_ALGO, s, &a->addr, a->addrlen); 322 } 323 } 324 } 325 326 int 327 delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find) 328 { 329 struct delegpt_addr* a = dp->result_list; 330 while(a) { 331 if(a == find) 332 return 1; 333 a = a->next_result; 334 } 335 return 0; 336 } 337 338 void 339 delegpt_usable_list_remove_addr(struct delegpt* dp, struct delegpt_addr* del) 340 { 341 struct delegpt_addr* usa = dp->usable_list, *prev = NULL; 342 while(usa) { 343 if(usa == del) { 344 /* snip off the usable list */ 345 if(prev) 346 prev->next_usable = usa->next_usable; 347 else dp->usable_list = usa->next_usable; 348 return; 349 } 350 prev = usa; 351 usa = usa->next_usable; 352 } 353 } 354 355 void 356 delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a) 357 { 358 if(delegpt_addr_on_result_list(dp, a)) 359 return; 360 delegpt_usable_list_remove_addr(dp, a); 361 a->next_result = dp->result_list; 362 dp->result_list = a; 363 } 364 365 void 366 delegpt_add_unused_targets(struct delegpt* dp) 367 { 368 struct delegpt_addr* usa = dp->usable_list; 369 dp->usable_list = NULL; 370 while(usa) { 371 usa->next_result = dp->result_list; 372 dp->result_list = usa; 373 usa = usa->next_usable; 374 } 375 } 376 377 size_t 378 delegpt_count_targets(struct delegpt* dp) 379 { 380 struct delegpt_addr* a; 381 size_t n = 0; 382 for(a = dp->target_list; a; a = a->next_target) 383 n++; 384 return n; 385 } 386 387 size_t 388 delegpt_count_missing_targets(struct delegpt* dp, int* alllame) 389 { 390 struct delegpt_ns* ns; 391 size_t n = 0, nlame = 0; 392 for(ns = dp->nslist; ns; ns = ns->next) { 393 if(ns->resolved) continue; 394 n++; 395 if(ns->lame) nlame++; 396 } 397 if(alllame && n == nlame) *alllame = 1; 398 return n; 399 } 400 401 /** find NS rrset in given list */ 402 static struct ub_packed_rrset_key* 403 find_NS(struct reply_info* rep, size_t from, size_t to, uint16_t qclass) 404 { 405 size_t i; 406 for(i=from; i<to; i++) { 407 if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS && 408 ntohs(rep->rrsets[i]->rk.rrset_class) == qclass) 409 return rep->rrsets[i]; 410 } 411 return NULL; 412 } 413 414 struct delegpt* 415 delegpt_from_message(struct dns_msg* msg, struct regional* region, int port) 416 { 417 struct ub_packed_rrset_key* ns_rrset = NULL; 418 struct delegpt* dp; 419 size_t i; 420 /* look for NS records in the authority section... */ 421 ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets, 422 msg->rep->an_numrrsets+msg->rep->ns_numrrsets, 423 msg->qinfo.qclass); 424 425 /* In some cases (even legitimate, perfectly legal cases), the 426 * NS set for the "referral" might be in the answer section. */ 427 if(!ns_rrset) 428 ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets, 429 msg->qinfo.qclass); 430 431 /* If there was no NS rrset in the authority section, then this 432 * wasn't a referral message. (It might not actually be a 433 * referral message anyway) */ 434 if(!ns_rrset) 435 return NULL; 436 437 /* If we found any, then Yay! we have a delegation point. */ 438 dp = delegpt_create(region); 439 if(!dp) 440 return NULL; 441 dp->has_parent_side_NS = 1; /* created from message */ 442 if(!delegpt_set_name(dp, region, ns_rrset->rk.dname)) 443 return NULL; 444 if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0, port)) 445 return NULL; 446 447 /* add glue, A and AAAA in answer and additional section */ 448 for(i=0; i<msg->rep->rrset_count; i++) { 449 struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; 450 /* skip auth section. FIXME really needed?*/ 451 if(msg->rep->an_numrrsets <= i && 452 i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets)) 453 continue; 454 455 if(ntohs(s->rk.type) == LDNS_RR_TYPE_A && 456 ntohs(s->rk.rrset_class) == msg->qinfo.qclass) { 457 if(!delegpt_add_rrset_A(dp, region, s, 0, NULL)) 458 return NULL; 459 } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA && 460 ntohs(s->rk.rrset_class) == msg->qinfo.qclass) { 461 if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL)) 462 return NULL; 463 } 464 } 465 return dp; 466 } 467 468 int 469 delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, 470 struct ub_packed_rrset_key* ns_rrset, uint8_t lame, int port) 471 { 472 struct packed_rrset_data* nsdata = (struct packed_rrset_data*) 473 ns_rrset->entry.data; 474 size_t i; 475 log_assert(!dp->dp_type_mlc); 476 if(nsdata->security == sec_status_bogus) 477 dp->bogus = 1; 478 for(i=0; i<nsdata->count; i++) { 479 if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */ 480 if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) != 481 (size_t)sldns_read_uint16(nsdata->rr_data[i])) 482 continue; /* bad format */ 483 /* add rdata of NS (= wirefmt dname), skip rdatalen bytes */ 484 if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame, 485 NULL, (port==-1?UNBOUND_DNS_PORT:port))) 486 return 0; 487 } 488 return 1; 489 } 490 491 int 492 delegpt_add_rrset_A(struct delegpt* dp, struct regional* region, 493 struct ub_packed_rrset_key* ak, uint8_t lame, int* additions) 494 { 495 struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; 496 size_t i; 497 struct sockaddr_in sa; 498 socklen_t len = (socklen_t)sizeof(sa); 499 log_assert(!dp->dp_type_mlc); 500 memset(&sa, 0, len); 501 sa.sin_family = AF_INET; 502 for(i=0; i<d->count; i++) { 503 if(d->rr_len[i] != 2 + INET_SIZE) 504 continue; 505 memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE); 506 if(!delegpt_add_target(dp, region, ak->rk.dname, 507 ak->rk.dname_len, (struct sockaddr_storage*)&sa, 508 len, (d->security==sec_status_bogus), lame, additions)) 509 return 0; 510 } 511 return 1; 512 } 513 514 int 515 delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, 516 struct ub_packed_rrset_key* ak, uint8_t lame, int* additions) 517 { 518 struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; 519 size_t i; 520 struct sockaddr_in6 sa; 521 socklen_t len = (socklen_t)sizeof(sa); 522 log_assert(!dp->dp_type_mlc); 523 memset(&sa, 0, len); 524 sa.sin6_family = AF_INET6; 525 for(i=0; i<d->count; i++) { 526 if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */ 527 continue; 528 memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE); 529 if(!delegpt_add_target(dp, region, ak->rk.dname, 530 ak->rk.dname_len, (struct sockaddr_storage*)&sa, 531 len, (d->security==sec_status_bogus), lame, additions)) 532 return 0; 533 } 534 return 1; 535 } 536 537 int 538 delegpt_add_rrset(struct delegpt* dp, struct regional* region, 539 struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions) 540 { 541 if(!rrset) 542 return 1; 543 if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS) 544 return delegpt_rrset_add_ns(dp, region, rrset, lame, -1); 545 else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A) 546 return delegpt_add_rrset_A(dp, region, rrset, lame, additions); 547 else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA) 548 return delegpt_add_rrset_AAAA(dp, region, rrset, lame, 549 additions); 550 log_warn("Unknown rrset type added to delegpt"); 551 return 1; 552 } 553 554 void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype) 555 { 556 if(ns) { 557 if(qtype == LDNS_RR_TYPE_A) 558 ns->got4 = 2; 559 else if(qtype == LDNS_RR_TYPE_AAAA) 560 ns->got6 = 2; 561 if(ns->got4 && ns->got6) 562 ns->resolved = 1; 563 } 564 } 565 566 void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg) 567 { 568 struct reply_info* rep = (struct reply_info*)msg->entry.data; 569 if(!rep) return; 570 571 /* if error or no answers */ 572 if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) { 573 struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname, 574 msg->key.qname_len); 575 delegpt_mark_neg(ns, msg->key.qtype); 576 } 577 } 578 579 void delegpt_no_ipv6(struct delegpt* dp) 580 { 581 struct delegpt_ns* ns; 582 for(ns = dp->nslist; ns; ns = ns->next) { 583 /* no ipv6, so only ipv4 is enough to resolve a nameserver */ 584 if(ns->got4) 585 ns->resolved = 1; 586 } 587 } 588 589 void delegpt_no_ipv4(struct delegpt* dp) 590 { 591 struct delegpt_ns* ns; 592 for(ns = dp->nslist; ns; ns = ns->next) { 593 /* no ipv4, so only ipv6 is enough to resolve a nameserver */ 594 if(ns->got6) 595 ns->resolved = 1; 596 } 597 } 598 599 struct delegpt* delegpt_create_mlc(uint8_t* name) 600 { 601 struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp)); 602 if(!dp) 603 return NULL; 604 dp->dp_type_mlc = 1; 605 if(name) { 606 dp->namelabs = dname_count_size_labels(name, &dp->namelen); 607 dp->name = memdup(name, dp->namelen); 608 if(!dp->name) { 609 free(dp); 610 return NULL; 611 } 612 } 613 return dp; 614 } 615 616 void delegpt_free_mlc(struct delegpt* dp) 617 { 618 struct delegpt_ns* n, *nn; 619 struct delegpt_addr* a, *na; 620 if(!dp) return; 621 log_assert(dp->dp_type_mlc); 622 n = dp->nslist; 623 while(n) { 624 nn = n->next; 625 free(n->name); 626 free(n->tls_auth_name); 627 free(n); 628 n = nn; 629 } 630 a = dp->target_list; 631 while(a) { 632 na = a->next_target; 633 free(a->tls_auth_name); 634 free(a); 635 a = na; 636 } 637 free(dp->name); 638 free(dp); 639 } 640 641 int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name) 642 { 643 log_assert(dp->dp_type_mlc); 644 dp->namelabs = dname_count_size_labels(name, &dp->namelen); 645 dp->name = memdup(name, dp->namelen); 646 return (dp->name != NULL); 647 } 648 649 int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame, 650 char* tls_auth_name, int port) 651 { 652 struct delegpt_ns* ns; 653 size_t len; 654 (void)dname_count_size_labels(name, &len); 655 log_assert(dp->dp_type_mlc); 656 /* slow check for duplicates to avoid counting failures when 657 * adding the same server as a dependency twice */ 658 if(delegpt_find_ns(dp, name, len)) 659 return 1; 660 ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns)); 661 if(!ns) 662 return 0; 663 ns->namelen = len; 664 ns->name = memdup(name, ns->namelen); 665 if(!ns->name) { 666 free(ns); 667 return 0; 668 } 669 ns->cache_lookup_count = 0; 670 ns->resolved = 0; 671 ns->got4 = 0; 672 ns->got6 = 0; 673 ns->lame = (uint8_t)lame; 674 ns->done_pside4 = 0; 675 ns->done_pside6 = 0; 676 ns->port = port; 677 if(tls_auth_name) { 678 ns->tls_auth_name = strdup(tls_auth_name); 679 if(!ns->tls_auth_name) { 680 free(ns->name); 681 free(ns); 682 return 0; 683 } 684 } else { 685 ns->tls_auth_name = NULL; 686 } 687 ns->next = dp->nslist; 688 dp->nslist = ns; 689 return 1; 690 } 691 692 int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, 693 socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name, 694 int port) 695 { 696 struct delegpt_addr* a; 697 log_assert(dp->dp_type_mlc); 698 if(port != -1) { 699 log_assert(port>0); 700 sockaddr_store_port(addr, addrlen, port); 701 } 702 /* check for duplicates */ 703 if((a = delegpt_find_addr(dp, addr, addrlen))) { 704 if(bogus) 705 a->bogus = bogus; 706 if(!lame) 707 a->lame = 0; 708 return 1; 709 } 710 711 a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr)); 712 if(!a) 713 return 0; 714 a->next_result = 0; 715 memcpy(&a->addr, addr, addrlen); 716 a->addrlen = addrlen; 717 a->attempts = 0; 718 a->bogus = bogus; 719 a->lame = lame; 720 a->dnsseclame = 0; 721 if(tls_auth_name) { 722 a->tls_auth_name = strdup(tls_auth_name); 723 if(!a->tls_auth_name) { 724 free(a); 725 return 0; 726 } 727 } else { 728 a->tls_auth_name = NULL; 729 } 730 a->next_target = dp->target_list; 731 dp->target_list = a; 732 a->next_usable = dp->usable_list; 733 dp->usable_list = a; 734 return 1; 735 } 736 737 int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, 738 struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, 739 uint8_t lame) 740 { 741 struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); 742 log_assert(dp->dp_type_mlc); 743 if(!ns) { 744 /* ignore it */ 745 return 1; 746 } 747 if(!lame) { 748 if(addr_is_ip6(addr, addrlen)) 749 ns->got6 = 1; 750 else ns->got4 = 1; 751 if(ns->got4 && ns->got6) 752 ns->resolved = 1; 753 } else { 754 if(addr_is_ip6(addr, addrlen)) 755 ns->done_pside6 = 1; 756 else ns->done_pside4 = 1; 757 } 758 log_assert(ns->port>0); 759 return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, 760 ns->tls_auth_name, ns->port); 761 } 762 763 size_t delegpt_get_mem(struct delegpt* dp) 764 { 765 struct delegpt_ns* ns; 766 size_t s; 767 if(!dp) return 0; 768 s = sizeof(*dp) + dp->namelen + 769 delegpt_count_targets(dp)*sizeof(struct delegpt_addr); 770 for(ns=dp->nslist; ns; ns=ns->next) 771 s += sizeof(*ns)+ns->namelen; 772 return s; 773 } 774