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