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