1 /*
2  * dnstap/dnstap_collector.c -- nsd collector process for dnstap information
3  *
4  * Copyright (c) 2018, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #include "config.h"
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #ifndef USE_MINI_EVENT
17 #  ifdef HAVE_EVENT_H
18 #    include <event.h>
19 #  else
20 #    include <event2/event.h>
21 #    include "event2/event_struct.h"
22 #    include "event2/event_compat.h"
23 #  endif
24 #else
25 #  include "mini_event.h"
26 #endif
27 #include "dnstap/dnstap_collector.h"
28 #include "dnstap/dnstap.h"
29 #include "util.h"
30 #include "nsd.h"
31 #include "region-allocator.h"
32 #include "buffer.h"
33 #include "namedb.h"
34 #include "options.h"
35 #include "remote.h"
36 
37 #include "udb.h"
38 #include "rrl.h"
39 
dt_collector_create(struct nsd * nsd)40 struct dt_collector* dt_collector_create(struct nsd* nsd)
41 {
42 	int i, sv[2];
43 	struct dt_collector* dt_col = (struct dt_collector*)xalloc_zero(
44 		sizeof(*dt_col));
45 	dt_col->count = nsd->child_count * 2;
46 	dt_col->dt_env = NULL;
47 	dt_col->region = region_create(xalloc, free);
48 	dt_col->send_buffer = buffer_create(dt_col->region,
49 		/* msglen + is_response + addrlen + is_tcp + packetlen + packet + zonelen + zone + spare + local_addr + addr */
50 		4+1+4+1+4+TCP_MAX_MESSAGE_LEN+4+MAXHOSTNAMELEN + 32 +
51 #ifdef INET6
52 		sizeof(struct sockaddr_storage) + sizeof(struct sockaddr_storage)
53 #else
54 		sizeof(struct sockaddr_in) + sizeof(struct sockaddr_in)
55 #endif
56 		);
57 
58 	/* open communication channels in struct nsd */
59 	nsd->dt_collector_fd_send = (int*)xalloc_array_zero(dt_col->count,
60 		sizeof(int));
61 	nsd->dt_collector_fd_recv = (int*)xalloc_array_zero(dt_col->count,
62 		sizeof(int));
63 	for(i=0; i<dt_col->count; i++) {
64 		int sv[2];
65 		int bufsz = buffer_capacity(dt_col->send_buffer);
66 		sv[0] = -1; /* For receiving by parent (dnstap-collector) */
67 		sv[1] = -1; /* For sending   by child  (server childs) */
68 		if(socketpair(AF_UNIX, SOCK_DGRAM
69 #ifdef SOCK_NONBLOCK
70 			| SOCK_NONBLOCK
71 #endif
72 			, 0, sv) < 0) {
73 			error("dnstap_collector: cannot create communication channel: %s",
74 				strerror(errno));
75 		}
76 #ifndef SOCK_NONBLOCK
77 		if (fcntl(sv[0], F_SETFL, O_NONBLOCK) == -1) {
78 			log_msg(LOG_ERR, "dnstap_collector receive fd fcntl "
79 				"failed: %s", strerror(errno));
80 		}
81 		if (fcntl(sv[1], F_SETFL, O_NONBLOCK) == -1) {
82 			log_msg(LOG_ERR, "dnstap_collector send fd fcntl "
83 				"failed: %s", strerror(errno));
84 		}
85 #endif
86 		if(setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &bufsz, sizeof(bufsz))) {
87 			log_msg(LOG_ERR, "setting dnstap_collector "
88 				"receive buffer size failed: %s", strerror(errno));
89 		}
90 		if(setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &bufsz, sizeof(bufsz))) {
91 			log_msg(LOG_ERR, "setting dnstap_collector "
92 				"send buffer size failed: %s", strerror(errno));
93 		}
94 		nsd->dt_collector_fd_recv[i] = sv[0];
95 		nsd->dt_collector_fd_send[i] = sv[1];
96 	}
97 	nsd->dt_collector_fd_swap = nsd->dt_collector_fd_send + nsd->child_count;
98 
99 	/* open socketpair */
100 	if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
101 		error("dnstap_collector: cannot create socketpair: %s",
102 			strerror(errno));
103 	}
104 	if(fcntl(sv[0], F_SETFL, O_NONBLOCK) == -1) {
105 		log_msg(LOG_ERR, "fcntl failed: %s", strerror(errno));
106 	}
107 	if(fcntl(sv[1], F_SETFL, O_NONBLOCK) == -1) {
108 		log_msg(LOG_ERR, "fcntl failed: %s", strerror(errno));
109 	}
110 	dt_col->cmd_socket_dt = sv[0];
111 	dt_col->cmd_socket_nsd = sv[1];
112 
113 	return dt_col;
114 }
115 
dt_collector_destroy(struct dt_collector * dt_col,struct nsd * nsd)116 void dt_collector_destroy(struct dt_collector* dt_col, struct nsd* nsd)
117 {
118 	if(!dt_col) return;
119 	free(nsd->dt_collector_fd_recv);
120 	nsd->dt_collector_fd_recv = NULL;
121 	if (nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap)
122 		free(nsd->dt_collector_fd_send);
123 	else
124 		free(nsd->dt_collector_fd_swap);
125 	nsd->dt_collector_fd_send = NULL;
126 	nsd->dt_collector_fd_swap = NULL;
127 	region_destroy(dt_col->region);
128 	free(dt_col);
129 }
130 
dt_collector_close(struct dt_collector * dt_col,struct nsd * nsd)131 void dt_collector_close(struct dt_collector* dt_col, struct nsd* nsd)
132 {
133 	int i, *fd_send;
134 	if(!dt_col) return;
135 	if(dt_col->cmd_socket_dt != -1) {
136 		close(dt_col->cmd_socket_dt);
137 		dt_col->cmd_socket_dt = -1;
138 	}
139 	if(dt_col->cmd_socket_nsd != -1) {
140 		close(dt_col->cmd_socket_nsd);
141 		dt_col->cmd_socket_nsd = -1;
142 	}
143 	fd_send = nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap
144 	        ? nsd->dt_collector_fd_send : nsd->dt_collector_fd_swap;
145 	for(i=0; i<dt_col->count; i++) {
146 		if(nsd->dt_collector_fd_recv[i] != -1) {
147 			close(nsd->dt_collector_fd_recv[i]);
148 			nsd->dt_collector_fd_recv[i] = -1;
149 		}
150 		if(fd_send[i] != -1) {
151 			close(fd_send[i]);
152 			fd_send[i] = -1;
153 		}
154 	}
155 }
156 
157 /* handle command from nsd to dt collector.
158  * mostly, check for fd closed, this means we have to exit */
159 void
dt_handle_cmd_from_nsd(int ATTR_UNUSED (fd),short event,void * arg)160 dt_handle_cmd_from_nsd(int ATTR_UNUSED(fd), short event, void* arg)
161 {
162 	struct dt_collector* dt_col = (struct dt_collector*)arg;
163 	if((event&EV_READ) != 0) {
164 		event_base_loopexit(dt_col->event_base, NULL);
165 	}
166 }
167 
168 /* receive data from fd into buffer, 1 when message received, -1 on error */
recv_into_buffer(int fd,struct buffer * buf)169 static int recv_into_buffer(int fd, struct buffer* buf)
170 {
171 	size_t msglen;
172 	ssize_t r;
173 
174 	assert(buffer_position(buf) == 0);
175 	r = recv(fd, buffer_current(buf), buffer_capacity(buf), MSG_DONTWAIT);
176 	if(r == -1) {
177 		if(errno == EAGAIN || errno == EINTR || errno == EMSGSIZE) {
178 			/* continue to receive a message later */
179 			return 0;
180 		}
181 		log_msg(LOG_ERR, "dnstap collector: receive failed: %s",
182 			strerror(errno));
183 		return -1;
184 	}
185 	if(r == 0) {
186 		/* Remote end closed the connection? */
187 		log_msg(LOG_ERR, "dnstap collector: remote closed connection");
188 		return -1;
189 	}
190 	assert(r > 4);
191 	msglen = buffer_read_u32_at(buf, 0);
192 	if(msglen != (size_t)(r - 4)) {
193 		/* Is this still possible now the communication channel is of
194 		 * type SOCK_DGRAM? I think not, but better safe than sorry. */
195 		log_msg(LOG_ERR, "dnstap collector: out of sync (msglen: %u)",
196 			(unsigned int) msglen);
197 		return 0;
198 	}
199 	buffer_skip(buf, r);
200 	buffer_flip(buf);
201 	return 1;
202 }
203 
204 /* submit the content of the buffer received to dnstap */
205 static void
dt_submit_content(struct dt_env * dt_env,struct buffer * buf)206 dt_submit_content(struct dt_env* dt_env, struct buffer* buf)
207 {
208 	uint8_t is_response, is_tcp;
209 #ifdef INET6
210 	struct sockaddr_storage local_addr, addr;
211 #else
212 	struct sockaddr_in local_addr, addr;
213 #endif
214 	socklen_t addrlen;
215 	size_t pktlen;
216 	uint8_t* data;
217 	size_t zonelen;
218 	uint8_t* zone;
219 
220 	/* parse content from buffer */
221 	if(!buffer_available(buf, 4+1+4)) return;
222 	buffer_skip(buf, 4); /* skip msglen */
223 	is_response = buffer_read_u8(buf);
224 	addrlen = buffer_read_u32(buf);
225 	if(addrlen > sizeof(local_addr) || addrlen > sizeof(addr)) return;
226 	if(!buffer_available(buf, 2*addrlen)) return;
227 	buffer_read(buf, &local_addr, addrlen);
228 	buffer_read(buf, &addr, addrlen);
229 	if(!buffer_available(buf, 1+4)) return;
230 	is_tcp = buffer_read_u8(buf);
231 	pktlen = buffer_read_u32(buf);
232 	if(!buffer_available(buf, pktlen)) return;
233 	data = buffer_current(buf);
234 	buffer_skip(buf, pktlen);
235 	if(!buffer_available(buf, 4)) return;
236 	zonelen = buffer_read_u32(buf);
237 	if(zonelen == 0) {
238 		zone = NULL;
239 	} else {
240 		if(zonelen > MAXDOMAINLEN) return;
241 		if(!buffer_available(buf, zonelen)) return;
242 		zone = buffer_current(buf);
243 		buffer_skip(buf, zonelen);
244 	}
245 
246 	/* submit it */
247 	if(is_response) {
248 		dt_msg_send_auth_response(dt_env, &local_addr, &addr, is_tcp, zone,
249 			zonelen, data, pktlen);
250 	} else {
251 		dt_msg_send_auth_query(dt_env, &local_addr, &addr, is_tcp, zone,
252 			zonelen, data, pktlen);
253 	}
254 }
255 
256 /* handle input from worker for dnstap */
257 void
dt_handle_input(int fd,short event,void * arg)258 dt_handle_input(int fd, short event, void* arg)
259 {
260 	struct dt_collector_input* dt_input = (struct dt_collector_input*)arg;
261 	if((event&EV_READ) != 0) {
262 		/* receive */
263 		int r = recv_into_buffer(fd, dt_input->buffer);
264 		if(r == 0)
265 			return;
266 		else if(r < 0) {
267 			event_base_loopexit(dt_input->dt_collector->event_base, NULL);
268 			return;
269 		}
270 		/* once data is complete, send it to dnstap */
271 		VERBOSITY(4, (LOG_INFO, "dnstap collector: received msg len %d",
272 			(int)buffer_remaining(dt_input->buffer)));
273 		if(dt_input->dt_collector->dt_env) {
274 			dt_submit_content(dt_input->dt_collector->dt_env,
275 				dt_input->buffer);
276 		}
277 
278 		/* clear buffer for next message */
279 		buffer_clear(dt_input->buffer);
280 	}
281 }
282 
283 /* init dnstap */
dt_init_dnstap(struct dt_collector * dt_col,struct nsd * nsd)284 static void dt_init_dnstap(struct dt_collector* dt_col, struct nsd* nsd)
285 {
286 	int num_workers = 1;
287 #ifdef HAVE_CHROOT
288 	if(nsd->chrootdir && nsd->chrootdir[0]) {
289 		int l = strlen(nsd->chrootdir)-1; /* ends in trailing slash */
290 		if (nsd->options->dnstap_socket_path &&
291 			nsd->options->dnstap_socket_path[0] == '/' &&
292 			strncmp(nsd->options->dnstap_socket_path,
293 				nsd->chrootdir, l) == 0)
294 			nsd->options->dnstap_socket_path += l;
295 	}
296 #endif
297 	dt_col->dt_env = dt_create(nsd->options->dnstap_socket_path,
298 		nsd->options->dnstap_ip, num_workers, nsd->options->dnstap_tls,
299 		nsd->options->dnstap_tls_server_name,
300 		nsd->options->dnstap_tls_cert_bundle,
301 		nsd->options->dnstap_tls_client_key_file,
302 		nsd->options->dnstap_tls_client_cert_file);
303 	if(!dt_col->dt_env) {
304 		log_msg(LOG_ERR, "could not create dnstap env");
305 		return;
306 	}
307 	dt_apply_cfg(dt_col->dt_env, nsd->options);
308 	dt_init(dt_col->dt_env);
309 }
310 
311 /* cleanup dt collector process for exit */
dt_collector_cleanup(struct dt_collector * dt_col,struct nsd * nsd)312 static void dt_collector_cleanup(struct dt_collector* dt_col, struct nsd* nsd)
313 {
314 	int i;
315 	dt_delete(dt_col->dt_env);
316 	event_del(dt_col->cmd_event);
317 	for(i=0; i<dt_col->count; i++) {
318 		event_del(dt_col->inputs[i].event);
319 	}
320 	dt_collector_close(dt_col, nsd);
321 	event_base_free(dt_col->event_base);
322 #ifdef MEMCLEAN
323 	free(dt_col->cmd_event);
324 	if(dt_col->inputs) {
325 		for(i=0; i<dt_col->count; i++) {
326 			free(dt_col->inputs[i].event);
327 		}
328 		free(dt_col->inputs);
329 	}
330 	dt_collector_destroy(dt_col, nsd);
331 	daemon_remote_delete(nsd->rc); /* ssl-delete secret keys */
332 	nsd_options_destroy(nsd->options);
333 	region_destroy(nsd->region);
334 #endif
335 }
336 
337 /* attach events to the event base to listen to the workers and cmd channel */
dt_attach_events(struct dt_collector * dt_col,struct nsd * nsd)338 static void dt_attach_events(struct dt_collector* dt_col, struct nsd* nsd)
339 {
340 	int i;
341 	/* create event base */
342 	dt_col->event_base = nsd_child_event_base();
343 	if(!dt_col->event_base) {
344 		error("dnstap collector: event_base create failed");
345 	}
346 
347 	/* add command handler */
348 	dt_col->cmd_event = (struct event*)xalloc_zero(
349 		sizeof(*dt_col->cmd_event));
350 	event_set(dt_col->cmd_event, dt_col->cmd_socket_dt,
351 		EV_PERSIST|EV_READ, dt_handle_cmd_from_nsd, dt_col);
352 	if(event_base_set(dt_col->event_base, dt_col->cmd_event) != 0)
353 		log_msg(LOG_ERR, "dnstap collector: event_base_set failed");
354 	if(event_add(dt_col->cmd_event, NULL) != 0)
355 		log_msg(LOG_ERR, "dnstap collector: event_add failed");
356 
357 	/* add worker input handlers */
358 	dt_col->inputs = xalloc_array_zero(dt_col->count,
359 		sizeof(*dt_col->inputs));
360 	for(i=0; i<dt_col->count; i++) {
361 		dt_col->inputs[i].dt_collector = dt_col;
362 		dt_col->inputs[i].event = (struct event*)xalloc_zero(
363 			sizeof(struct event));
364 		event_set(dt_col->inputs[i].event,
365 			nsd->dt_collector_fd_recv[i], EV_PERSIST|EV_READ,
366 			dt_handle_input, &dt_col->inputs[i]);
367 		if(event_base_set(dt_col->event_base,
368 			dt_col->inputs[i].event) != 0)
369 			log_msg(LOG_ERR, "dnstap collector: event_base_set failed");
370 		if(event_add(dt_col->inputs[i].event, NULL) != 0)
371 			log_msg(LOG_ERR, "dnstap collector: event_add failed");
372 
373 		dt_col->inputs[i].buffer = buffer_create(dt_col->region,
374 			/* msglen + is_response + addrlen + is_tcp + packetlen + packet + zonelen + zone + spare + local_addr + addr */
375 			4+1+4+1+4+TCP_MAX_MESSAGE_LEN+4+MAXHOSTNAMELEN + 32 +
376 #ifdef INET6
377 			sizeof(struct sockaddr_storage) + sizeof(struct sockaddr_storage)
378 #else
379 			sizeof(struct sockaddr_in) + sizeof(struct sockaddr_in)
380 #endif
381 		);
382 		assert(buffer_capacity(dt_col->inputs[i].buffer) ==
383 			buffer_capacity(dt_col->send_buffer));
384 	}
385 }
386 
387 /* the dnstap collector process main routine */
dt_collector_run(struct dt_collector * dt_col,struct nsd * nsd)388 static void dt_collector_run(struct dt_collector* dt_col, struct nsd* nsd)
389 {
390 	/* init dnstap */
391 	VERBOSITY(1, (LOG_INFO, "dnstap collector started"));
392 	dt_init_dnstap(dt_col, nsd);
393 	dt_attach_events(dt_col, nsd);
394 
395 	/* run */
396 	if(event_base_loop(dt_col->event_base, 0) == -1) {
397 		error("dnstap collector: event_base_loop failed");
398 	}
399 
400 	/* cleanup and done */
401 	VERBOSITY(1, (LOG_INFO, "dnstap collector stopped"));
402 	dt_collector_cleanup(dt_col, nsd);
403 	exit(0);
404 }
405 
dt_collector_start(struct dt_collector * dt_col,struct nsd * nsd)406 void dt_collector_start(struct dt_collector* dt_col, struct nsd* nsd)
407 {
408 	int i, *fd_send;
409 	/* fork */
410 	dt_col->dt_pid = fork();
411 	if(dt_col->dt_pid == -1) {
412 		error("dnstap_collector: fork failed: %s", strerror(errno));
413 	}
414 	if(dt_col->dt_pid == 0) {
415 		/* the dt collector process is this */
416 		/* close the nsd side of the command channel */
417 		close(dt_col->cmd_socket_nsd);
418 		dt_col->cmd_socket_nsd = -1;
419 
420 		/* close the send side of the communication channels */
421 		assert(nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap);
422 		fd_send = nsd->dt_collector_fd_send < nsd->dt_collector_fd_swap
423 			? nsd->dt_collector_fd_send : nsd->dt_collector_fd_swap;
424 		for(i=0; i<dt_col->count; i++) {
425 			if(fd_send[i] != -1) {
426 				close(fd_send[i]);
427 				fd_send[i] = -1;
428 			}
429 		}
430 #ifdef HAVE_SETPROCTITLE
431 		setproctitle("dnstap_collector");
432 #endif
433 		/* Free serve process specific memory pages */
434 #ifdef RATELIMIT
435 		rrl_mmap_deinit_keep_mmap();
436 #endif
437 		udb_base_free_keep_mmap(nsd->task[0]);
438 		udb_base_free_keep_mmap(nsd->task[1]);
439 		namedb_close(nsd->db);
440 
441 		dt_collector_run(dt_col, nsd);
442 		/* NOTREACH */
443 		exit(0);
444 	} else {
445 		/* the parent continues on, with starting NSD */
446 		/* close the dt side of the command channel */
447 		close(dt_col->cmd_socket_dt);
448 		dt_col->cmd_socket_dt = -1;
449 
450 		/* close the receive side of the communication channels */
451 		for(i=0; i<dt_col->count; i++) {
452 			if(nsd->dt_collector_fd_recv[i] != -1) {
453 				close(nsd->dt_collector_fd_recv[i]);
454 				nsd->dt_collector_fd_recv[i] = -1;
455 			}
456 		}
457 	}
458 }
459 
460 /* put data for sending to the collector process into the buffer */
461 static int
prep_send_data(struct buffer * buf,uint8_t is_response,struct sockaddr_storage * local_addr,struct sockaddr_storage * addr,socklen_t addrlen,int is_tcp,struct buffer * packet,struct zone * zone)462 prep_send_data(struct buffer* buf, uint8_t is_response,
463 #ifdef INET6
464 	struct sockaddr_storage* local_addr,
465 	struct sockaddr_storage* addr,
466 #else
467 	struct sockaddr_in* local_addr,
468 	struct sockaddr_in* addr,
469 #endif
470 	socklen_t addrlen, int is_tcp, struct buffer* packet,
471 	struct zone* zone)
472 {
473 	buffer_clear(buf);
474 #ifdef INET6
475 	if(local_addr->ss_family != addr->ss_family)
476 		return 0; /* must be same length to send */
477 #else
478 	if(local_addr->sin_family != addr->sin_family)
479 		return 0; /* must be same length to send */
480 #endif
481 	if(!buffer_available(buf, 4+1+4+2*addrlen+1+4+buffer_remaining(packet)))
482 		return 0; /* does not fit in send_buffer, log is dropped */
483 	buffer_skip(buf, 4); /* the length of the message goes here */
484 	buffer_write_u8(buf, is_response);
485 	buffer_write_u32(buf, addrlen);
486 	buffer_write(buf, local_addr, (size_t)addrlen);
487 	buffer_write(buf, addr, (size_t)addrlen);
488 	buffer_write_u8(buf, (is_tcp?1:0));
489 	buffer_write_u32(buf, buffer_remaining(packet));
490 	buffer_write(buf, buffer_begin(packet), buffer_remaining(packet));
491 	if(zone && zone->apex && domain_dname(zone->apex)) {
492 		if(!buffer_available(buf, 4 + domain_dname(zone->apex)->name_size))
493 			return 0;
494 		buffer_write_u32(buf, domain_dname(zone->apex)->name_size);
495 		buffer_write(buf, dname_name(domain_dname(zone->apex)),
496 			domain_dname(zone->apex)->name_size);
497 	} else {
498 		if(!buffer_available(buf, 4))
499 			return 0;
500 		buffer_write_u32(buf, 0);
501 	}
502 
503 	buffer_flip(buf);
504 	/* write length of message */
505 	buffer_write_u32_at(buf, 0, buffer_remaining(buf)-4);
506 	return 1;
507 }
508 
509 /* attempt to send buffer to socket, if it blocks do not send it.
510  * return 0 on success, -1 on error */
attempt_to_send(int s,uint8_t * data,size_t len)511 static int attempt_to_send(int s, uint8_t* data, size_t len)
512 {
513 	ssize_t r;
514 	if(len == 0)
515 		return 0;
516 	r = send(s, data, len, MSG_DONTWAIT | MSG_NOSIGNAL);
517 	if(r == -1) {
518 		if(errno == EAGAIN || errno == EINTR ||
519 				errno == ENOBUFS || errno == EMSGSIZE) {
520 			/* check if pipe is full, if the nonblocking fd blocks,
521 			 * then drop the message */
522 			return 0;
523 		}
524 		/* some sort of error, print it */
525 		log_msg(LOG_ERR, "dnstap collector: send failed: %s",
526 			strerror(errno));
527 		return -1;
528 	}
529 	assert(r > 0);
530 	if(r > 0) {
531 		assert((size_t)r == len);
532 		return 0;
533 	}
534 	/* Other end closed the channel? */
535 	log_msg(LOG_ERR, "dnstap collector: server child closed the channel");
536 	return -1;
537 }
538 
dt_collector_submit_auth_query(struct nsd * nsd,struct sockaddr_storage * local_addr,struct sockaddr_storage * addr,socklen_t addrlen,int is_tcp,struct buffer * packet)539 void dt_collector_submit_auth_query(struct nsd* nsd,
540 #ifdef INET6
541 	struct sockaddr_storage* local_addr,
542 	struct sockaddr_storage* addr,
543 #else
544 	struct sockaddr_in* local_addr,
545 	struct sockaddr_in* addr,
546 #endif
547 	socklen_t addrlen, int is_tcp, struct buffer* packet)
548 {
549 	if(!nsd->dt_collector) return;
550 	if(!nsd->options->dnstap_log_auth_query_messages) return;
551 	if(nsd->dt_collector_fd_send[nsd->this_child->child_num] == -1) return;
552 	VERBOSITY(4, (LOG_INFO, "dnstap submit auth query"));
553 
554 	/* marshal data into send buffer */
555 	if(!prep_send_data(nsd->dt_collector->send_buffer, 0, local_addr, addr, addrlen,
556 		is_tcp, packet, NULL))
557 		return; /* probably did not fit in buffer */
558 
559 	/* attempt to send data; do not block */
560 	if(attempt_to_send(nsd->dt_collector_fd_send[nsd->this_child->child_num],
561 			buffer_begin(nsd->dt_collector->send_buffer),
562 			buffer_remaining(nsd->dt_collector->send_buffer))) {
563 		/* Something went wrong sending to the socket. Don't send to
564 		 * this socket again. */
565 		close(nsd->dt_collector_fd_send[nsd->this_child->child_num]);
566 		nsd->dt_collector_fd_send[nsd->this_child->child_num] = -1;
567 	}
568 }
569 
dt_collector_submit_auth_response(struct nsd * nsd,struct sockaddr_storage * local_addr,struct sockaddr_storage * addr,socklen_t addrlen,int is_tcp,struct buffer * packet,struct zone * zone)570 void dt_collector_submit_auth_response(struct nsd* nsd,
571 #ifdef INET6
572 	struct sockaddr_storage* local_addr,
573 	struct sockaddr_storage* addr,
574 #else
575 	struct sockaddr_in* local_addr,
576 	struct sockaddr_in* addr,
577 #endif
578 	socklen_t addrlen, int is_tcp, struct buffer* packet,
579 	struct zone* zone)
580 {
581 	if(!nsd->dt_collector) return;
582 	if(!nsd->options->dnstap_log_auth_response_messages) return;
583 	if(nsd->dt_collector_fd_send[nsd->this_child->child_num] == -1) return;
584 	VERBOSITY(4, (LOG_INFO, "dnstap submit auth response"));
585 
586 	/* marshal data into send buffer */
587 	if(!prep_send_data(nsd->dt_collector->send_buffer, 1, local_addr, addr, addrlen,
588 		is_tcp, packet, zone))
589 		return; /* probably did not fit in buffer */
590 
591 	/* attempt to send data; do not block */
592 	if(attempt_to_send(nsd->dt_collector_fd_send[nsd->this_child->child_num],
593 			buffer_begin(nsd->dt_collector->send_buffer),
594 			buffer_remaining(nsd->dt_collector->send_buffer))) {
595 		/* Something went wrong sending to the socket. Don't send to
596 		 * this socket again. */
597 		close(nsd->dt_collector_fd_send[nsd->this_child->child_num]);
598 		nsd->dt_collector_fd_send[nsd->this_child->child_num] = -1;
599 	}
600 }
601