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); 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, (ub_callback_type)callback, 751 mydata); 752 if(!q) 753 return UB_NOMEM; 754 755 /* attach to mesh */ 756 if((r=libworker_attach_mesh(ctx, q, async_id)) != 0) 757 return r; 758 return UB_NOERROR; 759 } 760 761 762 int 763 ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype, 764 int rrclass, void* mydata, ub_callback_type callback, int* async_id) 765 { 766 struct ctx_query* q; 767 uint8_t* msg = NULL; 768 uint32_t len = 0; 769 770 if(async_id) 771 *async_id = 0; 772 lock_basic_lock(&ctx->cfglock); 773 if(!ctx->finalized) { 774 int r = context_finalize(ctx); 775 if(r) { 776 lock_basic_unlock(&ctx->cfglock); 777 return r; 778 } 779 } 780 if(!ctx->created_bg) { 781 int r; 782 ctx->created_bg = 1; 783 lock_basic_unlock(&ctx->cfglock); 784 r = libworker_bg(ctx); 785 if(r) { 786 lock_basic_lock(&ctx->cfglock); 787 ctx->created_bg = 0; 788 lock_basic_unlock(&ctx->cfglock); 789 return r; 790 } 791 } else { 792 lock_basic_unlock(&ctx->cfglock); 793 } 794 795 /* create new ctx_query and attempt to add to the list */ 796 q = context_new(ctx, name, rrtype, rrclass, callback, mydata); 797 if(!q) 798 return UB_NOMEM; 799 800 /* write over pipe to background worker */ 801 lock_basic_lock(&ctx->cfglock); 802 msg = context_serialize_new_query(q, &len); 803 if(!msg) { 804 (void)rbtree_delete(&ctx->queries, q->node.key); 805 ctx->num_async--; 806 context_query_delete(q); 807 lock_basic_unlock(&ctx->cfglock); 808 return UB_NOMEM; 809 } 810 if(async_id) 811 *async_id = q->querynum; 812 lock_basic_unlock(&ctx->cfglock); 813 814 lock_basic_lock(&ctx->qqpipe_lock); 815 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 816 lock_basic_unlock(&ctx->qqpipe_lock); 817 free(msg); 818 return UB_PIPE; 819 } 820 lock_basic_unlock(&ctx->qqpipe_lock); 821 free(msg); 822 return UB_NOERROR; 823 } 824 825 int 826 ub_cancel(struct ub_ctx* ctx, int async_id) 827 { 828 struct ctx_query* q; 829 uint8_t* msg = NULL; 830 uint32_t len = 0; 831 lock_basic_lock(&ctx->cfglock); 832 q = (struct ctx_query*)rbtree_search(&ctx->queries, &async_id); 833 if(!q || !q->async) { 834 /* it is not there, so nothing to do */ 835 lock_basic_unlock(&ctx->cfglock); 836 return UB_NOID; 837 } 838 log_assert(q->async); 839 q->cancelled = 1; 840 841 /* delete it */ 842 if(!ctx->dothread) { /* if forked */ 843 (void)rbtree_delete(&ctx->queries, q->node.key); 844 ctx->num_async--; 845 msg = context_serialize_cancel(q, &len); 846 context_query_delete(q); 847 lock_basic_unlock(&ctx->cfglock); 848 if(!msg) { 849 return UB_NOMEM; 850 } 851 /* send cancel to background worker */ 852 lock_basic_lock(&ctx->qqpipe_lock); 853 if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) { 854 lock_basic_unlock(&ctx->qqpipe_lock); 855 free(msg); 856 return UB_PIPE; 857 } 858 lock_basic_unlock(&ctx->qqpipe_lock); 859 free(msg); 860 } else { 861 lock_basic_unlock(&ctx->cfglock); 862 } 863 return UB_NOERROR; 864 } 865 866 void 867 ub_resolve_free(struct ub_result* result) 868 { 869 char** p; 870 if(!result) return; 871 free(result->qname); 872 if(result->canonname != result->qname) 873 free(result->canonname); 874 if(result->data) 875 for(p = result->data; *p; p++) 876 free(*p); 877 free(result->data); 878 free(result->len); 879 free(result->answer_packet); 880 free(result->why_bogus); 881 free(result); 882 } 883 884 const char* 885 ub_strerror(int err) 886 { 887 switch(err) { 888 case UB_NOERROR: return "no error"; 889 case UB_SOCKET: return "socket io error"; 890 case UB_NOMEM: return "out of memory"; 891 case UB_SYNTAX: return "syntax error"; 892 case UB_SERVFAIL: return "server failure"; 893 case UB_FORKFAIL: return "could not fork"; 894 case UB_INITFAIL: return "initialization failure"; 895 case UB_AFTERFINAL: return "setting change after finalize"; 896 case UB_PIPE: return "error in pipe communication with async"; 897 case UB_READFILE: return "error reading file"; 898 case UB_NOID: return "error async_id does not exist"; 899 default: return "unknown error"; 900 } 901 } 902 903 int 904 ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr) 905 { 906 struct sockaddr_storage storage; 907 socklen_t stlen; 908 struct config_stub* s; 909 char* dupl; 910 lock_basic_lock(&ctx->cfglock); 911 if(ctx->finalized) { 912 lock_basic_unlock(&ctx->cfglock); 913 errno=EINVAL; 914 return UB_AFTERFINAL; 915 } 916 if(!addr) { 917 /* disable fwd mode - the root stub should be first. */ 918 if(ctx->env->cfg->forwards && 919 strcmp(ctx->env->cfg->forwards->name, ".") == 0) { 920 s = ctx->env->cfg->forwards; 921 ctx->env->cfg->forwards = s->next; 922 s->next = NULL; 923 config_delstubs(s); 924 } 925 lock_basic_unlock(&ctx->cfglock); 926 return UB_NOERROR; 927 } 928 lock_basic_unlock(&ctx->cfglock); 929 930 /* check syntax for addr */ 931 if(!extstrtoaddr(addr, &storage, &stlen)) { 932 errno=EINVAL; 933 return UB_SYNTAX; 934 } 935 936 /* it parses, add root stub in front of list */ 937 lock_basic_lock(&ctx->cfglock); 938 if(!ctx->env->cfg->forwards || 939 strcmp(ctx->env->cfg->forwards->name, ".") != 0) { 940 s = calloc(1, sizeof(*s)); 941 if(!s) { 942 lock_basic_unlock(&ctx->cfglock); 943 errno=ENOMEM; 944 return UB_NOMEM; 945 } 946 s->name = strdup("."); 947 if(!s->name) { 948 free(s); 949 lock_basic_unlock(&ctx->cfglock); 950 errno=ENOMEM; 951 return UB_NOMEM; 952 } 953 s->next = ctx->env->cfg->forwards; 954 ctx->env->cfg->forwards = s; 955 } else { 956 log_assert(ctx->env->cfg->forwards); 957 s = ctx->env->cfg->forwards; 958 } 959 dupl = strdup(addr); 960 if(!dupl) { 961 lock_basic_unlock(&ctx->cfglock); 962 errno=ENOMEM; 963 return UB_NOMEM; 964 } 965 if(!cfg_strlist_insert(&s->addrs, dupl)) { 966 free(dupl); 967 lock_basic_unlock(&ctx->cfglock); 968 errno=ENOMEM; 969 return UB_NOMEM; 970 } 971 lock_basic_unlock(&ctx->cfglock); 972 return UB_NOERROR; 973 } 974 975 int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr, 976 int isprime) 977 { 978 char* a; 979 struct config_stub **prev, *elem; 980 981 /* check syntax for zone name */ 982 if(zone) { 983 uint8_t* nm; 984 int nmlabs; 985 size_t nmlen; 986 if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) { 987 errno=EINVAL; 988 return UB_SYNTAX; 989 } 990 free(nm); 991 } else { 992 zone = "."; 993 } 994 995 /* check syntax for addr (if not NULL) */ 996 if(addr) { 997 struct sockaddr_storage storage; 998 socklen_t stlen; 999 if(!extstrtoaddr(addr, &storage, &stlen)) { 1000 errno=EINVAL; 1001 return UB_SYNTAX; 1002 } 1003 } 1004 1005 lock_basic_lock(&ctx->cfglock); 1006 if(ctx->finalized) { 1007 lock_basic_unlock(&ctx->cfglock); 1008 errno=EINVAL; 1009 return UB_AFTERFINAL; 1010 } 1011 1012 /* arguments all right, now find or add the stub */ 1013 prev = &ctx->env->cfg->stubs; 1014 elem = cfg_stub_find(&prev, zone); 1015 if(!elem && !addr) { 1016 /* not found and we want to delete, nothing to do */ 1017 lock_basic_unlock(&ctx->cfglock); 1018 return UB_NOERROR; 1019 } else if(elem && !addr) { 1020 /* found, and we want to delete */ 1021 *prev = elem->next; 1022 config_delstub(elem); 1023 lock_basic_unlock(&ctx->cfglock); 1024 return UB_NOERROR; 1025 } else if(!elem) { 1026 /* not found, create the stub entry */ 1027 elem=(struct config_stub*)calloc(1, sizeof(struct config_stub)); 1028 if(elem) elem->name = strdup(zone); 1029 if(!elem || !elem->name) { 1030 free(elem); 1031 lock_basic_unlock(&ctx->cfglock); 1032 errno = ENOMEM; 1033 return UB_NOMEM; 1034 } 1035 elem->next = ctx->env->cfg->stubs; 1036 ctx->env->cfg->stubs = elem; 1037 } 1038 1039 /* add the address to the list and set settings */ 1040 elem->isprime = isprime; 1041 a = strdup(addr); 1042 if(!a) { 1043 lock_basic_unlock(&ctx->cfglock); 1044 errno = ENOMEM; 1045 return UB_NOMEM; 1046 } 1047 if(!cfg_strlist_insert(&elem->addrs, a)) { 1048 lock_basic_unlock(&ctx->cfglock); 1049 free(a); 1050 errno = ENOMEM; 1051 return UB_NOMEM; 1052 } 1053 lock_basic_unlock(&ctx->cfglock); 1054 return UB_NOERROR; 1055 } 1056 1057 int 1058 ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname) 1059 { 1060 FILE* in; 1061 int numserv = 0; 1062 char buf[1024]; 1063 char* parse, *addr; 1064 int r; 1065 1066 if(fname == NULL) { 1067 #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) 1068 fname = "/etc/resolv.conf"; 1069 #else 1070 FIXED_INFO *info; 1071 ULONG buflen = sizeof(*info); 1072 IP_ADDR_STRING *ptr; 1073 1074 info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO)); 1075 if (info == NULL) 1076 return UB_READFILE; 1077 1078 if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { 1079 free(info); 1080 info = (FIXED_INFO *) malloc(buflen); 1081 if (info == NULL) 1082 return UB_READFILE; 1083 } 1084 1085 if (GetNetworkParams(info, &buflen) == NO_ERROR) { 1086 int retval=0; 1087 ptr = &(info->DnsServerList); 1088 while (ptr) { 1089 numserv++; 1090 if((retval=ub_ctx_set_fwd(ctx, 1091 ptr->IpAddress.String))!=0) { 1092 free(info); 1093 return retval; 1094 } 1095 ptr = ptr->Next; 1096 } 1097 free(info); 1098 if (numserv==0) 1099 return UB_READFILE; 1100 return UB_NOERROR; 1101 } 1102 free(info); 1103 return UB_READFILE; 1104 #endif /* WINDOWS */ 1105 } 1106 in = fopen(fname, "r"); 1107 if(!in) { 1108 /* error in errno! perror(fname) */ 1109 return UB_READFILE; 1110 } 1111 while(fgets(buf, (int)sizeof(buf), in)) { 1112 buf[sizeof(buf)-1] = 0; 1113 parse=buf; 1114 while(*parse == ' ' || *parse == '\t') 1115 parse++; 1116 if(strncmp(parse, "nameserver", 10) == 0) { 1117 numserv++; 1118 parse += 10; /* skip 'nameserver' */ 1119 /* skip whitespace */ 1120 while(*parse == ' ' || *parse == '\t') 1121 parse++; 1122 addr = parse; 1123 /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ 1124 while(isxdigit((unsigned char)*parse) || *parse=='.' || *parse==':') 1125 parse++; 1126 /* terminate after the address, remove newline */ 1127 *parse = 0; 1128 1129 if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) { 1130 fclose(in); 1131 return r; 1132 } 1133 } 1134 } 1135 fclose(in); 1136 if(numserv == 0) { 1137 /* from resolv.conf(5) if none given, use localhost */ 1138 return ub_ctx_set_fwd(ctx, "127.0.0.1"); 1139 } 1140 return UB_NOERROR; 1141 } 1142 1143 int 1144 ub_ctx_hosts(struct ub_ctx* ctx, const char* fname) 1145 { 1146 FILE* in; 1147 char buf[1024], ldata[1024]; 1148 char* parse, *addr, *name, *ins; 1149 lock_basic_lock(&ctx->cfglock); 1150 if(ctx->finalized) { 1151 lock_basic_unlock(&ctx->cfglock); 1152 errno=EINVAL; 1153 return UB_AFTERFINAL; 1154 } 1155 lock_basic_unlock(&ctx->cfglock); 1156 if(fname == NULL) { 1157 #if defined(UB_ON_WINDOWS) && defined(HAVE_WINDOWS_H) 1158 /* 1159 * If this is Windows NT/XP/2K it's in 1160 * %WINDIR%\system32\drivers\etc\hosts. 1161 * If this is Windows 95/98/Me it's in %WINDIR%\hosts. 1162 */ 1163 name = getenv("WINDIR"); 1164 if (name != NULL) { 1165 int retval=0; 1166 snprintf(buf, sizeof(buf), "%s%s", name, 1167 "\\system32\\drivers\\etc\\hosts"); 1168 if((retval=ub_ctx_hosts(ctx, buf)) !=0 ) { 1169 snprintf(buf, sizeof(buf), "%s%s", name, 1170 "\\hosts"); 1171 retval=ub_ctx_hosts(ctx, buf); 1172 } 1173 return retval; 1174 } 1175 return UB_READFILE; 1176 #else 1177 fname = "/etc/hosts"; 1178 #endif /* WIN32 */ 1179 } 1180 in = fopen(fname, "r"); 1181 if(!in) { 1182 /* error in errno! perror(fname) */ 1183 return UB_READFILE; 1184 } 1185 while(fgets(buf, (int)sizeof(buf), in)) { 1186 buf[sizeof(buf)-1] = 0; 1187 parse=buf; 1188 while(*parse == ' ' || *parse == '\t') 1189 parse++; 1190 if(*parse == '#') 1191 continue; /* skip comment */ 1192 /* format: <addr> spaces <name> spaces <name> ... */ 1193 addr = parse; 1194 /* skip addr */ 1195 while(isxdigit((unsigned char)*parse) || *parse == '.' || *parse == ':') 1196 parse++; 1197 if(*parse == '\r') 1198 parse++; 1199 if(*parse == '\n' || *parse == 0) 1200 continue; 1201 if(*parse == '%') 1202 continue; /* ignore macOSX fe80::1%lo0 localhost */ 1203 if(*parse != ' ' && *parse != '\t') { 1204 /* must have whitespace after address */ 1205 fclose(in); 1206 errno=EINVAL; 1207 return UB_SYNTAX; 1208 } 1209 *parse++ = 0; /* end delimiter for addr ... */ 1210 /* go to names and add them */ 1211 while(*parse) { 1212 while(*parse == ' ' || *parse == '\t' || *parse=='\n' 1213 || *parse=='\r') 1214 parse++; 1215 if(*parse == 0 || *parse == '#') 1216 break; 1217 /* skip name, allows (too) many printable characters */ 1218 name = parse; 1219 while('!' <= *parse && *parse <= '~') 1220 parse++; 1221 if(*parse) 1222 *parse++ = 0; /* end delimiter for name */ 1223 snprintf(ldata, sizeof(ldata), "%s %s %s", 1224 name, str_is_ip6(addr)?"AAAA":"A", addr); 1225 ins = strdup(ldata); 1226 if(!ins) { 1227 /* out of memory */ 1228 fclose(in); 1229 errno=ENOMEM; 1230 return UB_NOMEM; 1231 } 1232 lock_basic_lock(&ctx->cfglock); 1233 if(!cfg_strlist_insert(&ctx->env->cfg->local_data, 1234 ins)) { 1235 lock_basic_unlock(&ctx->cfglock); 1236 fclose(in); 1237 free(ins); 1238 errno=ENOMEM; 1239 return UB_NOMEM; 1240 } 1241 lock_basic_unlock(&ctx->cfglock); 1242 } 1243 } 1244 fclose(in); 1245 return UB_NOERROR; 1246 } 1247 1248 /** finalize the context, if not already finalized */ 1249 static int ub_ctx_finalize(struct ub_ctx* ctx) 1250 { 1251 int res = 0; 1252 lock_basic_lock(&ctx->cfglock); 1253 if (!ctx->finalized) { 1254 res = context_finalize(ctx); 1255 } 1256 lock_basic_unlock(&ctx->cfglock); 1257 return res; 1258 } 1259 1260 /* Print local zones and RR data */ 1261 int ub_ctx_print_local_zones(struct ub_ctx* ctx) 1262 { 1263 int res = ub_ctx_finalize(ctx); 1264 if (res) return res; 1265 1266 local_zones_print(ctx->local_zones); 1267 1268 return UB_NOERROR; 1269 } 1270 1271 /* Add a new zone */ 1272 int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name, 1273 const char *zone_type) 1274 { 1275 enum localzone_type t; 1276 struct local_zone* z; 1277 uint8_t* nm; 1278 int nmlabs; 1279 size_t nmlen; 1280 1281 int res = ub_ctx_finalize(ctx); 1282 if (res) return res; 1283 1284 if(!local_zone_str2type(zone_type, &t)) { 1285 return UB_SYNTAX; 1286 } 1287 1288 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1289 return UB_SYNTAX; 1290 } 1291 1292 lock_rw_wrlock(&ctx->local_zones->lock); 1293 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1294 LDNS_RR_CLASS_IN))) { 1295 /* already present in tree */ 1296 lock_rw_wrlock(&z->lock); 1297 z->type = t; /* update type anyway */ 1298 lock_rw_unlock(&z->lock); 1299 lock_rw_unlock(&ctx->local_zones->lock); 1300 free(nm); 1301 return UB_NOERROR; 1302 } 1303 if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, 1304 LDNS_RR_CLASS_IN, t)) { 1305 lock_rw_unlock(&ctx->local_zones->lock); 1306 return UB_NOMEM; 1307 } 1308 lock_rw_unlock(&ctx->local_zones->lock); 1309 return UB_NOERROR; 1310 } 1311 1312 /* Remove zone */ 1313 int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name) 1314 { 1315 struct local_zone* z; 1316 uint8_t* nm; 1317 int nmlabs; 1318 size_t nmlen; 1319 1320 int res = ub_ctx_finalize(ctx); 1321 if (res) return res; 1322 1323 if(!parse_dname(zone_name, &nm, &nmlen, &nmlabs)) { 1324 return UB_SYNTAX; 1325 } 1326 1327 lock_rw_wrlock(&ctx->local_zones->lock); 1328 if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 1329 LDNS_RR_CLASS_IN))) { 1330 /* present in tree */ 1331 local_zones_del_zone(ctx->local_zones, z); 1332 } 1333 lock_rw_unlock(&ctx->local_zones->lock); 1334 free(nm); 1335 return UB_NOERROR; 1336 } 1337 1338 /* Add new RR data */ 1339 int ub_ctx_data_add(struct ub_ctx* ctx, const char *data) 1340 { 1341 int res = ub_ctx_finalize(ctx); 1342 if (res) return res; 1343 1344 res = local_zones_add_RR(ctx->local_zones, data); 1345 return (!res) ? UB_NOMEM : UB_NOERROR; 1346 } 1347 1348 /* Remove RR data */ 1349 int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data) 1350 { 1351 uint8_t* nm; 1352 int nmlabs; 1353 size_t nmlen; 1354 int res = ub_ctx_finalize(ctx); 1355 if (res) return res; 1356 1357 if(!parse_dname(data, &nm, &nmlen, &nmlabs)) 1358 return UB_SYNTAX; 1359 1360 local_zones_del_data(ctx->local_zones, nm, nmlen, nmlabs, 1361 LDNS_RR_CLASS_IN); 1362 1363 free(nm); 1364 return UB_NOERROR; 1365 } 1366 1367 const char* ub_version(void) 1368 { 1369 return PACKAGE_VERSION; 1370 } 1371 1372 int 1373 ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) { 1374 struct ub_event_base* new_base; 1375 1376 if (!ctx || !ctx->event_base || !base) { 1377 return UB_INITFAIL; 1378 } 1379 if (ub_libevent_get_event_base(ctx->event_base) == base) { 1380 /* already set */ 1381 return UB_NOERROR; 1382 } 1383 1384 lock_basic_lock(&ctx->cfglock); 1385 /* destroy the current worker - safe to pass in NULL */ 1386 libworker_delete_event(ctx->event_worker); 1387 ctx->event_worker = NULL; 1388 new_base = ub_libevent_event_base(base); 1389 if (new_base) 1390 ctx->event_base = new_base; 1391 ctx->created_bg = 0; 1392 ctx->dothread = 1; 1393 lock_basic_unlock(&ctx->cfglock); 1394 return new_base ? UB_NOERROR : UB_INITFAIL; 1395 } 1396