]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnstap.cc
Meson: Separate test files from common files
[thirdparty/pdns.git] / pdns / dnstap.cc
1 #include <boost/uuid/uuid.hpp>
2 #include "config.h"
3 #include "gettime.hh"
4 #include "dnstap.hh"
5
6 #ifndef DISABLE_PROTOBUF
7
8 #include <protozero/pbf_writer.hpp>
9
10 namespace DnstapBaseFields
11 {
12 enum : protozero::pbf_tag_type
13 {
14 identity = 1,
15 version = 2,
16 extra = 3,
17 message = 14,
18 type = 15
19 };
20 }
21
22 namespace DnstapMessageTypes
23 {
24 enum : protozero::pbf_tag_type
25 {
26 message = 1
27 };
28 }
29
30 namespace DnstapSocketFamilyTypes
31 {
32 enum : protozero::pbf_tag_type
33 {
34 inet = 1,
35 inet6 = 2
36 };
37 }
38
39 namespace DnstapMessageFields
40 {
41 enum : protozero::pbf_tag_type
42 {
43 type = 1,
44 socket_family = 2,
45 socket_protocol = 3,
46 query_address = 4,
47 response_address = 5,
48 query_port = 6,
49 response_port = 7,
50 query_time_sec = 8,
51 query_time_nsec = 9,
52 query_message = 10,
53 query_zone = 11,
54 response_time_sec = 12,
55 response_time_nsec = 13,
56 response_message = 14
57 };
58 }
59
60 std::string&& DnstapMessage::getBuffer()
61 {
62 return std::move(d_buffer);
63 }
64
65 DnstapMessage::DnstapMessage(std::string&& buffer, DnstapMessage::MessageType type, const std::string& identity, const ComboAddress* requestor, const ComboAddress* responder, DnstapMessage::ProtocolType protocol, const char* packet, const size_t len, const struct timespec* queryTime, const struct timespec* responseTime, const boost::optional<const DNSName&>& auth) :
66 d_buffer(std::move(buffer))
67 {
68 protozero::pbf_writer pbf{d_buffer};
69
70 pbf.add_bytes(DnstapBaseFields::identity, identity);
71 pbf.add_bytes(DnstapBaseFields::version, PACKAGE_STRING);
72 pbf.add_enum(DnstapBaseFields::type, DnstapMessageTypes::message);
73
74 protozero::pbf_writer pbf_message{pbf, DnstapBaseFields::message};
75
76 // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
77 pbf_message.add_enum(DnstapMessageFields::type, static_cast<protozero::pbf_tag_type>(type));
78 // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
79 pbf_message.add_enum(DnstapMessageFields::socket_protocol, static_cast<protozero::pbf_tag_type>(protocol));
80
81 if (requestor != nullptr) {
82 pbf_message.add_enum(DnstapMessageFields::socket_family, requestor->sin4.sin_family == AF_INET ? DnstapSocketFamilyTypes::inet : DnstapSocketFamilyTypes::inet6);
83 }
84 else if (responder != nullptr) {
85 pbf_message.add_enum(DnstapMessageFields::socket_family, responder->sin4.sin_family == AF_INET ? DnstapSocketFamilyTypes::inet : DnstapSocketFamilyTypes::inet6);
86 }
87
88 if (requestor != nullptr) {
89 if (requestor->sin4.sin_family == AF_INET) {
90 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
91 pbf_message.add_bytes(DnstapMessageFields::query_address, reinterpret_cast<const char*>(&requestor->sin4.sin_addr.s_addr), sizeof(requestor->sin4.sin_addr.s_addr));
92 }
93 else if (requestor->sin4.sin_family == AF_INET6) {
94 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
95 pbf_message.add_bytes(DnstapMessageFields::query_address, reinterpret_cast<const char*>(&requestor->sin6.sin6_addr.s6_addr), sizeof(requestor->sin6.sin6_addr.s6_addr));
96 }
97 pbf_message.add_uint32(DnstapMessageFields::query_port, ntohs(requestor->sin4.sin_port));
98 }
99
100 if (responder != nullptr) {
101 if (responder->sin4.sin_family == AF_INET) {
102 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
103 pbf_message.add_bytes(DnstapMessageFields::response_address, reinterpret_cast<const char*>(&responder->sin4.sin_addr.s_addr), sizeof(responder->sin4.sin_addr.s_addr));
104 }
105 else if (responder->sin4.sin_family == AF_INET6) {
106 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
107 pbf_message.add_bytes(DnstapMessageFields::response_address, reinterpret_cast<const char*>(&responder->sin6.sin6_addr.s6_addr), sizeof(responder->sin6.sin6_addr.s6_addr));
108 }
109 pbf_message.add_uint32(DnstapMessageFields::response_port, ntohs(responder->sin4.sin_port));
110 }
111
112 if (queryTime != nullptr) {
113 pbf_message.add_uint64(DnstapMessageFields::query_time_sec, queryTime->tv_sec);
114 pbf_message.add_fixed32(DnstapMessageFields::query_time_nsec, queryTime->tv_nsec);
115 }
116
117 if (responseTime != nullptr) {
118 pbf_message.add_uint64(DnstapMessageFields::response_time_sec, responseTime->tv_sec);
119 pbf_message.add_fixed32(DnstapMessageFields::response_time_nsec, responseTime->tv_nsec);
120 }
121
122 if (packet != nullptr && len >= sizeof(dnsheader)) {
123 const dnsheader_aligned dnsheader(packet);
124 if (!dnsheader->qr) {
125 pbf_message.add_bytes(DnstapMessageFields::query_message, packet, len);
126 }
127 else {
128 pbf_message.add_bytes(DnstapMessageFields::response_message, packet, len);
129 }
130 }
131
132 if (auth) {
133 pbf_message.add_bytes(DnstapMessageFields::query_zone, auth->toDNSString());
134 }
135
136 pbf_message.commit();
137 }
138
139 void DnstapMessage::setExtra(const std::string& extra)
140 {
141 protozero::pbf_writer pbf{d_buffer};
142 pbf.add_bytes(DnstapBaseFields::extra, extra);
143 }
144
145 #endif /* DISABLE_PROTOBUF */