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