1ff825849SDag-Erling Smørgrav /* dnstap support for Unbound */ 2ff825849SDag-Erling Smørgrav 3ff825849SDag-Erling Smørgrav /* 4ff825849SDag-Erling Smørgrav * Copyright (c) 2013-2014, Farsight Security, Inc. 5ff825849SDag-Erling Smørgrav * All rights reserved. 6ff825849SDag-Erling Smørgrav * 7ff825849SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 8ff825849SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 9ff825849SDag-Erling Smørgrav * are met: 10ff825849SDag-Erling Smørgrav * 11ff825849SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 12ff825849SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 13ff825849SDag-Erling Smørgrav * 14ff825849SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 15ff825849SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 16ff825849SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 17ff825849SDag-Erling Smørgrav * 18ff825849SDag-Erling Smørgrav * 3. Neither the name of the copyright holder nor the names of its 19ff825849SDag-Erling Smørgrav * contributors may be used to endorse or promote products derived from 20ff825849SDag-Erling Smørgrav * this software without specific prior written permission. 21ff825849SDag-Erling Smørgrav * 22ff825849SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23ff825849SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24ff825849SDag-Erling Smørgrav * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25ff825849SDag-Erling Smørgrav * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26ff825849SDag-Erling Smørgrav * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27ff825849SDag-Erling Smørgrav * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28ff825849SDag-Erling Smørgrav * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29ff825849SDag-Erling Smørgrav * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30ff825849SDag-Erling Smørgrav * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31ff825849SDag-Erling Smørgrav * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32ff825849SDag-Erling Smørgrav * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33ff825849SDag-Erling Smørgrav */ 34ff825849SDag-Erling Smørgrav 35ff825849SDag-Erling Smørgrav #include "dnstap/dnstap_config.h" 36ff825849SDag-Erling Smørgrav 37ff825849SDag-Erling Smørgrav #ifdef USE_DNSTAP 38ff825849SDag-Erling Smørgrav 39ff825849SDag-Erling Smørgrav #include "config.h" 40ff825849SDag-Erling Smørgrav #include <string.h> 41ff825849SDag-Erling Smørgrav #include <sys/time.h> 42e86b9096SDag-Erling Smørgrav #ifdef HAVE_SYS_STAT_H 43e86b9096SDag-Erling Smørgrav #include <sys/stat.h> 44e86b9096SDag-Erling Smørgrav #endif 45e86b9096SDag-Erling Smørgrav #include <errno.h> 4609a3aaf3SDag-Erling Smørgrav #include "sldns/sbuffer.h" 47ff825849SDag-Erling Smørgrav #include "util/config_file.h" 48ff825849SDag-Erling Smørgrav #include "util/net_help.h" 49ff825849SDag-Erling Smørgrav #include "util/netevent.h" 50ff825849SDag-Erling Smørgrav #include "util/log.h" 51ff825849SDag-Erling Smørgrav 52ff825849SDag-Erling Smørgrav #include <protobuf-c/protobuf-c.h> 53ff825849SDag-Erling Smørgrav 54ff825849SDag-Erling Smørgrav #include "dnstap/dnstap.h" 5525039b37SCy Schubert #include "dnstap/dtstream.h" 56ff825849SDag-Erling Smørgrav #include "dnstap/dnstap.pb-c.h" 57ff825849SDag-Erling Smørgrav 58ff825849SDag-Erling Smørgrav #define DNSTAP_INITIAL_BUF_SIZE 256 59ff825849SDag-Erling Smørgrav 60ff825849SDag-Erling Smørgrav struct dt_msg { 61ff825849SDag-Erling Smørgrav void *buf; 62ff825849SDag-Erling Smørgrav size_t len_buf; 63ff825849SDag-Erling Smørgrav Dnstap__Dnstap d; 64ff825849SDag-Erling Smørgrav Dnstap__Message m; 65ff825849SDag-Erling Smørgrav }; 66ff825849SDag-Erling Smørgrav 67ff825849SDag-Erling Smørgrav static int 68ff825849SDag-Erling Smørgrav dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz) 69ff825849SDag-Erling Smørgrav { 70ff825849SDag-Erling Smørgrav ProtobufCBufferSimple sbuf; 71ff825849SDag-Erling Smørgrav 72ff825849SDag-Erling Smørgrav memset(&sbuf, 0, sizeof(sbuf)); 73ff825849SDag-Erling Smørgrav sbuf.base.append = protobuf_c_buffer_simple_append; 74ff825849SDag-Erling Smørgrav sbuf.len = 0; 75ff825849SDag-Erling Smørgrav sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE; 76ff825849SDag-Erling Smørgrav sbuf.data = malloc(sbuf.alloced); 77ff825849SDag-Erling Smørgrav if (sbuf.data == NULL) 78ff825849SDag-Erling Smørgrav return 0; 79ff825849SDag-Erling Smørgrav sbuf.must_free_data = 1; 80ff825849SDag-Erling Smørgrav 81ff825849SDag-Erling Smørgrav *sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf); 82ff825849SDag-Erling Smørgrav if (sbuf.data == NULL) 83ff825849SDag-Erling Smørgrav return 0; 84ff825849SDag-Erling Smørgrav *buf = sbuf.data; 85ff825849SDag-Erling Smørgrav 86ff825849SDag-Erling Smørgrav return 1; 87ff825849SDag-Erling Smørgrav } 88ff825849SDag-Erling Smørgrav 8956850988SCy Schubert /** See if the message is sent due to dnstap sample rate */ 9056850988SCy Schubert static int 9156850988SCy Schubert dt_sample_rate_limited(struct dt_env* env) 9256850988SCy Schubert { 9356850988SCy Schubert lock_basic_lock(&env->sample_lock); 9456850988SCy Schubert /* Sampling is every [n] packets. Where n==1, every packet is sent */ 9556850988SCy Schubert if(env->sample_rate > 1) { 9656850988SCy Schubert int submit = 0; 9756850988SCy Schubert /* if sampling is engaged... */ 9856850988SCy Schubert if (env->sample_rate_count > env->sample_rate) { 9956850988SCy Schubert /* once the count passes the limit */ 10056850988SCy Schubert /* submit the message */ 10156850988SCy Schubert submit = 1; 10256850988SCy Schubert /* and reset the count */ 10356850988SCy Schubert env->sample_rate_count = 0; 10456850988SCy Schubert } 10556850988SCy Schubert /* increment count regardless */ 10656850988SCy Schubert env->sample_rate_count++; 10756850988SCy Schubert lock_basic_unlock(&env->sample_lock); 10856850988SCy Schubert return !submit; 10956850988SCy Schubert } 11056850988SCy Schubert lock_basic_unlock(&env->sample_lock); 11156850988SCy Schubert return 0; 11256850988SCy Schubert } 11356850988SCy Schubert 114ff825849SDag-Erling Smørgrav static void 115ff825849SDag-Erling Smørgrav dt_send(const struct dt_env *env, void *buf, size_t len_buf) 116ff825849SDag-Erling Smørgrav { 11725039b37SCy Schubert dt_msg_queue_submit(env->msgqueue, buf, len_buf); 118ff825849SDag-Erling Smørgrav } 119ff825849SDag-Erling Smørgrav 120ff825849SDag-Erling Smørgrav static void 121ff825849SDag-Erling Smørgrav dt_msg_init(const struct dt_env *env, 122ff825849SDag-Erling Smørgrav struct dt_msg *dm, 123ff825849SDag-Erling Smørgrav Dnstap__Message__Type mtype) 124ff825849SDag-Erling Smørgrav { 125ff825849SDag-Erling Smørgrav memset(dm, 0, sizeof(*dm)); 126ff825849SDag-Erling Smørgrav dm->d.base.descriptor = &dnstap__dnstap__descriptor; 127ff825849SDag-Erling Smørgrav dm->m.base.descriptor = &dnstap__message__descriptor; 128ff825849SDag-Erling Smørgrav dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE; 129ff825849SDag-Erling Smørgrav dm->d.message = &dm->m; 130ff825849SDag-Erling Smørgrav dm->m.type = mtype; 131ff825849SDag-Erling Smørgrav if (env->identity != NULL) { 132ff825849SDag-Erling Smørgrav dm->d.identity.data = (uint8_t *) env->identity; 133ff825849SDag-Erling Smørgrav dm->d.identity.len = (size_t) env->len_identity; 134ff825849SDag-Erling Smørgrav dm->d.has_identity = 1; 135ff825849SDag-Erling Smørgrav } 136ff825849SDag-Erling Smørgrav if (env->version != NULL) { 137ff825849SDag-Erling Smørgrav dm->d.version.data = (uint8_t *) env->version; 138ff825849SDag-Erling Smørgrav dm->d.version.len = (size_t) env->len_version; 139ff825849SDag-Erling Smørgrav dm->d.has_version = 1; 140ff825849SDag-Erling Smørgrav } 141ff825849SDag-Erling Smørgrav } 142ff825849SDag-Erling Smørgrav 143e86b9096SDag-Erling Smørgrav /* check that the socket file can be opened and exists, print error if not */ 144e86b9096SDag-Erling Smørgrav static void 145e86b9096SDag-Erling Smørgrav check_socket_file(const char* socket_path) 146e86b9096SDag-Erling Smørgrav { 147e86b9096SDag-Erling Smørgrav struct stat statbuf; 148e86b9096SDag-Erling Smørgrav memset(&statbuf, 0, sizeof(statbuf)); 149e86b9096SDag-Erling Smørgrav if(stat(socket_path, &statbuf) < 0) { 150e86b9096SDag-Erling Smørgrav log_warn("could not open dnstap-socket-path: %s, %s", 151e86b9096SDag-Erling Smørgrav socket_path, strerror(errno)); 152e86b9096SDag-Erling Smørgrav } 153e86b9096SDag-Erling Smørgrav } 154e86b9096SDag-Erling Smørgrav 155ff825849SDag-Erling Smørgrav struct dt_env * 15625039b37SCy Schubert dt_create(struct config_file* cfg) 157ff825849SDag-Erling Smørgrav { 158ff825849SDag-Erling Smørgrav struct dt_env *env; 159ff825849SDag-Erling Smørgrav 16025039b37SCy Schubert if(cfg->dnstap && cfg->dnstap_socket_path && cfg->dnstap_socket_path[0] && 16125039b37SCy Schubert (cfg->dnstap_ip==NULL || cfg->dnstap_ip[0]==0)) { 162369c6923SCy Schubert char* p = cfg->dnstap_socket_path; 163369c6923SCy Schubert if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(p, 164369c6923SCy Schubert cfg->chrootdir, strlen(cfg->chrootdir)) == 0) 165369c6923SCy Schubert p += strlen(cfg->chrootdir); 166f61ef7f6SDag-Erling Smørgrav verbose(VERB_OPS, "attempting to connect to dnstap socket %s", 167c0caa2e2SCy Schubert p); 168c0caa2e2SCy Schubert check_socket_file(p); 16925039b37SCy Schubert } 170ff825849SDag-Erling Smørgrav 171ff825849SDag-Erling Smørgrav env = (struct dt_env *) calloc(1, sizeof(struct dt_env)); 172ff825849SDag-Erling Smørgrav if (!env) 173ff825849SDag-Erling Smørgrav return NULL; 17456850988SCy Schubert lock_basic_init(&env->sample_lock); 175ff825849SDag-Erling Smørgrav 17625039b37SCy Schubert env->dtio = dt_io_thread_create(); 17725039b37SCy Schubert if(!env->dtio) { 17825039b37SCy Schubert log_err("malloc failure"); 179ff825849SDag-Erling Smørgrav free(env); 18025039b37SCy Schubert return NULL; 181ff825849SDag-Erling Smørgrav } 18225039b37SCy Schubert if(!dt_io_thread_apply_cfg(env->dtio, cfg)) { 18325039b37SCy Schubert dt_io_thread_delete(env->dtio); 18425039b37SCy Schubert free(env); 18525039b37SCy Schubert return NULL; 18625039b37SCy Schubert } 18725039b37SCy Schubert dt_apply_cfg(env, cfg); 188ff825849SDag-Erling Smørgrav return env; 189ff825849SDag-Erling Smørgrav } 190ff825849SDag-Erling Smørgrav 191ff825849SDag-Erling Smørgrav static void 192ff825849SDag-Erling Smørgrav dt_apply_identity(struct dt_env *env, struct config_file *cfg) 193ff825849SDag-Erling Smørgrav { 194ff825849SDag-Erling Smørgrav char buf[MAXHOSTNAMELEN+1]; 195*be771a7bSCy Schubert if (!cfg->dnstap_send_identity) { 196*be771a7bSCy Schubert free(env->identity); 197*be771a7bSCy Schubert env->identity = NULL; 198ff825849SDag-Erling Smørgrav return; 199*be771a7bSCy Schubert } 200ff825849SDag-Erling Smørgrav free(env->identity); 201ff825849SDag-Erling Smørgrav if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) { 202ff825849SDag-Erling Smørgrav if (gethostname(buf, MAXHOSTNAMELEN) == 0) { 203ff825849SDag-Erling Smørgrav buf[MAXHOSTNAMELEN] = 0; 204ff825849SDag-Erling Smørgrav env->identity = strdup(buf); 205ff825849SDag-Erling Smørgrav } else { 206ff825849SDag-Erling Smørgrav fatal_exit("dt_apply_identity: gethostname() failed"); 207ff825849SDag-Erling Smørgrav } 208ff825849SDag-Erling Smørgrav } else { 209ff825849SDag-Erling Smørgrav env->identity = strdup(cfg->dnstap_identity); 210ff825849SDag-Erling Smørgrav } 211ff825849SDag-Erling Smørgrav if (env->identity == NULL) 212ff825849SDag-Erling Smørgrav fatal_exit("dt_apply_identity: strdup() failed"); 213ff825849SDag-Erling Smørgrav env->len_identity = (unsigned int)strlen(env->identity); 214ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap identity field set to \"%s\"", 215ff825849SDag-Erling Smørgrav env->identity); 216ff825849SDag-Erling Smørgrav } 217ff825849SDag-Erling Smørgrav 218ff825849SDag-Erling Smørgrav static void 219ff825849SDag-Erling Smørgrav dt_apply_version(struct dt_env *env, struct config_file *cfg) 220ff825849SDag-Erling Smørgrav { 221*be771a7bSCy Schubert if (!cfg->dnstap_send_version) { 222*be771a7bSCy Schubert free(env->version); 223*be771a7bSCy Schubert env->version = NULL; 224ff825849SDag-Erling Smørgrav return; 225*be771a7bSCy Schubert } 226ff825849SDag-Erling Smørgrav free(env->version); 227ff825849SDag-Erling Smørgrav if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0) 228ff825849SDag-Erling Smørgrav env->version = strdup(PACKAGE_STRING); 229ff825849SDag-Erling Smørgrav else 230ff825849SDag-Erling Smørgrav env->version = strdup(cfg->dnstap_version); 231ff825849SDag-Erling Smørgrav if (env->version == NULL) 232ff825849SDag-Erling Smørgrav fatal_exit("dt_apply_version: strdup() failed"); 233ff825849SDag-Erling Smørgrav env->len_version = (unsigned int)strlen(env->version); 234ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap version field set to \"%s\"", 235ff825849SDag-Erling Smørgrav env->version); 236ff825849SDag-Erling Smørgrav } 237ff825849SDag-Erling Smørgrav 238ff825849SDag-Erling Smørgrav void 239*be771a7bSCy Schubert dt_apply_logcfg(struct dt_env *env, struct config_file *cfg) 240ff825849SDag-Erling Smørgrav { 241ff825849SDag-Erling Smørgrav if ((env->log_resolver_query_messages = (unsigned int) 242ff825849SDag-Erling Smørgrav cfg->dnstap_log_resolver_query_messages)) 243ff825849SDag-Erling Smørgrav { 244ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled"); 245ff825849SDag-Erling Smørgrav } 246ff825849SDag-Erling Smørgrav if ((env->log_resolver_response_messages = (unsigned int) 247ff825849SDag-Erling Smørgrav cfg->dnstap_log_resolver_response_messages)) 248ff825849SDag-Erling Smørgrav { 249ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled"); 250ff825849SDag-Erling Smørgrav } 251ff825849SDag-Erling Smørgrav if ((env->log_client_query_messages = (unsigned int) 252ff825849SDag-Erling Smørgrav cfg->dnstap_log_client_query_messages)) 253ff825849SDag-Erling Smørgrav { 254ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled"); 255ff825849SDag-Erling Smørgrav } 256ff825849SDag-Erling Smørgrav if ((env->log_client_response_messages = (unsigned int) 257ff825849SDag-Erling Smørgrav cfg->dnstap_log_client_response_messages)) 258ff825849SDag-Erling Smørgrav { 259ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled"); 260ff825849SDag-Erling Smørgrav } 261ff825849SDag-Erling Smørgrav if ((env->log_forwarder_query_messages = (unsigned int) 262ff825849SDag-Erling Smørgrav cfg->dnstap_log_forwarder_query_messages)) 263ff825849SDag-Erling Smørgrav { 264ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled"); 265ff825849SDag-Erling Smørgrav } 266ff825849SDag-Erling Smørgrav if ((env->log_forwarder_response_messages = (unsigned int) 267ff825849SDag-Erling Smørgrav cfg->dnstap_log_forwarder_response_messages)) 268ff825849SDag-Erling Smørgrav { 269ff825849SDag-Erling Smørgrav verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled"); 270ff825849SDag-Erling Smørgrav } 27156850988SCy Schubert lock_basic_lock(&env->sample_lock); 27256850988SCy Schubert if((env->sample_rate = (unsigned int)cfg->dnstap_sample_rate)) 27356850988SCy Schubert { 27456850988SCy Schubert verbose(VERB_OPS, "dnstap SAMPLE_RATE enabled and set to \"%d\"", (int)env->sample_rate); 27556850988SCy Schubert } 27656850988SCy Schubert lock_basic_unlock(&env->sample_lock); 277ff825849SDag-Erling Smørgrav } 278ff825849SDag-Erling Smørgrav 279*be771a7bSCy Schubert void 280*be771a7bSCy Schubert dt_apply_cfg(struct dt_env *env, struct config_file *cfg) 281*be771a7bSCy Schubert { 282*be771a7bSCy Schubert if (!cfg->dnstap) 283*be771a7bSCy Schubert return; 284*be771a7bSCy Schubert 285*be771a7bSCy Schubert dt_apply_identity(env, cfg); 286*be771a7bSCy Schubert dt_apply_version(env, cfg); 287*be771a7bSCy Schubert dt_apply_logcfg(env, cfg); 288*be771a7bSCy Schubert } 289*be771a7bSCy Schubert 290ff825849SDag-Erling Smørgrav int 291c0caa2e2SCy Schubert dt_init(struct dt_env *env, struct comm_base* base) 292ff825849SDag-Erling Smørgrav { 293c0caa2e2SCy Schubert env->msgqueue = dt_msg_queue_create(base); 29425039b37SCy Schubert if(!env->msgqueue) { 29525039b37SCy Schubert log_err("malloc failure"); 296ff825849SDag-Erling Smørgrav return 0; 29725039b37SCy Schubert } 29825039b37SCy Schubert if(!dt_io_thread_register_queue(env->dtio, env->msgqueue)) { 29925039b37SCy Schubert log_err("malloc failure"); 30025039b37SCy Schubert dt_msg_queue_delete(env->msgqueue); 30125039b37SCy Schubert env->msgqueue = NULL; 30225039b37SCy Schubert return 0; 30325039b37SCy Schubert } 304ff825849SDag-Erling Smørgrav return 1; 305ff825849SDag-Erling Smørgrav } 306ff825849SDag-Erling Smørgrav 307ff825849SDag-Erling Smørgrav void 30825039b37SCy Schubert dt_deinit(struct dt_env* env) 30925039b37SCy Schubert { 31025039b37SCy Schubert dt_io_thread_unregister_queue(env->dtio, env->msgqueue); 31125039b37SCy Schubert dt_msg_queue_delete(env->msgqueue); 31225039b37SCy Schubert } 31325039b37SCy Schubert 31425039b37SCy Schubert void 315ff825849SDag-Erling Smørgrav dt_delete(struct dt_env *env) 316ff825849SDag-Erling Smørgrav { 317ff825849SDag-Erling Smørgrav if (!env) 318ff825849SDag-Erling Smørgrav return; 31925039b37SCy Schubert dt_io_thread_delete(env->dtio); 32056850988SCy Schubert lock_basic_destroy(&env->sample_lock); 321ff825849SDag-Erling Smørgrav free(env->identity); 322ff825849SDag-Erling Smørgrav free(env->version); 323ff825849SDag-Erling Smørgrav free(env); 324ff825849SDag-Erling Smørgrav } 325ff825849SDag-Erling Smørgrav 326ff825849SDag-Erling Smørgrav static void 327ff825849SDag-Erling Smørgrav dt_fill_timeval(const struct timeval *tv, 328ff825849SDag-Erling Smørgrav uint64_t *time_sec, protobuf_c_boolean *has_time_sec, 329ff825849SDag-Erling Smørgrav uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec) 330ff825849SDag-Erling Smørgrav { 331ff825849SDag-Erling Smørgrav #ifndef S_SPLINT_S 332ff825849SDag-Erling Smørgrav *time_sec = tv->tv_sec; 333ff825849SDag-Erling Smørgrav *time_nsec = tv->tv_usec * 1000; 334ff825849SDag-Erling Smørgrav #endif 335ff825849SDag-Erling Smørgrav *has_time_sec = 1; 336ff825849SDag-Erling Smørgrav *has_time_nsec = 1; 337ff825849SDag-Erling Smørgrav } 338ff825849SDag-Erling Smørgrav 339ff825849SDag-Erling Smørgrav static void 340ff825849SDag-Erling Smørgrav dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has) 341ff825849SDag-Erling Smørgrav { 342ff825849SDag-Erling Smørgrav log_assert(b != NULL); 343ff825849SDag-Erling Smørgrav p->len = sldns_buffer_limit(b); 344ff825849SDag-Erling Smørgrav p->data = sldns_buffer_begin(b); 345ff825849SDag-Erling Smørgrav *has = 1; 346ff825849SDag-Erling Smørgrav } 347ff825849SDag-Erling Smørgrav 348ff825849SDag-Erling Smørgrav static void 349ff825849SDag-Erling Smørgrav dt_msg_fill_net(struct dt_msg *dm, 3505469a995SCy Schubert struct sockaddr_storage *qs, 3515469a995SCy Schubert struct sockaddr_storage *rs, 352ff825849SDag-Erling Smørgrav enum comm_point_type cptype, 353b7c0c8c1SCy Schubert void *cpssl, 3545469a995SCy Schubert ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr, 3555469a995SCy Schubert uint32_t *qport, protobuf_c_boolean *has_qport, 3565469a995SCy Schubert ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr, 3575469a995SCy Schubert uint32_t *rport, protobuf_c_boolean *has_rport) 358ff825849SDag-Erling Smørgrav { 3595469a995SCy Schubert log_assert(qs->ss_family == AF_INET6 || qs->ss_family == AF_INET); 3605469a995SCy Schubert if (qs->ss_family == AF_INET6) { 3615469a995SCy Schubert struct sockaddr_in6 *q = (struct sockaddr_in6 *) qs; 362ff825849SDag-Erling Smørgrav 363ff825849SDag-Erling Smørgrav /* socket_family */ 364ff825849SDag-Erling Smørgrav dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6; 365ff825849SDag-Erling Smørgrav dm->m.has_socket_family = 1; 366ff825849SDag-Erling Smørgrav 367ff825849SDag-Erling Smørgrav /* addr: query_address or response_address */ 3685469a995SCy Schubert qaddr->data = q->sin6_addr.s6_addr; 3695469a995SCy Schubert qaddr->len = 16; /* IPv6 */ 3705469a995SCy Schubert *has_qaddr = 1; 371ff825849SDag-Erling Smørgrav 372ff825849SDag-Erling Smørgrav /* port: query_port or response_port */ 3735469a995SCy Schubert *qport = ntohs(q->sin6_port); 3745469a995SCy Schubert *has_qport = 1; 3755469a995SCy Schubert } else if (qs->ss_family == AF_INET) { 3765469a995SCy Schubert struct sockaddr_in *q = (struct sockaddr_in *) qs; 377ff825849SDag-Erling Smørgrav 378ff825849SDag-Erling Smørgrav /* socket_family */ 379ff825849SDag-Erling Smørgrav dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET; 380ff825849SDag-Erling Smørgrav dm->m.has_socket_family = 1; 381ff825849SDag-Erling Smørgrav 382ff825849SDag-Erling Smørgrav /* addr: query_address or response_address */ 3835469a995SCy Schubert qaddr->data = (uint8_t *) &q->sin_addr.s_addr; 3845469a995SCy Schubert qaddr->len = 4; /* IPv4 */ 3855469a995SCy Schubert *has_qaddr = 1; 386ff825849SDag-Erling Smørgrav 387ff825849SDag-Erling Smørgrav /* port: query_port or response_port */ 3885469a995SCy Schubert *qport = ntohs(q->sin_port); 3895469a995SCy Schubert *has_qport = 1; 3905469a995SCy Schubert } 3915469a995SCy Schubert 3925469a995SCy Schubert /* 3935469a995SCy Schubert * This block is to fill second set of fields in DNSTAP-message defined as request_/response_ names. 3945469a995SCy Schubert * Additional responsive structure is: struct sockaddr_storage *rs 3955469a995SCy Schubert */ 3965469a995SCy Schubert if (rs && rs->ss_family == AF_INET6) { 3975469a995SCy Schubert struct sockaddr_in6 *r = (struct sockaddr_in6 *) rs; 3985469a995SCy Schubert 3995469a995SCy Schubert /* addr: query_address or response_address */ 4005469a995SCy Schubert raddr->data = r->sin6_addr.s6_addr; 4015469a995SCy Schubert raddr->len = 16; /* IPv6 */ 4025469a995SCy Schubert *has_raddr = 1; 4035469a995SCy Schubert 4045469a995SCy Schubert /* port: query_port or response_port */ 4055469a995SCy Schubert *rport = ntohs(r->sin6_port); 4065469a995SCy Schubert *has_rport = 1; 4075469a995SCy Schubert } else if (rs && rs->ss_family == AF_INET) { 4085469a995SCy Schubert struct sockaddr_in *r = (struct sockaddr_in *) rs; 4095469a995SCy Schubert 4105469a995SCy Schubert /* addr: query_address or response_address */ 4115469a995SCy Schubert raddr->data = (uint8_t *) &r->sin_addr.s_addr; 4125469a995SCy Schubert raddr->len = 4; /* IPv4 */ 4135469a995SCy Schubert *has_raddr = 1; 4145469a995SCy Schubert 4155469a995SCy Schubert /* port: query_port or response_port */ 4165469a995SCy Schubert *rport = ntohs(r->sin_port); 4175469a995SCy Schubert *has_rport = 1; 418ff825849SDag-Erling Smørgrav } 419ff825849SDag-Erling Smørgrav 420ff825849SDag-Erling Smørgrav if (cptype == comm_udp) { 421ff825849SDag-Erling Smørgrav /* socket_protocol */ 422ff825849SDag-Erling Smørgrav dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP; 423ff825849SDag-Erling Smørgrav dm->m.has_socket_protocol = 1; 424ff825849SDag-Erling Smørgrav } else if (cptype == comm_tcp) { 425b7c0c8c1SCy Schubert if (cpssl == NULL) { 426ff825849SDag-Erling Smørgrav /* socket_protocol */ 427ff825849SDag-Erling Smørgrav dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; 428ff825849SDag-Erling Smørgrav dm->m.has_socket_protocol = 1; 429b7c0c8c1SCy Schubert } else { 430b7c0c8c1SCy Schubert /* socket_protocol */ 431b7c0c8c1SCy Schubert dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT; 432b7c0c8c1SCy Schubert dm->m.has_socket_protocol = 1; 433b7c0c8c1SCy Schubert } 434b7c0c8c1SCy Schubert } else if (cptype == comm_http) { 435b7c0c8c1SCy Schubert /* socket_protocol */ 436b7c0c8c1SCy Schubert dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH; 437b7c0c8c1SCy Schubert dm->m.has_socket_protocol = 1; 438b7c0c8c1SCy Schubert } else { 439b7c0c8c1SCy Schubert /* other socket protocol */ 440b7c0c8c1SCy Schubert dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; 441b7c0c8c1SCy Schubert dm->m.has_socket_protocol = 1; 442ff825849SDag-Erling Smørgrav } 443ff825849SDag-Erling Smørgrav } 444ff825849SDag-Erling Smørgrav 445ff825849SDag-Erling Smørgrav void 446ff825849SDag-Erling Smørgrav dt_msg_send_client_query(struct dt_env *env, 447ff825849SDag-Erling Smørgrav struct sockaddr_storage *qsock, 4485469a995SCy Schubert struct sockaddr_storage *rsock, 449ff825849SDag-Erling Smørgrav enum comm_point_type cptype, 450b7c0c8c1SCy Schubert void *cpssl, 4518f76bb7dSCy Schubert sldns_buffer *qmsg, 4528f76bb7dSCy Schubert struct timeval* tstamp) 453ff825849SDag-Erling Smørgrav { 454ff825849SDag-Erling Smørgrav struct dt_msg dm; 455ff825849SDag-Erling Smørgrav struct timeval qtime; 456ff825849SDag-Erling Smørgrav 45756850988SCy Schubert if(dt_sample_rate_limited(env)) 45856850988SCy Schubert return; 45956850988SCy Schubert 4608f76bb7dSCy Schubert if(tstamp) 4618f76bb7dSCy Schubert memcpy(&qtime, tstamp, sizeof(qtime)); 4628f76bb7dSCy Schubert else gettimeofday(&qtime, NULL); 463ff825849SDag-Erling Smørgrav 464ff825849SDag-Erling Smørgrav /* type */ 465ff825849SDag-Erling Smørgrav dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY); 466ff825849SDag-Erling Smørgrav 467ff825849SDag-Erling Smørgrav /* query_time */ 468ff825849SDag-Erling Smørgrav dt_fill_timeval(&qtime, 469ff825849SDag-Erling Smørgrav &dm.m.query_time_sec, &dm.m.has_query_time_sec, 470ff825849SDag-Erling Smørgrav &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 471ff825849SDag-Erling Smørgrav 472ff825849SDag-Erling Smørgrav /* query_message */ 473ff825849SDag-Erling Smørgrav dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); 474ff825849SDag-Erling Smørgrav 4755469a995SCy Schubert /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ 476b7c0c8c1SCy Schubert dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl, 477ff825849SDag-Erling Smørgrav &dm.m.query_address, &dm.m.has_query_address, 4785469a995SCy Schubert &dm.m.query_port, &dm.m.has_query_port, 4795469a995SCy Schubert &dm.m.response_address, &dm.m.has_response_address, 4805469a995SCy Schubert &dm.m.response_port, &dm.m.has_response_port); 4815469a995SCy Schubert 482ff825849SDag-Erling Smørgrav 483ff825849SDag-Erling Smørgrav if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 484ff825849SDag-Erling Smørgrav dt_send(env, dm.buf, dm.len_buf); 485ff825849SDag-Erling Smørgrav } 486ff825849SDag-Erling Smørgrav 487ff825849SDag-Erling Smørgrav void 488ff825849SDag-Erling Smørgrav dt_msg_send_client_response(struct dt_env *env, 489ff825849SDag-Erling Smørgrav struct sockaddr_storage *qsock, 4905469a995SCy Schubert struct sockaddr_storage *rsock, 491ff825849SDag-Erling Smørgrav enum comm_point_type cptype, 492b7c0c8c1SCy Schubert void *cpssl, 493ff825849SDag-Erling Smørgrav sldns_buffer *rmsg) 494ff825849SDag-Erling Smørgrav { 495ff825849SDag-Erling Smørgrav struct dt_msg dm; 496ff825849SDag-Erling Smørgrav struct timeval rtime; 497ff825849SDag-Erling Smørgrav 49856850988SCy Schubert if(dt_sample_rate_limited(env)) 49956850988SCy Schubert return; 50056850988SCy Schubert 501ff825849SDag-Erling Smørgrav gettimeofday(&rtime, NULL); 502ff825849SDag-Erling Smørgrav 503ff825849SDag-Erling Smørgrav /* type */ 504ff825849SDag-Erling Smørgrav dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE); 505ff825849SDag-Erling Smørgrav 506ff825849SDag-Erling Smørgrav /* response_time */ 507ff825849SDag-Erling Smørgrav dt_fill_timeval(&rtime, 508ff825849SDag-Erling Smørgrav &dm.m.response_time_sec, &dm.m.has_response_time_sec, 509ff825849SDag-Erling Smørgrav &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); 510ff825849SDag-Erling Smørgrav 511ff825849SDag-Erling Smørgrav /* response_message */ 512ff825849SDag-Erling Smørgrav dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); 513ff825849SDag-Erling Smørgrav 5145469a995SCy Schubert /* socket_family, socket_protocol, query_address, query_port, response_address, response_port */ 515b7c0c8c1SCy Schubert dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl, 516ff825849SDag-Erling Smørgrav &dm.m.query_address, &dm.m.has_query_address, 5175469a995SCy Schubert &dm.m.query_port, &dm.m.has_query_port, 5185469a995SCy Schubert &dm.m.response_address, &dm.m.has_response_address, 5195469a995SCy Schubert &dm.m.response_port, &dm.m.has_response_port); 520ff825849SDag-Erling Smørgrav 521ff825849SDag-Erling Smørgrav if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 522ff825849SDag-Erling Smørgrav dt_send(env, dm.buf, dm.len_buf); 523ff825849SDag-Erling Smørgrav } 524ff825849SDag-Erling Smørgrav 525ff825849SDag-Erling Smørgrav void 526ff825849SDag-Erling Smørgrav dt_msg_send_outside_query(struct dt_env *env, 527ff825849SDag-Erling Smørgrav struct sockaddr_storage *rsock, 5285469a995SCy Schubert struct sockaddr_storage *qsock, 529ff825849SDag-Erling Smørgrav enum comm_point_type cptype, 530b7c0c8c1SCy Schubert void *cpssl, 531ff825849SDag-Erling Smørgrav uint8_t *zone, size_t zone_len, 532ff825849SDag-Erling Smørgrav sldns_buffer *qmsg) 533ff825849SDag-Erling Smørgrav { 534ff825849SDag-Erling Smørgrav struct dt_msg dm; 535ff825849SDag-Erling Smørgrav struct timeval qtime; 536ff825849SDag-Erling Smørgrav uint16_t qflags; 537ff825849SDag-Erling Smørgrav 53856850988SCy Schubert if(dt_sample_rate_limited(env)) 53956850988SCy Schubert return; 54056850988SCy Schubert 541ff825849SDag-Erling Smørgrav gettimeofday(&qtime, NULL); 542ff825849SDag-Erling Smørgrav qflags = sldns_buffer_read_u16_at(qmsg, 2); 543ff825849SDag-Erling Smørgrav 544ff825849SDag-Erling Smørgrav /* type */ 545ff825849SDag-Erling Smørgrav if (qflags & BIT_RD) { 546ff825849SDag-Erling Smørgrav if (!env->log_forwarder_query_messages) 547ff825849SDag-Erling Smørgrav return; 548ff825849SDag-Erling Smørgrav dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY); 549ff825849SDag-Erling Smørgrav } else { 550ff825849SDag-Erling Smørgrav if (!env->log_resolver_query_messages) 551ff825849SDag-Erling Smørgrav return; 552ff825849SDag-Erling Smørgrav dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY); 553ff825849SDag-Erling Smørgrav } 554ff825849SDag-Erling Smørgrav 555ff825849SDag-Erling Smørgrav /* query_zone */ 556ff825849SDag-Erling Smørgrav dm.m.query_zone.data = zone; 557ff825849SDag-Erling Smørgrav dm.m.query_zone.len = zone_len; 558ff825849SDag-Erling Smørgrav dm.m.has_query_zone = 1; 559ff825849SDag-Erling Smørgrav 560ff825849SDag-Erling Smørgrav /* query_time_sec, query_time_nsec */ 561ff825849SDag-Erling Smørgrav dt_fill_timeval(&qtime, 562ff825849SDag-Erling Smørgrav &dm.m.query_time_sec, &dm.m.has_query_time_sec, 563ff825849SDag-Erling Smørgrav &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 564ff825849SDag-Erling Smørgrav 565ff825849SDag-Erling Smørgrav /* query_message */ 566ff825849SDag-Erling Smørgrav dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); 567ff825849SDag-Erling Smørgrav 5685469a995SCy Schubert /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ 569b7c0c8c1SCy Schubert dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl, 570ff825849SDag-Erling Smørgrav &dm.m.response_address, &dm.m.has_response_address, 5715469a995SCy Schubert &dm.m.response_port, &dm.m.has_response_port, 5725469a995SCy Schubert &dm.m.query_address, &dm.m.has_query_address, 5735469a995SCy Schubert &dm.m.query_port, &dm.m.has_query_port); 574ff825849SDag-Erling Smørgrav 575ff825849SDag-Erling Smørgrav if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 576ff825849SDag-Erling Smørgrav dt_send(env, dm.buf, dm.len_buf); 577ff825849SDag-Erling Smørgrav } 578ff825849SDag-Erling Smørgrav 579ff825849SDag-Erling Smørgrav void 580ff825849SDag-Erling Smørgrav dt_msg_send_outside_response(struct dt_env *env, 581ff825849SDag-Erling Smørgrav struct sockaddr_storage *rsock, 5825469a995SCy Schubert struct sockaddr_storage *qsock, 583ff825849SDag-Erling Smørgrav enum comm_point_type cptype, 584b7c0c8c1SCy Schubert void *cpssl, 585ff825849SDag-Erling Smørgrav uint8_t *zone, size_t zone_len, 586ff825849SDag-Erling Smørgrav uint8_t *qbuf, size_t qbuf_len, 587ff825849SDag-Erling Smørgrav const struct timeval *qtime, 588ff825849SDag-Erling Smørgrav const struct timeval *rtime, 589ff825849SDag-Erling Smørgrav sldns_buffer *rmsg) 590ff825849SDag-Erling Smørgrav { 591ff825849SDag-Erling Smørgrav struct dt_msg dm; 592ff825849SDag-Erling Smørgrav uint16_t qflags; 593ff825849SDag-Erling Smørgrav 59456850988SCy Schubert if(dt_sample_rate_limited(env)) 59556850988SCy Schubert return; 59656850988SCy Schubert 5975469a995SCy Schubert (void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags)); 598ff825849SDag-Erling Smørgrav memcpy(&qflags, qbuf, sizeof(qflags)); 599ff825849SDag-Erling Smørgrav qflags = ntohs(qflags); 600ff825849SDag-Erling Smørgrav 601ff825849SDag-Erling Smørgrav /* type */ 602ff825849SDag-Erling Smørgrav if (qflags & BIT_RD) { 603ff825849SDag-Erling Smørgrav if (!env->log_forwarder_response_messages) 604ff825849SDag-Erling Smørgrav return; 605ff825849SDag-Erling Smørgrav dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE); 606ff825849SDag-Erling Smørgrav } else { 607e2d15004SDag-Erling Smørgrav if (!env->log_resolver_response_messages) 608ff825849SDag-Erling Smørgrav return; 609ff825849SDag-Erling Smørgrav dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE); 610ff825849SDag-Erling Smørgrav } 611ff825849SDag-Erling Smørgrav 612ff825849SDag-Erling Smørgrav /* query_zone */ 613ff825849SDag-Erling Smørgrav dm.m.query_zone.data = zone; 614ff825849SDag-Erling Smørgrav dm.m.query_zone.len = zone_len; 615ff825849SDag-Erling Smørgrav dm.m.has_query_zone = 1; 616ff825849SDag-Erling Smørgrav 617ff825849SDag-Erling Smørgrav /* query_time_sec, query_time_nsec */ 618ff825849SDag-Erling Smørgrav dt_fill_timeval(qtime, 619ff825849SDag-Erling Smørgrav &dm.m.query_time_sec, &dm.m.has_query_time_sec, 620ff825849SDag-Erling Smørgrav &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); 621ff825849SDag-Erling Smørgrav 622ff825849SDag-Erling Smørgrav /* response_time_sec, response_time_nsec */ 623ff825849SDag-Erling Smørgrav dt_fill_timeval(rtime, 624ff825849SDag-Erling Smørgrav &dm.m.response_time_sec, &dm.m.has_response_time_sec, 625ff825849SDag-Erling Smørgrav &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); 626ff825849SDag-Erling Smørgrav 627ff825849SDag-Erling Smørgrav /* response_message */ 628ff825849SDag-Erling Smørgrav dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); 629ff825849SDag-Erling Smørgrav 6305469a995SCy Schubert /* socket_family, socket_protocol, response_address, response_port, query_address, query_port */ 631b7c0c8c1SCy Schubert dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl, 632ff825849SDag-Erling Smørgrav &dm.m.response_address, &dm.m.has_response_address, 6335469a995SCy Schubert &dm.m.response_port, &dm.m.has_response_port, 6345469a995SCy Schubert &dm.m.query_address, &dm.m.has_query_address, 6355469a995SCy Schubert &dm.m.query_port, &dm.m.has_query_port); 636ff825849SDag-Erling Smørgrav 637ff825849SDag-Erling Smørgrav if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) 638ff825849SDag-Erling Smørgrav dt_send(env, dm.buf, dm.len_buf); 639ff825849SDag-Erling Smørgrav } 640ff825849SDag-Erling Smørgrav 641ff825849SDag-Erling Smørgrav #endif /* USE_DNSTAP */ 642