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