xref: /freebsd/contrib/unbound/dnstap/dnstap.c (revision 7a789145f88a6aceacc59029a0cafe7de7aeefea)
1 /* dnstap support for Unbound */
2 
3 /*
4  * Copyright (c) 2013-2014, Farsight Security, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "dnstap/dnstap_config.h"
36 
37 #ifdef USE_DNSTAP
38 
39 #include "config.h"
40 #include <string.h>
41 #include <sys/time.h>
42 #ifdef HAVE_SYS_STAT_H
43 #include <sys/stat.h>
44 #endif
45 #include <errno.h>
46 #include "sldns/sbuffer.h"
47 #include "util/config_file.h"
48 #include "util/net_help.h"
49 #include "util/netevent.h"
50 #include "util/log.h"
51 
52 #include <protobuf-c/protobuf-c.h>
53 
54 #include "dnstap/dnstap.h"
55 #include "dnstap/dtstream.h"
56 #include "dnstap/dnstap.pb-c.h"
57 
58 #define DNSTAP_INITIAL_BUF_SIZE		256
59 
60 struct dt_msg {
61 	void		*buf;
62 	size_t		len_buf;
63 	Dnstap__Dnstap	d;
64 	Dnstap__Message	m;
65 };
66 
67 static int
dt_pack(const Dnstap__Dnstap * d,void ** buf,size_t * sz)68 dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
69 {
70 	ProtobufCBufferSimple sbuf;
71 
72 	memset(&sbuf, 0, sizeof(sbuf));
73 	sbuf.base.append = protobuf_c_buffer_simple_append;
74 	sbuf.len = 0;
75 	sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE;
76 	sbuf.data = malloc(sbuf.alloced);
77 	if (sbuf.data == NULL)
78 		return 0;
79 	sbuf.must_free_data = 1;
80 
81 	*sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf);
82 	if (sbuf.data == NULL)
83 		return 0;
84 	*buf = sbuf.data;
85 
86 	return 1;
87 }
88 
89 /** See if the message is sent due to dnstap sample rate */
90 static int
dt_sample_rate_limited(struct dt_env * env)91 dt_sample_rate_limited(struct dt_env* env)
92 {
93 	lock_basic_lock(&env->sample_lock);
94 	/* Sampling is every [n] packets. Where n==1, every packet is sent */
95 	if(env->sample_rate > 1) {
96 		int submit = 0;
97 		/* if sampling is engaged... */
98 		if (env->sample_rate_count > env->sample_rate) {
99 			/* once the count passes the limit */
100 			/* submit the message */
101 			submit = 1;
102 			/* and reset the count */
103 			env->sample_rate_count = 0;
104 		}
105 		/* increment count regardless */
106 		env->sample_rate_count++;
107 		lock_basic_unlock(&env->sample_lock);
108 		return !submit;
109 	}
110 	lock_basic_unlock(&env->sample_lock);
111 	return 0;
112 }
113 
114 static void
dt_send(const struct dt_env * env,void * buf,size_t len_buf)115 dt_send(const struct dt_env *env, void *buf, size_t len_buf)
116 {
117 	dt_msg_queue_submit(env->msgqueue, buf, len_buf);
118 }
119 
120 static void
dt_msg_init(const struct dt_env * env,struct dt_msg * dm,Dnstap__Message__Type mtype)121 dt_msg_init(const struct dt_env *env,
122 	    struct dt_msg *dm,
123 	    Dnstap__Message__Type mtype)
124 {
125 	memset(dm, 0, sizeof(*dm));
126 	dm->d.base.descriptor = &dnstap__dnstap__descriptor;
127 	dm->m.base.descriptor = &dnstap__message__descriptor;
128 	dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE;
129 	dm->d.message = &dm->m;
130 	dm->m.type = mtype;
131 	if (env->identity != NULL) {
132 		dm->d.identity.data = (uint8_t *) env->identity;
133 		dm->d.identity.len = (size_t) env->len_identity;
134 		dm->d.has_identity = 1;
135 	}
136 	if (env->version != NULL) {
137 		dm->d.version.data = (uint8_t *) env->version;
138 		dm->d.version.len = (size_t) env->len_version;
139 		dm->d.has_version = 1;
140 	}
141 }
142 
143 /* check that the socket file can be opened and exists, print error if not */
144 static void
check_socket_file(const char * socket_path)145 check_socket_file(const char* socket_path)
146 {
147 	struct stat statbuf;
148 	memset(&statbuf, 0, sizeof(statbuf));
149 	if(stat(socket_path, &statbuf) < 0) {
150 		log_warn("could not open dnstap-socket-path: %s, %s",
151 			socket_path, strerror(errno));
152 	}
153 }
154 
155 struct dt_env *
dt_create(struct config_file * cfg)156 dt_create(struct config_file* cfg)
157 {
158 	struct dt_env *env;
159 
160 	if(cfg->dnstap && cfg->dnstap_socket_path && cfg->dnstap_socket_path[0] &&
161 		(cfg->dnstap_ip==NULL || cfg->dnstap_ip[0]==0)) {
162 		char* p = cfg->dnstap_socket_path;
163 		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(p,
164 			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
165 			p += strlen(cfg->chrootdir);
166 		verbose(VERB_OPS, "attempting to connect to dnstap socket %s",
167 			p);
168 		check_socket_file(p);
169 	}
170 
171 	env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
172 	if (!env)
173 		return NULL;
174 	lock_basic_init(&env->sample_lock);
175 
176 	env->dtio = dt_io_thread_create();
177 	if(!env->dtio) {
178 		log_err("malloc failure");
179 		dt_delete(env);
180 		return NULL;
181 	}
182 	if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
183 		dt_delete(env);
184 		return NULL;
185 	}
186 	if(!dt_apply_cfg(env, cfg)) {
187 		dt_delete(env);
188 		return NULL;
189 	}
190 	return env;
191 }
192 
193 static int
dt_apply_identity(struct dt_env * env,struct config_file * cfg)194 dt_apply_identity(struct dt_env *env, struct config_file *cfg)
195 {
196 	char buf[MAXHOSTNAMELEN+1];
197 	if (!cfg->dnstap_send_identity) {
198 		free(env->identity);
199 		env->identity = NULL;
200 		env->len_identity = 0;
201 		return 1;
202 	}
203 	free(env->identity);
204 	if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
205 		if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
206 			buf[MAXHOSTNAMELEN] = 0;
207 			env->identity = strdup(buf);
208 		} else {
209 			log_err("dt_apply_identity: gethostname() failed: %s",
210 				strerror(errno));
211 			env->identity = NULL;
212 			env->len_identity = 0;
213 			return 0;
214 		}
215 	} else {
216 		env->identity = strdup(cfg->dnstap_identity);
217 	}
218 	if (env->identity == NULL) {
219 		log_err("dt_apply_identity: strdup() failed");
220 		env->len_identity = 0;
221 		return 0;
222 	}
223 	env->len_identity = (unsigned int)strlen(env->identity);
224 	verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
225 		env->identity);
226 	return 1;
227 }
228 
229 static int
dt_apply_version(struct dt_env * env,struct config_file * cfg)230 dt_apply_version(struct dt_env *env, struct config_file *cfg)
231 {
232 	if (!cfg->dnstap_send_version) {
233 		free(env->version);
234 		env->version = NULL;
235 		env->len_version = 0;
236 		return 1;
237 	}
238 	free(env->version);
239 	if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
240 		env->version = strdup(PACKAGE_STRING);
241 	else
242 		env->version = strdup(cfg->dnstap_version);
243 	if (env->version == NULL) {
244 		log_err("dt_apply_version: strdup() failed");
245 		env->len_version = 0;
246 		return 0;
247 	}
248 	env->len_version = (unsigned int)strlen(env->version);
249 	verbose(VERB_OPS, "dnstap version field set to \"%s\"",
250 		env->version);
251 	return 1;
252 }
253 
254 void
dt_apply_logcfg(struct dt_env * env,struct config_file * cfg)255 dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
256 {
257 	if ((env->log_resolver_query_messages = (unsigned int)
258 	     cfg->dnstap_log_resolver_query_messages))
259 	{
260 		verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled");
261 	}
262 	if ((env->log_resolver_response_messages = (unsigned int)
263 	     cfg->dnstap_log_resolver_response_messages))
264 	{
265 		verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled");
266 	}
267 	if ((env->log_client_query_messages = (unsigned int)
268 	     cfg->dnstap_log_client_query_messages))
269 	{
270 		verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled");
271 	}
272 	if ((env->log_client_response_messages = (unsigned int)
273 	     cfg->dnstap_log_client_response_messages))
274 	{
275 		verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled");
276 	}
277 	if ((env->log_forwarder_query_messages = (unsigned int)
278 	     cfg->dnstap_log_forwarder_query_messages))
279 	{
280 		verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled");
281 	}
282 	if ((env->log_forwarder_response_messages = (unsigned int)
283 	     cfg->dnstap_log_forwarder_response_messages))
284 	{
285 		verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
286 	}
287 	lock_basic_lock(&env->sample_lock);
288 	if((env->sample_rate = (unsigned int)cfg->dnstap_sample_rate))
289 	{
290 		verbose(VERB_OPS, "dnstap SAMPLE_RATE enabled and set to \"%d\"", (int)env->sample_rate);
291 	}
292 	lock_basic_unlock(&env->sample_lock);
293 }
294 
295 int
dt_apply_cfg(struct dt_env * env,struct config_file * cfg)296 dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
297 {
298 	if (!cfg->dnstap)
299 		return 1;
300 
301 	dt_apply_logcfg(env, cfg);
302 	if(!dt_apply_identity(env, cfg))
303 		return 0;
304 	if(!dt_apply_version(env, cfg))
305 		return 0;
306 	return 1;
307 }
308 
309 int
dt_init(struct dt_env * env,struct comm_base * base)310 dt_init(struct dt_env *env, struct comm_base* base)
311 {
312 	env->msgqueue = dt_msg_queue_create(base);
313 	if(!env->msgqueue) {
314 		log_err("malloc failure");
315 		return 0;
316 	}
317 	if(!dt_io_thread_register_queue(env->dtio, env->msgqueue)) {
318 		log_err("malloc failure");
319 		dt_msg_queue_delete(env->msgqueue);
320 		env->msgqueue = NULL;
321 		return 0;
322 	}
323 	return 1;
324 }
325 
326 void
dt_deinit(struct dt_env * env)327 dt_deinit(struct dt_env* env)
328 {
329 	dt_io_thread_unregister_queue(env->dtio, env->msgqueue);
330 	dt_msg_queue_delete(env->msgqueue);
331 }
332 
333 void
dt_delete(struct dt_env * env)334 dt_delete(struct dt_env *env)
335 {
336 	if (!env)
337 		return;
338 	dt_io_thread_delete(env->dtio);
339 	lock_basic_destroy(&env->sample_lock);
340 	free(env->identity);
341 	free(env->version);
342 	free(env);
343 }
344 
345 static void
dt_fill_timeval(const struct timeval * tv,uint64_t * time_sec,protobuf_c_boolean * has_time_sec,uint32_t * time_nsec,protobuf_c_boolean * has_time_nsec)346 dt_fill_timeval(const struct timeval *tv,
347 		uint64_t *time_sec, protobuf_c_boolean *has_time_sec,
348 		uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec)
349 {
350 #ifndef S_SPLINT_S
351 	*time_sec = tv->tv_sec;
352 	*time_nsec = tv->tv_usec * 1000;
353 #endif
354 	*has_time_sec = 1;
355 	*has_time_nsec = 1;
356 }
357 
358 static void
dt_fill_buffer(sldns_buffer * b,ProtobufCBinaryData * p,protobuf_c_boolean * has)359 dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has)
360 {
361 	log_assert(b != NULL);
362 	p->len = sldns_buffer_limit(b);
363 	p->data = sldns_buffer_begin(b);
364 	*has = 1;
365 }
366 
367 static void
dt_msg_fill_net(struct dt_msg * dm,struct sockaddr_storage * qs,struct sockaddr_storage * rs,enum comm_point_type cptype,void * cpssl,ProtobufCBinaryData * qaddr,protobuf_c_boolean * has_qaddr,uint32_t * qport,protobuf_c_boolean * has_qport,ProtobufCBinaryData * raddr,protobuf_c_boolean * has_raddr,uint32_t * rport,protobuf_c_boolean * has_rport)368 dt_msg_fill_net(struct dt_msg *dm,
369 		struct sockaddr_storage *qs,
370 		struct sockaddr_storage *rs,
371 		enum comm_point_type cptype,
372 		void *cpssl,
373 		ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
374 		uint32_t *qport, protobuf_c_boolean *has_qport,
375 		ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
376 		uint32_t *rport, protobuf_c_boolean *has_rport)
377 {
378 	log_assert(qs->ss_family == AF_INET6 || qs->ss_family == AF_INET);
379 	if (qs->ss_family == AF_INET6) {
380 		struct sockaddr_in6 *q = (struct sockaddr_in6 *) qs;
381 
382 		/* socket_family */
383 		dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6;
384 		dm->m.has_socket_family = 1;
385 
386 		/* addr: query_address or response_address */
387 		qaddr->data = q->sin6_addr.s6_addr;
388 		qaddr->len = 16; /* IPv6 */
389 		*has_qaddr = 1;
390 
391 		/* port: query_port or response_port */
392 		*qport = ntohs(q->sin6_port);
393 		*has_qport = 1;
394 	} else if (qs->ss_family == AF_INET) {
395 		struct sockaddr_in *q = (struct sockaddr_in *) qs;
396 
397 		/* socket_family */
398 		dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET;
399 		dm->m.has_socket_family = 1;
400 
401 		/* addr: query_address or response_address */
402 		qaddr->data = (uint8_t *) &q->sin_addr.s_addr;
403 		qaddr->len = 4; /* IPv4 */
404 		*has_qaddr = 1;
405 
406 		/* port: query_port or response_port */
407 		*qport = ntohs(q->sin_port);
408 		*has_qport = 1;
409 	}
410 
411 	/*
412 	 * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names.
413 	 * Additional responsive structure is: struct sockaddr_storage *rs
414 	 */
415         if (rs && rs->ss_family == AF_INET6) {
416                 struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs;
417 
418                 /* addr: query_address or response_address */
419                 raddr->data = r->sin6_addr.s6_addr;
420                 raddr->len = 16; /* IPv6 */
421                 *has_raddr = 1;
422 
423                 /* port: query_port or response_port */
424                 *rport = ntohs(r->sin6_port);
425                 *has_rport = 1;
426         } else if (rs && rs->ss_family == AF_INET) {
427                 struct sockaddr_in *r = (struct sockaddr_in *) rs;
428 
429                 /* addr: query_address or response_address */
430                 raddr->data = (uint8_t *) &r->sin_addr.s_addr;
431                 raddr->len = 4; /* IPv4 */
432                 *has_raddr = 1;
433 
434                 /* port: query_port or response_port */
435                 *rport = ntohs(r->sin_port);
436                 *has_rport = 1;
437         }
438 
439 	if (cptype == comm_udp) {
440 		/* socket_protocol */
441 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
442 		dm->m.has_socket_protocol = 1;
443 	} else if (cptype == comm_tcp) {
444 		if (cpssl == NULL) {
445 			/* socket_protocol */
446 			dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
447 			dm->m.has_socket_protocol = 1;
448 		} else {
449 			/* socket_protocol */
450 			dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT;
451 			dm->m.has_socket_protocol = 1;
452 		}
453 	} else if (cptype == comm_http) {
454 		/* socket_protocol */
455 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH;
456 		dm->m.has_socket_protocol = 1;
457 	} else {
458 		/* other socket protocol */
459 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
460 		dm->m.has_socket_protocol = 1;
461 	}
462 }
463 
464 void
dt_msg_send_client_query(struct dt_env * env,struct sockaddr_storage * qsock,struct sockaddr_storage * rsock,enum comm_point_type cptype,void * cpssl,sldns_buffer * qmsg,struct timeval * tstamp)465 dt_msg_send_client_query(struct dt_env *env,
466 			 struct sockaddr_storage *qsock,
467 			 struct sockaddr_storage *rsock,
468 			 enum comm_point_type cptype,
469 			 void *cpssl,
470 			 sldns_buffer *qmsg,
471 			 struct timeval* tstamp)
472 {
473 	struct dt_msg dm;
474 	struct timeval qtime;
475 
476 	if(dt_sample_rate_limited(env))
477 		return;
478 
479 	if(tstamp)
480 		memcpy(&qtime, tstamp, sizeof(qtime));
481 	else 	gettimeofday(&qtime, NULL);
482 
483 	/* type */
484 	dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY);
485 
486 	/* query_time */
487 	dt_fill_timeval(&qtime,
488 			&dm.m.query_time_sec, &dm.m.has_query_time_sec,
489 			&dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
490 
491 	/* query_message */
492 	dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
493 
494 	/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
495 	dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
496 			&dm.m.query_address, &dm.m.has_query_address,
497 			&dm.m.query_port, &dm.m.has_query_port,
498 			&dm.m.response_address, &dm.m.has_response_address,
499 			&dm.m.response_port, &dm.m.has_response_port);
500 
501 
502 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
503 		dt_send(env, dm.buf, dm.len_buf);
504 }
505 
506 void
dt_msg_send_client_response(struct dt_env * env,struct sockaddr_storage * qsock,struct sockaddr_storage * rsock,enum comm_point_type cptype,void * cpssl,sldns_buffer * rmsg)507 dt_msg_send_client_response(struct dt_env *env,
508 			    struct sockaddr_storage *qsock,
509 			    struct sockaddr_storage *rsock,
510 			    enum comm_point_type cptype,
511 			    void *cpssl,
512 			    sldns_buffer *rmsg)
513 {
514 	struct dt_msg dm;
515 	struct timeval rtime;
516 
517 	if(dt_sample_rate_limited(env))
518 		return;
519 
520 	gettimeofday(&rtime, NULL);
521 
522 	/* type */
523 	dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE);
524 
525 	/* response_time */
526 	dt_fill_timeval(&rtime,
527 			&dm.m.response_time_sec, &dm.m.has_response_time_sec,
528 			&dm.m.response_time_nsec, &dm.m.has_response_time_nsec);
529 
530 	/* response_message */
531 	dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
532 
533 	/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
534 	dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
535 			&dm.m.query_address, &dm.m.has_query_address,
536 			&dm.m.query_port, &dm.m.has_query_port,
537                         &dm.m.response_address, &dm.m.has_response_address,
538                         &dm.m.response_port, &dm.m.has_response_port);
539 
540 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
541 		dt_send(env, dm.buf, dm.len_buf);
542 }
543 
544 void
dt_msg_send_outside_query(struct dt_env * env,struct sockaddr_storage * rsock,struct sockaddr_storage * qsock,enum comm_point_type cptype,void * cpssl,uint8_t * zone,size_t zone_len,sldns_buffer * qmsg)545 dt_msg_send_outside_query(struct dt_env *env,
546 			  struct sockaddr_storage *rsock,
547 			  struct sockaddr_storage *qsock,
548 			  enum comm_point_type cptype,
549 			  void *cpssl,
550 			  uint8_t *zone, size_t zone_len,
551 			  sldns_buffer *qmsg)
552 {
553 	struct dt_msg dm;
554 	struct timeval qtime;
555 	uint16_t qflags;
556 
557 	if(dt_sample_rate_limited(env))
558 		return;
559 
560 	gettimeofday(&qtime, NULL);
561 	qflags = sldns_buffer_read_u16_at(qmsg, 2);
562 
563 	/* type */
564 	if ((qflags & BIT_RD)) {
565 		if (!env->log_forwarder_query_messages)
566 			return;
567 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY);
568 	} else {
569 		if (!env->log_resolver_query_messages)
570 			return;
571 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY);
572 	}
573 
574 	/* query_zone */
575 	dm.m.query_zone.data = zone;
576 	dm.m.query_zone.len = zone_len;
577 	dm.m.has_query_zone = 1;
578 
579 	/* query_time_sec, query_time_nsec */
580 	dt_fill_timeval(&qtime,
581 			&dm.m.query_time_sec, &dm.m.has_query_time_sec,
582 			&dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
583 
584 	/* query_message */
585 	dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
586 
587 	/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
588 	dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
589 			&dm.m.response_address, &dm.m.has_response_address,
590 			&dm.m.response_port, &dm.m.has_response_port,
591 			&dm.m.query_address, &dm.m.has_query_address,
592 			&dm.m.query_port, &dm.m.has_query_port);
593 
594 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
595 		dt_send(env, dm.buf, dm.len_buf);
596 }
597 
598 void
dt_msg_send_outside_response(struct dt_env * env,struct sockaddr_storage * rsock,struct sockaddr_storage * qsock,enum comm_point_type cptype,void * cpssl,uint8_t * zone,size_t zone_len,uint8_t * qbuf,size_t qbuf_len,const struct timeval * qtime,const struct timeval * rtime,sldns_buffer * rmsg)599 dt_msg_send_outside_response(struct dt_env *env,
600 	struct sockaddr_storage *rsock,
601 	struct sockaddr_storage *qsock,
602 	enum comm_point_type cptype,
603 	void *cpssl,
604 	uint8_t *zone, size_t zone_len,
605 	uint8_t *qbuf, size_t qbuf_len,
606 	const struct timeval *qtime,
607 	const struct timeval *rtime,
608 	sldns_buffer *rmsg)
609 {
610 	struct dt_msg dm;
611 	uint16_t qflags;
612 
613 	if(dt_sample_rate_limited(env))
614 		return;
615 
616 	(void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags));
617 	memcpy(&qflags, qbuf, sizeof(qflags));
618 	qflags = ntohs(qflags);
619 
620 	/* type */
621 	if ((qflags & BIT_RD)) {
622 		if (!env->log_forwarder_response_messages)
623 			return;
624 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
625 	} else {
626 		if (!env->log_resolver_response_messages)
627 			return;
628 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE);
629 	}
630 
631 	/* query_zone */
632 	dm.m.query_zone.data = zone;
633 	dm.m.query_zone.len = zone_len;
634 	dm.m.has_query_zone = 1;
635 
636 	/* query_time_sec, query_time_nsec */
637 	dt_fill_timeval(qtime,
638 			&dm.m.query_time_sec, &dm.m.has_query_time_sec,
639 			&dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
640 
641 	/* response_time_sec, response_time_nsec */
642 	dt_fill_timeval(rtime,
643 			&dm.m.response_time_sec, &dm.m.has_response_time_sec,
644 			&dm.m.response_time_nsec, &dm.m.has_response_time_nsec);
645 
646 	/* response_message */
647 	dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
648 
649 	/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
650 	dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
651 			&dm.m.response_address, &dm.m.has_response_address,
652 			&dm.m.response_port, &dm.m.has_response_port,
653 			&dm.m.query_address, &dm.m.has_query_address,
654 			&dm.m.query_port, &dm.m.has_query_port);
655 
656 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
657 		dt_send(env, dm.buf, dm.len_buf);
658 }
659 
660 #endif /* USE_DNSTAP */
661