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