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