Home | History | Annotate | Line # | Download | only in dnstap
dnstap_collector.c revision 1.1.1.3
      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 
     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 
    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 
    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
    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 */
    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
    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
    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 */
    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 */
    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 */
    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 */
    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 
    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
    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 */
    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 
    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 
    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