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 if(!ctx || ctx->event_base) 575 return UB_INITFAIL; 576 /* no need to hold lock while testing for readability. */ 577 return tube_poll(ctx->rr_pipe); 578 } 579 580 int 581 ub_fd(struct ub_ctx* ctx) 582 { 583 if(!ctx || ctx->event_base) 584 return -1; 585 return tube_read_fd(ctx->rr_pipe); 586 } 587 588 /** process answer from bg worker */ 589 static int 590 process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, 591 ub_callback_type* cb, void** cbarg, int* err, 592 struct ub_result** res) 593 { 594 struct ctx_query* q; 595 if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) { 596 log_err("error: bad data from bg worker %d", 597 (int)context_serial_getcmd(msg, len)); 598 return 0; 599 } 600 601 lock_basic_lock(&ctx->cfglock); 602 q = context_deserialize_answer(ctx, msg, len, err); 603 if(!q) { 604 lock_basic_unlock(&ctx->cfglock); 605 /* probably simply the lookup that failed, i.e. 606 * response returned before cancel was sent out, so noerror */ 607 return 1; 608 } 609 log_assert(q->async); 610 611 /* grab cb while locked */ 612 if(q->cancelled) { 613 *cb = NULL; 614 *cbarg = NULL; 615 } else { 616 *cb = q->cb; 617 *cbarg = q->cb_arg; 618 } 619 if(*err) { 620 *res = NULL; 621 ub_resolve_free(q->res); 622 } else { 623 /* parse the message, extract rcode, fill result */ 624 sldns_buffer* buf = sldns_buffer_new(q->msg_len); 625 struct regional* region = regional_create(); 626 *res = q->res; 627 (*res)->rcode = LDNS_RCODE_SERVFAIL; 628 if(region && buf) { 629 sldns_buffer_clear(buf); 630 sldns_buffer_write(buf, q->msg, q->msg_len); 631 sldns_buffer_flip(buf); 632 libworker_enter_result(*res, buf, region, 633 q->msg_security); 634 } 635 (*res)->answer_packet = q->msg; 636 (*res)->answer_len = (int)q->msg_len; 637 q->msg = NULL; 638 sldns_buffer_free(buf); 639 regional_destroy(region); 640 } 641 q->res = NULL; 642 /* delete the q from list */ 643 (void)rbtree_delete(&ctx->queries, q->node.key); 644 ctx->num_async--; 645 context_query_delete(q); 646 lock_basic_unlock(&ctx->cfglock); 647 648 if(*cb) return 2; 649 ub_resolve_free(*res); 650 return 1; 651 } 652 653 /** process answer from bg worker */ 654 static int 655 process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len) 656 { 657 int err; 658 ub_callback_type cb; 659 void* cbarg; 660 struct ub_result* res; 661 int r; 662 663 r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res); 664 665 /* no locks held while calling callback, so that library is 666 * re-entrant. */ 667 if(r == 2) 668 (*cb)(cbarg, err, res); 669 670 return r; 671 } 672 673 int 674 ub_process(struct ub_ctx* ctx) 675 { 676 int r; 677 uint8_t* msg; 678 uint32_t len; 679 if(!ctx || ctx->event_base) 680 return UB_INITFAIL; 681 while(1) { 682 msg = NULL; 683 lock_basic_lock(&ctx->rrpipe_lock); 684 r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); 685 lock_basic_unlock(&ctx->rrpipe_lock); 686 if(r == 0) 687 return UB_PIPE; 688 else if(r == -1) 689 break; 690 if(!process_answer(ctx, msg, len)) { 691 free(msg); 692 return UB_PIPE; 693 } 694 free(msg); 695 } 696 return UB_NOERROR; 697 } 698 699 int 700 ub_wait(struct ub_ctx* ctx) 701 { 702 int err; 703 ub_callback_type cb; 704 void* cbarg; 705 struct ub_result* res; 706 int r; 707 uint8_t* msg; 708 uint32_t len; 709 if(!ctx || ctx->event_base) 710 return UB_INITFAIL; 711 /* this is basically the same loop as _process(), but with changes. 712 * holds the rrpipe lock and waits with tube_wait */ 713 while(1) { 714 lock_basic_lock(&ctx->rrpipe_lock); 715 lock_basic_lock(&ctx->cfglock); 716 if(ctx->num_async == 0) { 717 lock_basic_unlock(&ctx->cfglock); 718 lock_basic_unlock(&ctx->rrpipe_lock); 719 break; 720 } 721 lock_basic_unlock(&ctx->cfglock); 722 723 /* keep rrpipe locked, while 724 * o waiting for pipe readable 725 * o parsing message 726 * o possibly decrementing num_async 727 * do callback without lock 728 */ 729 r = tube_wait(ctx->rr_pipe); 730 if(r) { 731 r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); 732 if(r == 0) { 733 lock_basic_unlock(&ctx->rrpipe_lock); 734 return UB_PIPE; 735 } 736 if(r == -1) { 737 lock_basic_unlock(&ctx->rrpipe_lock); 738 continue; 739 } 740 r = process_answer_detail(ctx, msg, len, 741 &cb, &cbarg, &err, &res); 742 lock_basic_unlock(&ctx->rrpipe_lock); 743 free(msg); 744 if(r == 0) 745 return UB_PIPE; 746 if(r == 2) 747 (*cb)(cbarg, err, res); 748 } else { 749 lock_basic_unlock(&ctx->rrpipe_lock); 750 } 751 } 752 return UB_NOERROR; 753 } 754 755 int 756 ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype, 757 int rrclass, struct ub_result** result) 758 { 759 struct ctx_query* q; 760 int r; 761 *result = NULL; 762 763 lock_basic_lock(&ctx->cfglock); 764 if(!ctx->finalized) { 765 r = context_finalize(ctx); 766 if(r) { 767 lock_basic_unlock(&ctx->cfglock); 768 return r; 769 } 770 } 771 /* create new ctx_query and attempt to add to the list */ 772 lock_basic_unlock(&ctx->cfglock); 773 q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL); 774 if(!q) 775 return UB_NOMEM; 776 /* become a resolver thread for a bit */ 777 778 r = libworker_fg(ctx, q); 779 if(r) { 780 lock_basic_lock(&ctx->cfglock); 781 (void)rbtree_delete(&ctx->queries, q->node.key); 782 context_query_delete(q); 783 lock_basic_unlock(&ctx->cfglock); 784 return r; 785 } 786 q->res->answer_packet = q->msg; 787 q->res->answer_len = (int)q->msg_len; 788 q->msg = NULL; 789 *result = q->res; 790 q->res = NULL; 791 792 lock_basic_lock(&ctx->cfglock); 793 (void)rbtree_delete(&ctx->queries, q->node.key); 794 context_query_delete(q); 795 lock_basic_unlock(&ctx->cfglock); 796 return UB_NOERROR; 797 } 798 799 int 800 ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, 801 int rrclass, void* mydata, ub_event_callback_type callback, 802 int* async_id) 803 { 804 struct ctx_query* q; 805 int r; 806 807 if(async_id) 808 *async_id = 0; 809 lock_basic_lock(&ctx->cfglock); 810 if(!ctx->finalized) { 811 r = context_finalize(ctx); 812 if(r) { 813 lock_basic_unlock(&ctx->cfglock); 814 return r; 815 } 816 } 817 lock_basic_unlock(&ctx->cfglock); 818 if(!ctx->event_worker) { 819 ctx->event_worker = libworker_create_event(ctx, 820 ctx->event_base); 821 if(!ctx->event_worker) { 822 return UB_INITFAIL; 823 } 824 } 825 826 /* set time in case answer comes from cache */ 827 ub_comm_base_now(ctx->event_worker->base); 828 829 /* create new ctx_query and attempt to add to the list */ 830 q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata); 831 if(!q) 832 return UB_NOMEM; 833 834 /* attach to mesh */ 835 if((r=libworker_attach_mesh(ctx, q, async_id)) != 0) 836 return r; 837 return UB_NOERROR; 838 } 839 840 841 int 842 ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, 843 int rrclass, void* mydata, ub_callback_type callback, int* async_id) 844 { 845 struct ctx_query* q; 846 uint8_t* msg = NULL; 847 uint32_t len = 0; 848 if(!ctx || ctx->event_base) 849 return UB_INITFAIL; 850 851 if(async_id) 852 *async_id = 0; 853 lock_basic_lock(&ctx->cfglock); 854 if(!ctx->finalized) { 855 int r = context_finalize(ctx); 856 if(r) { 857 lock_basic_unlock(&ctx->cfglock); 858 return r; 859 } 860 } 861 if(!ctx->created_bg) { 862 int r; 863 ctx->created_bg = 1; 864 lock_basic_unlock(&ctx->cfglock); 865 r = libworker_bg(ctx); 866 if(r) { 867 lock_basic_lock(&ctx->cfglock); 868 ctx->created_bg = 0; 869 lock_basic_unlock(&ctx->cfglock); 870 return r; 871 } 872 } else { 873 lock_basic_unlock(&ctx->cfglock); 874 } 875 876 /* create new ctx_query and attempt to add to the list */ 877 q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata); 878 if(!q) 879 return UB_NOMEM; 880 881 /* write over pipe to background worker */ 882 lock_basic_lock(&ctx->cfglock); 883 msg = context_serialize_new_query(q, &len); 884 if(!msg) { 885 (void)rbtree_delete(&ctx->queries, q->node.key); 886 ctx->num_async--; 887 context_query_delete(q); 888 lock_basic_unlock(&ctx->cfglock); 889 return UB_NOMEM; 890 } 891 if(async_id) 892 *async_id = q->querynum; 893 lock_basic_unlock(&ctx->cfglock); 894 895 lock_basic_lock(&ctx->qqpipe_lock); 896 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 897 lock_basic_unlock(&ctx->qqpipe_lock); 898 free(msg); 899 return UB_PIPE; 900 } 901 lock_basic_unlock(&ctx->qqpipe_lock); 902 free(msg); 903 return UB_NOERROR; 904 } 905 906 int 907 ub_cancel(struct ub_ctx* ctx, int async_id) 908 { 909 struct ctx_query* q; 910 uint8_t* msg = NULL; 911 uint32_t len = 0; 912 lock_basic_lock(&ctx->cfglock); 913 q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id); 914 if(!q || !q->async) { 915 /* it is not there, so nothing to do */ 916 lock_basic_unlock(&ctx->cfglock); 917 return UB_NOID; 918 } 919 log_assert(q->async); 920 q->cancelled = 1; 921 922 /* delete it */ 923 if(!ctx->dothread) { /* if forked */ 924 (void)rbtree_delete(&ctx->queries, q->node.key); 925 ctx->num_async--; 926 msg = context_serialize_cancel(q, &len); 927 context_query_delete(q); 928 lock_basic_unlock(&ctx->cfglock); 929 if(!msg) { 930 return UB_NOMEM; 931 } 932 /* send cancel to background worker */ 933 lock_basic_lock(&ctx->qqpipe_lock); 934 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 935 lock_basic_unlock(&ctx->qqpipe_lock); 936 free(msg); 937 return UB_PIPE; 938 } 939 lock_basic_unlock(&ctx->qqpipe_lock); 940 free(msg); 941 } else { 942 lock_basic_unlock(&ctx->cfglock); 943 } 944 return UB_NOERROR; 945 } 946 947 void 948 ub_resolve_free(struct ub_result* result) 949 { 950 char** p; 951 if(!result) return; 952 free(result->qname); 953 if(result->canonname != result->qname) 954 free(result->canonname); 955 if(result->data) 956 for(p = result->data; *p; p++) 957 free(*p); 958 free(result->data); 959 free(result->len); 960 free(result->answer_packet); 961 free(result->why_bogus); 962 free(result); 963 } 964 965 const char* 966 ub_strerror(int err) 967 { 968 switch(err) { 969 case UB_NOERROR: return "no error"; 970 case UB_SOCKET: return "socket io error"; 971 case UB_NOMEM: return "out of memory"; 972 case UB_SYNTAX: return "syntax error"; 973 case UB_SERVFAIL: return "server failure"; 974 case UB_FORKFAIL: return "could not fork"; 975 case UB_INITFAIL: return "initialization failure"; 976 case UB_AFTERFINAL: return "setting change after finalize"; 977 case UB_PIPE: return "error in pipe communication with async"; 978 case UB_READFILE: return "error reading file"; 979 case UB_NOID: return "error async_id does not exist"; 980 default: return "unknown error"; 981 } 982 } 983 984 int 985 ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr) 986 { 987 struct sockaddr_storage storage; 988 socklen_t stlen; 989 struct config_stub* s; 990 char* dupl; 991 lock_basic_lock(&ctx->cfglock); 992 if(ctx->finalized) { 993 lock_basic_unlock(&ctx->cfglock); 994 errno=EINVAL; 995 return UB_AFTERFINAL; 996 } 997 if(!addr) { 998 /* disable fwd mode - the root stub should be first. */ 999 if(ctx->env->cfg->forwards && 1000 (ctx->env->cfg->forwards->name && 1001 strcmp(ctx->env->cfg->forwards->name, ".") == 0)) { 1002 s = ctx->env->cfg->forwards; 1003 ctx->env->cfg->forwards = s->next; 1004 s->next = NULL; 1005 config_delstubs(s); 1006 } 1007 lock_basic_unlock(&ctx->cfglock); 1008 return UB_NOERROR; 1009 } 1010 lock_basic_unlock(&ctx->cfglock); 1011 1012 /* check syntax for addr */ 1013 if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) { 1014 errno=EINVAL; 1015 return UB_SYNTAX; 1016 } 1017 1018 /* it parses, add root stub in front of list */ 1019 lock_basic_lock(&ctx->cfglock); 1020 if(!ctx->env->cfg->forwards || 1021 (ctx->env->cfg->forwards->name && 1022 strcmp(ctx->env->cfg->forwards->name, ".") != 0)) { 1023 s = calloc(1, sizeof(*s)); 1024 if(!s) { 1025 lock_basic_unlock(&ctx->cfglock); 1026 errno=ENOMEM; 1027 return UB_NOMEM; 1028 } 1029 s->name = strdup("."); 1030 if(!s->name) { 1031 free(s); 1032 lock_basic_unlock(&ctx->cfglock); 1033 errno=ENOMEM; 1034 return UB_NOMEM; 1035 } 1036 s->next = ctx->env->cfg->forwards; 1037 ctx->env->cfg->forwards = s; 1038 } else { 1039 log_assert(ctx->env->cfg->forwards); 1040 log_assert(ctx->env->cfg->forwards->name); 1041 s = ctx->env->cfg->forwards; 1042 } 1043 dupl = strdup(addr); 1044 if(!dupl) { 1045 lock_basic_unlock(&ctx->cfglock); 1046 errno=ENOMEM; 1047 return UB_NOMEM; 1048 } 1049 if(!cfg_strlist_insert(&s->addrs, dupl)) { 1050 lock_basic_unlock(&ctx->cfglock); 1051 errno=ENOMEM; 1052 return UB_NOMEM; 1053 } 1054 lock_basic_unlock(&ctx->cfglock); 1055 return UB_NOERROR; 1056 } 1057 1058 int ub_ctx_set_tls(struct ub_ctx* ctx, int tls) 1059 { 1060 lock_basic_lock(&ctx->cfglock); 1061 if(ctx->finalized) { 1062 lock_basic_unlock(&ctx->cfglock); 1063 errno=EINVAL; 1064 return UB_AFTERFINAL; 1065 } 1066 ctx->env->cfg->ssl_upstream = tls; 1067 lock_basic_unlock(&ctx->cfglock); 1068 return UB_NOERROR; 1069 } 1070 1071 int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, 1072 int isprime) 1073 { 1074 char* a; 1075 struct config_stub **prev, *elem; 1076 1077 /* check syntax for zone name */ 1078 if(zone) { 1079 uint8_t* nm; 1080 int nmlabs; 1081 size_t nmlen; 1082 if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) { 1083 errno=EINVAL; 1084 return UB_SYNTAX; 1085 } 1086 free(nm); 1087 } else { 1088 zone = "."; 1089 } 1090 1091 /* check syntax for addr (if not NULL) */ 1092 if(addr) { 1093 struct sockaddr_storage storage; 1094 socklen_t stlen; 1095 if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) { 1096 errno=EINVAL; 1097 return UB_SYNTAX; 1098 } 1099 } 1100 1101 lock_basic_lock(&ctx->cfglock); 1102 if(ctx->finalized) { 1103 lock_basic_unlock(&ctx->cfglock); 1104 errno=EINVAL; 1105 return UB_AFTERFINAL; 1106 } 1107 1108 /* arguments all right, now find or add the stub */ 1109 prev = &ctx->env->cfg->stubs; 1110 elem = cfg_stub_find(&prev, zone); 1111 if(!elem && !addr) { 1112 /* not found and we want to delete, nothing to do */ 1113 lock_basic_unlock(&ctx->cfglock); 1114 return UB_NOERROR; 1115 } else if(elem && !addr) { 1116 /* found, and we want to delete */ 1117 *prev = elem->next; 1118 config_delstub(elem); 1119 lock_basic_unlock(&ctx->cfglock); 1120 return UB_NOERROR; 1121 } else if(!elem) { 1122 /* not found, create the stub entry */ 1123 elem=(struct config_stub*)calloc(1, sizeof(struct config_stub)); 1124 if(elem) elem->name = strdup(zone); 1125 if(!elem || !elem->name) { 1126 free(elem); 1127 lock_basic_unlock(&ctx->cfglock); 1128 errno = ENOMEM; 1129 return UB_NOMEM; 1130 } 1131 elem->next = ctx->env->cfg->stubs; 1132 ctx->env->cfg->stubs = elem; 1133 } 1134 1135 /* add the address to the list and set settings */ 1136 elem->isprime = isprime; 1137 a = strdup(addr); 1138 if(!a) { 1139 lock_basic_unlock(&ctx->cfglock); 1140 errno = ENOMEM; 1141 return UB_NOMEM; 1142 } 1143 if(!cfg_strlist_insert(&elem->addrs, a)) { 1144 lock_basic_unlock(&ctx->cfglock); 1145 errno = ENOMEM; 1146 return UB_NOMEM; 1147 } 1148 lock_basic_unlock(&ctx->cfglock); 1149 return UB_NOERROR; 1150 } 1151 1152 int 1153 ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname) 1154 { 1155 FILE* in; 1156 int numserv = 0; 1157 char buf[1024]; 1158 char* parse, *addr; 1159 int r; 1160 1161 if(fname == NULL) { 1162 #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) 1163 fname = "/etc/resolv.conf"; 1164 #else 1165 FIXED_INFO *info; 1166 ULONG buflen = sizeof(*info); 1167 IP_ADDR_STRING *ptr; 1168 1169 info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO)); 1170 if (info == NULL) 1171 return UB_READFILE; 1172 1173 if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { 1174 free(info); 1175 info = (FIXED_INFO *) malloc(buflen); 1176 if (info == NULL) 1177 return UB_READFILE; 1178 } 1179 1180 if (GetNetworkParams(info, &buflen) == NO_ERROR) { 1181 int retval=0; 1182 ptr = &(info->DnsServerList); 1183 while (ptr) { 1184 numserv++; 1185 if((retval=ub_ctx_set_fwd(ctx, 1186 ptr->IpAddress.String))!=0) { 1187 free(info); 1188 return retval; 1189 } 1190 ptr = ptr->Next; 1191 } 1192 free(info); 1193 if (numserv==0) 1194 return UB_READFILE; 1195 return UB_NOERROR; 1196 } 1197 free(info); 1198 return UB_READFILE; 1199 #endif /* WINDOWS */ 1200 } 1201 in = fopen(fname, "r"); 1202 if(!in) { 1203 /* error in errno! perror(fname) */ 1204 return UB_READFILE; 1205 } 1206 while(fgets(buf, (int)sizeof(buf), in)) { 1207 buf[sizeof(buf)-1] = 0; 1208 parse=buf; 1209 while(*parse == ' ' || *parse == '\t') 1210 parse++; 1211 if(strncmp(parse, "nameserver", 10) == 0) { 1212 numserv++; 1213 parse += 10; /* skip 'nameserver' */ 1214 /* skip whitespace */ 1215 while(*parse == ' ' || *parse == '\t') 1216 parse++; 1217 addr = parse; 1218 /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ 1219 while(isxdigit((unsigned char)*parse) || *parse=='.' || *parse==':') 1220 parse++; 1221 /* terminate after the address, remove newline */ 1222 *parse = 0; 1223 1224 if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) { 1225 fclose(in); 1226 return r; 1227 } 1228 } 1229 } 1230 fclose(in); 1231 if(numserv == 0) { 1232 /* from resolv.conf(5) if none given, use localhost */ 1233 return ub_ctx_set_fwd(ctx, "127.0.0.1"); 1234 } 1235 return UB_NOERROR; 1236 } 1237 1238 int 1239 ub_ctx_hosts(struct ub_ctx* ctx, const char* fname) 1240 { 1241 FILE* in; 1242 char buf[1024], ldata[2048]; 1243 char* parse, *addr, *name, *ins; 1244 lock_basic_lock(&ctx->cfglock); 1245 if(ctx->finalized) { 1246 lock_basic_unlock(&ctx->cfglock); 1247 errno=EINVAL; 1248 return UB_AFTERFINAL; 1249 } 1250 lock_basic_unlock(&ctx->cfglock); 1251 if(fname == NULL) { 1252 #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) 1253 /* 1254 * If this is Windows NT/XP/2K it's in 1255 * %WINDIR%\system32\drivers\etc\hosts. 1256 * If this is Windows 95/98/Me it's in %WINDIR%\hosts. 1257 */ 1258 name = getenv("WINDIR"); 1259 if (name != NULL) { 1260 int retval=0; 1261 snprintf(buf, sizeof(buf), "%s%s", name, 1262 "\\system32\\drivers\\etc\\hosts"); 1263 if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { 1264 snprintf(buf, sizeof(buf), "%s%s", name, 1265 "\\hosts"); 1266 retval=ub_ctx_hosts(ctx, buf); 1267 } 1268 return retval; 1269 } 1270 return UB_READFILE; 1271 #else 1272 fname = "/etc/hosts"; 1273 #endif /* WIN32 */ 1274 } 1275 in = fopen(fname, "r"); 1276 if(!in) { 1277 /* error in errno! perror(fname) */ 1278 return UB_READFILE; 1279 } 1280 while(fgets(buf, (int)sizeof(buf), in)) { 1281 buf[sizeof(buf)-1] = 0; 1282 parse=buf; 1283 while(*parse == ' ' || *parse == '\t') 1284 parse++; 1285 if(*parse == '#') 1286 continue; /* skip comment */ 1287 /* format: <addr> spaces <name> spaces <name> ... */ 1288 addr = parse; 1289 /* skip addr */ 1290 while(isxdigit((unsigned char)*parse) || *parse == '.' || *parse == ':') 1291 parse++; 1292 if(*parse == '\r') 1293 parse++; 1294 if(*parse == '\n' || *parse == 0) 1295 continue; 1296 if(*parse == '%') 1297 continue; /* ignore macOSX fe80::1%lo0 localhost */ 1298 if(*parse != ' ' && *parse != '\t') { 1299 /* must have whitespace after address */ 1300 fclose(in); 1301 errno=EINVAL; 1302 return UB_SYNTAX; 1303 } 1304 *parse++ = 0; /* end delimiter for addr ... */ 1305 /* go to names and add them */ 1306 while(*parse) { 1307 while(*parse == ' ' || *parse == '\t' || *parse=='\n' 1308 || *parse=='\r') 1309 parse++; 1310 if(*parse == 0 || *parse == '#') 1311 break; 1312 /* skip name, allows (too) many printable characters */ 1313 name = parse; 1314 while('!' <= *parse && *parse <= '~') 1315 parse++; 1316 if(*parse) 1317 *parse++ = 0; /* end delimiter for name */ 1318 snprintf(ldata, sizeof(ldata), "%s %s %s", 1319 name, str_is_ip6(addr)?"AAAA":"A", addr); 1320 ins = strdup(ldata); 1321 if(!ins) { 1322 /* out of memory */ 1323 fclose(in); 1324 errno=ENOMEM; 1325 return UB_NOMEM; 1326 } 1327 lock_basic_lock(&ctx->cfglock); 1328 if(!cfg_strlist_insert(&ctx->env->cfg->local_data, 1329 ins)) { 1330 lock_basic_unlock(&ctx->cfglock); 1331 fclose(in); 1332 errno=ENOMEM; 1333 return UB_NOMEM; 1334 } 1335 lock_basic_unlock(&ctx->cfglock); 1336 } 1337 } 1338 fclose(in); 1339 return UB_NOERROR; 1340 } 1341 1342 /** finalize the context, if not already finalized */ 1343 static int ub_ctx_finalize(struct ub_ctx* ctx) 1344 { 1345 int res = 0; 1346 lock_basic_lock(&ctx->cfglock); 1347 if (!ctx->finalized) { 1348 res = context_finalize(ctx); 1349 } 1350 lock_basic_unlock(&ctx->cfglock); 1351 return res; 1352 } 1353 1354 /* Print local zones and RR data */ 1355 int ub_ctx_print_local_zones(struct ub_ctx* ctx) 1356 { 1357 int res = ub_ctx_finalize(ctx); 1358 if (res) return res; 1359 1360 local_zones_print(ctx->local_zones); 1361 1362 return UB_NOERROR; 1363 } 1364 1365 /* Add a new zone */ 1366 int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name, 1367 const char *zone_type) 1368 { 1369 enum localzone_type t; 1370 struct local_zone* z; 1371 uint8_t* nm; 1372 int nmlabs; 1373 size_t nmlen; 1374 1375 int res = ub_ctx_finalize(ctx); 1376 if (res) return res; 1377 1378 if(!local_zone_str2type(zone_type, &t)) { 1379 return UB_SYNTAX; 1380 } 1381 1382 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1383 return UB_SYNTAX; 1384 } 1385 1386 lock_rw_wrlock(&ctx->local_zones->lock); 1387 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1388 LDNS_RR_CLASS_IN))) { 1389 /* already present in tree */ 1390 lock_rw_wrlock(&z->lock); 1391 z->type = t; /* update type anyway */ 1392 lock_rw_unlock(&z->lock); 1393 lock_rw_unlock(&ctx->local_zones->lock); 1394 free(nm); 1395 return UB_NOERROR; 1396 } 1397 if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, 1398 LDNS_RR_CLASS_IN, t)) { 1399 lock_rw_unlock(&ctx->local_zones->lock); 1400 return UB_NOMEM; 1401 } 1402 lock_rw_unlock(&ctx->local_zones->lock); 1403 return UB_NOERROR; 1404 } 1405 1406 /* Remove zone */ 1407 int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name) 1408 { 1409 struct local_zone* z; 1410 uint8_t* nm; 1411 int nmlabs; 1412 size_t nmlen; 1413 1414 int res = ub_ctx_finalize(ctx); 1415 if (res) return res; 1416 1417 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1418 return UB_SYNTAX; 1419 } 1420 1421 lock_rw_wrlock(&ctx->local_zones->lock); 1422 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1423 LDNS_RR_CLASS_IN))) { 1424 /* present in tree */ 1425 local_zones_del_zone(ctx->local_zones, z); 1426 } 1427 lock_rw_unlock(&ctx->local_zones->lock); 1428 free(nm); 1429 return UB_NOERROR; 1430 } 1431 1432 /* Add new RR data */ 1433 int ub_ctx_data_add(struct ub_ctx* ctx, const char *data) 1434 { 1435 int res = ub_ctx_finalize(ctx); 1436 if (res) return res; 1437 1438 res = local_zones_add_RR(ctx->local_zones, data); 1439 return (!res) ? UB_NOMEM : UB_NOERROR; 1440 } 1441 1442 /* Remove RR data */ 1443 int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data) 1444 { 1445 uint8_t* nm; 1446 int nmlabs; 1447 size_t nmlen; 1448 int res = ub_ctx_finalize(ctx); 1449 if (res) return res; 1450 1451 if(!parse_dname(data, &nm, &nmlen, &nmlabs)) 1452 return UB_SYNTAX; 1453 1454 local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, 1455 LDNS_RR_CLASS_IN); 1456 1457 free(nm); 1458 return UB_NOERROR; 1459 } 1460 1461 const char* ub_version(void) 1462 { 1463 return PACKAGE_VERSION; 1464 } 1465 1466 int 1467 ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) { 1468 struct ub_event_base* new_base; 1469 1470 if (!ctx || !ctx->event_base || !base) { 1471 return UB_INITFAIL; 1472 } 1473 if (ub_libevent_get_event_base(ctx->event_base) == base) { 1474 /* already set */ 1475 return UB_NOERROR; 1476 } 1477 1478 lock_basic_lock(&ctx->cfglock); 1479 /* destroy the current worker - safe to pass in NULL */ 1480 1481 /* Unlock the cfglock during libworker_delete_event, since it 1482 * calls context_release_alloc, that wants to lock cfglock again. 1483 * Since the event base is used from one thread, the one that 1484 * called this function, it is safe to do so. */ 1485 lock_basic_unlock(&ctx->cfglock); 1486 libworker_delete_event(ctx->event_worker); 1487 ctx->event_worker = NULL; 1488 lock_basic_lock(&ctx->cfglock); 1489 new_base = ub_libevent_event_base(base); 1490 if (new_base) 1491 ctx->event_base = new_base; 1492 ctx->created_bg = 0; 1493 ctx->dothread = 1; 1494 lock_basic_unlock(&ctx->cfglock); 1495 return new_base ? UB_NOERROR : UB_INITFAIL; 1496 } 1497