xref: /openbsd/usr.sbin/nsd/dnstap/dnstap.c (revision 3efee2e1)
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 
68 struct dt_msg {
69 	void		*buf;
70 	size_t		len_buf;
71 	Dnstap__Dnstap	d;
72 	Dnstap__Message	m;
73 };
74 
75 static int
dt_pack(const Dnstap__Dnstap * d,void ** buf,size_t * sz)76 dt_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 
97 static void
dt_send(const struct dt_env * env,void * buf,size_t len_buf)98 dt_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 
109 static void
dt_msg_init(const struct dt_env * env,struct dt_msg * dm,Dnstap__Message__Type mtype)110 dt_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. */
134 struct 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 
149 void log_crypto_err(const char* str); /* in server.c */
150 
151 /* Create TLS writer object for fstrm. */
152 static struct dt_tls_writer*
tls_writer_init(char * ip,char * tls_server_name,char * tls_cert_bundle,char * tls_client_key_file,char * tls_client_cert_file)153 tls_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 */
257 static void
tls_writer_delete(struct dt_tls_writer * dtw)258 tls_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 */
277 static fstrm_res
dt_tls_writer_destroy(void * obj)278 dt_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 */
286 static fstrm_res
dt_tls_writer_open(void * obj)287 dt_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 */
418 static fstrm_res
dt_tls_writer_close(void * obj)419 dt_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 */
438 static fstrm_res
dt_tls_writer_read(void * obj,void * buf,size_t nbytes)439 dt_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 */
475 static fstrm_res
dt_tls_writer_write(void * obj,const struct iovec * iov,int iovcnt)476 dt_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 */
492 static struct fstrm_writer*
dt_tls_make_writer(struct fstrm_writer_options * fwopt,struct dt_tls_writer * dtw)493 dt_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 */
507 static void
check_socket_file(const char * socket_path)508 check_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 
518 struct dt_env *
dt_create(const char * socket_path,char * ip,unsigned num_workers,int tls,char * tls_server_name,char * tls_cert_bundle,char * tls_client_key_file,char * tls_client_cert_file)519 dt_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 
624 static void
dt_apply_identity(struct dt_env * env,struct nsd_options * cfg)625 dt_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 
648 static void
dt_apply_version(struct dt_env * env,struct nsd_options * cfg)649 dt_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 
665 void
dt_apply_cfg(struct dt_env * env,struct nsd_options * cfg)666 dt_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 
685 int
dt_init(struct dt_env * env)686 dt_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 
694 void
dt_delete(struct dt_env * env)695 dt_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 
706 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)707 dt_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 
719 static void
dt_fill_buffer(uint8_t * pkt,size_t pktlen,ProtobufCBinaryData * p,protobuf_c_boolean * has)720 dt_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 
727 static void
dt_msg_fill_net(struct dt_msg * dm,struct sockaddr_storage * rs,struct sockaddr_storage * qs,int is_tcp,ProtobufCBinaryData * raddr,protobuf_c_boolean * has_raddr,uint32_t * rport,protobuf_c_boolean * has_rport,ProtobufCBinaryData * qaddr,protobuf_c_boolean * has_qaddr,uint32_t * qport,protobuf_c_boolean * has_qport)728 dt_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 
821 void
822 dt_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 
867 void
868 dt_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