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 = fname_after_chroot(cfg->dnstap_socket_path, cfg, 1); 138 if(!p) { 139 log_err("malloc failure"); 140 return NULL; 141 } 142 verbose(VERB_OPS, "attempting to connect to dnstap socket %s", 143 p); 144 check_socket_file(p); 145 free(p); 146 } 147 148 env = (struct dt_env *) calloc(1, sizeof(struct dt_env)); 149 if (!env) 150 return NULL; 151 152 env->dtio = dt_io_thread_create(); 153 if(!env->dtio) { 154 log_err("malloc failure"); 155 free(env); 156 return NULL; 157 } 158 if(!dt_io_thread_apply_cfg(env->dtio, cfg)) { 159 dt_io_thread_delete(env->dtio); 160 free(env); 161 return NULL; 162 } 163 dt_apply_cfg(env, cfg); 164 return env; 165 } 166 167 static void 168 dt_apply_identity(struct dt_env *env, struct config_file *cfg) 169 { 170 char buf[MAXHOSTNAMELEN+1]; 171 if (!cfg->dnstap_send_identity) 172 return; 173 free(env->identity); 174 if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) { 175 if (gethostname(buf, MAXHOSTNAMELEN) == 0) { 176 buf[MAXHOSTNAMELEN] = 0; 177 env->identity = strdup(buf); 178 } else { 179 fatal_exit("dt_apply_identity: gethostname() failed"); 180 } 181 } else { 182 env->identity = strdup(cfg->dnstap_identity); 183 } 184 if (env->identity == NULL) 185 fatal_exit("dt_apply_identity: strdup() failed"); 186 env->len_identity = (unsigned int)strlen(env->identity); 187 verbose(VERB_OPS, "dnstap identity field set to \"%s\"", 188 env->identity); 189 } 190 191 static void 192 dt_apply_version(struct dt_env *env, struct config_file *cfg) 193 { 194 if (!cfg->dnstap_send_version) 195 return; 196 free(env->version); 197 if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0) 198 env->version = strdup(PACKAGE_STRING); 199 else 200 env->version = strdup(cfg->dnstap_version); 201 if (env->version == NULL) 202 fatal_exit("dt_apply_version: strdup() failed"); 203 env->len_version = (unsigned int)strlen(env->version); 204 verbose(VERB_OPS, "dnstap version field set to \"%s\"", 205 env->version); 206 } 207 208 void 209 dt_apply_cfg(struct dt_env *env, struct config_file *cfg) 210 { 211 if (!cfg->dnstap) 212 return; 213 214 dt_apply_identity(env, cfg); 215 dt_apply_version(env, cfg); 216 if ((env->log_resolver_query_messages = (unsigned int) 217 cfg->dnstap_log_resolver_query_messages)) 218 { 219 verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled"); 220 } 221 if ((env->log_resolver_response_messages = (unsigned int) 222 cfg->dnstap_log_resolver_response_messages)) 223 { 224 verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled"); 225 } 226 if ((env->log_client_query_messages = (unsigned int) 227 cfg->dnstap_log_client_query_messages)) 228 { 229 verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled"); 230 } 231 if ((env->log_client_response_messages = (unsigned int) 232 cfg->dnstap_log_client_response_messages)) 233 { 234 verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled"); 235 } 236 if ((env->log_forwarder_query_messages = (unsigned int) 237 cfg->dnstap_log_forwarder_query_messages)) 238 { 239 verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled"); 240 } 241 if ((env->log_forwarder_response_messages = (unsigned int) 242 cfg->dnstap_log_forwarder_response_messages)) 243 { 244 verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled"); 245 } 246 } 247 248 int 249 dt_init(struct dt_env *env, struct comm_base* base) 250 { 251 env->msgqueue = dt_msg_queue_create(base); 252 if(!env->msgqueue) { 253 log_err("malloc failure"); 254 return 0; 255 } 256 if(!dt_io_thread_register_queue(env->dtio, env->msgqueue)) { 257 log_err("malloc failure"); 258 dt_msg_queue_delete(env->msgqueue); 259 env->msgqueue = NULL; 260 return 0; 261 } 262 return 1; 263 } 264 265 void 266 dt_deinit(struct dt_env* env) 267 { 268 dt_io_thread_unregister_queue(env->dtio, env->msgqueue); 269 dt_msg_queue_delete(env->msgqueue); 270 } 271 272 void 273 dt_delete(struct dt_env *env) 274 { 275 if (!env) 276 return; 277 dt_io_thread_delete(env->dtio); 278 free(env->identity); 279 free(env->version); 280 free(env); 281 } 282 283 static void 284 dt_fill_timeval(const struct timeval *tv, 285 uint64_t *time_sec, protobuf_c_boolean *has_time_sec, 286 uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec) 287 { 288 #ifndef S_SPLINT_S 289 *time_sec = tv->tv_sec; 290 *time_nsec = tv->tv_usec * 1000; 291 #endif 292 *has_time_sec = 1; 293 *has_time_nsec = 1; 294 } 295 296 static void 297 dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has) 298 { 299 log_assert(b != NULL); 300 p->len = sldns_buffer_limit(b); 301 p->data = sldns_buffer_begin(b); 302 *has = 1; 303 } 304 305 static void 306 dt_msg_fill_net(struct dt_msg *dm, 307 struct sockaddr_storage *ss, 308 enum comm_point_type cptype, 309 ProtobufCBinaryData *addr, protobuf_c_boolean *has_addr, 310 uint32_t *port, protobuf_c_boolean *has_port) 311 { 312 log_assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET); 313 if (ss->ss_family == AF_INET6) { 314 struct sockaddr_in6 *s = (struct sockaddr_in6 *) ss; 315 316 /* socket_family */ 317 dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6; 318 dm->m.has_socket_family = 1; 319 320 /* addr: query_address or response_address */ 321 addr->data = s->sin6_addr.s6_addr; 322 addr->len = 16; /* IPv6 */ 323 *has_addr = 1; 324 325 /* port: query_port or response_port */ 326 *port = ntohs(s->sin6_port); 327 *has_port = 1; 328 } else if (ss->ss_family == AF_INET) { 329 struct sockaddr_in *s = (struct sockaddr_in *) ss; 330 331 /* socket_family */ 332 dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET; 333 dm->m.has_socket_family = 1; 334 335 /* addr: query_address or response_address */ 336 addr->data = (uint8_t *) &s->sin_addr.s_addr; 337 addr->len = 4; /* IPv4 */ 338 *has_addr = 1; 339 340 /* port: query_port or response_port */ 341 *port = ntohs(s->sin_port); 342 *has_port = 1; 343 } 344 345 log_assert(cptype == comm_udp || cptype == comm_tcp); 346 if (cptype == comm_udp) { 347 /* socket_protocol */ 348 dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP; 349 dm->m.has_socket_protocol = 1; 350 } else if (cptype == comm_tcp) { 351 /* socket_protocol */ 352 dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; 353 dm->m.has_socket_protocol = 1; 354 } 355 } 356 357 void 358 dt_msg_send_client_query(struct dt_env *env, 359 struct sockaddr_storage *qsock, 360 enum comm_point_type cptype, 361 sldns_buffer *qmsg) 362 { 363 struct dt_msg dm; 364 struct timeval qtime; 365 366 gettimeofday(&qtime, NULL); 367 368 /* type */ 369 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY); 370 371 /* query_time */ 372 dt_fill_timeval(&qtime, 373 &dm.m.query_time_sec, &dm.m.has_query_time_sec, 374 &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 375 376 /* query_message */ 377 dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); 378 379 /* socket_family, socket_protocol, query_address, query_port */ 380 log_assert(cptype == comm_udp || cptype == comm_tcp); 381 dt_msg_fill_net(&dm, qsock, cptype, 382 &dm.m.query_address, &dm.m.has_query_address, 383 &dm.m.query_port, &dm.m.has_query_port); 384 385 if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 386 dt_send(env, dm.buf, dm.len_buf); 387 } 388 389 void 390 dt_msg_send_client_response(struct dt_env *env, 391 struct sockaddr_storage *qsock, 392 enum comm_point_type cptype, 393 sldns_buffer *rmsg) 394 { 395 struct dt_msg dm; 396 struct timeval rtime; 397 398 gettimeofday(&rtime, NULL); 399 400 /* type */ 401 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE); 402 403 /* response_time */ 404 dt_fill_timeval(&rtime, 405 &dm.m.response_time_sec, &dm.m.has_response_time_sec, 406 &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); 407 408 /* response_message */ 409 dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); 410 411 /* socket_family, socket_protocol, query_address, query_port */ 412 log_assert(cptype == comm_udp || cptype == comm_tcp); 413 dt_msg_fill_net(&dm, qsock, cptype, 414 &dm.m.query_address, &dm.m.has_query_address, 415 &dm.m.query_port, &dm.m.has_query_port); 416 417 if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 418 dt_send(env, dm.buf, dm.len_buf); 419 } 420 421 void 422 dt_msg_send_outside_query(struct dt_env *env, 423 struct sockaddr_storage *rsock, 424 enum comm_point_type cptype, 425 uint8_t *zone, size_t zone_len, 426 sldns_buffer *qmsg) 427 { 428 struct dt_msg dm; 429 struct timeval qtime; 430 uint16_t qflags; 431 432 gettimeofday(&qtime, NULL); 433 qflags = sldns_buffer_read_u16_at(qmsg, 2); 434 435 /* type */ 436 if (qflags & BIT_RD) { 437 if (!env->log_forwarder_query_messages) 438 return; 439 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY); 440 } else { 441 if (!env->log_resolver_query_messages) 442 return; 443 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY); 444 } 445 446 /* query_zone */ 447 dm.m.query_zone.data = zone; 448 dm.m.query_zone.len = zone_len; 449 dm.m.has_query_zone = 1; 450 451 /* query_time_sec, query_time_nsec */ 452 dt_fill_timeval(&qtime, 453 &dm.m.query_time_sec, &dm.m.has_query_time_sec, 454 &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 455 456 /* query_message */ 457 dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); 458 459 /* socket_family, socket_protocol, response_address, response_port */ 460 log_assert(cptype == comm_udp || cptype == comm_tcp); 461 dt_msg_fill_net(&dm, rsock, cptype, 462 &dm.m.response_address, &dm.m.has_response_address, 463 &dm.m.response_port, &dm.m.has_response_port); 464 465 if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 466 dt_send(env, dm.buf, dm.len_buf); 467 } 468 469 void 470 dt_msg_send_outside_response(struct dt_env *env, 471 struct sockaddr_storage *rsock, 472 enum comm_point_type cptype, 473 uint8_t *zone, size_t zone_len, 474 uint8_t *qbuf, size_t qbuf_len, 475 const struct timeval *qtime, 476 const struct timeval *rtime, 477 sldns_buffer *rmsg) 478 { 479 struct dt_msg dm; 480 uint16_t qflags; 481 482 log_assert(qbuf_len >= sizeof(qflags)); 483 memcpy(&qflags, qbuf, sizeof(qflags)); 484 qflags = ntohs(qflags); 485 486 /* type */ 487 if (qflags & BIT_RD) { 488 if (!env->log_forwarder_response_messages) 489 return; 490 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE); 491 } else { 492 if (!env->log_resolver_response_messages) 493 return; 494 dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE); 495 } 496 497 /* query_zone */ 498 dm.m.query_zone.data = zone; 499 dm.m.query_zone.len = zone_len; 500 dm.m.has_query_zone = 1; 501 502 /* query_time_sec, query_time_nsec */ 503 dt_fill_timeval(qtime, 504 &dm.m.query_time_sec, &dm.m.has_query_time_sec, 505 &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 506 507 /* response_time_sec, response_time_nsec */ 508 dt_fill_timeval(rtime, 509 &dm.m.response_time_sec, &dm.m.has_response_time_sec, 510 &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); 511 512 /* response_message */ 513 dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); 514 515 /* socket_family, socket_protocol, response_address, response_port */ 516 log_assert(cptype == comm_udp || cptype == comm_tcp); 517 dt_msg_fill_net(&dm, rsock, cptype, 518 &dm.m.response_address, &dm.m.has_response_address, 519 &dm.m.response_port, &dm.m.has_response_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 #endif /* USE_DNSTAP */ 526