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