1 /* 2 * libunbound/worker.c - worker thread or process that resolves 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 LIMITED 25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 * POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /** 37 * \file 38 * 39 * This file contains the worker process or thread that performs 40 * the DNS resolving and validation. The worker is called by a procedure 41 * and if in the background continues until exit, if in the foreground 42 * returns from the procedure when done. 43 */ 44 #include "config.h" 45 #include <ldns/dname.h> 46 #include <ldns/wire2host.h> 47 #include <openssl/ssl.h> 48 #include "libunbound/libworker.h" 49 #include "libunbound/context.h" 50 #include "libunbound/unbound.h" 51 #include "services/outside_network.h" 52 #include "services/mesh.h" 53 #include "services/localzone.h" 54 #include "services/cache/rrset.h" 55 #include "services/outbound_list.h" 56 #include "util/module.h" 57 #include "util/regional.h" 58 #include "util/random.h" 59 #include "util/config_file.h" 60 #include "util/netevent.h" 61 #include "util/storage/lookup3.h" 62 #include "util/storage/slabhash.h" 63 #include "util/net_help.h" 64 #include "util/data/dname.h" 65 #include "util/data/msgreply.h" 66 #include "util/data/msgencode.h" 67 #include "util/tube.h" 68 #include "iterator/iter_fwd.h" 69 70 /** handle new query command for bg worker */ 71 static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len); 72 73 /** delete libworker struct */ 74 static void 75 libworker_delete(struct libworker* w) 76 { 77 if(!w) return; 78 if(w->env) { 79 outside_network_quit_prepare(w->back); 80 mesh_delete(w->env->mesh); 81 context_release_alloc(w->ctx, w->env->alloc, 82 !w->is_bg || w->is_bg_thread); 83 ldns_buffer_free(w->env->scratch_buffer); 84 regional_destroy(w->env->scratch); 85 forwards_delete(w->env->fwds); 86 ub_randfree(w->env->rnd); 87 free(w->env); 88 } 89 SSL_CTX_free(w->sslctx); 90 outside_network_delete(w->back); 91 comm_base_delete(w->base); 92 free(w); 93 } 94 95 /** setup fresh libworker struct */ 96 static struct libworker* 97 libworker_setup(struct ub_ctx* ctx, int is_bg) 98 { 99 unsigned int seed; 100 struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); 101 struct config_file* cfg = ctx->env->cfg; 102 int* ports; 103 int numports; 104 if(!w) return NULL; 105 w->is_bg = is_bg; 106 w->ctx = ctx; 107 w->env = (struct module_env*)malloc(sizeof(*w->env)); 108 if(!w->env) { 109 free(w); 110 return NULL; 111 } 112 *w->env = *ctx->env; 113 w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread); 114 if(!w->env->alloc) { 115 libworker_delete(w); 116 return NULL; 117 } 118 w->thread_num = w->env->alloc->thread_num; 119 alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w); 120 if(!w->is_bg || w->is_bg_thread) { 121 lock_basic_lock(&ctx->cfglock); 122 } 123 w->env->scratch = regional_create_custom(cfg->msg_buffer_size); 124 w->env->scratch_buffer = ldns_buffer_new(cfg->msg_buffer_size); 125 w->env->fwds = forwards_create(); 126 if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { 127 forwards_delete(w->env->fwds); 128 w->env->fwds = NULL; 129 } 130 if(cfg->ssl_upstream) { 131 w->sslctx = connect_sslctx_create(NULL, NULL, NULL); 132 if(!w->sslctx) { 133 libworker_delete(w); 134 return NULL; 135 } 136 } 137 if(!w->is_bg || w->is_bg_thread) { 138 lock_basic_unlock(&ctx->cfglock); 139 } 140 if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds) { 141 libworker_delete(w); 142 return NULL; 143 } 144 w->env->worker = (struct worker*)w; 145 w->env->probe_timer = NULL; 146 seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^ 147 (((unsigned int)w->thread_num)<<17); 148 seed ^= (unsigned int)w->env->alloc->next_id; 149 if(!w->is_bg || w->is_bg_thread) { 150 lock_basic_lock(&ctx->cfglock); 151 } 152 if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) { 153 if(!w->is_bg || w->is_bg_thread) { 154 lock_basic_unlock(&ctx->cfglock); 155 } 156 seed = 0; 157 libworker_delete(w); 158 return NULL; 159 } 160 if(!w->is_bg || w->is_bg_thread) { 161 lock_basic_unlock(&ctx->cfglock); 162 } 163 if(1) { 164 /* primitive lockout for threading: if it overwrites another 165 * thread it is like wiping the cache (which is likely empty 166 * at the start) */ 167 /* note we are holding the ctx lock in normal threaded 168 * cases so that is solved properly, it is only for many ctx 169 * in different threads that this may clash */ 170 static int done_raninit = 0; 171 if(!done_raninit) { 172 done_raninit = 1; 173 hash_set_raninit((uint32_t)ub_random(w->env->rnd)); 174 } 175 } 176 seed = 0; 177 178 w->base = comm_base_create(0); 179 if(!w->base) { 180 libworker_delete(w); 181 return NULL; 182 } 183 if(!w->is_bg || w->is_bg_thread) { 184 lock_basic_lock(&ctx->cfglock); 185 } 186 numports = cfg_condense_ports(cfg, &ports); 187 if(numports == 0) { 188 libworker_delete(w); 189 return NULL; 190 } 191 w->back = outside_network_create(w->base, cfg->msg_buffer_size, 192 (size_t)cfg->outgoing_num_ports, cfg->out_ifs, 193 cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, 194 cfg->do_tcp?cfg->outgoing_num_tcp:0, 195 w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id, 196 ports, numports, cfg->unwanted_threshold, 197 &libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx); 198 if(!w->is_bg || w->is_bg_thread) { 199 lock_basic_unlock(&ctx->cfglock); 200 } 201 free(ports); 202 if(!w->back) { 203 libworker_delete(w); 204 return NULL; 205 } 206 w->env->mesh = mesh_create(&ctx->mods, w->env); 207 if(!w->env->mesh) { 208 libworker_delete(w); 209 return NULL; 210 } 211 w->env->send_query = &libworker_send_query; 212 w->env->detach_subs = &mesh_detach_subs; 213 w->env->attach_sub = &mesh_attach_sub; 214 w->env->kill_sub = &mesh_state_delete; 215 w->env->detect_cycle = &mesh_detect_cycle; 216 comm_base_timept(w->base, &w->env->now, &w->env->now_tv); 217 return w; 218 } 219 220 /** handle cancel command for bg worker */ 221 static void 222 handle_cancel(struct libworker* w, uint8_t* buf, uint32_t len) 223 { 224 struct ctx_query* q; 225 if(w->is_bg_thread) { 226 lock_basic_lock(&w->ctx->cfglock); 227 q = context_deserialize_cancel(w->ctx, buf, len); 228 lock_basic_unlock(&w->ctx->cfglock); 229 } else { 230 q = context_deserialize_cancel(w->ctx, buf, len); 231 } 232 if(!q) { 233 /* probably simply lookup failed, i.e. the message had been 234 * processed and answered before the cancel arrived */ 235 return; 236 } 237 q->cancelled = 1; 238 free(buf); 239 } 240 241 /** do control command coming into bg server */ 242 static void 243 libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len) 244 { 245 switch(context_serial_getcmd(msg, len)) { 246 default: 247 case UB_LIBCMD_ANSWER: 248 log_err("unknown command for bg worker %d", 249 (int)context_serial_getcmd(msg, len)); 250 /* and fall through to quit */ 251 case UB_LIBCMD_QUIT: 252 free(msg); 253 comm_base_exit(w->base); 254 break; 255 case UB_LIBCMD_NEWQUERY: 256 handle_newq(w, msg, len); 257 break; 258 case UB_LIBCMD_CANCEL: 259 handle_cancel(w, msg, len); 260 break; 261 } 262 } 263 264 /** handle control command coming into server */ 265 void 266 libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 267 uint8_t* msg, size_t len, int err, void* arg) 268 { 269 struct libworker* w = (struct libworker*)arg; 270 271 if(err != 0) { 272 free(msg); 273 /* it is of no use to go on, exit */ 274 comm_base_exit(w->base); 275 return; 276 } 277 libworker_do_cmd(w, msg, len); /* also frees the buf */ 278 } 279 280 /** the background thread func */ 281 static void* 282 libworker_dobg(void* arg) 283 { 284 /* setup */ 285 uint32_t m; 286 struct libworker* w = (struct libworker*)arg; 287 struct ub_ctx* ctx; 288 if(!w) { 289 log_err("libunbound bg worker init failed, nomem"); 290 return NULL; 291 } 292 ctx = w->ctx; 293 log_thread_set(&w->thread_num); 294 #ifdef THREADS_DISABLED 295 /* we are forked */ 296 w->is_bg_thread = 0; 297 /* close non-used parts of the pipes */ 298 tube_close_write(ctx->qq_pipe); 299 tube_close_read(ctx->rr_pipe); 300 #endif 301 if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, 302 libworker_handle_control_cmd, w)) { 303 log_err("libunbound bg worker init failed, no bglisten"); 304 return NULL; 305 } 306 if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) { 307 log_err("libunbound bg worker init failed, no bgwrite"); 308 return NULL; 309 } 310 311 /* do the work */ 312 comm_base_dispatch(w->base); 313 314 /* cleanup */ 315 m = UB_LIBCMD_QUIT; 316 tube_remove_bg_listen(w->ctx->qq_pipe); 317 tube_remove_bg_write(w->ctx->rr_pipe); 318 libworker_delete(w); 319 (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, 320 (uint32_t)sizeof(m), 0); 321 #ifdef THREADS_DISABLED 322 /* close pipes from forked process before exit */ 323 tube_close_read(ctx->qq_pipe); 324 tube_close_write(ctx->rr_pipe); 325 #endif 326 return NULL; 327 } 328 329 int libworker_bg(struct ub_ctx* ctx) 330 { 331 struct libworker* w; 332 /* fork or threadcreate */ 333 lock_basic_lock(&ctx->cfglock); 334 if(ctx->dothread) { 335 lock_basic_unlock(&ctx->cfglock); 336 w = libworker_setup(ctx, 1); 337 if(!w) return UB_NOMEM; 338 w->is_bg_thread = 1; 339 #ifdef ENABLE_LOCK_CHECKS 340 w->thread_num = 1; /* for nicer DEBUG checklocks */ 341 #endif 342 ub_thread_create(&ctx->bg_tid, libworker_dobg, w); 343 } else { 344 lock_basic_unlock(&ctx->cfglock); 345 #ifndef HAVE_FORK 346 /* no fork on windows */ 347 return UB_FORKFAIL; 348 #else /* HAVE_FORK */ 349 switch((ctx->bg_pid=fork())) { 350 case 0: 351 w = libworker_setup(ctx, 1); 352 if(!w) fatal_exit("out of memory"); 353 /* close non-used parts of the pipes */ 354 tube_close_write(ctx->qq_pipe); 355 tube_close_read(ctx->rr_pipe); 356 (void)libworker_dobg(w); 357 exit(0); 358 break; 359 case -1: 360 return UB_FORKFAIL; 361 default: 362 break; 363 } 364 #endif /* HAVE_FORK */ 365 } 366 return UB_NOERROR; 367 } 368 369 /** get msg reply struct (in temp region) */ 370 static struct reply_info* 371 parse_reply(ldns_buffer* pkt, struct regional* region, struct query_info* qi) 372 { 373 struct reply_info* rep; 374 struct msg_parse* msg; 375 if(!(msg = regional_alloc(region, sizeof(*msg)))) { 376 return NULL; 377 } 378 memset(msg, 0, sizeof(*msg)); 379 ldns_buffer_set_position(pkt, 0); 380 if(parse_packet(pkt, msg, region) != 0) 381 return 0; 382 if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) { 383 return 0; 384 } 385 return rep; 386 } 387 388 /** insert canonname */ 389 static int 390 fill_canon(struct ub_result* res, uint8_t* s) 391 { 392 char buf[255+2]; 393 dname_str(s, buf); 394 res->canonname = strdup(buf); 395 return res->canonname != 0; 396 } 397 398 /** fill data into result */ 399 static int 400 fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer, 401 uint8_t* finalcname, struct query_info* rq) 402 { 403 size_t i; 404 struct packed_rrset_data* data; 405 if(!answer) { 406 if(finalcname) { 407 if(!fill_canon(res, finalcname)) 408 return 0; /* out of memory */ 409 } 410 res->data = (char**)calloc(1, sizeof(char*)); 411 res->len = (int*)calloc(1, sizeof(int)); 412 return (res->data && res->len); 413 } 414 data = (struct packed_rrset_data*)answer->entry.data; 415 if(query_dname_compare(rq->qname, answer->rk.dname) != 0) { 416 if(!fill_canon(res, answer->rk.dname)) 417 return 0; /* out of memory */ 418 } else res->canonname = NULL; 419 res->data = (char**)calloc(data->count+1, sizeof(char*)); 420 res->len = (int*)calloc(data->count+1, sizeof(int)); 421 if(!res->data || !res->len) 422 return 0; /* out of memory */ 423 for(i=0; i<data->count; i++) { 424 /* remove rdlength from rdata */ 425 res->len[i] = (int)(data->rr_len[i] - 2); 426 res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]); 427 if(!res->data[i]) 428 return 0; /* out of memory */ 429 } 430 res->data[data->count] = NULL; 431 res->len[data->count] = 0; 432 return 1; 433 } 434 435 /** fill result from parsed message, on error fills servfail */ 436 void 437 libworker_enter_result(struct ub_result* res, ldns_buffer* buf, 438 struct regional* temp, enum sec_status msg_security) 439 { 440 struct query_info rq; 441 struct reply_info* rep; 442 res->rcode = LDNS_RCODE_SERVFAIL; 443 rep = parse_reply(buf, temp, &rq); 444 if(!rep) { 445 log_err("cannot parse buf"); 446 return; /* error parsing buf, or out of memory */ 447 } 448 if(!fill_res(res, reply_find_answer_rrset(&rq, rep), 449 reply_find_final_cname_target(&rq, rep), &rq)) 450 return; /* out of memory */ 451 /* rcode, havedata, nxdomain, secure, bogus */ 452 res->rcode = (int)FLAGS_GET_RCODE(rep->flags); 453 if(res->data && res->data[0]) 454 res->havedata = 1; 455 if(res->rcode == LDNS_RCODE_NXDOMAIN) 456 res->nxdomain = 1; 457 if(msg_security == sec_status_secure) 458 res->secure = 1; 459 if(msg_security == sec_status_bogus) 460 res->bogus = 1; 461 } 462 463 /** fillup fg results */ 464 static void 465 libworker_fillup_fg(struct ctx_query* q, int rcode, ldns_buffer* buf, 466 enum sec_status s, char* why_bogus) 467 { 468 if(why_bogus) 469 q->res->why_bogus = strdup(why_bogus); 470 if(rcode != 0) { 471 q->res->rcode = rcode; 472 q->msg_security = s; 473 return; 474 } 475 476 q->res->rcode = LDNS_RCODE_SERVFAIL; 477 q->msg_security = 0; 478 q->msg = memdup(ldns_buffer_begin(buf), ldns_buffer_limit(buf)); 479 q->msg_len = ldns_buffer_limit(buf); 480 if(!q->msg) { 481 return; /* the error is in the rcode */ 482 } 483 484 /* canonname and results */ 485 q->msg_security = s; 486 libworker_enter_result(q->res, buf, q->w->env->scratch, s); 487 } 488 489 void 490 libworker_fg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s, 491 char* why_bogus) 492 { 493 struct ctx_query* q = (struct ctx_query*)arg; 494 /* fg query is done; exit comm base */ 495 comm_base_exit(q->w->base); 496 497 libworker_fillup_fg(q, rcode, buf, s, why_bogus); 498 } 499 500 /** setup qinfo and edns */ 501 static int 502 setup_qinfo_edns(struct libworker* w, struct ctx_query* q, 503 struct query_info* qinfo, struct edns_data* edns) 504 { 505 ldns_rdf* rdf; 506 qinfo->qtype = (uint16_t)q->res->qtype; 507 qinfo->qclass = (uint16_t)q->res->qclass; 508 rdf = ldns_dname_new_frm_str(q->res->qname); 509 if(!rdf) { 510 return 0; 511 } 512 #ifdef UNBOUND_ALLOC_LITE 513 qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); 514 qinfo->qname_len = ldns_rdf_size(rdf); 515 ldns_rdf_deep_free(rdf); 516 rdf = 0; 517 #else 518 qinfo->qname = ldns_rdf_data(rdf); 519 qinfo->qname_len = ldns_rdf_size(rdf); 520 #endif 521 edns->edns_present = 1; 522 edns->ext_rcode = 0; 523 edns->edns_version = 0; 524 edns->bits = EDNS_DO; 525 if(ldns_buffer_capacity(w->back->udp_buff) < 65535) 526 edns->udp_size = (uint16_t)ldns_buffer_capacity( 527 w->back->udp_buff); 528 else edns->udp_size = 65535; 529 ldns_rdf_free(rdf); 530 return 1; 531 } 532 533 int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) 534 { 535 struct libworker* w = libworker_setup(ctx, 0); 536 uint16_t qflags, qid; 537 struct query_info qinfo; 538 struct edns_data edns; 539 if(!w) 540 return UB_INITFAIL; 541 if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 542 libworker_delete(w); 543 return UB_SYNTAX; 544 } 545 qid = 0; 546 qflags = BIT_RD; 547 q->w = w; 548 /* see if there is a fixed answer */ 549 ldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 550 ldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 551 if(local_zones_answer(ctx->local_zones, &qinfo, &edns, 552 w->back->udp_buff, w->env->scratch)) { 553 regional_free_all(w->env->scratch); 554 libworker_fillup_fg(q, LDNS_RCODE_NOERROR, 555 w->back->udp_buff, sec_status_insecure, NULL); 556 libworker_delete(w); 557 free(qinfo.qname); 558 return UB_NOERROR; 559 } 560 /* process new query */ 561 if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 562 w->back->udp_buff, qid, libworker_fg_done_cb, q)) { 563 free(qinfo.qname); 564 return UB_NOMEM; 565 } 566 free(qinfo.qname); 567 568 /* wait for reply */ 569 comm_base_dispatch(w->base); 570 571 libworker_delete(w); 572 return UB_NOERROR; 573 } 574 575 /** add result to the bg worker result queue */ 576 static void 577 add_bg_result(struct libworker* w, struct ctx_query* q, ldns_buffer* pkt, 578 int err, char* reason) 579 { 580 uint8_t* msg = NULL; 581 uint32_t len = 0; 582 583 /* serialize and delete unneeded q */ 584 if(w->is_bg_thread) { 585 lock_basic_lock(&w->ctx->cfglock); 586 if(reason) 587 q->res->why_bogus = strdup(reason); 588 if(pkt) { 589 q->msg_len = ldns_buffer_remaining(pkt); 590 q->msg = memdup(ldns_buffer_begin(pkt), q->msg_len); 591 if(!q->msg) 592 msg = context_serialize_answer(q, UB_NOMEM, 593 NULL, &len); 594 else msg = context_serialize_answer(q, err, 595 NULL, &len); 596 } else msg = context_serialize_answer(q, err, NULL, &len); 597 lock_basic_unlock(&w->ctx->cfglock); 598 } else { 599 if(reason) 600 q->res->why_bogus = strdup(reason); 601 msg = context_serialize_answer(q, err, pkt, &len); 602 (void)rbtree_delete(&w->ctx->queries, q->node.key); 603 w->ctx->num_async--; 604 context_query_delete(q); 605 } 606 607 if(!msg) { 608 log_err("out of memory for async answer"); 609 return; 610 } 611 if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) { 612 log_err("out of memory for async answer"); 613 return; 614 } 615 } 616 617 void 618 libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s, 619 char* why_bogus) 620 { 621 struct ctx_query* q = (struct ctx_query*)arg; 622 623 if(q->cancelled) { 624 if(q->w->is_bg_thread) { 625 /* delete it now */ 626 struct ub_ctx* ctx = q->w->ctx; 627 lock_basic_lock(&ctx->cfglock); 628 (void)rbtree_delete(&ctx->queries, q->node.key); 629 ctx->num_async--; 630 context_query_delete(q); 631 lock_basic_unlock(&ctx->cfglock); 632 } 633 /* cancelled, do not give answer */ 634 return; 635 } 636 q->msg_security = s; 637 if(rcode != 0) { 638 error_encode(buf, rcode, NULL, 0, BIT_RD, NULL); 639 } 640 add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus); 641 } 642 643 644 /** handle new query command for bg worker */ 645 static void 646 handle_newq(struct libworker* w, uint8_t* buf, uint32_t len) 647 { 648 uint16_t qflags, qid; 649 struct query_info qinfo; 650 struct edns_data edns; 651 struct ctx_query* q; 652 if(w->is_bg_thread) { 653 lock_basic_lock(&w->ctx->cfglock); 654 q = context_lookup_new_query(w->ctx, buf, len); 655 lock_basic_unlock(&w->ctx->cfglock); 656 } else { 657 q = context_deserialize_new_query(w->ctx, buf, len); 658 } 659 free(buf); 660 if(!q) { 661 log_err("failed to deserialize newq"); 662 return; 663 } 664 if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 665 add_bg_result(w, q, NULL, UB_SYNTAX, NULL); 666 return; 667 } 668 qid = 0; 669 qflags = BIT_RD; 670 /* see if there is a fixed answer */ 671 ldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 672 ldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 673 if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns, 674 w->back->udp_buff, w->env->scratch)) { 675 regional_free_all(w->env->scratch); 676 q->msg_security = sec_status_insecure; 677 add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL); 678 free(qinfo.qname); 679 return; 680 } 681 q->w = w; 682 /* process new query */ 683 if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 684 w->back->udp_buff, qid, libworker_bg_done_cb, q)) { 685 add_bg_result(w, q, NULL, UB_NOMEM, NULL); 686 } 687 free(qinfo.qname); 688 } 689 690 void libworker_alloc_cleanup(void* arg) 691 { 692 struct libworker* w = (struct libworker*)arg; 693 slabhash_clear(&w->env->rrset_cache->table); 694 slabhash_clear(w->env->msg_cache); 695 } 696 697 /** compare outbound entry qstates */ 698 static int 699 outbound_entry_compare(void* a, void* b) 700 { 701 struct outbound_entry* e1 = (struct outbound_entry*)a; 702 struct outbound_entry* e2 = (struct outbound_entry*)b; 703 if(e1->qstate == e2->qstate) 704 return 1; 705 return 0; 706 } 707 708 struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, 709 uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, 710 int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen, 711 uint8_t* zone, size_t zonelen, struct module_qstate* q) 712 { 713 struct libworker* w = (struct libworker*)q->env->worker; 714 struct outbound_entry* e = (struct outbound_entry*)regional_alloc( 715 q->region, sizeof(*e)); 716 if(!e) 717 return NULL; 718 e->qstate = q; 719 e->qsent = outnet_serviced_query(w->back, qname, 720 qnamelen, qtype, qclass, flags, dnssec, want_dnssec, 721 q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr, 722 addrlen, zone, zonelen, libworker_handle_service_reply, e, 723 w->back->udp_buff, &outbound_entry_compare); 724 if(!e->qsent) { 725 return NULL; 726 } 727 return e; 728 } 729 730 int 731 libworker_handle_reply(struct comm_point* c, void* arg, int error, 732 struct comm_reply* reply_info) 733 { 734 struct module_qstate* q = (struct module_qstate*)arg; 735 struct libworker* lw = (struct libworker*)q->env->worker; 736 struct outbound_entry e; 737 e.qstate = q; 738 e.qsent = NULL; 739 740 if(error != 0) { 741 mesh_report_reply(lw->env->mesh, &e, reply_info, error); 742 return 0; 743 } 744 /* sanity check. */ 745 if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer)) 746 || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) != 747 LDNS_PACKET_QUERY 748 || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) { 749 /* error becomes timeout for the module as if this reply 750 * never arrived. */ 751 mesh_report_reply(lw->env->mesh, &e, reply_info, 752 NETEVENT_TIMEOUT); 753 return 0; 754 } 755 mesh_report_reply(lw->env->mesh, &e, reply_info, NETEVENT_NOERROR); 756 return 0; 757 } 758 759 int 760 libworker_handle_service_reply(struct comm_point* c, void* arg, int error, 761 struct comm_reply* reply_info) 762 { 763 struct outbound_entry* e = (struct outbound_entry*)arg; 764 struct libworker* lw = (struct libworker*)e->qstate->env->worker; 765 766 if(error != 0) { 767 mesh_report_reply(lw->env->mesh, e, reply_info, error); 768 return 0; 769 } 770 /* sanity check. */ 771 if(!LDNS_QR_WIRE(ldns_buffer_begin(c->buffer)) 772 || LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) != 773 LDNS_PACKET_QUERY 774 || LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1) { 775 /* error becomes timeout for the module as if this reply 776 * never arrived. */ 777 mesh_report_reply(lw->env->mesh, e, reply_info, 778 NETEVENT_TIMEOUT); 779 return 0; 780 } 781 mesh_report_reply(lw->env->mesh, e, reply_info, NETEVENT_NOERROR); 782 return 0; 783 } 784 785 /* --- fake callbacks for fptr_wlist to work --- */ 786 void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 787 uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), 788 int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) 789 { 790 log_assert(0); 791 } 792 793 int worker_handle_request(struct comm_point* ATTR_UNUSED(c), 794 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 795 struct comm_reply* ATTR_UNUSED(repinfo)) 796 { 797 log_assert(0); 798 return 0; 799 } 800 801 int worker_handle_reply(struct comm_point* ATTR_UNUSED(c), 802 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 803 struct comm_reply* ATTR_UNUSED(reply_info)) 804 { 805 log_assert(0); 806 return 0; 807 } 808 809 int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), 810 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 811 struct comm_reply* ATTR_UNUSED(reply_info)) 812 { 813 log_assert(0); 814 return 0; 815 } 816 817 int remote_accept_callback(struct comm_point* ATTR_UNUSED(c), 818 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 819 struct comm_reply* ATTR_UNUSED(repinfo)) 820 { 821 log_assert(0); 822 return 0; 823 } 824 825 int remote_control_callback(struct comm_point* ATTR_UNUSED(c), 826 void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 827 struct comm_reply* ATTR_UNUSED(repinfo)) 828 { 829 log_assert(0); 830 return 0; 831 } 832 833 void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) 834 { 835 log_assert(0); 836 } 837 838 struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname), 839 size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 840 uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 841 int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), 842 struct sockaddr_storage* ATTR_UNUSED(addr), 843 socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q)) 844 { 845 log_assert(0); 846 return 0; 847 } 848 849 void 850 worker_alloc_cleanup(void* ATTR_UNUSED(arg)) 851 { 852 log_assert(0); 853 } 854 855 void worker_stat_timer_cb(void* ATTR_UNUSED(arg)) 856 { 857 log_assert(0); 858 } 859 860 void worker_probe_timer_cb(void* ATTR_UNUSED(arg)) 861 { 862 log_assert(0); 863 } 864 865 void worker_start_accept(void* ATTR_UNUSED(arg)) 866 { 867 log_assert(0); 868 } 869 870 void worker_stop_accept(void* ATTR_UNUSED(arg)) 871 { 872 log_assert(0); 873 } 874 875 int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) 876 { 877 log_assert(0); 878 return 0; 879 } 880 881 int 882 codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 883 { 884 log_assert(0); 885 return 0; 886 } 887 888 int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 889 { 890 log_assert(0); 891 return 0; 892 } 893 894 void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) 895 { 896 log_assert(0); 897 } 898 899 #ifdef UB_ON_WINDOWS 900 void 901 worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* 902 ATTR_UNUSED(arg)) { 903 log_assert(0); 904 } 905 906 void 907 wsvc_cron_cb(void* ATTR_UNUSED(arg)) 908 { 909 log_assert(0); 910 } 911 #endif /* UB_ON_WINDOWS */ 912