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