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