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