diff options
Diffstat (limited to 'external/unbound/dnstap')
-rw-r--r-- | external/unbound/dnstap/dnstap.c | 501 | ||||
-rw-r--r-- | external/unbound/dnstap/dnstap.h | 188 | ||||
-rw-r--r-- | external/unbound/dnstap/dnstap.m4 | 54 | ||||
-rw-r--r-- | external/unbound/dnstap/dnstap.pb-c.c | 518 | ||||
-rw-r--r-- | external/unbound/dnstap/dnstap.pb-c.h | 158 | ||||
-rw-r--r-- | external/unbound/dnstap/dnstap.proto | 262 | ||||
-rw-r--r-- | external/unbound/dnstap/dnstap_config.h.in | 17 |
7 files changed, 1698 insertions, 0 deletions
diff --git a/external/unbound/dnstap/dnstap.c b/external/unbound/dnstap/dnstap.c new file mode 100644 index 000000000..d999ffd50 --- /dev/null +++ b/external/unbound/dnstap/dnstap.c @@ -0,0 +1,501 @@ +/* dnstap support for Unbound */ + +/* + * Copyright (c) 2013-2014, Farsight Security, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dnstap/dnstap_config.h" + +#ifdef USE_DNSTAP + +#include "config.h" +#include <sys/time.h> +#include "ldns/sbuffer.h" +#include "util/config_file.h" +#include "util/net_help.h" +#include "util/netevent.h" +#include "util/log.h" + +#include <fstrm.h> +#include <protobuf-c/protobuf-c.h> + +#include "dnstap/dnstap.h" +#include "dnstap/dnstap.pb-c.h" + +#define DNSTAP_CONTENT_TYPE "protobuf:dnstap.Dnstap" +#define DNSTAP_INITIAL_BUF_SIZE 256 + +struct dt_msg { + void *buf; + size_t len_buf; + Dnstap__Dnstap d; + Dnstap__Message m; +}; + +static int +dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz) +{ + ProtobufCBufferSimple sbuf; + + sbuf.base.append = protobuf_c_buffer_simple_append; + sbuf.len = 0; + sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE; + sbuf.data = malloc(sbuf.alloced); + if (sbuf.data == NULL) + return 0; + sbuf.must_free_data = 1; + + *sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf); + if (sbuf.data == NULL) + return 0; + *buf = sbuf.data; + + return 1; +} + +static void +dt_send(const struct dt_env *env, void *buf, size_t len_buf) +{ + fstrm_res res; + if (!buf) + return; + res = fstrm_io_submit(env->fio, env->fq, buf, len_buf, + fstrm_free_wrapper, NULL); + if (res != FSTRM_RES_SUCCESS) + free(buf); +} + +static void +dt_msg_init(const struct dt_env *env, + struct dt_msg *dm, + Dnstap__Message__Type mtype) +{ + memset(dm, 0, sizeof(*dm)); + dm->d.base.descriptor = &dnstap__dnstap__descriptor; + dm->m.base.descriptor = &dnstap__message__descriptor; + dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE; + dm->d.message = &dm->m; + dm->m.type = mtype; + if (env->identity != NULL) { + dm->d.identity.data = (uint8_t *) env->identity; + dm->d.identity.len = (size_t) env->len_identity; + dm->d.has_identity = 1; + } + if (env->version != NULL) { + dm->d.version.data = (uint8_t *) env->version; + dm->d.version.len = (size_t) env->len_version; + dm->d.has_version = 1; + } +} + +struct dt_env * +dt_create(const char *socket_path, unsigned num_workers) +{ + char *fio_err; + struct dt_env *env; + struct fstrm_io_options *fopt; + struct fstrm_unix_writer_options *fuwopt; + + verbose(VERB_OPS, "opening dnstap socket %s", socket_path); + log_assert(socket_path != NULL); + log_assert(num_workers > 0); + + env = (struct dt_env *) calloc(1, sizeof(struct dt_env)); + if (!env) + return NULL; + + fuwopt = fstrm_unix_writer_options_init(); + fstrm_unix_writer_options_set_socket_path(fuwopt, socket_path); + fopt = fstrm_io_options_init(); + fstrm_io_options_set_content_type(fopt, + DNSTAP_CONTENT_TYPE, + sizeof(DNSTAP_CONTENT_TYPE) - 1); + fstrm_io_options_set_num_queues(fopt, num_workers); + fstrm_io_options_set_writer(fopt, fstrm_unix_writer, fuwopt); + env->fio = fstrm_io_init(fopt, &fio_err); + if (env->fio == NULL) { + verbose(VERB_DETAIL, "dt_create: fstrm_io_init() failed: %s", + fio_err); + free(fio_err); + free(env); + env = NULL; + } + fstrm_io_options_destroy(&fopt); + fstrm_unix_writer_options_destroy(&fuwopt); + + return env; +} + +static void +dt_apply_identity(struct dt_env *env, struct config_file *cfg) +{ + char buf[MAXHOSTNAMELEN+1]; + if (!cfg->dnstap_send_identity) + return; + free(env->identity); + if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) { + if (gethostname(buf, MAXHOSTNAMELEN) == 0) { + buf[MAXHOSTNAMELEN] = 0; + env->identity = strdup(buf); + } else { + fatal_exit("dt_apply_identity: gethostname() failed"); + } + } else { + env->identity = strdup(cfg->dnstap_identity); + } + if (env->identity == NULL) + fatal_exit("dt_apply_identity: strdup() failed"); + env->len_identity = (unsigned int)strlen(env->identity); + verbose(VERB_OPS, "dnstap identity field set to \"%s\"", + env->identity); +} + +static void +dt_apply_version(struct dt_env *env, struct config_file *cfg) +{ + if (!cfg->dnstap_send_version) + return; + free(env->version); + if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0) + env->version = strdup(PACKAGE_STRING); + else + env->version = strdup(cfg->dnstap_version); + if (env->version == NULL) + fatal_exit("dt_apply_version: strdup() failed"); + env->len_version = (unsigned int)strlen(env->version); + verbose(VERB_OPS, "dnstap version field set to \"%s\"", + env->version); +} + +void +dt_apply_cfg(struct dt_env *env, struct config_file *cfg) +{ + if (!cfg->dnstap) + return; + + dt_apply_identity(env, cfg); + dt_apply_version(env, cfg); + if ((env->log_resolver_query_messages = (unsigned int) + cfg->dnstap_log_resolver_query_messages)) + { + verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled"); + } + if ((env->log_resolver_response_messages = (unsigned int) + cfg->dnstap_log_resolver_response_messages)) + { + verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled"); + } + if ((env->log_client_query_messages = (unsigned int) + cfg->dnstap_log_client_query_messages)) + { + verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled"); + } + if ((env->log_client_response_messages = (unsigned int) + cfg->dnstap_log_client_response_messages)) + { + verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled"); + } + if ((env->log_forwarder_query_messages = (unsigned int) + cfg->dnstap_log_forwarder_query_messages)) + { + verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled"); + } + if ((env->log_forwarder_response_messages = (unsigned int) + cfg->dnstap_log_forwarder_response_messages)) + { + verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled"); + } +} + +int +dt_init(struct dt_env *env) +{ + env->fq = fstrm_io_get_queue(env->fio); + if (env->fq == NULL) + return 0; + return 1; +} + +void +dt_delete(struct dt_env *env) +{ + if (!env) + return; + verbose(VERB_OPS, "closing dnstap socket"); + fstrm_io_destroy(&env->fio); + free(env->identity); + free(env->version); + free(env); +} + +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) +{ +#ifndef S_SPLINT_S + *time_sec = tv->tv_sec; + *time_nsec = tv->tv_usec * 1000; +#endif + *has_time_sec = 1; + *has_time_nsec = 1; +} + +static void +dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has) +{ + log_assert(b != NULL); + p->len = sldns_buffer_limit(b); + p->data = sldns_buffer_begin(b); + *has = 1; +} + +static void +dt_msg_fill_net(struct dt_msg *dm, + struct sockaddr_storage *ss, + enum comm_point_type cptype, + ProtobufCBinaryData *addr, protobuf_c_boolean *has_addr, + uint32_t *port, protobuf_c_boolean *has_port) +{ + log_assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET); + if (ss->ss_family == AF_INET6) { + struct sockaddr_in6 *s = (struct sockaddr_in6 *) ss; + + /* socket_family */ + dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6; + dm->m.has_socket_family = 1; + + /* addr: query_address or response_address */ + addr->data = s->sin6_addr.s6_addr; + addr->len = 16; /* IPv6 */ + *has_addr = 1; + + /* port: query_port or response_port */ + *port = ntohs(s->sin6_port); + *has_port = 1; + } else if (ss->ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *) ss; + + /* socket_family */ + dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET; + dm->m.has_socket_family = 1; + + /* addr: query_address or response_address */ + addr->data = (uint8_t *) &s->sin_addr.s_addr; + addr->len = 4; /* IPv4 */ + *has_addr = 1; + + /* port: query_port or response_port */ + *port = ntohs(s->sin_port); + *has_port = 1; + } + + log_assert(cptype == comm_udp || cptype == comm_tcp); + if (cptype == comm_udp) { + /* socket_protocol */ + dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP; + dm->m.has_socket_protocol = 1; + } else if (cptype == comm_tcp) { + /* socket_protocol */ + dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; + dm->m.has_socket_protocol = 1; + } +} + +void +dt_msg_send_client_query(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + sldns_buffer *qmsg) +{ + struct dt_msg dm; + struct timeval qtime; + + gettimeofday(&qtime, NULL); + + /* type */ + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY); + + /* query_time */ + dt_fill_timeval(&qtime, + &dm.m.query_time_sec, &dm.m.has_query_time_sec, + &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); + + /* query_message */ + dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); + + /* socket_family, socket_protocol, query_address, query_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, qsock, cptype, + &dm.m.query_address, &dm.m.has_query_address, + &dm.m.query_port, &dm.m.has_query_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +void +dt_msg_send_client_response(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + sldns_buffer *rmsg) +{ + struct dt_msg dm; + struct timeval rtime; + + gettimeofday(&rtime, NULL); + + /* type */ + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE); + + /* response_time */ + dt_fill_timeval(&rtime, + &dm.m.response_time_sec, &dm.m.has_response_time_sec, + &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); + + /* response_message */ + dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); + + /* socket_family, socket_protocol, query_address, query_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, qsock, cptype, + &dm.m.query_address, &dm.m.has_query_address, + &dm.m.query_port, &dm.m.has_query_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +void +dt_msg_send_outside_query(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + uint8_t *zone, size_t zone_len, + sldns_buffer *qmsg) +{ + struct dt_msg dm; + struct timeval qtime; + uint16_t qflags; + + gettimeofday(&qtime, NULL); + qflags = sldns_buffer_read_u16_at(qmsg, 2); + + /* type */ + if (qflags & BIT_RD) { + if (!env->log_forwarder_query_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY); + } else { + if (!env->log_resolver_query_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY); + } + + /* query_zone */ + dm.m.query_zone.data = zone; + dm.m.query_zone.len = zone_len; + dm.m.has_query_zone = 1; + + /* query_time_sec, query_time_nsec */ + dt_fill_timeval(&qtime, + &dm.m.query_time_sec, &dm.m.has_query_time_sec, + &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); + + /* query_message */ + dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); + + /* socket_family, socket_protocol, response_address, response_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, rsock, cptype, + &dm.m.response_address, &dm.m.has_response_address, + &dm.m.response_port, &dm.m.has_response_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +void +dt_msg_send_outside_response(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + 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) +{ + struct dt_msg dm; + uint16_t qflags; + + log_assert(qbuf_len >= sizeof(qflags)); + memcpy(&qflags, qbuf, sizeof(qflags)); + qflags = ntohs(qflags); + + /* type */ + if (qflags & BIT_RD) { + if (!env->log_forwarder_response_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE); + } else { + if (!env->log_resolver_query_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE); + } + + /* query_zone */ + dm.m.query_zone.data = zone; + dm.m.query_zone.len = zone_len; + dm.m.has_query_zone = 1; + + /* query_time_sec, query_time_nsec */ + dt_fill_timeval(qtime, + &dm.m.query_time_sec, &dm.m.has_query_time_sec, + &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); + + /* response_time_sec, response_time_nsec */ + dt_fill_timeval(rtime, + &dm.m.response_time_sec, &dm.m.has_response_time_sec, + &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); + + /* response_message */ + dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); + + /* socket_family, socket_protocol, response_address, response_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, rsock, cptype, + &dm.m.response_address, &dm.m.has_response_address, + &dm.m.response_port, &dm.m.has_response_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +#endif /* USE_DNSTAP */ diff --git a/external/unbound/dnstap/dnstap.h b/external/unbound/dnstap/dnstap.h new file mode 100644 index 000000000..d9121df7d --- /dev/null +++ b/external/unbound/dnstap/dnstap.h @@ -0,0 +1,188 @@ +/* dnstap support for Unbound */ + +/* + * Copyright (c) 2013-2014, Farsight Security, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UNBOUND_DNSTAP_H +#define UNBOUND_DNSTAP_H + +#include "dnstap/dnstap_config.h" + +#ifdef USE_DNSTAP + +struct config_file; +struct fstrm_io; +struct fstrm_queue; +struct sldns_buffer; + +struct dt_env { + /** dnstap I/O socket */ + struct fstrm_io *fio; + + /** dnstap I/O queue */ + struct fstrm_queue *fq; + + /** dnstap "identity" field, NULL if disabled */ + char *identity; + + /** dnstap "version" field, NULL if disabled */ + char *version; + + /** length of "identity" field */ + unsigned len_identity; + + /** length of "version" field */ + unsigned len_version; + + /** whether to log Message/RESOLVER_QUERY */ + unsigned log_resolver_query_messages : 1; + /** whether to log Message/RESOLVER_RESPONSE */ + unsigned log_resolver_response_messages : 1; + /** whether to log Message/CLIENT_QUERY */ + unsigned log_client_query_messages : 1; + /** whether to log Message/CLIENT_RESPONSE */ + unsigned log_client_response_messages : 1; + /** whether to log Message/FORWARDER_QUERY */ + unsigned log_forwarder_query_messages : 1; + /** whether to log Message/FORWARDER_RESPONSE */ + unsigned log_forwarder_response_messages : 1; +}; + +/** + * Create dnstap environment object. Afterwards, call dt_apply_cfg() to fill in + * the config variables and dt_init() to fill in the per-worker state. Each + * worker needs a copy of this object but with its own I/O queue (the fq field + * of the structure) to ensure lock-free access to its own per-worker circular + * queue. Duplicate the environment object if more than one worker needs to + * share access to the dnstap I/O socket. + * @param socket_path: path to dnstap logging socket, must be non-NULL. + * @param num_workers: number of worker threads, must be > 0. + * @return dt_env object, NULL on failure. + */ +struct dt_env * +dt_create(const char *socket_path, unsigned num_workers); + +/** + * Apply config settings. + * @param env: dnstap environment object. + * @param cfg: new config settings. + */ +void +dt_apply_cfg(struct dt_env *env, struct config_file *cfg); + +/** + * Initialize per-worker state in dnstap environment object. + * @param env: dnstap environment object to initialize, created with dt_create(). + * @return: true on success, false on failure. + */ +int +dt_init(struct dt_env *env); + +/** + * Delete dnstap environment object. Closes dnstap I/O socket and deletes all + * per-worker I/O queues. + */ +void +dt_delete(struct dt_env *env); + +/** + * Create and send a new dnstap "Message" event of type CLIENT_QUERY. + * @param env: dnstap environment object. + * @param qsock: address/port of client. + * @param cptype: comm_udp or comm_tcp. + * @param qmsg: query message. + */ +void +dt_msg_send_client_query(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + struct sldns_buffer *qmsg); + +/** + * Create and send a new dnstap "Message" event of type CLIENT_RESPONSE. + * @param env: dnstap environment object. + * @param qsock: address/port of client. + * @param cptype: comm_udp or comm_tcp. + * @param rmsg: response message. + */ +void +dt_msg_send_client_response(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + struct sldns_buffer *rmsg); + +/** + * Create and send a new dnstap "Message" event of type RESOLVER_QUERY or + * FORWARDER_QUERY. The type used is dependent on the value of the RD bit + * in the query header. + * @param env: dnstap environment object. + * @param rsock: address/port of server the query is being sent to. + * @param cptype: comm_udp or comm_tcp. + * @param zone: query zone. + * @param zone_len: length of zone. + * @param qmsg: query message. + */ +void +dt_msg_send_outside_query(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + uint8_t *zone, size_t zone_len, + struct sldns_buffer *qmsg); + +/** + * Create and send a new dnstap "Message" event of type RESOLVER_RESPONSE or + * FORWARDER_RESPONSE. The type used is dependent on the value of the RD bit + * in the query header. + * @param env: dnstap environment object. + * @param rsock: address/port of server the response was received from. + * @param cptype: comm_udp or comm_tcp. + * @param zone: query zone. + * @param zone_len: length of zone. + * @param qbuf: outside_network's qbuf key. + * @param qbuf_len: length of outside_network's qbuf key. + * @param qtime: time query message was sent. + * @param rtime: time response message was sent. + * @param rmsg: response message. + */ +void +dt_msg_send_outside_response(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + uint8_t *zone, size_t zone_len, + uint8_t *qbuf, size_t qbuf_len, + const struct timeval *qtime, + const struct timeval *rtime, + struct sldns_buffer *rmsg); + +#endif /* USE_DNSTAP */ + +#endif /* UNBOUND_DNSTAP_H */ diff --git a/external/unbound/dnstap/dnstap.m4 b/external/unbound/dnstap/dnstap.m4 new file mode 100644 index 000000000..de63256dc --- /dev/null +++ b/external/unbound/dnstap/dnstap.m4 @@ -0,0 +1,54 @@ +# dnstap.m4 + +# dt_DNSTAP(default_dnstap_socket_path, [action-if-true], [action-if-false]) +# -------------------------------------------------------------------------- +# Check for required dnstap libraries and add dnstap configure args. +AC_DEFUN([dt_DNSTAP], +[ + AC_ARG_ENABLE([dnstap], + AS_HELP_STRING([--enable-dnstap], + [Enable dnstap support (requires fstrm, protobuf-c)]), + [opt_dnstap=$enableval], [opt_dnstap=no]) + + AC_ARG_WITH([dnstap-socket-path], + AS_HELP_STRING([--with-dnstap-socket-path=pathname], + [set default dnstap socket path]), + [opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"]) + + if test "x$opt_dnstap" != "xno"; then + AC_PATH_PROG([PROTOC_C], [protoc-c]) + if test -z "$PROTOC_C"; then + AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!]) + fi + AC_ARG_WITH([protobuf-c], AC_HELP_STRING([--with-protobuf-c=path], + [Path where protobuf-c is installed, for dnstap]), [ + # workaround for protobuf includes at old dir before protobuf-1.0.0 + if test -f $withval/include/google/protobuf-c/protobuf-c.h; then + CFLAGS="$CFLAGS -I$withval/include/google" + else + CFLAGS="$CFLAGS -I$withval/include" + fi + LDFLAGS="$LDFLAGS -L$withval/lib" + ], [ + # workaround for protobuf includes at old dir before protobuf-1.0.0 + if test -f /usr/include/google/protobuf-c/protobuf-c.h; then + CFLAGS="$CFLAGS -I/usr/include/google" + else + if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then + CFLAGS="$CFLAGS -I/usr/local/include/google" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + fi + fi + ]) + AC_ARG_WITH([libfstrm], AC_HELP_STRING([--with-libfstrm=path], + [Path where libfstrm in installed, for dnstap]), [ + CFLAGS="$CFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" + ]) + AC_SEARCH_LIBS([fstrm_io_init], [fstrm]) + AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c]) + $2 + else + $3 + fi +]) diff --git a/external/unbound/dnstap/dnstap.pb-c.c b/external/unbound/dnstap/dnstap.pb-c.c new file mode 100644 index 000000000..51100eb56 --- /dev/null +++ b/external/unbound/dnstap/dnstap.pb-c.c @@ -0,0 +1,518 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C_NO_DEPRECATED +#define PROTOBUF_C_NO_DEPRECATED +#endif + +#include "dnstap/dnstap.pb-c.h" +void dnstap__dnstap__init + (Dnstap__Dnstap *message) +{ + static Dnstap__Dnstap init_value = DNSTAP__DNSTAP__INIT; + *message = init_value; +} +size_t dnstap__dnstap__get_packed_size + (const Dnstap__Dnstap *message) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__dnstap__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t dnstap__dnstap__pack + (const Dnstap__Dnstap *message, + uint8_t *out) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__dnstap__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t dnstap__dnstap__pack_to_buffer + (const Dnstap__Dnstap *message, + ProtobufCBuffer *buffer) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__dnstap__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Dnstap__Dnstap * + dnstap__dnstap__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Dnstap__Dnstap *) + protobuf_c_message_unpack (&dnstap__dnstap__descriptor, + allocator, len, data); +} +void dnstap__dnstap__free_unpacked + (Dnstap__Dnstap *message, + ProtobufCAllocator *allocator) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__dnstap__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void dnstap__message__init + (Dnstap__Message *message) +{ + static Dnstap__Message init_value = DNSTAP__MESSAGE__INIT; + *message = init_value; +} +size_t dnstap__message__get_packed_size + (const Dnstap__Message *message) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__message__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t dnstap__message__pack + (const Dnstap__Message *message, + uint8_t *out) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__message__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t dnstap__message__pack_to_buffer + (const Dnstap__Message *message, + ProtobufCBuffer *buffer) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__message__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Dnstap__Message * + dnstap__message__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Dnstap__Message *) + protobuf_c_message_unpack (&dnstap__message__descriptor, + allocator, len, data); +} +void dnstap__message__free_unpacked + (Dnstap__Message *message, + ProtobufCAllocator *allocator) +{ + PROTOBUF_C_ASSERT (message->base.descriptor == &dnstap__message__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +const ProtobufCEnumValue dnstap__dnstap__type__enum_values_by_number[1] = +{ + { "MESSAGE", "DNSTAP__DNSTAP__TYPE__MESSAGE", 1 }, +}; +static const ProtobufCIntRange dnstap__dnstap__type__value_ranges[] = { +{1, 0},{0, 1} +}; +const ProtobufCEnumValueIndex dnstap__dnstap__type__enum_values_by_name[1] = +{ + { "MESSAGE", 0 }, +}; +const ProtobufCEnumDescriptor dnstap__dnstap__type__descriptor = +{ + PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC, + "dnstap.Dnstap.Type", + "Type", + "Dnstap__Dnstap__Type", + "dnstap", + 1, + dnstap__dnstap__type__enum_values_by_number, + 1, + dnstap__dnstap__type__enum_values_by_name, + 1, + dnstap__dnstap__type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor dnstap__dnstap__field_descriptors[5] = +{ + { + "identity", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, has_identity), + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, identity), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "version", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, has_version), + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, version), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "extra", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, has_extra), + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, extra), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "message", + 14, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, message), + &dnstap__message__descriptor, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "type", + 15, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + PROTOBUF_C_OFFSETOF(Dnstap__Dnstap, type), + &dnstap__dnstap__type__descriptor, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned dnstap__dnstap__field_indices_by_name[] = { + 2, /* field[2] = extra */ + 0, /* field[0] = identity */ + 3, /* field[3] = message */ + 4, /* field[4] = type */ + 1, /* field[1] = version */ +}; +static const ProtobufCIntRange dnstap__dnstap__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 14, 3 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor dnstap__dnstap__descriptor = +{ + PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC, + "dnstap.Dnstap", + "Dnstap", + "Dnstap__Dnstap", + "dnstap", + sizeof(Dnstap__Dnstap), + 5, + dnstap__dnstap__field_descriptors, + dnstap__dnstap__field_indices_by_name, + 2, dnstap__dnstap__number_ranges, + (ProtobufCMessageInit) dnstap__dnstap__init, + NULL,NULL,NULL /* reserved[123] */ +}; +const ProtobufCEnumValue dnstap__message__type__enum_values_by_number[10] = +{ + { "AUTH_QUERY", "DNSTAP__MESSAGE__TYPE__AUTH_QUERY", 1 }, + { "AUTH_RESPONSE", "DNSTAP__MESSAGE__TYPE__AUTH_RESPONSE", 2 }, + { "RESOLVER_QUERY", "DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY", 3 }, + { "RESOLVER_RESPONSE", "DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE", 4 }, + { "CLIENT_QUERY", "DNSTAP__MESSAGE__TYPE__CLIENT_QUERY", 5 }, + { "CLIENT_RESPONSE", "DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE", 6 }, + { "FORWARDER_QUERY", "DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY", 7 }, + { "FORWARDER_RESPONSE", "DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE", 8 }, + { "STUB_QUERY", "DNSTAP__MESSAGE__TYPE__STUB_QUERY", 9 }, + { "STUB_RESPONSE", "DNSTAP__MESSAGE__TYPE__STUB_RESPONSE", 10 }, +}; +static const ProtobufCIntRange dnstap__message__type__value_ranges[] = { +{1, 0},{0, 10} +}; +const ProtobufCEnumValueIndex dnstap__message__type__enum_values_by_name[10] = +{ + { "AUTH_QUERY", 0 }, + { "AUTH_RESPONSE", 1 }, + { "CLIENT_QUERY", 4 }, + { "CLIENT_RESPONSE", 5 }, + { "FORWARDER_QUERY", 6 }, + { "FORWARDER_RESPONSE", 7 }, + { "RESOLVER_QUERY", 2 }, + { "RESOLVER_RESPONSE", 3 }, + { "STUB_QUERY", 8 }, + { "STUB_RESPONSE", 9 }, +}; +const ProtobufCEnumDescriptor dnstap__message__type__descriptor = +{ + PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC, + "dnstap.Message.Type", + "Type", + "Dnstap__Message__Type", + "dnstap", + 10, + dnstap__message__type__enum_values_by_number, + 10, + dnstap__message__type__enum_values_by_name, + 1, + dnstap__message__type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCFieldDescriptor dnstap__message__field_descriptors[14] = +{ + { + "type", + 1, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + PROTOBUF_C_OFFSETOF(Dnstap__Message, type), + &dnstap__message__type__descriptor, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "socket_family", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_socket_family), + PROTOBUF_C_OFFSETOF(Dnstap__Message, socket_family), + &dnstap__socket_family__descriptor, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "socket_protocol", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_socket_protocol), + PROTOBUF_C_OFFSETOF(Dnstap__Message, socket_protocol), + &dnstap__socket_protocol__descriptor, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "query_address", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_query_address), + PROTOBUF_C_OFFSETOF(Dnstap__Message, query_address), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "response_address", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_response_address), + PROTOBUF_C_OFFSETOF(Dnstap__Message, response_address), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "query_port", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_query_port), + PROTOBUF_C_OFFSETOF(Dnstap__Message, query_port), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "response_port", + 7, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_response_port), + PROTOBUF_C_OFFSETOF(Dnstap__Message, response_port), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "query_time_sec", + 8, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_query_time_sec), + PROTOBUF_C_OFFSETOF(Dnstap__Message, query_time_sec), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "query_time_nsec", + 9, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_FIXED32, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_query_time_nsec), + PROTOBUF_C_OFFSETOF(Dnstap__Message, query_time_nsec), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "query_message", + 10, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_query_message), + PROTOBUF_C_OFFSETOF(Dnstap__Message, query_message), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "query_zone", + 11, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_query_zone), + PROTOBUF_C_OFFSETOF(Dnstap__Message, query_zone), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "response_time_sec", + 12, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_response_time_sec), + PROTOBUF_C_OFFSETOF(Dnstap__Message, response_time_sec), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "response_time_nsec", + 13, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_FIXED32, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_response_time_nsec), + PROTOBUF_C_OFFSETOF(Dnstap__Message, response_time_nsec), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "response_message", + 14, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_OFFSETOF(Dnstap__Message, has_response_message), + PROTOBUF_C_OFFSETOF(Dnstap__Message, response_message), + NULL, + NULL, + 0, /* packed */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned dnstap__message__field_indices_by_name[] = { + 3, /* field[3] = query_address */ + 9, /* field[9] = query_message */ + 5, /* field[5] = query_port */ + 8, /* field[8] = query_time_nsec */ + 7, /* field[7] = query_time_sec */ + 10, /* field[10] = query_zone */ + 4, /* field[4] = response_address */ + 13, /* field[13] = response_message */ + 6, /* field[6] = response_port */ + 12, /* field[12] = response_time_nsec */ + 11, /* field[11] = response_time_sec */ + 1, /* field[1] = socket_family */ + 2, /* field[2] = socket_protocol */ + 0, /* field[0] = type */ +}; +static const ProtobufCIntRange dnstap__message__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 14 } +}; +const ProtobufCMessageDescriptor dnstap__message__descriptor = +{ + PROTOBUF_C_MESSAGE_DESCRIPTOR_MAGIC, + "dnstap.Message", + "Message", + "Dnstap__Message", + "dnstap", + sizeof(Dnstap__Message), + 14, + dnstap__message__field_descriptors, + dnstap__message__field_indices_by_name, + 1, dnstap__message__number_ranges, + (ProtobufCMessageInit) dnstap__message__init, + NULL,NULL,NULL /* reserved[123] */ +}; +const ProtobufCEnumValue dnstap__socket_family__enum_values_by_number[2] = +{ + { "INET", "DNSTAP__SOCKET_FAMILY__INET", 1 }, + { "INET6", "DNSTAP__SOCKET_FAMILY__INET6", 2 }, +}; +static const ProtobufCIntRange dnstap__socket_family__value_ranges[] = { +{1, 0},{0, 2} +}; +const ProtobufCEnumValueIndex dnstap__socket_family__enum_values_by_name[2] = +{ + { "INET", 0 }, + { "INET6", 1 }, +}; +const ProtobufCEnumDescriptor dnstap__socket_family__descriptor = +{ + PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC, + "dnstap.SocketFamily", + "SocketFamily", + "Dnstap__SocketFamily", + "dnstap", + 2, + dnstap__socket_family__enum_values_by_number, + 2, + dnstap__socket_family__enum_values_by_name, + 1, + dnstap__socket_family__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +const ProtobufCEnumValue dnstap__socket_protocol__enum_values_by_number[2] = +{ + { "UDP", "DNSTAP__SOCKET_PROTOCOL__UDP", 1 }, + { "TCP", "DNSTAP__SOCKET_PROTOCOL__TCP", 2 }, +}; +static const ProtobufCIntRange dnstap__socket_protocol__value_ranges[] = { +{1, 0},{0, 2} +}; +const ProtobufCEnumValueIndex dnstap__socket_protocol__enum_values_by_name[2] = +{ + { "TCP", 1 }, + { "UDP", 0 }, +}; +const ProtobufCEnumDescriptor dnstap__socket_protocol__descriptor = +{ + PROTOBUF_C_ENUM_DESCRIPTOR_MAGIC, + "dnstap.SocketProtocol", + "SocketProtocol", + "Dnstap__SocketProtocol", + "dnstap", + 2, + dnstap__socket_protocol__enum_values_by_number, + 2, + dnstap__socket_protocol__enum_values_by_name, + 1, + dnstap__socket_protocol__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/external/unbound/dnstap/dnstap.pb-c.h b/external/unbound/dnstap/dnstap.pb-c.h new file mode 100644 index 000000000..d85e77715 --- /dev/null +++ b/external/unbound/dnstap/dnstap.pb-c.h @@ -0,0 +1,158 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ + +#ifndef PROTOBUF_C_dnstap_2fdnstap_2eproto__INCLUDED +#define PROTOBUF_C_dnstap_2fdnstap_2eproto__INCLUDED + +#include <google/protobuf-c/protobuf-c.h> + +PROTOBUF_C_BEGIN_DECLS + + +typedef struct _Dnstap__Dnstap Dnstap__Dnstap; +typedef struct _Dnstap__Message Dnstap__Message; + + +/* --- enums --- */ + +typedef enum _Dnstap__Dnstap__Type { + DNSTAP__DNSTAP__TYPE__MESSAGE = 1 +} Dnstap__Dnstap__Type; +typedef enum _Dnstap__Message__Type { + DNSTAP__MESSAGE__TYPE__AUTH_QUERY = 1, + DNSTAP__MESSAGE__TYPE__AUTH_RESPONSE = 2, + DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY = 3, + DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE = 4, + DNSTAP__MESSAGE__TYPE__CLIENT_QUERY = 5, + DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE = 6, + DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY = 7, + DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE = 8, + DNSTAP__MESSAGE__TYPE__STUB_QUERY = 9, + DNSTAP__MESSAGE__TYPE__STUB_RESPONSE = 10 +} Dnstap__Message__Type; +typedef enum _Dnstap__SocketFamily { + DNSTAP__SOCKET_FAMILY__INET = 1, + DNSTAP__SOCKET_FAMILY__INET6 = 2 +} Dnstap__SocketFamily; +typedef enum _Dnstap__SocketProtocol { + DNSTAP__SOCKET_PROTOCOL__UDP = 1, + DNSTAP__SOCKET_PROTOCOL__TCP = 2 +} Dnstap__SocketProtocol; + +/* --- messages --- */ + +struct _Dnstap__Dnstap +{ + ProtobufCMessage base; + protobuf_c_boolean has_identity; + ProtobufCBinaryData identity; + protobuf_c_boolean has_version; + ProtobufCBinaryData version; + protobuf_c_boolean has_extra; + ProtobufCBinaryData extra; + Dnstap__Dnstap__Type type; + Dnstap__Message *message; +}; +#define DNSTAP__DNSTAP__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&dnstap__dnstap__descriptor) \ + , 0,{0,NULL}, 0,{0,NULL}, 0,{0,NULL}, 0, NULL } + + +struct _Dnstap__Message +{ + ProtobufCMessage base; + Dnstap__Message__Type type; + protobuf_c_boolean has_socket_family; + Dnstap__SocketFamily socket_family; + protobuf_c_boolean has_socket_protocol; + Dnstap__SocketProtocol socket_protocol; + protobuf_c_boolean has_query_address; + ProtobufCBinaryData query_address; + protobuf_c_boolean has_response_address; + ProtobufCBinaryData response_address; + protobuf_c_boolean has_query_port; + uint32_t query_port; + protobuf_c_boolean has_response_port; + uint32_t response_port; + protobuf_c_boolean has_query_time_sec; + uint64_t query_time_sec; + protobuf_c_boolean has_query_time_nsec; + uint32_t query_time_nsec; + protobuf_c_boolean has_query_message; + ProtobufCBinaryData query_message; + protobuf_c_boolean has_query_zone; + ProtobufCBinaryData query_zone; + protobuf_c_boolean has_response_time_sec; + uint64_t response_time_sec; + protobuf_c_boolean has_response_time_nsec; + uint32_t response_time_nsec; + protobuf_c_boolean has_response_message; + ProtobufCBinaryData response_message; +}; +#define DNSTAP__MESSAGE__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&dnstap__message__descriptor) \ + , 0, 0,0, 0,0, 0,{0,NULL}, 0,{0,NULL}, 0,0, 0,0, 0,0, 0,0, 0,{0,NULL}, 0,{0,NULL}, 0,0, 0,0, 0,{0,NULL} } + + +/* Dnstap__Dnstap methods */ +void dnstap__dnstap__init + (Dnstap__Dnstap *message); +size_t dnstap__dnstap__get_packed_size + (const Dnstap__Dnstap *message); +size_t dnstap__dnstap__pack + (const Dnstap__Dnstap *message, + uint8_t *out); +size_t dnstap__dnstap__pack_to_buffer + (const Dnstap__Dnstap *message, + ProtobufCBuffer *buffer); +Dnstap__Dnstap * + dnstap__dnstap__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void dnstap__dnstap__free_unpacked + (Dnstap__Dnstap *message, + ProtobufCAllocator *allocator); +/* Dnstap__Message methods */ +void dnstap__message__init + (Dnstap__Message *message); +size_t dnstap__message__get_packed_size + (const Dnstap__Message *message); +size_t dnstap__message__pack + (const Dnstap__Message *message, + uint8_t *out); +size_t dnstap__message__pack_to_buffer + (const Dnstap__Message *message, + ProtobufCBuffer *buffer); +Dnstap__Message * + dnstap__message__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void dnstap__message__free_unpacked + (Dnstap__Message *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*Dnstap__Dnstap_Closure) + (const Dnstap__Dnstap *message, + void *closure_data); +typedef void (*Dnstap__Message_Closure) + (const Dnstap__Message *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor dnstap__socket_family__descriptor; +extern const ProtobufCEnumDescriptor dnstap__socket_protocol__descriptor; +extern const ProtobufCMessageDescriptor dnstap__dnstap__descriptor; +extern const ProtobufCEnumDescriptor dnstap__dnstap__type__descriptor; +extern const ProtobufCMessageDescriptor dnstap__message__descriptor; +extern const ProtobufCEnumDescriptor dnstap__message__type__descriptor; + +PROTOBUF_C_END_DECLS + + +#endif /* PROTOBUF_dnstap_2fdnstap_2eproto__INCLUDED */ diff --git a/external/unbound/dnstap/dnstap.proto b/external/unbound/dnstap/dnstap.proto new file mode 100644 index 000000000..3504d99ed --- /dev/null +++ b/external/unbound/dnstap/dnstap.proto @@ -0,0 +1,262 @@ +// dnstap: flexible, structured event replication format for DNS software +// +// This file contains the protobuf schemas for the "dnstap" structured event +// replication format for DNS software. + +// Written in 2013-2014 by Farsight Security, Inc. +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this file to the public +// domain worldwide. This file is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication along +// with this file. If not, see: +// +// <http://creativecommons.org/publicdomain/zero/1.0/>. + +package dnstap; + +// "Dnstap": this is the top-level dnstap type, which is a "union" type that +// contains other kinds of dnstap payloads, although currently only one type +// of dnstap payload is defined. +// See: https://developers.google.com/protocol-buffers/docs/techniques#union +message Dnstap { + // DNS server identity. + // If enabled, this is the identity string of the DNS server which generated + // this message. Typically this would be the same string as returned by an + // "NSID" (RFC 5001) query. + optional bytes identity = 1; + + // DNS server version. + // If enabled, this is the version string of the DNS server which generated + // this message. Typically this would be the same string as returned by a + // "version.bind" query. + optional bytes version = 2; + + // Extra data for this payload. + // This field can be used for adding an arbitrary byte-string annotation to + // the payload. No encoding or interpretation is applied or enforced. + optional bytes extra = 3; + + // Identifies which field below is filled in. + enum Type { + MESSAGE = 1; + } + required Type type = 15; + + // One of the following will be filled in. + optional Message message = 14; +} + +// SocketFamily: the network protocol family of a socket. This specifies how +// to interpret "network address" fields. +enum SocketFamily { + INET = 1; // IPv4 (RFC 791) + INET6 = 2; // IPv6 (RFC 2460) +} + +// SocketProtocol: the transport protocol of a socket. This specifies how to +// interpret "transport port" fields. +enum SocketProtocol { + UDP = 1; // User Datagram Protocol (RFC 768) + TCP = 2; // Transmission Control Protocol (RFC 793) +} + +// Message: a wire-format (RFC 1035 section 4) DNS message and associated +// metadata. Applications generating "Message" payloads should follow +// certain requirements based on the MessageType, see below. +message Message { + + // There are eight types of "Message" defined that correspond to the + // four arrows in the following diagram, slightly modified from RFC 1035 + // section 2: + + // +---------+ +----------+ +--------+ + // | | query | | query | | + // | Stub |-SQ--------CQ->| Recursive|-RQ----AQ->| Auth. | + // | Resolver| | Server | | Name | + // | |<-SR--------CR-| |<-RR----AR-| Server | + // +---------+ response | | response | | + // +----------+ +--------+ + + // Each arrow has two Type values each, one for each "end" of each arrow, + // because these are considered to be distinct events. Each end of each + // arrow on the diagram above has been marked with a two-letter Type + // mnemonic. Clockwise from upper left, these mnemonic values are: + // + // SQ: STUB_QUERY + // CQ: CLIENT_QUERY + // RQ: RESOLVER_QUERY + // AQ: AUTH_QUERY + // AR: AUTH_RESPONSE + // RR: RESOLVER_RESPONSE + // CR: CLIENT_RESPONSE + // SR: STUB_RESPONSE + + // Two additional types of "Message" have been defined for the + // "forwarding" case where an upstream DNS server is responsible for + // further recursion. These are not shown on the diagram above, but have + // the following mnemonic values: + + // FQ: FORWARDER_QUERY + // FR: FORWARDER_RESPONSE + + // The "Message" Type values are defined below. + + enum Type { + // AUTH_QUERY is a DNS query message received from a resolver by an + // authoritative name server, from the perspective of the authorative + // name server. + AUTH_QUERY = 1; + + // AUTH_RESPONSE is a DNS response message sent from an authoritative + // name server to a resolver, from the perspective of the authoritative + // name server. + AUTH_RESPONSE = 2; + + // RESOLVER_QUERY is a DNS query message sent from a resolver to an + // authoritative name server, from the perspective of the resolver. + // Resolvers typically clear the RD (recursion desired) bit when + // sending queries. + RESOLVER_QUERY = 3; + + // RESOLVER_RESPONSE is a DNS response message received from an + // authoritative name server by a resolver, from the perspective of + // the resolver. + RESOLVER_RESPONSE = 4; + + // CLIENT_QUERY is a DNS query message sent from a client to a DNS + // server which is expected to perform further recursion, from the + // perspective of the DNS server. The client may be a stub resolver or + // forwarder or some other type of software which typically sets the RD + // (recursion desired) bit when querying the DNS server. The DNS server + // may be a simple forwarding proxy or it may be a full recursive + // resolver. + CLIENT_QUERY = 5; + + // CLIENT_RESPONSE is a DNS response message sent from a DNS server to + // a client, from the perspective of the DNS server. The DNS server + // typically sets the RA (recursion available) bit when responding. + CLIENT_RESPONSE = 6; + + // FORWARDER_QUERY is a DNS query message sent from a downstream DNS + // server to an upstream DNS server which is expected to perform + // further recursion, from the perspective of the downstream DNS + // server. + FORWARDER_QUERY = 7; + + // FORWARDER_RESPONSE is a DNS response message sent from an upstream + // DNS server performing recursion to a downstream DNS server, from the + // perspective of the downstream DNS server. + FORWARDER_RESPONSE = 8; + + // STUB_QUERY is a DNS query message sent from a stub resolver to a DNS + // server, from the perspective of the stub resolver. + STUB_QUERY = 9; + + // STUB_RESPONSE is a DNS response message sent from a DNS server to a + // stub resolver, from the perspective of the stub resolver. + STUB_RESPONSE = 10; + } + + // One of the Type values described above. + required Type type = 1; + + // One of the SocketFamily values described above. + optional SocketFamily socket_family = 2; + + // One of the SocketProtocol values described above. + optional SocketProtocol socket_protocol = 3; + + // The network address of the message initiator. + // For SocketFamily INET, this field is 4 octets (IPv4 address). + // For SocketFamily INET6, this field is 16 octets (IPv6 address). + optional bytes query_address = 4; + + // The network address of the message responder. + // For SocketFamily INET, this field is 4 octets (IPv4 address). + // For SocketFamily INET6, this field is 16 octets (IPv6 address). + optional bytes response_address = 5; + + // The transport port of the message initiator. + // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. + optional uint32 query_port = 6; + + // The transport port of the message responder. + // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. + optional uint32 response_port = 7; + + // The time at which the DNS query message was sent or received, depending + // on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY. + // This is the number of seconds since the UNIX epoch. + optional uint64 query_time_sec = 8; + + // The time at which the DNS query message was sent or received. + // This is the seconds fraction, expressed as a count of nanoseconds. + optional fixed32 query_time_nsec = 9; + + // The initiator's original wire-format DNS query message, verbatim. + optional bytes query_message = 10; + + // The "zone" or "bailiwick" pertaining to the DNS query message. + // This is a wire-format DNS domain name. + optional bytes query_zone = 11; + + // The time at which the DNS response message was sent or received, + // depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or + // CLIENT_RESPONSE. + // This is the number of seconds since the UNIX epoch. + optional uint64 response_time_sec = 12; + + // The time at which the DNS response message was sent or received. + // This is the seconds fraction, expressed as a count of nanoseconds. + optional fixed32 response_time_nsec = 13; + + // The responder's original wire-format DNS response message, verbatim. + optional bytes response_message = 14; +} + +// All fields except for 'type' in the Message schema are optional. +// It is recommended that at least the following fields be filled in for +// particular types of Messages. + +// AUTH_QUERY: +// socket_family, socket_protocol +// query_address, query_port +// query_message +// query_time_sec, query_time_nsec + +// AUTH_RESPONSE: +// socket_family, socket_protocol +// query_address, query_port +// query_time_sec, query_time_nsec +// response_message +// response_time_sec, response_time_nsec + +// RESOLVER_QUERY: +// socket_family, socket_protocol +// query_name, query_type, query_class +// query_message +// query_time_sec, query_time_nsec +// query_zone +// response_address, response_port + +// RESOLVER_RESPONSE: +// socket_family, socket_protocol +// query_name, query_type, query_class +// query_time_sec, query_time_nsec +// query_zone +// response_address, response_port +// response_message +// response_time_sec, response_time_nsec + +// CLIENT_QUERY: +// socket_family, socket_protocol +// query_message +// query_time_sec, query_time_nsec + +// CLIENT_RESPONSE: +// socket_family, socket_protocol +// query_time_sec, query_time_nsec +// response_message +// response_time_sec, response_time_nsec diff --git a/external/unbound/dnstap/dnstap_config.h.in b/external/unbound/dnstap/dnstap_config.h.in new file mode 100644 index 000000000..c9f74893a --- /dev/null +++ b/external/unbound/dnstap/dnstap_config.h.in @@ -0,0 +1,17 @@ +#ifndef UNBOUND_DNSTAP_CONFIG_H +#define UNBOUND_DNSTAP_CONFIG_H + +/* + * Process this file (dnstap_config.h.in) with AC_CONFIG_FILES to generate + * dnstap_config.h. + * + * This file exists so that USE_DNSTAP can be used without including config.h. + */ + +#if @ENABLE_DNSTAP@ /* ENABLE_DNSTAP */ +# ifndef USE_DNSTAP +# define USE_DNSTAP 1 +# endif +#endif + +#endif /* UNBOUND_DNSTAP_CONFIG_H */ |