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