xref: /freebsd/contrib/unbound/libunbound/libworker.c (revision 7a789145f88a6aceacc59029a0cafe7de7aeefea)
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
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 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 #ifdef HAVE_SSL
46 #include <openssl/ssl.h>
47 #endif
48 #include "libunbound/libworker.h"
49 #include "libunbound/context.h"
50 #include "libunbound/unbound.h"
51 #include "libunbound/worker.h"
52 #include "libunbound/unbound-event.h"
53 #include "services/outside_network.h"
54 #include "services/mesh.h"
55 #include "services/localzone.h"
56 #include "services/cache/rrset.h"
57 #include "services/outbound_list.h"
58 #include "services/authzone.h"
59 #include "util/fptr_wlist.h"
60 #include "util/module.h"
61 #include "util/regional.h"
62 #include "util/random.h"
63 #include "util/config_file.h"
64 #include "util/netevent.h"
65 #include "util/proxy_protocol.h"
66 #include "util/storage/lookup3.h"
67 #include "util/storage/slabhash.h"
68 #include "util/net_help.h"
69 #include "util/data/dname.h"
70 #include "util/data/msgreply.h"
71 #include "util/data/msgencode.h"
72 #include "util/tube.h"
73 #include "sldns/sbuffer.h"
74 #include "sldns/str2wire.h"
75 #ifdef USE_DNSTAP
76 #include "dnstap/dtstream.h"
77 #endif
78 
79 #ifdef HAVE_TARGETCONDITIONALS_H
80 #include <TargetConditionals.h>
81 #endif
82 
83 #if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH)
84 #undef HAVE_FORK
85 #endif
86 
87 /** handle new query command for bg worker */
88 static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
89 
90 /** delete libworker env */
91 static void
libworker_delete_env(struct libworker * w)92 libworker_delete_env(struct libworker* w)
93 {
94 	if(w->env) {
95 		outside_network_quit_prepare(w->back);
96 		mesh_delete(w->env->mesh);
97 		context_release_alloc(w->ctx, w->env->alloc,
98 			!w->is_bg || w->is_bg_thread);
99 		sldns_buffer_free(w->env->scratch_buffer);
100 		regional_destroy(w->env->scratch);
101 		ub_randfree(w->env->rnd);
102 		free(w->env);
103 	}
104 #ifdef HAVE_SSL
105 	SSL_CTX_free(w->sslctx);
106 #endif
107 	outside_network_delete(w->back);
108 	shared_ports_delete(w->shared_ports);
109 }
110 
111 /** delete libworker struct */
112 static void
libworker_delete(struct libworker * w)113 libworker_delete(struct libworker* w)
114 {
115 	if(!w) return;
116 	libworker_delete_env(w);
117 	comm_base_delete(w->base);
118 	free(w);
119 }
120 
121 void
libworker_delete_event(struct libworker * w)122 libworker_delete_event(struct libworker* w)
123 {
124 	if(!w) return;
125 	libworker_delete_env(w);
126 	comm_base_delete_no_base(w->base);
127 	free(w);
128 }
129 
130 /** setup fresh libworker struct */
131 static struct libworker*
libworker_setup(struct ub_ctx * ctx,int is_bg,struct ub_event_base * eb)132 libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
133 {
134 	struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
135 	struct config_file* cfg = ctx->env->cfg;
136 	int* ports;
137 	int numports;
138 	if(!w) return NULL;
139 	w->is_bg = is_bg;
140 	w->ctx = ctx;
141 	w->env = (struct module_env*)malloc(sizeof(*w->env));
142 	if(!w->env) {
143 		free(w);
144 		return NULL;
145 	}
146 	*w->env = *ctx->env;
147 	w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread);
148 	if(!w->env->alloc) {
149 		libworker_delete(w);
150 		return NULL;
151 	}
152 	w->thread_num = w->env->alloc->thread_num;
153 	alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w);
154 	if(!w->is_bg || w->is_bg_thread) {
155 		lock_basic_lock(&ctx->cfglock);
156 	}
157 	w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
158 	w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
159 #ifdef HAVE_SSL
160 	w->sslctx = connect_sslctx_create(NULL, NULL,
161 		cfg->tls_cert_bundle, cfg->tls_win_cert);
162 	if(!w->sslctx) {
163 		/* to make the setup fail after unlock */
164 		sldns_buffer_free(w->env->scratch_buffer);
165 		w->env->scratch_buffer = NULL;
166 	}
167 #endif
168 	if(!w->is_bg || w->is_bg_thread) {
169 		lock_basic_unlock(&ctx->cfglock);
170 	}
171 	if(!w->env->scratch || !w->env->scratch_buffer) {
172 		libworker_delete(w);
173 		return NULL;
174 	}
175 	w->env->worker = (struct worker*)w;
176 	w->env->probe_timer = NULL;
177 	if(!w->is_bg || w->is_bg_thread) {
178 		lock_basic_lock(&ctx->cfglock);
179 	}
180 	if(!(w->env->rnd = ub_initstate(ctx->seed_rnd))) {
181 		if(!w->is_bg || w->is_bg_thread) {
182 			lock_basic_unlock(&ctx->cfglock);
183 		}
184 		libworker_delete(w);
185 		return NULL;
186 	}
187 	if(!w->is_bg || w->is_bg_thread) {
188 		lock_basic_unlock(&ctx->cfglock);
189 	}
190 	if(1) {
191 		/* primitive lockout for threading: if it overwrites another
192 		 * thread it is like wiping the cache (which is likely empty
193 		 * at the start) */
194 		/* note we are holding the ctx lock in normal threaded
195 		 * cases so that is solved properly, it is only for many ctx
196 		 * in different threads that this may clash */
197 		static int done_raninit = 0;
198 		if(!done_raninit) {
199 			done_raninit = 1;
200 			hash_set_raninit((uint32_t)ub_random(w->env->rnd));
201 		}
202 	}
203 
204 	if(eb)
205 		w->base = comm_base_create_event(eb);
206 	else	w->base = comm_base_create(0);
207 	if(!w->base) {
208 		libworker_delete(w);
209 		return NULL;
210 	}
211 	w->env->worker_base = w->base;
212 	if(!w->is_bg || w->is_bg_thread) {
213 		lock_basic_lock(&ctx->cfglock);
214 	}
215 	numports = cfg_condense_ports(cfg, &ports);
216 	if(numports == 0) {
217 		if(!w->is_bg || w->is_bg_thread) {
218 			lock_basic_unlock(&ctx->cfglock);
219 		}
220 		libworker_delete(w);
221 		return NULL;
222 	}
223 	if(!(w->shared_ports = shared_ports_create(cfg->out_ifs,
224 		cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, ports, numports))) {
225 		if(!w->is_bg || w->is_bg_thread) {
226 			lock_basic_unlock(&ctx->cfglock);
227 		}
228 		libworker_delete(w);
229 		return NULL;
230 	}
231 	w->back = outside_network_create(w->base, cfg->msg_buffer_size,
232 		(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
233 		cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
234 		cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
235 		w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
236 		cfg->unwanted_threshold,
237 		cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
238 		cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
239 		cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect,
240 		cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
241 		cfg->tcp_auth_query_timeout, w->shared_ports);
242 	w->env->outnet = w->back;
243 	if(!w->is_bg || w->is_bg_thread) {
244 		lock_basic_unlock(&ctx->cfglock);
245 	}
246 	free(ports);
247 	if(!w->back) {
248 		libworker_delete(w);
249 		return NULL;
250 	}
251 	w->env->mesh = mesh_create(&ctx->mods, w->env);
252 	if(!w->env->mesh) {
253 		libworker_delete(w);
254 		return NULL;
255 	}
256 	w->env->send_query = &libworker_send_query;
257 	w->env->detach_subs = &mesh_detach_subs;
258 	w->env->attach_sub = &mesh_attach_sub;
259 	w->env->add_sub = &mesh_add_sub;
260 	w->env->kill_sub = &mesh_state_delete;
261 	w->env->detect_cycle = &mesh_detect_cycle;
262 	comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
263 	pp_init(&sldns_write_uint16, &sldns_write_uint32);
264 	return w;
265 }
266 
libworker_create_event(struct ub_ctx * ctx,struct ub_event_base * eb)267 struct libworker* libworker_create_event(struct ub_ctx* ctx,
268 	struct ub_event_base* eb)
269 {
270 	return libworker_setup(ctx, 0, eb);
271 }
272 
273 /** handle cancel command for bg worker */
274 static void
handle_cancel(struct libworker * w,uint8_t * buf,uint32_t len)275 handle_cancel(struct libworker* w, uint8_t* buf, uint32_t len)
276 {
277 	struct ctx_query* q;
278 	if(w->is_bg_thread) {
279 		lock_basic_lock(&w->ctx->cfglock);
280 		q = context_deserialize_cancel(w->ctx, buf, len);
281 		lock_basic_unlock(&w->ctx->cfglock);
282 	} else {
283 		q = context_deserialize_cancel(w->ctx, buf, len);
284 	}
285 	if(!q) {
286 		/* probably simply lookup failed, i.e. the message had been
287 		 * processed and answered before the cancel arrived */
288 		return;
289 	}
290 	q->cancelled = 1;
291 	free(buf);
292 }
293 
294 /** do control command coming into bg server */
295 static void
libworker_do_cmd(struct libworker * w,uint8_t * msg,uint32_t len)296 libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
297 {
298 	switch(context_serial_getcmd(msg, len)) {
299 		default:
300 		case UB_LIBCMD_ANSWER:
301 			log_err("unknown command for bg worker %d",
302 				(int)context_serial_getcmd(msg, len));
303 			/* and fall through to quit */
304 			ATTR_FALLTHROUGH
305 			/* fallthrough */
306 		case UB_LIBCMD_QUIT:
307 			free(msg);
308 			comm_base_exit(w->base);
309 			break;
310 		case UB_LIBCMD_NEWQUERY:
311 			handle_newq(w, msg, len);
312 			break;
313 		case UB_LIBCMD_CANCEL:
314 			handle_cancel(w, msg, len);
315 			break;
316 	}
317 }
318 
319 /** handle control command coming into server */
320 void
libworker_handle_control_cmd(struct tube * ATTR_UNUSED (tube),uint8_t * msg,size_t len,int err,void * arg)321 libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
322 	uint8_t* msg, size_t len, int err, void* arg)
323 {
324 	struct libworker* w = (struct libworker*)arg;
325 
326 	if(err != 0) {
327 		free(msg);
328 		/* it is of no use to go on, exit */
329 		comm_base_exit(w->base);
330 		return;
331 	}
332 	libworker_do_cmd(w, msg, len); /* also frees the buf */
333 }
334 
335 /** the background thread func */
336 static void*
libworker_dobg(void * arg)337 libworker_dobg(void* arg)
338 {
339 	/* setup */
340 	uint32_t m;
341 	struct libworker* w = (struct libworker*)arg;
342 	struct ub_ctx* ctx;
343 	if(!w) {
344 		log_err("libunbound bg worker init failed, nomem");
345 		return NULL;
346 	}
347 	ctx = w->ctx;
348 	log_thread_set(&w->thread_num);
349 #ifdef THREADS_DISABLED
350 	/* we are forked */
351 	w->is_bg_thread = 0;
352 	/* close non-used parts of the pipes */
353 	tube_close_write(ctx->qq_pipe);
354 	tube_close_read(ctx->rr_pipe);
355 #endif
356 	if(!tube_setup_bg_listen(ctx->qq_pipe, w->base,
357 		libworker_handle_control_cmd, w)) {
358 		log_err("libunbound bg worker init failed, no bglisten");
359 		return NULL;
360 	}
361 	if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) {
362 		log_err("libunbound bg worker init failed, no bgwrite");
363 		return NULL;
364 	}
365 
366 	/* do the work */
367 	comm_base_dispatch(w->base);
368 
369 	/* cleanup */
370 	m = UB_LIBCMD_QUIT;
371 	w->want_quit = 1;
372 	tube_remove_bg_listen(w->ctx->qq_pipe);
373 	tube_remove_bg_write(w->ctx->rr_pipe);
374 	libworker_delete(w);
375 	(void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m,
376 		(uint32_t)sizeof(m), 0);
377 #ifdef THREADS_DISABLED
378 	/* close pipes from forked process before exit */
379 	tube_close_read(ctx->qq_pipe);
380 	tube_close_write(ctx->rr_pipe);
381 #endif
382 	return NULL;
383 }
384 
libworker_bg(struct ub_ctx * ctx)385 int libworker_bg(struct ub_ctx* ctx)
386 {
387 	struct libworker* w;
388 	/* fork or threadcreate */
389 	lock_basic_lock(&ctx->cfglock);
390 	if(ctx->dothread) {
391 		lock_basic_unlock(&ctx->cfglock);
392 		w = libworker_setup(ctx, 1, NULL);
393 		if(!w) return UB_NOMEM;
394 		w->is_bg_thread = 1;
395 		ctx->thread_worker = w;
396 #ifdef ENABLE_LOCK_CHECKS
397 		w->thread_num = 1; /* for nicer DEBUG checklocks */
398 #endif
399 		ub_thread_create(&ctx->bg_tid, libworker_dobg, w);
400 	} else {
401 		lock_basic_unlock(&ctx->cfglock);
402 #ifndef HAVE_FORK
403 		/* no fork on windows */
404 		return UB_FORKFAIL;
405 #else /* HAVE_FORK */
406 		switch((ctx->bg_pid=fork())) {
407 			case 0:
408 				w = libworker_setup(ctx, 1, NULL);
409 				if(!w) fatal_exit("out of memory");
410 				/* close non-used parts of the pipes */
411 				tube_close_write(ctx->qq_pipe);
412 				tube_close_read(ctx->rr_pipe);
413 				(void)libworker_dobg(w);
414 				exit(0);
415 				break;
416 			case -1:
417 				return UB_FORKFAIL;
418 			default:
419 				/* close non-used parts, so that the worker
420 				 * bgprocess gets 'pipe closed' when the
421 				 * main process exits */
422 				tube_close_read(ctx->qq_pipe);
423 				tube_close_write(ctx->rr_pipe);
424 				break;
425 		}
426 #endif /* HAVE_FORK */
427 	}
428 	return UB_NOERROR;
429 }
430 
431 /** insert canonname */
432 static int
fill_canon(struct ub_result * res,uint8_t * s)433 fill_canon(struct ub_result* res, uint8_t* s)
434 {
435 	char buf[LDNS_MAX_DOMAINLEN];
436 	dname_str(s, buf);
437 	res->canonname = strdup(buf);
438 	return res->canonname != 0;
439 }
440 
441 /** fill data into result */
442 static int
fill_res(struct ub_result * res,struct ub_packed_rrset_key * answer,uint8_t * finalcname,struct query_info * rq,struct reply_info * rep)443 fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer,
444 	uint8_t* finalcname, struct query_info* rq, struct reply_info* rep)
445 {
446 	size_t i;
447 	struct packed_rrset_data* data;
448 	res->ttl = 0;
449 	if(!answer) {
450 		if(finalcname) {
451 			if(!fill_canon(res, finalcname))
452 				return 0; /* out of memory */
453 		}
454 		if(rep->rrset_count != 0)
455 			res->ttl = (int)rep->ttl;
456 		res->data = (char**)calloc(1, sizeof(char*));
457 		if(!res->data)
458 			return 0; /* out of memory */
459 		res->len = (int*)calloc(1, sizeof(int));
460 		if(!res->len) {
461 			free(res->data);
462 			res->data = NULL;
463 			return 0; /* out of memory */
464 		}
465 		return 1;
466 	}
467 	data = (struct packed_rrset_data*)answer->entry.data;
468 	if(query_dname_compare(rq->qname, answer->rk.dname) != 0) {
469 		if(!fill_canon(res, answer->rk.dname))
470 			return 0; /* out of memory */
471 	} else	res->canonname = NULL;
472 	res->data = (char**)calloc(data->count+1, sizeof(char*));
473 	if(!res->data)
474 		return 0; /* out of memory */
475 	res->len = (int*)calloc(data->count+1, sizeof(int));
476 	if(!res->len) {
477 		free(res->data);
478 		res->data = NULL;
479 		return 0; /* out of memory */
480 	}
481 	for(i=0; i<data->count; i++) {
482 		/* remove rdlength from rdata */
483 		res->len[i] = (int)(data->rr_len[i] - 2);
484 		res->data[i] = memdup(data->rr_data[i]+2, (size_t)res->len[i]);
485 		if(!res->data[i]) {
486 			size_t j;
487 			for(j=0; j<i; j++) {
488 				free(res->data[j]);
489 				res->data[j] = NULL;
490 			}
491 			free(res->data);
492 			res->data = NULL;
493 			free(res->len);
494 			res->len = NULL;
495 			return 0; /* out of memory */
496 		}
497 	}
498 	/* ttl for positive answers, from CNAME and answer RRs */
499 	if(data->count != 0) {
500 		size_t j;
501 		res->ttl = (int)data->ttl;
502 		for(j=0; j<rep->an_numrrsets; j++) {
503 			struct packed_rrset_data* d =
504 				(struct packed_rrset_data*)rep->rrsets[j]->
505 				entry.data;
506 			if((int)d->ttl < res->ttl)
507 				res->ttl = (int)d->ttl;
508 		}
509 	}
510 	/* ttl for negative answers */
511 	if(data->count == 0 && rep->rrset_count != 0)
512 		res->ttl = (int)rep->ttl;
513 	res->data[data->count] = NULL;
514 	res->len[data->count] = 0;
515 	return 1;
516 }
517 
518 /** fill result from parsed message, on error fills servfail */
519 void
libworker_enter_result(struct ub_result * res,sldns_buffer * buf,struct regional * temp,enum sec_status msg_security)520 libworker_enter_result(struct ub_result* res, sldns_buffer* buf,
521 	struct regional* temp, enum sec_status msg_security)
522 {
523 	struct query_info rq;
524 	struct reply_info* rep;
525 	res->rcode = LDNS_RCODE_SERVFAIL;
526 	rep = parse_reply_in_temp_region(buf, temp, &rq);
527 	if(!rep) {
528 		log_err("cannot parse buf");
529 		return; /* error parsing buf, or out of memory */
530 	}
531 	if(!fill_res(res, reply_find_answer_rrset(&rq, rep),
532 		reply_find_final_cname_target(&rq, rep), &rq, rep))
533 		return; /* out of memory */
534 	/* rcode, havedata, nxdomain, secure, bogus */
535 	res->rcode = (int)FLAGS_GET_RCODE(rep->flags);
536 	if(res->data && res->data[0])
537 		res->havedata = 1;
538 	if(res->rcode == LDNS_RCODE_NXDOMAIN)
539 		res->nxdomain = 1;
540 	if(msg_security == sec_status_secure)
541 		res->secure = 1;
542 	if(msg_security == sec_status_bogus ||
543 		msg_security == sec_status_secure_sentinel_fail)
544 		res->bogus = 1;
545 }
546 
547 /** fillup fg results */
548 static void
libworker_fillup_fg(struct ctx_query * q,int rcode,sldns_buffer * buf,enum sec_status s,char * why_bogus,int was_ratelimited)549 libworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf,
550 	enum sec_status s, char* why_bogus, int was_ratelimited)
551 {
552 	q->res->was_ratelimited = was_ratelimited;
553 	if(why_bogus)
554 		q->res->why_bogus = strdup(why_bogus);
555 	if(rcode != 0) {
556 		q->res->rcode = rcode;
557 		q->msg_security = s;
558 		return;
559 	}
560 
561 	q->res->rcode = LDNS_RCODE_SERVFAIL;
562 	q->msg_security = sec_status_unchecked;
563 	q->msg = memdup(sldns_buffer_begin(buf), sldns_buffer_limit(buf));
564 	q->msg_len = sldns_buffer_limit(buf);
565 	if(!q->msg) {
566 		return; /* the error is in the rcode */
567 	}
568 
569 	/* canonname and results */
570 	q->msg_security = s;
571 	libworker_enter_result(q->res, buf, q->w->env->scratch, s);
572 }
573 
574 void
libworker_fg_done_cb(void * arg,int rcode,sldns_buffer * buf,enum sec_status s,char * why_bogus,int was_ratelimited)575 libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s,
576 	char* why_bogus, int was_ratelimited)
577 {
578 	struct ctx_query* q = (struct ctx_query*)arg;
579 	/* fg query is done; exit comm base */
580 	comm_base_exit(q->w->base);
581 
582 	libworker_fillup_fg(q, rcode, buf, s, why_bogus, was_ratelimited);
583 }
584 
585 /** setup qinfo and edns */
586 static int
setup_qinfo_edns(struct libworker * w,struct ctx_query * q,struct query_info * qinfo,struct edns_data * edns)587 setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
588 	struct query_info* qinfo, struct edns_data* edns)
589 {
590 	qinfo->qtype = (uint16_t)q->res->qtype;
591 	qinfo->qclass = (uint16_t)q->res->qclass;
592 	qinfo->local_alias = NULL;
593 	qinfo->qname = sldns_str2wire_dname(q->res->qname, &qinfo->qname_len);
594 	if(!qinfo->qname) {
595 		return 0;
596 	}
597 	edns->edns_present = 1;
598 	edns->ext_rcode = 0;
599 	edns->edns_version = 0;
600 	edns->bits = EDNS_DO;
601 	edns->opt_list_in = NULL;
602 	edns->opt_list_out = NULL;
603 	edns->opt_list_inplace_cb_out = NULL;
604 	edns->padding_block_size = 0;
605 	edns->cookie_present = 0;
606 	edns->cookie_valid = 0;
607 	if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
608 		edns->udp_size = (uint16_t)sldns_buffer_capacity(
609 			w->back->udp_buff);
610 	else	edns->udp_size = 65535;
611 	return 1;
612 }
613 
libworker_fg(struct ub_ctx * ctx,struct ctx_query * q)614 int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
615 {
616 	struct libworker* w = libworker_setup(ctx, 0, NULL);
617 	uint16_t qflags, qid;
618 	struct query_info qinfo;
619 	struct edns_data edns;
620 	if(!w)
621 		return UB_INITFAIL;
622 	if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
623 		libworker_delete(w);
624 		return UB_SYNTAX;
625 	}
626 	qid = 0;
627 	qflags = BIT_RD;
628 	q->w = w;
629 	/* see if there is a fixed answer */
630 	sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
631 	sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
632 	if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns,
633 		w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
634 		NULL, 0, NULL, 0, NULL)) {
635 		regional_free_all(w->env->scratch);
636 		libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
637 			w->back->udp_buff, sec_status_insecure, NULL, 0);
638 		libworker_delete(w);
639 		free(qinfo.qname);
640 		return UB_NOERROR;
641 	}
642 	if(ctx->env->auth_zones && auth_zones_downstream_answer(
643 		ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
644 		w->back->udp_buff, w->env->scratch)) {
645 		regional_free_all(w->env->scratch);
646 		libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
647 			w->back->udp_buff, sec_status_insecure, NULL, 0);
648 		libworker_delete(w);
649 		free(qinfo.qname);
650 		return UB_NOERROR;
651 	}
652 	/* process new query */
653 	if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
654 		w->back->udp_buff, qid, libworker_fg_done_cb, q, 0,
655 		&q->unique_info)) {
656 		free(qinfo.qname);
657 		return UB_NOMEM;
658 	}
659 	free(qinfo.qname);
660 
661 	/* wait for reply */
662 	comm_base_dispatch(w->base);
663 
664 	libworker_delete(w);
665 	return UB_NOERROR;
666 }
667 
668 void
libworker_event_done_cb(void * arg,int rcode,sldns_buffer * buf,enum sec_status s,char * why_bogus,int was_ratelimited)669 libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf,
670 	enum sec_status s, char* why_bogus, int was_ratelimited)
671 {
672 	struct ctx_query* q = (struct ctx_query*)arg;
673 	ub_event_callback_type cb = q->cb_event;
674 	void* cb_arg = q->cb_arg;
675 	int cancelled = q->cancelled;
676 
677 	/* delete it now */
678 	struct ub_ctx* ctx = q->w->ctx;
679 	lock_basic_lock(&ctx->cfglock);
680 	(void)rbtree_delete(&ctx->queries, q->node.key);
681 	ctx->num_async--;
682 	context_query_delete(q);
683 	lock_basic_unlock(&ctx->cfglock);
684 
685 	if(!cancelled) {
686 		/* call callback */
687 		int sec = 0;
688 		if(s == sec_status_bogus)
689 			sec = 1;
690 		else if(s == sec_status_secure)
691 			sec = 2;
692 		(*cb)(cb_arg, rcode, (buf?(void*)sldns_buffer_begin(buf):NULL),
693 			(buf?(int)sldns_buffer_limit(buf):0), sec, why_bogus, was_ratelimited);
694 	}
695 }
696 
libworker_attach_mesh(struct ub_ctx * ctx,struct ctx_query * q,int * async_id)697 int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
698 	int* async_id)
699 {
700 	struct libworker* w = ctx->event_worker;
701 	uint16_t qflags, qid;
702 	struct query_info qinfo;
703 	struct edns_data edns;
704 	if(!w)
705 		return UB_INITFAIL;
706 	if(!setup_qinfo_edns(w, q, &qinfo, &edns))
707 		return UB_SYNTAX;
708 	qid = 0;
709 	qflags = BIT_RD;
710 	q->w = w;
711 	/* see if there is a fixed answer */
712 	sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
713 	sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
714 	if(local_zones_answer(ctx->local_zones, w->env, &qinfo, &edns,
715 		w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
716 		NULL, 0, NULL, 0, NULL)) {
717 		regional_free_all(w->env->scratch);
718 		free(qinfo.qname);
719 		libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
720 			w->back->udp_buff, sec_status_insecure, NULL, 0);
721 		return UB_NOERROR;
722 	}
723 	if(ctx->env->auth_zones && auth_zones_downstream_answer(
724 		ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
725 		w->back->udp_buff, w->env->scratch)) {
726 		regional_free_all(w->env->scratch);
727 		free(qinfo.qname);
728 		libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
729 			w->back->udp_buff, sec_status_insecure, NULL, 0);
730 		return UB_NOERROR;
731 	}
732 	/* process new query */
733 	if(async_id)
734 		*async_id = q->querynum;
735 	if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
736 		w->back->udp_buff, qid, libworker_event_done_cb, q, 0,
737 		&q->unique_info)) {
738 		free(qinfo.qname);
739 		return UB_NOMEM;
740 	}
741 	free(qinfo.qname);
742 	return UB_NOERROR;
743 }
744 
745 /** add result to the bg worker result queue */
746 static void
add_bg_result(struct libworker * w,struct ctx_query * q,sldns_buffer * pkt,int err,char * reason,int was_ratelimited)747 add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt,
748 	int err, char* reason, int was_ratelimited)
749 {
750 	uint8_t* msg = NULL;
751 	uint32_t len = 0;
752 
753 	if(w->want_quit) {
754 		context_query_delete(q);
755 		return;
756 	}
757 	/* serialize and delete unneeded q */
758 	if(w->is_bg_thread) {
759 		lock_basic_lock(&w->ctx->cfglock);
760 		if(reason)
761 			q->res->why_bogus = strdup(reason);
762 		q->res->was_ratelimited = was_ratelimited;
763 		if(pkt) {
764 			q->msg_len = sldns_buffer_remaining(pkt);
765 			q->msg = memdup(sldns_buffer_begin(pkt), q->msg_len);
766 			if(!q->msg) {
767 				msg = context_serialize_answer(q, UB_NOMEM, NULL, &len);
768 			} else {
769 				msg = context_serialize_answer(q, err, NULL, &len);
770 			}
771 		} else {
772 			msg = context_serialize_answer(q, err, NULL, &len);
773 		}
774 		lock_basic_unlock(&w->ctx->cfglock);
775 	} else {
776 		if(reason)
777 			q->res->why_bogus = strdup(reason);
778 		q->res->was_ratelimited = was_ratelimited;
779 		msg = context_serialize_answer(q, err, pkt, &len);
780 		(void)rbtree_delete(&w->ctx->queries, q->node.key);
781 		w->ctx->num_async--;
782 		context_query_delete(q);
783 	}
784 
785 	if(!msg) {
786 		log_err("out of memory for async answer");
787 		return;
788 	}
789 	if(!tube_queue_item(w->ctx->rr_pipe, msg, len)) {
790 		log_err("out of memory for async answer");
791 		return;
792 	}
793 }
794 
795 void
libworker_bg_done_cb(void * arg,int rcode,sldns_buffer * buf,enum sec_status s,char * why_bogus,int was_ratelimited)796 libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, enum sec_status s,
797 	char* why_bogus, int was_ratelimited)
798 {
799 	struct ctx_query* q = (struct ctx_query*)arg;
800 
801 	if(q->cancelled || q->w->back->want_to_quit) {
802 		if(q->w->is_bg_thread) {
803 			/* delete it now */
804 			struct ub_ctx* ctx = q->w->ctx;
805 			lock_basic_lock(&ctx->cfglock);
806 			(void)rbtree_delete(&ctx->queries, q->node.key);
807 			ctx->num_async--;
808 			context_query_delete(q);
809 			lock_basic_unlock(&ctx->cfglock);
810 		}
811 		/* cancelled, do not give answer */
812 		return;
813 	}
814 	q->msg_security = s;
815 	if(!buf) {
816 		buf = q->w->env->scratch_buffer;
817 	}
818 	if(rcode != 0) {
819 		error_encode(buf, rcode, NULL, 0, BIT_RD, NULL);
820 	}
821 	add_bg_result(q->w, q, buf, UB_NOERROR, why_bogus, was_ratelimited);
822 }
823 
824 
825 /** handle new query command for bg worker */
826 static void
handle_newq(struct libworker * w,uint8_t * buf,uint32_t len)827 handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
828 {
829 	uint16_t qflags, qid;
830 	struct query_info qinfo;
831 	struct edns_data edns;
832 	struct ctx_query* q;
833 	if(w->is_bg_thread) {
834 		lock_basic_lock(&w->ctx->cfglock);
835 		q = context_lookup_new_query(w->ctx, buf, len);
836 		lock_basic_unlock(&w->ctx->cfglock);
837 	} else {
838 		q = context_deserialize_new_query(w->ctx, buf, len);
839 	}
840 	free(buf);
841 	if(!q) {
842 		log_err("failed to deserialize newq");
843 		return;
844 	}
845 	if(!setup_qinfo_edns(w, q, &qinfo, &edns)) {
846 		add_bg_result(w, q, NULL, UB_SYNTAX, NULL, 0);
847 		return;
848 	}
849 	qid = 0;
850 	qflags = BIT_RD;
851 	/* see if there is a fixed answer */
852 	sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
853 	sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
854 	if(local_zones_answer(w->ctx->local_zones, w->env, &qinfo, &edns,
855 		w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
856 		NULL, 0, NULL, 0, NULL)) {
857 		regional_free_all(w->env->scratch);
858 		q->msg_security = sec_status_insecure;
859 		add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);
860 		free(qinfo.qname);
861 		return;
862 	}
863 	if(w->ctx->env->auth_zones && auth_zones_downstream_answer(
864 		w->ctx->env->auth_zones, w->env, &qinfo, &edns, NULL,
865 		w->back->udp_buff, w->env->scratch)) {
866 		regional_free_all(w->env->scratch);
867 		q->msg_security = sec_status_insecure;
868 		add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL, 0);
869 		free(qinfo.qname);
870 		return;
871 	}
872 	q->w = w;
873 	/* process new query */
874 	if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
875 		w->back->udp_buff, qid, libworker_bg_done_cb, q, 0,
876 		&q->unique_info)) {
877 		add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
878 	}
879 	free(qinfo.qname);
880 }
881 
libworker_alloc_cleanup(void * arg)882 void libworker_alloc_cleanup(void* arg)
883 {
884 	struct libworker* w = (struct libworker*)arg;
885 	slabhash_clear(&w->env->rrset_cache->table);
886         slabhash_clear(w->env->msg_cache);
887 }
888 
libworker_send_query(struct query_info * qinfo,uint16_t flags,int dnssec,int want_dnssec,int nocaps,int check_ratelimit,struct sockaddr_storage * addr,socklen_t addrlen,uint8_t * zone,size_t zonelen,int tcp_upstream,int ssl_upstream,char * tls_auth_name,struct module_qstate * q,int * was_ratelimited,int * ratelimit_incremented)889 struct outbound_entry* libworker_send_query(struct query_info* qinfo,
890 	uint16_t flags, int dnssec, int want_dnssec, int nocaps,
891 	int check_ratelimit,
892 	struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
893 	size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
894 	struct module_qstate* q, int* was_ratelimited,
895 	int* ratelimit_incremented)
896 {
897 	struct libworker* w = (struct libworker*)q->env->worker;
898 	struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
899 		q->region, sizeof(*e));
900 	if(!e)
901 		return NULL;
902 	e->qstate = q;
903 	e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
904 		want_dnssec, nocaps, check_ratelimit, tcp_upstream, ssl_upstream,
905 		tls_auth_name, addr, addrlen, zone, zonelen, q,
906 		libworker_handle_service_reply, e, w->back->udp_buff, q->env,
907 		was_ratelimited, ratelimit_incremented);
908 	if(!e->qsent) {
909 		return NULL;
910 	}
911 	return e;
912 }
913 
914 int
libworker_handle_service_reply(struct comm_point * c,void * arg,int error,struct comm_reply * reply_info)915 libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
916         struct comm_reply* reply_info)
917 {
918 	struct outbound_entry* e = (struct outbound_entry*)arg;
919 	struct libworker* lw = (struct libworker*)e->qstate->env->worker;
920 
921 	if(error != 0) {
922 		mesh_report_reply(lw->env->mesh, e, reply_info, error);
923 		return 0;
924 	}
925 	/* sanity check. */
926 	if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer))
927 		|| LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) !=
928 			LDNS_PACKET_QUERY
929 		|| LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) {
930 		/* error becomes timeout for the module as if this reply
931 		 * never arrived. */
932 		mesh_report_reply(lw->env->mesh, e, reply_info,
933 			NETEVENT_TIMEOUT);
934 		return 0;
935 	}
936 	mesh_report_reply(lw->env->mesh,  e, reply_info, NETEVENT_NOERROR);
937 	return 0;
938 }
939 
940 /* --- fake callbacks for fptr_wlist to work --- */
worker_handle_control_cmd(struct tube * ATTR_UNUSED (tube),uint8_t * ATTR_UNUSED (buffer),size_t ATTR_UNUSED (len),int ATTR_UNUSED (error),void * ATTR_UNUSED (arg))941 void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
942 	uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
943 	int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
944 {
945 	log_assert(0);
946 }
947 
worker_handle_request(struct comm_point * ATTR_UNUSED (c),void * ATTR_UNUSED (arg),int ATTR_UNUSED (error),struct comm_reply * ATTR_UNUSED (repinfo))948 int worker_handle_request(struct comm_point* ATTR_UNUSED(c),
949 	void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
950         struct comm_reply* ATTR_UNUSED(repinfo))
951 {
952 	log_assert(0);
953 	return 0;
954 }
955 
worker_handle_service_reply(struct comm_point * ATTR_UNUSED (c),void * ATTR_UNUSED (arg),int ATTR_UNUSED (error),struct comm_reply * ATTR_UNUSED (reply_info))956 int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
957 	void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
958         struct comm_reply* ATTR_UNUSED(reply_info))
959 {
960 	log_assert(0);
961 	return 0;
962 }
963 
remote_accept_callback(struct comm_point * ATTR_UNUSED (c),void * ATTR_UNUSED (arg),int ATTR_UNUSED (error),struct comm_reply * ATTR_UNUSED (repinfo))964 int remote_accept_callback(struct comm_point* ATTR_UNUSED(c),
965 	void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
966         struct comm_reply* ATTR_UNUSED(repinfo))
967 {
968 	log_assert(0);
969 	return 0;
970 }
971 
remote_control_callback(struct comm_point * ATTR_UNUSED (c),void * ATTR_UNUSED (arg),int ATTR_UNUSED (error),struct comm_reply * ATTR_UNUSED (repinfo))972 int remote_control_callback(struct comm_point* ATTR_UNUSED(c),
973 	void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
974         struct comm_reply* ATTR_UNUSED(repinfo))
975 {
976 	log_assert(0);
977 	return 0;
978 }
979 
worker_sighandler(int ATTR_UNUSED (sig),void * ATTR_UNUSED (arg))980 void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
981 {
982 	log_assert(0);
983 }
984 
worker_send_query(struct query_info * ATTR_UNUSED (qinfo),uint16_t ATTR_UNUSED (flags),int ATTR_UNUSED (dnssec),int ATTR_UNUSED (want_dnssec),int ATTR_UNUSED (nocaps),int ATTR_UNUSED (check_ratelimit),struct sockaddr_storage * ATTR_UNUSED (addr),socklen_t ATTR_UNUSED (addrlen),uint8_t * ATTR_UNUSED (zone),size_t ATTR_UNUSED (zonelen),int ATTR_UNUSED (tcp_upstream),int ATTR_UNUSED (ssl_upstream),char * ATTR_UNUSED (tls_auth_name),struct module_qstate * ATTR_UNUSED (q),int * ATTR_UNUSED (was_ratelimited),int * ATTR_UNUSED (ratelimit_incremented))985 struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
986 	uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
987 	int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
988 	int ATTR_UNUSED(check_ratelimit),
989 	struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
990 	uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
991 	int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
992 	struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
993 	int* ATTR_UNUSED(ratelimit_incremented))
994 {
995 	log_assert(0);
996 	return 0;
997 }
998 
999 void
worker_alloc_cleanup(void * ATTR_UNUSED (arg))1000 worker_alloc_cleanup(void* ATTR_UNUSED(arg))
1001 {
1002 	log_assert(0);
1003 }
1004 
worker_stat_timer_cb(void * ATTR_UNUSED (arg))1005 void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
1006 {
1007 	log_assert(0);
1008 }
1009 
worker_probe_timer_cb(void * ATTR_UNUSED (arg))1010 void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
1011 {
1012 	log_assert(0);
1013 }
1014 
worker_start_accept(void * ATTR_UNUSED (arg))1015 void worker_start_accept(void* ATTR_UNUSED(arg))
1016 {
1017 	log_assert(0);
1018 }
1019 
worker_stop_accept(void * ATTR_UNUSED (arg))1020 void worker_stop_accept(void* ATTR_UNUSED(arg))
1021 {
1022 	log_assert(0);
1023 }
1024 
order_lock_cmp(const void * ATTR_UNUSED (e1),const void * ATTR_UNUSED (e2))1025 int order_lock_cmp(const void* ATTR_UNUSED(e1), const void* ATTR_UNUSED(e2))
1026 {
1027 	log_assert(0);
1028 	return 0;
1029 }
1030 
1031 int
codeline_cmp(const void * ATTR_UNUSED (a),const void * ATTR_UNUSED (b))1032 codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
1033 {
1034 	log_assert(0);
1035 	return 0;
1036 }
1037 
replay_var_compare(const void * ATTR_UNUSED (a),const void * ATTR_UNUSED (b))1038 int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
1039 {
1040         log_assert(0);
1041         return 0;
1042 }
1043 
remote_get_opt_ssl(char * ATTR_UNUSED (str),void * ATTR_UNUSED (arg))1044 void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
1045 {
1046         log_assert(0);
1047 }
1048 
1049 #ifdef UB_ON_WINDOWS
1050 void
worker_win_stop_cb(int ATTR_UNUSED (fd),short ATTR_UNUSED (ev),void * ATTR_UNUSED (arg))1051 worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
1052         ATTR_UNUSED(arg)) {
1053         log_assert(0);
1054 }
1055 
1056 void
wsvc_cron_cb(void * ATTR_UNUSED (arg))1057 wsvc_cron_cb(void* ATTR_UNUSED(arg))
1058 {
1059         log_assert(0);
1060 }
1061 #endif /* UB_ON_WINDOWS */
1062 
1063 #ifdef USE_DNSTAP
dtio_tap_callback(int ATTR_UNUSED (fd),short ATTR_UNUSED (ev),void * ATTR_UNUSED (arg))1064 void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
1065 	void* ATTR_UNUSED(arg))
1066 {
1067 	log_assert(0);
1068 }
1069 #endif
1070 
1071 #ifdef USE_DNSTAP
dtio_mainfdcallback(int ATTR_UNUSED (fd),short ATTR_UNUSED (ev),void * ATTR_UNUSED (arg))1072 void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
1073 	void* ATTR_UNUSED(arg))
1074 {
1075 	log_assert(0);
1076 }
1077 #endif
1078 
fast_reload_service_cb(int ATTR_UNUSED (fd),short ATTR_UNUSED (ev),void * ATTR_UNUSED (arg))1079 void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
1080 	void* ATTR_UNUSED(arg))
1081 {
1082 	log_assert(0);
1083 }
1084 
fast_reload_client_callback(struct comm_point * ATTR_UNUSED (c),void * ATTR_UNUSED (arg),int ATTR_UNUSED (error),struct comm_reply * ATTR_UNUSED (repinfo))1085 int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
1086 	void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
1087         struct comm_reply* ATTR_UNUSED(repinfo))
1088 {
1089 	log_assert(0);
1090 	return 0;
1091 }
1092 
1093 #ifdef HAVE_NGTCP2
doq_client_event_cb(int ATTR_UNUSED (fd),short ATTR_UNUSED (ev),void * ATTR_UNUSED (arg))1094 void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
1095 	void* ATTR_UNUSED(arg))
1096 {
1097 	log_assert(0);
1098 }
1099 #endif
1100 
1101 #ifdef HAVE_NGTCP2
doq_client_timer_cb(int ATTR_UNUSED (fd),short ATTR_UNUSED (ev),void * ATTR_UNUSED (arg))1102 void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
1103 	void* ATTR_UNUSED(arg))
1104 {
1105 	log_assert(0);
1106 }
1107 #endif
1108