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