1238106Sdes/* 2238106Sdes * iterator/iter_delegpt.c - delegation point with NS and address information. 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file implements the Delegation Point. It contains a list of name servers 40238106Sdes * and their addresses if known. 41238106Sdes */ 42238106Sdes#include "config.h" 43238106Sdes#include "iterator/iter_delegpt.h" 44238106Sdes#include "services/cache/dns.h" 45238106Sdes#include "util/regional.h" 46238106Sdes#include "util/data/dname.h" 47238106Sdes#include "util/data/packed_rrset.h" 48238106Sdes#include "util/data/msgreply.h" 49238106Sdes#include "util/net_help.h" 50269257Sdes#include "ldns/rrdef.h" 51269257Sdes#include "ldns/sbuffer.h" 52238106Sdes 53238106Sdesstruct delegpt* 54238106Sdesdelegpt_create(struct regional* region) 55238106Sdes{ 56238106Sdes struct delegpt* dp=(struct delegpt*)regional_alloc( 57238106Sdes region, sizeof(*dp)); 58238106Sdes if(!dp) 59238106Sdes return NULL; 60238106Sdes memset(dp, 0, sizeof(*dp)); 61238106Sdes return dp; 62238106Sdes} 63238106Sdes 64238106Sdesstruct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) 65238106Sdes{ 66238106Sdes struct delegpt* copy = delegpt_create(region); 67238106Sdes struct delegpt_ns* ns; 68238106Sdes struct delegpt_addr* a; 69238106Sdes if(!copy) 70238106Sdes return NULL; 71238106Sdes if(!delegpt_set_name(copy, region, dp->name)) 72238106Sdes return NULL; 73238106Sdes copy->bogus = dp->bogus; 74238106Sdes copy->has_parent_side_NS = dp->has_parent_side_NS; 75238106Sdes for(ns = dp->nslist; ns; ns = ns->next) { 76269257Sdes if(!delegpt_add_ns(copy, region, ns->name, ns->lame)) 77238106Sdes return NULL; 78238106Sdes copy->nslist->resolved = ns->resolved; 79238106Sdes copy->nslist->got4 = ns->got4; 80238106Sdes copy->nslist->got6 = ns->got6; 81238106Sdes copy->nslist->done_pside4 = ns->done_pside4; 82238106Sdes copy->nslist->done_pside6 = ns->done_pside6; 83238106Sdes } 84238106Sdes for(a = dp->target_list; a; a = a->next_target) { 85238106Sdes if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, 86238106Sdes a->bogus, a->lame)) 87238106Sdes return NULL; 88238106Sdes } 89238106Sdes return copy; 90238106Sdes} 91238106Sdes 92238106Sdesint 93238106Sdesdelegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name) 94238106Sdes{ 95238106Sdes log_assert(!dp->dp_type_mlc); 96238106Sdes dp->namelabs = dname_count_size_labels(name, &dp->namelen); 97238106Sdes dp->name = regional_alloc_init(region, name, dp->namelen); 98238106Sdes return dp->name != 0; 99238106Sdes} 100238106Sdes 101238106Sdesint 102238106Sdesdelegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name, 103269257Sdes uint8_t lame) 104238106Sdes{ 105238106Sdes struct delegpt_ns* ns; 106238106Sdes size_t len; 107238106Sdes (void)dname_count_size_labels(name, &len); 108238106Sdes log_assert(!dp->dp_type_mlc); 109238106Sdes /* slow check for duplicates to avoid counting failures when 110238106Sdes * adding the same server as a dependency twice */ 111238106Sdes if(delegpt_find_ns(dp, name, len)) 112238106Sdes return 1; 113238106Sdes ns = (struct delegpt_ns*)regional_alloc(region, 114238106Sdes sizeof(struct delegpt_ns)); 115238106Sdes if(!ns) 116238106Sdes return 0; 117238106Sdes ns->next = dp->nslist; 118238106Sdes ns->namelen = len; 119238106Sdes dp->nslist = ns; 120238106Sdes ns->name = regional_alloc_init(region, name, ns->namelen); 121238106Sdes ns->resolved = 0; 122238106Sdes ns->got4 = 0; 123238106Sdes ns->got6 = 0; 124269257Sdes ns->lame = lame; 125238106Sdes ns->done_pside4 = 0; 126238106Sdes ns->done_pside6 = 0; 127238106Sdes return ns->name != 0; 128238106Sdes} 129238106Sdes 130238106Sdesstruct delegpt_ns* 131238106Sdesdelegpt_find_ns(struct delegpt* dp, uint8_t* name, size_t namelen) 132238106Sdes{ 133238106Sdes struct delegpt_ns* p = dp->nslist; 134238106Sdes while(p) { 135238106Sdes if(namelen == p->namelen && 136238106Sdes query_dname_compare(name, p->name) == 0) { 137238106Sdes return p; 138238106Sdes } 139238106Sdes p = p->next; 140238106Sdes } 141238106Sdes return NULL; 142238106Sdes} 143238106Sdes 144238106Sdesstruct delegpt_addr* 145238106Sdesdelegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, 146238106Sdes socklen_t addrlen) 147238106Sdes{ 148238106Sdes struct delegpt_addr* p = dp->target_list; 149238106Sdes while(p) { 150238106Sdes if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0) { 151238106Sdes return p; 152238106Sdes } 153238106Sdes p = p->next_target; 154238106Sdes } 155238106Sdes return NULL; 156238106Sdes} 157238106Sdes 158238106Sdesint 159238106Sdesdelegpt_add_target(struct delegpt* dp, struct regional* region, 160238106Sdes uint8_t* name, size_t namelen, struct sockaddr_storage* addr, 161269257Sdes socklen_t addrlen, uint8_t bogus, uint8_t lame) 162238106Sdes{ 163238106Sdes struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); 164238106Sdes log_assert(!dp->dp_type_mlc); 165238106Sdes if(!ns) { 166238106Sdes /* ignore it */ 167238106Sdes return 1; 168238106Sdes } 169238106Sdes if(!lame) { 170238106Sdes if(addr_is_ip6(addr, addrlen)) 171238106Sdes ns->got6 = 1; 172238106Sdes else ns->got4 = 1; 173238106Sdes if(ns->got4 && ns->got6) 174238106Sdes ns->resolved = 1; 175238106Sdes } 176238106Sdes return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame); 177238106Sdes} 178238106Sdes 179238106Sdesint 180238106Sdesdelegpt_add_addr(struct delegpt* dp, struct regional* region, 181269257Sdes struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, 182269257Sdes uint8_t lame) 183238106Sdes{ 184238106Sdes struct delegpt_addr* a; 185238106Sdes log_assert(!dp->dp_type_mlc); 186238106Sdes /* check for duplicates */ 187238106Sdes if((a = delegpt_find_addr(dp, addr, addrlen))) { 188238106Sdes if(bogus) 189238106Sdes a->bogus = bogus; 190238106Sdes if(!lame) 191238106Sdes a->lame = 0; 192238106Sdes return 1; 193238106Sdes } 194238106Sdes 195238106Sdes a = (struct delegpt_addr*)regional_alloc(region, 196238106Sdes sizeof(struct delegpt_addr)); 197238106Sdes if(!a) 198238106Sdes return 0; 199238106Sdes a->next_target = dp->target_list; 200238106Sdes dp->target_list = a; 201238106Sdes a->next_result = 0; 202238106Sdes a->next_usable = dp->usable_list; 203238106Sdes dp->usable_list = a; 204238106Sdes memcpy(&a->addr, addr, addrlen); 205238106Sdes a->addrlen = addrlen; 206238106Sdes a->attempts = 0; 207238106Sdes a->bogus = bogus; 208238106Sdes a->lame = lame; 209269257Sdes a->dnsseclame = 0; 210238106Sdes return 1; 211238106Sdes} 212238106Sdes 213238106Sdesvoid 214238106Sdesdelegpt_count_ns(struct delegpt* dp, size_t* numns, size_t* missing) 215238106Sdes{ 216238106Sdes struct delegpt_ns* ns; 217238106Sdes *numns = 0; 218238106Sdes *missing = 0; 219238106Sdes for(ns = dp->nslist; ns; ns = ns->next) { 220238106Sdes (*numns)++; 221238106Sdes if(!ns->resolved) 222238106Sdes (*missing)++; 223238106Sdes } 224238106Sdes} 225238106Sdes 226238106Sdesvoid 227238106Sdesdelegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres, 228238106Sdes size_t* numavail) 229238106Sdes{ 230238106Sdes struct delegpt_addr* a; 231238106Sdes *numaddr = 0; 232238106Sdes *numres = 0; 233238106Sdes *numavail = 0; 234238106Sdes for(a = dp->target_list; a; a = a->next_target) { 235238106Sdes (*numaddr)++; 236238106Sdes } 237238106Sdes for(a = dp->result_list; a; a = a->next_result) { 238238106Sdes (*numres)++; 239238106Sdes } 240238106Sdes for(a = dp->usable_list; a; a = a->next_usable) { 241238106Sdes (*numavail)++; 242238106Sdes } 243238106Sdes} 244238106Sdes 245238106Sdesvoid delegpt_log(enum verbosity_value v, struct delegpt* dp) 246238106Sdes{ 247238106Sdes char buf[LDNS_MAX_DOMAINLEN+1]; 248238106Sdes struct delegpt_ns* ns; 249238106Sdes struct delegpt_addr* a; 250238106Sdes size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0; 251238106Sdes if(verbosity < v) 252238106Sdes return; 253238106Sdes dname_str(dp->name, buf); 254238106Sdes if(dp->nslist == NULL && dp->target_list == NULL) { 255238106Sdes log_info("DelegationPoint<%s>: empty", buf); 256238106Sdes return; 257238106Sdes } 258238106Sdes delegpt_count_ns(dp, &numns, &missing); 259238106Sdes delegpt_count_addr(dp, &numaddr, &numres, &numavail); 260238106Sdes log_info("DelegationPoint<%s>: %u names (%u missing), " 261238106Sdes "%u addrs (%u result, %u avail)%s", 262238106Sdes buf, (unsigned)numns, (unsigned)missing, 263238106Sdes (unsigned)numaddr, (unsigned)numres, (unsigned)numavail, 264238106Sdes (dp->has_parent_side_NS?" parentNS":" cacheNS")); 265238106Sdes if(verbosity >= VERB_ALGO) { 266238106Sdes for(ns = dp->nslist; ns; ns = ns->next) { 267238106Sdes dname_str(ns->name, buf); 268238106Sdes log_info(" %s %s%s%s%s%s%s%s", buf, 269238106Sdes (ns->resolved?"*":""), 270238106Sdes (ns->got4?" A":""), (ns->got6?" AAAA":""), 271238106Sdes (dp->bogus?" BOGUS":""), (ns->lame?" PARENTSIDE":""), 272238106Sdes (ns->done_pside4?" PSIDE_A":""), 273238106Sdes (ns->done_pside6?" PSIDE_AAAA":"")); 274238106Sdes } 275238106Sdes for(a = dp->target_list; a; a = a->next_target) { 276238106Sdes const char* str = " "; 277238106Sdes if(a->bogus && a->lame) str = " BOGUS ADDR_LAME "; 278238106Sdes else if(a->bogus) str = " BOGUS "; 279238106Sdes else if(a->lame) str = " ADDR_LAME "; 280238106Sdes log_addr(VERB_ALGO, str, &a->addr, a->addrlen); 281238106Sdes } 282238106Sdes } 283238106Sdes} 284238106Sdes 285238106Sdesvoid 286238106Sdesdelegpt_add_unused_targets(struct delegpt* dp) 287238106Sdes{ 288238106Sdes struct delegpt_addr* usa = dp->usable_list; 289238106Sdes dp->usable_list = NULL; 290238106Sdes while(usa) { 291238106Sdes usa->next_result = dp->result_list; 292238106Sdes dp->result_list = usa; 293238106Sdes usa = usa->next_usable; 294238106Sdes } 295238106Sdes} 296238106Sdes 297238106Sdessize_t 298238106Sdesdelegpt_count_targets(struct delegpt* dp) 299238106Sdes{ 300238106Sdes struct delegpt_addr* a; 301238106Sdes size_t n = 0; 302238106Sdes for(a = dp->target_list; a; a = a->next_target) 303238106Sdes n++; 304238106Sdes return n; 305238106Sdes} 306238106Sdes 307238106Sdessize_t 308238106Sdesdelegpt_count_missing_targets(struct delegpt* dp) 309238106Sdes{ 310238106Sdes struct delegpt_ns* ns; 311238106Sdes size_t n = 0; 312238106Sdes for(ns = dp->nslist; ns; ns = ns->next) 313238106Sdes if(!ns->resolved) 314238106Sdes n++; 315238106Sdes return n; 316238106Sdes} 317238106Sdes 318238106Sdes/** find NS rrset in given list */ 319238106Sdesstatic struct ub_packed_rrset_key* 320238106Sdesfind_NS(struct reply_info* rep, size_t from, size_t to) 321238106Sdes{ 322238106Sdes size_t i; 323238106Sdes for(i=from; i<to; i++) { 324238106Sdes if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS) 325238106Sdes return rep->rrsets[i]; 326238106Sdes } 327238106Sdes return NULL; 328238106Sdes} 329238106Sdes 330238106Sdesstruct delegpt* 331238106Sdesdelegpt_from_message(struct dns_msg* msg, struct regional* region) 332238106Sdes{ 333238106Sdes struct ub_packed_rrset_key* ns_rrset = NULL; 334238106Sdes struct delegpt* dp; 335238106Sdes size_t i; 336238106Sdes /* look for NS records in the authority section... */ 337238106Sdes ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets, 338238106Sdes msg->rep->an_numrrsets+msg->rep->ns_numrrsets); 339238106Sdes 340238106Sdes /* In some cases (even legitimate, perfectly legal cases), the 341238106Sdes * NS set for the "referral" might be in the answer section. */ 342238106Sdes if(!ns_rrset) 343238106Sdes ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets); 344238106Sdes 345238106Sdes /* If there was no NS rrset in the authority section, then this 346238106Sdes * wasn't a referral message. (It might not actually be a 347238106Sdes * referral message anyway) */ 348238106Sdes if(!ns_rrset) 349238106Sdes return NULL; 350238106Sdes 351238106Sdes /* If we found any, then Yay! we have a delegation point. */ 352238106Sdes dp = delegpt_create(region); 353238106Sdes if(!dp) 354238106Sdes return NULL; 355238106Sdes dp->has_parent_side_NS = 1; /* created from message */ 356238106Sdes if(!delegpt_set_name(dp, region, ns_rrset->rk.dname)) 357238106Sdes return NULL; 358238106Sdes if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0)) 359238106Sdes return NULL; 360238106Sdes 361238106Sdes /* add glue, A and AAAA in answer and additional section */ 362238106Sdes for(i=0; i<msg->rep->rrset_count; i++) { 363238106Sdes struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; 364238106Sdes /* skip auth section. FIXME really needed?*/ 365238106Sdes if(msg->rep->an_numrrsets <= i && 366238106Sdes i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets)) 367238106Sdes continue; 368238106Sdes 369238106Sdes if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) { 370238106Sdes if(!delegpt_add_rrset_A(dp, region, s, 0)) 371238106Sdes return NULL; 372238106Sdes } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) { 373238106Sdes if(!delegpt_add_rrset_AAAA(dp, region, s, 0)) 374238106Sdes return NULL; 375238106Sdes } 376238106Sdes } 377238106Sdes return dp; 378238106Sdes} 379238106Sdes 380238106Sdesint 381238106Sdesdelegpt_rrset_add_ns(struct delegpt* dp, struct regional* region, 382269257Sdes struct ub_packed_rrset_key* ns_rrset, uint8_t lame) 383238106Sdes{ 384238106Sdes struct packed_rrset_data* nsdata = (struct packed_rrset_data*) 385238106Sdes ns_rrset->entry.data; 386238106Sdes size_t i; 387238106Sdes log_assert(!dp->dp_type_mlc); 388238106Sdes if(nsdata->security == sec_status_bogus) 389238106Sdes dp->bogus = 1; 390238106Sdes for(i=0; i<nsdata->count; i++) { 391238106Sdes if(nsdata->rr_len[i] < 2+1) continue; /* len + root label */ 392238106Sdes if(dname_valid(nsdata->rr_data[i]+2, nsdata->rr_len[i]-2) != 393269257Sdes (size_t)sldns_read_uint16(nsdata->rr_data[i])) 394238106Sdes continue; /* bad format */ 395238106Sdes /* add rdata of NS (= wirefmt dname), skip rdatalen bytes */ 396238106Sdes if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame)) 397238106Sdes return 0; 398238106Sdes } 399238106Sdes return 1; 400238106Sdes} 401238106Sdes 402238106Sdesint 403238106Sdesdelegpt_add_rrset_A(struct delegpt* dp, struct regional* region, 404269257Sdes struct ub_packed_rrset_key* ak, uint8_t lame) 405238106Sdes{ 406238106Sdes struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; 407238106Sdes size_t i; 408238106Sdes struct sockaddr_in sa; 409238106Sdes socklen_t len = (socklen_t)sizeof(sa); 410238106Sdes log_assert(!dp->dp_type_mlc); 411238106Sdes memset(&sa, 0, len); 412238106Sdes sa.sin_family = AF_INET; 413238106Sdes sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); 414238106Sdes for(i=0; i<d->count; i++) { 415238106Sdes if(d->rr_len[i] != 2 + INET_SIZE) 416238106Sdes continue; 417238106Sdes memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE); 418238106Sdes if(!delegpt_add_target(dp, region, ak->rk.dname, 419238106Sdes ak->rk.dname_len, (struct sockaddr_storage*)&sa, 420238106Sdes len, (d->security==sec_status_bogus), lame)) 421238106Sdes return 0; 422238106Sdes } 423238106Sdes return 1; 424238106Sdes} 425238106Sdes 426238106Sdesint 427238106Sdesdelegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region, 428269257Sdes struct ub_packed_rrset_key* ak, uint8_t lame) 429238106Sdes{ 430238106Sdes struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data; 431238106Sdes size_t i; 432238106Sdes struct sockaddr_in6 sa; 433238106Sdes socklen_t len = (socklen_t)sizeof(sa); 434238106Sdes log_assert(!dp->dp_type_mlc); 435238106Sdes memset(&sa, 0, len); 436238106Sdes sa.sin6_family = AF_INET6; 437238106Sdes sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); 438238106Sdes for(i=0; i<d->count; i++) { 439238106Sdes if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */ 440238106Sdes continue; 441238106Sdes memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE); 442238106Sdes if(!delegpt_add_target(dp, region, ak->rk.dname, 443238106Sdes ak->rk.dname_len, (struct sockaddr_storage*)&sa, 444238106Sdes len, (d->security==sec_status_bogus), lame)) 445238106Sdes return 0; 446238106Sdes } 447238106Sdes return 1; 448238106Sdes} 449238106Sdes 450238106Sdesint 451238106Sdesdelegpt_add_rrset(struct delegpt* dp, struct regional* region, 452269257Sdes struct ub_packed_rrset_key* rrset, uint8_t lame) 453238106Sdes{ 454238106Sdes if(!rrset) 455238106Sdes return 1; 456238106Sdes if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS) 457238106Sdes return delegpt_rrset_add_ns(dp, region, rrset, lame); 458238106Sdes else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A) 459238106Sdes return delegpt_add_rrset_A(dp, region, rrset, lame); 460238106Sdes else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA) 461238106Sdes return delegpt_add_rrset_AAAA(dp, region, rrset, lame); 462238106Sdes log_warn("Unknown rrset type added to delegpt"); 463238106Sdes return 1; 464238106Sdes} 465238106Sdes 466238106Sdesvoid delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg) 467238106Sdes{ 468238106Sdes struct reply_info* rep = (struct reply_info*)msg->entry.data; 469238106Sdes if(!rep) return; 470238106Sdes 471238106Sdes /* if error or no answers */ 472238106Sdes if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) { 473238106Sdes struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname, 474238106Sdes msg->key.qname_len); 475238106Sdes if(ns) { 476238106Sdes if(msg->key.qtype == LDNS_RR_TYPE_A) 477238106Sdes ns->got4 = 1; 478238106Sdes else if(msg->key.qtype == LDNS_RR_TYPE_AAAA) 479238106Sdes ns->got6 = 1; 480238106Sdes if(ns->got4 && ns->got6) 481238106Sdes ns->resolved = 1; 482238106Sdes } 483238106Sdes } 484238106Sdes} 485238106Sdes 486238106Sdesvoid delegpt_no_ipv6(struct delegpt* dp) 487238106Sdes{ 488238106Sdes struct delegpt_ns* ns; 489238106Sdes for(ns = dp->nslist; ns; ns = ns->next) { 490238106Sdes /* no ipv6, so only ipv4 is enough to resolve a nameserver */ 491238106Sdes if(ns->got4) 492238106Sdes ns->resolved = 1; 493238106Sdes } 494238106Sdes} 495238106Sdes 496238106Sdesvoid delegpt_no_ipv4(struct delegpt* dp) 497238106Sdes{ 498238106Sdes struct delegpt_ns* ns; 499238106Sdes for(ns = dp->nslist; ns; ns = ns->next) { 500238106Sdes /* no ipv4, so only ipv6 is enough to resolve a nameserver */ 501238106Sdes if(ns->got6) 502238106Sdes ns->resolved = 1; 503238106Sdes } 504238106Sdes} 505238106Sdes 506238106Sdesstruct delegpt* delegpt_create_mlc(uint8_t* name) 507238106Sdes{ 508238106Sdes struct delegpt* dp=(struct delegpt*)calloc(1, sizeof(*dp)); 509238106Sdes if(!dp) 510238106Sdes return NULL; 511238106Sdes dp->dp_type_mlc = 1; 512238106Sdes if(name) { 513238106Sdes dp->namelabs = dname_count_size_labels(name, &dp->namelen); 514238106Sdes dp->name = memdup(name, dp->namelen); 515238106Sdes if(!dp->name) { 516238106Sdes free(dp); 517238106Sdes return NULL; 518238106Sdes } 519238106Sdes } 520238106Sdes return dp; 521238106Sdes} 522238106Sdes 523238106Sdesvoid delegpt_free_mlc(struct delegpt* dp) 524238106Sdes{ 525238106Sdes struct delegpt_ns* n, *nn; 526238106Sdes struct delegpt_addr* a, *na; 527238106Sdes if(!dp) return; 528238106Sdes log_assert(dp->dp_type_mlc); 529238106Sdes n = dp->nslist; 530238106Sdes while(n) { 531238106Sdes nn = n->next; 532238106Sdes free(n->name); 533238106Sdes free(n); 534238106Sdes n = nn; 535238106Sdes } 536238106Sdes a = dp->target_list; 537238106Sdes while(a) { 538238106Sdes na = a->next_target; 539238106Sdes free(a); 540238106Sdes a = na; 541238106Sdes } 542238106Sdes free(dp->name); 543238106Sdes free(dp); 544238106Sdes} 545238106Sdes 546238106Sdesint delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name) 547238106Sdes{ 548238106Sdes log_assert(dp->dp_type_mlc); 549238106Sdes dp->namelabs = dname_count_size_labels(name, &dp->namelen); 550238106Sdes dp->name = memdup(name, dp->namelen); 551238106Sdes return (dp->name != NULL); 552238106Sdes} 553238106Sdes 554269257Sdesint delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame) 555238106Sdes{ 556238106Sdes struct delegpt_ns* ns; 557238106Sdes size_t len; 558238106Sdes (void)dname_count_size_labels(name, &len); 559238106Sdes log_assert(dp->dp_type_mlc); 560238106Sdes /* slow check for duplicates to avoid counting failures when 561238106Sdes * adding the same server as a dependency twice */ 562238106Sdes if(delegpt_find_ns(dp, name, len)) 563238106Sdes return 1; 564238106Sdes ns = (struct delegpt_ns*)malloc(sizeof(struct delegpt_ns)); 565238106Sdes if(!ns) 566238106Sdes return 0; 567238106Sdes ns->namelen = len; 568238106Sdes ns->name = memdup(name, ns->namelen); 569238106Sdes if(!ns->name) { 570238106Sdes free(ns); 571238106Sdes return 0; 572238106Sdes } 573238106Sdes ns->next = dp->nslist; 574238106Sdes dp->nslist = ns; 575238106Sdes ns->resolved = 0; 576238106Sdes ns->got4 = 0; 577238106Sdes ns->got6 = 0; 578238106Sdes ns->lame = (uint8_t)lame; 579238106Sdes ns->done_pside4 = 0; 580238106Sdes ns->done_pside6 = 0; 581238106Sdes return 1; 582238106Sdes} 583238106Sdes 584238106Sdesint delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr, 585269257Sdes socklen_t addrlen, uint8_t bogus, uint8_t lame) 586238106Sdes{ 587238106Sdes struct delegpt_addr* a; 588238106Sdes log_assert(dp->dp_type_mlc); 589238106Sdes /* check for duplicates */ 590238106Sdes if((a = delegpt_find_addr(dp, addr, addrlen))) { 591238106Sdes if(bogus) 592238106Sdes a->bogus = bogus; 593238106Sdes if(!lame) 594238106Sdes a->lame = 0; 595238106Sdes return 1; 596238106Sdes } 597238106Sdes 598238106Sdes a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr)); 599238106Sdes if(!a) 600238106Sdes return 0; 601238106Sdes a->next_target = dp->target_list; 602238106Sdes dp->target_list = a; 603238106Sdes a->next_result = 0; 604238106Sdes a->next_usable = dp->usable_list; 605238106Sdes dp->usable_list = a; 606238106Sdes memcpy(&a->addr, addr, addrlen); 607238106Sdes a->addrlen = addrlen; 608238106Sdes a->attempts = 0; 609238106Sdes a->bogus = bogus; 610238106Sdes a->lame = lame; 611269257Sdes a->dnsseclame = 0; 612238106Sdes return 1; 613238106Sdes} 614238106Sdes 615238106Sdesint delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen, 616269257Sdes struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, 617269257Sdes uint8_t lame) 618238106Sdes{ 619238106Sdes struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen); 620238106Sdes log_assert(dp->dp_type_mlc); 621238106Sdes if(!ns) { 622238106Sdes /* ignore it */ 623238106Sdes return 1; 624238106Sdes } 625238106Sdes if(!lame) { 626238106Sdes if(addr_is_ip6(addr, addrlen)) 627238106Sdes ns->got6 = 1; 628238106Sdes else ns->got4 = 1; 629238106Sdes if(ns->got4 && ns->got6) 630238106Sdes ns->resolved = 1; 631238106Sdes } 632238106Sdes return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame); 633238106Sdes} 634238106Sdes 635238106Sdessize_t delegpt_get_mem(struct delegpt* dp) 636238106Sdes{ 637238106Sdes struct delegpt_ns* ns; 638238106Sdes size_t s; 639238106Sdes if(!dp) return 0; 640238106Sdes s = sizeof(*dp) + dp->namelen + 641238106Sdes delegpt_count_targets(dp)*sizeof(struct delegpt_addr); 642238106Sdes for(ns=dp->nslist; ns; ns=ns->next) 643238106Sdes s += sizeof(*ns)+ns->namelen; 644238106Sdes return s; 645238106Sdes} 646