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 seed = 0; 113 ub_randfree(ctx->seed_rnd); 114 free(ctx); 115 errno = ENOMEM; 116 return NULL; 117 } 118 seed = 0; 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 free(dup); 396 return UB_NOMEM; 397 } 398 lock_basic_unlock(&ctx->cfglock); 399 return UB_NOERROR; 400 } 401 402 int 403 ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname) 404 { 405 char* dup = strdup(fname); 406 if(!dup) return UB_NOMEM; 407 lock_basic_lock(&ctx->cfglock); 408 if(ctx->finalized) { 409 lock_basic_unlock(&ctx->cfglock); 410 free(dup); 411 return UB_AFTERFINAL; 412 } 413 if(!cfg_strlist_insert(&ctx->env->cfg->trust_anchor_file_list, dup)) { 414 lock_basic_unlock(&ctx->cfglock); 415 free(dup); 416 return UB_NOMEM; 417 } 418 lock_basic_unlock(&ctx->cfglock); 419 return UB_NOERROR; 420 } 421 422 int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname) 423 { 424 char* dup = strdup(fname); 425 if(!dup) return UB_NOMEM; 426 lock_basic_lock(&ctx->cfglock); 427 if(ctx->finalized) { 428 lock_basic_unlock(&ctx->cfglock); 429 free(dup); 430 return UB_AFTERFINAL; 431 } 432 if(!cfg_strlist_insert(&ctx->env->cfg->auto_trust_anchor_file_list, 433 dup)) { 434 lock_basic_unlock(&ctx->cfglock); 435 free(dup); 436 return UB_NOMEM; 437 } 438 lock_basic_unlock(&ctx->cfglock); 439 return UB_NOERROR; 440 } 441 442 int 443 ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname) 444 { 445 char* dup = strdup(fname); 446 if(!dup) return UB_NOMEM; 447 lock_basic_lock(&ctx->cfglock); 448 if(ctx->finalized) { 449 lock_basic_unlock(&ctx->cfglock); 450 free(dup); 451 return UB_AFTERFINAL; 452 } 453 if(!cfg_strlist_insert(&ctx->env->cfg->trusted_keys_file_list, dup)) { 454 lock_basic_unlock(&ctx->cfglock); 455 free(dup); 456 return UB_NOMEM; 457 } 458 lock_basic_unlock(&ctx->cfglock); 459 return UB_NOERROR; 460 } 461 462 int 463 ub_ctx_debuglevel(struct ub_ctx* ctx, int d) 464 { 465 lock_basic_lock(&ctx->cfglock); 466 verbosity = d; 467 ctx->env->cfg->verbosity = d; 468 lock_basic_unlock(&ctx->cfglock); 469 return UB_NOERROR; 470 } 471 472 int ub_ctx_debugout(struct ub_ctx* ctx, void* out) 473 { 474 lock_basic_lock(&ctx->cfglock); 475 log_file((FILE*)out); 476 ctx->logfile_override = 1; 477 ctx->log_out = out; 478 lock_basic_unlock(&ctx->cfglock); 479 return UB_NOERROR; 480 } 481 482 int 483 ub_ctx_async(struct ub_ctx* ctx, int dothread) 484 { 485 #ifdef THREADS_DISABLED 486 if(dothread) /* cannot do threading */ 487 return UB_NOERROR; 488 #endif 489 lock_basic_lock(&ctx->cfglock); 490 if(ctx->finalized) { 491 lock_basic_unlock(&ctx->cfglock); 492 return UB_AFTERFINAL; 493 } 494 ctx->dothread = dothread; 495 lock_basic_unlock(&ctx->cfglock); 496 return UB_NOERROR; 497 } 498 499 int 500 ub_poll(struct ub_ctx* ctx) 501 { 502 /* no need to hold lock while testing for readability. */ 503 return tube_poll(ctx->rr_pipe); 504 } 505 506 int 507 ub_fd(struct ub_ctx* ctx) 508 { 509 return tube_read_fd(ctx->rr_pipe); 510 } 511 512 /** process answer from bg worker */ 513 static int 514 process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, 515 ub_callback_type* cb, void** cbarg, int* err, 516 struct ub_result** res) 517 { 518 struct ctx_query* q; 519 if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) { 520 log_err("error: bad data from bg worker %d", 521 (int)context_serial_getcmd(msg, len)); 522 return 0; 523 } 524 525 lock_basic_lock(&ctx->cfglock); 526 q = context_deserialize_answer(ctx, msg, len, err); 527 if(!q) { 528 lock_basic_unlock(&ctx->cfglock); 529 /* probably simply the lookup that failed, i.e. 530 * response returned before cancel was sent out, so noerror */ 531 return 1; 532 } 533 log_assert(q->async); 534 535 /* grab cb while locked */ 536 if(q->cancelled) { 537 *cb = NULL; 538 *cbarg = NULL; 539 } else { 540 *cb = q->cb; 541 *cbarg = q->cb_arg; 542 } 543 if(*err) { 544 *res = NULL; 545 ub_resolve_free(q->res); 546 } else { 547 /* parse the message, extract rcode, fill result */ 548 sldns_buffer* buf = sldns_buffer_new(q->msg_len); 549 struct regional* region = regional_create(); 550 *res = q->res; 551 (*res)->rcode = LDNS_RCODE_SERVFAIL; 552 if(region && buf) { 553 sldns_buffer_clear(buf); 554 sldns_buffer_write(buf, q->msg, q->msg_len); 555 sldns_buffer_flip(buf); 556 libworker_enter_result(*res, buf, region, 557 q->msg_security); 558 } 559 (*res)->answer_packet = q->msg; 560 (*res)->answer_len = (int)q->msg_len; 561 q->msg = NULL; 562 sldns_buffer_free(buf); 563 regional_destroy(region); 564 } 565 q->res = NULL; 566 /* delete the q from list */ 567 (void)rbtree_delete(&ctx->queries, q->node.key); 568 ctx->num_async--; 569 context_query_delete(q); 570 lock_basic_unlock(&ctx->cfglock); 571 572 if(*cb) return 2; 573 ub_resolve_free(*res); 574 return 1; 575 } 576 577 /** process answer from bg worker */ 578 static int 579 process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len) 580 { 581 int err; 582 ub_callback_type cb; 583 void* cbarg; 584 struct ub_result* res; 585 int r; 586 587 r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res); 588 589 /* no locks held while calling callback, so that library is 590 * re-entrant. */ 591 if(r == 2) 592 (*cb)(cbarg, err, res); 593 594 return r; 595 } 596 597 int 598 ub_process(struct ub_ctx* ctx) 599 { 600 int r; 601 uint8_t* msg; 602 uint32_t len; 603 while(1) { 604 msg = NULL; 605 lock_basic_lock(&ctx->rrpipe_lock); 606 r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); 607 lock_basic_unlock(&ctx->rrpipe_lock); 608 if(r == 0) 609 return UB_PIPE; 610 else if(r == -1) 611 break; 612 if(!process_answer(ctx, msg, len)) { 613 free(msg); 614 return UB_PIPE; 615 } 616 free(msg); 617 } 618 return UB_NOERROR; 619 } 620 621 int 622 ub_wait(struct ub_ctx* ctx) 623 { 624 int err; 625 ub_callback_type cb; 626 void* cbarg; 627 struct ub_result* res; 628 int r; 629 uint8_t* msg; 630 uint32_t len; 631 /* this is basically the same loop as _process(), but with changes. 632 * holds the rrpipe lock and waits with tube_wait */ 633 while(1) { 634 lock_basic_lock(&ctx->rrpipe_lock); 635 lock_basic_lock(&ctx->cfglock); 636 if(ctx->num_async == 0) { 637 lock_basic_unlock(&ctx->cfglock); 638 lock_basic_unlock(&ctx->rrpipe_lock); 639 break; 640 } 641 lock_basic_unlock(&ctx->cfglock); 642 643 /* keep rrpipe locked, while 644 * o waiting for pipe readable 645 * o parsing message 646 * o possibly decrementing num_async 647 * do callback without lock 648 */ 649 r = tube_wait(ctx->rr_pipe); 650 if(r) { 651 r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1); 652 if(r == 0) { 653 lock_basic_unlock(&ctx->rrpipe_lock); 654 return UB_PIPE; 655 } 656 if(r == -1) { 657 lock_basic_unlock(&ctx->rrpipe_lock); 658 continue; 659 } 660 r = process_answer_detail(ctx, msg, len, 661 &cb, &cbarg, &err, &res); 662 lock_basic_unlock(&ctx->rrpipe_lock); 663 free(msg); 664 if(r == 0) 665 return UB_PIPE; 666 if(r == 2) 667 (*cb)(cbarg, err, res); 668 } else { 669 lock_basic_unlock(&ctx->rrpipe_lock); 670 } 671 } 672 return UB_NOERROR; 673 } 674 675 int 676 ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype, 677 int rrclass, struct ub_result** result) 678 { 679 struct ctx_query* q; 680 int r; 681 *result = NULL; 682 683 lock_basic_lock(&ctx->cfglock); 684 if(!ctx->finalized) { 685 r = context_finalize(ctx); 686 if(r) { 687 lock_basic_unlock(&ctx->cfglock); 688 return r; 689 } 690 } 691 /* create new ctx_query and attempt to add to the list */ 692 lock_basic_unlock(&ctx->cfglock); 693 q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL); 694 if(!q) 695 return UB_NOMEM; 696 /* become a resolver thread for a bit */ 697 698 r = libworker_fg(ctx, q); 699 if(r) { 700 lock_basic_lock(&ctx->cfglock); 701 (void)rbtree_delete(&ctx->queries, q->node.key); 702 context_query_delete(q); 703 lock_basic_unlock(&ctx->cfglock); 704 return r; 705 } 706 q->res->answer_packet = q->msg; 707 q->res->answer_len = (int)q->msg_len; 708 q->msg = NULL; 709 *result = q->res; 710 q->res = NULL; 711 712 lock_basic_lock(&ctx->cfglock); 713 (void)rbtree_delete(&ctx->queries, q->node.key); 714 context_query_delete(q); 715 lock_basic_unlock(&ctx->cfglock); 716 return UB_NOERROR; 717 } 718 719 int 720 ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype, 721 int rrclass, void* mydata, ub_event_callback_type callback, 722 int* async_id) 723 { 724 struct ctx_query* q; 725 int r; 726 727 if(async_id) 728 *async_id = 0; 729 lock_basic_lock(&ctx->cfglock); 730 if(!ctx->finalized) { 731 int r = context_finalize(ctx); 732 if(r) { 733 lock_basic_unlock(&ctx->cfglock); 734 return r; 735 } 736 } 737 lock_basic_unlock(&ctx->cfglock); 738 if(!ctx->event_worker) { 739 ctx->event_worker = libworker_create_event(ctx, 740 ctx->event_base); 741 if(!ctx->event_worker) { 742 return UB_INITFAIL; 743 } 744 } 745 746 /* set time in case answer comes from cache */ 747 ub_comm_base_now(ctx->event_worker->base); 748 749 /* create new ctx_query and attempt to add to the list */ 750 q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata); 751 if(!q) 752 return UB_NOMEM; 753 754 /* attach to mesh */ 755 if((r=libworker_attach_mesh(ctx, q, async_id)) != 0) 756 return r; 757 return UB_NOERROR; 758 } 759 760 761 int 762 ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, 763 int rrclass, void* mydata, ub_callback_type callback, int* async_id) 764 { 765 struct ctx_query* q; 766 uint8_t* msg = NULL; 767 uint32_t len = 0; 768 769 if(async_id) 770 *async_id = 0; 771 lock_basic_lock(&ctx->cfglock); 772 if(!ctx->finalized) { 773 int r = context_finalize(ctx); 774 if(r) { 775 lock_basic_unlock(&ctx->cfglock); 776 return r; 777 } 778 } 779 if(!ctx->created_bg) { 780 int r; 781 ctx->created_bg = 1; 782 lock_basic_unlock(&ctx->cfglock); 783 r = libworker_bg(ctx); 784 if(r) { 785 lock_basic_lock(&ctx->cfglock); 786 ctx->created_bg = 0; 787 lock_basic_unlock(&ctx->cfglock); 788 return r; 789 } 790 } else { 791 lock_basic_unlock(&ctx->cfglock); 792 } 793 794 /* create new ctx_query and attempt to add to the list */ 795 q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata); 796 if(!q) 797 return UB_NOMEM; 798 799 /* write over pipe to background worker */ 800 lock_basic_lock(&ctx->cfglock); 801 msg = context_serialize_new_query(q, &len); 802 if(!msg) { 803 (void)rbtree_delete(&ctx->queries, q->node.key); 804 ctx->num_async--; 805 context_query_delete(q); 806 lock_basic_unlock(&ctx->cfglock); 807 return UB_NOMEM; 808 } 809 if(async_id) 810 *async_id = q->querynum; 811 lock_basic_unlock(&ctx->cfglock); 812 813 lock_basic_lock(&ctx->qqpipe_lock); 814 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 815 lock_basic_unlock(&ctx->qqpipe_lock); 816 free(msg); 817 return UB_PIPE; 818 } 819 lock_basic_unlock(&ctx->qqpipe_lock); 820 free(msg); 821 return UB_NOERROR; 822 } 823 824 int 825 ub_cancel(struct ub_ctx* ctx, int async_id) 826 { 827 struct ctx_query* q; 828 uint8_t* msg = NULL; 829 uint32_t len = 0; 830 lock_basic_lock(&ctx->cfglock); 831 q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id); 832 if(!q || !q->async) { 833 /* it is not there, so nothing to do */ 834 lock_basic_unlock(&ctx->cfglock); 835 return UB_NOID; 836 } 837 log_assert(q->async); 838 q->cancelled = 1; 839 840 /* delete it */ 841 if(!ctx->dothread) { /* if forked */ 842 (void)rbtree_delete(&ctx->queries, q->node.key); 843 ctx->num_async--; 844 msg = context_serialize_cancel(q, &len); 845 context_query_delete(q); 846 lock_basic_unlock(&ctx->cfglock); 847 if(!msg) { 848 return UB_NOMEM; 849 } 850 /* send cancel to background worker */ 851 lock_basic_lock(&ctx->qqpipe_lock); 852 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 853 lock_basic_unlock(&ctx->qqpipe_lock); 854 free(msg); 855 return UB_PIPE; 856 } 857 lock_basic_unlock(&ctx->qqpipe_lock); 858 free(msg); 859 } else { 860 lock_basic_unlock(&ctx->cfglock); 861 } 862 return UB_NOERROR; 863 } 864 865 void 866 ub_resolve_free(struct ub_result* result) 867 { 868 char** p; 869 if(!result) return; 870 free(result->qname); 871 if(result->canonname != result->qname) 872 free(result->canonname); 873 if(result->data) 874 for(p = result->data; *p; p++) 875 free(*p); 876 free(result->data); 877 free(result->len); 878 free(result->answer_packet); 879 free(result->why_bogus); 880 free(result); 881 } 882 883 const char* 884 ub_strerror(int err) 885 { 886 switch(err) { 887 case UB_NOERROR: return "no error"; 888 case UB_SOCKET: return "socket io error"; 889 case UB_NOMEM: return "out of memory"; 890 case UB_SYNTAX: return "syntax error"; 891 case UB_SERVFAIL: return "server failure"; 892 case UB_FORKFAIL: return "could not fork"; 893 case UB_INITFAIL: return "initialization failure"; 894 case UB_AFTERFINAL: return "setting change after finalize"; 895 case UB_PIPE: return "error in pipe communication with async"; 896 case UB_READFILE: return "error reading file"; 897 case UB_NOID: return "error async_id does not exist"; 898 default: return "unknown error"; 899 } 900 } 901 902 int 903 ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr) 904 { 905 struct sockaddr_storage storage; 906 socklen_t stlen; 907 struct config_stub* s; 908 char* dupl; 909 lock_basic_lock(&ctx->cfglock); 910 if(ctx->finalized) { 911 lock_basic_unlock(&ctx->cfglock); 912 errno=EINVAL; 913 return UB_AFTERFINAL; 914 } 915 if(!addr) { 916 /* disable fwd mode - the root stub should be first. */ 917 if(ctx->env->cfg->forwards && 918 strcmp(ctx->env->cfg->forwards->name, ".") == 0) { 919 s = ctx->env->cfg->forwards; 920 ctx->env->cfg->forwards = s->next; 921 s->next = NULL; 922 config_delstubs(s); 923 } 924 lock_basic_unlock(&ctx->cfglock); 925 return UB_NOERROR; 926 } 927 lock_basic_unlock(&ctx->cfglock); 928 929 /* check syntax for addr */ 930 if(!extstrtoaddr(addr, &storage, &stlen)) { 931 errno=EINVAL; 932 return UB_SYNTAX; 933 } 934 935 /* it parses, add root stub in front of list */ 936 lock_basic_lock(&ctx->cfglock); 937 if(!ctx->env->cfg->forwards || 938 strcmp(ctx->env->cfg->forwards->name, ".") != 0) { 939 s = calloc(1, sizeof(*s)); 940 if(!s) { 941 lock_basic_unlock(&ctx->cfglock); 942 errno=ENOMEM; 943 return UB_NOMEM; 944 } 945 s->name = strdup("."); 946 if(!s->name) { 947 free(s); 948 lock_basic_unlock(&ctx->cfglock); 949 errno=ENOMEM; 950 return UB_NOMEM; 951 } 952 s->next = ctx->env->cfg->forwards; 953 ctx->env->cfg->forwards = s; 954 } else { 955 log_assert(ctx->env->cfg->forwards); 956 s = ctx->env->cfg->forwards; 957 } 958 dupl = strdup(addr); 959 if(!dupl) { 960 lock_basic_unlock(&ctx->cfglock); 961 errno=ENOMEM; 962 return UB_NOMEM; 963 } 964 if(!cfg_strlist_insert(&s->addrs, dupl)) { 965 free(dupl); 966 lock_basic_unlock(&ctx->cfglock); 967 errno=ENOMEM; 968 return UB_NOMEM; 969 } 970 lock_basic_unlock(&ctx->cfglock); 971 return UB_NOERROR; 972 } 973 974 int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, 975 int isprime) 976 { 977 char* a; 978 struct config_stub **prev, *elem; 979 980 /* check syntax for zone name */ 981 if(zone) { 982 uint8_t* nm; 983 int nmlabs; 984 size_t nmlen; 985 if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) { 986 errno=EINVAL; 987 return UB_SYNTAX; 988 } 989 free(nm); 990 } else { 991 zone = "."; 992 } 993 994 /* check syntax for addr (if not NULL) */ 995 if(addr) { 996 struct sockaddr_storage storage; 997 socklen_t stlen; 998 if(!extstrtoaddr(addr, &storage, &stlen)) { 999 errno=EINVAL; 1000 return UB_SYNTAX; 1001 } 1002 } 1003 1004 lock_basic_lock(&ctx->cfglock); 1005 if(ctx->finalized) { 1006 lock_basic_unlock(&ctx->cfglock); 1007 errno=EINVAL; 1008 return UB_AFTERFINAL; 1009 } 1010 1011 /* arguments all right, now find or add the stub */ 1012 prev = &ctx->env->cfg->stubs; 1013 elem = cfg_stub_find(&prev, zone); 1014 if(!elem && !addr) { 1015 /* not found and we want to delete, nothing to do */ 1016 lock_basic_unlock(&ctx->cfglock); 1017 return UB_NOERROR; 1018 } else if(elem && !addr) { 1019 /* found, and we want to delete */ 1020 *prev = elem->next; 1021 config_delstub(elem); 1022 lock_basic_unlock(&ctx->cfglock); 1023 return UB_NOERROR; 1024 } else if(!elem) { 1025 /* not found, create the stub entry */ 1026 elem=(struct config_stub*)calloc(1, sizeof(struct config_stub)); 1027 if(elem) elem->name = strdup(zone); 1028 if(!elem || !elem->name) { 1029 free(elem); 1030 lock_basic_unlock(&ctx->cfglock); 1031 errno = ENOMEM; 1032 return UB_NOMEM; 1033 } 1034 elem->next = ctx->env->cfg->stubs; 1035 ctx->env->cfg->stubs = elem; 1036 } 1037 1038 /* add the address to the list and set settings */ 1039 elem->isprime = isprime; 1040 a = strdup(addr); 1041 if(!a) { 1042 lock_basic_unlock(&ctx->cfglock); 1043 errno = ENOMEM; 1044 return UB_NOMEM; 1045 } 1046 if(!cfg_strlist_insert(&elem->addrs, a)) { 1047 lock_basic_unlock(&ctx->cfglock); 1048 free(a); 1049 errno = ENOMEM; 1050 return UB_NOMEM; 1051 } 1052 lock_basic_unlock(&ctx->cfglock); 1053 return UB_NOERROR; 1054 } 1055 1056 int 1057 ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname) 1058 { 1059 FILE* in; 1060 int numserv = 0; 1061 char buf[1024]; 1062 char* parse, *addr; 1063 int r; 1064 1065 if(fname == NULL) { 1066 #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) 1067 fname = "/etc/resolv.conf"; 1068 #else 1069 FIXED_INFO *info; 1070 ULONG buflen = sizeof(*info); 1071 IP_ADDR_STRING *ptr; 1072 1073 info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO)); 1074 if (info == NULL) 1075 return UB_READFILE; 1076 1077 if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { 1078 free(info); 1079 info = (FIXED_INFO *) malloc(buflen); 1080 if (info == NULL) 1081 return UB_READFILE; 1082 } 1083 1084 if (GetNetworkParams(info, &buflen) == NO_ERROR) { 1085 int retval=0; 1086 ptr = &(info->DnsServerList); 1087 while (ptr) { 1088 numserv++; 1089 if((retval=ub_ctx_set_fwd(ctx, 1090 ptr->IpAddress.String))!=0) { 1091 free(info); 1092 return retval; 1093 } 1094 ptr = ptr->Next; 1095 } 1096 free(info); 1097 if (numserv==0) 1098 return UB_READFILE; 1099 return UB_NOERROR; 1100 } 1101 free(info); 1102 return UB_READFILE; 1103 #endif /* WINDOWS */ 1104 } 1105 in = fopen(fname, "r"); 1106 if(!in) { 1107 /* error in errno! perror(fname) */ 1108 return UB_READFILE; 1109 } 1110 while(fgets(buf, (int)sizeof(buf), in)) { 1111 buf[sizeof(buf)-1] = 0; 1112 parse=buf; 1113 while(*parse == ' ' || *parse == '\t') 1114 parse++; 1115 if(strncmp(parse, "nameserver", 10) == 0) { 1116 numserv++; 1117 parse += 10; /* skip 'nameserver' */ 1118 /* skip whitespace */ 1119 while(*parse == ' ' || *parse == '\t') 1120 parse++; 1121 addr = parse; 1122 /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ 1123 while(isxdigit((unsigned char)*parse) || *parse=='.' || *parse==':') 1124 parse++; 1125 /* terminate after the address, remove newline */ 1126 *parse = 0; 1127 1128 if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) { 1129 fclose(in); 1130 return r; 1131 } 1132 } 1133 } 1134 fclose(in); 1135 if(numserv == 0) { 1136 /* from resolv.conf(5) if none given, use localhost */ 1137 return ub_ctx_set_fwd(ctx, "127.0.0.1"); 1138 } 1139 return UB_NOERROR; 1140 } 1141 1142 int 1143 ub_ctx_hosts(struct ub_ctx* ctx, const char* fname) 1144 { 1145 FILE* in; 1146 char buf[1024], ldata[1024]; 1147 char* parse, *addr, *name, *ins; 1148 lock_basic_lock(&ctx->cfglock); 1149 if(ctx->finalized) { 1150 lock_basic_unlock(&ctx->cfglock); 1151 errno=EINVAL; 1152 return UB_AFTERFINAL; 1153 } 1154 lock_basic_unlock(&ctx->cfglock); 1155 if(fname == NULL) { 1156 #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) 1157 /* 1158 * If this is Windows NT/XP/2K it's in 1159 * %WINDIR%\system32\drivers\etc\hosts. 1160 * If this is Windows 95/98/Me it's in %WINDIR%\hosts. 1161 */ 1162 name = getenv("WINDIR"); 1163 if (name != NULL) { 1164 int retval=0; 1165 snprintf(buf, sizeof(buf), "%s%s", name, 1166 "\\system32\\drivers\\etc\\hosts"); 1167 if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { 1168 snprintf(buf, sizeof(buf), "%s%s", name, 1169 "\\hosts"); 1170 retval=ub_ctx_hosts(ctx, buf); 1171 } 1172 return retval; 1173 } 1174 return UB_READFILE; 1175 #else 1176 fname = "/etc/hosts"; 1177 #endif /* WIN32 */ 1178 } 1179 in = fopen(fname, "r"); 1180 if(!in) { 1181 /* error in errno! perror(fname) */ 1182 return UB_READFILE; 1183 } 1184 while(fgets(buf, (int)sizeof(buf), in)) { 1185 buf[sizeof(buf)-1] = 0; 1186 parse=buf; 1187 while(*parse == ' ' || *parse == '\t') 1188 parse++; 1189 if(*parse == '#') 1190 continue; /* skip comment */ 1191 /* format: <addr> spaces <name> spaces <name> ... */ 1192 addr = parse; 1193 /* skip addr */ 1194 while(isxdigit((unsigned char)*parse) || *parse == '.' || *parse == ':') 1195 parse++; 1196 if(*parse == '\r') 1197 parse++; 1198 if(*parse == '\n' || *parse == 0) 1199 continue; 1200 if(*parse == '%') 1201 continue; /* ignore macOSX fe80::1%lo0 localhost */ 1202 if(*parse != ' ' && *parse != '\t') { 1203 /* must have whitespace after address */ 1204 fclose(in); 1205 errno=EINVAL; 1206 return UB_SYNTAX; 1207 } 1208 *parse++ = 0; /* end delimiter for addr ... */ 1209 /* go to names and add them */ 1210 while(*parse) { 1211 while(*parse == ' ' || *parse == '\t' || *parse=='\n' 1212 || *parse=='\r') 1213 parse++; 1214 if(*parse == 0 || *parse == '#') 1215 break; 1216 /* skip name, allows (too) many printable characters */ 1217 name = parse; 1218 while('!' <= *parse && *parse <= '~') 1219 parse++; 1220 if(*parse) 1221 *parse++ = 0; /* end delimiter for name */ 1222 snprintf(ldata, sizeof(ldata), "%s %s %s", 1223 name, str_is_ip6(addr)?"AAAA":"A", addr); 1224 ins = strdup(ldata); 1225 if(!ins) { 1226 /* out of memory */ 1227 fclose(in); 1228 errno=ENOMEM; 1229 return UB_NOMEM; 1230 } 1231 lock_basic_lock(&ctx->cfglock); 1232 if(!cfg_strlist_insert(&ctx->env->cfg->local_data, 1233 ins)) { 1234 lock_basic_unlock(&ctx->cfglock); 1235 fclose(in); 1236 free(ins); 1237 errno=ENOMEM; 1238 return UB_NOMEM; 1239 } 1240 lock_basic_unlock(&ctx->cfglock); 1241 } 1242 } 1243 fclose(in); 1244 return UB_NOERROR; 1245 } 1246 1247 /** finalize the context, if not already finalized */ 1248 static int ub_ctx_finalize(struct ub_ctx* ctx) 1249 { 1250 int res = 0; 1251 lock_basic_lock(&ctx->cfglock); 1252 if (!ctx->finalized) { 1253 res = context_finalize(ctx); 1254 } 1255 lock_basic_unlock(&ctx->cfglock); 1256 return res; 1257 } 1258 1259 /* Print local zones and RR data */ 1260 int ub_ctx_print_local_zones(struct ub_ctx* ctx) 1261 { 1262 int res = ub_ctx_finalize(ctx); 1263 if (res) return res; 1264 1265 local_zones_print(ctx->local_zones); 1266 1267 return UB_NOERROR; 1268 } 1269 1270 /* Add a new zone */ 1271 int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name, 1272 const char *zone_type) 1273 { 1274 enum localzone_type t; 1275 struct local_zone* z; 1276 uint8_t* nm; 1277 int nmlabs; 1278 size_t nmlen; 1279 1280 int res = ub_ctx_finalize(ctx); 1281 if (res) return res; 1282 1283 if(!local_zone_str2type(zone_type, &t)) { 1284 return UB_SYNTAX; 1285 } 1286 1287 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1288 return UB_SYNTAX; 1289 } 1290 1291 lock_rw_wrlock(&ctx->local_zones->lock); 1292 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1293 LDNS_RR_CLASS_IN))) { 1294 /* already present in tree */ 1295 lock_rw_wrlock(&z->lock); 1296 z->type = t; /* update type anyway */ 1297 lock_rw_unlock(&z->lock); 1298 lock_rw_unlock(&ctx->local_zones->lock); 1299 free(nm); 1300 return UB_NOERROR; 1301 } 1302 if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, 1303 LDNS_RR_CLASS_IN, t)) { 1304 lock_rw_unlock(&ctx->local_zones->lock); 1305 return UB_NOMEM; 1306 } 1307 lock_rw_unlock(&ctx->local_zones->lock); 1308 return UB_NOERROR; 1309 } 1310 1311 /* Remove zone */ 1312 int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name) 1313 { 1314 struct local_zone* z; 1315 uint8_t* nm; 1316 int nmlabs; 1317 size_t nmlen; 1318 1319 int res = ub_ctx_finalize(ctx); 1320 if (res) return res; 1321 1322 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1323 return UB_SYNTAX; 1324 } 1325 1326 lock_rw_wrlock(&ctx->local_zones->lock); 1327 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1328 LDNS_RR_CLASS_IN))) { 1329 /* present in tree */ 1330 local_zones_del_zone(ctx->local_zones, z); 1331 } 1332 lock_rw_unlock(&ctx->local_zones->lock); 1333 free(nm); 1334 return UB_NOERROR; 1335 } 1336 1337 /* Add new RR data */ 1338 int ub_ctx_data_add(struct ub_ctx* ctx, const char *data) 1339 { 1340 int res = ub_ctx_finalize(ctx); 1341 if (res) return res; 1342 1343 res = local_zones_add_RR(ctx->local_zones, data); 1344 return (!res) ? UB_NOMEM : UB_NOERROR; 1345 } 1346 1347 /* Remove RR data */ 1348 int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data) 1349 { 1350 uint8_t* nm; 1351 int nmlabs; 1352 size_t nmlen; 1353 int res = ub_ctx_finalize(ctx); 1354 if (res) return res; 1355 1356 if(!parse_dname(data, &nm, &nmlen, &nmlabs)) 1357 return UB_SYNTAX; 1358 1359 local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, 1360 LDNS_RR_CLASS_IN); 1361 1362 free(nm); 1363 return UB_NOERROR; 1364 } 1365 1366 const char* ub_version(void) 1367 { 1368 return PACKAGE_VERSION; 1369 } 1370 1371 int 1372 ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) { 1373 struct ub_event_base* new_base; 1374 1375 if (!ctx || !ctx->event_base || !base) { 1376 return UB_INITFAIL; 1377 } 1378 if (ub_libevent_get_event_base(ctx->event_base) == base) { 1379 /* already set */ 1380 return UB_NOERROR; 1381 } 1382 1383 lock_basic_lock(&ctx->cfglock); 1384 /* destroy the current worker - safe to pass in NULL */ 1385 libworker_delete_event(ctx->event_worker); 1386 ctx->event_worker = NULL; 1387 new_base = ub_libevent_event_base(base); 1388 if (new_base) 1389 ctx->event_base = new_base; 1390 ctx->created_bg = 0; 1391 ctx->dothread = 1; 1392 lock_basic_unlock(&ctx->cfglock); 1393 return new_base ? UB_NOERROR : UB_INITFAIL; 1394 } 1395