1 /* 2 * options.c -- options functions. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 #include "config.h" 10 #include <string.h> 11 #include <stdio.h> 12 #include <errno.h> 13 #include "options.h" 14 #include "query.h" 15 #include "tsig.h" 16 #include "difffile.h" 17 #include "rrl.h" 18 19 #include "configyyrename.h" 20 #include "configparser.h" 21 config_parser_state_t* cfg_parser = 0; 22 extern FILE* c_in, *c_out; 23 int c_parse(void); 24 int c_lex(void); 25 int c_wrap(void); 26 void c_error(const char *message); 27 extern char* c_text; 28 29 static int 30 rbtree_strcmp(const void* p1, const void* p2) 31 { 32 if(p1 == NULL && p2 == NULL) return 0; 33 if(p1 == NULL) return -1; 34 if(p2 == NULL) return 1; 35 return strcmp((const char*)p1, (const char*)p2); 36 } 37 38 nsd_options_t* 39 nsd_options_create(region_type* region) 40 { 41 nsd_options_t* opt; 42 opt = (nsd_options_t*)region_alloc(region, sizeof(nsd_options_t)); 43 opt->region = region; 44 opt->zone_options = rbtree_create(region, 45 (int (*)(const void *, const void *)) dname_compare); 46 opt->configfile = NULL; 47 opt->zonestatnames = rbtree_create(opt->region, rbtree_strcmp); 48 opt->patterns = rbtree_create(region, rbtree_strcmp); 49 opt->keys = rbtree_create(region, rbtree_strcmp); 50 opt->ip_addresses = NULL; 51 opt->ip_transparent = 0; 52 opt->ip_freebind = 0; 53 opt->debug_mode = 0; 54 opt->verbosity = 0; 55 opt->hide_version = 0; 56 opt->do_ip4 = 1; 57 opt->do_ip6 = 1; 58 opt->database = DBFILE; 59 opt->identity = 0; 60 opt->version = 0; 61 opt->nsid = 0; 62 opt->logfile = 0; 63 opt->log_time_ascii = 1; 64 opt->round_robin = 0; /* also packet.h::round_robin */ 65 opt->server_count = 1; 66 opt->tcp_count = 100; 67 opt->tcp_query_count = 0; 68 opt->tcp_timeout = TCP_TIMEOUT; 69 opt->tcp_mss = 0; 70 opt->outgoing_tcp_mss = 0; 71 opt->ipv4_edns_size = EDNS_MAX_MESSAGE_LEN; 72 opt->ipv6_edns_size = EDNS_MAX_MESSAGE_LEN; 73 opt->pidfile = PIDFILE; 74 opt->port = UDP_PORT; 75 /* deprecated? opt->port = TCP_PORT; */ 76 opt->reuseport = 0; 77 opt->statistics = 0; 78 opt->chroot = 0; 79 opt->username = USER; 80 opt->zonesdir = ZONESDIR; 81 opt->xfrdfile = XFRDFILE; 82 opt->xfrdir = XFRDIR; 83 opt->zonelistfile = ZONELISTFILE; 84 #ifdef RATELIMIT 85 opt->rrl_size = RRL_BUCKETS; 86 opt->rrl_slip = RRL_SLIP; 87 opt->rrl_ipv4_prefix_length = RRL_IPV4_PREFIX_LENGTH; 88 opt->rrl_ipv6_prefix_length = RRL_IPV6_PREFIX_LENGTH; 89 # ifdef RATELIMIT_DEFAULT_OFF 90 opt->rrl_ratelimit = 0; 91 opt->rrl_whitelist_ratelimit = 0; 92 # else 93 opt->rrl_ratelimit = RRL_LIMIT/2; 94 opt->rrl_whitelist_ratelimit = RRL_WLIST_LIMIT/2; 95 # endif 96 #endif 97 opt->zonefiles_check = 1; 98 if(opt->database == NULL || opt->database[0] == 0) 99 opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL; 100 else opt->zonefiles_write = 0; 101 opt->xfrd_reload_timeout = 1; 102 opt->control_enable = 0; 103 opt->control_interface = NULL; 104 opt->control_port = NSD_CONTROL_PORT; 105 opt->server_key_file = CONFIGDIR"/nsd_server.key"; 106 opt->server_cert_file = CONFIGDIR"/nsd_server.pem"; 107 opt->control_key_file = CONFIGDIR"/nsd_control.key"; 108 opt->control_cert_file = CONFIGDIR"/nsd_control.pem"; 109 return opt; 110 } 111 112 int 113 nsd_options_insert_zone(nsd_options_t* opt, zone_options_t* zone) 114 { 115 /* create dname for lookup */ 116 const dname_type* dname = dname_parse(opt->region, zone->name); 117 if(!dname) 118 return 0; 119 zone->node.key = dname; 120 if(!rbtree_insert(opt->zone_options, (rbnode_t*)zone)) 121 return 0; 122 return 1; 123 } 124 125 int 126 nsd_options_insert_pattern(nsd_options_t* opt, pattern_options_t* pat) 127 { 128 if(!pat->pname) 129 return 0; 130 pat->node.key = pat->pname; 131 if(!rbtree_insert(opt->patterns, (rbnode_t*)pat)) 132 return 0; 133 return 1; 134 } 135 136 int 137 parse_options_file(nsd_options_t* opt, const char* file, 138 void (*err)(void*,const char*), void* err_arg) 139 { 140 FILE *in = 0; 141 pattern_options_t* pat; 142 acl_options_t* acl; 143 144 if(!cfg_parser) { 145 cfg_parser = (config_parser_state_t*)region_alloc( 146 opt->region, sizeof(config_parser_state_t)); 147 cfg_parser->chroot = 0; 148 } 149 cfg_parser->err = err; 150 cfg_parser->err_arg = err_arg; 151 cfg_parser->filename = (char*)file; 152 cfg_parser->line = 1; 153 cfg_parser->errors = 0; 154 cfg_parser->server_settings_seen = 0; 155 cfg_parser->opt = opt; 156 cfg_parser->current_pattern = 0; 157 cfg_parser->current_zone = 0; 158 cfg_parser->current_key = 0; 159 cfg_parser->current_ip_address_option = opt->ip_addresses; 160 while(cfg_parser->current_ip_address_option && cfg_parser->current_ip_address_option->next) 161 cfg_parser->current_ip_address_option = cfg_parser->current_ip_address_option->next; 162 cfg_parser->current_allow_notify = 0; 163 cfg_parser->current_request_xfr = 0; 164 cfg_parser->current_notify = 0; 165 cfg_parser->current_provide_xfr = 0; 166 167 in = fopen(cfg_parser->filename, "r"); 168 if(!in) { 169 if(err) { 170 char m[MAXSYSLOGMSGLEN]; 171 snprintf(m, sizeof(m), "Could not open %s: %s\n", 172 file, strerror(errno)); 173 err(err_arg, m); 174 } else { 175 fprintf(stderr, "Could not open %s: %s\n", 176 file, strerror(errno)); 177 } 178 return 0; 179 } 180 c_in = in; 181 c_parse(); 182 fclose(in); 183 184 opt->configfile = region_strdup(opt->region, file); 185 if(cfg_parser->current_pattern) { 186 if(!cfg_parser->current_pattern->pname) 187 c_error("last pattern has no name"); 188 else { 189 if(!nsd_options_insert_pattern(cfg_parser->opt, 190 cfg_parser->current_pattern)) 191 c_error("duplicate pattern"); 192 } 193 } 194 if(cfg_parser->current_zone) { 195 if(!cfg_parser->current_zone->name) 196 c_error("last zone has no name"); 197 else { 198 if(!nsd_options_insert_zone(opt, 199 cfg_parser->current_zone)) 200 c_error("duplicate zone"); 201 } 202 if(!cfg_parser->current_zone->pattern) 203 c_error("last zone has no pattern"); 204 } 205 if(cfg_parser->current_key) 206 { 207 if(!cfg_parser->current_key->name) 208 c_error("last key has no name"); 209 if(!cfg_parser->current_key->algorithm) 210 c_error("last key has no algorithm"); 211 if(!cfg_parser->current_key->secret) 212 c_error("last key has no secret blob"); 213 key_options_insert(opt, cfg_parser->current_key); 214 } 215 RBTREE_FOR(pat, pattern_options_t*, opt->patterns) 216 { 217 /* lookup keys for acls */ 218 for(acl=pat->allow_notify; acl; acl=acl->next) 219 { 220 if(acl->nokey || acl->blocked) 221 continue; 222 acl->key_options = key_options_find(opt, acl->key_name); 223 if(!acl->key_options) 224 c_error_msg("key %s in pattern %s could not be found", 225 acl->key_name, pat->pname); 226 } 227 for(acl=pat->notify; acl; acl=acl->next) 228 { 229 if(acl->nokey || acl->blocked) 230 continue; 231 acl->key_options = key_options_find(opt, acl->key_name); 232 if(!acl->key_options) 233 c_error_msg("key %s in pattern %s could not be found", 234 acl->key_name, pat->pname); 235 } 236 for(acl=pat->request_xfr; acl; acl=acl->next) 237 { 238 if(acl->nokey || acl->blocked) 239 continue; 240 acl->key_options = key_options_find(opt, acl->key_name); 241 if(!acl->key_options) 242 c_error_msg("key %s in pattern %s could not be found", 243 acl->key_name, pat->pname); 244 } 245 for(acl=pat->provide_xfr; acl; acl=acl->next) 246 { 247 if(acl->nokey || acl->blocked) 248 continue; 249 acl->key_options = key_options_find(opt, acl->key_name); 250 if(!acl->key_options) 251 c_error_msg("key %s in pattern %s could not be found", 252 acl->key_name, pat->pname); 253 } 254 } 255 256 if(cfg_parser->errors > 0) 257 { 258 if(err) { 259 char m[MAXSYSLOGMSGLEN]; 260 snprintf(m, sizeof(m), "read %s failed: %d errors in " 261 "configuration file\n", file, 262 cfg_parser->errors); 263 err(err_arg, m); 264 } else { 265 fprintf(stderr, "read %s failed: %d errors in " 266 "configuration file\n", file, 267 cfg_parser->errors); 268 } 269 return 0; 270 } 271 return 1; 272 } 273 274 void options_zonestatnames_create(nsd_options_t* opt) 275 { 276 zone_options_t* zopt; 277 /* allocate "" as zonestat 0, for zones without a zonestat */ 278 if(!rbtree_search(opt->zonestatnames, "")) { 279 struct zonestatname* n; 280 n = (struct zonestatname*)xalloc(sizeof(*n)); 281 memset(n, 0, sizeof(*n)); 282 n->node.key = strdup(""); 283 if(!n->node.key) { 284 log_msg(LOG_ERR, "malloc failed: %s", strerror(errno)); 285 exit(1); 286 } 287 n->id = (unsigned)(opt->zonestatnames->count); 288 rbtree_insert(opt->zonestatnames, (rbnode_t*)n); 289 } 290 RBTREE_FOR(zopt, zone_options_t*, opt->zone_options) { 291 /* insert into tree, so that when read in later id exists */ 292 (void)getzonestatid(opt, zopt); 293 } 294 } 295 296 #define ZONELIST_HEADER "# NSD zone list\n# name pattern\n" 297 static int 298 comp_zonebucket(const void* a, const void* b) 299 { 300 /* the line size is much smaller than max-int, and positive, 301 * so the subtraction works */ 302 return *(const int*)b - *(const int*)a; 303 } 304 305 /* insert free entry into zonelist free buckets */ 306 static void 307 zone_list_free_insert(nsd_options_t* opt, int linesize, off_t off) 308 { 309 struct zonelist_free* e; 310 struct zonelist_bucket* b = (struct zonelist_bucket*)rbtree_search( 311 opt->zonefree, &linesize); 312 if(!b) { 313 b = region_alloc_zero(opt->region, sizeof(*b)); 314 b->linesize = linesize; 315 b->node = *RBTREE_NULL; 316 b->node.key = &b->linesize; 317 rbtree_insert(opt->zonefree, &b->node); 318 } 319 e = (struct zonelist_free*)region_alloc_zero(opt->region, sizeof(*e)); 320 e->next = b->list; 321 b->list = e; 322 e->off = off; 323 opt->zonefree_number++; 324 } 325 326 zone_options_t* 327 zone_list_zone_insert(nsd_options_t* opt, const char* nm, const char* patnm, 328 int linesize, off_t off) 329 { 330 pattern_options_t* pat = pattern_options_find(opt, patnm); 331 zone_options_t* zone; 332 if(!pat) { 333 log_msg(LOG_ERR, "pattern does not exist for zone %s " 334 "pattern %s", nm, patnm); 335 return NULL; 336 } 337 zone = zone_options_create(opt->region); 338 zone->part_of_config = 0; 339 zone->name = region_strdup(opt->region, nm); 340 zone->linesize = linesize; 341 zone->off = off; 342 zone->pattern = pat; 343 if(!nsd_options_insert_zone(opt, zone)) { 344 log_msg(LOG_ERR, "bad domain name or duplicate zone '%s' " 345 "pattern %s", nm, patnm); 346 region_recycle(opt->region, (void*)zone->name, strlen(nm)+1); 347 region_recycle(opt->region, zone, sizeof(*zone)); 348 return NULL; 349 } 350 return zone; 351 } 352 353 int 354 parse_zone_list_file(nsd_options_t* opt) 355 { 356 /* zonelist looks like this: 357 # name pattern 358 add example.com master 359 del example.net slave 360 add foo.bar.nl slave 361 add rutabaga.uk config 362 */ 363 char buf[1024]; 364 365 /* create empty data structures */ 366 opt->zonefree = rbtree_create(opt->region, comp_zonebucket); 367 opt->zonelist = NULL; 368 opt->zonefree_number = 0; 369 opt->zonelist_off = 0; 370 371 /* try to open the zonelist file, an empty or nonexist file is OK */ 372 opt->zonelist = fopen(opt->zonelistfile, "r+"); 373 if(!opt->zonelist) { 374 if(errno == ENOENT) 375 return 1; /* file does not exist, it is created later */ 376 log_msg(LOG_ERR, "could not open zone list %s: %s", opt->zonelistfile, 377 strerror(errno)); 378 return 0; 379 } 380 /* read header */ 381 buf[strlen(ZONELIST_HEADER)] = 0; 382 if(fread(buf, 1, strlen(ZONELIST_HEADER), opt->zonelist) != 383 strlen(ZONELIST_HEADER) || strncmp(buf, ZONELIST_HEADER, 384 strlen(ZONELIST_HEADER)) != 0) { 385 log_msg(LOG_ERR, "zone list %s contains bad header\n", opt->zonelistfile); 386 fclose(opt->zonelist); 387 opt->zonelist = NULL; 388 return 0; 389 } 390 391 /* read entries in file */ 392 while(fgets(buf, sizeof(buf), opt->zonelist)) { 393 /* skip comments and empty lines */ 394 if(buf[0] == 0 || buf[0] == '\n' || buf[0] == '#') 395 continue; 396 if(strncmp(buf, "add ", 4) == 0) { 397 int linesize = strlen(buf); 398 /* parse the 'add' line */ 399 /* pick last space on the line, so that the domain 400 * name can have a space in it (but not the pattern)*/ 401 char* space = strrchr(buf+4, ' '); 402 char* nm, *patnm; 403 if(!space) { 404 /* parse error */ 405 log_msg(LOG_ERR, "parse error in %s: '%s'", 406 opt->zonelistfile, buf); 407 continue; 408 } 409 nm = buf+4; 410 *space = 0; 411 patnm = space+1; 412 if(linesize && buf[linesize-1] == '\n') 413 buf[linesize-1] = 0; 414 415 /* store offset and line size for zone entry */ 416 /* and create zone entry in zonetree */ 417 (void)zone_list_zone_insert(opt, nm, patnm, linesize, 418 ftello(opt->zonelist)-linesize); 419 } else if(strncmp(buf, "del ", 4) == 0) { 420 /* store offset and line size for deleted entry */ 421 int linesize = strlen(buf); 422 zone_list_free_insert(opt, linesize, 423 ftello(opt->zonelist)-linesize); 424 } else { 425 log_msg(LOG_WARNING, "bad data in %s, '%s'", opt->zonelistfile, 426 buf); 427 } 428 } 429 /* store EOF offset */ 430 opt->zonelist_off = ftello(opt->zonelist); 431 return 1; 432 } 433 434 void 435 zone_options_delete(nsd_options_t* opt, zone_options_t* zone) 436 { 437 rbtree_delete(opt->zone_options, zone->node.key); 438 region_recycle(opt->region, (void*)zone->node.key, dname_total_size( 439 (dname_type*)zone->node.key)); 440 region_recycle(opt->region, zone, sizeof(*zone)); 441 } 442 443 /* add a new zone to the zonelist */ 444 zone_options_t* 445 zone_list_add(nsd_options_t* opt, const char* zname, const char* pname) 446 { 447 int r; 448 struct zonelist_free* e; 449 struct zonelist_bucket* b; 450 int linesize = 6 + strlen(zname) + strlen(pname); 451 /* create zone entry */ 452 zone_options_t* zone = zone_list_zone_insert(opt, zname, pname, 453 linesize, 0); 454 if(!zone) 455 return NULL; 456 457 /* use free entry or append to file or create new file */ 458 if(!opt->zonelist || opt->zonelist_off == 0) { 459 /* create new file */ 460 if(opt->zonelist) fclose(opt->zonelist); 461 opt->zonelist = fopen(opt->zonelistfile, "w+"); 462 if(!opt->zonelist) { 463 log_msg(LOG_ERR, "could not create zone list %s: %s", 464 opt->zonelistfile, strerror(errno)); 465 log_msg(LOG_ERR, "zone %s could not be added", zname); 466 zone_options_delete(opt, zone); 467 return NULL; 468 } 469 r = fprintf(opt->zonelist, ZONELIST_HEADER); 470 if(r != strlen(ZONELIST_HEADER)) { 471 if(r == -1) 472 log_msg(LOG_ERR, "could not write to %s: %s", 473 opt->zonelistfile, strerror(errno)); 474 else log_msg(LOG_ERR, "partial write to %s: disk full", 475 opt->zonelistfile); 476 log_msg(LOG_ERR, "zone %s could not be added", zname); 477 zone_options_delete(opt, zone); 478 return NULL; 479 } 480 zone->off = ftello(opt->zonelist); 481 if(zone->off == -1) 482 log_msg(LOG_ERR, "ftello(%s): %s", opt->zonelistfile, strerror(errno)); 483 r = fprintf(opt->zonelist, "add %s %s\n", zname, pname); 484 if(r != zone->linesize) { 485 if(r == -1) 486 log_msg(LOG_ERR, "could not write to %s: %s", 487 opt->zonelistfile, strerror(errno)); 488 else log_msg(LOG_ERR, "partial write to %s: disk full", 489 opt->zonelistfile); 490 log_msg(LOG_ERR, "zone %s could not be added", zname); 491 zone_options_delete(opt, zone); 492 return NULL; 493 } 494 opt->zonelist_off = ftello(opt->zonelist); 495 if(opt->zonelist_off == -1) 496 log_msg(LOG_ERR, "ftello(%s): %s", opt->zonelistfile, strerror(errno)); 497 if(fflush(opt->zonelist) != 0) { 498 log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno)); 499 } 500 return zone; 501 } 502 b = (struct zonelist_bucket*)rbtree_search(opt->zonefree, 503 &zone->linesize); 504 if(!b || b->list == NULL) { 505 /* no empty place, append to file */ 506 zone->off = opt->zonelist_off; 507 if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) { 508 log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno)); 509 log_msg(LOG_ERR, "zone %s could not be added", zname); 510 zone_options_delete(opt, zone); 511 return NULL; 512 } 513 r = fprintf(opt->zonelist, "add %s %s\n", zname, pname); 514 if(r != zone->linesize) { 515 if(r == -1) 516 log_msg(LOG_ERR, "could not write to %s: %s", 517 opt->zonelistfile, strerror(errno)); 518 else log_msg(LOG_ERR, "partial write to %s: disk full", 519 opt->zonelistfile); 520 log_msg(LOG_ERR, "zone %s could not be added", zname); 521 zone_options_delete(opt, zone); 522 return NULL; 523 } 524 opt->zonelist_off += linesize; 525 if(fflush(opt->zonelist) != 0) { 526 log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno)); 527 } 528 return zone; 529 } 530 /* reuse empty spot */ 531 e = b->list; 532 zone->off = e->off; 533 if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) { 534 log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno)); 535 log_msg(LOG_ERR, "zone %s could not be added", zname); 536 zone_options_delete(opt, zone); 537 return NULL; 538 } 539 r = fprintf(opt->zonelist, "add %s %s\n", zname, pname); 540 if(r != zone->linesize) { 541 if(r == -1) 542 log_msg(LOG_ERR, "could not write to %s: %s", 543 opt->zonelistfile, strerror(errno)); 544 else log_msg(LOG_ERR, "partial write to %s: disk full", 545 opt->zonelistfile); 546 log_msg(LOG_ERR, "zone %s could not be added", zname); 547 zone_options_delete(opt, zone); 548 return NULL; 549 } 550 if(fflush(opt->zonelist) != 0) { 551 log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno)); 552 } 553 554 /* snip off and recycle element */ 555 b->list = e->next; 556 region_recycle(opt->region, e, sizeof(*e)); 557 if(b->list == NULL) { 558 rbtree_delete(opt->zonefree, &b->linesize); 559 region_recycle(opt->region, b, sizeof(*b)); 560 } 561 opt->zonefree_number--; 562 return zone; 563 } 564 565 /* remove a zone on the zonelist */ 566 void 567 zone_list_del(nsd_options_t* opt, zone_options_t* zone) 568 { 569 /* put its space onto the free entry */ 570 if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) { 571 log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno)); 572 return; 573 } 574 fprintf(opt->zonelist, "del"); 575 zone_list_free_insert(opt, zone->linesize, zone->off); 576 577 /* remove zone_options_t */ 578 zone_options_delete(opt, zone); 579 580 /* see if we need to compact: it is going to halve the zonelist */ 581 if(opt->zonefree_number > opt->zone_options->count) { 582 zone_list_compact(opt); 583 } else { 584 if(fflush(opt->zonelist) != 0) { 585 log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno)); 586 } 587 } 588 } 589 /* postorder delete of zonelist free space tree */ 590 static void 591 delbucket(region_type* region, struct zonelist_bucket* b) 592 { 593 struct zonelist_free* e, *f; 594 if(!b || (rbnode_t*)b==RBTREE_NULL) 595 return; 596 delbucket(region, (struct zonelist_bucket*)b->node.left); 597 delbucket(region, (struct zonelist_bucket*)b->node.right); 598 e = b->list; 599 while(e) { 600 f = e->next; 601 region_recycle(region, e, sizeof(*e)); 602 e = f; 603 } 604 region_recycle(region, b, sizeof(*b)); 605 } 606 607 /* compact zonelist file */ 608 void 609 zone_list_compact(nsd_options_t* opt) 610 { 611 char outname[1024]; 612 FILE* out; 613 zone_options_t* zone; 614 off_t off; 615 int r; 616 snprintf(outname, sizeof(outname), "%s~", opt->zonelistfile); 617 /* useful, when : count-of-free > count-of-used */ 618 /* write zonelist to zonelist~ */ 619 out = fopen(outname, "w+"); 620 if(!out) { 621 log_msg(LOG_ERR, "could not open %s: %s", outname, strerror(errno)); 622 return; 623 } 624 r = fprintf(out, ZONELIST_HEADER); 625 if(r == -1) { 626 log_msg(LOG_ERR, "write %s failed: %s", outname, 627 strerror(errno)); 628 fclose(out); 629 return; 630 } else if(r != strlen(ZONELIST_HEADER)) { 631 log_msg(LOG_ERR, "write %s was partial: disk full", 632 outname); 633 fclose(out); 634 return; 635 } 636 off = ftello(out); 637 if(off == -1) { 638 log_msg(LOG_ERR, "ftello(%s): %s", outname, strerror(errno)); 639 fclose(out); 640 return; 641 } 642 RBTREE_FOR(zone, zone_options_t*, opt->zone_options) { 643 if(zone->part_of_config) 644 continue; 645 r = fprintf(out, "add %s %s\n", zone->name, 646 zone->pattern->pname); 647 if(r < 0) { 648 log_msg(LOG_ERR, "write %s failed: %s", outname, 649 strerror(errno)); 650 fclose(out); 651 return; 652 } else if(r != zone->linesize) { 653 log_msg(LOG_ERR, "write %s was partial: disk full", 654 outname); 655 fclose(out); 656 return; 657 } 658 } 659 if(fflush(out) != 0) { 660 log_msg(LOG_ERR, "fflush %s: %s", outname, strerror(errno)); 661 } 662 663 /* rename zonelist~ onto zonelist */ 664 if(rename(outname, opt->zonelistfile) == -1) { 665 log_msg(LOG_ERR, "rename(%s to %s) failed: %s", 666 outname, opt->zonelistfile, strerror(errno)); 667 fclose(out); 668 return; 669 } 670 fclose(opt->zonelist); 671 /* set offsets */ 672 RBTREE_FOR(zone, zone_options_t*, opt->zone_options) { 673 if(zone->part_of_config) 674 continue; 675 zone->off = off; 676 off += zone->linesize; 677 } 678 /* empty the free tree */ 679 delbucket(opt->region, (struct zonelist_bucket*)opt->zonefree->root); 680 opt->zonefree->root = RBTREE_NULL; 681 opt->zonefree->count = 0; 682 opt->zonefree_number = 0; 683 /* finish */ 684 opt->zonelist = out; 685 opt->zonelist_off = off; 686 } 687 688 /* close zonelist file */ 689 void 690 zone_list_close(nsd_options_t* opt) 691 { 692 fclose(opt->zonelist); 693 opt->zonelist = NULL; 694 } 695 696 void 697 c_error_va_list_pos(int showpos, const char* fmt, va_list args) 698 { 699 char* at = NULL; 700 cfg_parser->errors++; 701 if(showpos && c_text && c_text[0]!=0) { 702 at = c_text; 703 } 704 if(cfg_parser->err) { 705 char m[MAXSYSLOGMSGLEN]; 706 snprintf(m, sizeof(m), "%s:%d: ", cfg_parser->filename, 707 cfg_parser->line); 708 (*cfg_parser->err)(cfg_parser->err_arg, m); 709 if(at) { 710 snprintf(m, sizeof(m), "at '%s': ", at); 711 (*cfg_parser->err)(cfg_parser->err_arg, m); 712 } 713 (*cfg_parser->err)(cfg_parser->err_arg, "error: "); 714 vsnprintf(m, sizeof(m), fmt, args); 715 (*cfg_parser->err)(cfg_parser->err_arg, m); 716 (*cfg_parser->err)(cfg_parser->err_arg, "\n"); 717 return; 718 } 719 fprintf(stderr, "%s:%d: ", cfg_parser->filename, cfg_parser->line); 720 if(at) fprintf(stderr, "at '%s': ", at); 721 fprintf(stderr, "error: "); 722 vfprintf(stderr, fmt, args); 723 fprintf(stderr, "\n"); 724 } 725 726 void 727 c_error_msg_pos(int showpos, const char* fmt, ...) 728 { 729 va_list args; 730 va_start(args, fmt); 731 c_error_va_list_pos(showpos, fmt, args); 732 va_end(args); 733 } 734 735 void 736 c_error_msg(const char* fmt, ...) 737 { 738 va_list args; 739 va_start(args, fmt); 740 c_error_va_list_pos(0, fmt, args); 741 va_end(args); 742 } 743 744 void 745 c_error(const char* str) 746 { 747 if((strcmp(str, "syntax error")==0 || strcmp(str, "parse error")==0)) 748 c_error_msg_pos(1, "%s", str); 749 else c_error_msg("%s", str); 750 } 751 752 int 753 c_wrap() 754 { 755 return 1; 756 } 757 758 zone_options_t* 759 zone_options_create(region_type* region) 760 { 761 zone_options_t* zone; 762 zone = (zone_options_t*)region_alloc(region, sizeof(zone_options_t)); 763 zone->node = *RBTREE_NULL; 764 zone->name = 0; 765 zone->pattern = 0; 766 zone->part_of_config = 0; 767 return zone; 768 } 769 770 /* true is booleans are the same truth value */ 771 #define booleq(x,y) ( ((x) && (y)) || (!(x) && !(y)) ) 772 773 int 774 acl_equal(acl_options_t* p, acl_options_t* q) 775 { 776 if(!booleq(p->use_axfr_only, q->use_axfr_only)) return 0; 777 if(!booleq(p->allow_udp, q->allow_udp)) return 0; 778 if(strcmp(p->ip_address_spec, q->ip_address_spec)!=0) return 0; 779 /* the ip6, port, addr, mask, type: are derived from the ip_address_spec */ 780 if(!booleq(p->nokey, q->nokey)) return 0; 781 if(!booleq(p->blocked, q->blocked)) return 0; 782 if(p->key_name && q->key_name) { 783 if(strcmp(p->key_name, q->key_name)!=0) return 0; 784 } else if(p->key_name && !q->key_name) return 0; 785 else if(!p->key_name && q->key_name) return 0; 786 /* key_options is derived from key_name */ 787 return 1; 788 } 789 790 int 791 acl_list_equal(acl_options_t* p, acl_options_t* q) 792 { 793 /* must be same and in same order */ 794 while(p && q) { 795 if(!acl_equal(p, q)) 796 return 0; 797 p = p->next; 798 q = q->next; 799 } 800 if(!p && !q) return 1; 801 /* different lengths */ 802 return 0; 803 } 804 805 pattern_options_t* 806 pattern_options_create(region_type* region) 807 { 808 pattern_options_t* p; 809 p = (pattern_options_t*)region_alloc(region, sizeof(pattern_options_t)); 810 p->node = *RBTREE_NULL; 811 p->pname = 0; 812 p->zonefile = 0; 813 p->zonestats = 0; 814 p->allow_notify = 0; 815 p->request_xfr = 0; 816 p->size_limit_xfr = 0; 817 p->notify = 0; 818 p->provide_xfr = 0; 819 p->outgoing_interface = 0; 820 p->notify_retry = 5; 821 p->notify_retry_is_default = 1; 822 p->allow_axfr_fallback = 1; 823 p->allow_axfr_fallback_is_default = 1; 824 p->implicit = 0; 825 p->xfrd_flags = 0; 826 p->max_refresh_time = 2419200; /* 4 weeks */ 827 p->max_refresh_time_is_default = 1; 828 p->min_refresh_time = 0; 829 p->min_refresh_time_is_default = 1; 830 p->max_retry_time = 1209600; /* 2 weeks */ 831 p->max_retry_time_is_default = 1; 832 p->min_retry_time = 0; 833 p->min_retry_time_is_default = 1; 834 #ifdef RATELIMIT 835 p->rrl_whitelist = 0; 836 #endif 837 return p; 838 } 839 840 static void 841 acl_delete(region_type* region, acl_options_t* acl) 842 { 843 if(acl->ip_address_spec) 844 region_recycle(region, (void*)acl->ip_address_spec, 845 strlen(acl->ip_address_spec)+1); 846 if(acl->key_name) 847 region_recycle(region, (void*)acl->key_name, 848 strlen(acl->key_name)+1); 849 /* key_options is a convenience pointer, not owned by the acl */ 850 region_recycle(region, acl, sizeof(*acl)); 851 } 852 853 static void 854 acl_list_delete(region_type* region, acl_options_t* list) 855 { 856 acl_options_t* n; 857 while(list) { 858 n = list->next; 859 acl_delete(region, list); 860 list = n; 861 } 862 } 863 864 void 865 pattern_options_remove(nsd_options_t* opt, const char* name) 866 { 867 pattern_options_t* p = (pattern_options_t*)rbtree_delete( 868 opt->patterns, name); 869 /* delete p and its contents */ 870 if (!p) 871 return; 872 if(p->pname) 873 region_recycle(opt->region, (void*)p->pname, 874 strlen(p->pname)+1); 875 if(p->zonefile) 876 region_recycle(opt->region, (void*)p->zonefile, 877 strlen(p->zonefile)+1); 878 if(p->zonestats) 879 region_recycle(opt->region, (void*)p->zonestats, 880 strlen(p->zonestats)+1); 881 acl_list_delete(opt->region, p->allow_notify); 882 acl_list_delete(opt->region, p->request_xfr); 883 acl_list_delete(opt->region, p->notify); 884 acl_list_delete(opt->region, p->provide_xfr); 885 acl_list_delete(opt->region, p->outgoing_interface); 886 887 region_recycle(opt->region, p, sizeof(pattern_options_t)); 888 } 889 890 static acl_options_t* 891 copy_acl(region_type* region, acl_options_t* a) 892 { 893 acl_options_t* b; 894 if(!a) return NULL; 895 b = (acl_options_t*)region_alloc(region, sizeof(*b)); 896 /* copy the whole lot */ 897 *b = *a; 898 /* fix the pointers */ 899 if(a->ip_address_spec) 900 b->ip_address_spec = region_strdup(region, a->ip_address_spec); 901 if(a->key_name) 902 b->key_name = region_strdup(region, a->key_name); 903 b->next = NULL; 904 b->key_options = NULL; 905 return b; 906 } 907 908 static acl_options_t* 909 copy_acl_list(nsd_options_t* opt, acl_options_t* a) 910 { 911 acl_options_t* b, *blast = NULL, *blist = NULL; 912 while(a) { 913 b = copy_acl(opt->region, a); 914 /* fixup key_options */ 915 if(b->key_name) 916 b->key_options = key_options_find(opt, b->key_name); 917 else b->key_options = NULL; 918 919 /* link as last into list */ 920 b->next = NULL; 921 if(!blist) blist = b; 922 else blast->next = b; 923 blast = b; 924 925 a = a->next; 926 } 927 return blist; 928 } 929 930 static void 931 copy_changed_acl(nsd_options_t* opt, acl_options_t** orig, 932 acl_options_t* anew) 933 { 934 if(!acl_list_equal(*orig, anew)) { 935 acl_list_delete(opt->region, *orig); 936 *orig = copy_acl_list(opt, anew); 937 } 938 } 939 940 static void 941 copy_pat_fixed(region_type* region, pattern_options_t* orig, 942 pattern_options_t* p) 943 { 944 orig->allow_axfr_fallback = p->allow_axfr_fallback; 945 orig->allow_axfr_fallback_is_default = 946 p->allow_axfr_fallback_is_default; 947 orig->notify_retry = p->notify_retry; 948 orig->notify_retry_is_default = p->notify_retry_is_default; 949 orig->implicit = p->implicit; 950 if(p->zonefile) 951 orig->zonefile = region_strdup(region, p->zonefile); 952 else orig->zonefile = NULL; 953 if(p->zonestats) 954 orig->zonestats = region_strdup(region, p->zonestats); 955 else orig->zonestats = NULL; 956 orig->max_refresh_time = p->max_refresh_time; 957 orig->max_refresh_time_is_default = p->max_refresh_time_is_default; 958 orig->min_refresh_time = p->min_refresh_time; 959 orig->min_refresh_time_is_default = p->min_refresh_time_is_default; 960 orig->max_retry_time = p->max_retry_time; 961 orig->max_retry_time_is_default = p->max_retry_time_is_default; 962 orig->min_retry_time = p->min_retry_time; 963 orig->min_retry_time_is_default = p->min_retry_time_is_default; 964 #ifdef RATELIMIT 965 orig->rrl_whitelist = p->rrl_whitelist; 966 #endif 967 } 968 969 void 970 pattern_options_add_modify(nsd_options_t* opt, pattern_options_t* p) 971 { 972 pattern_options_t* orig = pattern_options_find(opt, p->pname); 973 if(!orig) { 974 /* needs to be copied to opt region */ 975 orig = pattern_options_create(opt->region); 976 orig->pname = region_strdup(opt->region, p->pname); 977 copy_pat_fixed(opt->region, orig, p); 978 orig->allow_notify = copy_acl_list(opt, p->allow_notify); 979 orig->request_xfr = copy_acl_list(opt, p->request_xfr); 980 orig->notify = copy_acl_list(opt, p->notify); 981 orig->provide_xfr = copy_acl_list(opt, p->provide_xfr); 982 orig->outgoing_interface = copy_acl_list(opt, 983 p->outgoing_interface); 984 nsd_options_insert_pattern(opt, orig); 985 } else { 986 /* modify in place so pointers stay valid (and copy 987 into region). Do not touch unchanged acls. */ 988 if(orig->zonefile) 989 region_recycle(opt->region, (char*)orig->zonefile, 990 strlen(orig->zonefile)+1); 991 if(orig->zonestats) 992 region_recycle(opt->region, (char*)orig->zonestats, 993 strlen(orig->zonestats)+1); 994 copy_pat_fixed(opt->region, orig, p); 995 copy_changed_acl(opt, &orig->allow_notify, p->allow_notify); 996 copy_changed_acl(opt, &orig->request_xfr, p->request_xfr); 997 copy_changed_acl(opt, &orig->notify, p->notify); 998 copy_changed_acl(opt, &orig->provide_xfr, p->provide_xfr); 999 copy_changed_acl(opt, &orig->outgoing_interface, 1000 p->outgoing_interface); 1001 } 1002 } 1003 1004 pattern_options_t* 1005 pattern_options_find(nsd_options_t* opt, const char* name) 1006 { 1007 return (pattern_options_t*)rbtree_search(opt->patterns, name); 1008 } 1009 1010 int 1011 pattern_options_equal(pattern_options_t* p, pattern_options_t* q) 1012 { 1013 if(strcmp(p->pname, q->pname) != 0) return 0; 1014 if(!p->zonefile && q->zonefile) return 0; 1015 else if(p->zonefile && !q->zonefile) return 0; 1016 else if(p->zonefile && q->zonefile) { 1017 if(strcmp(p->zonefile, q->zonefile) != 0) return 0; 1018 } 1019 if(!p->zonestats && q->zonestats) return 0; 1020 else if(p->zonestats && !q->zonestats) return 0; 1021 else if(p->zonestats && q->zonestats) { 1022 if(strcmp(p->zonestats, q->zonestats) != 0) return 0; 1023 } 1024 if(!booleq(p->allow_axfr_fallback, q->allow_axfr_fallback)) return 0; 1025 if(!booleq(p->allow_axfr_fallback_is_default, 1026 q->allow_axfr_fallback_is_default)) return 0; 1027 if(p->notify_retry != q->notify_retry) return 0; 1028 if(!booleq(p->notify_retry_is_default, 1029 q->notify_retry_is_default)) return 0; 1030 if(!booleq(p->implicit, q->implicit)) return 0; 1031 if(!acl_list_equal(p->allow_notify, q->allow_notify)) return 0; 1032 if(!acl_list_equal(p->request_xfr, q->request_xfr)) return 0; 1033 if(!acl_list_equal(p->notify, q->notify)) return 0; 1034 if(!acl_list_equal(p->provide_xfr, q->provide_xfr)) return 0; 1035 if(!acl_list_equal(p->outgoing_interface, q->outgoing_interface)) 1036 return 0; 1037 if(p->max_refresh_time != q->max_refresh_time) return 0; 1038 if(!booleq(p->max_refresh_time_is_default, 1039 q->max_refresh_time_is_default)) return 0; 1040 if(p->min_refresh_time != q->min_refresh_time) return 0; 1041 if(!booleq(p->min_refresh_time_is_default, 1042 q->min_refresh_time_is_default)) return 0; 1043 if(p->max_retry_time != q->max_retry_time) return 0; 1044 if(!booleq(p->max_retry_time_is_default, 1045 q->max_retry_time_is_default)) return 0; 1046 if(p->min_retry_time != q->min_retry_time) return 0; 1047 if(!booleq(p->min_retry_time_is_default, 1048 q->min_retry_time_is_default)) return 0; 1049 #ifdef RATELIMIT 1050 if(p->rrl_whitelist != q->rrl_whitelist) return 0; 1051 #endif 1052 if(p->size_limit_xfr != q->size_limit_xfr) return 0; 1053 return 1; 1054 } 1055 1056 static void 1057 marshal_u8(struct buffer* b, uint8_t v) 1058 { 1059 buffer_reserve(b, 1); 1060 buffer_write_u8(b, v); 1061 } 1062 1063 static uint8_t 1064 unmarshal_u8(struct buffer* b) 1065 { 1066 return buffer_read_u8(b); 1067 } 1068 1069 static void 1070 marshal_u64(struct buffer* b, uint64_t v) 1071 { 1072 buffer_reserve(b, 8); 1073 buffer_write_u64(b, v); 1074 } 1075 1076 static uint64_t 1077 unmarshal_u64(struct buffer* b) 1078 { 1079 return buffer_read_u64(b); 1080 } 1081 1082 #ifdef RATELIMIT 1083 static void 1084 marshal_u16(struct buffer* b, uint16_t v) 1085 { 1086 buffer_reserve(b, 2); 1087 buffer_write_u16(b, v); 1088 } 1089 #endif 1090 1091 #ifdef RATELIMIT 1092 static uint16_t 1093 unmarshal_u16(struct buffer* b) 1094 { 1095 return buffer_read_u16(b); 1096 } 1097 #endif 1098 1099 static void 1100 marshal_u32(struct buffer* b, uint32_t v) 1101 { 1102 buffer_reserve(b, 4); 1103 buffer_write_u32(b, v); 1104 } 1105 1106 static uint32_t 1107 unmarshal_u32(struct buffer* b) 1108 { 1109 return buffer_read_u32(b); 1110 } 1111 1112 static void 1113 marshal_str(struct buffer* b, const char* s) 1114 { 1115 if(!s) marshal_u8(b, 0); 1116 else { 1117 size_t len = strlen(s); 1118 marshal_u8(b, 1); 1119 buffer_reserve(b, len+1); 1120 buffer_write(b, s, len+1); 1121 } 1122 } 1123 1124 static char* 1125 unmarshal_str(region_type* r, struct buffer* b) 1126 { 1127 uint8_t nonnull = unmarshal_u8(b); 1128 if(nonnull) { 1129 char* result = region_strdup(r, (char*)buffer_current(b)); 1130 size_t len = strlen((char*)buffer_current(b)); 1131 buffer_skip(b, len+1); 1132 return result; 1133 } else return NULL; 1134 } 1135 1136 static void 1137 marshal_acl(struct buffer* b, acl_options_t* acl) 1138 { 1139 buffer_reserve(b, sizeof(*acl)); 1140 buffer_write(b, acl, sizeof(*acl)); 1141 marshal_str(b, acl->ip_address_spec); 1142 marshal_str(b, acl->key_name); 1143 } 1144 1145 static acl_options_t* 1146 unmarshal_acl(region_type* r, struct buffer* b) 1147 { 1148 acl_options_t* acl = (acl_options_t*)region_alloc(r, sizeof(*acl)); 1149 buffer_read(b, acl, sizeof(*acl)); 1150 acl->next = NULL; 1151 acl->key_options = NULL; 1152 acl->ip_address_spec = unmarshal_str(r, b); 1153 acl->key_name = unmarshal_str(r, b); 1154 return acl; 1155 } 1156 1157 static void 1158 marshal_acl_list(struct buffer* b, acl_options_t* list) 1159 { 1160 while(list) { 1161 marshal_u8(b, 1); /* is there a next one marker */ 1162 marshal_acl(b, list); 1163 list = list->next; 1164 } 1165 marshal_u8(b, 0); /* end of list marker */ 1166 } 1167 1168 static acl_options_t* 1169 unmarshal_acl_list(region_type* r, struct buffer* b) 1170 { 1171 acl_options_t* a, *last=NULL, *list=NULL; 1172 while(unmarshal_u8(b)) { 1173 a = unmarshal_acl(r, b); 1174 /* link in */ 1175 a->next = NULL; 1176 if(!list) list = a; 1177 else last->next = a; 1178 last = a; 1179 } 1180 return list; 1181 } 1182 1183 void 1184 pattern_options_marshal(struct buffer* b, pattern_options_t* p) 1185 { 1186 marshal_str(b, p->pname); 1187 marshal_str(b, p->zonefile); 1188 marshal_str(b, p->zonestats); 1189 #ifdef RATELIMIT 1190 marshal_u16(b, p->rrl_whitelist); 1191 #endif 1192 marshal_u8(b, p->allow_axfr_fallback); 1193 marshal_u8(b, p->allow_axfr_fallback_is_default); 1194 marshal_u8(b, p->notify_retry); 1195 marshal_u8(b, p->notify_retry_is_default); 1196 marshal_u8(b, p->implicit); 1197 marshal_u64(b, p->size_limit_xfr); 1198 marshal_acl_list(b, p->allow_notify); 1199 marshal_acl_list(b, p->request_xfr); 1200 marshal_acl_list(b, p->notify); 1201 marshal_acl_list(b, p->provide_xfr); 1202 marshal_acl_list(b, p->outgoing_interface); 1203 marshal_u32(b, p->max_refresh_time); 1204 marshal_u8(b, p->max_refresh_time_is_default); 1205 marshal_u32(b, p->min_refresh_time); 1206 marshal_u8(b, p->min_refresh_time_is_default); 1207 marshal_u32(b, p->max_retry_time); 1208 marshal_u8(b, p->max_retry_time_is_default); 1209 marshal_u32(b, p->min_retry_time); 1210 marshal_u8(b, p->min_retry_time_is_default); 1211 } 1212 1213 pattern_options_t* 1214 pattern_options_unmarshal(region_type* r, struct buffer* b) 1215 { 1216 pattern_options_t* p = pattern_options_create(r); 1217 p->pname = unmarshal_str(r, b); 1218 p->zonefile = unmarshal_str(r, b); 1219 p->zonestats = unmarshal_str(r, b); 1220 #ifdef RATELIMIT 1221 p->rrl_whitelist = unmarshal_u16(b); 1222 #endif 1223 p->allow_axfr_fallback = unmarshal_u8(b); 1224 p->allow_axfr_fallback_is_default = unmarshal_u8(b); 1225 p->notify_retry = unmarshal_u8(b); 1226 p->notify_retry_is_default = unmarshal_u8(b); 1227 p->implicit = unmarshal_u8(b); 1228 p->size_limit_xfr = unmarshal_u64(b); 1229 p->allow_notify = unmarshal_acl_list(r, b); 1230 p->request_xfr = unmarshal_acl_list(r, b); 1231 p->notify = unmarshal_acl_list(r, b); 1232 p->provide_xfr = unmarshal_acl_list(r, b); 1233 p->outgoing_interface = unmarshal_acl_list(r, b); 1234 p->max_refresh_time = unmarshal_u32(b); 1235 p->max_refresh_time_is_default = unmarshal_u8(b); 1236 p->min_refresh_time = unmarshal_u32(b); 1237 p->min_refresh_time_is_default = unmarshal_u8(b); 1238 p->max_retry_time = unmarshal_u32(b); 1239 p->max_retry_time_is_default = unmarshal_u8(b); 1240 p->min_retry_time = unmarshal_u32(b); 1241 p->min_retry_time_is_default = unmarshal_u8(b); 1242 return p; 1243 } 1244 1245 key_options_t* 1246 key_options_create(region_type* region) 1247 { 1248 key_options_t* key; 1249 key = (key_options_t*)region_alloc_zero(region, sizeof(key_options_t)); 1250 return key; 1251 } 1252 1253 void 1254 key_options_insert(nsd_options_t* opt, key_options_t* key) 1255 { 1256 if(!key->name) return; 1257 key->node.key = key->name; 1258 (void)rbtree_insert(opt->keys, &key->node); 1259 } 1260 1261 key_options_t* 1262 key_options_find(nsd_options_t* opt, const char* name) 1263 { 1264 return (key_options_t*)rbtree_search(opt->keys, name); 1265 } 1266 1267 /** remove tsig_key contents */ 1268 void 1269 key_options_desetup(region_type* region, key_options_t* key) 1270 { 1271 /* keep tsig_key pointer so that existing references keep valid */ 1272 if(!key->tsig_key) 1273 return; 1274 /* name stays the same */ 1275 if(key->tsig_key->data) { 1276 /* wipe secret! */ 1277 memset(key->tsig_key->data, 0xdd, key->tsig_key->size); 1278 region_recycle(region, key->tsig_key->data, 1279 key->tsig_key->size); 1280 key->tsig_key->data = NULL; 1281 key->tsig_key->size = 0; 1282 } 1283 } 1284 1285 /** add tsig_key contents */ 1286 void 1287 key_options_setup(region_type* region, key_options_t* key) 1288 { 1289 uint8_t data[16384]; /* 16KB */ 1290 int size; 1291 if(!key->tsig_key) { 1292 /* create it */ 1293 key->tsig_key = (tsig_key_type *) region_alloc(region, 1294 sizeof(tsig_key_type)); 1295 /* create name */ 1296 key->tsig_key->name = dname_parse(region, key->name); 1297 if(!key->tsig_key->name) { 1298 log_msg(LOG_ERR, "Failed to parse tsig key name %s", 1299 key->name); 1300 /* key and base64 were checked during syntax parse */ 1301 exit(1); 1302 } 1303 key->tsig_key->size = 0; 1304 key->tsig_key->data = NULL; 1305 } 1306 size = __b64_pton(key->secret, data, sizeof(data)); 1307 if(size == -1) { 1308 log_msg(LOG_ERR, "Failed to parse tsig key data %s", 1309 key->name); 1310 /* key and base64 were checked during syntax parse */ 1311 exit(1); 1312 } 1313 key->tsig_key->size = size; 1314 key->tsig_key->data = (uint8_t *)region_alloc_init(region, data, size); 1315 } 1316 1317 void 1318 key_options_remove(nsd_options_t* opt, const char* name) 1319 { 1320 key_options_t* k = key_options_find(opt, name); 1321 if(!k) return; 1322 (void)rbtree_delete(opt->keys, name); 1323 if(k->name) 1324 region_recycle(opt->region, k->name, strlen(k->name)+1); 1325 if(k->algorithm) 1326 region_recycle(opt->region, k->algorithm, strlen(k->algorithm)+1); 1327 if(k->secret) { 1328 memset(k->secret, 0xdd, strlen(k->secret)); /* wipe secret! */ 1329 region_recycle(opt->region, k->secret, strlen(k->secret)+1); 1330 } 1331 if(k->tsig_key) { 1332 tsig_del_key(k->tsig_key); 1333 if(k->tsig_key->name) 1334 region_recycle(opt->region, (void*)k->tsig_key->name, 1335 dname_total_size(k->tsig_key->name)); 1336 key_options_desetup(opt->region, k); 1337 region_recycle(opt->region, k->tsig_key, sizeof(tsig_key_type)); 1338 } 1339 region_recycle(opt->region, k, sizeof(key_options_t)); 1340 } 1341 1342 int 1343 key_options_equal(key_options_t* p, key_options_t* q) 1344 { 1345 return strcmp(p->name, q->name)==0 && strcmp(p->algorithm, 1346 q->algorithm)==0 && strcmp(p->secret, q->secret)==0; 1347 } 1348 1349 void 1350 key_options_add_modify(nsd_options_t* opt, key_options_t* key) 1351 { 1352 key_options_t* orig = key_options_find(opt, key->name); 1353 if(!orig) { 1354 /* needs to be copied to opt region */ 1355 orig = key_options_create(opt->region); 1356 orig->name = region_strdup(opt->region, key->name); 1357 orig->algorithm = region_strdup(opt->region, key->algorithm); 1358 orig->secret = region_strdup(opt->region, key->secret); 1359 key_options_setup(opt->region, orig); 1360 tsig_add_key(orig->tsig_key); 1361 key_options_insert(opt, orig); 1362 } else { 1363 /* modify entries in existing key, and copy to opt region */ 1364 key_options_desetup(opt->region, orig); 1365 region_recycle(opt->region, orig->algorithm, 1366 strlen(orig->algorithm)+1); 1367 orig->algorithm = region_strdup(opt->region, key->algorithm); 1368 region_recycle(opt->region, orig->secret, 1369 strlen(orig->secret)+1); 1370 orig->secret = region_strdup(opt->region, key->secret); 1371 key_options_setup(opt->region, orig); 1372 } 1373 } 1374 1375 int 1376 acl_check_incoming(acl_options_t* acl, struct query* q, 1377 acl_options_t** reason) 1378 { 1379 /* check each acl element. 1380 if 1 blocked element matches - return -1. 1381 if any element matches - return number. 1382 else return -1. */ 1383 int found_match = -1; 1384 int number = 0; 1385 acl_options_t* match = 0; 1386 1387 if(reason) 1388 *reason = NULL; 1389 1390 while(acl) 1391 { 1392 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "testing acl %s %s", 1393 acl->ip_address_spec, acl->nokey?"NOKEY": 1394 (acl->blocked?"BLOCKED":acl->key_name))); 1395 if(acl_addr_matches(acl, q) && acl_key_matches(acl, q)) { 1396 if(!match) 1397 { 1398 match = acl; /* remember first match */ 1399 found_match=number; 1400 } 1401 if(acl->blocked) { 1402 if(reason) 1403 *reason = acl; 1404 return -1; 1405 } 1406 } 1407 number++; 1408 acl = acl->next; 1409 } 1410 1411 if(reason) 1412 *reason = match; 1413 return found_match; 1414 } 1415 1416 #ifdef INET6 1417 int 1418 acl_addr_matches_ipv6host(acl_options_t* acl, struct sockaddr_storage* addr_storage, unsigned int port) 1419 { 1420 struct sockaddr_in6* addr = (struct sockaddr_in6*)addr_storage; 1421 if(acl->port != 0 && acl->port != port) 1422 return 0; 1423 switch(acl->rangetype) { 1424 case acl_range_mask: 1425 case acl_range_subnet: 1426 if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr, 1427 (uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr))) 1428 return 0; 1429 break; 1430 case acl_range_minmax: 1431 if(!acl_addr_match_range((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr, 1432 (uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr))) 1433 return 0; 1434 break; 1435 case acl_range_single: 1436 default: 1437 if(memcmp(&addr->sin6_addr, &acl->addr.addr6, 1438 sizeof(struct in6_addr)) != 0) 1439 return 0; 1440 break; 1441 } 1442 return 1; 1443 } 1444 #endif 1445 1446 int 1447 acl_addr_matches_ipv4host(acl_options_t* acl, struct sockaddr_in* addr, unsigned int port) 1448 { 1449 if(acl->port != 0 && acl->port != port) 1450 return 0; 1451 switch(acl->rangetype) { 1452 case acl_range_mask: 1453 case acl_range_subnet: 1454 if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr, 1455 (uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr))) 1456 return 0; 1457 break; 1458 case acl_range_minmax: 1459 if(!acl_addr_match_range((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr, 1460 (uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr))) 1461 return 0; 1462 break; 1463 case acl_range_single: 1464 default: 1465 if(memcmp(&addr->sin_addr, &acl->addr.addr, 1466 sizeof(struct in_addr)) != 0) 1467 return 0; 1468 break; 1469 } 1470 return 1; 1471 } 1472 1473 int 1474 acl_addr_matches_host(acl_options_t* acl, acl_options_t* host) 1475 { 1476 if(acl->is_ipv6) 1477 { 1478 #ifdef INET6 1479 struct sockaddr_storage* addr = (struct sockaddr_storage*)&host->addr; 1480 if(!host->is_ipv6) return 0; 1481 return acl_addr_matches_ipv6host(acl, addr, host->port); 1482 #else 1483 return 0; /* no inet6, no match */ 1484 #endif 1485 } 1486 else 1487 { 1488 struct sockaddr_in* addr = (struct sockaddr_in*)&host->addr; 1489 if(host->is_ipv6) return 0; 1490 return acl_addr_matches_ipv4host(acl, addr, host->port); 1491 } 1492 /* ENOTREACH */ 1493 return 0; 1494 } 1495 1496 int 1497 acl_addr_matches(acl_options_t* acl, struct query* q) 1498 { 1499 if(acl->is_ipv6) 1500 { 1501 #ifdef INET6 1502 struct sockaddr_storage* addr = (struct sockaddr_storage*)&q->addr; 1503 if(addr->ss_family != AF_INET6) 1504 return 0; 1505 return acl_addr_matches_ipv6host(acl, addr, ntohs(((struct sockaddr_in6*)addr)->sin6_port)); 1506 #else 1507 return 0; /* no inet6, no match */ 1508 #endif 1509 } 1510 else 1511 { 1512 struct sockaddr_in* addr = (struct sockaddr_in*)&q->addr; 1513 if(addr->sin_family != AF_INET) 1514 return 0; 1515 return acl_addr_matches_ipv4host(acl, addr, ntohs(addr->sin_port)); 1516 } 1517 /* ENOTREACH */ 1518 return 0; 1519 } 1520 1521 int 1522 acl_addr_match_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz) 1523 { 1524 size_t i; 1525 #ifndef NDEBUG 1526 assert(sz % 4 == 0); 1527 #endif 1528 sz /= 4; 1529 for(i=0; i<sz; ++i) 1530 { 1531 if(((*a++)&*mask) != ((*b++)&*mask)) 1532 return 0; 1533 ++mask; 1534 } 1535 return 1; 1536 } 1537 1538 int 1539 acl_addr_match_range(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz) 1540 { 1541 size_t i; 1542 uint8_t checkmin = 1, checkmax = 1; 1543 #ifndef NDEBUG 1544 assert(sz % 4 == 0); 1545 #endif 1546 /* check treats x as one huge number */ 1547 sz /= 4; 1548 for(i=0; i<sz; ++i) 1549 { 1550 /* if outside bounds, we are done */ 1551 if(checkmin) 1552 if(minval[i] > x[i]) 1553 return 0; 1554 if(checkmax) 1555 if(maxval[i] < x[i]) 1556 return 0; 1557 /* if x is equal to a bound, that bound needs further checks */ 1558 if(checkmin && minval[i]!=x[i]) 1559 checkmin = 0; 1560 if(checkmax && maxval[i]!=x[i]) 1561 checkmax = 0; 1562 if(!checkmin && !checkmax) 1563 return 1; /* will always match */ 1564 } 1565 return 1; 1566 } 1567 1568 int 1569 acl_key_matches(acl_options_t* acl, struct query* q) 1570 { 1571 if(acl->blocked) 1572 return 1; 1573 if(acl->nokey) { 1574 if(q->tsig.status == TSIG_NOT_PRESENT) 1575 return 1; 1576 return 0; 1577 } 1578 /* check name of tsig key */ 1579 if(q->tsig.status != TSIG_OK) { 1580 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail query has no TSIG")); 1581 return 0; /* query has no TSIG */ 1582 } 1583 if(q->tsig.error_code != TSIG_ERROR_NOERROR) { 1584 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail, tsig has error")); 1585 return 0; /* some tsig error */ 1586 } 1587 if(!acl->key_options->tsig_key) { 1588 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail no config")); 1589 return 0; /* key not properly configured */ 1590 } 1591 if(dname_compare(q->tsig.key_name, 1592 acl->key_options->tsig_key->name) != 0) { 1593 DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail wrong key name")); 1594 return 0; /* wrong key name */ 1595 } 1596 if(tsig_strlowercmp(q->tsig.algorithm->short_name, 1597 acl->key_options->algorithm) != 0) { 1598 DEBUG(DEBUG_XFRD,2, (LOG_ERR, "query tsig wrong algorithm")); 1599 return 0; /* no such algo */ 1600 } 1601 return 1; 1602 } 1603 1604 int 1605 acl_same_host(acl_options_t* a, acl_options_t* b) 1606 { 1607 if(a->is_ipv6 && !b->is_ipv6) 1608 return 0; 1609 if(!a->is_ipv6 && b->is_ipv6) 1610 return 0; 1611 if(a->port != b->port) 1612 return 0; 1613 if(a->rangetype != b->rangetype) 1614 return 0; 1615 if(!a->is_ipv6) { 1616 if(memcmp(&a->addr.addr, &b->addr.addr, 1617 sizeof(struct in_addr)) != 0) 1618 return 0; 1619 if(a->rangetype != acl_range_single && 1620 memcmp(&a->range_mask.addr, &b->range_mask.addr, 1621 sizeof(struct in_addr)) != 0) 1622 return 0; 1623 } else { 1624 #ifdef INET6 1625 if(memcmp(&a->addr.addr6, &b->addr.addr6, 1626 sizeof(struct in6_addr)) != 0) 1627 return 0; 1628 if(a->rangetype != acl_range_single && 1629 memcmp(&a->range_mask.addr6, &b->range_mask.addr6, 1630 sizeof(struct in6_addr)) != 0) 1631 return 0; 1632 #else 1633 return 0; 1634 #endif 1635 } 1636 return 1; 1637 } 1638 1639 #if defined(HAVE_SSL) 1640 void 1641 key_options_tsig_add(nsd_options_t* opt) 1642 { 1643 key_options_t* optkey; 1644 RBTREE_FOR(optkey, key_options_t*, opt->keys) { 1645 key_options_setup(opt->region, optkey); 1646 tsig_add_key(optkey->tsig_key); 1647 } 1648 } 1649 #endif 1650 1651 int 1652 zone_is_slave(zone_options_t* opt) 1653 { 1654 return opt && opt->pattern && opt->pattern->request_xfr != 0; 1655 } 1656 1657 /* get a character in string (or replacement char if not long enough) */ 1658 static const char* 1659 get_char(const char* str, size_t i) 1660 { 1661 static char res[2]; 1662 if(i >= strlen(str)) 1663 return "."; 1664 res[0] = str[i]; 1665 res[1] = 0; 1666 return res; 1667 } 1668 /* get end label of the zone name (or .) */ 1669 static const char* 1670 get_end_label(zone_options_t* zone, int i) 1671 { 1672 const dname_type* d = (const dname_type*)zone->node.key; 1673 if(i >= d->label_count) { 1674 return "."; 1675 } 1676 return wirelabel2str(dname_label(d, i)); 1677 } 1678 /* replace occurrences of one with two */ 1679 void 1680 replace_str(char* str, size_t len, const char* one, const char* two) 1681 { 1682 char* pos; 1683 char* at = str; 1684 while( (pos=strstr(at, one)) ) { 1685 if(strlen(str)+strlen(two)-strlen(one) >= len) 1686 return; /* no more space to replace */ 1687 /* stuff before pos is fine */ 1688 /* move the stuff after pos to make space for two, add 1689 * one to length of remainder to also copy the 0 byte end */ 1690 memmove(pos+strlen(two), pos+strlen(one), 1691 strlen(pos+strlen(one))+1); 1692 /* copy in two */ 1693 memmove(pos, two, strlen(two)); 1694 /* at is end of the newly inserted two (avoids recursion if 1695 * two contains one) */ 1696 at = pos+strlen(two); 1697 } 1698 } 1699 1700 const char* 1701 config_cook_string(zone_options_t* zone, const char* input) 1702 { 1703 static char f[1024]; 1704 /* if not a template, return as-is */ 1705 if(!strchr(input, '%')) { 1706 return input; 1707 } 1708 strlcpy(f, input, sizeof(f)); 1709 if(strstr(f, "%1")) 1710 replace_str(f, sizeof(f), "%1", get_char(zone->name, 0)); 1711 if(strstr(f, "%2")) 1712 replace_str(f, sizeof(f), "%2", get_char(zone->name, 1)); 1713 if(strstr(f, "%3")) 1714 replace_str(f, sizeof(f), "%3", get_char(zone->name, 2)); 1715 if(strstr(f, "%z")) 1716 replace_str(f, sizeof(f), "%z", get_end_label(zone, 1)); 1717 if(strstr(f, "%y")) 1718 replace_str(f, sizeof(f), "%y", get_end_label(zone, 2)); 1719 if(strstr(f, "%x")) 1720 replace_str(f, sizeof(f), "%x", get_end_label(zone, 3)); 1721 if(strstr(f, "%s")) 1722 replace_str(f, sizeof(f), "%s", zone->name); 1723 return f; 1724 } 1725 1726 const char* 1727 config_make_zonefile(zone_options_t* zone, struct nsd* nsd) 1728 { 1729 static char f[1024]; 1730 /* if not a template, return as-is */ 1731 if(!strchr(zone->pattern->zonefile, '%')) { 1732 if (nsd->chrootdir && nsd->chrootdir[0] && 1733 zone->pattern->zonefile && 1734 zone->pattern->zonefile[0] == '/' && 1735 strncmp(zone->pattern->zonefile, nsd->chrootdir, 1736 strlen(nsd->chrootdir)) == 0) 1737 /* -1 because chrootdir ends in trailing slash */ 1738 return zone->pattern->zonefile + strlen(nsd->chrootdir) - 1; 1739 return zone->pattern->zonefile; 1740 } 1741 strlcpy(f, zone->pattern->zonefile, sizeof(f)); 1742 if(strstr(f, "%1")) 1743 replace_str(f, sizeof(f), "%1", get_char(zone->name, 0)); 1744 if(strstr(f, "%2")) 1745 replace_str(f, sizeof(f), "%2", get_char(zone->name, 1)); 1746 if(strstr(f, "%3")) 1747 replace_str(f, sizeof(f), "%3", get_char(zone->name, 2)); 1748 if(strstr(f, "%z")) 1749 replace_str(f, sizeof(f), "%z", get_end_label(zone, 1)); 1750 if(strstr(f, "%y")) 1751 replace_str(f, sizeof(f), "%y", get_end_label(zone, 2)); 1752 if(strstr(f, "%x")) 1753 replace_str(f, sizeof(f), "%x", get_end_label(zone, 3)); 1754 if(strstr(f, "%s")) 1755 replace_str(f, sizeof(f), "%s", zone->name); 1756 if (nsd->chrootdir && nsd->chrootdir[0] && f[0] == '/' && 1757 strncmp(f, nsd->chrootdir, strlen(nsd->chrootdir)) == 0) 1758 /* -1 because chrootdir ends in trailing slash */ 1759 return f + strlen(nsd->chrootdir) - 1; 1760 return f; 1761 } 1762 1763 zone_options_t* 1764 zone_options_find(nsd_options_t* opt, const struct dname* apex) 1765 { 1766 return (zone_options_t*) rbtree_search(opt->zone_options, apex); 1767 } 1768 1769 acl_options_t* 1770 acl_find_num(acl_options_t* acl, int num) 1771 { 1772 int count = num; 1773 if(num < 0) 1774 return 0; 1775 while(acl && count > 0) { 1776 acl = acl->next; 1777 count--; 1778 } 1779 if(count == 0) 1780 return acl; 1781 return 0; 1782 } 1783 1784 /* true if ipv6 address, false if ipv4 */ 1785 int 1786 parse_acl_is_ipv6(const char* p) 1787 { 1788 /* see if addr is ipv6 or ipv4 -- by : and . */ 1789 while(*p) { 1790 if(*p == '.') return 0; 1791 if(*p == ':') return 1; 1792 ++p; 1793 } 1794 return 0; 1795 } 1796 1797 /* returns range type. mask is the 2nd part of the range */ 1798 int 1799 parse_acl_range_type(char* ip, char** mask) 1800 { 1801 char *p; 1802 if((p=strchr(ip, '&'))!=0) { 1803 *p = 0; 1804 *mask = p+1; 1805 return acl_range_mask; 1806 } 1807 if((p=strchr(ip, '/'))!=0) { 1808 *p = 0; 1809 *mask = p+1; 1810 return acl_range_subnet; 1811 } 1812 if((p=strchr(ip, '-'))!=0) { 1813 *p = 0; 1814 *mask = p+1; 1815 return acl_range_minmax; 1816 } 1817 *mask = 0; 1818 return acl_range_single; 1819 } 1820 1821 /* parses subnet mask, fills 0 mask as well */ 1822 void 1823 parse_acl_range_subnet(char* p, void* addr, int maxbits) 1824 { 1825 int subnet_bits = atoi(p); 1826 uint8_t* addr_bytes = (uint8_t*)addr; 1827 if(subnet_bits == 0 && strcmp(p, "0")!=0) { 1828 c_error_msg("bad subnet range '%s'", p); 1829 return; 1830 } 1831 if(subnet_bits < 0 || subnet_bits > maxbits) { 1832 c_error_msg("subnet of %d bits out of range [0..%d]", subnet_bits, maxbits); 1833 return; 1834 } 1835 /* fill addr with n bits of 1s (struct has been zeroed) */ 1836 while(subnet_bits >= 8) { 1837 *addr_bytes++ = 0xff; 1838 subnet_bits -= 8; 1839 } 1840 if(subnet_bits > 0) { 1841 uint8_t shifts[] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; 1842 *addr_bytes = shifts[subnet_bits]; 1843 } 1844 } 1845 1846 acl_options_t* 1847 parse_acl_info(region_type* region, char* ip, const char* key) 1848 { 1849 char* p; 1850 acl_options_t* acl = (acl_options_t*)region_alloc(region, sizeof(acl_options_t)); 1851 acl->next = 0; 1852 /* ip */ 1853 acl->ip_address_spec = region_strdup(region, ip); 1854 acl->use_axfr_only = 0; 1855 acl->allow_udp = 0; 1856 acl->ixfr_disabled = 0; 1857 acl->bad_xfr_count = 0; 1858 acl->key_options = 0; 1859 acl->is_ipv6 = 0; 1860 acl->port = 0; 1861 memset(&acl->addr, 0, sizeof(union acl_addr_storage)); 1862 memset(&acl->range_mask, 0, sizeof(union acl_addr_storage)); 1863 if((p=strrchr(ip, '@'))!=0) { 1864 if(atoi(p+1) == 0) c_error("expected port number after '@'"); 1865 else acl->port = atoi(p+1); 1866 *p=0; 1867 } 1868 acl->rangetype = parse_acl_range_type(ip, &p); 1869 if(parse_acl_is_ipv6(ip)) { 1870 acl->is_ipv6 = 1; 1871 #ifdef INET6 1872 if(inet_pton(AF_INET6, ip, &acl->addr.addr6) != 1) 1873 c_error_msg("Bad ip6 address '%s'", ip); 1874 if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) 1875 if(inet_pton(AF_INET6, p, &acl->range_mask.addr6) != 1) 1876 c_error_msg("Bad ip6 address mask '%s'", p); 1877 if(acl->rangetype==acl_range_subnet) 1878 parse_acl_range_subnet(p, &acl->range_mask.addr6, 128); 1879 #else 1880 c_error_msg("encountered IPv6 address '%s'.", ip); 1881 #endif /* INET6 */ 1882 } else { 1883 acl->is_ipv6 = 0; 1884 if(inet_pton(AF_INET, ip, &acl->addr.addr) != 1) 1885 c_error_msg("Bad ip4 address '%s'", ip); 1886 if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) 1887 if(inet_pton(AF_INET, p, &acl->range_mask.addr) != 1) 1888 c_error_msg("Bad ip4 address mask '%s'", p); 1889 if(acl->rangetype==acl_range_subnet) 1890 parse_acl_range_subnet(p, &acl->range_mask.addr, 32); 1891 } 1892 1893 /* key */ 1894 if(strcmp(key, "NOKEY")==0) { 1895 acl->nokey = 1; 1896 acl->blocked = 0; 1897 acl->key_name = 0; 1898 } else if(strcmp(key, "BLOCKED")==0) { 1899 acl->nokey = 0; 1900 acl->blocked = 1; 1901 acl->key_name = 0; 1902 } else { 1903 acl->nokey = 0; 1904 acl->blocked = 0; 1905 acl->key_name = region_strdup(region, key); 1906 } 1907 return acl; 1908 } 1909 1910 /* copy acl list at end of parser start, update current */ 1911 static 1912 void append_acl(acl_options_t** start, acl_options_t** cur, 1913 acl_options_t* list) 1914 { 1915 while(list) { 1916 acl_options_t* acl = copy_acl(cfg_parser->opt->region, list); 1917 acl->next = NULL; 1918 if(*cur) 1919 (*cur)->next = acl; 1920 else *start = acl; 1921 *cur = acl; 1922 list = list->next; 1923 } 1924 } 1925 1926 void 1927 config_apply_pattern(const char* name) 1928 { 1929 /* find the pattern */ 1930 pattern_options_t* pat = pattern_options_find(cfg_parser->opt, name); 1931 pattern_options_t* a = cfg_parser->current_pattern; 1932 if(!pat) { 1933 c_error_msg("could not find pattern %s", name); 1934 return; 1935 } 1936 1937 /* apply settings */ 1938 if(pat->zonefile) 1939 a->zonefile = region_strdup(cfg_parser->opt->region, 1940 pat->zonefile); 1941 if(pat->zonestats) 1942 a->zonestats = region_strdup(cfg_parser->opt->region, 1943 pat->zonestats); 1944 if(!pat->allow_axfr_fallback_is_default) { 1945 a->allow_axfr_fallback = pat->allow_axfr_fallback; 1946 a->allow_axfr_fallback_is_default = 0; 1947 } 1948 if(!pat->notify_retry_is_default) { 1949 a->notify_retry = pat->notify_retry; 1950 a->notify_retry_is_default = 0; 1951 } 1952 if(!pat->max_refresh_time_is_default) { 1953 a->max_refresh_time = pat->max_refresh_time; 1954 a->max_refresh_time_is_default = 0; 1955 } 1956 if(!pat->min_refresh_time_is_default) { 1957 a->min_refresh_time = pat->min_refresh_time; 1958 a->min_refresh_time_is_default = 0; 1959 } 1960 if(!pat->max_retry_time_is_default) { 1961 a->max_retry_time = pat->max_retry_time; 1962 a->max_retry_time_is_default = 0; 1963 } 1964 if(!pat->min_retry_time_is_default) { 1965 a->min_retry_time = pat->min_retry_time; 1966 a->min_retry_time_is_default = 0; 1967 } 1968 a->size_limit_xfr = pat->size_limit_xfr; 1969 #ifdef RATELIMIT 1970 a->rrl_whitelist |= pat->rrl_whitelist; 1971 #endif 1972 /* append acl items */ 1973 append_acl(&a->allow_notify, &cfg_parser->current_allow_notify, 1974 pat->allow_notify); 1975 append_acl(&a->request_xfr, &cfg_parser->current_request_xfr, 1976 pat->request_xfr); 1977 append_acl(&a->notify, &cfg_parser->current_notify, pat->notify); 1978 append_acl(&a->provide_xfr, &cfg_parser->current_provide_xfr, 1979 pat->provide_xfr); 1980 append_acl(&a->outgoing_interface, &cfg_parser-> 1981 current_outgoing_interface, pat->outgoing_interface); 1982 } 1983 1984 void 1985 nsd_options_destroy(nsd_options_t* opt) 1986 { 1987 region_destroy(opt->region); 1988 } 1989 1990 unsigned getzonestatid(nsd_options_t* opt, zone_options_t* zopt) 1991 { 1992 #ifdef USE_ZONE_STATS 1993 const char* statname; 1994 struct zonestatname* n; 1995 rbnode_t* res; 1996 /* try to find the instantiated zonestat name */ 1997 if(!zopt->pattern->zonestats || zopt->pattern->zonestats[0]==0) 1998 return 0; /* no zone stats */ 1999 statname = config_cook_string(zopt, zopt->pattern->zonestats); 2000 res = rbtree_search(opt->zonestatnames, statname); 2001 if(res) 2002 return ((struct zonestatname*)res)->id; 2003 /* create it */ 2004 n = (struct zonestatname*)xalloc(sizeof(*n)); 2005 memset(n, 0, sizeof(*n)); 2006 n->node.key = strdup(statname); 2007 if(!n->node.key) { 2008 log_msg(LOG_ERR, "malloc failed: %s", strerror(errno)); 2009 exit(1); 2010 } 2011 n->id = (unsigned)(opt->zonestatnames->count); 2012 rbtree_insert(opt->zonestatnames, (rbnode_t*)n); 2013 return n->id; 2014 #else /* USE_ZONE_STATS */ 2015 (void)opt; (void)zopt; 2016 return 0; 2017 #endif /* USE_ZONE_STATS */ 2018 } 2019