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