libworker.c revision 307729
1238106Sdes/* 2238106Sdes * libunbound/worker.c - worker thread or process that resolves 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24266114Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25266114Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26266114Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27266114Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28266114Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29266114Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30266114Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31266114Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32266114Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33266114Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains the worker process or thread that performs 40238106Sdes * the DNS resolving and validation. The worker is called by a procedure 41238106Sdes * and if in the background continues until exit, if in the foreground 42238106Sdes * returns from the procedure when done. 43238106Sdes */ 44238106Sdes#include "config.h" 45249141Sdes#ifdef HAVE_SSL 46238106Sdes#include <openssl/ssl.h> 47249141Sdes#endif 48238106Sdes#include "libunbound/libworker.h" 49238106Sdes#include "libunbound/context.h" 50238106Sdes#include "libunbound/unbound.h" 51255579Sdes#include "libunbound/worker.h" 52266114Sdes#include "libunbound/unbound-event.h" 53238106Sdes#include "services/outside_network.h" 54238106Sdes#include "services/mesh.h" 55238106Sdes#include "services/localzone.h" 56238106Sdes#include "services/cache/rrset.h" 57238106Sdes#include "services/outbound_list.h" 58255579Sdes#include "util/fptr_wlist.h" 59238106Sdes#include "util/module.h" 60238106Sdes#include "util/regional.h" 61238106Sdes#include "util/random.h" 62238106Sdes#include "util/config_file.h" 63238106Sdes#include "util/netevent.h" 64238106Sdes#include "util/storage/lookup3.h" 65238106Sdes#include "util/storage/slabhash.h" 66238106Sdes#include "util/net_help.h" 67238106Sdes#include "util/data/dname.h" 68238106Sdes#include "util/data/msgreply.h" 69238106Sdes#include "util/data/msgencode.h" 70238106Sdes#include "util/tube.h" 71238106Sdes#include "iterator/iter_fwd.h" 72238106Sdes#include "iterator/iter_hints.h" 73287917Sdes#include "sldns/sbuffer.h" 74287917Sdes#include "sldns/str2wire.h" 75238106Sdes 76238106Sdes/** handle new query command for bg worker */ 77238106Sdesstatic void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len); 78238106Sdes 79266114Sdes/** delete libworker env */ 80238106Sdesstatic void 81266114Sdeslibworker_delete_env(struct libworker* w) 82238106Sdes{ 83238106Sdes if(w->env) { 84238106Sdes outside_network_quit_prepare(w->back); 85238106Sdes mesh_delete(w->env->mesh); 86238106Sdes context_release_alloc(w->ctx, w->env->alloc, 87238106Sdes !w->is_bg || w->is_bg_thread); 88266114Sdes sldns_buffer_free(w->env->scratch_buffer); 89238106Sdes regional_destroy(w->env->scratch); 90238106Sdes forwards_delete(w->env->fwds); 91238106Sdes hints_delete(w->env->hints); 92238106Sdes ub_randfree(w->env->rnd); 93238106Sdes free(w->env); 94238106Sdes } 95249141Sdes#ifdef HAVE_SSL 96238106Sdes SSL_CTX_free(w->sslctx); 97249141Sdes#endif 98238106Sdes outside_network_delete(w->back); 99266114Sdes} 100266114Sdes 101266114Sdes/** delete libworker struct */ 102266114Sdesstatic void 103266114Sdeslibworker_delete(struct libworker* w) 104266114Sdes{ 105266114Sdes if(!w) return; 106266114Sdes libworker_delete_env(w); 107238106Sdes comm_base_delete(w->base); 108238106Sdes free(w); 109238106Sdes} 110238106Sdes 111266114Sdesvoid 112266114Sdeslibworker_delete_event(struct libworker* w) 113266114Sdes{ 114266114Sdes if(!w) return; 115266114Sdes libworker_delete_env(w); 116266114Sdes comm_base_delete_no_base(w->base); 117266114Sdes free(w); 118266114Sdes} 119266114Sdes 120238106Sdes/** setup fresh libworker struct */ 121238106Sdesstatic struct libworker* 122307729Sdeslibworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb) 123238106Sdes{ 124238106Sdes unsigned int seed; 125238106Sdes struct libworker* w = (struct libworker*)calloc(1, sizeof(*w)); 126238106Sdes struct config_file* cfg = ctx->env->cfg; 127238106Sdes int* ports; 128238106Sdes int numports; 129238106Sdes if(!w) return NULL; 130238106Sdes w->is_bg = is_bg; 131238106Sdes w->ctx = ctx; 132238106Sdes w->env = (struct module_env*)malloc(sizeof(*w->env)); 133238106Sdes if(!w->env) { 134238106Sdes free(w); 135238106Sdes return NULL; 136238106Sdes } 137238106Sdes *w->env = *ctx->env; 138238106Sdes w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread); 139238106Sdes if(!w->env->alloc) { 140238106Sdes libworker_delete(w); 141238106Sdes return NULL; 142238106Sdes } 143238106Sdes w->thread_num = w->env->alloc->thread_num; 144238106Sdes alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w); 145238106Sdes if(!w->is_bg || w->is_bg_thread) { 146238106Sdes lock_basic_lock(&ctx->cfglock); 147238106Sdes } 148238106Sdes w->env->scratch = regional_create_custom(cfg->msg_buffer_size); 149266114Sdes w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size); 150238106Sdes w->env->fwds = forwards_create(); 151238106Sdes if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { 152238106Sdes forwards_delete(w->env->fwds); 153238106Sdes w->env->fwds = NULL; 154238106Sdes } 155238106Sdes w->env->hints = hints_create(); 156238106Sdes if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { 157238106Sdes hints_delete(w->env->hints); 158238106Sdes w->env->hints = NULL; 159238106Sdes } 160238106Sdes if(cfg->ssl_upstream) { 161238106Sdes w->sslctx = connect_sslctx_create(NULL, NULL, NULL); 162238106Sdes if(!w->sslctx) { 163238106Sdes /* to make the setup fail after unlock */ 164238106Sdes hints_delete(w->env->hints); 165238106Sdes w->env->hints = NULL; 166238106Sdes } 167238106Sdes } 168238106Sdes if(!w->is_bg || w->is_bg_thread) { 169238106Sdes lock_basic_unlock(&ctx->cfglock); 170238106Sdes } 171238106Sdes if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds || 172238106Sdes !w->env->hints) { 173238106Sdes libworker_delete(w); 174238106Sdes return NULL; 175238106Sdes } 176238106Sdes w->env->worker = (struct worker*)w; 177238106Sdes w->env->probe_timer = NULL; 178238106Sdes seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^ 179238106Sdes (((unsigned int)w->thread_num)<<17); 180238106Sdes seed ^= (unsigned int)w->env->alloc->next_id; 181238106Sdes if(!w->is_bg || w->is_bg_thread) { 182238106Sdes lock_basic_lock(&ctx->cfglock); 183238106Sdes } 184238106Sdes if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) { 185238106Sdes if(!w->is_bg || w->is_bg_thread) { 186238106Sdes lock_basic_unlock(&ctx->cfglock); 187238106Sdes } 188238106Sdes seed = 0; 189238106Sdes libworker_delete(w); 190238106Sdes return NULL; 191238106Sdes } 192238106Sdes if(!w->is_bg || w->is_bg_thread) { 193238106Sdes lock_basic_unlock(&ctx->cfglock); 194238106Sdes } 195238106Sdes if(1) { 196238106Sdes /* primitive lockout for threading: if it overwrites another 197238106Sdes * thread it is like wiping the cache (which is likely empty 198238106Sdes * at the start) */ 199238106Sdes /* note we are holding the ctx lock in normal threaded 200238106Sdes * cases so that is solved properly, it is only for many ctx 201238106Sdes * in different threads that this may clash */ 202238106Sdes static int done_raninit = 0; 203238106Sdes if(!done_raninit) { 204238106Sdes done_raninit = 1; 205238106Sdes hash_set_raninit((uint32_t)ub_random(w->env->rnd)); 206238106Sdes } 207238106Sdes } 208238106Sdes seed = 0; 209238106Sdes 210266114Sdes if(eb) 211266114Sdes w->base = comm_base_create_event(eb); 212266114Sdes else w->base = comm_base_create(0); 213238106Sdes if(!w->base) { 214238106Sdes libworker_delete(w); 215238106Sdes return NULL; 216238106Sdes } 217238106Sdes if(!w->is_bg || w->is_bg_thread) { 218238106Sdes lock_basic_lock(&ctx->cfglock); 219238106Sdes } 220238106Sdes numports = cfg_condense_ports(cfg, &ports); 221238106Sdes if(numports == 0) { 222266114Sdes int locked = !w->is_bg || w->is_bg_thread; 223238106Sdes libworker_delete(w); 224266114Sdes if(locked) { 225266114Sdes lock_basic_unlock(&ctx->cfglock); 226266114Sdes } 227238106Sdes return NULL; 228238106Sdes } 229238106Sdes w->back = outside_network_create(w->base, cfg->msg_buffer_size, 230238106Sdes (size_t)cfg->outgoing_num_ports, cfg->out_ifs, 231238106Sdes cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, 232238106Sdes cfg->do_tcp?cfg->outgoing_num_tcp:0, 233238106Sdes w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id, 234238106Sdes ports, numports, cfg->unwanted_threshold, 235296415Sdes cfg->outgoing_tcp_mss, 236266114Sdes &libworker_alloc_cleanup, w, cfg->do_udp, w->sslctx, 237276605Sdes cfg->delay_close, NULL); 238238106Sdes if(!w->is_bg || w->is_bg_thread) { 239238106Sdes lock_basic_unlock(&ctx->cfglock); 240238106Sdes } 241238106Sdes free(ports); 242238106Sdes if(!w->back) { 243238106Sdes libworker_delete(w); 244238106Sdes return NULL; 245238106Sdes } 246238106Sdes w->env->mesh = mesh_create(&ctx->mods, w->env); 247238106Sdes if(!w->env->mesh) { 248238106Sdes libworker_delete(w); 249238106Sdes return NULL; 250238106Sdes } 251238106Sdes w->env->send_query = &libworker_send_query; 252238106Sdes w->env->detach_subs = &mesh_detach_subs; 253238106Sdes w->env->attach_sub = &mesh_attach_sub; 254238106Sdes w->env->kill_sub = &mesh_state_delete; 255238106Sdes w->env->detect_cycle = &mesh_detect_cycle; 256238106Sdes comm_base_timept(w->base, &w->env->now, &w->env->now_tv); 257238106Sdes return w; 258238106Sdes} 259238106Sdes 260266114Sdesstruct libworker* libworker_create_event(struct ub_ctx* ctx, 261307729Sdes struct ub_event_base* eb) 262266114Sdes{ 263266114Sdes return libworker_setup(ctx, 0, eb); 264266114Sdes} 265266114Sdes 266238106Sdes/** handle cancel command for bg worker */ 267238106Sdesstatic void 268238106Sdeshandle_cancel(struct libworker* w, uint8_t* buf, uint32_t len) 269238106Sdes{ 270238106Sdes struct ctx_query* q; 271238106Sdes if(w->is_bg_thread) { 272238106Sdes lock_basic_lock(&w->ctx->cfglock); 273238106Sdes q = context_deserialize_cancel(w->ctx, buf, len); 274238106Sdes lock_basic_unlock(&w->ctx->cfglock); 275238106Sdes } else { 276238106Sdes q = context_deserialize_cancel(w->ctx, buf, len); 277238106Sdes } 278238106Sdes if(!q) { 279238106Sdes /* probably simply lookup failed, i.e. the message had been 280238106Sdes * processed and answered before the cancel arrived */ 281238106Sdes return; 282238106Sdes } 283238106Sdes q->cancelled = 1; 284238106Sdes free(buf); 285238106Sdes} 286238106Sdes 287238106Sdes/** do control command coming into bg server */ 288238106Sdesstatic void 289238106Sdeslibworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len) 290238106Sdes{ 291238106Sdes switch(context_serial_getcmd(msg, len)) { 292238106Sdes default: 293238106Sdes case UB_LIBCMD_ANSWER: 294238106Sdes log_err("unknown command for bg worker %d", 295238106Sdes (int)context_serial_getcmd(msg, len)); 296238106Sdes /* and fall through to quit */ 297238106Sdes case UB_LIBCMD_QUIT: 298238106Sdes free(msg); 299238106Sdes comm_base_exit(w->base); 300238106Sdes break; 301238106Sdes case UB_LIBCMD_NEWQUERY: 302238106Sdes handle_newq(w, msg, len); 303238106Sdes break; 304238106Sdes case UB_LIBCMD_CANCEL: 305238106Sdes handle_cancel(w, msg, len); 306238106Sdes break; 307238106Sdes } 308238106Sdes} 309238106Sdes 310238106Sdes/** handle control command coming into server */ 311238106Sdesvoid 312238106Sdeslibworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 313238106Sdes uint8_t* msg, size_t len, int err, void* arg) 314238106Sdes{ 315238106Sdes struct libworker* w = (struct libworker*)arg; 316238106Sdes 317238106Sdes if(err != 0) { 318238106Sdes free(msg); 319238106Sdes /* it is of no use to go on, exit */ 320238106Sdes comm_base_exit(w->base); 321238106Sdes return; 322238106Sdes } 323238106Sdes libworker_do_cmd(w, msg, len); /* also frees the buf */ 324238106Sdes} 325238106Sdes 326238106Sdes/** the background thread func */ 327238106Sdesstatic void* 328238106Sdeslibworker_dobg(void* arg) 329238106Sdes{ 330238106Sdes /* setup */ 331238106Sdes uint32_t m; 332238106Sdes struct libworker* w = (struct libworker*)arg; 333238106Sdes struct ub_ctx* ctx; 334238106Sdes if(!w) { 335238106Sdes log_err("libunbound bg worker init failed, nomem"); 336238106Sdes return NULL; 337238106Sdes } 338238106Sdes ctx = w->ctx; 339238106Sdes log_thread_set(&w->thread_num); 340238106Sdes#ifdef THREADS_DISABLED 341238106Sdes /* we are forked */ 342238106Sdes w->is_bg_thread = 0; 343238106Sdes /* close non-used parts of the pipes */ 344238106Sdes tube_close_write(ctx->qq_pipe); 345238106Sdes tube_close_read(ctx->rr_pipe); 346238106Sdes#endif 347238106Sdes if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, 348238106Sdes libworker_handle_control_cmd, w)) { 349238106Sdes log_err("libunbound bg worker init failed, no bglisten"); 350238106Sdes return NULL; 351238106Sdes } 352238106Sdes if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) { 353238106Sdes log_err("libunbound bg worker init failed, no bgwrite"); 354238106Sdes return NULL; 355238106Sdes } 356238106Sdes 357238106Sdes /* do the work */ 358238106Sdes comm_base_dispatch(w->base); 359238106Sdes 360238106Sdes /* cleanup */ 361238106Sdes m = UB_LIBCMD_QUIT; 362238106Sdes tube_remove_bg_listen(w->ctx->qq_pipe); 363238106Sdes tube_remove_bg_write(w->ctx->rr_pipe); 364238106Sdes libworker_delete(w); 365238106Sdes (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, 366238106Sdes (uint32_t)sizeof(m), 0); 367238106Sdes#ifdef THREADS_DISABLED 368238106Sdes /* close pipes from forked process before exit */ 369238106Sdes tube_close_read(ctx->qq_pipe); 370238106Sdes tube_close_write(ctx->rr_pipe); 371238106Sdes#endif 372238106Sdes return NULL; 373238106Sdes} 374238106Sdes 375238106Sdesint libworker_bg(struct ub_ctx* ctx) 376238106Sdes{ 377238106Sdes struct libworker* w; 378238106Sdes /* fork or threadcreate */ 379238106Sdes lock_basic_lock(&ctx->cfglock); 380238106Sdes if(ctx->dothread) { 381238106Sdes lock_basic_unlock(&ctx->cfglock); 382266114Sdes w = libworker_setup(ctx, 1, NULL); 383238106Sdes if(!w) return UB_NOMEM; 384238106Sdes w->is_bg_thread = 1; 385238106Sdes#ifdef ENABLE_LOCK_CHECKS 386238106Sdes w->thread_num = 1; /* for nicer DEBUG checklocks */ 387238106Sdes#endif 388238106Sdes ub_thread_create(&ctx->bg_tid, libworker_dobg, w); 389238106Sdes } else { 390238106Sdes lock_basic_unlock(&ctx->cfglock); 391238106Sdes#ifndef HAVE_FORK 392238106Sdes /* no fork on windows */ 393238106Sdes return UB_FORKFAIL; 394238106Sdes#else /* HAVE_FORK */ 395238106Sdes switch((ctx->bg_pid=fork())) { 396238106Sdes case 0: 397266114Sdes w = libworker_setup(ctx, 1, NULL); 398238106Sdes if(!w) fatal_exit("out of memory"); 399238106Sdes /* close non-used parts of the pipes */ 400238106Sdes tube_close_write(ctx->qq_pipe); 401238106Sdes tube_close_read(ctx->rr_pipe); 402238106Sdes (void)libworker_dobg(w); 403238106Sdes exit(0); 404238106Sdes break; 405238106Sdes case -1: 406238106Sdes return UB_FORKFAIL; 407238106Sdes default: 408266114Sdes /* close non-used parts, so that the worker 409266114Sdes * bgprocess gets 'pipe closed' when the 410266114Sdes * main process exits */ 411266114Sdes tube_close_read(ctx->qq_pipe); 412266114Sdes tube_close_write(ctx->rr_pipe); 413238106Sdes break; 414238106Sdes } 415238106Sdes#endif /* HAVE_FORK */ 416238106Sdes } 417238106Sdes return UB_NOERROR; 418238106Sdes} 419238106Sdes 420238106Sdes/** get msg reply struct (in temp region) */ 421238106Sdesstatic struct reply_info* 422266114Sdesparse_reply(sldns_buffer* pkt, struct regional* region, struct query_info* qi) 423238106Sdes{ 424238106Sdes struct reply_info* rep; 425238106Sdes struct msg_parse* msg; 426238106Sdes if(!(msg = regional_alloc(region, sizeof(*msg)))) { 427238106Sdes return NULL; 428238106Sdes } 429238106Sdes memset(msg, 0, sizeof(*msg)); 430266114Sdes sldns_buffer_set_position(pkt, 0); 431238106Sdes if(parse_packet(pkt, msg, region) != 0) 432238106Sdes return 0; 433238106Sdes if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) { 434238106Sdes return 0; 435238106Sdes } 436238106Sdes return rep; 437238106Sdes} 438238106Sdes 439238106Sdes/** insert canonname */ 440238106Sdesstatic int 441238106Sdesfill_canon(struct ub_result* res, uint8_t* s) 442238106Sdes{ 443238106Sdes char buf[255+2]; 444238106Sdes dname_str(s, buf); 445238106Sdes res->canonname = strdup(buf); 446238106Sdes return res->canonname != 0; 447238106Sdes} 448238106Sdes 449238106Sdes/** fill data into result */ 450238106Sdesstatic int 451238106Sdesfill_res(struct ub_result* res, struct ub_packed_rrset_key* answer, 452249141Sdes uint8_t* finalcname, struct query_info* rq, struct reply_info* rep) 453238106Sdes{ 454238106Sdes size_t i; 455238106Sdes struct packed_rrset_data* data; 456249141Sdes res->ttl = 0; 457238106Sdes if(!answer) { 458238106Sdes if(finalcname) { 459238106Sdes if(!fill_canon(res, finalcname)) 460238106Sdes return 0; /* out of memory */ 461238106Sdes } 462249141Sdes if(rep->rrset_count != 0) 463249141Sdes res->ttl = (int)rep->ttl; 464238106Sdes res->data = (char**)calloc(1, sizeof(char*)); 465238106Sdes res->len = (int*)calloc(1, sizeof(int)); 466238106Sdes return (res->data && res->len); 467238106Sdes } 468238106Sdes data = (struct packed_rrset_data*)answer->entry.data; 469238106Sdes if(query_dname_compare(rq->qname, answer->rk.dname) != 0) { 470238106Sdes if(!fill_canon(res, answer->rk.dname)) 471238106Sdes return 0; /* out of memory */ 472238106Sdes } else res->canonname = NULL; 473238106Sdes res->data = (char**)calloc(data->count+1, sizeof(char*)); 474238106Sdes res->len = (int*)calloc(data->count+1, sizeof(int)); 475238106Sdes if(!res->data || !res->len) 476238106Sdes return 0; /* out of memory */ 477238106Sdes for(i=0; i<data->count; i++) { 478238106Sdes /* remove rdlength from rdata */ 479238106Sdes res->len[i] = (int)(data->rr_len[i] - 2); 480238106Sdes res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]); 481238106Sdes if(!res->data[i]) 482238106Sdes return 0; /* out of memory */ 483238106Sdes } 484249141Sdes /* ttl for positive answers, from CNAME and answer RRs */ 485249141Sdes if(data->count != 0) { 486249141Sdes size_t j; 487249141Sdes res->ttl = (int)data->ttl; 488249141Sdes for(j=0; j<rep->an_numrrsets; j++) { 489249141Sdes struct packed_rrset_data* d = 490249141Sdes (struct packed_rrset_data*)rep->rrsets[j]-> 491249141Sdes entry.data; 492249141Sdes if((int)d->ttl < res->ttl) 493249141Sdes res->ttl = (int)d->ttl; 494249141Sdes } 495249141Sdes } 496249141Sdes /* ttl for negative answers */ 497249141Sdes if(data->count == 0 && rep->rrset_count != 0) 498249141Sdes res->ttl = (int)rep->ttl; 499238106Sdes res->data[data->count] = NULL; 500238106Sdes res->len[data->count] = 0; 501238106Sdes return 1; 502238106Sdes} 503238106Sdes 504238106Sdes/** fill result from parsed message, on error fills servfail */ 505238106Sdesvoid 506266114Sdeslibworker_enter_result(struct ub_result* res, sldns_buffer* buf, 507238106Sdes struct regional* temp, enum sec_status msg_security) 508238106Sdes{ 509238106Sdes struct query_info rq; 510238106Sdes struct reply_info* rep; 511238106Sdes res->rcode = LDNS_RCODE_SERVFAIL; 512238106Sdes rep = parse_reply(buf, temp, &rq); 513238106Sdes if(!rep) { 514238106Sdes log_err("cannot parse buf"); 515238106Sdes return; /* error parsing buf, or out of memory */ 516238106Sdes } 517238106Sdes if(!fill_res(res, reply_find_answer_rrset(&rq, rep), 518249141Sdes reply_find_final_cname_target(&rq, rep), &rq, rep)) 519238106Sdes return; /* out of memory */ 520238106Sdes /* rcode, havedata, nxdomain, secure, bogus */ 521238106Sdes res->rcode = (int)FLAGS_GET_RCODE(rep->flags); 522238106Sdes if(res->data && res->data[0]) 523238106Sdes res->havedata = 1; 524238106Sdes if(res->rcode == LDNS_RCODE_NXDOMAIN) 525238106Sdes res->nxdomain = 1; 526238106Sdes if(msg_security == sec_status_secure) 527238106Sdes res->secure = 1; 528238106Sdes if(msg_security == sec_status_bogus) 529238106Sdes res->bogus = 1; 530238106Sdes} 531238106Sdes 532238106Sdes/** fillup fg results */ 533238106Sdesstatic void 534266114Sdeslibworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf, 535238106Sdes enum sec_status s, char* why_bogus) 536238106Sdes{ 537238106Sdes if(why_bogus) 538238106Sdes q->res->why_bogus = strdup(why_bogus); 539238106Sdes if(rcode != 0) { 540238106Sdes q->res->rcode = rcode; 541238106Sdes q->msg_security = s; 542238106Sdes return; 543238106Sdes } 544238106Sdes 545238106Sdes q->res->rcode = LDNS_RCODE_SERVFAIL; 546238106Sdes q->msg_security = 0; 547266114Sdes q->msg = memdup(sldns_buffer_begin(buf), sldns_buffer_limit(buf)); 548266114Sdes q->msg_len = sldns_buffer_limit(buf); 549238106Sdes if(!q->msg) { 550238106Sdes return; /* the error is in the rcode */ 551238106Sdes } 552238106Sdes 553238106Sdes /* canonname and results */ 554238106Sdes q->msg_security = s; 555238106Sdes libworker_enter_result(q->res, buf, q->w->env->scratch, s); 556238106Sdes} 557238106Sdes 558238106Sdesvoid 559266114Sdeslibworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, 560238106Sdes char* why_bogus) 561238106Sdes{ 562238106Sdes struct ctx_query* q = (struct ctx_query*)arg; 563238106Sdes /* fg query is done; exit comm base */ 564238106Sdes comm_base_exit(q->w->base); 565238106Sdes 566238106Sdes libworker_fillup_fg(q, rcode, buf, s, why_bogus); 567238106Sdes} 568238106Sdes 569238106Sdes/** setup qinfo and edns */ 570238106Sdesstatic int 571238106Sdessetup_qinfo_edns(struct libworker* w, struct ctx_query* q, 572238106Sdes struct query_info* qinfo, struct edns_data* edns) 573238106Sdes{ 574238106Sdes qinfo->qtype = (uint16_t)q->res->qtype; 575238106Sdes qinfo->qclass = (uint16_t)q->res->qclass; 576266114Sdes qinfo->qname = sldns_str2wire_dname(q->res->qname, &qinfo->qname_len); 577266114Sdes if(!qinfo->qname) { 578238106Sdes return 0; 579238106Sdes } 580238106Sdes edns->edns_present = 1; 581238106Sdes edns->ext_rcode = 0; 582238106Sdes edns->edns_version = 0; 583238106Sdes edns->bits = EDNS_DO; 584307729Sdes edns->opt_list = NULL; 585266114Sdes if(sldns_buffer_capacity(w->back->udp_buff) < 65535) 586266114Sdes edns->udp_size = (uint16_t)sldns_buffer_capacity( 587238106Sdes w->back->udp_buff); 588238106Sdes else edns->udp_size = 65535; 589238106Sdes return 1; 590238106Sdes} 591238106Sdes 592238106Sdesint libworker_fg(struct ub_ctx* ctx, struct ctx_query* q) 593238106Sdes{ 594266114Sdes struct libworker* w = libworker_setup(ctx, 0, NULL); 595238106Sdes uint16_t qflags, qid; 596238106Sdes struct query_info qinfo; 597238106Sdes struct edns_data edns; 598238106Sdes if(!w) 599238106Sdes return UB_INITFAIL; 600238106Sdes if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 601238106Sdes libworker_delete(w); 602238106Sdes return UB_SYNTAX; 603238106Sdes } 604238106Sdes qid = 0; 605238106Sdes qflags = BIT_RD; 606238106Sdes q->w = w; 607238106Sdes /* see if there is a fixed answer */ 608266114Sdes sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 609266114Sdes sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 610238106Sdes if(local_zones_answer(ctx->local_zones, &qinfo, &edns, 611307729Sdes w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, 612307729Sdes NULL, 0, NULL, 0)) { 613238106Sdes regional_free_all(w->env->scratch); 614238106Sdes libworker_fillup_fg(q, LDNS_RCODE_NOERROR, 615238106Sdes w->back->udp_buff, sec_status_insecure, NULL); 616238106Sdes libworker_delete(w); 617238106Sdes free(qinfo.qname); 618238106Sdes return UB_NOERROR; 619238106Sdes } 620238106Sdes /* process new query */ 621238106Sdes if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 622238106Sdes w->back->udp_buff, qid, libworker_fg_done_cb, q)) { 623238106Sdes free(qinfo.qname); 624238106Sdes return UB_NOMEM; 625238106Sdes } 626238106Sdes free(qinfo.qname); 627238106Sdes 628238106Sdes /* wait for reply */ 629238106Sdes comm_base_dispatch(w->base); 630238106Sdes 631238106Sdes libworker_delete(w); 632238106Sdes return UB_NOERROR; 633238106Sdes} 634238106Sdes 635266114Sdesvoid 636266114Sdeslibworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf, 637266114Sdes enum sec_status s, char* why_bogus) 638266114Sdes{ 639266114Sdes struct ctx_query* q = (struct ctx_query*)arg; 640266114Sdes ub_event_callback_t cb = (ub_event_callback_t)q->cb; 641266114Sdes void* cb_arg = q->cb_arg; 642266114Sdes int cancelled = q->cancelled; 643266114Sdes 644266114Sdes /* delete it now */ 645266114Sdes struct ub_ctx* ctx = q->w->ctx; 646266114Sdes lock_basic_lock(&ctx->cfglock); 647266114Sdes (void)rbtree_delete(&ctx->queries, q->node.key); 648266114Sdes ctx->num_async--; 649266114Sdes context_query_delete(q); 650266114Sdes lock_basic_unlock(&ctx->cfglock); 651266114Sdes 652266114Sdes if(!cancelled) { 653266114Sdes /* call callback */ 654266114Sdes int sec = 0; 655266114Sdes if(s == sec_status_bogus) 656266114Sdes sec = 1; 657266114Sdes else if(s == sec_status_secure) 658266114Sdes sec = 2; 659266114Sdes (*cb)(cb_arg, rcode, (void*)sldns_buffer_begin(buf), 660266114Sdes (int)sldns_buffer_limit(buf), sec, why_bogus); 661266114Sdes } 662266114Sdes} 663266114Sdes 664266114Sdesint libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q, 665266114Sdes int* async_id) 666266114Sdes{ 667266114Sdes struct libworker* w = ctx->event_worker; 668266114Sdes uint16_t qflags, qid; 669266114Sdes struct query_info qinfo; 670266114Sdes struct edns_data edns; 671266114Sdes if(!w) 672266114Sdes return UB_INITFAIL; 673266114Sdes if(!setup_qinfo_edns(w, q, &qinfo, &edns)) 674266114Sdes return UB_SYNTAX; 675266114Sdes qid = 0; 676266114Sdes qflags = BIT_RD; 677266114Sdes q->w = w; 678266114Sdes /* see if there is a fixed answer */ 679266114Sdes sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 680266114Sdes sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 681266114Sdes if(local_zones_answer(ctx->local_zones, &qinfo, &edns, 682307729Sdes w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, 683307729Sdes NULL, 0, NULL, 0)) { 684266114Sdes regional_free_all(w->env->scratch); 685266114Sdes free(qinfo.qname); 686266114Sdes libworker_event_done_cb(q, LDNS_RCODE_NOERROR, 687266114Sdes w->back->udp_buff, sec_status_insecure, NULL); 688266114Sdes return UB_NOERROR; 689266114Sdes } 690266114Sdes /* process new query */ 691266114Sdes if(async_id) 692266114Sdes *async_id = q->querynum; 693266114Sdes if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 694266114Sdes w->back->udp_buff, qid, libworker_event_done_cb, q)) { 695266114Sdes free(qinfo.qname); 696266114Sdes return UB_NOMEM; 697266114Sdes } 698266114Sdes free(qinfo.qname); 699266114Sdes return UB_NOERROR; 700266114Sdes} 701266114Sdes 702238106Sdes/** add result to the bg worker result queue */ 703238106Sdesstatic void 704266114Sdesadd_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt, 705238106Sdes int err, char* reason) 706238106Sdes{ 707238106Sdes uint8_t* msg = NULL; 708238106Sdes uint32_t len = 0; 709238106Sdes 710238106Sdes /* serialize and delete unneeded q */ 711238106Sdes if(w->is_bg_thread) { 712238106Sdes lock_basic_lock(&w->ctx->cfglock); 713238106Sdes if(reason) 714238106Sdes q->res->why_bogus = strdup(reason); 715238106Sdes if(pkt) { 716266114Sdes q->msg_len = sldns_buffer_remaining(pkt); 717266114Sdes q->msg = memdup(sldns_buffer_begin(pkt), q->msg_len); 718238106Sdes if(!q->msg) 719238106Sdes msg = context_serialize_answer(q, UB_NOMEM, 720238106Sdes NULL, &len); 721238106Sdes else msg = context_serialize_answer(q, err, 722238106Sdes NULL, &len); 723238106Sdes } else msg = context_serialize_answer(q, err, NULL, &len); 724238106Sdes lock_basic_unlock(&w->ctx->cfglock); 725238106Sdes } else { 726238106Sdes if(reason) 727238106Sdes q->res->why_bogus = strdup(reason); 728238106Sdes msg = context_serialize_answer(q, err, pkt, &len); 729238106Sdes (void)rbtree_delete(&w->ctx->queries, q->node.key); 730238106Sdes w->ctx->num_async--; 731238106Sdes context_query_delete(q); 732238106Sdes } 733238106Sdes 734238106Sdes if(!msg) { 735238106Sdes log_err("out of memory for async answer"); 736238106Sdes return; 737238106Sdes } 738238106Sdes if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) { 739238106Sdes log_err("out of memory for async answer"); 740238106Sdes return; 741238106Sdes } 742238106Sdes} 743238106Sdes 744238106Sdesvoid 745266114Sdeslibworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s, 746238106Sdes char* why_bogus) 747238106Sdes{ 748238106Sdes struct ctx_query* q = (struct ctx_query*)arg; 749238106Sdes 750238106Sdes if(q->cancelled) { 751238106Sdes if(q->w->is_bg_thread) { 752238106Sdes /* delete it now */ 753238106Sdes struct ub_ctx* ctx = q->w->ctx; 754238106Sdes lock_basic_lock(&ctx->cfglock); 755238106Sdes (void)rbtree_delete(&ctx->queries, q->node.key); 756238106Sdes ctx->num_async--; 757238106Sdes context_query_delete(q); 758238106Sdes lock_basic_unlock(&ctx->cfglock); 759238106Sdes } 760238106Sdes /* cancelled, do not give answer */ 761238106Sdes return; 762238106Sdes } 763238106Sdes q->msg_security = s; 764249141Sdes if(!buf) 765249141Sdes buf = q->w->env->scratch_buffer; 766238106Sdes if(rcode != 0) { 767238106Sdes error_encode(buf, rcode, NULL, 0, BIT_RD, NULL); 768238106Sdes } 769238106Sdes add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus); 770238106Sdes} 771238106Sdes 772238106Sdes 773238106Sdes/** handle new query command for bg worker */ 774238106Sdesstatic void 775238106Sdeshandle_newq(struct libworker* w, uint8_t* buf, uint32_t len) 776238106Sdes{ 777238106Sdes uint16_t qflags, qid; 778238106Sdes struct query_info qinfo; 779238106Sdes struct edns_data edns; 780238106Sdes struct ctx_query* q; 781238106Sdes if(w->is_bg_thread) { 782238106Sdes lock_basic_lock(&w->ctx->cfglock); 783238106Sdes q = context_lookup_new_query(w->ctx, buf, len); 784238106Sdes lock_basic_unlock(&w->ctx->cfglock); 785238106Sdes } else { 786238106Sdes q = context_deserialize_new_query(w->ctx, buf, len); 787238106Sdes } 788238106Sdes free(buf); 789238106Sdes if(!q) { 790238106Sdes log_err("failed to deserialize newq"); 791238106Sdes return; 792238106Sdes } 793238106Sdes if(!setup_qinfo_edns(w, q, &qinfo, &edns)) { 794238106Sdes add_bg_result(w, q, NULL, UB_SYNTAX, NULL); 795238106Sdes return; 796238106Sdes } 797238106Sdes qid = 0; 798238106Sdes qflags = BIT_RD; 799238106Sdes /* see if there is a fixed answer */ 800266114Sdes sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid); 801266114Sdes sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags); 802238106Sdes if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns, 803307729Sdes w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0, 804307729Sdes NULL, 0, NULL, 0)) { 805238106Sdes regional_free_all(w->env->scratch); 806238106Sdes q->msg_security = sec_status_insecure; 807238106Sdes add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL); 808238106Sdes free(qinfo.qname); 809238106Sdes return; 810238106Sdes } 811238106Sdes q->w = w; 812238106Sdes /* process new query */ 813238106Sdes if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns, 814238106Sdes w->back->udp_buff, qid, libworker_bg_done_cb, q)) { 815238106Sdes add_bg_result(w, q, NULL, UB_NOMEM, NULL); 816238106Sdes } 817238106Sdes free(qinfo.qname); 818238106Sdes} 819238106Sdes 820238106Sdesvoid libworker_alloc_cleanup(void* arg) 821238106Sdes{ 822238106Sdes struct libworker* w = (struct libworker*)arg; 823238106Sdes slabhash_clear(&w->env->rrset_cache->table); 824238106Sdes slabhash_clear(w->env->msg_cache); 825238106Sdes} 826238106Sdes 827238106Sdesstruct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, 828238106Sdes uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, 829307729Sdes int want_dnssec, int nocaps, struct edns_option* opt_list, 830307729Sdes struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, 831307729Sdes size_t zonelen, struct module_qstate* q) 832238106Sdes{ 833238106Sdes struct libworker* w = (struct libworker*)q->env->worker; 834238106Sdes struct outbound_entry* e = (struct outbound_entry*)regional_alloc( 835238106Sdes q->region, sizeof(*e)); 836238106Sdes if(!e) 837238106Sdes return NULL; 838238106Sdes e->qstate = q; 839238106Sdes e->qsent = outnet_serviced_query(w->back, qname, 840276605Sdes qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps, 841307729Sdes q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list, 842307729Sdes addr, addrlen, zone, zonelen, libworker_handle_service_reply, 843307729Sdes e, w->back->udp_buff); 844238106Sdes if(!e->qsent) { 845238106Sdes return NULL; 846238106Sdes } 847238106Sdes return e; 848238106Sdes} 849238106Sdes 850238106Sdesint 851238106Sdeslibworker_handle_reply(struct comm_point* c, void* arg, int error, 852238106Sdes struct comm_reply* reply_info) 853238106Sdes{ 854238106Sdes struct module_qstate* q = (struct module_qstate*)arg; 855238106Sdes struct libworker* lw = (struct libworker*)q->env->worker; 856238106Sdes struct outbound_entry e; 857238106Sdes e.qstate = q; 858238106Sdes e.qsent = NULL; 859238106Sdes 860238106Sdes if(error != 0) { 861238106Sdes mesh_report_reply(lw->env->mesh, &e, reply_info, error); 862238106Sdes return 0; 863238106Sdes } 864238106Sdes /* sanity check. */ 865266114Sdes if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer)) 866266114Sdes || LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) != 867238106Sdes LDNS_PACKET_QUERY 868266114Sdes || LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) { 869238106Sdes /* error becomes timeout for the module as if this reply 870238106Sdes * never arrived. */ 871238106Sdes mesh_report_reply(lw->env->mesh, &e, reply_info, 872238106Sdes NETEVENT_TIMEOUT); 873238106Sdes return 0; 874238106Sdes } 875238106Sdes mesh_report_reply(lw->env->mesh, &e, reply_info, NETEVENT_NOERROR); 876238106Sdes return 0; 877238106Sdes} 878238106Sdes 879238106Sdesint 880238106Sdeslibworker_handle_service_reply(struct comm_point* c, void* arg, int error, 881238106Sdes struct comm_reply* reply_info) 882238106Sdes{ 883238106Sdes struct outbound_entry* e = (struct outbound_entry*)arg; 884238106Sdes struct libworker* lw = (struct libworker*)e->qstate->env->worker; 885238106Sdes 886238106Sdes if(error != 0) { 887238106Sdes mesh_report_reply(lw->env->mesh, e, reply_info, error); 888238106Sdes return 0; 889238106Sdes } 890238106Sdes /* sanity check. */ 891266114Sdes if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer)) 892266114Sdes || LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) != 893238106Sdes LDNS_PACKET_QUERY 894266114Sdes || LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) { 895238106Sdes /* error becomes timeout for the module as if this reply 896238106Sdes * never arrived. */ 897238106Sdes mesh_report_reply(lw->env->mesh, e, reply_info, 898238106Sdes NETEVENT_TIMEOUT); 899238106Sdes return 0; 900238106Sdes } 901238106Sdes mesh_report_reply(lw->env->mesh, e, reply_info, NETEVENT_NOERROR); 902238106Sdes return 0; 903238106Sdes} 904238106Sdes 905238106Sdes/* --- fake callbacks for fptr_wlist to work --- */ 906238106Sdesvoid worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), 907238106Sdes uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len), 908238106Sdes int ATTR_UNUSED(error), void* ATTR_UNUSED(arg)) 909238106Sdes{ 910238106Sdes log_assert(0); 911238106Sdes} 912238106Sdes 913238106Sdesint worker_handle_request(struct comm_point* ATTR_UNUSED(c), 914238106Sdes void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 915238106Sdes struct comm_reply* ATTR_UNUSED(repinfo)) 916238106Sdes{ 917238106Sdes log_assert(0); 918238106Sdes return 0; 919238106Sdes} 920238106Sdes 921238106Sdesint worker_handle_reply(struct comm_point* ATTR_UNUSED(c), 922238106Sdes void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 923238106Sdes struct comm_reply* ATTR_UNUSED(reply_info)) 924238106Sdes{ 925238106Sdes log_assert(0); 926238106Sdes return 0; 927238106Sdes} 928238106Sdes 929238106Sdesint worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), 930238106Sdes void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 931238106Sdes struct comm_reply* ATTR_UNUSED(reply_info)) 932238106Sdes{ 933238106Sdes log_assert(0); 934238106Sdes return 0; 935238106Sdes} 936238106Sdes 937238106Sdesint remote_accept_callback(struct comm_point* ATTR_UNUSED(c), 938238106Sdes void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 939238106Sdes struct comm_reply* ATTR_UNUSED(repinfo)) 940238106Sdes{ 941238106Sdes log_assert(0); 942238106Sdes return 0; 943238106Sdes} 944238106Sdes 945238106Sdesint remote_control_callback(struct comm_point* ATTR_UNUSED(c), 946238106Sdes void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), 947238106Sdes struct comm_reply* ATTR_UNUSED(repinfo)) 948238106Sdes{ 949238106Sdes log_assert(0); 950238106Sdes return 0; 951238106Sdes} 952238106Sdes 953238106Sdesvoid worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) 954238106Sdes{ 955238106Sdes log_assert(0); 956238106Sdes} 957238106Sdes 958238106Sdesstruct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname), 959238106Sdes size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), 960238106Sdes uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), 961238106Sdes int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), 962307729Sdes int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list), 963307729Sdes struct sockaddr_storage* ATTR_UNUSED(addr), 964255579Sdes socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), 965255579Sdes size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q)) 966238106Sdes{ 967238106Sdes log_assert(0); 968238106Sdes return 0; 969238106Sdes} 970238106Sdes 971238106Sdesvoid 972238106Sdesworker_alloc_cleanup(void* ATTR_UNUSED(arg)) 973238106Sdes{ 974238106Sdes log_assert(0); 975238106Sdes} 976238106Sdes 977238106Sdesvoid worker_stat_timer_cb(void* ATTR_UNUSED(arg)) 978238106Sdes{ 979238106Sdes log_assert(0); 980238106Sdes} 981238106Sdes 982238106Sdesvoid worker_probe_timer_cb(void* ATTR_UNUSED(arg)) 983238106Sdes{ 984238106Sdes log_assert(0); 985238106Sdes} 986238106Sdes 987238106Sdesvoid worker_start_accept(void* ATTR_UNUSED(arg)) 988238106Sdes{ 989238106Sdes log_assert(0); 990238106Sdes} 991238106Sdes 992238106Sdesvoid worker_stop_accept(void* ATTR_UNUSED(arg)) 993238106Sdes{ 994238106Sdes log_assert(0); 995238106Sdes} 996238106Sdes 997238106Sdesint order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2)) 998238106Sdes{ 999238106Sdes log_assert(0); 1000238106Sdes return 0; 1001238106Sdes} 1002238106Sdes 1003238106Sdesint 1004238106Sdescodeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1005238106Sdes{ 1006238106Sdes log_assert(0); 1007238106Sdes return 0; 1008238106Sdes} 1009238106Sdes 1010238106Sdesint replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) 1011238106Sdes{ 1012238106Sdes log_assert(0); 1013238106Sdes return 0; 1014238106Sdes} 1015238106Sdes 1016238106Sdesvoid remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) 1017238106Sdes{ 1018238106Sdes log_assert(0); 1019238106Sdes} 1020238106Sdes 1021238106Sdes#ifdef UB_ON_WINDOWS 1022238106Sdesvoid 1023238106Sdesworker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* 1024238106Sdes ATTR_UNUSED(arg)) { 1025238106Sdes log_assert(0); 1026238106Sdes} 1027238106Sdes 1028238106Sdesvoid 1029238106Sdeswsvc_cron_cb(void* ATTR_UNUSED(arg)) 1030238106Sdes{ 1031238106Sdes log_assert(0); 1032238106Sdes} 1033238106Sdes#endif /* UB_ON_WINDOWS */ 1034