1 /* 2 * unbound.c - unbound validating resolver public API implementation 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 resolve DNS queries and 40 * validate the answers. Synchronously and asynchronously. 41 * 42 */ 43 44 /* include the public api first, it should be able to stand alone */ 45 #include "libunbound/unbound.h" 46 #include "libunbound/unbound-event.h" 47 #include "config.h" 48 #include <ctype.h> 49 #include "libunbound/context.h" 50 #include "libunbound/libworker.h" 51 #include "util/locks.h" 52 #include "util/config_file.h" 53 #include "util/alloc.h" 54 #include "util/module.h" 55 #include "util/regional.h" 56 #include "util/log.h" 57 #include "util/random.h" 58 #include "util/net_help.h" 59 #include "util/tube.h" 60 #include "util/ub_event.h" 61 #include "util/edns.h" 62 #include "services/modstack.h" 63 #include "services/localzone.h" 64 #include "services/cache/infra.h" 65 #include "services/cache/rrset.h" 66 #include "services/authzone.h" 67 #include "services/listen_dnsport.h" 68 #include "sldns/sbuffer.h" 69 #include "iterator/iter_fwd.h" 70 #include "iterator/iter_hints.h" 71 #ifdef HAVE_PTHREAD 72 #include <signal.h> 73 #endif 74 #ifdef HAVE_SYS_WAIT_H 75 #include <sys/wait.h> 76 #endif 77 #ifdef HAVE_TIME_H 78 #include <time.h> 79 #endif 80 81 #if defined(UB_ON_WINDOWS) && defined (HAVE_WINDOWS_H) 82 #include <windows.h> 83 #include <iphlpapi.h> 84 #endif /* UB_ON_WINDOWS */ 85 86 /** store that the logfile has a debug override */ 87 int ctx_logfile_overridden = 0; 88 89 /** create context functionality, but no pipes */ 90 static struct ub_ctx* ub_ctx_create_nopipe(void) 91 { 92 struct ub_ctx* ctx; 93 #ifdef USE_WINSOCK 94 int r; 95 WSADATA wsa_data; 96 #endif 97 98 checklock_start(); 99 if(!ctx_logfile_overridden) 100 log_init(NULL, 0, NULL); /* logs to stderr */ 101 log_ident_set("libunbound"); 102 #ifdef USE_WINSOCK 103 if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) { 104 log_err("could not init winsock. WSAStartup: %s", 105 wsa_strerror(r)); 106 return NULL; 107 } 108 #endif 109 verbosity = NO_VERBOSE; /* errors only */ 110 checklock_start(); 111 ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx)); 112 if(!ctx) { 113 errno = ENOMEM; 114 return NULL; 115 } 116 alloc_init(&ctx->superalloc, NULL, 0); 117 if(!(ctx->seed_rnd = ub_initstate(NULL))) { 118 ub_randfree(ctx->seed_rnd); 119 free(ctx); 120 errno = ENOMEM; 121 return NULL; 122 } 123 lock_basic_init(&ctx->qqpipe_lock); 124 lock_basic_init(&ctx->rrpipe_lock); 125 lock_basic_init(&ctx->cfglock); 126 ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env)); 127 if(!ctx->env) { 128 ub_randfree(ctx->seed_rnd); 129 free(ctx); 130 errno = ENOMEM; 131 return NULL; 132 } 133 ctx->env->cfg = config_create_forlib(); 134 if(!ctx->env->cfg) { 135 free(ctx->env); 136 ub_randfree(ctx->seed_rnd); 137 free(ctx); 138 errno = ENOMEM; 139 return NULL; 140 } 141 /* init edns_known_options */ 142 if(!edns_known_options_init(ctx->env)) { 143 config_delete(ctx->env->cfg); 144 free(ctx->env); 145 ub_randfree(ctx->seed_rnd); 146 free(ctx); 147 errno = ENOMEM; 148 return NULL; 149 } 150 ctx->env->auth_zones = auth_zones_create(); 151 if(!ctx->env->auth_zones) { 152 edns_known_options_delete(ctx->env); 153 config_delete(ctx->env->cfg); 154 free(ctx->env); 155 ub_randfree(ctx->seed_rnd); 156 free(ctx); 157 errno = ENOMEM; 158 return NULL; 159 } 160 ctx->env->edns_strings = edns_strings_create(); 161 if(!ctx->env->edns_strings) { 162 auth_zones_delete(ctx->env->auth_zones); 163 edns_known_options_delete(ctx->env); 164 config_delete(ctx->env->cfg); 165 free(ctx->env); 166 ub_randfree(ctx->seed_rnd); 167 free(ctx); 168 errno = ENOMEM; 169 return NULL; 170 } 171 172 ctx->env->alloc = &ctx->superalloc; 173 ctx->env->worker = NULL; 174 ctx->env->need_to_validate = 0; 175 modstack_init(&ctx->mods); 176 ctx->env->modstack = &ctx->mods; 177 rbtree_init(&ctx->queries, &context_query_cmp); 178 return ctx; 179 } 180 181 struct ub_ctx* 182 ub_ctx_create(void) 183 { 184 struct ub_ctx* ctx = ub_ctx_create_nopipe(); 185 if(!ctx) 186 return NULL; 187 if((ctx->qq_pipe = tube_create()) == NULL) { 188 int e = errno; 189 ub_randfree(ctx->seed_rnd); 190 config_delete(ctx->env->cfg); 191 modstack_call_deinit(&ctx->mods, ctx->env); 192 modstack_call_destartup(&ctx->mods, ctx->env); 193 modstack_free(&ctx->mods); 194 listen_desetup_locks(); 195 edns_known_options_delete(ctx->env); 196 edns_strings_delete(ctx->env->edns_strings); 197 free(ctx->env); 198 free(ctx); 199 errno = e; 200 return NULL; 201 } 202 if((ctx->rr_pipe = tube_create()) == NULL) { 203 int e = errno; 204 tube_delete(ctx->qq_pipe); 205 ub_randfree(ctx->seed_rnd); 206 config_delete(ctx->env->cfg); 207 modstack_call_deinit(&ctx->mods, ctx->env); 208 modstack_call_destartup(&ctx->mods, ctx->env); 209 modstack_free(&ctx->mods); 210 listen_desetup_locks(); 211 edns_known_options_delete(ctx->env); 212 edns_strings_delete(ctx->env->edns_strings); 213 free(ctx->env); 214 free(ctx); 215 errno = e; 216 return NULL; 217 } 218 return ctx; 219 } 220 221 struct ub_ctx* 222 ub_ctx_create_ub_event(struct ub_event_base* ueb) 223 { 224 struct ub_ctx* ctx = ub_ctx_create_nopipe(); 225 if(!ctx) 226 return NULL; 227 /* no pipes, but we have the locks to make sure everything works */ 228 ctx->created_bg = 0; 229 ctx->dothread = 1; /* the processing is in the same process, 230 makes ub_cancel and ub_ctx_delete do the right thing */ 231 ctx->event_base = ueb; 232 return ctx; 233 } 234 235 struct ub_ctx* 236 ub_ctx_create_event(struct event_base* eb) 237 { 238 struct ub_ctx* ctx = ub_ctx_create_nopipe(); 239 if(!ctx) 240 return NULL; 241 /* no pipes, but we have the locks to make sure everything works */ 242 ctx->created_bg = 0; 243 ctx->dothread = 1; /* the processing is in the same process, 244 makes ub_cancel and ub_ctx_delete do the right thing */ 245 ctx->event_base = ub_libevent_event_base(eb); 246 if (!ctx->event_base) { 247 ub_ctx_delete(ctx); 248 return NULL; 249 } 250 ctx->event_base_malloced = 1; 251 return ctx; 252 } 253 254 /** delete q */ 255 static void 256 delq(rbnode_type* n, void* ATTR_UNUSED(arg)) 257 { 258 struct ctx_query* q = (struct ctx_query*)n; 259 context_query_delete(q); 260 } 261 262 /** stop the bg thread */ 263 static void ub_stop_bg(struct ub_ctx* ctx) 264 { 265 /* stop the bg thread */ 266 lock_basic_lock(&ctx->cfglock); 267 if(ctx->created_bg) { 268 uint8_t* msg; 269 uint32_t len; 270 uint32_t cmd = UB_LIBCMD_QUIT; 271 lock_basic_unlock(&ctx->cfglock); 272 lock_basic_lock(&ctx->qqpipe_lock); 273 (void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd, 274 (uint32_t)sizeof(cmd), 0); 275 lock_basic_unlock(&ctx->qqpipe_lock); 276 lock_basic_lock(&ctx->rrpipe_lock); 277 while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) { 278 /* discard all results except a quit confirm */ 279 if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) { 280 free(msg); 281 break; 282 } 283 free(msg); 284 } 285 lock_basic_unlock(&ctx->rrpipe_lock); 286 287 /* if bg worker is a thread, wait for it to exit, so that all 288 * resources are really gone. */ 289 lock_basic_lock(&ctx->cfglock); 290 if(ctx->dothread) { 291 lock_basic_unlock(&ctx->cfglock); 292 ub_thread_join(ctx->bg_tid); 293 } else { 294 lock_basic_unlock(&ctx->cfglock); 295 #ifndef UB_ON_WINDOWS 296 if(waitpid(ctx->bg_pid, NULL, 0) == -1) { 297 if(verbosity > 2) 298 log_err("waitpid: %s", strerror(errno)); 299 } 300 #endif 301 } 302 } 303 else { 304 lock_basic_unlock(&ctx->cfglock); 305 } 306 } 307 308 void 309 ub_ctx_delete(struct ub_ctx* ctx) 310 { 311 struct alloc_cache* a, *na; 312 int do_stop = 1; 313 if(!ctx) return; 314 315 /* if the delete is called but it has forked, and before the fork 316 * the context was finalized, then the bg worker is not stopped 317 * from here. There is one worker, but two contexts that refer to 318 * it and only one should clean up, the one with getpid == pipe_pid.*/ 319 if(ctx->created_bg && ctx->pipe_pid != getpid()) { 320 do_stop = 0; 321 #ifndef USE_WINSOCK 322 /* Stop events from getting deregistered, if the backend is 323 * epoll, the epoll fd is the same as the other process. 324 * That process should deregister them. */ 325 if(ctx->qq_pipe->listen_com) 326 ctx->qq_pipe->listen_com->event_added = 0; 327 if(ctx->qq_pipe->res_com) 328 ctx->qq_pipe->res_com->event_added = 0; 329 if(ctx->rr_pipe->listen_com) 330 ctx->rr_pipe->listen_com->event_added = 0; 331 if(ctx->rr_pipe->res_com) 332 ctx->rr_pipe->res_com->event_added = 0; 333 #endif 334 } 335 /* see if bg thread is created and if threads have been killed */ 336 /* no locks, because those may be held by terminated threads */ 337 /* for processes the read pipe is closed and we see that on read */ 338 #ifdef HAVE_PTHREAD 339 if(ctx->created_bg && ctx->dothread && do_stop) { 340 if(pthread_kill(ctx->bg_tid, 0) == ESRCH) { 341 /* thread has been killed */ 342 do_stop = 0; 343 } 344 } 345 #endif /* HAVE_PTHREAD */ 346 if(do_stop) 347 ub_stop_bg(ctx); 348 if(ctx->created_bg && ctx->pipe_pid != getpid() && ctx->thread_worker) { 349 /* This delete is happening from a different process. Delete 350 * the thread worker from this process memory space. The 351 * thread is not there to do so, so it is freed here. */ 352 struct ub_event_base* evbase = comm_base_internal( 353 ctx->thread_worker->base); 354 libworker_delete_event(ctx->thread_worker); 355 ctx->thread_worker = NULL; 356 #ifdef USE_MINI_EVENT 357 ub_event_base_free(evbase); 358 #else 359 /* cannot event_base_free, because the epoll_fd cleanup 360 * in libevent could stop the original event_base in the 361 * other process from working. */ 362 free(evbase); 363 #endif 364 } 365 libworker_delete_event(ctx->event_worker); 366 367 modstack_call_deinit(&ctx->mods, ctx->env); 368 modstack_call_destartup(&ctx->mods, ctx->env); 369 modstack_free(&ctx->mods); 370 a = ctx->alloc_list; 371 while(a) { 372 na = a->super; 373 a->super = &ctx->superalloc; 374 alloc_clear(a); 375 free(a); 376 a = na; 377 } 378 local_zones_delete(ctx->local_zones); 379 lock_basic_destroy(&ctx->qqpipe_lock); 380 lock_basic_destroy(&ctx->rrpipe_lock); 381 lock_basic_destroy(&ctx->cfglock); 382 tube_delete(ctx->qq_pipe); 383 tube_delete(ctx->rr_pipe); 384 if(ctx->env) { 385 slabhash_delete(ctx->env->msg_cache); 386 rrset_cache_delete(ctx->env->rrset_cache); 387 infra_delete(ctx->env->infra_cache); 388 config_delete(ctx->env->cfg); 389 edns_known_options_delete(ctx->env); 390 edns_strings_delete(ctx->env->edns_strings); 391 forwards_delete(ctx->env->fwds); 392 hints_delete(ctx->env->hints); 393 auth_zones_delete(ctx->env->auth_zones); 394 free(ctx->env); 395 } 396 ub_randfree(ctx->seed_rnd); 397 alloc_clear(&ctx->superalloc); 398 listen_desetup_locks(); 399 traverse_postorder(&ctx->queries, delq, NULL); 400 if(ctx_logfile_overridden) { 401 log_file(NULL); 402 ctx_logfile_overridden = 0; 403 } 404 if(ctx->event_base_malloced) 405 free(ctx->event_base); 406 free(ctx); 407 #ifdef USE_WINSOCK 408 WSACleanup(); 409 #endif 410 } 411 412 int 413 ub_ctx_set_option(struct ub_ctx* ctx, const char* opt, const char* val) 414 { 415 lock_basic_lock(&ctx->cfglock); 416 if(ctx->finalized) { 417 lock_basic_unlock(&ctx->cfglock); 418 return UB_AFTERFINAL; 419 } 420 if(!config_set_option(ctx->env->cfg, opt, val)) { 421 lock_basic_unlock(&ctx->cfglock); 422 return UB_SYNTAX; 423 } 424 lock_basic_unlock(&ctx->cfglock); 425 return UB_NOERROR; 426 } 427 428 int 429 ub_ctx_get_option(struct ub_ctx* ctx, const char* opt, char** str) 430 { 431 int r; 432 lock_basic_lock(&ctx->cfglock); 433 r = config_get_option_collate(ctx->env->cfg, opt, str); 434 lock_basic_unlock(&ctx->cfglock); 435 if(r == 0) r = UB_NOERROR; 436 else if(r == 1) r = UB_SYNTAX; 437 else if(r == 2) r = UB_NOMEM; 438 return r; 439 } 440 441 int 442 ub_ctx_config(struct ub_ctx* ctx, const char* fname) 443 { 444 lock_basic_lock(&ctx->cfglock); 445 if(ctx->finalized) { 446 lock_basic_unlock(&ctx->cfglock); 447 return UB_AFTERFINAL; 448 } 449 if(!config_read(ctx->env->cfg, fname, NULL)) { 450 lock_basic_unlock(&ctx->cfglock); 451 return UB_SYNTAX; 452 } 453 lock_basic_unlock(&ctx->cfglock); 454 return UB_NOERROR; 455 } 456 457 int 458 ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta) 459 { 460 char* dup = strdup(ta); 461 if(!dup) return UB_NOMEM; 462 lock_basic_lock(&ctx->cfglock); 463 if(ctx->finalized) { 464 lock_basic_unlock(&ctx->cfglock); 465 free(dup); 466 return UB_AFTERFINAL; 467 } 468 if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_list, dup)) { 469 lock_basic_unlock(&ctx->cfglock); 470 return UB_NOMEM; 471 } 472 lock_basic_unlock(&ctx->cfglock); 473 return UB_NOERROR; 474 } 475 476 int 477 ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname) 478 { 479 char* dup = strdup(fname); 480 if(!dup) return UB_NOMEM; 481 lock_basic_lock(&ctx->cfglock); 482 if(ctx->finalized) { 483 lock_basic_unlock(&ctx->cfglock); 484 free(dup); 485 return UB_AFTERFINAL; 486 } 487 if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) { 488 lock_basic_unlock(&ctx->cfglock); 489 return UB_NOMEM; 490 } 491 lock_basic_unlock(&ctx->cfglock); 492 return UB_NOERROR; 493 } 494 495 int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname) 496 { 497 char* dup = strdup(fname); 498 if(!dup) return UB_NOMEM; 499 lock_basic_lock(&ctx->cfglock); 500 if(ctx->finalized) { 501 lock_basic_unlock(&ctx->cfglock); 502 free(dup); 503 return UB_AFTERFINAL; 504 } 505 if(!cfg_strlist_insert(&ctx->env->cfg->auto_trust_anchor_file_list, 506 dup)) { 507 lock_basic_unlock(&ctx->cfglock); 508 return UB_NOMEM; 509 } 510 lock_basic_unlock(&ctx->cfglock); 511 return UB_NOERROR; 512 } 513 514 int 515 ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname) 516 { 517 char* dup = strdup(fname); 518 if(!dup) return UB_NOMEM; 519 lock_basic_lock(&ctx->cfglock); 520 if(ctx->finalized) { 521 lock_basic_unlock(&ctx->cfglock); 522 free(dup); 523 return UB_AFTERFINAL; 524 } 525 if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) { 526 lock_basic_unlock(&ctx->cfglock); 527 return UB_NOMEM; 528 } 529 lock_basic_unlock(&ctx->cfglock); 530 return UB_NOERROR; 531 } 532 533 int 534 ub_ctx_debuglevel(struct ub_ctx* ctx, int d) 535 { 536 lock_basic_lock(&ctx->cfglock); 537 verbosity = d; 538 ctx->env->cfg->verbosity = d; 539 lock_basic_unlock(&ctx->cfglock); 540 return UB_NOERROR; 541 } 542 543 int ub_ctx_debugout(struct ub_ctx* ctx, void* out) 544 { 545 lock_basic_lock(&ctx->cfglock); 546 log_file((FILE*)out); 547 ctx_logfile_overridden = 1; 548 ctx->logfile_override = 1; 549 ctx->log_out = out; 550 lock_basic_unlock(&ctx->cfglock); 551 return UB_NOERROR; 552 } 553 554 int 555 ub_ctx_async(struct ub_ctx* ctx, int dothread) 556 { 557 #ifdef THREADS_DISABLED 558 if(dothread) /* cannot do threading */ 559 return UB_NOERROR; 560 #endif 561 lock_basic_lock(&ctx->cfglock); 562 if(ctx->finalized) { 563 lock_basic_unlock(&ctx->cfglock); 564 return UB_AFTERFINAL; 565 } 566 ctx->dothread = dothread; 567 lock_basic_unlock(&ctx->cfglock); 568 return UB_NOERROR; 569 } 570 571 int 572 ub_poll(struct ub_ctx* ctx) 573 { 574 /* no need to hold lock while testing for readability. */ 575 return tube_poll(ctx->rr_pipe); 576 } 577 578 int 579 ub_fd(struct ub_ctx* ctx) 580 { 581 return tube_read_fd(ctx->rr_pipe); 582 } 583 584 /** process answer from bg worker */ 585 static int 586 process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, 587 ub_callback_type* cb, void** cbarg, int* err, 588 struct ub_result** res) 589 { 590 struct ctx_query* q; 591 if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) { 592 log_err("error: bad data from bg worker %d", 593 (int)context_serial_getcmd(msg, len)); 594 return 0; 595 } 596 597 lock_basic_lock(&ctx->cfglock); 598 q = context_deserialize_answer(ctx, msg, len, err); 599 if(!q) { 600 lock_basic_unlock(&ctx->cfglock); 601 /* probably simply the lookup that failed, i.e. 602 * response returned before cancel was sent out, so noerror */ 603 return 1; 604 } 605 log_assert(q->async); 606 607 /* grab cb while locked */ 608 if(q->cancelled) { 609 *cb = NULL; 610 *cbarg = NULL; 611 } else { 612 *cb = q->cb; 613 *cbarg = q->cb_arg; 614 } 615 if(*err) { 616 *res = NULL; 617 ub_resolve_free(q->res); 618 } else { 619 /* parse the message, extract rcode, fill result */ 620 sldns_buffer* buf = sldns_buffer_new(q->msg_len); 621 struct regional* region = regional_create(); 622 *res = q->res; 623 (*res)->rcode = LDNS_RCODE_SERVFAIL; 624 if(region && buf) { 625 sldns_buffer_clear(buf); 626 sldns_buffer_write(buf, q->msg, q->msg_len); 627 sldns_buffer_flip(buf); 628 libworker_enter_result(*res, buf, region, 629 q->msg_security); 630 } 631 (*res)->answer_packet = q->msg; 632 (*res)->answer_len = (int)q->msg_len; 633 q->msg = NULL; 634 sldns_buffer_free(buf); 635 regional_destroy(region); 636 } 637 q->res = NULL; 638 /* delete the q from list */ 639 (void)rbtree_delete(&ctx->queries, q->node.key); 640 ctx->num_async--; 641 context_query_delete(q); 642 lock_basic_unlock(&ctx->cfglock); 643 644 if(*cb) return 2; 645 ub_resolve_free(*res); 646 return 1; 647 } 648 649 /** process answer from bg worker */ 650 static int 651 process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len) 652 { 653 int err; 654 ub_callback_type cb; 655 void* cbarg; 656 struct ub_result* res; 657 int r; 658 659 r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res); 660 661 /* no locks held while calling callback, so that library is 662 * re-entrant. */ 663 if(r == 2) 664 (*cb)(cbarg, err, res); 665 666 return r; 667 } 668 669 int 670 ub_process(struct ub_ctx* ctx) 671 { 672 int r; 673 uint8_t* msg; 674 uint32_t len; 675 while(1) { 676 msg = NULL; 677 lock_basic_lock(&ctx->rrpipe_lock); 678 r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); 679 lock_basic_unlock(&ctx->rrpipe_lock); 680 if(r == 0) 681 return UB_PIPE; 682 else if(r == -1) 683 break; 684 if(!process_answer(ctx, msg, len)) { 685 free(msg); 686 return UB_PIPE; 687 } 688 free(msg); 689 } 690 return UB_NOERROR; 691 } 692 693 int 694 ub_wait(struct ub_ctx* ctx) 695 { 696 int err; 697 ub_callback_type cb; 698 void* cbarg; 699 struct ub_result* res; 700 int r; 701 uint8_t* msg; 702 uint32_t len; 703 /* this is basically the same loop as _process(), but with changes. 704 * holds the rrpipe lock and waits with tube_wait */ 705 while(1) { 706 lock_basic_lock(&ctx->rrpipe_lock); 707 lock_basic_lock(&ctx->cfglock); 708 if(ctx->num_async == 0) { 709 lock_basic_unlock(&ctx->cfglock); 710 lock_basic_unlock(&ctx->rrpipe_lock); 711 break; 712 } 713 lock_basic_unlock(&ctx->cfglock); 714 715 /* keep rrpipe locked, while 716 * o waiting for pipe readable 717 * o parsing message 718 * o possibly decrementing num_async 719 * do callback without lock 720 */ 721 r = tube_wait(ctx->rr_pipe); 722 if(r) { 723 r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); 724 if(r == 0) { 725 lock_basic_unlock(&ctx->rrpipe_lock); 726 return UB_PIPE; 727 } 728 if(r == -1) { 729 lock_basic_unlock(&ctx->rrpipe_lock); 730 continue; 731 } 732 r = process_answer_detail(ctx, msg, len, 733 &cb, &cbarg, &err, &res); 734 lock_basic_unlock(&ctx->rrpipe_lock); 735 free(msg); 736 if(r == 0) 737 return UB_PIPE; 738 if(r == 2) 739 (*cb)(cbarg, err, res); 740 } else { 741 lock_basic_unlock(&ctx->rrpipe_lock); 742 } 743 } 744 return UB_NOERROR; 745 } 746 747 int 748 ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype, 749 int rrclass, struct ub_result** result) 750 { 751 struct ctx_query* q; 752 int r; 753 *result = NULL; 754 755 lock_basic_lock(&ctx->cfglock); 756 if(!ctx->finalized) { 757 r = context_finalize(ctx); 758 if(r) { 759 lock_basic_unlock(&ctx->cfglock); 760 return r; 761 } 762 } 763 /* create new ctx_query and attempt to add to the list */ 764 lock_basic_unlock(&ctx->cfglock); 765 q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL); 766 if(!q) 767 return UB_NOMEM; 768 /* become a resolver thread for a bit */ 769 770 r = libworker_fg(ctx, q); 771 if(r) { 772 lock_basic_lock(&ctx->cfglock); 773 (void)rbtree_delete(&ctx->queries, q->node.key); 774 context_query_delete(q); 775 lock_basic_unlock(&ctx->cfglock); 776 return r; 777 } 778 q->res->answer_packet = q->msg; 779 q->res->answer_len = (int)q->msg_len; 780 q->msg = NULL; 781 *result = q->res; 782 q->res = NULL; 783 784 lock_basic_lock(&ctx->cfglock); 785 (void)rbtree_delete(&ctx->queries, q->node.key); 786 context_query_delete(q); 787 lock_basic_unlock(&ctx->cfglock); 788 return UB_NOERROR; 789 } 790 791 int 792 ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, 793 int rrclass, void* mydata, ub_event_callback_type callback, 794 int* async_id) 795 { 796 struct ctx_query* q; 797 int r; 798 799 if(async_id) 800 *async_id = 0; 801 lock_basic_lock(&ctx->cfglock); 802 if(!ctx->finalized) { 803 r = context_finalize(ctx); 804 if(r) { 805 lock_basic_unlock(&ctx->cfglock); 806 return r; 807 } 808 } 809 lock_basic_unlock(&ctx->cfglock); 810 if(!ctx->event_worker) { 811 ctx->event_worker = libworker_create_event(ctx, 812 ctx->event_base); 813 if(!ctx->event_worker) { 814 return UB_INITFAIL; 815 } 816 } 817 818 /* set time in case answer comes from cache */ 819 ub_comm_base_now(ctx->event_worker->base); 820 821 /* create new ctx_query and attempt to add to the list */ 822 q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata); 823 if(!q) 824 return UB_NOMEM; 825 826 /* attach to mesh */ 827 if((r=libworker_attach_mesh(ctx, q, async_id)) != 0) 828 return r; 829 return UB_NOERROR; 830 } 831 832 833 int 834 ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, 835 int rrclass, void* mydata, ub_callback_type callback, int* async_id) 836 { 837 struct ctx_query* q; 838 uint8_t* msg = NULL; 839 uint32_t len = 0; 840 841 if(async_id) 842 *async_id = 0; 843 lock_basic_lock(&ctx->cfglock); 844 if(!ctx->finalized) { 845 int r = context_finalize(ctx); 846 if(r) { 847 lock_basic_unlock(&ctx->cfglock); 848 return r; 849 } 850 } 851 if(!ctx->created_bg) { 852 int r; 853 ctx->created_bg = 1; 854 lock_basic_unlock(&ctx->cfglock); 855 r = libworker_bg(ctx); 856 if(r) { 857 lock_basic_lock(&ctx->cfglock); 858 ctx->created_bg = 0; 859 lock_basic_unlock(&ctx->cfglock); 860 return r; 861 } 862 } else { 863 lock_basic_unlock(&ctx->cfglock); 864 } 865 866 /* create new ctx_query and attempt to add to the list */ 867 q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata); 868 if(!q) 869 return UB_NOMEM; 870 871 /* write over pipe to background worker */ 872 lock_basic_lock(&ctx->cfglock); 873 msg = context_serialize_new_query(q, &len); 874 if(!msg) { 875 (void)rbtree_delete(&ctx->queries, q->node.key); 876 ctx->num_async--; 877 context_query_delete(q); 878 lock_basic_unlock(&ctx->cfglock); 879 return UB_NOMEM; 880 } 881 if(async_id) 882 *async_id = q->querynum; 883 lock_basic_unlock(&ctx->cfglock); 884 885 lock_basic_lock(&ctx->qqpipe_lock); 886 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 887 lock_basic_unlock(&ctx->qqpipe_lock); 888 free(msg); 889 return UB_PIPE; 890 } 891 lock_basic_unlock(&ctx->qqpipe_lock); 892 free(msg); 893 return UB_NOERROR; 894 } 895 896 int 897 ub_cancel(struct ub_ctx* ctx, int async_id) 898 { 899 struct ctx_query* q; 900 uint8_t* msg = NULL; 901 uint32_t len = 0; 902 lock_basic_lock(&ctx->cfglock); 903 q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id); 904 if(!q || !q->async) { 905 /* it is not there, so nothing to do */ 906 lock_basic_unlock(&ctx->cfglock); 907 return UB_NOID; 908 } 909 log_assert(q->async); 910 q->cancelled = 1; 911 912 /* delete it */ 913 if(!ctx->dothread) { /* if forked */ 914 (void)rbtree_delete(&ctx->queries, q->node.key); 915 ctx->num_async--; 916 msg = context_serialize_cancel(q, &len); 917 context_query_delete(q); 918 lock_basic_unlock(&ctx->cfglock); 919 if(!msg) { 920 return UB_NOMEM; 921 } 922 /* send cancel to background worker */ 923 lock_basic_lock(&ctx->qqpipe_lock); 924 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 925 lock_basic_unlock(&ctx->qqpipe_lock); 926 free(msg); 927 return UB_PIPE; 928 } 929 lock_basic_unlock(&ctx->qqpipe_lock); 930 free(msg); 931 } else { 932 lock_basic_unlock(&ctx->cfglock); 933 } 934 return UB_NOERROR; 935 } 936 937 void 938 ub_resolve_free(struct ub_result* result) 939 { 940 char** p; 941 if(!result) return; 942 free(result->qname); 943 if(result->canonname != result->qname) 944 free(result->canonname); 945 if(result->data) 946 for(p = result->data; *p; p++) 947 free(*p); 948 free(result->data); 949 free(result->len); 950 free(result->answer_packet); 951 free(result->why_bogus); 952 free(result); 953 } 954 955 const char* 956 ub_strerror(int err) 957 { 958 switch(err) { 959 case UB_NOERROR: return "no error"; 960 case UB_SOCKET: return "socket io error"; 961 case UB_NOMEM: return "out of memory"; 962 case UB_SYNTAX: return "syntax error"; 963 case UB_SERVFAIL: return "server failure"; 964 case UB_FORKFAIL: return "could not fork"; 965 case UB_INITFAIL: return "initialization failure"; 966 case UB_AFTERFINAL: return "setting change after finalize"; 967 case UB_PIPE: return "error in pipe communication with async"; 968 case UB_READFILE: return "error reading file"; 969 case UB_NOID: return "error async_id does not exist"; 970 default: return "unknown error"; 971 } 972 } 973 974 int 975 ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr) 976 { 977 struct sockaddr_storage storage; 978 socklen_t stlen; 979 struct config_stub* s; 980 char* dupl; 981 lock_basic_lock(&ctx->cfglock); 982 if(ctx->finalized) { 983 lock_basic_unlock(&ctx->cfglock); 984 errno=EINVAL; 985 return UB_AFTERFINAL; 986 } 987 if(!addr) { 988 /* disable fwd mode - the root stub should be first. */ 989 if(ctx->env->cfg->forwards && 990 (ctx->env->cfg->forwards->name && 991 strcmp(ctx->env->cfg->forwards->name, ".") == 0)) { 992 s = ctx->env->cfg->forwards; 993 ctx->env->cfg->forwards = s->next; 994 s->next = NULL; 995 config_delstubs(s); 996 } 997 lock_basic_unlock(&ctx->cfglock); 998 return UB_NOERROR; 999 } 1000 lock_basic_unlock(&ctx->cfglock); 1001 1002 /* check syntax for addr */ 1003 if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) { 1004 errno=EINVAL; 1005 return UB_SYNTAX; 1006 } 1007 1008 /* it parses, add root stub in front of list */ 1009 lock_basic_lock(&ctx->cfglock); 1010 if(!ctx->env->cfg->forwards || 1011 (ctx->env->cfg->forwards->name && 1012 strcmp(ctx->env->cfg->forwards->name, ".") != 0)) { 1013 s = calloc(1, sizeof(*s)); 1014 if(!s) { 1015 lock_basic_unlock(&ctx->cfglock); 1016 errno=ENOMEM; 1017 return UB_NOMEM; 1018 } 1019 s->name = strdup("."); 1020 if(!s->name) { 1021 free(s); 1022 lock_basic_unlock(&ctx->cfglock); 1023 errno=ENOMEM; 1024 return UB_NOMEM; 1025 } 1026 s->next = ctx->env->cfg->forwards; 1027 ctx->env->cfg->forwards = s; 1028 } else { 1029 log_assert(ctx->env->cfg->forwards); 1030 log_assert(ctx->env->cfg->forwards->name); 1031 s = ctx->env->cfg->forwards; 1032 } 1033 dupl = strdup(addr); 1034 if(!dupl) { 1035 lock_basic_unlock(&ctx->cfglock); 1036 errno=ENOMEM; 1037 return UB_NOMEM; 1038 } 1039 if(!cfg_strlist_insert(&s->addrs, dupl)) { 1040 lock_basic_unlock(&ctx->cfglock); 1041 errno=ENOMEM; 1042 return UB_NOMEM; 1043 } 1044 lock_basic_unlock(&ctx->cfglock); 1045 return UB_NOERROR; 1046 } 1047 1048 int ub_ctx_set_tls(struct ub_ctx* ctx, int tls) 1049 { 1050 lock_basic_lock(&ctx->cfglock); 1051 if(ctx->finalized) { 1052 lock_basic_unlock(&ctx->cfglock); 1053 errno=EINVAL; 1054 return UB_AFTERFINAL; 1055 } 1056 ctx->env->cfg->ssl_upstream = tls; 1057 lock_basic_unlock(&ctx->cfglock); 1058 return UB_NOERROR; 1059 } 1060 1061 int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, 1062 int isprime) 1063 { 1064 char* a; 1065 struct config_stub **prev, *elem; 1066 1067 /* check syntax for zone name */ 1068 if(zone) { 1069 uint8_t* nm; 1070 int nmlabs; 1071 size_t nmlen; 1072 if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) { 1073 errno=EINVAL; 1074 return UB_SYNTAX; 1075 } 1076 free(nm); 1077 } else { 1078 zone = "."; 1079 } 1080 1081 /* check syntax for addr (if not NULL) */ 1082 if(addr) { 1083 struct sockaddr_storage storage; 1084 socklen_t stlen; 1085 if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) { 1086 errno=EINVAL; 1087 return UB_SYNTAX; 1088 } 1089 } 1090 1091 lock_basic_lock(&ctx->cfglock); 1092 if(ctx->finalized) { 1093 lock_basic_unlock(&ctx->cfglock); 1094 errno=EINVAL; 1095 return UB_AFTERFINAL; 1096 } 1097 1098 /* arguments all right, now find or add the stub */ 1099 prev = &ctx->env->cfg->stubs; 1100 elem = cfg_stub_find(&prev, zone); 1101 if(!elem && !addr) { 1102 /* not found and we want to delete, nothing to do */ 1103 lock_basic_unlock(&ctx->cfglock); 1104 return UB_NOERROR; 1105 } else if(elem && !addr) { 1106 /* found, and we want to delete */ 1107 *prev = elem->next; 1108 config_delstub(elem); 1109 lock_basic_unlock(&ctx->cfglock); 1110 return UB_NOERROR; 1111 } else if(!elem) { 1112 /* not found, create the stub entry */ 1113 elem=(struct config_stub*)calloc(1, sizeof(struct config_stub)); 1114 if(elem) elem->name = strdup(zone); 1115 if(!elem || !elem->name) { 1116 free(elem); 1117 lock_basic_unlock(&ctx->cfglock); 1118 errno = ENOMEM; 1119 return UB_NOMEM; 1120 } 1121 elem->next = ctx->env->cfg->stubs; 1122 ctx->env->cfg->stubs = elem; 1123 } 1124 1125 /* add the address to the list and set settings */ 1126 elem->isprime = isprime; 1127 a = strdup(addr); 1128 if(!a) { 1129 lock_basic_unlock(&ctx->cfglock); 1130 errno = ENOMEM; 1131 return UB_NOMEM; 1132 } 1133 if(!cfg_strlist_insert(&elem->addrs, a)) { 1134 lock_basic_unlock(&ctx->cfglock); 1135 errno = ENOMEM; 1136 return UB_NOMEM; 1137 } 1138 lock_basic_unlock(&ctx->cfglock); 1139 return UB_NOERROR; 1140 } 1141 1142 int 1143 ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname) 1144 { 1145 FILE* in; 1146 int numserv = 0; 1147 char buf[1024]; 1148 char* parse, *addr; 1149 int r; 1150 1151 if(fname == NULL) { 1152 #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) 1153 fname = "/etc/resolv.conf"; 1154 #else 1155 FIXED_INFO *info; 1156 ULONG buflen = sizeof(*info); 1157 IP_ADDR_STRING *ptr; 1158 1159 info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO)); 1160 if (info == NULL) 1161 return UB_READFILE; 1162 1163 if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { 1164 free(info); 1165 info = (FIXED_INFO *) malloc(buflen); 1166 if (info == NULL) 1167 return UB_READFILE; 1168 } 1169 1170 if (GetNetworkParams(info, &buflen) == NO_ERROR) { 1171 int retval=0; 1172 ptr = &(info->DnsServerList); 1173 while (ptr) { 1174 numserv++; 1175 if((retval=ub_ctx_set_fwd(ctx, 1176 ptr->IpAddress.String))!=0) { 1177 free(info); 1178 return retval; 1179 } 1180 ptr = ptr->Next; 1181 } 1182 free(info); 1183 if (numserv==0) 1184 return UB_READFILE; 1185 return UB_NOERROR; 1186 } 1187 free(info); 1188 return UB_READFILE; 1189 #endif /* WINDOWS */ 1190 } 1191 in = fopen(fname, "r"); 1192 if(!in) { 1193 /* error in errno! perror(fname) */ 1194 return UB_READFILE; 1195 } 1196 while(fgets(buf, (int)sizeof(buf), in)) { 1197 buf[sizeof(buf)-1] = 0; 1198 parse=buf; 1199 while(*parse == ' ' || *parse == '\t') 1200 parse++; 1201 if(strncmp(parse, "nameserver", 10) == 0) { 1202 numserv++; 1203 parse += 10; /* skip 'nameserver' */ 1204 /* skip whitespace */ 1205 while(*parse == ' ' || *parse == '\t') 1206 parse++; 1207 addr = parse; 1208 /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ 1209 while(isxdigit((unsigned char)*parse) || *parse=='.' || *parse==':') 1210 parse++; 1211 /* terminate after the address, remove newline */ 1212 *parse = 0; 1213 1214 if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) { 1215 fclose(in); 1216 return r; 1217 } 1218 } 1219 } 1220 fclose(in); 1221 if(numserv == 0) { 1222 /* from resolv.conf(5) if none given, use localhost */ 1223 return ub_ctx_set_fwd(ctx, "127.0.0.1"); 1224 } 1225 return UB_NOERROR; 1226 } 1227 1228 int 1229 ub_ctx_hosts(struct ub_ctx* ctx, const char* fname) 1230 { 1231 FILE* in; 1232 char buf[1024], ldata[2048]; 1233 char* parse, *addr, *name, *ins; 1234 lock_basic_lock(&ctx->cfglock); 1235 if(ctx->finalized) { 1236 lock_basic_unlock(&ctx->cfglock); 1237 errno=EINVAL; 1238 return UB_AFTERFINAL; 1239 } 1240 lock_basic_unlock(&ctx->cfglock); 1241 if(fname == NULL) { 1242 #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) 1243 /* 1244 * If this is Windows NT/XP/2K it's in 1245 * %WINDIR%\system32\drivers\etc\hosts. 1246 * If this is Windows 95/98/Me it's in %WINDIR%\hosts. 1247 */ 1248 name = getenv("WINDIR"); 1249 if (name != NULL) { 1250 int retval=0; 1251 snprintf(buf, sizeof(buf), "%s%s", name, 1252 "\\system32\\drivers\\etc\\hosts"); 1253 if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { 1254 snprintf(buf, sizeof(buf), "%s%s", name, 1255 "\\hosts"); 1256 retval=ub_ctx_hosts(ctx, buf); 1257 } 1258 return retval; 1259 } 1260 return UB_READFILE; 1261 #else 1262 fname = "/etc/hosts"; 1263 #endif /* WIN32 */ 1264 } 1265 in = fopen(fname, "r"); 1266 if(!in) { 1267 /* error in errno! perror(fname) */ 1268 return UB_READFILE; 1269 } 1270 while(fgets(buf, (int)sizeof(buf), in)) { 1271 buf[sizeof(buf)-1] = 0; 1272 parse=buf; 1273 while(*parse == ' ' || *parse == '\t') 1274 parse++; 1275 if(*parse == '#') 1276 continue; /* skip comment */ 1277 /* format: <addr> spaces <name> spaces <name> ... */ 1278 addr = parse; 1279 /* skip addr */ 1280 while(isxdigit((unsigned char)*parse) || *parse == '.' || *parse == ':') 1281 parse++; 1282 if(*parse == '\r') 1283 parse++; 1284 if(*parse == '\n' || *parse == 0) 1285 continue; 1286 if(*parse == '%') 1287 continue; /* ignore macOSX fe80::1%lo0 localhost */ 1288 if(*parse != ' ' && *parse != '\t') { 1289 /* must have whitespace after address */ 1290 fclose(in); 1291 errno=EINVAL; 1292 return UB_SYNTAX; 1293 } 1294 *parse++ = 0; /* end delimiter for addr ... */ 1295 /* go to names and add them */ 1296 while(*parse) { 1297 while(*parse == ' ' || *parse == '\t' || *parse=='\n' 1298 || *parse=='\r') 1299 parse++; 1300 if(*parse == 0 || *parse == '#') 1301 break; 1302 /* skip name, allows (too) many printable characters */ 1303 name = parse; 1304 while('!' <= *parse && *parse <= '~') 1305 parse++; 1306 if(*parse) 1307 *parse++ = 0; /* end delimiter for name */ 1308 snprintf(ldata, sizeof(ldata), "%s %s %s", 1309 name, str_is_ip6(addr)?"AAAA":"A", addr); 1310 ins = strdup(ldata); 1311 if(!ins) { 1312 /* out of memory */ 1313 fclose(in); 1314 errno=ENOMEM; 1315 return UB_NOMEM; 1316 } 1317 lock_basic_lock(&ctx->cfglock); 1318 if(!cfg_strlist_insert(&ctx->env->cfg->local_data, 1319 ins)) { 1320 lock_basic_unlock(&ctx->cfglock); 1321 fclose(in); 1322 errno=ENOMEM; 1323 return UB_NOMEM; 1324 } 1325 lock_basic_unlock(&ctx->cfglock); 1326 } 1327 } 1328 fclose(in); 1329 return UB_NOERROR; 1330 } 1331 1332 /** finalize the context, if not already finalized */ 1333 static int ub_ctx_finalize(struct ub_ctx* ctx) 1334 { 1335 int res = 0; 1336 lock_basic_lock(&ctx->cfglock); 1337 if (!ctx->finalized) { 1338 res = context_finalize(ctx); 1339 } 1340 lock_basic_unlock(&ctx->cfglock); 1341 return res; 1342 } 1343 1344 /* Print local zones and RR data */ 1345 int ub_ctx_print_local_zones(struct ub_ctx* ctx) 1346 { 1347 int res = ub_ctx_finalize(ctx); 1348 if (res) return res; 1349 1350 local_zones_print(ctx->local_zones); 1351 1352 return UB_NOERROR; 1353 } 1354 1355 /* Add a new zone */ 1356 int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name, 1357 const char *zone_type) 1358 { 1359 enum localzone_type t; 1360 struct local_zone* z; 1361 uint8_t* nm; 1362 int nmlabs; 1363 size_t nmlen; 1364 1365 int res = ub_ctx_finalize(ctx); 1366 if (res) return res; 1367 1368 if(!local_zone_str2type(zone_type, &t)) { 1369 return UB_SYNTAX; 1370 } 1371 1372 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1373 return UB_SYNTAX; 1374 } 1375 1376 lock_rw_wrlock(&ctx->local_zones->lock); 1377 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1378 LDNS_RR_CLASS_IN))) { 1379 /* already present in tree */ 1380 lock_rw_wrlock(&z->lock); 1381 z->type = t; /* update type anyway */ 1382 lock_rw_unlock(&z->lock); 1383 lock_rw_unlock(&ctx->local_zones->lock); 1384 free(nm); 1385 return UB_NOERROR; 1386 } 1387 if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, 1388 LDNS_RR_CLASS_IN, t)) { 1389 lock_rw_unlock(&ctx->local_zones->lock); 1390 return UB_NOMEM; 1391 } 1392 lock_rw_unlock(&ctx->local_zones->lock); 1393 return UB_NOERROR; 1394 } 1395 1396 /* Remove zone */ 1397 int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name) 1398 { 1399 struct local_zone* z; 1400 uint8_t* nm; 1401 int nmlabs; 1402 size_t nmlen; 1403 1404 int res = ub_ctx_finalize(ctx); 1405 if (res) return res; 1406 1407 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1408 return UB_SYNTAX; 1409 } 1410 1411 lock_rw_wrlock(&ctx->local_zones->lock); 1412 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1413 LDNS_RR_CLASS_IN))) { 1414 /* present in tree */ 1415 local_zones_del_zone(ctx->local_zones, z); 1416 } 1417 lock_rw_unlock(&ctx->local_zones->lock); 1418 free(nm); 1419 return UB_NOERROR; 1420 } 1421 1422 /* Add new RR data */ 1423 int ub_ctx_data_add(struct ub_ctx* ctx, const char *data) 1424 { 1425 int res = ub_ctx_finalize(ctx); 1426 if (res) return res; 1427 1428 res = local_zones_add_RR(ctx->local_zones, data); 1429 return (!res) ? UB_NOMEM : UB_NOERROR; 1430 } 1431 1432 /* Remove RR data */ 1433 int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data) 1434 { 1435 uint8_t* nm; 1436 int nmlabs; 1437 size_t nmlen; 1438 int res = ub_ctx_finalize(ctx); 1439 if (res) return res; 1440 1441 if(!parse_dname(data, &nm, &nmlen, &nmlabs)) 1442 return UB_SYNTAX; 1443 1444 local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, 1445 LDNS_RR_CLASS_IN); 1446 1447 free(nm); 1448 return UB_NOERROR; 1449 } 1450 1451 const char* ub_version(void) 1452 { 1453 return PACKAGE_VERSION; 1454 } 1455 1456 int 1457 ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) { 1458 struct ub_event_base* new_base; 1459 1460 if (!ctx || !ctx->event_base || !base) { 1461 return UB_INITFAIL; 1462 } 1463 if (ub_libevent_get_event_base(ctx->event_base) == base) { 1464 /* already set */ 1465 return UB_NOERROR; 1466 } 1467 1468 lock_basic_lock(&ctx->cfglock); 1469 /* destroy the current worker - safe to pass in NULL */ 1470 libworker_delete_event(ctx->event_worker); 1471 ctx->event_worker = NULL; 1472 new_base = ub_libevent_event_base(base); 1473 if (new_base) 1474 ctx->event_base = new_base; 1475 ctx->created_bg = 0; 1476 ctx->dothread = 1; 1477 lock_basic_unlock(&ctx->cfglock); 1478 return new_base ? UB_NOERROR : UB_INITFAIL; 1479 } 1480