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 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 static void 90 dt_send(const struct dt_env *env, void *buf, size_t len_buf) 91 { 92 dt_msg_queue_submit(env->msgqueue, buf, len_buf); 93 } 94 95 static void 96 dt_msg_init(const struct dt_env *env, 97 struct dt_msg *dm, 98 Dnstap__Message__Type mtype) 99 { 100 memset(dm, 0, sizeof(*dm)); 101 dm->d.base.descriptor = &dnstap__dnstap__descriptor; 102 dm->m.base.descriptor = &dnstap__message__descriptor; 103 dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE; 104 dm->d.message = &dm->m; 105 dm->m.type = mtype; 106 if (env->identity != NULL) { 107 dm->d.identity.data = (uint8_t *) env->identity; 108 dm->d.identity.len = (size_t) env->len_identity; 109 dm->d.has_identity = 1; 110 } 111 if (env->version != NULL) { 112 dm->d.version.data = (uint8_t *) env->version; 113 dm->d.version.len = (size_t) env->len_version; 114 dm->d.has_version = 1; 115 } 116 } 117 118 /* check that the socket file can be opened and exists, print error if not */ 119 static void 120 check_socket_file(const char* socket_path) 121 { 122 struct stat statbuf; 123 memset(&statbuf, 0, sizeof(statbuf)); 124 if(stat(socket_path, &statbuf) < 0) { 125 log_warn("could not open dnstap-socket-path: %s, %s", 126 socket_path, strerror(errno)); 127 } 128 } 129 130 struct dt_env * 131 dt_create(struct config_file* cfg) 132 { 133 struct dt_env *env; 134 135 if(cfg->dnstap && cfg->dnstap_socket_path && cfg->dnstap_socket_path[0] && 136 (cfg->dnstap_ip==NULL || cfg->dnstap_ip[0]==0)) { 137 char* p = cfg->dnstap_socket_path; 138 if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(p, 139 cfg->chrootdir, strlen(cfg->chrootdir)) == 0) 140 p += strlen(cfg->chrootdir); 141 verbose(VERB_OPS, "attempting to connect to dnstap socket %s", 142 p); 143 check_socket_file(p); 144 } 145 146 env = (struct dt_env *) calloc(1, sizeof(struct dt_env)); 147 if (!env) 148 return NULL; 149 150 env->dtio = dt_io_thread_create(); 151 if(!env->dtio) { 152 log_err("malloc failure"); 153 free(env); 154 return NULL; 155 } 156 if(!dt_io_thread_apply_cfg(env->dtio, cfg)) { 157 dt_io_thread_delete(env->dtio); 158 free(env); 159 return NULL; 160 } 161 dt_apply_cfg(env, cfg); 162 return env; 163 } 164 165 static void 166 dt_apply_identity(struct dt_env *env, struct config_file *cfg) 167 { 168 char buf[MAXHOSTNAMELEN+1]; 169 if (!cfg->dnstap_send_identity) 170 return; 171 free(env->identity); 172 if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) { 173 if (gethostname(buf, MAXHOSTNAMELEN) == 0) { 174 buf[MAXHOSTNAMELEN] = 0; 175 env->identity = strdup(buf); 176 } else { 177 fatal_exit("dt_apply_identity: gethostname() failed"); 178 } 179 } else { 180 env->identity = strdup(cfg->dnstap_identity); 181 } 182 if (env->identity == NULL) 183 fatal_exit("dt_apply_identity: strdup() failed"); 184 env->len_identity = (unsigned int)strlen(env->identity); 185 verbose(VERB_OPS, "dnstap identity field set to \"%s\"", 186 env->identity); 187 } 188 189 static void 190 dt_apply_version(struct dt_env *env, struct config_file *cfg) 191 { 192 if (!cfg->dnstap_send_version) 193 return; 194 free(env->version); 195 if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0) 196 env->version = strdup(PACKAGE_STRING); 197 else 198 env->version = strdup(cfg->dnstap_version); 199 if (env->version == NULL) 200 fatal_exit("dt_apply_version: strdup() failed"); 201 env->len_version = (unsigned int)strlen(env->version); 202 verbose(VERB_OPS, "dnstap version field set to \"%s\"", 203 env->version); 204 } 205 206 void 207 dt_apply_cfg(struct dt_env *env, struct config_file *cfg) 208 { 209 if (!cfg->dnstap) 210 return; 211 212 dt_apply_identity(env, cfg); 213 dt_apply_version(env, cfg); 214 if ((env->log_resolver_query_messages = (unsigned int) 215 cfg->dnstap_log_resolver_query_messages)) 216 { 217 verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled"); 218 } 219 if ((env->log_resolver_response_messages = (unsigned int) 220 cfg->dnstap_log_resolver_response_messages)) 221 { 222 verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled"); 223 } 224 if ((env->log_client_query_messages = (unsigned int) 225 cfg->dnstap_log_client_query_messages)) 226 { 227 verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled"); 228 } 229 if ((env->log_client_response_messages = (unsigned int) 230 cfg->dnstap_log_client_response_messages)) 231 { 232 verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled"); 233 } 234 if ((env->log_forwarder_query_messages = (unsigned int) 235 cfg->dnstap_log_forwarder_query_messages)) 236 { 237 verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled"); 238 } 239 if ((env->log_forwarder_response_messages = (unsigned int) 240 cfg->dnstap_log_forwarder_response_messages)) 241 { 242 verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled"); 243 } 244 } 245 246 int 247 dt_init(struct dt_env *env, struct comm_base* base) 248 { 249 env->msgqueue = dt_msg_queue_create(base); 250 if(!env->msgqueue) { 251 log_err("malloc failure"); 252 return 0; 253 } 254 if(!dt_io_thread_register_queue(env->dtio, env->msgqueue)) { 255 log_err("malloc failure"); 256 dt_msg_queue_delete(env->msgqueue); 257 env->msgqueue = NULL; 258 return 0; 259 } 260 return 1; 261 } 262 263 void 264 dt_deinit(struct dt_env* env) 265 { 266 dt_io_thread_unregister_queue(env->dtio, env->msgqueue); 267 dt_msg_queue_delete(env->msgqueue); 268 } 269 270 void 271 dt_delete(struct dt_env *env) 272 { 273 if (!env) 274 return; 275 dt_io_thread_delete(env->dtio); 276 free(env->identity); 277 free(env->version); 278 free(env); 279 } 280 281 static void 282 dt_fill_timeval(const struct timeval *tv, 283 uint64_t *time_sec, protobuf_c_boolean *has_time_sec, 284 uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec) 285 { 286 #ifndef S_SPLINT_S 287 *time_sec = tv->tv_sec; 288 *time_nsec = tv->tv_usec * 1000; 289 #endif 290 *has_time_sec = 1; 291 *has_time_nsec = 1; 292 } 293 294 static void 295 dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has) 296 { 297 log_assert(b != NULL); 298 p->len = sldns_buffer_limit(b); 299 p->data = sldns_buffer_begin(b); 300 *has = 1; 301 } 302 303 static void 304 dt_msg_fill_net(struct dt_msg *dm, 305 struct sockaddr_storage *qs, 306 struct sockaddr_storage *rs, 307 enum comm_point_type cptype, 308 void *cpssl, 309 ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr, 310 uint32_t *qport, protobuf_c_boolean *has_qport, 311 ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr, 312 uint32_t *rport, protobuf_c_boolean *has_rport) 313 { 314 log_assert(qs->ss_family == AF_INET6 || qs->ss_family == AF_INET); 315 if (qs->ss_family == AF_INET6) { 316 struct sockaddr_in6 *q = (struct sockaddr_in6 *) qs; 317 318 /* socket_family */ 319 dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6; 320 dm->m.has_socket_family = 1; 321 322 /* addr: query_address or response_address */ 323 qaddr->data = q->sin6_addr.s6_addr; 324 qaddr->len = 16; /* IPv6 */ 325 *has_qaddr = 1; 326 327 /* port: query_port or response_port */ 328 *qport = ntohs(q->sin6_port); 329 *has_qport = 1; 330 } else if (qs->ss_family == AF_INET) { 331 struct sockaddr_in *q = (struct sockaddr_in *) qs; 332 333 /* socket_family */ 334 dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET; 335 dm->m.has_socket_family = 1; 336 337 /* addr: query_address or response_address */ 338 qaddr->data = (uint8_t *) &q->sin_addr.s_addr; 339 qaddr->len = 4; /* IPv4 */ 340 *has_qaddr = 1; 341 342 /* port: query_port or response_port */ 343 *qport = ntohs(q->sin_port); 344 *has_qport = 1; 345 } 346 347 /* 348 * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names. 349 * Additional responsive structure is: struct sockaddr_storage *rs 350 */ 351 if (rs && rs->ss_family == AF_INET6) { 352 struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs; 353 354 /* addr: query_address or response_address */ 355 raddr->data = r->sin6_addr.s6_addr; 356 raddr->len = 16; /* IPv6 */ 357 *has_raddr = 1; 358 359 /* port: query_port or response_port */ 360 *rport = ntohs(r->sin6_port); 361 *has_rport = 1; 362 } else if (rs && rs->ss_family == AF_INET) { 363 struct sockaddr_in *r = (struct sockaddr_in *) rs; 364 365 /* addr: query_address or response_address */ 366 raddr->data = (uint8_t *) &r->sin_addr.s_addr; 367 raddr->len = 4; /* IPv4 */ 368 *has_raddr = 1; 369 370 /* port: query_port or response_port */ 371 *rport = ntohs(r->sin_port); 372 *has_rport = 1; 373 } 374 375 if (cptype == comm_udp) { 376 /* socket_protocol */ 377 dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP; 378 dm->m.has_socket_protocol = 1; 379 } else if (cptype == comm_tcp) { 380 if (cpssl == NULL) { 381 /* socket_protocol */ 382 dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; 383 dm->m.has_socket_protocol = 1; 384 } else { 385 /* socket_protocol */ 386 dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT; 387 dm->m.has_socket_protocol = 1; 388 } 389 } else if (cptype == comm_http) { 390 /* socket_protocol */ 391 dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH; 392 dm->m.has_socket_protocol = 1; 393 } else { 394 /* other socket protocol */ 395 dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; 396 dm->m.has_socket_protocol = 1; 397 } 398 } 399 400 void 401 dt_msg_send_client_query(struct dt_env *env, 402 struct sockaddr_storage *qsock, 403 struct sockaddr_storage *rsock, 404 enum comm_point_type cptype, 405 void *cpssl, 406 sldns_buffer *qmsg, 407 struct timeval* tstamp) 408 { 409 struct dt_msg dm; 410 struct timeval qtime; 411 412 if(tstamp) 413 memcpy(&qtime, tstamp, sizeof(qtime)); 414 else gettimeofday(&qtime, NULL); 415 416 /* type */ 417 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY); 418 419 /* query_time */ 420 dt_fill_timeval(&qtime, 421 &dm.m.query_time_sec, &dm.m.has_query_time_sec, 422 &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 423 424 /* query_message */ 425 dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); 426 427 /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ 428 dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl, 429 &dm.m.query_address, &dm.m.has_query_address, 430 &dm.m.query_port, &dm.m.has_query_port, 431 &dm.m.response_address, &dm.m.has_response_address, 432 &dm.m.response_port, &dm.m.has_response_port); 433 434 435 if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 436 dt_send(env, dm.buf, dm.len_buf); 437 } 438 439 void 440 dt_msg_send_client_response(struct dt_env *env, 441 struct sockaddr_storage *qsock, 442 struct sockaddr_storage *rsock, 443 enum comm_point_type cptype, 444 void *cpssl, 445 sldns_buffer *rmsg) 446 { 447 struct dt_msg dm; 448 struct timeval rtime; 449 450 gettimeofday(&rtime, NULL); 451 452 /* type */ 453 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE); 454 455 /* response_time */ 456 dt_fill_timeval(&rtime, 457 &dm.m.response_time_sec, &dm.m.has_response_time_sec, 458 &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); 459 460 /* response_message */ 461 dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); 462 463 /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ 464 dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl, 465 &dm.m.query_address, &dm.m.has_query_address, 466 &dm.m.query_port, &dm.m.has_query_port, 467 &dm.m.response_address, &dm.m.has_response_address, 468 &dm.m.response_port, &dm.m.has_response_port); 469 470 if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 471 dt_send(env, dm.buf, dm.len_buf); 472 } 473 474 void 475 dt_msg_send_outside_query(struct dt_env *env, 476 struct sockaddr_storage *rsock, 477 struct sockaddr_storage *qsock, 478 enum comm_point_type cptype, 479 void *cpssl, 480 uint8_t *zone, size_t zone_len, 481 sldns_buffer *qmsg) 482 { 483 struct dt_msg dm; 484 struct timeval qtime; 485 uint16_t qflags; 486 487 gettimeofday(&qtime, NULL); 488 qflags = sldns_buffer_read_u16_at(qmsg, 2); 489 490 /* type */ 491 if (qflags & BIT_RD) { 492 if (!env->log_forwarder_query_messages) 493 return; 494 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY); 495 } else { 496 if (!env->log_resolver_query_messages) 497 return; 498 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY); 499 } 500 501 /* query_zone */ 502 dm.m.query_zone.data = zone; 503 dm.m.query_zone.len = zone_len; 504 dm.m.has_query_zone = 1; 505 506 /* query_time_sec, query_time_nsec */ 507 dt_fill_timeval(&qtime, 508 &dm.m.query_time_sec, &dm.m.has_query_time_sec, 509 &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 510 511 /* query_message */ 512 dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); 513 514 /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ 515 dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl, 516 &dm.m.response_address, &dm.m.has_response_address, 517 &dm.m.response_port, &dm.m.has_response_port, 518 &dm.m.query_address, &dm.m.has_query_address, 519 &dm.m.query_port, &dm.m.has_query_port); 520 521 if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 522 dt_send(env, dm.buf, dm.len_buf); 523 } 524 525 void 526 dt_msg_send_outside_response(struct dt_env *env, 527 struct sockaddr_storage *rsock, 528 struct sockaddr_storage *qsock, 529 enum comm_point_type cptype, 530 void *cpssl, 531 uint8_t *zone, size_t zone_len, 532 uint8_t *qbuf, size_t qbuf_len, 533 const struct timeval *qtime, 534 const struct timeval *rtime, 535 sldns_buffer *rmsg) 536 { 537 struct dt_msg dm; 538 uint16_t qflags; 539 540 (void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags)); 541 memcpy(&qflags, qbuf, sizeof(qflags)); 542 qflags = ntohs(qflags); 543 544 /* type */ 545 if (qflags & BIT_RD) { 546 if (!env->log_forwarder_response_messages) 547 return; 548 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE); 549 } else { 550 if (!env->log_resolver_response_messages) 551 return; 552 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE); 553 } 554 555 /* query_zone */ 556 dm.m.query_zone.data = zone; 557 dm.m.query_zone.len = zone_len; 558 dm.m.has_query_zone = 1; 559 560 /* query_time_sec, query_time_nsec */ 561 dt_fill_timeval(qtime, 562 &dm.m.query_time_sec, &dm.m.has_query_time_sec, 563 &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 564 565 /* response_time_sec, response_time_nsec */ 566 dt_fill_timeval(rtime, 567 &dm.m.response_time_sec, &dm.m.has_response_time_sec, 568 &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); 569 570 /* response_message */ 571 dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); 572 573 /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ 574 dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl, 575 &dm.m.response_address, &dm.m.has_response_address, 576 &dm.m.response_port, &dm.m.has_response_port, 577 &dm.m.query_address, &dm.m.has_query_address, 578 &dm.m.query_port, &dm.m.has_query_port); 579 580 if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 581 dt_send(env, dm.buf, dm.len_buf); 582 } 583 584 #endif /* USE_DNSTAP */ 585