]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/services/localzone.c
Upgrade Unbound to 1.6.6. More to follow.
[FreeBSD/FreeBSD.git] / contrib / unbound / services / localzone.c
1 /*
2  * services/localzone.c - local zones authority service.
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 functions to enable local zone authority service.
40  */
41 #include "config.h"
42 #include "services/localzone.h"
43 #include "sldns/str2wire.h"
44 #include "sldns/sbuffer.h"
45 #include "util/regional.h"
46 #include "util/config_file.h"
47 #include "util/data/dname.h"
48 #include "util/data/packed_rrset.h"
49 #include "util/data/msgencode.h"
50 #include "util/net_help.h"
51 #include "util/netevent.h"
52 #include "util/data/msgreply.h"
53 #include "util/data/msgparse.h"
54 #include "util/as112.h"
55 #include "util/config_file.h"
56
57 /* maximum RRs in an RRset, to cap possible 'endless' list RRs.
58  * with 16 bytes for an A record, a 64K packet has about 4000 max */
59 #define LOCALZONE_RRSET_COUNT_MAX 4096
60
61 struct local_zones* 
62 local_zones_create(void)
63 {
64         struct local_zones* zones = (struct local_zones*)calloc(1, 
65                 sizeof(*zones));
66         if(!zones)
67                 return NULL;
68         rbtree_init(&zones->ztree, &local_zone_cmp);
69         lock_rw_init(&zones->lock);
70         lock_protect(&zones->lock, &zones->ztree, sizeof(zones->ztree));
71         /* also lock protects the rbnode's in struct local_zone */
72         return zones;
73 }
74
75 /** helper traverse to delete zones */
76 static void 
77 lzdel(rbnode_type* n, void* ATTR_UNUSED(arg))
78 {
79         struct local_zone* z = (struct local_zone*)n->key;
80         local_zone_delete(z);
81 }
82
83 void 
84 local_zones_delete(struct local_zones* zones)
85 {
86         if(!zones)
87                 return;
88         lock_rw_destroy(&zones->lock);
89         /* walk through zones and delete them all */
90         traverse_postorder(&zones->ztree, lzdel, NULL);
91         free(zones);
92 }
93
94 void 
95 local_zone_delete(struct local_zone* z)
96 {
97         if(!z)
98                 return;
99         lock_rw_destroy(&z->lock);
100         regional_destroy(z->region);
101         free(z->name);
102         free(z->taglist);
103         free(z);
104 }
105
106 int 
107 local_zone_cmp(const void* z1, const void* z2)
108 {
109         /* first sort on class, so that hierarchy can be maintained within
110          * a class */
111         struct local_zone* a = (struct local_zone*)z1;
112         struct local_zone* b = (struct local_zone*)z2;
113         int m;
114         if(a->dclass != b->dclass) {
115                 if(a->dclass < b->dclass)
116                         return -1;
117                 return 1;
118         }
119         return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m);
120 }
121
122 int 
123 local_data_cmp(const void* d1, const void* d2)
124 {
125         struct local_data* a = (struct local_data*)d1;
126         struct local_data* b = (struct local_data*)d2;
127         int m;
128         return dname_canon_lab_cmp(a->name, a->namelabs, b->name, 
129                 b->namelabs, &m);
130 }
131
132 /* form wireformat from text format domain name */
133 int
134 parse_dname(const char* str, uint8_t** res, size_t* len, int* labs)
135 {
136         *res = sldns_str2wire_dname(str, len);
137         *labs = 0;
138         if(!*res) {
139                 log_err("cannot parse name %s", str);
140                 return 0;
141         }
142         *labs = dname_count_size_labels(*res, len);
143         return 1;
144 }
145
146 /** create a new localzone */
147 static struct local_zone*
148 local_zone_create(uint8_t* nm, size_t len, int labs, 
149         enum localzone_type t, uint16_t dclass)
150 {
151         struct local_zone* z = (struct local_zone*)calloc(1, sizeof(*z));
152         if(!z) {
153                 return NULL;
154         }
155         z->node.key = z;
156         z->dclass = dclass;
157         z->type = t;
158         z->name = nm;
159         z->namelen = len;
160         z->namelabs = labs;
161         lock_rw_init(&z->lock);
162         z->region = regional_create_custom(sizeof(struct regional));
163         if(!z->region) {
164                 free(z);
165                 return NULL;
166         }
167         rbtree_init(&z->data, &local_data_cmp);
168         lock_protect(&z->lock, &z->parent, sizeof(*z)-sizeof(rbnode_type));
169         /* also the zones->lock protects node, parent, name*, class */
170         return z;
171 }
172
173 /** enter a new zone with allocated dname returns with WRlock */
174 static struct local_zone*
175 lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len, 
176         int labs, enum localzone_type t, uint16_t c)
177 {
178         struct local_zone* z = local_zone_create(nm, len, labs, t, c);
179         if(!z) {
180                 free(nm);
181                 log_err("out of memory");
182                 return NULL;
183         }
184
185         /* add to rbtree */
186         lock_rw_wrlock(&zones->lock);
187         lock_rw_wrlock(&z->lock);
188         if(!rbtree_insert(&zones->ztree, &z->node)) {
189                 struct local_zone* oldz;
190                 char str[256];
191                 dname_str(nm, str);
192                 log_warn("duplicate local-zone %s", str);
193                 lock_rw_unlock(&z->lock);
194                 /* save zone name locally before deallocation,
195                  * otherwise, nm is gone if we zone_delete now. */
196                 oldz = z;
197                 /* find the correct zone, so not an error for duplicate */
198                 z = local_zones_find(zones, nm, len, labs, c);
199                 lock_rw_wrlock(&z->lock);
200                 lock_rw_unlock(&zones->lock);
201                 local_zone_delete(oldz);
202                 return z;
203         }
204         lock_rw_unlock(&zones->lock);
205         return z;
206 }
207
208 /** enter a new zone */
209 static struct local_zone*
210 lz_enter_zone(struct local_zones* zones, const char* name, const char* type,
211         uint16_t dclass)
212 {
213         struct local_zone* z;
214         enum localzone_type t;
215         uint8_t* nm;
216         size_t len;
217         int labs;
218         if(!parse_dname(name, &nm, &len, &labs)) {
219                 log_err("bad zone name %s %s", name, type);
220                 return NULL;
221         }
222         if(!local_zone_str2type(type, &t)) {
223                 log_err("bad lz_enter_zone type %s %s", name, type);
224                 free(nm);
225                 return NULL;
226         }
227         if(!(z=lz_enter_zone_dname(zones, nm, len, labs, t, dclass))) {
228                 log_err("could not enter zone %s %s", name, type);
229                 return NULL;
230         }
231         return z;
232 }
233
234 int
235 rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
236         uint16_t* dclass, time_t* ttl, uint8_t* rr, size_t len,
237         uint8_t** rdata, size_t* rdata_len)
238 {
239         size_t dname_len = 0;
240         int e = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600,
241                 NULL, 0, NULL, 0);
242         if(e) {
243                 log_err("error parsing local-data at %d: '%s': %s",
244                         LDNS_WIREPARSE_OFFSET(e), str,
245                         sldns_get_errorstr_parse(e));
246                 return 0;
247         }
248         *nm = memdup(rr, dname_len);
249         if(!*nm) {
250                 log_err("out of memory");
251                 return 0;
252         }
253         *dclass = sldns_wirerr_get_class(rr, len, dname_len);
254         *type = sldns_wirerr_get_type(rr, len, dname_len);
255         *ttl = (time_t)sldns_wirerr_get_ttl(rr, len, dname_len);
256         *rdata = sldns_wirerr_get_rdatawl(rr, len, dname_len);
257         *rdata_len = sldns_wirerr_get_rdatalen(rr, len, dname_len)+2;
258         return 1;
259 }
260
261 /** return name and class of rr; parses string */
262 static int
263 get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass,
264         uint16_t* dtype)
265 {
266         uint8_t rr[LDNS_RR_BUF_SIZE];
267         size_t len = sizeof(rr), dname_len = 0;
268         int s = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600,
269                 NULL, 0, NULL, 0);
270         if(s != 0) {
271                 log_err("error parsing local-data at %d '%s': %s",
272                         LDNS_WIREPARSE_OFFSET(s), str,
273                         sldns_get_errorstr_parse(s));
274                 return 0;
275         }
276         *nm = memdup(rr, dname_len);
277         *dclass = sldns_wirerr_get_class(rr, len, dname_len);
278         *dtype = sldns_wirerr_get_type(rr, len, dname_len);
279         if(!*nm) {
280                 log_err("out of memory");
281                 return 0;
282         }
283         return 1;
284 }
285
286 /**
287  * Find an rrset in local data structure.
288  * @param data: local data domain name structure.
289  * @param type: type to look for (host order).
290  * @param alias_ok: 1 if matching a non-exact, alias type such as CNAME is
291  * allowed.  otherwise 0.
292  * @return rrset pointer or NULL if not found.
293  */
294 static struct local_rrset*
295 local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
296 {
297         struct local_rrset* p;
298         type = htons(type);
299         for(p = data->rrsets; p; p = p->next) {
300                 if(p->rrset->rk.type == type)
301                         return p;
302                 if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
303                         return p;
304         }
305         return NULL;
306 }
307
308 /** check for RR duplicates */
309 static int
310 rr_is_duplicate(struct packed_rrset_data* pd, uint8_t* rdata, size_t rdata_len)
311 {
312         size_t i;
313         for(i=0; i<pd->count; i++) {
314                 if(pd->rr_len[i] == rdata_len &&
315                         memcmp(pd->rr_data[i], rdata, rdata_len) == 0)
316                         return 1;
317         }
318         return 0;
319 }
320
321 /** new local_rrset */
322 static struct local_rrset*
323 new_local_rrset(struct regional* region, struct local_data* node,
324         uint16_t rrtype, uint16_t rrclass)
325 {
326         struct packed_rrset_data* pd;
327         struct local_rrset* rrset = (struct local_rrset*)
328                 regional_alloc_zero(region, sizeof(*rrset));
329         if(!rrset) {
330                 log_err("out of memory");
331                 return NULL;
332         }
333         rrset->next = node->rrsets;
334         node->rrsets = rrset;
335         rrset->rrset = (struct ub_packed_rrset_key*)
336                 regional_alloc_zero(region, sizeof(*rrset->rrset));
337         if(!rrset->rrset) {
338                 log_err("out of memory");
339                 return NULL;
340         }
341         rrset->rrset->entry.key = rrset->rrset;
342         pd = (struct packed_rrset_data*)regional_alloc_zero(region,
343                 sizeof(*pd));
344         if(!pd) {
345                 log_err("out of memory");
346                 return NULL;
347         }
348         pd->trust = rrset_trust_prim_noglue;
349         pd->security = sec_status_insecure;
350         rrset->rrset->entry.data = pd;
351         rrset->rrset->rk.dname = node->name;
352         rrset->rrset->rk.dname_len = node->namelen;
353         rrset->rrset->rk.type = htons(rrtype);
354         rrset->rrset->rk.rrset_class = htons(rrclass);
355         return rrset;
356 }
357
358 /** insert RR into RRset data structure; Wastes a couple of bytes */
359 int
360 rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
361         uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr)
362 {
363         size_t* oldlen = pd->rr_len;
364         time_t* oldttl = pd->rr_ttl;
365         uint8_t** olddata = pd->rr_data;
366
367         /* add RR to rrset */
368         if(pd->count > LOCALZONE_RRSET_COUNT_MAX) {
369                 log_warn("RRset '%s' has more than %d records, record ignored",
370                         rrstr, LOCALZONE_RRSET_COUNT_MAX);
371                 return 1;
372         }
373         pd->count++;
374         pd->rr_len = regional_alloc(region, sizeof(*pd->rr_len)*pd->count);
375         pd->rr_ttl = regional_alloc(region, sizeof(*pd->rr_ttl)*pd->count);
376         pd->rr_data = regional_alloc(region, sizeof(*pd->rr_data)*pd->count);
377         if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) {
378                 log_err("out of memory");
379                 return 0;
380         }
381         if(pd->count > 1) {
382                 memcpy(pd->rr_len+1, oldlen, 
383                         sizeof(*pd->rr_len)*(pd->count-1));
384                 memcpy(pd->rr_ttl+1, oldttl, 
385                         sizeof(*pd->rr_ttl)*(pd->count-1));
386                 memcpy(pd->rr_data+1, olddata, 
387                         sizeof(*pd->rr_data)*(pd->count-1));
388         }
389         pd->rr_len[0] = rdata_len;
390         pd->rr_ttl[0] = ttl;
391         pd->rr_data[0] = regional_alloc_init(region, rdata, rdata_len);
392         if(!pd->rr_data[0]) {
393                 log_err("out of memory");
394                 return 0;
395         }
396         return 1;
397 }
398
399 /** find a data node by exact name */
400 static struct local_data* 
401 lz_find_node(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs)
402 {
403         struct local_data key;
404         key.node.key = &key;
405         key.name = nm;
406         key.namelen = nmlen;
407         key.namelabs = nmlabs;
408         return (struct local_data*)rbtree_search(&z->data, &key.node);
409 }
410
411 /** find a node, create it if not and all its empty nonterminal parents */
412 static int
413 lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen, 
414         int nmlabs, struct local_data** res)
415 {
416         struct local_data* ld = lz_find_node(z, nm, nmlen, nmlabs);
417         if(!ld) {
418                 /* create a domain name to store rr. */
419                 ld = (struct local_data*)regional_alloc_zero(z->region,
420                         sizeof(*ld));
421                 if(!ld) {
422                         log_err("out of memory adding local data");
423                         return 0;
424                 }
425                 ld->node.key = ld;
426                 ld->name = regional_alloc_init(z->region, nm, nmlen);
427                 if(!ld->name) {
428                         log_err("out of memory");
429                         return 0;
430                 }
431                 ld->namelen = nmlen;
432                 ld->namelabs = nmlabs;
433                 if(!rbtree_insert(&z->data, &ld->node)) {
434                         log_assert(0); /* duplicate name */
435                 }
436                 /* see if empty nonterminals need to be created */
437                 if(nmlabs > z->namelabs) {
438                         dname_remove_label(&nm, &nmlen);
439                         if(!lz_find_create_node(z, nm, nmlen, nmlabs-1, res))
440                                 return 0;
441                 }
442         }
443         *res = ld;
444         return 1;
445 }
446
447 /** enter data RR into auth zone */
448 static int
449 lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
450 {
451         uint8_t* nm;
452         size_t nmlen;
453         int nmlabs;
454         struct local_data* node;
455         struct local_rrset* rrset;
456         struct packed_rrset_data* pd;
457         uint16_t rrtype = 0, rrclass = 0;
458         time_t ttl = 0;
459         uint8_t rr[LDNS_RR_BUF_SIZE];
460         uint8_t* rdata;
461         size_t rdata_len;
462         if(!rrstr_get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr,
463                 sizeof(rr), &rdata, &rdata_len)) {
464                 log_err("bad local-data: %s", rrstr);
465                 return 0;
466         }
467         log_assert(z->dclass == rrclass);
468         if(z->type == local_zone_redirect &&
469                 query_dname_compare(z->name, nm) != 0) {
470                 log_err("local-data in redirect zone must reside at top of zone"
471                         ", not at %s", rrstr);
472                 free(nm);
473                 return 0;
474         }
475         nmlabs = dname_count_size_labels(nm, &nmlen);
476         if(!lz_find_create_node(z, nm, nmlen, nmlabs, &node)) {
477                 free(nm);
478                 return 0;
479         }
480         log_assert(node);
481         free(nm);
482
483         /* Reject it if we would end up having CNAME and other data (including
484          * another CNAME) for a redirect zone. */
485         if(z->type == local_zone_redirect && node->rrsets) {
486                 const char* othertype = NULL;
487                 if (rrtype == LDNS_RR_TYPE_CNAME)
488                         othertype = "other";
489                 else if (node->rrsets->rrset->rk.type ==
490                          htons(LDNS_RR_TYPE_CNAME)) {
491                         othertype = "CNAME";
492                 }
493                 if(othertype) {
494                         log_err("local-data '%s' in redirect zone must not "
495                                 "coexist with %s local-data", rrstr, othertype);
496                         return 0;
497                 }
498         }
499         rrset = local_data_find_type(node, rrtype, 0);
500         if(!rrset) {
501                 rrset = new_local_rrset(z->region, node, rrtype, rrclass);
502                 if(!rrset)
503                         return 0;
504                 if(query_dname_compare(node->name, z->name) == 0) {
505                         if(rrtype == LDNS_RR_TYPE_NSEC)
506                           rrset->rrset->rk.flags = PACKED_RRSET_NSEC_AT_APEX;
507                         if(rrtype == LDNS_RR_TYPE_SOA)
508                                 z->soa = rrset->rrset;
509                 }
510         } 
511         pd = (struct packed_rrset_data*)rrset->rrset->entry.data;
512         log_assert(rrset && pd);
513
514         /* check for duplicate RR */
515         if(rr_is_duplicate(pd, rdata, rdata_len)) {
516                 verbose(VERB_ALGO, "ignoring duplicate RR: %s", rrstr);
517                 return 1;
518         } 
519         return rrset_insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr);
520 }
521
522 /** enter a data RR into auth data; a zone for it must exist */
523 static int
524 lz_enter_rr_str(struct local_zones* zones, const char* rr)
525 {
526         uint8_t* rr_name;
527         uint16_t rr_class, rr_type;
528         size_t len;
529         int labs;
530         struct local_zone* z;
531         int r;
532         if(!get_rr_nameclass(rr, &rr_name, &rr_class, &rr_type)) {
533                 log_err("bad rr %s", rr);
534                 return 0;
535         }
536         labs = dname_count_size_labels(rr_name, &len);
537         lock_rw_rdlock(&zones->lock);
538         z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
539         if(!z) {
540                 lock_rw_unlock(&zones->lock);
541                 fatal_exit("internal error: no zone for rr %s", rr);
542         }
543         lock_rw_wrlock(&z->lock);
544         lock_rw_unlock(&zones->lock);
545         free(rr_name);
546         r = lz_enter_rr_into_zone(z, rr);
547         lock_rw_unlock(&z->lock);
548         return r;
549 }
550
551 /** enter tagstring into zone */
552 static int
553 lz_enter_zone_tag(struct local_zones* zones, char* zname, uint8_t* list,
554         size_t len, uint16_t rr_class)
555 {
556         uint8_t dname[LDNS_MAX_DOMAINLEN+1];
557         size_t dname_len = sizeof(dname);
558         int dname_labs, r = 0;
559         struct local_zone* z;
560
561         if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
562                 log_err("cannot parse zone name in local-zone-tag: %s", zname);
563                 return 0;
564         }
565         dname_labs = dname_count_labels(dname);
566         
567         lock_rw_rdlock(&zones->lock);
568         z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class);
569         if(!z) {
570                 lock_rw_unlock(&zones->lock);
571                 log_err("no local-zone for tag %s", zname);
572                 return 0;
573         }
574         lock_rw_wrlock(&z->lock);
575         lock_rw_unlock(&zones->lock);
576         free(z->taglist);
577         z->taglist = memdup(list, len);
578         z->taglen = len;
579         if(z->taglist)
580                 r = 1;
581         lock_rw_unlock(&z->lock);
582         return r;
583 }
584
585 /** enter override into zone */
586 static int
587 lz_enter_override(struct local_zones* zones, char* zname, char* netblock,
588         char* type, uint16_t rr_class)
589 {
590         uint8_t dname[LDNS_MAX_DOMAINLEN+1];
591         size_t dname_len = sizeof(dname);
592         int dname_labs;
593         struct sockaddr_storage addr;
594         int net;
595         socklen_t addrlen;
596         struct local_zone* z;
597         enum localzone_type t;
598
599         /* parse zone name */
600         if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
601                 log_err("cannot parse zone name in local-zone-override: %s %s",
602                         zname, netblock);
603                 return 0;
604         }
605         dname_labs = dname_count_labels(dname);
606
607         /* parse netblock */
608         if(!netblockstrtoaddr(netblock, UNBOUND_DNS_PORT, &addr, &addrlen,
609                 &net)) {
610                 log_err("cannot parse netblock in local-zone-override: %s %s",
611                         zname, netblock);
612                 return 0;
613         }
614
615         /* parse zone type */
616         if(!local_zone_str2type(type, &t)) {
617                 log_err("cannot parse type in local-zone-override: %s %s %s",
618                         zname, netblock, type);
619                 return 0;
620         }
621
622         /* find localzone entry */
623         lock_rw_rdlock(&zones->lock);
624         z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class);
625         if(!z) {
626                 lock_rw_unlock(&zones->lock);
627                 log_err("no local-zone for local-zone-override %s", zname);
628                 return 0;
629         }
630         lock_rw_wrlock(&z->lock);
631         lock_rw_unlock(&zones->lock);
632
633         /* create netblock addr_tree if not present yet */
634         if(!z->override_tree) {
635                 z->override_tree = (struct rbtree_type*)regional_alloc_zero(
636                         z->region, sizeof(*z->override_tree));
637                 if(!z->override_tree) {
638                         lock_rw_unlock(&z->lock);
639                         log_err("out of memory");
640                         return 0;
641                 }
642                 addr_tree_init(z->override_tree);
643         }
644         /* add new elem to tree */
645         if(z->override_tree) {
646                 struct local_zone_override* n;
647                 n = (struct local_zone_override*)regional_alloc_zero(
648                         z->region, sizeof(*n));
649                 if(!n) {
650                         lock_rw_unlock(&z->lock);
651                         log_err("out of memory");
652                         return 0;
653                 }
654                 n->type = t;
655                 if(!addr_tree_insert(z->override_tree,
656                         (struct addr_tree_node*)n, &addr, addrlen, net)) {
657                         lock_rw_unlock(&z->lock);
658                         log_err("duplicate local-zone-override %s %s",
659                                 zname, netblock);
660                         return 1;
661                 }
662         }
663
664         lock_rw_unlock(&z->lock);
665         return 1;
666 }
667
668 /** parse local-zone: statements */
669 static int
670 lz_enter_zones(struct local_zones* zones, struct config_file* cfg)
671 {
672         struct config_str2list* p;
673         struct local_zone* z;
674         for(p = cfg->local_zones; p; p = p->next) {
675                 if(!(z=lz_enter_zone(zones, p->str, p->str2, 
676                         LDNS_RR_CLASS_IN)))
677                         return 0;
678                 lock_rw_unlock(&z->lock);
679         }
680         return 1;
681 }
682
683 /** lookup a zone in rbtree; exact match only; SLOW due to parse */
684 static int
685 lz_exists(struct local_zones* zones, const char* name)
686 {
687         struct local_zone z;
688         z.node.key = &z;
689         z.dclass = LDNS_RR_CLASS_IN;
690         if(!parse_dname(name, &z.name, &z.namelen, &z.namelabs)) {
691                 log_err("bad name %s", name);
692                 return 0;
693         }
694         lock_rw_rdlock(&zones->lock);
695         if(rbtree_search(&zones->ztree, &z.node)) {
696                 lock_rw_unlock(&zones->lock);
697                 free(z.name);
698                 return 1;
699         }
700         lock_rw_unlock(&zones->lock);
701         free(z.name);
702         return 0;
703 }
704
705 /** lookup a zone in cfg->nodefault list */
706 static int
707 lz_nodefault(struct config_file* cfg, const char* name)
708 {
709         struct config_strlist* p;
710         size_t len = strlen(name);
711         if(len == 0) return 0;
712         if(name[len-1] == '.') len--;
713
714         for(p = cfg->local_zones_nodefault; p; p = p->next) {
715                 /* compare zone name, lowercase, compare without ending . */
716                 if(strncasecmp(p->str, name, len) == 0 && 
717                         (strlen(p->str) == len || (strlen(p->str)==len+1 &&
718                         p->str[len] == '.')))
719                         return 1;
720         }
721         return 0;
722 }
723
724 /** enter (AS112) empty default zone */
725 static int
726 add_empty_default(struct local_zones* zones, struct config_file* cfg,
727         const char* name)
728 {
729         struct local_zone* z;
730         char str[1024]; /* known long enough */
731         if(lz_exists(zones, name) || lz_nodefault(cfg, name))
732                 return 1; /* do not enter default content */
733         if(!(z=lz_enter_zone(zones, name, "static", LDNS_RR_CLASS_IN)))
734                 return 0;
735         snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. "
736                 "nobody.invalid. 1 3600 1200 604800 10800", name);
737         if(!lz_enter_rr_into_zone(z, str)) {
738                 lock_rw_unlock(&z->lock);
739                 return 0;
740         }
741         snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name);
742         if(!lz_enter_rr_into_zone(z, str)) {
743                 lock_rw_unlock(&z->lock);
744                 return 0;
745         }
746         lock_rw_unlock(&z->lock);
747         return 1;
748 }
749
750 /** enter default zones */
751 int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg)
752 {
753         struct local_zone* z;
754         const char** zstr;
755
756         /* Do not add any default */
757         if(cfg->local_zones_disable_default)
758                 return 1;
759
760         /* this list of zones is from RFC 6303 and RFC 7686 */
761
762         /* block localhost level zones first, then onion and later the LAN zones */
763
764         /* localhost. zone */
765         if(!lz_exists(zones, "localhost.") &&
766                 !lz_nodefault(cfg, "localhost.")) {
767                 if(!(z=lz_enter_zone(zones, "localhost.", "redirect", 
768                         LDNS_RR_CLASS_IN)) ||
769                    !lz_enter_rr_into_zone(z,
770                         "localhost. 10800 IN NS localhost.") ||
771                    !lz_enter_rr_into_zone(z,
772                         "localhost. 10800 IN SOA localhost. nobody.invalid. "
773                         "1 3600 1200 604800 10800") ||
774                    !lz_enter_rr_into_zone(z,
775                         "localhost. 10800 IN A 127.0.0.1") ||
776                    !lz_enter_rr_into_zone(z,
777                         "localhost. 10800 IN AAAA ::1")) {
778                         log_err("out of memory adding default zone");
779                         if(z) { lock_rw_unlock(&z->lock); }
780                         return 0;
781                 }
782                 lock_rw_unlock(&z->lock);
783         }
784         /* reverse ip4 zone */
785         if(!lz_exists(zones, "127.in-addr.arpa.") &&
786                 !lz_nodefault(cfg, "127.in-addr.arpa.")) {
787                 if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static", 
788                         LDNS_RR_CLASS_IN)) ||
789                    !lz_enter_rr_into_zone(z,
790                         "127.in-addr.arpa. 10800 IN NS localhost.") ||
791                    !lz_enter_rr_into_zone(z,
792                         "127.in-addr.arpa. 10800 IN SOA localhost. "
793                         "nobody.invalid. 1 3600 1200 604800 10800") ||
794                    !lz_enter_rr_into_zone(z,
795                         "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
796                         log_err("out of memory adding default zone");
797                         if(z) { lock_rw_unlock(&z->lock); }
798                         return 0;
799                 }
800                 lock_rw_unlock(&z->lock);
801         }
802         /* reverse ip6 zone */
803         if(!lz_exists(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") &&
804                 !lz_nodefault(cfg, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")) {
805                 if(!(z=lz_enter_zone(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", "static", 
806                         LDNS_RR_CLASS_IN)) ||
807                    !lz_enter_rr_into_zone(z,
808                         "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost.") ||
809                    !lz_enter_rr_into_zone(z,
810                         "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. "
811                         "nobody.invalid. 1 3600 1200 604800 10800") ||
812                    !lz_enter_rr_into_zone(z,
813                         "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.")) {
814                         log_err("out of memory adding default zone");
815                         if(z) { lock_rw_unlock(&z->lock); }
816                         return 0;
817                 }
818                 lock_rw_unlock(&z->lock);
819         }
820         /* onion. zone (RFC 7686) */
821         if(!add_empty_default(zones, cfg, "onion.")) {
822                 log_err("out of memory adding default zone");
823                 return 0;
824         }
825         /* test. zone (RFC 7686) */
826         if(!add_empty_default(zones, cfg, "test.")) {
827                 log_err("out of memory adding default zone");
828                 return 0;
829         }
830         /* invalid. zone (RFC 7686) */
831         if(!add_empty_default(zones, cfg, "invalid.")) {
832                 log_err("out of memory adding default zone");
833                 return 0;
834         }
835         /* block AS112 zones, unless asked not to */
836         if(!cfg->unblock_lan_zones) {
837                 for(zstr = as112_zones; *zstr; zstr++) {
838                         if(!add_empty_default(zones, cfg, *zstr)) {
839                                 log_err("out of memory adding default zone");
840                                 return 0;
841                         }
842                 }
843         }
844         return 1;
845 }
846
847 /** parse local-zone-override: statements */
848 static int
849 lz_enter_overrides(struct local_zones* zones, struct config_file* cfg)
850 {
851         struct config_str3list* p;
852         for(p = cfg->local_zone_overrides; p; p = p->next) {
853                 if(!lz_enter_override(zones, p->str, p->str2, p->str3,
854                         LDNS_RR_CLASS_IN))
855                         return 0;
856         }
857         return 1;
858 }
859
860 /** setup parent pointers, so that a lookup can be done for closest match */
861 static void
862 init_parents(struct local_zones* zones)
863 {
864         struct local_zone* node, *prev = NULL, *p;
865         int m;
866         lock_rw_wrlock(&zones->lock);
867         RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
868                 lock_rw_wrlock(&node->lock);
869                 node->parent = NULL;
870                 if(!prev || prev->dclass != node->dclass) {
871                         prev = node;
872                         lock_rw_unlock(&node->lock);
873                         continue;
874                 }
875                 (void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
876                         node->namelabs, &m); /* we know prev is smaller */
877                 /* sort order like: . com. bla.com. zwb.com. net. */
878                 /* find the previous, or parent-parent-parent */
879                 for(p = prev; p; p = p->parent)
880                         /* looking for name with few labels, a parent */
881                         if(p->namelabs <= m) {
882                                 /* ==: since prev matched m, this is closest*/
883                                 /* <: prev matches more, but is not a parent,
884                                  * this one is a (grand)parent */
885                                 node->parent = p;
886                                 break;
887                         }
888                 prev = node;
889
890                 if(node->override_tree)
891                         addr_tree_init_parents(node->override_tree);
892                 lock_rw_unlock(&node->lock);
893         }
894         lock_rw_unlock(&zones->lock);
895 }
896
897 /** enter implicit transparent zone for local-data: without local-zone: */
898 static int
899 lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
900 {
901         /* walk over all items that have no parent zone and find
902          * the name that covers them all (could be the root) and
903          * add that as a transparent zone */
904         struct config_strlist* p;
905         int have_name = 0;
906         int have_other_classes = 0;
907         uint16_t dclass = 0;
908         uint8_t* nm = 0;
909         size_t nmlen = 0;
910         int nmlabs = 0;
911         int match = 0; /* number of labels match count */
912
913         init_parents(zones); /* to enable local_zones_lookup() */
914         for(p = cfg->local_data; p; p = p->next) {
915                 uint8_t* rr_name;
916                 uint16_t rr_class, rr_type;
917                 size_t len;
918                 int labs;
919                 if(!get_rr_nameclass(p->str, &rr_name, &rr_class, &rr_type)) {
920                         log_err("Bad local-data RR %s", p->str);
921                         return 0;
922                 }
923                 labs = dname_count_size_labels(rr_name, &len);
924                 lock_rw_rdlock(&zones->lock);
925                 if(!local_zones_lookup(zones, rr_name, len, labs, rr_class,
926                         rr_type)) {
927                         if(!have_name) {
928                                 dclass = rr_class;
929                                 nm = rr_name;
930                                 nmlen = len;
931                                 nmlabs = labs;
932                                 match = labs;
933                                 have_name = 1;
934                         } else {
935                                 int m;
936                                 if(rr_class != dclass) {
937                                         /* process other classes later */
938                                         free(rr_name);
939                                         have_other_classes = 1;
940                                         lock_rw_unlock(&zones->lock);
941                                         continue;
942                                 }
943                                 /* find smallest shared topdomain */
944                                 (void)dname_lab_cmp(nm, nmlabs, 
945                                         rr_name, labs, &m);
946                                 free(rr_name);
947                                 if(m < match)
948                                         match = m;
949                         }
950                 } else free(rr_name);
951                 lock_rw_unlock(&zones->lock);
952         }
953         if(have_name) {
954                 uint8_t* n2;
955                 struct local_zone* z;
956                 /* allocate zone of smallest shared topdomain to contain em */
957                 n2 = nm;
958                 dname_remove_labels(&n2, &nmlen, nmlabs - match);
959                 n2 = memdup(n2, nmlen);
960                 free(nm);
961                 if(!n2) {
962                         log_err("out of memory");
963                         return 0;
964                 }
965                 log_nametypeclass(VERB_ALGO, "implicit transparent local-zone", 
966                         n2, 0, dclass);
967                 if(!(z=lz_enter_zone_dname(zones, n2, nmlen, match, 
968                         local_zone_transparent, dclass))) {
969                         return 0;
970                 }
971                 lock_rw_unlock(&z->lock);
972         }
973         if(have_other_classes) { 
974                 /* restart to setup other class */
975                 return lz_setup_implicit(zones, cfg);
976         }
977         return 1;
978 }
979
980 /** enter local-zone-tag info */
981 static int
982 lz_enter_zone_tags(struct local_zones* zones, struct config_file* cfg)
983 {
984         struct config_strbytelist* p;
985         int c = 0;
986         for(p = cfg->local_zone_tags; p; p = p->next) {
987                 if(!lz_enter_zone_tag(zones, p->str, p->str2, p->str2len,
988                         LDNS_RR_CLASS_IN))
989                         return 0;
990                 c++;
991         }
992         if(c) verbose(VERB_ALGO, "applied tags to %d local zones", c);
993         return 1;
994 }
995         
996 /** enter auth data */
997 static int
998 lz_enter_data(struct local_zones* zones, struct config_file* cfg)
999 {
1000         struct config_strlist* p;
1001         for(p = cfg->local_data; p; p = p->next) {
1002                 if(!lz_enter_rr_str(zones, p->str))
1003                         return 0;
1004         }
1005         return 1;
1006 }
1007
1008 /** free memory from config */
1009 static void
1010 lz_freeup_cfg(struct config_file* cfg)
1011 {
1012         config_deldblstrlist(cfg->local_zones);
1013         cfg->local_zones = NULL;
1014         config_delstrlist(cfg->local_zones_nodefault);
1015         cfg->local_zones_nodefault = NULL;
1016         config_delstrlist(cfg->local_data);
1017         cfg->local_data = NULL;
1018 }
1019
1020 int 
1021 local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
1022 {
1023         /* create zones from zone statements. */
1024         if(!lz_enter_zones(zones, cfg)) {
1025                 return 0;
1026         }
1027         /* apply default zones+content (unless disabled, or overridden) */
1028         if(!local_zone_enter_defaults(zones, cfg)) {
1029                 return 0;
1030         }
1031         /* enter local zone overrides */
1032         if(!lz_enter_overrides(zones, cfg)) {
1033                 return 0;
1034         }
1035         /* create implicit transparent zone from data. */
1036         if(!lz_setup_implicit(zones, cfg)) {
1037                 return 0;
1038         }
1039
1040         /* setup parent ptrs for lookup during data entry */
1041         init_parents(zones);
1042         /* insert local zone tags */
1043         if(!lz_enter_zone_tags(zones, cfg)) {
1044                 return 0;
1045         }
1046         /* insert local data */
1047         if(!lz_enter_data(zones, cfg)) {
1048                 return 0;
1049         }
1050         /* freeup memory from cfg struct. */
1051         lz_freeup_cfg(cfg);
1052         return 1;
1053 }
1054
1055 struct local_zone* 
1056 local_zones_lookup(struct local_zones* zones,
1057         uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype)
1058 {
1059         return local_zones_tags_lookup(zones, name, len, labs,
1060                 dclass, dtype, NULL, 0, 1);
1061 }
1062
1063 struct local_zone* 
1064 local_zones_tags_lookup(struct local_zones* zones,
1065         uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
1066         uint8_t* taglist, size_t taglen, int ignoretags)
1067 {
1068         rbnode_type* res = NULL;
1069         struct local_zone *result;
1070         struct local_zone key;
1071         int m;
1072         /* for type DS use a zone higher when on a zonecut */
1073         if(dtype == LDNS_RR_TYPE_DS && !dname_is_root(name)) {
1074                 dname_remove_label(&name, &len);
1075                 labs--;
1076         }
1077         key.node.key = &key;
1078         key.dclass = dclass;
1079         key.name = name;
1080         key.namelen = len;
1081         key.namelabs = labs;
1082         rbtree_find_less_equal(&zones->ztree, &key, &res);
1083         result = (struct local_zone*)res;
1084         /* exact or smaller element (or no element) */
1085         if(!result || result->dclass != dclass)
1086                 return NULL;
1087         /* count number of labels matched */
1088         (void)dname_lab_cmp(result->name, result->namelabs, key.name,
1089                 key.namelabs, &m);
1090         while(result) { /* go up until qname is zone or subdomain of zone */
1091                 if(result->namelabs <= m)
1092                         if(ignoretags || !result->taglist ||
1093                                 taglist_intersect(result->taglist, 
1094                                 result->taglen, taglist, taglen))
1095                                 break;
1096                 result = result->parent;
1097         }
1098         return result;
1099 }
1100
1101 struct local_zone* 
1102 local_zones_find(struct local_zones* zones,
1103         uint8_t* name, size_t len, int labs, uint16_t dclass)
1104 {
1105         struct local_zone key;
1106         key.node.key = &key;
1107         key.dclass = dclass;
1108         key.name = name;
1109         key.namelen = len;
1110         key.namelabs = labs;
1111         /* exact */
1112         return (struct local_zone*)rbtree_search(&zones->ztree, &key);
1113 }
1114
1115 /** print all RRsets in local zone */
1116 static void 
1117 local_zone_out(struct local_zone* z)
1118 {
1119         struct local_data* d;
1120         struct local_rrset* p;
1121         RBTREE_FOR(d, struct local_data*, &z->data) {
1122                 for(p = d->rrsets; p; p = p->next) {
1123                         log_nametypeclass(0, "rrset", d->name, 
1124                                 ntohs(p->rrset->rk.type),
1125                                 ntohs(p->rrset->rk.rrset_class));
1126                 }
1127         }
1128 }
1129
1130 void local_zones_print(struct local_zones* zones)
1131 {
1132         struct local_zone* z;
1133         lock_rw_rdlock(&zones->lock);
1134         log_info("number of auth zones %u", (unsigned)zones->ztree.count);
1135         RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
1136                 lock_rw_rdlock(&z->lock);
1137                 switch(z->type) {
1138                 case local_zone_deny:
1139                         log_nametypeclass(0, "deny zone", 
1140                                 z->name, 0, z->dclass);
1141                         break;
1142                 case local_zone_refuse:
1143                         log_nametypeclass(0, "refuse zone", 
1144                                 z->name, 0, z->dclass);
1145                         break;
1146                 case local_zone_redirect:
1147                         log_nametypeclass(0, "redirect zone", 
1148                                 z->name, 0, z->dclass);
1149                         break;
1150                 case local_zone_transparent:
1151                         log_nametypeclass(0, "transparent zone", 
1152                                 z->name, 0, z->dclass);
1153                         break;
1154                 case local_zone_typetransparent:
1155                         log_nametypeclass(0, "typetransparent zone", 
1156                                 z->name, 0, z->dclass);
1157                         break;
1158                 case local_zone_static:
1159                         log_nametypeclass(0, "static zone", 
1160                                 z->name, 0, z->dclass);
1161                         break;
1162                 case local_zone_inform:
1163                         log_nametypeclass(0, "inform zone", 
1164                                 z->name, 0, z->dclass);
1165                         break;
1166                 case local_zone_inform_deny:
1167                         log_nametypeclass(0, "inform_deny zone", 
1168                                 z->name, 0, z->dclass);
1169                         break;
1170                 case local_zone_always_transparent:
1171                         log_nametypeclass(0, "always_transparent zone", 
1172                                 z->name, 0, z->dclass);
1173                         break;
1174                 case local_zone_always_refuse:
1175                         log_nametypeclass(0, "always_refuse zone", 
1176                                 z->name, 0, z->dclass);
1177                         break;
1178                 case local_zone_always_nxdomain:
1179                         log_nametypeclass(0, "always_nxdomain zone", 
1180                                 z->name, 0, z->dclass);
1181                         break;
1182                 default:
1183                         log_nametypeclass(0, "badtyped zone", 
1184                                 z->name, 0, z->dclass);
1185                         break;
1186                 }
1187                 local_zone_out(z);
1188                 lock_rw_unlock(&z->lock);
1189         }
1190         lock_rw_unlock(&zones->lock);
1191 }
1192
1193 /** encode answer consisting of 1 rrset */
1194 static int
1195 local_encode(struct query_info* qinfo, struct module_env* env,
1196         struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
1197         struct ub_packed_rrset_key* rrset, int ansec, int rcode)
1198 {
1199         struct reply_info rep;
1200         uint16_t udpsize;
1201         /* make answer with time=0 for fixed TTL values */
1202         memset(&rep, 0, sizeof(rep));
1203         rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
1204         rep.qdcount = 1;
1205         if(ansec)
1206                 rep.an_numrrsets = 1;
1207         else    rep.ns_numrrsets = 1;
1208         rep.rrset_count = 1;
1209         rep.rrsets = &rrset;
1210         udpsize = edns->udp_size;
1211         edns->edns_version = EDNS_ADVERTISED_VERSION;
1212         edns->udp_size = EDNS_ADVERTISED_SIZE;
1213         edns->ext_rcode = 0;
1214         edns->bits &= EDNS_DO;
1215         if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, temp)
1216                 || !reply_info_answer_encode(qinfo, &rep,
1217                 *(uint16_t*)sldns_buffer_begin(buf),
1218                 sldns_buffer_read_u16_at(buf, 2),
1219                 buf, 0, 0, temp, udpsize, edns,
1220                 (int)(edns->bits&EDNS_DO), 0))
1221                 error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
1222                         *(uint16_t*)sldns_buffer_begin(buf),
1223                         sldns_buffer_read_u16_at(buf, 2), edns);
1224         return 1;
1225 }
1226
1227 /** encode local error answer */
1228 static void
1229 local_error_encode(struct query_info* qinfo, struct module_env* env,
1230         struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
1231         int rcode, int r)
1232 {
1233         edns->edns_version = EDNS_ADVERTISED_VERSION;
1234         edns->udp_size = EDNS_ADVERTISED_SIZE;
1235         edns->ext_rcode = 0;
1236         edns->bits &= EDNS_DO;
1237
1238         if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
1239                 rcode, edns, temp))
1240                 edns->opt_list = NULL;
1241         error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
1242                 sldns_buffer_read_u16_at(buf, 2), edns);
1243 }
1244
1245 /** find local data tag string match for the given type in the list */
1246 int
1247 local_data_find_tag_datas(const struct query_info* qinfo,
1248         struct config_strlist* list, struct ub_packed_rrset_key* r,
1249         struct regional* temp)
1250 {
1251         struct config_strlist* p;
1252         char buf[65536];
1253         uint8_t rr[LDNS_RR_BUF_SIZE];
1254         size_t len;
1255         int res;
1256         struct packed_rrset_data* d;
1257         for(p=list; p; p=p->next) {
1258                 uint16_t rdr_type;
1259
1260                 len = sizeof(rr);
1261                 /* does this element match the type? */
1262                 snprintf(buf, sizeof(buf), ". %s", p->str);
1263                 res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600,
1264                         NULL, 0, NULL, 0);
1265                 if(res != 0)
1266                         /* parse errors are already checked before, in
1267                          * acllist check_data, skip this for robustness */
1268                         continue;
1269                 if(len < 1 /* . */ + 8 /* typeclassttl*/ + 2 /*rdatalen*/)
1270                         continue;
1271                 rdr_type = sldns_wirerr_get_type(rr, len, 1);
1272                 if(rdr_type != qinfo->qtype && rdr_type != LDNS_RR_TYPE_CNAME)
1273                         continue;
1274                 
1275                 /* do we have entries already? if not setup key */
1276                 if(r->rk.dname == NULL) {
1277                         r->entry.key = r;
1278                         r->rk.dname = qinfo->qname;
1279                         r->rk.dname_len = qinfo->qname_len;
1280                         r->rk.type = htons(rdr_type);
1281                         r->rk.rrset_class = htons(qinfo->qclass);
1282                         r->rk.flags = 0;
1283                         d = (struct packed_rrset_data*)regional_alloc_zero(
1284                                 temp, sizeof(struct packed_rrset_data)
1285                                 + sizeof(size_t) + sizeof(uint8_t*) +
1286                                 sizeof(time_t));
1287                         if(!d) return 0; /* out of memory */
1288                         r->entry.data = d;
1289                         d->ttl = sldns_wirerr_get_ttl(rr, len, 1);
1290                         d->rr_len = (size_t*)((uint8_t*)d +
1291                                 sizeof(struct packed_rrset_data));
1292                         d->rr_data = (uint8_t**)&(d->rr_len[1]);
1293                         d->rr_ttl = (time_t*)&(d->rr_data[1]);
1294                 }
1295                 d = (struct packed_rrset_data*)r->entry.data;
1296                 /* add entry to the data */
1297                 if(d->count != 0) {
1298                         size_t* oldlen = d->rr_len;
1299                         uint8_t** olddata = d->rr_data;
1300                         time_t* oldttl = d->rr_ttl;
1301                         /* increase arrays for lookup */
1302                         /* this is of course slow for very many records,
1303                          * but most redirects are expected with few records */
1304                         d->rr_len = (size_t*)regional_alloc_zero(temp,
1305                                 (d->count+1)*sizeof(size_t));
1306                         d->rr_data = (uint8_t**)regional_alloc_zero(temp,
1307                                 (d->count+1)*sizeof(uint8_t*));
1308                         d->rr_ttl = (time_t*)regional_alloc_zero(temp,
1309                                 (d->count+1)*sizeof(time_t));
1310                         if(!d->rr_len || !d->rr_data || !d->rr_ttl)
1311                                 return 0; /* out of memory */
1312                         /* first one was allocated after struct d, but new
1313                          * ones get their own array increment alloc, so
1314                          * copy old content */
1315                         memmove(d->rr_len, oldlen, d->count*sizeof(size_t));
1316                         memmove(d->rr_data, olddata, d->count*sizeof(uint8_t*));
1317                         memmove(d->rr_ttl, oldttl, d->count*sizeof(time_t));
1318                 }
1319
1320                 d->rr_len[d->count] = sldns_wirerr_get_rdatalen(rr, len, 1)+2;
1321                 d->rr_ttl[d->count] = sldns_wirerr_get_ttl(rr, len, 1);
1322                 d->rr_data[d->count] = regional_alloc_init(temp,
1323                         sldns_wirerr_get_rdatawl(rr, len, 1),
1324                         d->rr_len[d->count]);
1325                 if(!d->rr_data[d->count])
1326                         return 0; /* out of memory */
1327                 d->count++;
1328         }
1329         if(r->rk.dname)
1330                 return 1;
1331         return 0;
1332 }
1333
1334 static int
1335 find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
1336         struct ub_packed_rrset_key* r, struct regional* temp)
1337 {
1338         int result = local_data_find_tag_datas(qinfo, list, r, temp);
1339
1340         /* If we've found a non-exact alias type of local data, make a shallow
1341          * copy of the RRset and remember it in qinfo to complete the alias
1342          * chain later. */
1343         if(result && qinfo->qtype != LDNS_RR_TYPE_CNAME &&
1344                 r->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
1345                 qinfo->local_alias =
1346                         regional_alloc_zero(temp, sizeof(struct local_rrset));
1347                 if(!qinfo->local_alias)
1348                         return 0; /* out of memory */
1349                 qinfo->local_alias->rrset =
1350                         regional_alloc_init(temp, r, sizeof(*r));
1351                 if(!qinfo->local_alias->rrset)
1352                         return 0; /* out of memory */
1353         }
1354         return result;
1355 }
1356
1357 /** answer local data match */
1358 static int
1359 local_data_answer(struct local_zone* z, struct module_env* env,
1360         struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
1361         struct regional* temp, int labs, struct local_data** ldp,
1362         enum localzone_type lz_type, int tag, struct config_strlist** tag_datas,
1363         size_t tag_datas_size, char** tagname, int num_tags)
1364 {
1365         struct local_data key;
1366         struct local_data* ld;
1367         struct local_rrset* lr;
1368         key.node.key = &key;
1369         key.name = qinfo->qname;
1370         key.namelen = qinfo->qname_len;
1371         key.namelabs = labs;
1372         if(lz_type == local_zone_redirect) {
1373                 key.name = z->name;
1374                 key.namelen = z->namelen;
1375                 key.namelabs = z->namelabs;
1376                 if(tag != -1 && (size_t)tag<tag_datas_size && tag_datas[tag]) {
1377                         struct ub_packed_rrset_key r;
1378                         memset(&r, 0, sizeof(r));
1379                         if(find_tag_datas(qinfo, tag_datas[tag], &r, temp)) {
1380                                 verbose(VERB_ALGO, "redirect with tag data [%d] %s",
1381                                         tag, (tag<num_tags?tagname[tag]:"null"));
1382
1383                                 /* If we found a matching alias, we should
1384                                  * use it as part of the answer, but we can't
1385                                  * encode it until we complete the alias
1386                                  * chain. */
1387                                 if(qinfo->local_alias)
1388                                         return 1;
1389                                 return local_encode(qinfo, env, edns, buf, temp,
1390                                         &r, 1, LDNS_RCODE_NOERROR);
1391                         }
1392                 }
1393         }
1394         ld = (struct local_data*)rbtree_search(&z->data, &key.node);
1395         *ldp = ld;
1396         if(!ld) {
1397                 return 0;
1398         }
1399         lr = local_data_find_type(ld, qinfo->qtype, 1);
1400         if(!lr)
1401                 return 0;
1402
1403         /* Special case for alias matching.  See local_data_answer(). */
1404         if(lz_type == local_zone_redirect &&
1405                 qinfo->qtype != LDNS_RR_TYPE_CNAME &&
1406                 lr->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
1407                 qinfo->local_alias =
1408                         regional_alloc_zero(temp, sizeof(struct local_rrset));
1409                 if(!qinfo->local_alias)
1410                         return 0; /* out of memory */
1411                 qinfo->local_alias->rrset =
1412                         regional_alloc_init(temp, lr->rrset, sizeof(*lr->rrset));
1413                 if(!qinfo->local_alias->rrset)
1414                         return 0; /* out of memory */
1415                 qinfo->local_alias->rrset->rk.dname = qinfo->qname;
1416                 qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
1417                 return 1;
1418         }
1419         if(lz_type == local_zone_redirect) {
1420                 /* convert rrset name to query name; like a wildcard */
1421                 struct ub_packed_rrset_key r = *lr->rrset;
1422                 r.rk.dname = qinfo->qname;
1423                 r.rk.dname_len = qinfo->qname_len;
1424                 return local_encode(qinfo, env, edns, buf, temp, &r, 1, 
1425                         LDNS_RCODE_NOERROR);
1426         }
1427         return local_encode(qinfo, env, edns, buf, temp, lr->rrset, 1, 
1428                 LDNS_RCODE_NOERROR);
1429 }
1430
1431 /** 
1432  * answer in case where no exact match is found 
1433  * @param z: zone for query
1434  * @param env: module environment
1435  * @param qinfo: query
1436  * @param edns: edns from query
1437  * @param buf: buffer for answer.
1438  * @param temp: temp region for encoding
1439  * @param ld: local data, if NULL, no such name exists in localdata.
1440  * @param lz_type: type of the local zone
1441  * @return 1 if a reply is to be sent, 0 if not.
1442  */
1443 static int
1444 lz_zone_answer(struct local_zone* z, struct module_env* env,
1445         struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
1446         struct regional* temp, struct local_data* ld, enum localzone_type lz_type)
1447 {
1448         if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
1449                 /** no reply at all, signal caller by clearing buffer. */
1450                 sldns_buffer_clear(buf);
1451                 sldns_buffer_flip(buf);
1452                 return 1;
1453         } else if(lz_type == local_zone_refuse
1454                 || lz_type == local_zone_always_refuse) {
1455                 local_error_encode(qinfo, env, edns, buf, temp,
1456                         LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA));
1457                 return 1;
1458         } else if(lz_type == local_zone_static ||
1459                 lz_type == local_zone_redirect ||
1460                 lz_type == local_zone_always_nxdomain) {
1461                 /* for static, reply nodata or nxdomain
1462                  * for redirect, reply nodata */
1463                 /* no additional section processing,
1464                  * cname, dname or wildcard processing,
1465                  * or using closest match for NSEC.
1466                  * or using closest match for returning delegation downwards
1467                  */
1468                 int rcode = (ld || lz_type == local_zone_redirect)?
1469                         LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
1470                 if(z->soa)
1471                         return local_encode(qinfo, env, edns, buf, temp, 
1472                                 z->soa, 0, rcode);
1473                 local_error_encode(qinfo, env, edns, buf, temp, rcode,
1474                         (rcode|BIT_AA));
1475                 return 1;
1476         } else if(lz_type == local_zone_typetransparent
1477                 || lz_type == local_zone_always_transparent) {
1478                 /* no NODATA or NXDOMAINS for this zone type */
1479                 return 0;
1480         }
1481         /* else lz_type == local_zone_transparent */
1482
1483         /* if the zone is transparent and the name exists, but the type
1484          * does not, then we should make this noerror/nodata */
1485         if(ld && ld->rrsets) {
1486                 int rcode = LDNS_RCODE_NOERROR;
1487                 if(z->soa)
1488                         return local_encode(qinfo, env, edns, buf, temp, 
1489                                 z->soa, 0, rcode);
1490                 local_error_encode(qinfo, env, edns, buf, temp, rcode,
1491                         (rcode|BIT_AA));
1492                 return 1;
1493         }
1494
1495         /* stop here, and resolve further on */
1496         return 0;
1497 }
1498
1499 /** print log information for an inform zone query */
1500 static void
1501 lz_inform_print(struct local_zone* z, struct query_info* qinfo,
1502         struct comm_reply* repinfo)
1503 {
1504         char ip[128], txt[512];
1505         char zname[LDNS_MAX_DOMAINLEN+1];
1506         uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
1507         dname_str(z->name, zname);
1508         addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
1509         snprintf(txt, sizeof(txt), "%s inform %s@%u", zname, ip,
1510                 (unsigned)port);
1511         log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
1512 }
1513
1514 static enum localzone_type
1515 lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
1516         uint8_t *tagactions, size_t tagactionssize, enum localzone_type lzt,
1517         struct comm_reply* repinfo, struct rbtree_type* override_tree,
1518         int* tag, char** tagname, int num_tags)
1519 {
1520         struct local_zone_override* lzo;        
1521         if(repinfo && override_tree) {
1522                 lzo = (struct local_zone_override*)addr_tree_lookup(
1523                         override_tree, &repinfo->addr, repinfo->addrlen);
1524                 if(lzo && lzo->type) {
1525                         verbose(VERB_ALGO, "local zone override to type %s",
1526                                 local_zone_type2str(lzo->type));
1527                         return lzo->type;
1528                 }
1529         }
1530         if(!taglist || !taglist2)
1531                 return lzt;
1532         return local_data_find_tag_action(taglist, taglen, taglist2, taglen2,
1533                 tagactions, tagactionssize, lzt, tag, tagname, num_tags);
1534 }
1535
1536 enum localzone_type
1537 local_data_find_tag_action(const uint8_t* taglist, size_t taglen,
1538         const uint8_t* taglist2, size_t taglen2, const uint8_t* tagactions,
1539         size_t tagactionssize, enum localzone_type lzt, int* tag,
1540         char* const* tagname, int num_tags)
1541 {
1542         size_t i, j;
1543         uint8_t tagmatch;
1544
1545         for(i=0; i<taglen && i<taglen2; i++) {
1546                 tagmatch = (taglist[i] & taglist2[i]);
1547                 for(j=0; j<8 && tagmatch>0; j++) {
1548                         if((tagmatch & 0x1)) {
1549                                 *tag = (int)(i*8+j);
1550                                 verbose(VERB_ALGO, "matched tag [%d] %s",
1551                                         *tag, (*tag<num_tags?tagname[*tag]:"null"));
1552                                 /* does this tag have a tag action? */
1553                                 if(i*8+j < tagactionssize && tagactions
1554                                    && tagactions[i*8+j] != 0) {
1555                                   verbose(VERB_ALGO, "tag action [%d] %s to type %s",
1556                                         *tag, (*tag<num_tags?tagname[*tag]:"null"),
1557                                         local_zone_type2str(
1558                                         (enum localzone_type)
1559                                         tagactions[i*8+j]));
1560                                   return (enum localzone_type)tagactions[i*8+j];
1561                                 }
1562                                 return lzt;
1563                         }
1564                         tagmatch >>= 1; 
1565                 }
1566         }
1567         return lzt;
1568 }
1569
1570 int 
1571 local_zones_answer(struct local_zones* zones, struct module_env* env,
1572         struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
1573         struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
1574         size_t taglen, uint8_t* tagactions, size_t tagactionssize,
1575         struct config_strlist** tag_datas, size_t tag_datas_size,
1576         char** tagname, int num_tags, struct view* view)
1577 {
1578         /* see if query is covered by a zone,
1579          *      if so:  - try to match (exact) local data 
1580          *              - look at zone type for negative response. */
1581         int labs = dname_count_labels(qinfo->qname);
1582         struct local_data* ld = NULL;
1583         struct local_zone* z = NULL;
1584         enum localzone_type lzt = local_zone_transparent;
1585         int r, tag = -1;
1586
1587         if(view) {
1588                 lock_rw_rdlock(&view->lock);
1589                 if(view->local_zones &&
1590                         (z = local_zones_lookup(view->local_zones,
1591                         qinfo->qname, qinfo->qname_len, labs,
1592                         qinfo->qclass, qinfo->qtype))) {
1593                         verbose(VERB_ALGO, 
1594                                 "using localzone from view: %s", 
1595                                 view->name);
1596                         lock_rw_rdlock(&z->lock);
1597                         lzt = z->type;
1598                 }
1599                 if(view->local_zones && !z && !view->isfirst){
1600                         lock_rw_unlock(&view->lock);
1601                         return 0;
1602                 }
1603                 lock_rw_unlock(&view->lock);
1604         }
1605         if(!z) {
1606                 /* try global local_zones tree */
1607                 lock_rw_rdlock(&zones->lock);
1608                 if(!(z = local_zones_tags_lookup(zones, qinfo->qname,
1609                         qinfo->qname_len, labs, qinfo->qclass, qinfo->qtype,
1610                         taglist, taglen, 0))) {
1611                         lock_rw_unlock(&zones->lock);
1612                         return 0;
1613                 }
1614                 lock_rw_rdlock(&z->lock);
1615
1616                 lzt = lz_type(taglist, taglen, z->taglist, z->taglen,
1617                         tagactions, tagactionssize, z->type, repinfo,
1618                         z->override_tree, &tag, tagname, num_tags);
1619                 lock_rw_unlock(&zones->lock);
1620         }
1621         if((lzt == local_zone_inform || lzt == local_zone_inform_deny)
1622                 && repinfo)
1623                 lz_inform_print(z, qinfo, repinfo);
1624
1625         if(lzt != local_zone_always_refuse
1626                 && lzt != local_zone_always_transparent
1627                 && lzt != local_zone_always_nxdomain
1628                 && local_data_answer(z, env, qinfo, edns, buf, temp, labs, &ld, lzt,
1629                         tag, tag_datas, tag_datas_size, tagname, num_tags)) {
1630                 lock_rw_unlock(&z->lock);
1631                 /* We should tell the caller that encode is deferred if we found
1632                  * a local alias. */
1633                 return !qinfo->local_alias;
1634         }
1635         r = lz_zone_answer(z, env, qinfo, edns, buf, temp, ld, lzt);
1636         lock_rw_unlock(&z->lock);
1637         return r && !qinfo->local_alias; /* see above */
1638 }
1639
1640 const char* local_zone_type2str(enum localzone_type t)
1641 {
1642         switch(t) {
1643                 case local_zone_unset: return "unset";
1644                 case local_zone_deny: return "deny";
1645                 case local_zone_refuse: return "refuse";
1646                 case local_zone_redirect: return "redirect";
1647                 case local_zone_transparent: return "transparent";
1648                 case local_zone_typetransparent: return "typetransparent";
1649                 case local_zone_static: return "static";
1650                 case local_zone_nodefault: return "nodefault";
1651                 case local_zone_inform: return "inform";
1652                 case local_zone_inform_deny: return "inform_deny";
1653                 case local_zone_always_transparent: return "always_transparent";
1654                 case local_zone_always_refuse: return "always_refuse";
1655                 case local_zone_always_nxdomain: return "always_nxdomain";
1656         }
1657         return "badtyped"; 
1658 }
1659
1660 int local_zone_str2type(const char* type, enum localzone_type* t)
1661 {
1662         if(strcmp(type, "deny") == 0)
1663                 *t = local_zone_deny;
1664         else if(strcmp(type, "refuse") == 0)
1665                 *t = local_zone_refuse;
1666         else if(strcmp(type, "static") == 0)
1667                 *t = local_zone_static;
1668         else if(strcmp(type, "transparent") == 0)
1669                 *t = local_zone_transparent;
1670         else if(strcmp(type, "typetransparent") == 0)
1671                 *t = local_zone_typetransparent;
1672         else if(strcmp(type, "redirect") == 0)
1673                 *t = local_zone_redirect;
1674         else if(strcmp(type, "inform") == 0)
1675                 *t = local_zone_inform;
1676         else if(strcmp(type, "inform_deny") == 0)
1677                 *t = local_zone_inform_deny;
1678         else if(strcmp(type, "always_transparent") == 0)
1679                 *t = local_zone_always_transparent;
1680         else if(strcmp(type, "always_refuse") == 0)
1681                 *t = local_zone_always_refuse;
1682         else if(strcmp(type, "always_nxdomain") == 0)
1683                 *t = local_zone_always_nxdomain;
1684         else if(strcmp(type, "nodefault") == 0)
1685                 *t = local_zone_nodefault;
1686         else return 0;
1687         return 1;
1688 }
1689
1690 /** iterate over the kiddies of the given name and set their parent ptr */
1691 static void
1692 set_kiddo_parents(struct local_zone* z, struct local_zone* match, 
1693         struct local_zone* newp)
1694 {
1695         /* both zones and z are locked already */
1696         /* in the sorted rbtree, the kiddies of z are located after z */
1697         /* z must be present in the tree */
1698         struct local_zone* p = z;
1699         p = (struct local_zone*)rbtree_next(&p->node);
1700         while(p!=(struct local_zone*)RBTREE_NULL &&
1701                 p->dclass == z->dclass && dname_strict_subdomain(p->name,
1702                 p->namelabs, z->name, z->namelabs)) {
1703                 /* update parent ptr */
1704                 /* only when matches with existing parent pointer, so that
1705                  * deeper child structures are not touched, i.e.
1706                  * update of x, and a.x, b.x, f.b.x, g.b.x, c.x, y
1707                  * gets to update a.x, b.x and c.x */
1708                 lock_rw_wrlock(&p->lock);
1709                 if(p->parent == match)
1710                         p->parent = newp;
1711                 lock_rw_unlock(&p->lock);
1712                 p = (struct local_zone*)rbtree_next(&p->node);
1713         }
1714 }
1715
1716 struct local_zone* local_zones_add_zone(struct local_zones* zones,
1717         uint8_t* name, size_t len, int labs, uint16_t dclass,
1718         enum localzone_type tp)
1719 {
1720         /* create */
1721         struct local_zone* z = local_zone_create(name, len, labs, tp, dclass);
1722         if(!z) {
1723                 free(name);
1724                 return NULL;
1725         }
1726         lock_rw_wrlock(&z->lock);
1727
1728         /* find the closest parent */
1729         z->parent = local_zones_find(zones, name, len, labs, dclass);
1730
1731         /* insert into the tree */
1732         if(!rbtree_insert(&zones->ztree, &z->node)) {
1733                 /* duplicate entry! */
1734                 lock_rw_unlock(&z->lock);
1735                 local_zone_delete(z);
1736                 log_err("internal: duplicate entry in local_zones_add_zone");
1737                 return NULL;
1738         }
1739
1740         /* set parent pointers right */
1741         set_kiddo_parents(z, z->parent, z);
1742
1743         lock_rw_unlock(&z->lock);
1744         return z;
1745 }
1746
1747 void local_zones_del_zone(struct local_zones* zones, struct local_zone* z)
1748 {
1749         /* fix up parents in tree */
1750         lock_rw_wrlock(&z->lock);
1751         set_kiddo_parents(z, z, z->parent);
1752
1753         /* remove from tree */
1754         (void)rbtree_delete(&zones->ztree, z);
1755
1756         /* delete the zone */
1757         lock_rw_unlock(&z->lock);
1758         local_zone_delete(z);
1759 }
1760
1761 int
1762 local_zones_add_RR(struct local_zones* zones, const char* rr)
1763 {
1764         uint8_t* rr_name;
1765         uint16_t rr_class, rr_type;
1766         size_t len;
1767         int labs;
1768         struct local_zone* z;
1769         int r;
1770         if(!get_rr_nameclass(rr, &rr_name, &rr_class, &rr_type)) {
1771                 return 0;
1772         }
1773         labs = dname_count_size_labels(rr_name, &len);
1774         /* could first try readlock then get writelock if zone does not exist,
1775          * but we do not add enough RRs (from multiple threads) to optimize */
1776         lock_rw_wrlock(&zones->lock);
1777         z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
1778         if(!z) {
1779                 z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
1780                         local_zone_transparent);
1781                 if(!z) {
1782                         lock_rw_unlock(&zones->lock);
1783                         return 0;
1784                 }
1785         } else {
1786                 free(rr_name);
1787         }
1788         lock_rw_wrlock(&z->lock);
1789         lock_rw_unlock(&zones->lock);
1790         r = lz_enter_rr_into_zone(z, rr);
1791         lock_rw_unlock(&z->lock);
1792         return r;
1793 }
1794
1795 /** returns true if the node is terminal so no deeper domain names exist */
1796 static int
1797 is_terminal(struct local_data* d)
1798 {
1799         /* for empty nonterminals, the deeper domain names are sorted
1800          * right after them, so simply check the next name in the tree 
1801          */
1802         struct local_data* n = (struct local_data*)rbtree_next(&d->node);
1803         if(n == (struct local_data*)RBTREE_NULL)
1804                 return 1; /* last in tree, no deeper node */
1805         if(dname_strict_subdomain(n->name, n->namelabs, d->name, d->namelabs))
1806                 return 0; /* there is a deeper node */
1807         return 1;
1808 }
1809
1810 /** delete empty terminals from tree when final data is deleted */
1811 static void 
1812 del_empty_term(struct local_zone* z, struct local_data* d, 
1813         uint8_t* name, size_t len, int labs)
1814 {
1815         while(d && d->rrsets == NULL && is_terminal(d)) {
1816                 /* is this empty nonterminal? delete */
1817                 /* note, no memory recycling in zone region */
1818                 (void)rbtree_delete(&z->data, d);
1819
1820                 /* go up and to the next label */
1821                 if(dname_is_root(name))
1822                         return;
1823                 dname_remove_label(&name, &len);
1824                 labs--;
1825                 d = lz_find_node(z, name, len, labs);
1826         }
1827 }
1828
1829 /** find and remove type from list in domain struct */
1830 static void
1831 del_local_rrset(struct local_data* d, uint16_t dtype)
1832 {
1833         struct local_rrset* prev=NULL, *p=d->rrsets;
1834         while(p && ntohs(p->rrset->rk.type) != dtype) {
1835                 prev = p;
1836                 p = p->next;
1837         }
1838         if(!p) 
1839                 return; /* rrset type not found */
1840         /* unlink it */
1841         if(prev) prev->next = p->next;
1842         else d->rrsets = p->next;
1843         /* no memory recycling for zone deletions ... */
1844 }
1845
1846 void local_zones_del_data(struct local_zones* zones, 
1847         uint8_t* name, size_t len, int labs, uint16_t dclass)
1848 {
1849         /* find zone */
1850         struct local_zone* z;
1851         struct local_data* d;
1852
1853         /* remove DS */
1854         lock_rw_rdlock(&zones->lock);
1855         z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS);
1856         if(z) {
1857                 lock_rw_wrlock(&z->lock);
1858                 d = lz_find_node(z, name, len, labs);
1859                 if(d) {
1860                         del_local_rrset(d, LDNS_RR_TYPE_DS);
1861                         del_empty_term(z, d, name, len, labs);
1862                 }
1863                 lock_rw_unlock(&z->lock);
1864         }
1865         lock_rw_unlock(&zones->lock);
1866
1867         /* remove other types */
1868         lock_rw_rdlock(&zones->lock);
1869         z = local_zones_lookup(zones, name, len, labs, dclass, 0);
1870         if(!z) {
1871                 /* no such zone, we're done */
1872                 lock_rw_unlock(&zones->lock);
1873                 return;
1874         }
1875         lock_rw_wrlock(&z->lock);
1876         lock_rw_unlock(&zones->lock);
1877
1878         /* find the domain */
1879         d = lz_find_node(z, name, len, labs);
1880         if(d) {
1881                 /* no memory recycling for zone deletions ... */
1882                 d->rrsets = NULL;
1883                 /* did we delete the soa record ? */
1884                 if(query_dname_compare(d->name, z->name) == 0)
1885                         z->soa = NULL;
1886
1887                 /* cleanup the empty nonterminals for this name */
1888                 del_empty_term(z, d, name, len, labs);
1889         }
1890
1891         lock_rw_unlock(&z->lock);
1892 }