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