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