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