xref: /openbsd/usr.sbin/unbound/dnstap/dnstap.c (revision f46c52bf)
198f3ca02Sbrad /* dnstap support for Unbound */
298f3ca02Sbrad 
398f3ca02Sbrad /*
498f3ca02Sbrad  * Copyright (c) 2013-2014, Farsight Security, Inc.
598f3ca02Sbrad  * All rights reserved.
698f3ca02Sbrad  *
798f3ca02Sbrad  * Redistribution and use in source and binary forms, with or without
898f3ca02Sbrad  * modification, are permitted provided that the following conditions
998f3ca02Sbrad  * are met:
1098f3ca02Sbrad  *
1198f3ca02Sbrad  * 1. Redistributions of source code must retain the above copyright
1298f3ca02Sbrad  * notice, this list of conditions and the following disclaimer.
1398f3ca02Sbrad  *
1498f3ca02Sbrad  * 2. Redistributions in binary form must reproduce the above copyright
1598f3ca02Sbrad  * notice, this list of conditions and the following disclaimer in the
1698f3ca02Sbrad  * documentation and/or other materials provided with the distribution.
1798f3ca02Sbrad  *
1898f3ca02Sbrad  * 3. Neither the name of the copyright holder nor the names of its
1998f3ca02Sbrad  * contributors may be used to endorse or promote products derived from
2098f3ca02Sbrad  * this software without specific prior written permission.
2198f3ca02Sbrad  *
2298f3ca02Sbrad  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2398f3ca02Sbrad  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2498f3ca02Sbrad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2598f3ca02Sbrad  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
2698f3ca02Sbrad  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2798f3ca02Sbrad  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2898f3ca02Sbrad  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2998f3ca02Sbrad  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3098f3ca02Sbrad  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3198f3ca02Sbrad  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3298f3ca02Sbrad  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3398f3ca02Sbrad  */
3498f3ca02Sbrad 
3598f3ca02Sbrad #include "dnstap/dnstap_config.h"
3698f3ca02Sbrad 
3798f3ca02Sbrad #ifdef USE_DNSTAP
3898f3ca02Sbrad 
3998f3ca02Sbrad #include "config.h"
4098f3ca02Sbrad #include <string.h>
4198f3ca02Sbrad #include <sys/time.h>
423150e5f6Ssthen #ifdef HAVE_SYS_STAT_H
433150e5f6Ssthen #include <sys/stat.h>
443150e5f6Ssthen #endif
453150e5f6Ssthen #include <errno.h>
46fdfb4ba6Ssthen #include "sldns/sbuffer.h"
4798f3ca02Sbrad #include "util/config_file.h"
4898f3ca02Sbrad #include "util/net_help.h"
4998f3ca02Sbrad #include "util/netevent.h"
5098f3ca02Sbrad #include "util/log.h"
5198f3ca02Sbrad 
5298f3ca02Sbrad #include <protobuf-c/protobuf-c.h>
5398f3ca02Sbrad 
5498f3ca02Sbrad #include "dnstap/dnstap.h"
55a3167c07Ssthen #include "dnstap/dtstream.h"
5698f3ca02Sbrad #include "dnstap/dnstap.pb-c.h"
5798f3ca02Sbrad 
5898f3ca02Sbrad #define DNSTAP_INITIAL_BUF_SIZE		256
5998f3ca02Sbrad 
6098f3ca02Sbrad struct dt_msg {
6198f3ca02Sbrad 	void		*buf;
6298f3ca02Sbrad 	size_t		len_buf;
6398f3ca02Sbrad 	Dnstap__Dnstap	d;
6498f3ca02Sbrad 	Dnstap__Message	m;
6598f3ca02Sbrad };
6698f3ca02Sbrad 
6798f3ca02Sbrad static int
dt_pack(const Dnstap__Dnstap * d,void ** buf,size_t * sz)6898f3ca02Sbrad dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
6998f3ca02Sbrad {
7098f3ca02Sbrad 	ProtobufCBufferSimple sbuf;
7198f3ca02Sbrad 
7298f3ca02Sbrad 	memset(&sbuf, 0, sizeof(sbuf));
7398f3ca02Sbrad 	sbuf.base.append = protobuf_c_buffer_simple_append;
7498f3ca02Sbrad 	sbuf.len = 0;
7598f3ca02Sbrad 	sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE;
7698f3ca02Sbrad 	sbuf.data = malloc(sbuf.alloced);
7798f3ca02Sbrad 	if (sbuf.data == NULL)
7898f3ca02Sbrad 		return 0;
7998f3ca02Sbrad 	sbuf.must_free_data = 1;
8098f3ca02Sbrad 
8198f3ca02Sbrad 	*sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf);
8298f3ca02Sbrad 	if (sbuf.data == NULL)
8398f3ca02Sbrad 		return 0;
8498f3ca02Sbrad 	*buf = sbuf.data;
8598f3ca02Sbrad 
8698f3ca02Sbrad 	return 1;
8798f3ca02Sbrad }
8898f3ca02Sbrad 
8998f3ca02Sbrad static void
dt_send(const struct dt_env * env,void * buf,size_t len_buf)9098f3ca02Sbrad dt_send(const struct dt_env *env, void *buf, size_t len_buf)
9198f3ca02Sbrad {
92a3167c07Ssthen 	dt_msg_queue_submit(env->msgqueue, buf, len_buf);
9398f3ca02Sbrad }
9498f3ca02Sbrad 
9598f3ca02Sbrad static void
dt_msg_init(const struct dt_env * env,struct dt_msg * dm,Dnstap__Message__Type mtype)9698f3ca02Sbrad dt_msg_init(const struct dt_env *env,
9798f3ca02Sbrad 	    struct dt_msg *dm,
9898f3ca02Sbrad 	    Dnstap__Message__Type mtype)
9998f3ca02Sbrad {
10098f3ca02Sbrad 	memset(dm, 0, sizeof(*dm));
10198f3ca02Sbrad 	dm->d.base.descriptor = &dnstap__dnstap__descriptor;
10298f3ca02Sbrad 	dm->m.base.descriptor = &dnstap__message__descriptor;
10398f3ca02Sbrad 	dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE;
10498f3ca02Sbrad 	dm->d.message = &dm->m;
10598f3ca02Sbrad 	dm->m.type = mtype;
10698f3ca02Sbrad 	if (env->identity != NULL) {
10798f3ca02Sbrad 		dm->d.identity.data = (uint8_t *) env->identity;
10898f3ca02Sbrad 		dm->d.identity.len = (size_t) env->len_identity;
10998f3ca02Sbrad 		dm->d.has_identity = 1;
11098f3ca02Sbrad 	}
11198f3ca02Sbrad 	if (env->version != NULL) {
11298f3ca02Sbrad 		dm->d.version.data = (uint8_t *) env->version;
11398f3ca02Sbrad 		dm->d.version.len = (size_t) env->len_version;
11498f3ca02Sbrad 		dm->d.has_version = 1;
11598f3ca02Sbrad 	}
11698f3ca02Sbrad }
11798f3ca02Sbrad 
1183150e5f6Ssthen /* check that the socket file can be opened and exists, print error if not */
1193150e5f6Ssthen static void
check_socket_file(const char * socket_path)1203150e5f6Ssthen check_socket_file(const char* socket_path)
1213150e5f6Ssthen {
1223150e5f6Ssthen 	struct stat statbuf;
1233150e5f6Ssthen 	memset(&statbuf, 0, sizeof(statbuf));
1243150e5f6Ssthen 	if(stat(socket_path, &statbuf) < 0) {
1253150e5f6Ssthen 		log_warn("could not open dnstap-socket-path: %s, %s",
1263150e5f6Ssthen 			socket_path, strerror(errno));
1273150e5f6Ssthen 	}
1283150e5f6Ssthen }
1293150e5f6Ssthen 
13098f3ca02Sbrad struct dt_env *
dt_create(struct config_file * cfg)131a3167c07Ssthen dt_create(struct config_file* cfg)
13298f3ca02Sbrad {
13398f3ca02Sbrad 	struct dt_env *env;
13498f3ca02Sbrad 
135a3167c07Ssthen 	if(cfg->dnstap && cfg->dnstap_socket_path && cfg->dnstap_socket_path[0] &&
136a3167c07Ssthen 		(cfg->dnstap_ip==NULL || cfg->dnstap_ip[0]==0)) {
137eba819a2Ssthen 		char* p = cfg->dnstap_socket_path;
138eba819a2Ssthen 		if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(p,
139eba819a2Ssthen 			cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
140eba819a2Ssthen 			p += strlen(cfg->chrootdir);
14132e31f52Ssthen 		verbose(VERB_OPS, "attempting to connect to dnstap socket %s",
1422c144df0Ssthen 			p);
1432c144df0Ssthen 		check_socket_file(p);
144a3167c07Ssthen 	}
14598f3ca02Sbrad 
14698f3ca02Sbrad 	env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
14798f3ca02Sbrad 	if (!env)
14898f3ca02Sbrad 		return NULL;
14998f3ca02Sbrad 
150a3167c07Ssthen 	env->dtio = dt_io_thread_create();
151a3167c07Ssthen 	if(!env->dtio) {
152a3167c07Ssthen 		log_err("malloc failure");
15398f3ca02Sbrad 		free(env);
154a3167c07Ssthen 		return NULL;
15598f3ca02Sbrad 	}
156a3167c07Ssthen 	if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
157a3167c07Ssthen 		dt_io_thread_delete(env->dtio);
158a3167c07Ssthen 		free(env);
159a3167c07Ssthen 		return NULL;
160a3167c07Ssthen 	}
161a3167c07Ssthen 	dt_apply_cfg(env, cfg);
16298f3ca02Sbrad 	return env;
16398f3ca02Sbrad }
16498f3ca02Sbrad 
16598f3ca02Sbrad static void
dt_apply_identity(struct dt_env * env,struct config_file * cfg)16698f3ca02Sbrad dt_apply_identity(struct dt_env *env, struct config_file *cfg)
16798f3ca02Sbrad {
16898f3ca02Sbrad 	char buf[MAXHOSTNAMELEN+1];
16998f3ca02Sbrad 	if (!cfg->dnstap_send_identity)
17098f3ca02Sbrad 		return;
17198f3ca02Sbrad 	free(env->identity);
17298f3ca02Sbrad 	if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
17398f3ca02Sbrad 		if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
17498f3ca02Sbrad 			buf[MAXHOSTNAMELEN] = 0;
17598f3ca02Sbrad 			env->identity = strdup(buf);
17698f3ca02Sbrad 		} else {
17798f3ca02Sbrad 			fatal_exit("dt_apply_identity: gethostname() failed");
17898f3ca02Sbrad 		}
17998f3ca02Sbrad 	} else {
18098f3ca02Sbrad 		env->identity = strdup(cfg->dnstap_identity);
18198f3ca02Sbrad 	}
18298f3ca02Sbrad 	if (env->identity == NULL)
18398f3ca02Sbrad 		fatal_exit("dt_apply_identity: strdup() failed");
18498f3ca02Sbrad 	env->len_identity = (unsigned int)strlen(env->identity);
18598f3ca02Sbrad 	verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
18698f3ca02Sbrad 		env->identity);
18798f3ca02Sbrad }
18898f3ca02Sbrad 
18998f3ca02Sbrad static void
dt_apply_version(struct dt_env * env,struct config_file * cfg)19098f3ca02Sbrad dt_apply_version(struct dt_env *env, struct config_file *cfg)
19198f3ca02Sbrad {
19298f3ca02Sbrad 	if (!cfg->dnstap_send_version)
19398f3ca02Sbrad 		return;
19498f3ca02Sbrad 	free(env->version);
19598f3ca02Sbrad 	if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
19698f3ca02Sbrad 		env->version = strdup(PACKAGE_STRING);
19798f3ca02Sbrad 	else
19898f3ca02Sbrad 		env->version = strdup(cfg->dnstap_version);
19998f3ca02Sbrad 	if (env->version == NULL)
20098f3ca02Sbrad 		fatal_exit("dt_apply_version: strdup() failed");
20198f3ca02Sbrad 	env->len_version = (unsigned int)strlen(env->version);
20298f3ca02Sbrad 	verbose(VERB_OPS, "dnstap version field set to \"%s\"",
20398f3ca02Sbrad 		env->version);
20498f3ca02Sbrad }
20598f3ca02Sbrad 
20698f3ca02Sbrad void
dt_apply_cfg(struct dt_env * env,struct config_file * cfg)20798f3ca02Sbrad dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
20898f3ca02Sbrad {
20998f3ca02Sbrad 	if (!cfg->dnstap)
21098f3ca02Sbrad 		return;
21198f3ca02Sbrad 
21298f3ca02Sbrad 	dt_apply_identity(env, cfg);
21398f3ca02Sbrad 	dt_apply_version(env, cfg);
21498f3ca02Sbrad 	if ((env->log_resolver_query_messages = (unsigned int)
21598f3ca02Sbrad 	     cfg->dnstap_log_resolver_query_messages))
21698f3ca02Sbrad 	{
21798f3ca02Sbrad 		verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled");
21898f3ca02Sbrad 	}
21998f3ca02Sbrad 	if ((env->log_resolver_response_messages = (unsigned int)
22098f3ca02Sbrad 	     cfg->dnstap_log_resolver_response_messages))
22198f3ca02Sbrad 	{
22298f3ca02Sbrad 		verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled");
22398f3ca02Sbrad 	}
22498f3ca02Sbrad 	if ((env->log_client_query_messages = (unsigned int)
22598f3ca02Sbrad 	     cfg->dnstap_log_client_query_messages))
22698f3ca02Sbrad 	{
22798f3ca02Sbrad 		verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled");
22898f3ca02Sbrad 	}
22998f3ca02Sbrad 	if ((env->log_client_response_messages = (unsigned int)
23098f3ca02Sbrad 	     cfg->dnstap_log_client_response_messages))
23198f3ca02Sbrad 	{
23298f3ca02Sbrad 		verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled");
23398f3ca02Sbrad 	}
23498f3ca02Sbrad 	if ((env->log_forwarder_query_messages = (unsigned int)
23598f3ca02Sbrad 	     cfg->dnstap_log_forwarder_query_messages))
23698f3ca02Sbrad 	{
23798f3ca02Sbrad 		verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled");
23898f3ca02Sbrad 	}
23998f3ca02Sbrad 	if ((env->log_forwarder_response_messages = (unsigned int)
24098f3ca02Sbrad 	     cfg->dnstap_log_forwarder_response_messages))
24198f3ca02Sbrad 	{
24298f3ca02Sbrad 		verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
24398f3ca02Sbrad 	}
24498f3ca02Sbrad }
24598f3ca02Sbrad 
24698f3ca02Sbrad int
dt_init(struct dt_env * env,struct comm_base * base)2472c144df0Ssthen dt_init(struct dt_env *env, struct comm_base* base)
24898f3ca02Sbrad {
2492c144df0Ssthen 	env->msgqueue = dt_msg_queue_create(base);
250a3167c07Ssthen 	if(!env->msgqueue) {
251a3167c07Ssthen 		log_err("malloc failure");
25298f3ca02Sbrad 		return 0;
253a3167c07Ssthen 	}
254a3167c07Ssthen 	if(!dt_io_thread_register_queue(env->dtio, env->msgqueue)) {
255a3167c07Ssthen 		log_err("malloc failure");
256a3167c07Ssthen 		dt_msg_queue_delete(env->msgqueue);
257a3167c07Ssthen 		env->msgqueue = NULL;
258a3167c07Ssthen 		return 0;
259a3167c07Ssthen 	}
26098f3ca02Sbrad 	return 1;
26198f3ca02Sbrad }
26298f3ca02Sbrad 
26398f3ca02Sbrad void
dt_deinit(struct dt_env * env)264a3167c07Ssthen dt_deinit(struct dt_env* env)
265a3167c07Ssthen {
266a3167c07Ssthen 	dt_io_thread_unregister_queue(env->dtio, env->msgqueue);
267a3167c07Ssthen 	dt_msg_queue_delete(env->msgqueue);
268a3167c07Ssthen }
269a3167c07Ssthen 
270a3167c07Ssthen void
dt_delete(struct dt_env * env)27198f3ca02Sbrad dt_delete(struct dt_env *env)
27298f3ca02Sbrad {
27398f3ca02Sbrad 	if (!env)
27498f3ca02Sbrad 		return;
275a3167c07Ssthen 	dt_io_thread_delete(env->dtio);
27698f3ca02Sbrad 	free(env->identity);
27798f3ca02Sbrad 	free(env->version);
27898f3ca02Sbrad 	free(env);
27998f3ca02Sbrad }
28098f3ca02Sbrad 
28198f3ca02Sbrad 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)28298f3ca02Sbrad dt_fill_timeval(const struct timeval *tv,
28398f3ca02Sbrad 		uint64_t *time_sec, protobuf_c_boolean *has_time_sec,
28498f3ca02Sbrad 		uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec)
28598f3ca02Sbrad {
28698f3ca02Sbrad #ifndef S_SPLINT_S
28798f3ca02Sbrad 	*time_sec = tv->tv_sec;
28898f3ca02Sbrad 	*time_nsec = tv->tv_usec * 1000;
28998f3ca02Sbrad #endif
29098f3ca02Sbrad 	*has_time_sec = 1;
29198f3ca02Sbrad 	*has_time_nsec = 1;
29298f3ca02Sbrad }
29398f3ca02Sbrad 
29498f3ca02Sbrad static void
dt_fill_buffer(sldns_buffer * b,ProtobufCBinaryData * p,protobuf_c_boolean * has)29598f3ca02Sbrad dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has)
29698f3ca02Sbrad {
29798f3ca02Sbrad 	log_assert(b != NULL);
29898f3ca02Sbrad 	p->len = sldns_buffer_limit(b);
29998f3ca02Sbrad 	p->data = sldns_buffer_begin(b);
30098f3ca02Sbrad 	*has = 1;
30198f3ca02Sbrad }
30298f3ca02Sbrad 
30398f3ca02Sbrad 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)30498f3ca02Sbrad dt_msg_fill_net(struct dt_msg *dm,
305191f22c6Ssthen 		struct sockaddr_storage *qs,
306191f22c6Ssthen 		struct sockaddr_storage *rs,
30798f3ca02Sbrad 		enum comm_point_type cptype,
308*f46c52bfSsthen 		void *cpssl,
309191f22c6Ssthen 		ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
310191f22c6Ssthen 		uint32_t *qport, protobuf_c_boolean *has_qport,
311191f22c6Ssthen 		ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
312191f22c6Ssthen 		uint32_t *rport, protobuf_c_boolean *has_rport)
31398f3ca02Sbrad {
314191f22c6Ssthen 	log_assert(qs->ss_family == AF_INET6 || qs->ss_family == AF_INET);
315191f22c6Ssthen 	if (qs->ss_family == AF_INET6) {
316191f22c6Ssthen 		struct sockaddr_in6 *q = (struct sockaddr_in6 *) qs;
31798f3ca02Sbrad 
31898f3ca02Sbrad 		/* socket_family */
31998f3ca02Sbrad 		dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6;
32098f3ca02Sbrad 		dm->m.has_socket_family = 1;
32198f3ca02Sbrad 
32298f3ca02Sbrad 		/* addr: query_address or response_address */
323191f22c6Ssthen 		qaddr->data = q->sin6_addr.s6_addr;
324191f22c6Ssthen 		qaddr->len = 16; /* IPv6 */
325191f22c6Ssthen 		*has_qaddr = 1;
32698f3ca02Sbrad 
32798f3ca02Sbrad 		/* port: query_port or response_port */
328191f22c6Ssthen 		*qport = ntohs(q->sin6_port);
329191f22c6Ssthen 		*has_qport = 1;
330191f22c6Ssthen 	} else if (qs->ss_family == AF_INET) {
331191f22c6Ssthen 		struct sockaddr_in *q = (struct sockaddr_in *) qs;
33298f3ca02Sbrad 
33398f3ca02Sbrad 		/* socket_family */
33498f3ca02Sbrad 		dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET;
33598f3ca02Sbrad 		dm->m.has_socket_family = 1;
33698f3ca02Sbrad 
33798f3ca02Sbrad 		/* addr: query_address or response_address */
338191f22c6Ssthen 		qaddr->data = (uint8_t *) &q->sin_addr.s_addr;
339191f22c6Ssthen 		qaddr->len = 4; /* IPv4 */
340191f22c6Ssthen 		*has_qaddr = 1;
34198f3ca02Sbrad 
34298f3ca02Sbrad 		/* port: query_port or response_port */
343191f22c6Ssthen 		*qport = ntohs(q->sin_port);
344191f22c6Ssthen 		*has_qport = 1;
345191f22c6Ssthen 	}
346191f22c6Ssthen 
347191f22c6Ssthen 	/*
348191f22c6Ssthen 	 * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names.
349191f22c6Ssthen 	 * Additional responsive structure is: struct sockaddr_storage *rs
350191f22c6Ssthen 	 */
351191f22c6Ssthen         if (rs && rs->ss_family == AF_INET6) {
352191f22c6Ssthen                 struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs;
353191f22c6Ssthen 
354191f22c6Ssthen                 /* addr: query_address or response_address */
355191f22c6Ssthen                 raddr->data = r->sin6_addr.s6_addr;
356191f22c6Ssthen                 raddr->len = 16; /* IPv6 */
357191f22c6Ssthen                 *has_raddr = 1;
358191f22c6Ssthen 
359191f22c6Ssthen                 /* port: query_port or response_port */
360191f22c6Ssthen                 *rport = ntohs(r->sin6_port);
361191f22c6Ssthen                 *has_rport = 1;
362191f22c6Ssthen         } else if (rs && rs->ss_family == AF_INET) {
363191f22c6Ssthen                 struct sockaddr_in *r = (struct sockaddr_in *) rs;
364191f22c6Ssthen 
365191f22c6Ssthen                 /* addr: query_address or response_address */
366191f22c6Ssthen                 raddr->data = (uint8_t *) &r->sin_addr.s_addr;
367191f22c6Ssthen                 raddr->len = 4; /* IPv4 */
368191f22c6Ssthen                 *has_raddr = 1;
369191f22c6Ssthen 
370191f22c6Ssthen                 /* port: query_port or response_port */
371191f22c6Ssthen                 *rport = ntohs(r->sin_port);
372191f22c6Ssthen                 *has_rport = 1;
37398f3ca02Sbrad         }
37498f3ca02Sbrad 
37598f3ca02Sbrad 	if (cptype == comm_udp) {
37698f3ca02Sbrad 		/* socket_protocol */
37798f3ca02Sbrad 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
37898f3ca02Sbrad 		dm->m.has_socket_protocol = 1;
37998f3ca02Sbrad 	} else if (cptype == comm_tcp) {
380*f46c52bfSsthen 		if (cpssl == NULL) {
38198f3ca02Sbrad 			/* socket_protocol */
38298f3ca02Sbrad 			dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
38398f3ca02Sbrad 			dm->m.has_socket_protocol = 1;
384*f46c52bfSsthen 		} else {
385*f46c52bfSsthen 			/* socket_protocol */
386*f46c52bfSsthen 			dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT;
387*f46c52bfSsthen 			dm->m.has_socket_protocol = 1;
388*f46c52bfSsthen 		}
389*f46c52bfSsthen 	} else if (cptype == comm_http) {
390*f46c52bfSsthen 		/* socket_protocol */
391*f46c52bfSsthen 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH;
392*f46c52bfSsthen 		dm->m.has_socket_protocol = 1;
393*f46c52bfSsthen 	} else {
394*f46c52bfSsthen 		/* other socket protocol */
395*f46c52bfSsthen 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
396*f46c52bfSsthen 		dm->m.has_socket_protocol = 1;
39798f3ca02Sbrad 	}
39898f3ca02Sbrad }
39998f3ca02Sbrad 
40098f3ca02Sbrad 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)40198f3ca02Sbrad dt_msg_send_client_query(struct dt_env *env,
40298f3ca02Sbrad 			 struct sockaddr_storage *qsock,
403191f22c6Ssthen 			 struct sockaddr_storage *rsock,
40498f3ca02Sbrad 			 enum comm_point_type cptype,
405*f46c52bfSsthen 			 void *cpssl,
4068b7325afSsthen 			 sldns_buffer *qmsg,
4078b7325afSsthen 			 struct timeval* tstamp)
40898f3ca02Sbrad {
40998f3ca02Sbrad 	struct dt_msg dm;
41098f3ca02Sbrad 	struct timeval qtime;
41198f3ca02Sbrad 
4128b7325afSsthen 	if(tstamp)
4138b7325afSsthen 		memcpy(&qtime, tstamp, sizeof(qtime));
4148b7325afSsthen 	else 	gettimeofday(&qtime, NULL);
41598f3ca02Sbrad 
41698f3ca02Sbrad 	/* type */
41798f3ca02Sbrad 	dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY);
41898f3ca02Sbrad 
41998f3ca02Sbrad 	/* query_time */
42098f3ca02Sbrad 	dt_fill_timeval(&qtime,
42198f3ca02Sbrad 			&dm.m.query_time_sec, &dm.m.has_query_time_sec,
42298f3ca02Sbrad 			&dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
42398f3ca02Sbrad 
42498f3ca02Sbrad 	/* query_message */
42598f3ca02Sbrad 	dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
42698f3ca02Sbrad 
427191f22c6Ssthen 	/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
428*f46c52bfSsthen 	dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
42998f3ca02Sbrad 			&dm.m.query_address, &dm.m.has_query_address,
430191f22c6Ssthen 			&dm.m.query_port, &dm.m.has_query_port,
431191f22c6Ssthen 			&dm.m.response_address, &dm.m.has_response_address,
432191f22c6Ssthen 			&dm.m.response_port, &dm.m.has_response_port);
433191f22c6Ssthen 
43498f3ca02Sbrad 
43598f3ca02Sbrad 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
43698f3ca02Sbrad 		dt_send(env, dm.buf, dm.len_buf);
43798f3ca02Sbrad }
43898f3ca02Sbrad 
43998f3ca02Sbrad 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)44098f3ca02Sbrad dt_msg_send_client_response(struct dt_env *env,
44198f3ca02Sbrad 			    struct sockaddr_storage *qsock,
442191f22c6Ssthen 			    struct sockaddr_storage *rsock,
44398f3ca02Sbrad 			    enum comm_point_type cptype,
444*f46c52bfSsthen 			    void *cpssl,
44598f3ca02Sbrad 			    sldns_buffer *rmsg)
44698f3ca02Sbrad {
44798f3ca02Sbrad 	struct dt_msg dm;
44898f3ca02Sbrad 	struct timeval rtime;
44998f3ca02Sbrad 
45098f3ca02Sbrad 	gettimeofday(&rtime, NULL);
45198f3ca02Sbrad 
45298f3ca02Sbrad 	/* type */
45398f3ca02Sbrad 	dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE);
45498f3ca02Sbrad 
45598f3ca02Sbrad 	/* response_time */
45698f3ca02Sbrad 	dt_fill_timeval(&rtime,
45798f3ca02Sbrad 			&dm.m.response_time_sec, &dm.m.has_response_time_sec,
45898f3ca02Sbrad 			&dm.m.response_time_nsec, &dm.m.has_response_time_nsec);
45998f3ca02Sbrad 
46098f3ca02Sbrad 	/* response_message */
46198f3ca02Sbrad 	dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
46298f3ca02Sbrad 
463191f22c6Ssthen 	/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
464*f46c52bfSsthen 	dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
46598f3ca02Sbrad 			&dm.m.query_address, &dm.m.has_query_address,
466191f22c6Ssthen 			&dm.m.query_port, &dm.m.has_query_port,
467191f22c6Ssthen                         &dm.m.response_address, &dm.m.has_response_address,
468191f22c6Ssthen                         &dm.m.response_port, &dm.m.has_response_port);
46998f3ca02Sbrad 
47098f3ca02Sbrad 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
47198f3ca02Sbrad 		dt_send(env, dm.buf, dm.len_buf);
47298f3ca02Sbrad }
47398f3ca02Sbrad 
47498f3ca02Sbrad 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)47598f3ca02Sbrad dt_msg_send_outside_query(struct dt_env *env,
47698f3ca02Sbrad 			  struct sockaddr_storage *rsock,
477191f22c6Ssthen 			  struct sockaddr_storage *qsock,
47898f3ca02Sbrad 			  enum comm_point_type cptype,
479*f46c52bfSsthen 			  void *cpssl,
48098f3ca02Sbrad 			  uint8_t *zone, size_t zone_len,
48198f3ca02Sbrad 			  sldns_buffer *qmsg)
48298f3ca02Sbrad {
48398f3ca02Sbrad 	struct dt_msg dm;
48498f3ca02Sbrad 	struct timeval qtime;
48598f3ca02Sbrad 	uint16_t qflags;
48698f3ca02Sbrad 
48798f3ca02Sbrad 	gettimeofday(&qtime, NULL);
48898f3ca02Sbrad 	qflags = sldns_buffer_read_u16_at(qmsg, 2);
48998f3ca02Sbrad 
49098f3ca02Sbrad 	/* type */
49198f3ca02Sbrad 	if (qflags & BIT_RD) {
49298f3ca02Sbrad 		if (!env->log_forwarder_query_messages)
49398f3ca02Sbrad 			return;
49498f3ca02Sbrad 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY);
49598f3ca02Sbrad 	} else {
49698f3ca02Sbrad 		if (!env->log_resolver_query_messages)
49798f3ca02Sbrad 			return;
49898f3ca02Sbrad 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY);
49998f3ca02Sbrad 	}
50098f3ca02Sbrad 
50198f3ca02Sbrad 	/* query_zone */
50298f3ca02Sbrad 	dm.m.query_zone.data = zone;
50398f3ca02Sbrad 	dm.m.query_zone.len = zone_len;
50498f3ca02Sbrad 	dm.m.has_query_zone = 1;
50598f3ca02Sbrad 
50698f3ca02Sbrad 	/* query_time_sec, query_time_nsec */
50798f3ca02Sbrad 	dt_fill_timeval(&qtime,
50898f3ca02Sbrad 			&dm.m.query_time_sec, &dm.m.has_query_time_sec,
50998f3ca02Sbrad 			&dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
51098f3ca02Sbrad 
51198f3ca02Sbrad 	/* query_message */
51298f3ca02Sbrad 	dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
51398f3ca02Sbrad 
514191f22c6Ssthen 	/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
515*f46c52bfSsthen 	dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
51698f3ca02Sbrad 			&dm.m.response_address, &dm.m.has_response_address,
517191f22c6Ssthen 			&dm.m.response_port, &dm.m.has_response_port,
518191f22c6Ssthen 			&dm.m.query_address, &dm.m.has_query_address,
519191f22c6Ssthen 			&dm.m.query_port, &dm.m.has_query_port);
52098f3ca02Sbrad 
52198f3ca02Sbrad 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
52298f3ca02Sbrad 		dt_send(env, dm.buf, dm.len_buf);
52398f3ca02Sbrad }
52498f3ca02Sbrad 
52598f3ca02Sbrad 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)52698f3ca02Sbrad dt_msg_send_outside_response(struct dt_env *env,
52798f3ca02Sbrad 	struct sockaddr_storage *rsock,
528191f22c6Ssthen 	struct sockaddr_storage *qsock,
52998f3ca02Sbrad 	enum comm_point_type cptype,
530*f46c52bfSsthen 	void *cpssl,
53198f3ca02Sbrad 	uint8_t *zone, size_t zone_len,
53298f3ca02Sbrad 	uint8_t *qbuf, size_t qbuf_len,
53398f3ca02Sbrad 	const struct timeval *qtime,
53498f3ca02Sbrad 	const struct timeval *rtime,
53598f3ca02Sbrad 	sldns_buffer *rmsg)
53698f3ca02Sbrad {
53798f3ca02Sbrad 	struct dt_msg dm;
53898f3ca02Sbrad 	uint16_t qflags;
53998f3ca02Sbrad 
540191f22c6Ssthen 	(void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags));
54198f3ca02Sbrad 	memcpy(&qflags, qbuf, sizeof(qflags));
54298f3ca02Sbrad 	qflags = ntohs(qflags);
54398f3ca02Sbrad 
54498f3ca02Sbrad 	/* type */
54598f3ca02Sbrad 	if (qflags & BIT_RD) {
54698f3ca02Sbrad 		if (!env->log_forwarder_response_messages)
54798f3ca02Sbrad 			return;
54898f3ca02Sbrad 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
54998f3ca02Sbrad 	} else {
5502ee382b6Ssthen 		if (!env->log_resolver_response_messages)
55198f3ca02Sbrad 			return;
55298f3ca02Sbrad 		dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE);
55398f3ca02Sbrad 	}
55498f3ca02Sbrad 
55598f3ca02Sbrad 	/* query_zone */
55698f3ca02Sbrad 	dm.m.query_zone.data = zone;
55798f3ca02Sbrad 	dm.m.query_zone.len = zone_len;
55898f3ca02Sbrad 	dm.m.has_query_zone = 1;
55998f3ca02Sbrad 
56098f3ca02Sbrad 	/* query_time_sec, query_time_nsec */
56198f3ca02Sbrad 	dt_fill_timeval(qtime,
56298f3ca02Sbrad 			&dm.m.query_time_sec, &dm.m.has_query_time_sec,
56398f3ca02Sbrad 			&dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
56498f3ca02Sbrad 
56598f3ca02Sbrad 	/* response_time_sec, response_time_nsec */
56698f3ca02Sbrad 	dt_fill_timeval(rtime,
56798f3ca02Sbrad 			&dm.m.response_time_sec, &dm.m.has_response_time_sec,
56898f3ca02Sbrad 			&dm.m.response_time_nsec, &dm.m.has_response_time_nsec);
56998f3ca02Sbrad 
57098f3ca02Sbrad 	/* response_message */
57198f3ca02Sbrad 	dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
57298f3ca02Sbrad 
573191f22c6Ssthen 	/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
574*f46c52bfSsthen 	dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
57598f3ca02Sbrad 			&dm.m.response_address, &dm.m.has_response_address,
576191f22c6Ssthen 			&dm.m.response_port, &dm.m.has_response_port,
577191f22c6Ssthen 			&dm.m.query_address, &dm.m.has_query_address,
578191f22c6Ssthen 			&dm.m.query_port, &dm.m.has_query_port);
57998f3ca02Sbrad 
58098f3ca02Sbrad 	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
58198f3ca02Sbrad 		dt_send(env, dm.buf, dm.len_buf);
58298f3ca02Sbrad }
58398f3ca02Sbrad 
58498f3ca02Sbrad #endif /* USE_DNSTAP */
585