summaryrefslogtreecommitdiffstats
path: root/src/contrib/dnstap/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contrib/dnstap/message.c')
-rw-r--r--src/contrib/dnstap/message.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/contrib/dnstap/message.c b/src/contrib/dnstap/message.c
new file mode 100644
index 0000000..a5f798e
--- /dev/null
+++ b/src/contrib/dnstap/message.c
@@ -0,0 +1,130 @@
+/* Copyright (C) 2017 Farsight Security, Inc. <software@farsightsecurity.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libknot/errcode.h"
+
+#include "contrib/dnstap/convert.h"
+#include "contrib/dnstap/message.h"
+
+static void set_address(const struct sockaddr *sockaddr,
+ ProtobufCBinaryData *addr,
+ protobuf_c_boolean *has_addr,
+ uint32_t *port,
+ protobuf_c_boolean *has_port)
+{
+ if (sockaddr == NULL) {
+ *has_addr = 0;
+ *has_port = 0;
+ return;
+ }
+
+ *has_addr = 1;
+ *has_port = 1;
+
+ if (sockaddr->sa_family == AF_INET) {
+ const struct sockaddr_in *sai;
+ sai = (const struct sockaddr_in *)sockaddr;
+ addr->len = sizeof(sai->sin_addr);
+ addr->data = (uint8_t *)&sai->sin_addr.s_addr;
+ *port = ntohs(sai->sin_port);
+ } else if (sockaddr->sa_family == AF_INET6) {
+ const struct sockaddr_in6 *sai6;
+ sai6 = (const struct sockaddr_in6 *)sockaddr;
+ addr->len = sizeof(sai6->sin6_addr);
+ addr->data = (uint8_t *)&sai6->sin6_addr.s6_addr;
+ *port = ntohs(sai6->sin6_port);
+ }
+}
+
+static int get_family(const struct sockaddr *query_sa,
+ const struct sockaddr *response_sa)
+{
+ const struct sockaddr *source = query_sa ? query_sa : response_sa;
+ if (source == NULL) {
+ return 0;
+ }
+
+ return dt_family_encode(source->sa_family);
+}
+
+int dt_message_fill(Dnstap__Message *m,
+ const Dnstap__Message__Type type,
+ const struct sockaddr *query_sa,
+ const struct sockaddr *response_sa,
+ const int protocol,
+ const void *wire,
+ const size_t len_wire,
+ const struct timespec *mtime)
+{
+ if (m == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ memset(m, 0, sizeof(*m));
+
+ m->base.descriptor = &dnstap__message__descriptor;
+
+ // Message.type
+ m->type = type;
+
+ // Message.socket_family
+ m->socket_family = get_family(query_sa, response_sa);
+ m->has_socket_family = m->socket_family != 0;
+
+ // Message.socket_protocol
+ m->socket_protocol = dt_protocol_encode(protocol);
+ m->has_socket_protocol = m->socket_protocol != 0;
+
+ // Message addresses
+ set_address(query_sa, &m->query_address, &m->has_query_address,
+ &m->query_port, &m->has_query_port);
+ set_address(response_sa, &m->response_address, &m->has_response_address,
+ &m->response_port, &m->has_response_port);
+
+ if (dt_message_type_is_query(type)) {
+ // Message.query_message
+ m->query_message.len = len_wire;
+ m->query_message.data = (uint8_t *)wire;
+ m->has_query_message = 1;
+ // Message.query_time_sec, Message.query_time_nsec
+ if (mtime != NULL) {
+ m->query_time_sec = mtime->tv_sec;
+ m->query_time_nsec = mtime->tv_nsec;
+ m->has_query_time_sec = 1;
+ m->has_query_time_nsec = 1;
+ }
+ } else if (dt_message_type_is_response(type)) {
+ // Message.response_message
+ m->response_message.len = len_wire;
+ m->response_message.data = (uint8_t *)wire;
+ m->has_response_message = 1;
+ // Message.response_time_sec, Message.response_time_nsec
+ if (mtime != NULL) {
+ m->response_time_sec = mtime->tv_sec;
+ m->response_time_nsec = mtime->tv_nsec;
+ m->has_response_time_sec = 1;
+ m->has_response_time_nsec = 1;
+ }
+ }
+
+ return KNOT_EOK;
+}