1/* dnstap support for NSD */
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 <unistd.h>
47#include "util.h"
48#include "options.h"
49
50#include <fstrm.h>
51#include <protobuf-c/protobuf-c.h>
52
53#include "dnstap/dnstap.h"
54#include "dnstap/dnstap.pb-c.h"
55
56#ifdef HAVE_SSL
57#ifdef HAVE_OPENSSL_SSL_H
58#include <openssl/ssl.h>
59#endif
60#ifdef HAVE_OPENSSL_ERR_H
61#include <openssl/err.h>
62#endif
63#endif
64
65#define DNSTAP_CONTENT_TYPE		"protobuf:dnstap.Dnstap"
66#define DNSTAP_INITIAL_BUF_SIZE		256
67
68struct dt_msg {
69	void		*buf;
70	size_t		len_buf;
71	Dnstap__Dnstap	d;
72	Dnstap__Message	m;
73};
74
75static int
76dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
77{
78	ProtobufCBufferSimple sbuf;
79
80	memset(&sbuf, 0, sizeof(sbuf));
81	sbuf.base.append = protobuf_c_buffer_simple_append;
82	sbuf.len = 0;
83	sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE;
84	sbuf.data = malloc(sbuf.alloced);
85	if (sbuf.data == NULL)
86		return 0;
87	sbuf.must_free_data = 1;
88
89	*sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf);
90	if (sbuf.data == NULL)
91		return 0;
92	*buf = sbuf.data;
93
94	return 1;
95}
96
97static void
98dt_send(const struct dt_env *env, void *buf, size_t len_buf)
99{
100	fstrm_res res;
101	if (!buf)
102		return;
103	res = fstrm_iothr_submit(env->iothr, env->ioq, buf, len_buf,
104				 fstrm_free_wrapper, NULL);
105	if (res != fstrm_res_success)
106		free(buf);
107}
108
109static void
110dt_msg_init(const struct dt_env *env,
111	    struct dt_msg *dm,
112	    Dnstap__Message__Type mtype)
113{
114	memset(dm, 0, sizeof(*dm));
115	dm->d.base.descriptor = &dnstap__dnstap__descriptor;
116	dm->m.base.descriptor = &dnstap__message__descriptor;
117	dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE;
118	dm->d.message = &dm->m;
119	dm->m.type = mtype;
120	if (env->identity != NULL) {
121		dm->d.identity.data = (uint8_t *) env->identity;
122		dm->d.identity.len = (size_t) env->len_identity;
123		dm->d.has_identity = 1;
124	}
125	if (env->version != NULL) {
126		dm->d.version.data = (uint8_t *) env->version;
127		dm->d.version.len = (size_t) env->len_version;
128		dm->d.has_version = 1;
129	}
130}
131
132#ifdef HAVE_SSL
133/** TLS writer object for fstrm. */
134struct dt_tls_writer {
135	/* ip address */
136	char* ip;
137	/* if connected already */
138	int connected;
139	/* file descriptor */
140	int fd;
141	/* TLS context */
142	SSL_CTX* ctx;
143	/* SSL transport */
144	SSL* ssl;
145	/* the server name to authenticate */
146	char* tls_server_name;
147};
148
149void log_crypto_err(const char* str); /* in server.c */
150
151/* Create TLS writer object for fstrm. */
152static struct dt_tls_writer*
153tls_writer_init(char* ip, char* tls_server_name, char* tls_cert_bundle,
154	char* tls_client_key_file, char* tls_client_cert_file)
155{
156	struct dt_tls_writer* dtw = (struct dt_tls_writer*)calloc(1,
157		sizeof(*dtw));
158	if(!dtw) return NULL;
159	dtw->fd = -1;
160	dtw->ip = strdup(ip);
161	if(!dtw->ip) {
162		free(dtw);
163		return NULL;
164	}
165	dtw->ctx = SSL_CTX_new(SSLv23_client_method());
166	if(!dtw->ctx) {
167		log_msg(LOG_ERR, "dnstap: SSL_CTX_new failed");
168		free(dtw->ip);
169		free(dtw);
170		return NULL;
171	}
172#if SSL_OP_NO_SSLv2 != 0
173	if((SSL_CTX_set_options(dtw->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
174		!= SSL_OP_NO_SSLv2) {
175		log_msg(LOG_ERR, "dnstap: could not set SSL_OP_NO_SSLv2");
176		SSL_CTX_free(dtw->ctx);
177		free(dtw->ip);
178		free(dtw);
179		return NULL;
180	}
181#endif
182	if((SSL_CTX_set_options(dtw->ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
183		!= SSL_OP_NO_SSLv3) {
184		log_msg(LOG_ERR, "dnstap: could not set SSL_OP_NO_SSLv3");
185		SSL_CTX_free(dtw->ctx);
186		free(dtw->ip);
187		free(dtw);
188		return NULL;
189	}
190#if defined(SSL_OP_NO_RENEGOTIATION)
191	/* disable client renegotiation */
192	if((SSL_CTX_set_options(dtw->ctx, SSL_OP_NO_RENEGOTIATION) &
193		SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) {
194		log_msg(LOG_ERR, "dnstap: could not set SSL_OP_NO_RENEGOTIATION");
195		SSL_CTX_free(dtw->ctx);
196		free(dtw->ip);
197		free(dtw);
198		return NULL;
199	}
200#endif
201	if(tls_client_key_file && tls_client_key_file[0]) {
202		if(!SSL_CTX_use_certificate_chain_file(dtw->ctx,
203			tls_client_cert_file)) {
204			log_msg(LOG_ERR, "dnstap: SSL_CTX_use_certificate_chain_file failed for %s", tls_client_cert_file);
205			SSL_CTX_free(dtw->ctx);
206			free(dtw->ip);
207			free(dtw);
208			return NULL;
209		}
210		if(!SSL_CTX_use_PrivateKey_file(dtw->ctx, tls_client_key_file,
211			SSL_FILETYPE_PEM)) {
212			log_msg(LOG_ERR, "dnstap: SSL_CTX_use_PrivateKey_file failed for %s", tls_client_key_file);
213			SSL_CTX_free(dtw->ctx);
214			free(dtw->ip);
215			free(dtw);
216			return NULL;
217		}
218		if(!SSL_CTX_check_private_key(dtw->ctx)) {
219			log_msg(LOG_ERR, "dnstap: SSL_CTX_check_private_key failed for %s", tls_client_key_file);
220			SSL_CTX_free(dtw->ctx);
221			free(dtw->ip);
222			free(dtw);
223			return NULL;
224		}
225	}
226	if(tls_cert_bundle && tls_cert_bundle[0]) {
227		if(!SSL_CTX_load_verify_locations(dtw->ctx, tls_cert_bundle, NULL)) {
228			log_msg(LOG_ERR, "dnstap: SSL_CTX_load_verify_locations failed for %s", tls_cert_bundle);
229			SSL_CTX_free(dtw->ctx);
230			free(dtw->ip);
231			free(dtw);
232			return NULL;
233		}
234		if(SSL_CTX_set_default_verify_paths(dtw->ctx) != 1) {
235			log_msg(LOG_ERR, "dnstap: SSL_CTX_set_default_verify_paths failed");
236			SSL_CTX_free(dtw->ctx);
237			free(dtw->ip);
238			free(dtw);
239			return NULL;
240		}
241		SSL_CTX_set_verify(dtw->ctx, SSL_VERIFY_PEER, NULL);
242	}
243	if(tls_server_name) {
244		dtw->tls_server_name = strdup(tls_server_name);
245		if(!dtw->tls_server_name) {
246				log_msg(LOG_ERR, "dnstap: strdup failed");
247				SSL_CTX_free(dtw->ctx);
248				free(dtw->ip);
249				free(dtw);
250				return NULL;
251		}
252	}
253	return dtw;
254}
255
256/* Delete TLS writer object */
257static void
258tls_writer_delete(struct dt_tls_writer* dtw)
259{
260	if(!dtw)
261		return;
262	if(dtw->ssl)
263		SSL_shutdown(dtw->ssl);
264	SSL_free(dtw->ssl);
265	dtw->ssl = NULL;
266	SSL_CTX_free(dtw->ctx);
267	if(dtw->fd != -1) {
268		close(dtw->fd);
269		dtw->fd = -1;
270	}
271	free(dtw->ip);
272	free(dtw->tls_server_name);
273	free(dtw);
274}
275
276/* The fstrm writer destroy callback for TLS */
277static fstrm_res
278dt_tls_writer_destroy(void* obj)
279{
280	struct dt_tls_writer* dtw = (struct dt_tls_writer*)obj;
281	tls_writer_delete(dtw);
282	return fstrm_res_success;
283}
284
285/* The fstrm writer open callback for TLS */
286static fstrm_res
287dt_tls_writer_open(void* obj)
288{
289	struct sockaddr_storage addr;
290	socklen_t addrlen;
291	char* svr, *at = NULL;
292	int port = 3333;
293	int addrfamily;
294	struct dt_tls_writer* dtw = (struct dt_tls_writer*)obj;
295	X509* x;
296
297	/* skip action if already connected */
298	if(dtw->connected)
299		return fstrm_res_success;
300
301	/* figure out port number */
302	svr = dtw->ip;
303	at = strchr(svr, '@');
304	if(at != NULL) {
305		*at = 0;
306		port = atoi(at+1);
307	}
308
309	/* parse addr */
310	memset(&addr, 0, sizeof(addr));
311#ifdef INET6
312	if(strchr(svr, ':')) {
313		struct sockaddr_in6 sa;
314		addrlen = (socklen_t)sizeof(struct sockaddr_in6);
315		memset(&sa, 0, addrlen);
316		sa.sin6_family = AF_INET6;
317		sa.sin6_port = (in_port_t)htons((uint16_t)port);
318		if(inet_pton((int)sa.sin6_family, svr, &sa.sin6_addr) <= 0) {
319			log_msg(LOG_ERR, "dnstap: could not parse IP: %s", svr);
320			if(at != NULL)
321				*at = '@';
322			return fstrm_res_failure;
323		}
324		memcpy(&addr, &sa, addrlen);
325		addrfamily = AF_INET6;
326	} else
327#else
328		if(1)
329#endif
330	{
331		struct sockaddr_in sa;
332		addrlen = (socklen_t)sizeof(struct sockaddr_in);
333		memset(&sa, 0, addrlen);
334		sa.sin_family = AF_INET;
335		sa.sin_port = (in_port_t)htons((uint16_t)port);
336		if(inet_pton((int)sa.sin_family, svr, &sa.sin_addr) <= 0) {
337			log_msg(LOG_ERR, "dnstap: could not parse IP: %s", svr);
338			if(at != NULL)
339				*at = '@';
340			return fstrm_res_failure;
341		}
342		memcpy(&addr, &sa, addrlen);
343		addrfamily = AF_INET;
344	}
345	if(at != NULL)
346		*at = '@';
347
348	/* open socket */
349	dtw->fd = socket(addrfamily, SOCK_STREAM, 0);
350	if(dtw->fd == -1) {
351		log_msg(LOG_ERR, "dnstap: socket failed: %s", strerror(errno));
352		return fstrm_res_failure;
353	}
354	if(connect(dtw->fd, (struct sockaddr*)&addr, addrlen) < 0) {
355		log_msg(LOG_ERR, "dnstap: connect failed: %s", strerror(errno));
356		return fstrm_res_failure;
357	}
358	dtw->connected = 1;
359
360	/* setup SSL */
361	dtw->ssl = SSL_new(dtw->ctx);
362	if(!dtw->ssl) {
363		log_msg(LOG_ERR, "dnstap: SSL_new failed");
364		return fstrm_res_failure;
365	}
366	SSL_set_connect_state(dtw->ssl);
367	(void)SSL_set_mode(dtw->ssl, SSL_MODE_AUTO_RETRY);
368	if(!SSL_set_fd(dtw->ssl, dtw->fd)) {
369		log_msg(LOG_ERR, "dnstap: SSL_set_fd failed");
370		return fstrm_res_failure;
371	}
372	if(dtw->tls_server_name && dtw->tls_server_name[0]) {
373		if(!SSL_set1_host(dtw->ssl, dtw->tls_server_name)) {
374			log_msg(LOG_ERR, "dnstap: TLS setting of hostname %s failed to %s",
375				dtw->tls_server_name, dtw->ip);
376			return fstrm_res_failure;
377		}
378	}
379
380	/* handshake */
381	while(1) {
382		int r;
383		ERR_clear_error();
384		if( (r=SSL_do_handshake(dtw->ssl)) == 1)
385			break;
386		r = SSL_get_error(dtw->ssl, r);
387		if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) {
388			if(r == SSL_ERROR_ZERO_RETURN) {
389				log_msg(LOG_ERR, "dnstap: EOF on SSL_do_handshake");
390				return fstrm_res_failure;
391			}
392			if(r == SSL_ERROR_SYSCALL) {
393				log_msg(LOG_ERR, "dnstap: SSL_do_handshake failed: %s", strerror(errno));
394				return fstrm_res_failure;
395			}
396			log_crypto_err("dnstap: SSL_do_handshake failed");
397			return fstrm_res_failure;
398		}
399		/* wants to be called again */
400	}
401
402	/* check authenticity of server */
403	if(SSL_get_verify_result(dtw->ssl) != X509_V_OK) {
404		log_crypto_err("SSL verification failed");
405		return fstrm_res_failure;
406	}
407	x = SSL_get_peer_certificate(dtw->ssl);
408	if(!x) {
409		log_crypto_err("Server presented no peer certificate");
410		return fstrm_res_failure;
411	}
412	X509_free(x);
413
414	return fstrm_res_success;
415}
416
417/* The fstrm writer close callback for TLS */
418static fstrm_res
419dt_tls_writer_close(void* obj)
420{
421	struct dt_tls_writer* dtw = (struct dt_tls_writer*)obj;
422	if(dtw->connected) {
423		dtw->connected = 0;
424		if(dtw->ssl)
425			SSL_shutdown(dtw->ssl);
426		SSL_free(dtw->ssl);
427		dtw->ssl = NULL;
428		if(dtw->fd != -1) {
429			close(dtw->fd);
430			dtw->fd = -1;
431		}
432		return fstrm_res_success;
433	}
434	return fstrm_res_failure;
435}
436
437/* The fstrm writer read callback for TLS */
438static fstrm_res
439dt_tls_writer_read(void* obj, void* buf, size_t nbytes)
440{
441	/* want to read nbytes of data */
442	struct dt_tls_writer* dtw = (struct dt_tls_writer*)obj;
443	size_t nread = 0;
444	if(!dtw->connected)
445		return fstrm_res_failure;
446	while(nread < nbytes) {
447		int r;
448		ERR_clear_error();
449		if((r = SSL_read(dtw->ssl, ((char*)buf)+nread, nbytes-nread)) <= 0) {
450			r = SSL_get_error(dtw->ssl, r);
451			if(r == SSL_ERROR_ZERO_RETURN) {
452				log_msg(LOG_ERR, "dnstap: EOF from %s",
453					dtw->ip);
454				return fstrm_res_failure;
455			}
456			if(r == SSL_ERROR_SYSCALL) {
457				log_msg(LOG_ERR, "dnstap: read %s: %s",
458					dtw->ip, strerror(errno));
459				return fstrm_res_failure;
460			}
461			if(r == SSL_ERROR_SSL) {
462				log_crypto_err("dnstap: could not SSL_read");
463				return fstrm_res_failure;
464			}
465			log_msg(LOG_ERR, "dnstap: SSL_read failed with err %d",
466				r);
467			return fstrm_res_failure;
468		}
469		nread += r;
470	}
471	return fstrm_res_success;
472}
473
474/* The fstrm writer write callback for TLS */
475static fstrm_res
476dt_tls_writer_write(void* obj, const struct iovec* iov, int iovcnt)
477{
478	struct dt_tls_writer* dtw = (struct dt_tls_writer*)obj;
479	int i;
480	if(!dtw->connected)
481		return fstrm_res_failure;
482	for(i=0; i<iovcnt; i++) {
483		if(SSL_write(dtw->ssl, iov[i].iov_base, (int)(iov[i].iov_len)) <= 0) {
484			log_crypto_err("dnstap: could not SSL_write");
485			return fstrm_res_failure;
486		}
487	}
488	return fstrm_res_success;
489}
490
491/* Create the fstrm writer object for TLS */
492static struct fstrm_writer*
493dt_tls_make_writer(struct fstrm_writer_options* fwopt,
494	struct dt_tls_writer* dtw)
495{
496	struct fstrm_rdwr* rdwr = fstrm_rdwr_init(dtw);
497	fstrm_rdwr_set_destroy(rdwr, dt_tls_writer_destroy);
498	fstrm_rdwr_set_open(rdwr, dt_tls_writer_open);
499	fstrm_rdwr_set_close(rdwr, dt_tls_writer_close);
500	fstrm_rdwr_set_read(rdwr, dt_tls_writer_read);
501	fstrm_rdwr_set_write(rdwr, dt_tls_writer_write);
502	return fstrm_writer_init(fwopt, &rdwr);
503}
504#endif /* HAVE_SSL */
505
506/* check that the socket file can be opened and exists, print error if not */
507static void
508check_socket_file(const char* socket_path)
509{
510	struct stat statbuf;
511	memset(&statbuf, 0, sizeof(statbuf));
512	if(stat(socket_path, &statbuf) < 0) {
513		log_msg(LOG_WARNING, "could not open dnstap-socket-path: %s, %s",
514			socket_path, strerror(errno));
515	}
516}
517
518struct dt_env *
519dt_create(const char *socket_path, char* ip, unsigned num_workers,
520	int tls, char* tls_server_name, char* tls_cert_bundle,
521	char* tls_client_key_file, char* tls_client_cert_file)
522{
523#ifndef NDEBUG
524	fstrm_res res;
525#endif
526	struct dt_env *env;
527	struct fstrm_iothr_options *fopt;
528	struct fstrm_unix_writer_options *fuwopt = NULL;
529	struct fstrm_tcp_writer_options *ftwopt = NULL;
530	struct fstrm_writer *fw;
531	struct fstrm_writer_options *fwopt;
532
533	assert(num_workers > 0);
534	if(ip == NULL || ip[0] == 0) {
535		VERBOSITY(1, (LOG_INFO, "attempting to connect to dnstap socket %s",
536			socket_path));
537		assert(socket_path != NULL);
538		check_socket_file(socket_path);
539	} else {
540		VERBOSITY(1, (LOG_INFO, "attempting to connect to dnstap %ssocket %s",
541			(tls?"tls ":""), ip));
542	}
543
544	env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
545	if (!env)
546		return NULL;
547
548	fwopt = fstrm_writer_options_init();
549#ifndef NDEBUG
550	res =
551#else
552	(void)
553#endif
554	    fstrm_writer_options_add_content_type(fwopt,
555		DNSTAP_CONTENT_TYPE, sizeof(DNSTAP_CONTENT_TYPE) - 1);
556	assert(res == fstrm_res_success);
557
558	if(ip == NULL || ip[0] == 0) {
559		fuwopt = fstrm_unix_writer_options_init();
560		fstrm_unix_writer_options_set_socket_path(fuwopt, socket_path);
561	} else {
562		char* at = strchr(ip, '@');
563		if(!tls) {
564			ftwopt = fstrm_tcp_writer_options_init();
565			if(at == NULL) {
566				fstrm_tcp_writer_options_set_socket_address(ftwopt, ip);
567				fstrm_tcp_writer_options_set_socket_port(ftwopt, "3333");
568			} else {
569				*at = 0;
570				fstrm_tcp_writer_options_set_socket_address(ftwopt, ip);
571				fstrm_tcp_writer_options_set_socket_port(ftwopt, at+1);
572				*at = '@';
573			}
574		} else {
575#ifdef HAVE_SSL
576			env->tls_writer = tls_writer_init(ip, tls_server_name,
577				tls_cert_bundle, tls_client_key_file,
578				tls_client_cert_file);
579#else
580			(void)tls_server_name;
581			(void)tls_cert_bundle;
582			(void)tls_client_key_file;
583			(void)tls_client_cert_file;
584			log_msg(LOG_ERR, "dnstap: tls enabled but compiled without ssl.");
585#endif
586			if(!env->tls_writer) {
587				log_msg(LOG_ERR, "dt_create: tls_writer_init() failed");
588				fstrm_writer_options_destroy(&fwopt);
589				free(env);
590				return NULL;
591			}
592		}
593	}
594	if(ip == NULL || ip[0] == 0)
595		fw = fstrm_unix_writer_init(fuwopt, fwopt);
596	else if(!tls)
597		fw = fstrm_tcp_writer_init(ftwopt, fwopt);
598#ifdef HAVE_SSL
599	else
600		fw = dt_tls_make_writer(fwopt, env->tls_writer);
601#endif
602	assert(fw != NULL);
603
604	fopt = fstrm_iothr_options_init();
605	fstrm_iothr_options_set_num_input_queues(fopt, num_workers);
606	env->iothr = fstrm_iothr_init(fopt, &fw);
607	if (env->iothr == NULL) {
608		log_msg(LOG_ERR, "dt_create: fstrm_iothr_init() failed");
609		fstrm_writer_destroy(&fw);
610		free(env);
611		env = NULL;
612	}
613	fstrm_iothr_options_destroy(&fopt);
614
615	if(ip == NULL || ip[0] == 0)
616		fstrm_unix_writer_options_destroy(&fuwopt);
617	else if(!tls)
618		fstrm_tcp_writer_options_destroy(&ftwopt);
619	fstrm_writer_options_destroy(&fwopt);
620
621	return env;
622}
623
624static void
625dt_apply_identity(struct dt_env *env, struct nsd_options *cfg)
626{
627	char buf[MAXHOSTNAMELEN+1];
628	if (!cfg->dnstap_send_identity)
629		return;
630	free(env->identity);
631	if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
632		if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
633			buf[MAXHOSTNAMELEN] = 0;
634			env->identity = strdup(buf);
635		} else {
636			error("dt_apply_identity: gethostname() failed");
637		}
638	} else {
639		env->identity = strdup(cfg->dnstap_identity);
640	}
641	if (env->identity == NULL)
642		error("dt_apply_identity: strdup() failed");
643	env->len_identity = (unsigned int)strlen(env->identity);
644	VERBOSITY(1, (LOG_INFO, "dnstap identity field set to \"%s\"",
645		env->identity));
646}
647
648static void
649dt_apply_version(struct dt_env *env, struct nsd_options *cfg)
650{
651	if (!cfg->dnstap_send_version)
652		return;
653	free(env->version);
654	if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
655		env->version = strdup(PACKAGE_STRING);
656	else
657		env->version = strdup(cfg->dnstap_version);
658	if (env->version == NULL)
659		error("dt_apply_version: strdup() failed");
660	env->len_version = (unsigned int)strlen(env->version);
661	VERBOSITY(1, (LOG_INFO, "dnstap version field set to \"%s\"",
662		env->version));
663}
664
665void
666dt_apply_cfg(struct dt_env *env, struct nsd_options *cfg)
667{
668	if (!cfg->dnstap_enable)
669		return;
670
671	dt_apply_identity(env, cfg);
672	dt_apply_version(env, cfg);
673	if ((env->log_auth_query_messages = (unsigned int)
674	     cfg->dnstap_log_auth_query_messages))
675	{
676		VERBOSITY(1, (LOG_INFO, "dnstap Message/AUTH_QUERY enabled"));
677	}
678	if ((env->log_auth_response_messages = (unsigned int)
679	     cfg->dnstap_log_auth_response_messages))
680	{
681		VERBOSITY(1, (LOG_INFO, "dnstap Message/AUTH_RESPONSE enabled"));
682	}
683}
684
685int
686dt_init(struct dt_env *env)
687{
688	env->ioq = fstrm_iothr_get_input_queue(env->iothr);
689	if (env->ioq == NULL)
690		return 0;
691	return 1;
692}
693
694void
695dt_delete(struct dt_env *env)
696{
697	if (!env)
698		return;
699	VERBOSITY(1, (LOG_INFO, "closing dnstap socket"));
700	fstrm_iothr_destroy(&env->iothr);
701	free(env->identity);
702	free(env->version);
703	free(env);
704}
705
706static void
707dt_fill_timeval(const struct timeval *tv,
708		uint64_t *time_sec, protobuf_c_boolean *has_time_sec,
709		uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec)
710{
711#ifndef S_SPLINT_S
712	*time_sec = tv->tv_sec;
713	*time_nsec = tv->tv_usec * 1000;
714#endif
715	*has_time_sec = 1;
716	*has_time_nsec = 1;
717}
718
719static void
720dt_fill_buffer(uint8_t* pkt, size_t pktlen, ProtobufCBinaryData *p, protobuf_c_boolean *has)
721{
722	p->len = pktlen;
723	p->data = pkt;
724	*has = 1;
725}
726
727static void
728dt_msg_fill_net(struct dt_msg *dm,
729#ifdef INET6
730		struct sockaddr_storage *rs,
731		struct sockaddr_storage *qs,
732#else
733		struct sockaddr_in *rs,
734		struct sockaddr_in *qs,
735#endif
736		int is_tcp,
737		ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
738		uint32_t *rport, protobuf_c_boolean *has_rport,
739		ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
740		uint32_t *qport, protobuf_c_boolean *has_qport)
741
742{
743#ifdef INET6
744	assert(qs->ss_family == AF_INET6 || qs->ss_family == AF_INET);
745	if (qs->ss_family == AF_INET6) {
746		struct sockaddr_in6 *s = (struct sockaddr_in6 *) qs;
747
748		/* socket_family */
749		dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6;
750		dm->m.has_socket_family = 1;
751
752		/* addr: query_address or response_address */
753		qaddr->data = s->sin6_addr.s6_addr;
754		qaddr->len = 16; /* IPv6 */
755		*has_qaddr = 1;
756
757		/* port: query_port or response_port */
758		*qport = ntohs(s->sin6_port);
759		*has_qport = 1;
760	} else if (qs->ss_family == AF_INET) {
761#else
762	if (qs->sin_family == AF_INET) {
763#endif /* INET6 */
764		struct sockaddr_in *s = (struct sockaddr_in *) qs;
765
766		/* socket_family */
767		dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET;
768		dm->m.has_socket_family = 1;
769
770		/* addr: query_address or response_address */
771		qaddr->data = (uint8_t *) &s->sin_addr.s_addr;
772		qaddr->len = 4; /* IPv4 */
773		*has_qaddr = 1;
774
775		/* port: query_port or response_port */
776		*qport = ntohs(s->sin_port);
777		*has_qport = 1;
778	}
779
780#ifdef INET6
781        assert(rs->ss_family == AF_INET6 || rs->ss_family == AF_INET);
782        if (rs->ss_family == AF_INET6) {
783                struct sockaddr_in6 *s = (struct sockaddr_in6 *) rs;
784
785                /* addr: query_address or response_address */
786                raddr->data = s->sin6_addr.s6_addr;
787                raddr->len = 16; /* IPv6 */
788                *has_raddr = 1;
789
790                /* port: query_port or response_port */
791                *rport = ntohs(s->sin6_port);
792                *has_rport = 1;
793        } else if (rs->ss_family == AF_INET) {
794#else
795        if (rs->sin_family == AF_INET) {
796#endif /* INET6 */
797                struct sockaddr_in *s = (struct sockaddr_in *) rs;
798
799                /* addr: query_address or response_address */
800                raddr->data = (uint8_t *) &s->sin_addr.s_addr;
801                raddr->len = 4; /* IPv4 */
802                *has_raddr = 1;
803
804                /* port: query_port or response_port */
805                *rport = ntohs(s->sin_port);
806                *has_rport = 1;
807        }
808
809
810	if (!is_tcp) {
811		/* socket_protocol */
812		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
813		dm->m.has_socket_protocol = 1;
814	} else {
815		/* socket_protocol */
816		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
817		dm->m.has_socket_protocol = 1;
818	}
819}
820
821void
822dt_msg_send_auth_query(struct dt_env *env,
823#ifdef INET6
824	struct sockaddr_storage* local_addr,
825	struct sockaddr_storage* addr,
826#else
827	struct sockaddr_in* local_addr,
828	struct sockaddr_in* addr,
829#endif
830	int is_tcp, uint8_t* zone, size_t zonelen, uint8_t* pkt, size_t pktlen)
831{
832	struct dt_msg dm;
833	struct timeval qtime;
834
835	gettimeofday(&qtime, NULL);
836
837	/* type */
838	dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__AUTH_QUERY);
839
840	if(zone) {
841		/* query_zone */
842		dm.m.query_zone.data = zone;
843		dm.m.query_zone.len = zonelen;
844		dm.m.has_query_zone = 1;
845	}
846
847	/* query_time */
848	dt_fill_timeval(&qtime,
849			&dm.m.query_time_sec, &dm.m.has_query_time_sec,
850			&dm.m.query_time_nsec, &dm.m.has_query_time_nsec);
851
852	/* query_message */
853	dt_fill_buffer(pkt, pktlen, &dm.m.query_message, &dm.m.has_query_message);
854
855	/* socket_family, socket_protocol, query_address, query_port, reponse_address (local_address), response_port (local_port) */
856	dt_msg_fill_net(&dm, local_addr, addr, is_tcp,
857			&dm.m.response_address, &dm.m.has_response_address,
858			&dm.m.response_port, &dm.m.has_response_port,
859			&dm.m.query_address, &dm.m.has_query_address,
860			&dm.m.query_port, &dm.m.has_query_port);
861
862
863	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
864		dt_send(env, dm.buf, dm.len_buf);
865}
866
867void
868dt_msg_send_auth_response(struct dt_env *env,
869#ifdef INET6
870	struct sockaddr_storage* local_addr,
871	struct sockaddr_storage* addr,
872#else
873	struct sockaddr_in* local_addr,
874	struct sockaddr_in* addr,
875#endif
876	int is_tcp, uint8_t* zone, size_t zonelen, uint8_t* pkt, size_t pktlen)
877{
878	struct dt_msg dm;
879	struct timeval rtime;
880
881	gettimeofday(&rtime, NULL);
882
883	/* type */
884	dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__AUTH_RESPONSE);
885
886	if(zone) {
887		/* query_zone */
888		dm.m.query_zone.data = zone;
889		dm.m.query_zone.len = zonelen;
890		dm.m.has_query_zone = 1;
891	}
892
893	/* response_time */
894	dt_fill_timeval(&rtime,
895			&dm.m.response_time_sec, &dm.m.has_response_time_sec,
896			&dm.m.response_time_nsec, &dm.m.has_response_time_nsec);
897
898	/* response_message */
899	dt_fill_buffer(pkt, pktlen, &dm.m.response_message, &dm.m.has_response_message);
900
901	/* socket_family, socket_protocol, query_address, query_port, response_address (local_address), response_port (local_port)  */
902	dt_msg_fill_net(&dm, local_addr, addr, is_tcp,
903			&dm.m.response_address, &dm.m.has_response_address,
904			&dm.m.response_port, &dm.m.has_response_port,
905			&dm.m.query_address, &dm.m.has_query_address,
906			&dm.m.query_port, &dm.m.has_query_port);
907
908	if (dt_pack(&dm.d, &dm.buf, &dm.len_buf))
909		dt_send(env, dm.buf, dm.len_buf);
910}
911
912#endif /* USE_DNSTAP */
913