]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/unbound/services/localzone.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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 "ldns/str2wire.h"
44 #include "ldns/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
55 struct local_zones* 
56 local_zones_create(void)
57 {
58         struct local_zones* zones = (struct local_zones*)calloc(1, 
59                 sizeof(*zones));
60         if(!zones)
61                 return NULL;
62         rbtree_init(&zones->ztree, &local_zone_cmp);
63         lock_rw_init(&zones->lock);
64         lock_protect(&zones->lock, &zones->ztree, sizeof(zones->ztree));
65         /* also lock protects the rbnode's in struct local_zone */
66         return zones;
67 }
68
69 /** helper traverse to delete zones */
70 static void 
71 lzdel(rbnode_t* n, void* ATTR_UNUSED(arg))
72 {
73         struct local_zone* z = (struct local_zone*)n->key;
74         local_zone_delete(z);
75 }
76
77 void 
78 local_zones_delete(struct local_zones* zones)
79 {
80         if(!zones)
81                 return;
82         lock_rw_destroy(&zones->lock);
83         /* walk through zones and delete them all */
84         traverse_postorder(&zones->ztree, lzdel, NULL);
85         free(zones);
86 }
87
88 void 
89 local_zone_delete(struct local_zone* z)
90 {
91         if(!z)
92                 return;
93         lock_rw_destroy(&z->lock);
94         regional_destroy(z->region);
95         free(z->name);
96         free(z);
97 }
98
99 int 
100 local_zone_cmp(const void* z1, const void* z2)
101 {
102         /* first sort on class, so that hierarchy can be maintained within
103          * a class */
104         struct local_zone* a = (struct local_zone*)z1;
105         struct local_zone* b = (struct local_zone*)z2;
106         int m;
107         if(a->dclass != b->dclass) {
108                 if(a->dclass < b->dclass)
109                         return -1;
110                 return 1;
111         }
112         return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m);
113 }
114
115 int 
116 local_data_cmp(const void* d1, const void* d2)
117 {
118         struct local_data* a = (struct local_data*)d1;
119         struct local_data* b = (struct local_data*)d2;
120         int m;
121         return dname_canon_lab_cmp(a->name, a->namelabs, b->name, 
122                 b->namelabs, &m);
123 }
124
125 /* form wireformat from text format domain name */
126 int
127 parse_dname(const char* str, uint8_t** res, size_t* len, int* labs)
128 {
129         *res = sldns_str2wire_dname(str, len);
130         *labs = 0;
131         if(!*res) {
132                 log_err("cannot parse name %s", str);
133                 return 0;
134         }
135         *labs = dname_count_size_labels(*res, len);
136         return 1;
137 }
138
139 /** create a new localzone */
140 static struct local_zone*
141 local_zone_create(uint8_t* nm, size_t len, int labs, 
142         enum localzone_type t, uint16_t dclass)
143 {
144         struct local_zone* z = (struct local_zone*)calloc(1, sizeof(*z));
145         if(!z) {
146                 return NULL;
147         }
148         z->node.key = z;
149         z->dclass = dclass;
150         z->type = t;
151         z->name = nm;
152         z->namelen = len;
153         z->namelabs = labs;
154         lock_rw_init(&z->lock);
155         z->region = regional_create();
156         if(!z->region) {
157                 free(z);
158                 return NULL;
159         }
160         rbtree_init(&z->data, &local_data_cmp);
161         lock_protect(&z->lock, &z->parent, sizeof(*z)-sizeof(rbnode_t));
162         /* also the zones->lock protects node, parent, name*, class */
163         return z;
164 }
165
166 /** enter a new zone with allocated dname returns with WRlock */
167 static struct local_zone*
168 lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len, 
169         int labs, enum localzone_type t, uint16_t c)
170 {
171         struct local_zone* z = local_zone_create(nm, len, labs, t, c);
172         if(!z) {
173                 log_err("out of memory");
174                 return NULL;
175         }
176
177         /* add to rbtree */
178         lock_rw_wrlock(&zones->lock);
179         lock_rw_wrlock(&z->lock);
180         if(!rbtree_insert(&zones->ztree, &z->node)) {
181                 log_warn("duplicate local-zone");
182                 lock_rw_unlock(&z->lock);
183                 local_zone_delete(z);
184                 lock_rw_unlock(&zones->lock);
185                 return NULL;
186         }
187         lock_rw_unlock(&zones->lock);
188         return z;
189 }
190
191 /** enter a new zone */
192 static struct local_zone*
193 lz_enter_zone(struct local_zones* zones, const char* name, const char* type,
194         uint16_t dclass)
195 {
196         struct local_zone* z;
197         enum localzone_type t;
198         uint8_t* nm;
199         size_t len;
200         int labs;
201         if(!parse_dname(name, &nm, &len, &labs)) {
202                 log_err("bad zone name %s %s", name, type);
203                 return NULL;
204         }
205         if(!local_zone_str2type(type, &t)) {
206                 log_err("bad lz_enter_zone type %s %s", name, type);
207                 free(nm);
208                 return NULL;
209         }
210         if(!(z=lz_enter_zone_dname(zones, nm, len, labs, t, dclass))) {
211                 log_err("could not enter zone %s %s", name, type);
212                 return NULL;
213         }
214         return z;
215 }
216
217 /** return name and class and rdata of rr; parses string */
218 static int
219 get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
220         uint16_t* dclass, time_t* ttl, uint8_t* rr, size_t len,
221         uint8_t** rdata, size_t* rdata_len)
222 {
223         size_t dname_len = 0;
224         int e = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600,
225                 NULL, 0, NULL, 0);
226         if(e) {
227                 log_err("error parsing local-data at %d: '%s': %s",
228                         LDNS_WIREPARSE_OFFSET(e), str,
229                         sldns_get_errorstr_parse(e));
230                 return 0;
231         }
232         *nm = memdup(rr, dname_len);
233         if(!*nm) {
234                 log_err("out of memory");
235                 return 0;
236         }
237         *dclass = sldns_wirerr_get_class(rr, len, dname_len);
238         *type = sldns_wirerr_get_type(rr, len, dname_len);
239         *ttl = (time_t)sldns_wirerr_get_ttl(rr, len, dname_len);
240         *rdata = sldns_wirerr_get_rdatawl(rr, len, dname_len);
241         *rdata_len = sldns_wirerr_get_rdatalen(rr, len, dname_len)+2;
242         return 1;
243 }
244
245 /** return name and class of rr; parses string */
246 static int
247 get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass)
248 {
249         uint8_t rr[LDNS_RR_BUF_SIZE];
250         size_t len = sizeof(rr), dname_len = 0;
251         int s = sldns_str2wire_rr_buf(str, rr, &len, &dname_len, 3600,
252                 NULL, 0, NULL, 0);
253         if(s != 0) {
254                 log_err("error parsing local-data at %d '%s': %s",
255                         LDNS_WIREPARSE_OFFSET(s), str,
256                         sldns_get_errorstr_parse(s));
257                 return 0;
258         }
259         *nm = memdup(rr, dname_len);
260         *dclass = sldns_wirerr_get_class(rr, len, dname_len);
261         if(!*nm) {
262                 log_err("out of memory");
263                 return 0;
264         }
265         return 1;
266 }
267
268 /**
269  * Find an rrset in local data structure.
270  * @param data: local data domain name structure.
271  * @param type: type to look for (host order).
272  * @return rrset pointer or NULL if not found.
273  */
274 static struct local_rrset*
275 local_data_find_type(struct local_data* data, uint16_t type)
276 {
277         struct local_rrset* p;
278         type = htons(type);
279         for(p = data->rrsets; p; p = p->next) {
280                 if(p->rrset->rk.type == type)
281                         return p;
282         }
283         return NULL;
284 }
285
286 /** check for RR duplicates */
287 static int
288 rr_is_duplicate(struct packed_rrset_data* pd, uint8_t* rdata, size_t rdata_len)
289 {
290         size_t i;
291         for(i=0; i<pd->count; i++) {
292                 if(pd->rr_len[i] == rdata_len &&
293                         memcmp(pd->rr_data[i], rdata, rdata_len) == 0)
294                         return 1;
295         }
296         return 0;
297 }
298
299 /** new local_rrset */
300 static struct local_rrset*
301 new_local_rrset(struct regional* region, struct local_data* node,
302         uint16_t rrtype, uint16_t rrclass)
303 {
304         struct packed_rrset_data* pd;
305         struct local_rrset* rrset = (struct local_rrset*)
306                 regional_alloc_zero(region, sizeof(*rrset));
307         if(!rrset) {
308                 log_err("out of memory");
309                 return NULL;
310         }
311         rrset->next = node->rrsets;
312         node->rrsets = rrset;
313         rrset->rrset = (struct ub_packed_rrset_key*)
314                 regional_alloc_zero(region, sizeof(*rrset->rrset));
315         if(!rrset->rrset) {
316                 log_err("out of memory");
317                 return NULL;
318         }
319         rrset->rrset->entry.key = rrset->rrset;
320         pd = (struct packed_rrset_data*)regional_alloc_zero(region,
321                 sizeof(*pd));
322         if(!pd) {
323                 log_err("out of memory");
324                 return NULL;
325         }
326         pd->trust = rrset_trust_prim_noglue;
327         pd->security = sec_status_insecure;
328         rrset->rrset->entry.data = pd;
329         rrset->rrset->rk.dname = node->name;
330         rrset->rrset->rk.dname_len = node->namelen;
331         rrset->rrset->rk.type = htons(rrtype);
332         rrset->rrset->rk.rrset_class = htons(rrclass);
333         return rrset;
334 }
335
336 /** insert RR into RRset data structure; Wastes a couple of bytes */
337 static int
338 insert_rr(struct regional* region, struct packed_rrset_data* pd,
339         uint8_t* rdata, size_t rdata_len, time_t ttl)
340 {
341         size_t* oldlen = pd->rr_len;
342         time_t* oldttl = pd->rr_ttl;
343         uint8_t** olddata = pd->rr_data;
344
345         /* add RR to rrset */
346         pd->count++;
347         pd->rr_len = regional_alloc(region, sizeof(*pd->rr_len)*pd->count);
348         pd->rr_ttl = regional_alloc(region, sizeof(*pd->rr_ttl)*pd->count);
349         pd->rr_data = regional_alloc(region, sizeof(*pd->rr_data)*pd->count);
350         if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) {
351                 log_err("out of memory");
352                 return 0;
353         }
354         if(pd->count > 1) {
355                 memcpy(pd->rr_len+1, oldlen, 
356                         sizeof(*pd->rr_len)*(pd->count-1));
357                 memcpy(pd->rr_ttl+1, oldttl, 
358                         sizeof(*pd->rr_ttl)*(pd->count-1));
359                 memcpy(pd->rr_data+1, olddata, 
360                         sizeof(*pd->rr_data)*(pd->count-1));
361         }
362         pd->rr_len[0] = rdata_len;
363         pd->rr_ttl[0] = ttl;
364         pd->rr_data[0] = regional_alloc_init(region, rdata, rdata_len);
365         if(!pd->rr_data[0]) {
366                 log_err("out of memory");
367                 return 0;
368         }
369         return 1;
370 }
371
372 /** find a data node by exact name */
373 static struct local_data* 
374 lz_find_node(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs)
375 {
376         struct local_data key;
377         key.node.key = &key;
378         key.name = nm;
379         key.namelen = nmlen;
380         key.namelabs = nmlabs;
381         return (struct local_data*)rbtree_search(&z->data, &key.node);
382 }
383
384 /** find a node, create it if not and all its empty nonterminal parents */
385 static int
386 lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen, 
387         int nmlabs, struct local_data** res)
388 {
389         struct local_data* ld = lz_find_node(z, nm, nmlen, nmlabs);
390         if(!ld) {
391                 /* create a domain name to store rr. */
392                 ld = (struct local_data*)regional_alloc_zero(z->region,
393                         sizeof(*ld));
394                 if(!ld) {
395                         log_err("out of memory adding local data");
396                         return 0;
397                 }
398                 ld->node.key = ld;
399                 ld->name = regional_alloc_init(z->region, nm, nmlen);
400                 if(!ld->name) {
401                         log_err("out of memory");
402                         return 0;
403                 }
404                 ld->namelen = nmlen;
405                 ld->namelabs = nmlabs;
406                 if(!rbtree_insert(&z->data, &ld->node)) {
407                         log_assert(0); /* duplicate name */
408                 }
409                 /* see if empty nonterminals need to be created */
410                 if(nmlabs > z->namelabs) {
411                         dname_remove_label(&nm, &nmlen);
412                         if(!lz_find_create_node(z, nm, nmlen, nmlabs-1, res))
413                                 return 0;
414                 }
415         }
416         *res = ld;
417         return 1;
418 }
419
420 /** enter data RR into auth zone */
421 static int
422 lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
423 {
424         uint8_t* nm;
425         size_t nmlen;
426         int nmlabs;
427         struct local_data* node;
428         struct local_rrset* rrset;
429         struct packed_rrset_data* pd;
430         uint16_t rrtype = 0, rrclass = 0;
431         time_t ttl = 0;
432         uint8_t rr[LDNS_RR_BUF_SIZE];
433         uint8_t* rdata;
434         size_t rdata_len;
435         if(!get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr, sizeof(rr),
436                 &rdata, &rdata_len)) {
437                 log_err("bad local-data: %s", rrstr);
438                 return 0;
439         }
440         log_assert(z->dclass == rrclass);
441         if(z->type == local_zone_redirect &&
442                 query_dname_compare(z->name, nm) != 0) {
443                 log_err("local-data in redirect zone must reside at top of zone"
444                         ", not at %s", rrstr);
445                 free(nm);
446                 return 0;
447         }
448         nmlabs = dname_count_size_labels(nm, &nmlen);
449         if(!lz_find_create_node(z, nm, nmlen, nmlabs, &node)) {
450                 free(nm);
451                 return 0;
452         }
453         log_assert(node);
454         free(nm);
455
456         rrset = local_data_find_type(node, rrtype);
457         if(!rrset) {
458                 rrset = new_local_rrset(z->region, node, rrtype, rrclass);
459                 if(!rrset)
460                         return 0;
461                 if(query_dname_compare(node->name, z->name) == 0) {
462                         if(rrtype == LDNS_RR_TYPE_NSEC)
463                           rrset->rrset->rk.flags = PACKED_RRSET_NSEC_AT_APEX;
464                         if(rrtype == LDNS_RR_TYPE_SOA)
465                                 z->soa = rrset->rrset;
466                 }
467         } 
468         pd = (struct packed_rrset_data*)rrset->rrset->entry.data;
469         log_assert(rrset && pd);
470
471         /* check for duplicate RR */
472         if(rr_is_duplicate(pd, rdata, rdata_len)) {
473                 verbose(VERB_ALGO, "ignoring duplicate RR: %s", rrstr);
474                 return 1;
475         } 
476         return insert_rr(z->region, pd, rdata, rdata_len, ttl);
477 }
478
479 /** enter a data RR into auth data; a zone for it must exist */
480 static int
481 lz_enter_rr_str(struct local_zones* zones, const char* rr)
482 {
483         uint8_t* rr_name;
484         uint16_t rr_class;
485         size_t len;
486         int labs;
487         struct local_zone* z;
488         int r;
489         if(!get_rr_nameclass(rr, &rr_name, &rr_class)) {
490                 log_err("bad rr %s", rr);
491                 return 0;
492         }
493         labs = dname_count_size_labels(rr_name, &len);
494         lock_rw_rdlock(&zones->lock);
495         z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
496         if(!z) {
497                 lock_rw_unlock(&zones->lock);
498                 fatal_exit("internal error: no zone for rr %s", rr);
499         }
500         lock_rw_wrlock(&z->lock);
501         lock_rw_unlock(&zones->lock);
502         free(rr_name);
503         r = lz_enter_rr_into_zone(z, rr);
504         lock_rw_unlock(&z->lock);
505         return r;
506 }
507
508 /** parse local-zone: statements */
509 static int
510 lz_enter_zones(struct local_zones* zones, struct config_file* cfg)
511 {
512         struct config_str2list* p;
513         struct local_zone* z;
514         for(p = cfg->local_zones; p; p = p->next) {
515                 if(!(z=lz_enter_zone(zones, p->str, p->str2, 
516                         LDNS_RR_CLASS_IN)))
517                         return 0;
518                 lock_rw_unlock(&z->lock);
519         }
520         return 1;
521 }
522
523 /** lookup a zone in rbtree; exact match only; SLOW due to parse */
524 static int
525 lz_exists(struct local_zones* zones, const char* name)
526 {
527         struct local_zone z;
528         z.node.key = &z;
529         z.dclass = LDNS_RR_CLASS_IN;
530         if(!parse_dname(name, &z.name, &z.namelen, &z.namelabs)) {
531                 log_err("bad name %s", name);
532                 return 0;
533         }
534         lock_rw_rdlock(&zones->lock);
535         if(rbtree_search(&zones->ztree, &z.node)) {
536                 lock_rw_unlock(&zones->lock);
537                 free(z.name);
538                 return 1;
539         }
540         lock_rw_unlock(&zones->lock);
541         free(z.name);
542         return 0;
543 }
544
545 /** lookup a zone in cfg->nodefault list */
546 static int
547 lz_nodefault(struct config_file* cfg, const char* name)
548 {
549         struct config_strlist* p;
550         size_t len = strlen(name);
551         if(len == 0) return 0;
552         if(name[len-1] == '.') len--;
553
554         for(p = cfg->local_zones_nodefault; p; p = p->next) {
555                 /* compare zone name, lowercase, compare without ending . */
556                 if(strncasecmp(p->str, name, len) == 0 && 
557                         (strlen(p->str) == len || (strlen(p->str)==len+1 &&
558                         p->str[len] == '.')))
559                         return 1;
560         }
561         return 0;
562 }
563
564 /** enter AS112 default zone */
565 static int
566 add_as112_default(struct local_zones* zones, struct config_file* cfg,
567         const char* name)
568 {
569         struct local_zone* z;
570         char str[1024]; /* known long enough */
571         if(lz_exists(zones, name) || lz_nodefault(cfg, name))
572                 return 1; /* do not enter default content */
573         if(!(z=lz_enter_zone(zones, name, "static", LDNS_RR_CLASS_IN)))
574                 return 0;
575         snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. "
576                 "nobody.invalid. 1 3600 1200 604800 10800", name);
577         if(!lz_enter_rr_into_zone(z, str)) {
578                 lock_rw_unlock(&z->lock);
579                 return 0;
580         }
581         snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name);
582         if(!lz_enter_rr_into_zone(z, str)) {
583                 lock_rw_unlock(&z->lock);
584                 return 0;
585         }
586         lock_rw_unlock(&z->lock);
587         return 1;
588 }
589
590 /** enter default zones */
591 static int
592 lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
593 {
594         struct local_zone* z;
595
596         /* this list of zones is from RFC 6303 */
597
598         /* block localhost level zones, first, later the LAN zones */
599
600         /* localhost. zone */
601         if(!lz_exists(zones, "localhost.") &&
602                 !lz_nodefault(cfg, "localhost.")) {
603                 if(!(z=lz_enter_zone(zones, "localhost.", "static", 
604                         LDNS_RR_CLASS_IN)) ||
605                    !lz_enter_rr_into_zone(z,
606                         "localhost. 10800 IN NS localhost.") ||
607                    !lz_enter_rr_into_zone(z,
608                         "localhost. 10800 IN SOA localhost. nobody.invalid. "
609                         "1 3600 1200 604800 10800") ||
610                    !lz_enter_rr_into_zone(z,
611                         "localhost. 10800 IN A 127.0.0.1") ||
612                    !lz_enter_rr_into_zone(z,
613                         "localhost. 10800 IN AAAA ::1")) {
614                         log_err("out of memory adding default zone");
615                         if(z) { lock_rw_unlock(&z->lock); }
616                         return 0;
617                 }
618                 lock_rw_unlock(&z->lock);
619         }
620         /* reverse ip4 zone */
621         if(!lz_exists(zones, "127.in-addr.arpa.") &&
622                 !lz_nodefault(cfg, "127.in-addr.arpa.")) {
623                 if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static", 
624                         LDNS_RR_CLASS_IN)) ||
625                    !lz_enter_rr_into_zone(z,
626                         "127.in-addr.arpa. 10800 IN NS localhost.") ||
627                    !lz_enter_rr_into_zone(z,
628                         "127.in-addr.arpa. 10800 IN SOA localhost. "
629                         "nobody.invalid. 1 3600 1200 604800 10800") ||
630                    !lz_enter_rr_into_zone(z,
631                         "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
632                         log_err("out of memory adding default zone");
633                         if(z) { lock_rw_unlock(&z->lock); }
634                         return 0;
635                 }
636                 lock_rw_unlock(&z->lock);
637         }
638         /* reverse ip6 zone */
639         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.") &&
640                 !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.")) {
641                 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", 
642                         LDNS_RR_CLASS_IN)) ||
643                    !lz_enter_rr_into_zone(z,
644                         "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.") ||
645                    !lz_enter_rr_into_zone(z,
646                         "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. "
647                         "nobody.invalid. 1 3600 1200 604800 10800") ||
648                    !lz_enter_rr_into_zone(z,
649                         "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.")) {
650                         log_err("out of memory adding default zone");
651                         if(z) { lock_rw_unlock(&z->lock); }
652                         return 0;
653                 }
654                 lock_rw_unlock(&z->lock);
655         }
656
657         /* if unblock lan-zones, then do not add the zones below.
658          * we do add the zones above, about 127.0.0.1, because localhost is
659          * not on the lan. */
660         if(cfg->unblock_lan_zones)
661                 return 1;
662
663         /* block LAN level zones */
664         if (    !add_as112_default(zones, cfg, "10.in-addr.arpa.") ||
665                 !add_as112_default(zones, cfg, "16.172.in-addr.arpa.") ||
666                 !add_as112_default(zones, cfg, "17.172.in-addr.arpa.") ||
667                 !add_as112_default(zones, cfg, "18.172.in-addr.arpa.") ||
668                 !add_as112_default(zones, cfg, "19.172.in-addr.arpa.") ||
669                 !add_as112_default(zones, cfg, "20.172.in-addr.arpa.") ||
670                 !add_as112_default(zones, cfg, "21.172.in-addr.arpa.") ||
671                 !add_as112_default(zones, cfg, "22.172.in-addr.arpa.") ||
672                 !add_as112_default(zones, cfg, "23.172.in-addr.arpa.") ||
673                 !add_as112_default(zones, cfg, "24.172.in-addr.arpa.") ||
674                 !add_as112_default(zones, cfg, "25.172.in-addr.arpa.") ||
675                 !add_as112_default(zones, cfg, "26.172.in-addr.arpa.") ||
676                 !add_as112_default(zones, cfg, "27.172.in-addr.arpa.") ||
677                 !add_as112_default(zones, cfg, "28.172.in-addr.arpa.") ||
678                 !add_as112_default(zones, cfg, "29.172.in-addr.arpa.") ||
679                 !add_as112_default(zones, cfg, "30.172.in-addr.arpa.") ||
680                 !add_as112_default(zones, cfg, "31.172.in-addr.arpa.") ||
681                 !add_as112_default(zones, cfg, "168.192.in-addr.arpa.") ||
682                 !add_as112_default(zones, cfg, "0.in-addr.arpa.") ||
683                 !add_as112_default(zones, cfg, "64.100.in-addr.arpa.") ||
684                 !add_as112_default(zones, cfg, "65.100.in-addr.arpa.") ||
685                 !add_as112_default(zones, cfg, "66.100.in-addr.arpa.") ||
686                 !add_as112_default(zones, cfg, "67.100.in-addr.arpa.") ||
687                 !add_as112_default(zones, cfg, "68.100.in-addr.arpa.") ||
688                 !add_as112_default(zones, cfg, "69.100.in-addr.arpa.") ||
689                 !add_as112_default(zones, cfg, "70.100.in-addr.arpa.") ||
690                 !add_as112_default(zones, cfg, "71.100.in-addr.arpa.") ||
691                 !add_as112_default(zones, cfg, "72.100.in-addr.arpa.") ||
692                 !add_as112_default(zones, cfg, "73.100.in-addr.arpa.") ||
693                 !add_as112_default(zones, cfg, "74.100.in-addr.arpa.") ||
694                 !add_as112_default(zones, cfg, "75.100.in-addr.arpa.") ||
695                 !add_as112_default(zones, cfg, "76.100.in-addr.arpa.") ||
696                 !add_as112_default(zones, cfg, "77.100.in-addr.arpa.") ||
697                 !add_as112_default(zones, cfg, "78.100.in-addr.arpa.") ||
698                 !add_as112_default(zones, cfg, "79.100.in-addr.arpa.") ||
699                 !add_as112_default(zones, cfg, "80.100.in-addr.arpa.") ||
700                 !add_as112_default(zones, cfg, "81.100.in-addr.arpa.") ||
701                 !add_as112_default(zones, cfg, "82.100.in-addr.arpa.") ||
702                 !add_as112_default(zones, cfg, "83.100.in-addr.arpa.") ||
703                 !add_as112_default(zones, cfg, "84.100.in-addr.arpa.") ||
704                 !add_as112_default(zones, cfg, "85.100.in-addr.arpa.") ||
705                 !add_as112_default(zones, cfg, "86.100.in-addr.arpa.") ||
706                 !add_as112_default(zones, cfg, "87.100.in-addr.arpa.") ||
707                 !add_as112_default(zones, cfg, "88.100.in-addr.arpa.") ||
708                 !add_as112_default(zones, cfg, "89.100.in-addr.arpa.") ||
709                 !add_as112_default(zones, cfg, "90.100.in-addr.arpa.") ||
710                 !add_as112_default(zones, cfg, "91.100.in-addr.arpa.") ||
711                 !add_as112_default(zones, cfg, "92.100.in-addr.arpa.") ||
712                 !add_as112_default(zones, cfg, "93.100.in-addr.arpa.") ||
713                 !add_as112_default(zones, cfg, "94.100.in-addr.arpa.") ||
714                 !add_as112_default(zones, cfg, "95.100.in-addr.arpa.") ||
715                 !add_as112_default(zones, cfg, "96.100.in-addr.arpa.") ||
716                 !add_as112_default(zones, cfg, "97.100.in-addr.arpa.") ||
717                 !add_as112_default(zones, cfg, "98.100.in-addr.arpa.") ||
718                 !add_as112_default(zones, cfg, "99.100.in-addr.arpa.") ||
719                 !add_as112_default(zones, cfg, "100.100.in-addr.arpa.") ||
720                 !add_as112_default(zones, cfg, "101.100.in-addr.arpa.") ||
721                 !add_as112_default(zones, cfg, "102.100.in-addr.arpa.") ||
722                 !add_as112_default(zones, cfg, "103.100.in-addr.arpa.") ||
723                 !add_as112_default(zones, cfg, "104.100.in-addr.arpa.") ||
724                 !add_as112_default(zones, cfg, "105.100.in-addr.arpa.") ||
725                 !add_as112_default(zones, cfg, "106.100.in-addr.arpa.") ||
726                 !add_as112_default(zones, cfg, "107.100.in-addr.arpa.") ||
727                 !add_as112_default(zones, cfg, "108.100.in-addr.arpa.") ||
728                 !add_as112_default(zones, cfg, "109.100.in-addr.arpa.") ||
729                 !add_as112_default(zones, cfg, "110.100.in-addr.arpa.") ||
730                 !add_as112_default(zones, cfg, "111.100.in-addr.arpa.") ||
731                 !add_as112_default(zones, cfg, "112.100.in-addr.arpa.") ||
732                 !add_as112_default(zones, cfg, "113.100.in-addr.arpa.") ||
733                 !add_as112_default(zones, cfg, "114.100.in-addr.arpa.") ||
734                 !add_as112_default(zones, cfg, "115.100.in-addr.arpa.") ||
735                 !add_as112_default(zones, cfg, "116.100.in-addr.arpa.") ||
736                 !add_as112_default(zones, cfg, "117.100.in-addr.arpa.") ||
737                 !add_as112_default(zones, cfg, "118.100.in-addr.arpa.") ||
738                 !add_as112_default(zones, cfg, "119.100.in-addr.arpa.") ||
739                 !add_as112_default(zones, cfg, "120.100.in-addr.arpa.") ||
740                 !add_as112_default(zones, cfg, "121.100.in-addr.arpa.") ||
741                 !add_as112_default(zones, cfg, "122.100.in-addr.arpa.") ||
742                 !add_as112_default(zones, cfg, "123.100.in-addr.arpa.") ||
743                 !add_as112_default(zones, cfg, "124.100.in-addr.arpa.") ||
744                 !add_as112_default(zones, cfg, "125.100.in-addr.arpa.") ||
745                 !add_as112_default(zones, cfg, "126.100.in-addr.arpa.") ||
746                 !add_as112_default(zones, cfg, "127.100.in-addr.arpa.") ||
747                 !add_as112_default(zones, cfg, "254.169.in-addr.arpa.") ||
748                 !add_as112_default(zones, cfg, "2.0.192.in-addr.arpa.") ||
749                 !add_as112_default(zones, cfg, "100.51.198.in-addr.arpa.") ||
750                 !add_as112_default(zones, cfg, "113.0.203.in-addr.arpa.") ||
751                 !add_as112_default(zones, cfg, "255.255.255.255.in-addr.arpa.") ||
752                 !add_as112_default(zones, cfg, "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.0.ip6.arpa.") ||
753                 !add_as112_default(zones, cfg, "d.f.ip6.arpa.") ||
754                 !add_as112_default(zones, cfg, "8.e.f.ip6.arpa.") ||
755                 !add_as112_default(zones, cfg, "9.e.f.ip6.arpa.") ||
756                 !add_as112_default(zones, cfg, "a.e.f.ip6.arpa.") ||
757                 !add_as112_default(zones, cfg, "b.e.f.ip6.arpa.") ||
758                 !add_as112_default(zones, cfg, "8.b.d.0.1.0.0.2.ip6.arpa.")) {
759                 log_err("out of memory adding default zone");
760                 return 0;
761         }
762         return 1;
763 }
764
765 /** setup parent pointers, so that a lookup can be done for closest match */
766 static void
767 init_parents(struct local_zones* zones)
768 {
769         struct local_zone* node, *prev = NULL, *p;
770         int m;
771         lock_rw_wrlock(&zones->lock);
772         RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
773                 lock_rw_wrlock(&node->lock);
774                 node->parent = NULL;
775                 if(!prev || prev->dclass != node->dclass) {
776                         prev = node;
777                         lock_rw_unlock(&node->lock);
778                         continue;
779                 }
780                 (void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
781                         node->namelabs, &m); /* we know prev is smaller */
782                 /* sort order like: . com. bla.com. zwb.com. net. */
783                 /* find the previous, or parent-parent-parent */
784                 for(p = prev; p; p = p->parent)
785                         /* looking for name with few labels, a parent */
786                         if(p->namelabs <= m) {
787                                 /* ==: since prev matched m, this is closest*/
788                                 /* <: prev matches more, but is not a parent,
789                                  * this one is a (grand)parent */
790                                 node->parent = p;
791                                 break;
792                         }
793                 prev = node;
794                 lock_rw_unlock(&node->lock);
795         }
796         lock_rw_unlock(&zones->lock);
797 }
798
799 /** enter implicit transparent zone for local-data: without local-zone: */
800 static int
801 lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
802 {
803         /* walk over all items that have no parent zone and find
804          * the name that covers them all (could be the root) and
805          * add that as a transparent zone */
806         struct config_strlist* p;
807         int have_name = 0;
808         int have_other_classes = 0;
809         uint16_t dclass = 0;
810         uint8_t* nm = 0;
811         size_t nmlen = 0;
812         int nmlabs = 0;
813         int match = 0; /* number of labels match count */
814
815         init_parents(zones); /* to enable local_zones_lookup() */
816         for(p = cfg->local_data; p; p = p->next) {
817                 uint8_t* rr_name;
818                 uint16_t rr_class;
819                 size_t len;
820                 int labs;
821                 if(!get_rr_nameclass(p->str, &rr_name, &rr_class)) {
822                         log_err("Bad local-data RR %s", p->str);
823                         return 0;
824                 }
825                 labs = dname_count_size_labels(rr_name, &len);
826                 lock_rw_rdlock(&zones->lock);
827                 if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) {
828                         if(!have_name) {
829                                 dclass = rr_class;
830                                 nm = rr_name;
831                                 nmlen = len;
832                                 nmlabs = labs;
833                                 match = labs;
834                                 have_name = 1;
835                         } else {
836                                 int m;
837                                 if(rr_class != dclass) {
838                                         /* process other classes later */
839                                         free(rr_name);
840                                         have_other_classes = 1;
841                                         lock_rw_unlock(&zones->lock);
842                                         continue;
843                                 }
844                                 /* find smallest shared topdomain */
845                                 (void)dname_lab_cmp(nm, nmlabs, 
846                                         rr_name, labs, &m);
847                                 free(rr_name);
848                                 if(m < match)
849                                         match = m;
850                         }
851                 } else free(rr_name);
852                 lock_rw_unlock(&zones->lock);
853         }
854         if(have_name) {
855                 uint8_t* n2;
856                 struct local_zone* z;
857                 /* allocate zone of smallest shared topdomain to contain em */
858                 n2 = nm;
859                 dname_remove_labels(&n2, &nmlen, nmlabs - match);
860                 n2 = memdup(n2, nmlen);
861                 free(nm);
862                 if(!n2) {
863                         log_err("out of memory");
864                         return 0;
865                 }
866                 log_nametypeclass(VERB_ALGO, "implicit transparent local-zone", 
867                         n2, 0, dclass);
868                 if(!(z=lz_enter_zone_dname(zones, n2, nmlen, match, 
869                         local_zone_transparent, dclass))) {
870                         return 0;
871                 }
872                 lock_rw_unlock(&z->lock);
873         }
874         if(have_other_classes) { 
875                 /* restart to setup other class */
876                 return lz_setup_implicit(zones, cfg);
877         }
878         return 1;
879 }
880
881 /** enter auth data */
882 static int
883 lz_enter_data(struct local_zones* zones, struct config_file* cfg)
884 {
885         struct config_strlist* p;
886         for(p = cfg->local_data; p; p = p->next) {
887                 if(!lz_enter_rr_str(zones, p->str))
888                         return 0;
889         }
890         return 1;
891 }
892
893 /** free memory from config */
894 static void
895 lz_freeup_cfg(struct config_file* cfg)
896 {
897         config_deldblstrlist(cfg->local_zones);
898         cfg->local_zones = NULL;
899         config_delstrlist(cfg->local_zones_nodefault);
900         cfg->local_zones_nodefault = NULL;
901         config_delstrlist(cfg->local_data);
902         cfg->local_data = NULL;
903 }
904
905 int 
906 local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
907 {
908         /* create zones from zone statements. */
909         if(!lz_enter_zones(zones, cfg)) {
910                 return 0;
911         }
912         /* apply default zones+content (unless disabled, or overridden) */
913         if(!lz_enter_defaults(zones, cfg)) {
914                 return 0;
915         }
916         /* create implicit transparent zone from data. */
917         if(!lz_setup_implicit(zones, cfg)) {
918                 return 0;
919         }
920
921         /* setup parent ptrs for lookup during data entry */
922         init_parents(zones);
923         /* insert local data */
924         if(!lz_enter_data(zones, cfg)) {
925                 return 0;
926         }
927         /* freeup memory from cfg struct. */
928         lz_freeup_cfg(cfg);
929         return 1;
930 }
931
932 struct local_zone* 
933 local_zones_lookup(struct local_zones* zones,
934         uint8_t* name, size_t len, int labs, uint16_t dclass)
935 {
936         rbnode_t* res = NULL;
937         struct local_zone *result;
938         struct local_zone key;
939         key.node.key = &key;
940         key.dclass = dclass;
941         key.name = name;
942         key.namelen = len;
943         key.namelabs = labs;
944         if(rbtree_find_less_equal(&zones->ztree, &key, &res)) {
945                 /* exact */
946                 return (struct local_zone*)res;
947         } else {
948                 /* smaller element (or no element) */
949                 int m;
950                 result = (struct local_zone*)res;
951                 if(!result || result->dclass != dclass)
952                         return NULL;
953                 /* count number of labels matched */
954                 (void)dname_lab_cmp(result->name, result->namelabs, key.name,
955                         key.namelabs, &m);
956                 while(result) { /* go up until qname is subdomain of zone */
957                         if(result->namelabs <= m)
958                                 break;
959                         result = result->parent;
960                 }
961                 return result;
962         }
963 }
964
965 struct local_zone* 
966 local_zones_find(struct local_zones* zones,
967         uint8_t* name, size_t len, int labs, uint16_t dclass)
968 {
969         struct local_zone key;
970         key.node.key = &key;
971         key.dclass = dclass;
972         key.name = name;
973         key.namelen = len;
974         key.namelabs = labs;
975         /* exact */
976         return (struct local_zone*)rbtree_search(&zones->ztree, &key);
977 }
978
979 /** print all RRsets in local zone */
980 static void 
981 local_zone_out(struct local_zone* z)
982 {
983         struct local_data* d;
984         struct local_rrset* p;
985         RBTREE_FOR(d, struct local_data*, &z->data) {
986                 for(p = d->rrsets; p; p = p->next) {
987                         log_nametypeclass(0, "rrset", d->name, 
988                                 ntohs(p->rrset->rk.type),
989                                 ntohs(p->rrset->rk.rrset_class));
990                 }
991         }
992 }
993
994 void local_zones_print(struct local_zones* zones)
995 {
996         struct local_zone* z;
997         lock_rw_rdlock(&zones->lock);
998         log_info("number of auth zones %u", (unsigned)zones->ztree.count);
999         RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
1000                 lock_rw_rdlock(&z->lock);
1001                 switch(z->type) {
1002                 case local_zone_deny:
1003                         log_nametypeclass(0, "deny zone", 
1004                                 z->name, 0, z->dclass);
1005                         break;
1006                 case local_zone_refuse:
1007                         log_nametypeclass(0, "refuse zone", 
1008                                 z->name, 0, z->dclass);
1009                         break;
1010                 case local_zone_redirect:
1011                         log_nametypeclass(0, "redirect zone", 
1012                                 z->name, 0, z->dclass);
1013                         break;
1014                 case local_zone_transparent:
1015                         log_nametypeclass(0, "transparent zone", 
1016                                 z->name, 0, z->dclass);
1017                         break;
1018                 case local_zone_typetransparent:
1019                         log_nametypeclass(0, "typetransparent zone", 
1020                                 z->name, 0, z->dclass);
1021                         break;
1022                 case local_zone_static:
1023                         log_nametypeclass(0, "static zone", 
1024                                 z->name, 0, z->dclass);
1025                         break;
1026                 case local_zone_inform:
1027                         log_nametypeclass(0, "inform zone", 
1028                                 z->name, 0, z->dclass);
1029                         break;
1030                 default:
1031                         log_nametypeclass(0, "badtyped zone", 
1032                                 z->name, 0, z->dclass);
1033                         break;
1034                 }
1035                 local_zone_out(z);
1036                 lock_rw_unlock(&z->lock);
1037         }
1038         lock_rw_unlock(&zones->lock);
1039 }
1040
1041 /** encode answer consisting of 1 rrset */
1042 static int
1043 local_encode(struct query_info* qinfo, struct edns_data* edns, 
1044         sldns_buffer* buf, struct regional* temp, 
1045         struct ub_packed_rrset_key* rrset, int ansec, int rcode)
1046 {
1047         struct reply_info rep;
1048         uint16_t udpsize;
1049         /* make answer with time=0 for fixed TTL values */
1050         memset(&rep, 0, sizeof(rep));
1051         rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode);
1052         rep.qdcount = 1;
1053         if(ansec)
1054                 rep.an_numrrsets = 1;
1055         else    rep.ns_numrrsets = 1;
1056         rep.rrset_count = 1;
1057         rep.rrsets = &rrset;
1058         udpsize = edns->udp_size;
1059         edns->edns_version = EDNS_ADVERTISED_VERSION;
1060         edns->udp_size = EDNS_ADVERTISED_SIZE;
1061         edns->ext_rcode = 0;
1062         edns->bits &= EDNS_DO;
1063         if(!reply_info_answer_encode(qinfo, &rep, 
1064                 *(uint16_t*)sldns_buffer_begin(buf),
1065                 sldns_buffer_read_u16_at(buf, 2),
1066                 buf, 0, 0, temp, udpsize, edns, 
1067                 (int)(edns->bits&EDNS_DO), 0))
1068                 error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
1069                         *(uint16_t*)sldns_buffer_begin(buf),
1070                        sldns_buffer_read_u16_at(buf, 2), edns);
1071         return 1;
1072 }
1073
1074 /** answer local data match */
1075 static int
1076 local_data_answer(struct local_zone* z, struct query_info* qinfo,
1077         struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
1078         int labs, struct local_data** ldp)
1079 {
1080         struct local_data key;
1081         struct local_data* ld;
1082         struct local_rrset* lr;
1083         key.node.key = &key;
1084         key.name = qinfo->qname;
1085         key.namelen = qinfo->qname_len;
1086         key.namelabs = labs;
1087         if(z->type == local_zone_redirect) {
1088                 key.name = z->name;
1089                 key.namelen = z->namelen;
1090                 key.namelabs = z->namelabs;
1091         }
1092         ld = (struct local_data*)rbtree_search(&z->data, &key.node);
1093         *ldp = ld;
1094         if(!ld) {
1095                 return 0;
1096         }
1097         lr = local_data_find_type(ld, qinfo->qtype);
1098         if(!lr)
1099                 return 0;
1100         if(z->type == local_zone_redirect) {
1101                 /* convert rrset name to query name; like a wildcard */
1102                 struct ub_packed_rrset_key r = *lr->rrset;
1103                 r.rk.dname = qinfo->qname;
1104                 r.rk.dname_len = qinfo->qname_len;
1105                 return local_encode(qinfo, edns, buf, temp, &r, 1, 
1106                         LDNS_RCODE_NOERROR);
1107         }
1108         return local_encode(qinfo, edns, buf, temp, lr->rrset, 1, 
1109                 LDNS_RCODE_NOERROR);
1110 }
1111
1112 /** 
1113  * answer in case where no exact match is found 
1114  * @param z: zone for query
1115  * @param qinfo: query
1116  * @param edns: edns from query
1117  * @param buf: buffer for answer.
1118  * @param temp: temp region for encoding
1119  * @param ld: local data, if NULL, no such name exists in localdata.
1120  * @return 1 if a reply is to be sent, 0 if not.
1121  */
1122 static int
1123 lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
1124         struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
1125         struct local_data* ld)
1126 {
1127         if(z->type == local_zone_deny) {
1128                 /** no reply at all, signal caller by clearing buffer. */
1129                 sldns_buffer_clear(buf);
1130                 sldns_buffer_flip(buf);
1131                 return 1;
1132         } else if(z->type == local_zone_refuse) {
1133                 error_encode(buf, (LDNS_RCODE_REFUSED|BIT_AA), qinfo,
1134                         *(uint16_t*)sldns_buffer_begin(buf),
1135                        sldns_buffer_read_u16_at(buf, 2), edns);
1136                 return 1;
1137         } else if(z->type == local_zone_static ||
1138                 z->type == local_zone_redirect) {
1139                 /* for static, reply nodata or nxdomain
1140                  * for redirect, reply nodata */
1141                 /* no additional section processing,
1142                  * cname, dname or wildcard processing,
1143                  * or using closest match for NSEC.
1144                  * or using closest match for returning delegation downwards
1145                  */
1146                 int rcode = ld?LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
1147                 if(z->soa)
1148                         return local_encode(qinfo, edns, buf, temp, 
1149                                 z->soa, 0, rcode);
1150                 error_encode(buf, (rcode|BIT_AA), qinfo, 
1151                         *(uint16_t*)sldns_buffer_begin(buf), 
1152                         sldns_buffer_read_u16_at(buf, 2), edns);
1153                 return 1;
1154         } else if(z->type == local_zone_typetransparent) {
1155                 /* no NODATA or NXDOMAINS for this zone type */
1156                 return 0;
1157         }
1158         /* else z->type == local_zone_transparent */
1159
1160         /* if the zone is transparent and the name exists, but the type
1161          * does not, then we should make this noerror/nodata */
1162         if(ld && ld->rrsets) {
1163                 int rcode = LDNS_RCODE_NOERROR;
1164                 if(z->soa)
1165                         return local_encode(qinfo, edns, buf, temp, 
1166                                 z->soa, 0, rcode);
1167                 error_encode(buf, (rcode|BIT_AA), qinfo, 
1168                         *(uint16_t*)sldns_buffer_begin(buf), 
1169                         sldns_buffer_read_u16_at(buf, 2), edns);
1170                 return 1;
1171         }
1172
1173         /* stop here, and resolve further on */
1174         return 0;
1175 }
1176
1177 /** print log information for an inform zone query */
1178 static void
1179 lz_inform_print(struct local_zone* z, struct query_info* qinfo,
1180         struct comm_reply* repinfo)
1181 {
1182         char ip[128], txt[512];
1183         char zname[LDNS_MAX_DOMAINLEN+1];
1184         uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
1185         dname_str(z->name, zname);
1186         addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
1187         snprintf(txt, sizeof(txt), "%s inform %s@%u", zname, ip,
1188                 (unsigned)port);
1189         log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
1190 }
1191
1192 int 
1193 local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
1194         struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
1195         struct comm_reply* repinfo)
1196 {
1197         /* see if query is covered by a zone,
1198          *      if so:  - try to match (exact) local data 
1199          *              - look at zone type for negative response. */
1200         int labs = dname_count_labels(qinfo->qname);
1201         struct local_data* ld;
1202         struct local_zone* z;
1203         int r;
1204         lock_rw_rdlock(&zones->lock);
1205         z = local_zones_lookup(zones, qinfo->qname,
1206                 qinfo->qname_len, labs, qinfo->qclass);
1207         if(!z) {
1208                 lock_rw_unlock(&zones->lock);
1209                 return 0;
1210         }
1211         lock_rw_rdlock(&z->lock);
1212         lock_rw_unlock(&zones->lock);
1213
1214         if(z->type == local_zone_inform && repinfo)
1215                 lz_inform_print(z, qinfo, repinfo);
1216
1217         if(local_data_answer(z, qinfo, edns, buf, temp, labs, &ld)) {
1218                 lock_rw_unlock(&z->lock);
1219                 return 1;
1220         }
1221         r = lz_zone_answer(z, qinfo, edns, buf, temp, ld);
1222         lock_rw_unlock(&z->lock);
1223         return r;
1224 }
1225
1226 const char* local_zone_type2str(enum localzone_type t)
1227 {
1228         switch(t) {
1229                 case local_zone_deny: return "deny";
1230                 case local_zone_refuse: return "refuse";
1231                 case local_zone_redirect: return "redirect";
1232                 case local_zone_transparent: return "transparent";
1233                 case local_zone_typetransparent: return "typetransparent";
1234                 case local_zone_static: return "static";
1235                 case local_zone_nodefault: return "nodefault";
1236                 case local_zone_inform: return "inform";
1237         }
1238         return "badtyped"; 
1239 }
1240
1241 int local_zone_str2type(const char* type, enum localzone_type* t)
1242 {
1243         if(strcmp(type, "deny") == 0)
1244                 *t = local_zone_deny;
1245         else if(strcmp(type, "refuse") == 0)
1246                 *t = local_zone_refuse;
1247         else if(strcmp(type, "static") == 0)
1248                 *t = local_zone_static;
1249         else if(strcmp(type, "transparent") == 0)
1250                 *t = local_zone_transparent;
1251         else if(strcmp(type, "typetransparent") == 0)
1252                 *t = local_zone_typetransparent;
1253         else if(strcmp(type, "redirect") == 0)
1254                 *t = local_zone_redirect;
1255         else if(strcmp(type, "inform") == 0)
1256                 *t = local_zone_inform;
1257         else return 0;
1258         return 1;
1259 }
1260
1261 /** iterate over the kiddies of the given name and set their parent ptr */
1262 static void
1263 set_kiddo_parents(struct local_zone* z, struct local_zone* match, 
1264         struct local_zone* newp)
1265 {
1266         /* both zones and z are locked already */
1267         /* in the sorted rbtree, the kiddies of z are located after z */
1268         /* z must be present in the tree */
1269         struct local_zone* p = z;
1270         p = (struct local_zone*)rbtree_next(&p->node);
1271         while(p!=(struct local_zone*)RBTREE_NULL &&
1272                 p->dclass == z->dclass && dname_strict_subdomain(p->name,
1273                 p->namelabs, z->name, z->namelabs)) {
1274                 /* update parent ptr */
1275                 /* only when matches with existing parent pointer, so that
1276                  * deeper child structures are not touched, i.e.
1277                  * update of x, and a.x, b.x, f.b.x, g.b.x, c.x, y
1278                  * gets to update a.x, b.x and c.x */
1279                 lock_rw_wrlock(&p->lock);
1280                 if(p->parent == match)
1281                         p->parent = newp;
1282                 lock_rw_unlock(&p->lock);
1283                 p = (struct local_zone*)rbtree_next(&p->node);
1284         }
1285 }
1286
1287 struct local_zone* local_zones_add_zone(struct local_zones* zones,
1288         uint8_t* name, size_t len, int labs, uint16_t dclass,
1289         enum localzone_type tp)
1290 {
1291         /* create */
1292         struct local_zone* z = local_zone_create(name, len, labs, tp, dclass);
1293         if(!z) return NULL;
1294         lock_rw_wrlock(&z->lock);
1295
1296         /* find the closest parent */
1297         z->parent = local_zones_find(zones, name, len, labs, dclass);
1298
1299         /* insert into the tree */
1300         if(!rbtree_insert(&zones->ztree, &z->node)) {
1301                 /* duplicate entry! */
1302                 lock_rw_unlock(&z->lock);
1303                 local_zone_delete(z);
1304                 log_err("internal: duplicate entry in local_zones_add_zone");
1305                 return NULL;
1306         }
1307
1308         /* set parent pointers right */
1309         set_kiddo_parents(z, z->parent, z);
1310
1311         lock_rw_unlock(&z->lock);
1312         return z;
1313 }
1314
1315 void local_zones_del_zone(struct local_zones* zones, struct local_zone* z)
1316 {
1317         /* fix up parents in tree */
1318         lock_rw_wrlock(&z->lock);
1319         set_kiddo_parents(z, z, z->parent);
1320
1321         /* remove from tree */
1322         (void)rbtree_delete(&zones->ztree, z);
1323
1324         /* delete the zone */
1325         lock_rw_unlock(&z->lock);
1326         local_zone_delete(z);
1327 }
1328
1329 int
1330 local_zones_add_RR(struct local_zones* zones, const char* rr)
1331 {
1332         uint8_t* rr_name;
1333         uint16_t rr_class;
1334         size_t len;
1335         int labs;
1336         struct local_zone* z;
1337         int r;
1338         if(!get_rr_nameclass(rr, &rr_name, &rr_class)) {
1339                 return 0;
1340         }
1341         labs = dname_count_size_labels(rr_name, &len);
1342         /* could first try readlock then get writelock if zone does not exist,
1343          * but we do not add enough RRs (from multiple threads) to optimize */
1344         lock_rw_wrlock(&zones->lock);
1345         z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
1346         if(!z) {
1347                 z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
1348                         local_zone_transparent);
1349                 if(!z) {
1350                         lock_rw_unlock(&zones->lock);
1351                         return 0;
1352                 }
1353         } else {
1354                 free(rr_name);
1355         }
1356         lock_rw_wrlock(&z->lock);
1357         lock_rw_unlock(&zones->lock);
1358         r = lz_enter_rr_into_zone(z, rr);
1359         lock_rw_unlock(&z->lock);
1360         return r;
1361 }
1362
1363 /** returns true if the node is terminal so no deeper domain names exist */
1364 static int
1365 is_terminal(struct local_data* d)
1366 {
1367         /* for empty nonterminals, the deeper domain names are sorted
1368          * right after them, so simply check the next name in the tree 
1369          */
1370         struct local_data* n = (struct local_data*)rbtree_next(&d->node);
1371         if(n == (struct local_data*)RBTREE_NULL)
1372                 return 1; /* last in tree, no deeper node */
1373         if(dname_strict_subdomain(n->name, n->namelabs, d->name, d->namelabs))
1374                 return 0; /* there is a deeper node */
1375         return 1;
1376 }
1377
1378 /** delete empty terminals from tree when final data is deleted */
1379 static void 
1380 del_empty_term(struct local_zone* z, struct local_data* d, 
1381         uint8_t* name, size_t len, int labs)
1382 {
1383         while(d && d->rrsets == NULL && is_terminal(d)) {
1384                 /* is this empty nonterminal? delete */
1385                 /* note, no memory recycling in zone region */
1386                 (void)rbtree_delete(&z->data, d);
1387
1388                 /* go up and to the next label */
1389                 if(dname_is_root(name))
1390                         return;
1391                 dname_remove_label(&name, &len);
1392                 labs--;
1393                 d = lz_find_node(z, name, len, labs);
1394         }
1395 }
1396
1397 void local_zones_del_data(struct local_zones* zones, 
1398         uint8_t* name, size_t len, int labs, uint16_t dclass)
1399 {
1400         /* find zone */
1401         struct local_zone* z;
1402         struct local_data* d;
1403         lock_rw_rdlock(&zones->lock);
1404         z = local_zones_lookup(zones, name, len, labs, dclass);
1405         if(!z) {
1406                 /* no such zone, we're done */
1407                 lock_rw_unlock(&zones->lock);
1408                 return;
1409         }
1410         lock_rw_wrlock(&z->lock);
1411         lock_rw_unlock(&zones->lock);
1412
1413         /* find the domain */
1414         d = lz_find_node(z, name, len, labs);
1415         if(d) {
1416                 /* no memory recycling for zone deletions ... */
1417                 d->rrsets = NULL;
1418                 /* did we delete the soa record ? */
1419                 if(query_dname_compare(d->name, z->name) == 0)
1420                         z->soa = NULL;
1421
1422                 /* cleanup the empty nonterminals for this name */
1423                 del_empty_term(z, d, name, len, labs);
1424         }
1425
1426         lock_rw_unlock(&z->lock);
1427 }