]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdist-protobuf.cc
Merge pull request #11954 from Habbie/axfr-primary-tc-servfail
[thirdparty/pdns.git] / pdns / dnsdist-protobuf.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #include "config.h"
23
24 #ifndef DISABLE_PROTOBUF
25 #include "dnsdist.hh"
26 #include "dnsdist-protobuf.hh"
27 #include "protozero.hh"
28
29 DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSQuestion& dq): d_dq(dq), d_type(pdns::ProtoZero::Message::MessageType::DNSQueryType)
30 {
31 }
32
33 DNSDistProtoBufMessage::DNSDistProtoBufMessage(const DNSResponse& dr, bool includeCNAME): d_dq(dr), d_dr(&dr), d_type(pdns::ProtoZero::Message::MessageType::DNSResponseType), d_includeCNAME(includeCNAME)
34 {
35 }
36
37 void DNSDistProtoBufMessage::setServerIdentity(const std::string& serverId)
38 {
39 d_serverIdentity = serverId;
40 }
41
42 void DNSDistProtoBufMessage::setRequestor(const ComboAddress& requestor)
43 {
44 d_requestor = requestor;
45 }
46
47 void DNSDistProtoBufMessage::setResponder(const ComboAddress& responder)
48 {
49 d_responder = responder;
50 }
51
52 void DNSDistProtoBufMessage::setRequestorPort(uint16_t port)
53 {
54 if (d_requestor) {
55 d_requestor->setPort(port);
56 }
57 }
58
59 void DNSDistProtoBufMessage::setResponderPort(uint16_t port)
60 {
61 if (d_responder) {
62 d_responder->setPort(port);
63 }
64 }
65
66 void DNSDistProtoBufMessage::setResponseCode(uint8_t rcode)
67 {
68 d_rcode = rcode;
69 }
70
71 void DNSDistProtoBufMessage::setType(pdns::ProtoZero::Message::MessageType type)
72 {
73 d_type = type;
74 }
75
76 void DNSDistProtoBufMessage::setBytes(size_t bytes)
77 {
78 d_bytes = bytes;
79 }
80
81 void DNSDistProtoBufMessage::setTime(time_t sec, uint32_t usec)
82 {
83 d_time = std::pair(sec, usec);
84 }
85
86 void DNSDistProtoBufMessage::setQueryTime(time_t sec, uint32_t usec)
87 {
88 d_queryTime = std::pair(sec, usec);
89 }
90
91 void DNSDistProtoBufMessage::setQuestion(const DNSName& name, uint16_t qtype, uint16_t qclass)
92 {
93 d_question = DNSDistProtoBufMessage::PBQuestion(name, qtype, qclass);
94 }
95
96 void DNSDistProtoBufMessage::setEDNSSubnet(const Netmask& nm)
97 {
98 d_ednsSubnet = nm;
99 }
100
101 void DNSDistProtoBufMessage::addTag(const std::string& strValue)
102 {
103 d_additionalTags.push_back(strValue);
104 }
105
106 void DNSDistProtoBufMessage::addRR(DNSName&& qname, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& strBlob)
107 {
108 d_additionalRRs.push_back({std::move(qname), strBlob, uTTL, uType, uClass});
109 }
110
111 void DNSDistProtoBufMessage::serialize(std::string& data) const
112 {
113 if ((data.capacity() - data.size()) < 128) {
114 data.reserve(data.size() + 128);
115 }
116 pdns::ProtoZero::Message m{data};
117
118 m.setType(d_type);
119
120 if (d_time) {
121 m.setTime(d_time->first, d_time->second);
122 }
123 else {
124 struct timespec ts;
125 gettime(&ts, true);
126 m.setTime(ts.tv_sec, ts.tv_nsec / 1000);
127 }
128
129 const auto distProto = d_dq.getProtocol();
130 pdns::ProtoZero::Message::TransportProtocol protocol = pdns::ProtoZero::Message::TransportProtocol::UDP;
131
132 if (distProto == dnsdist::Protocol::DoTCP) {
133 protocol = pdns::ProtoZero::Message::TransportProtocol::TCP;
134 }
135 else if (distProto == dnsdist::Protocol::DoT) {
136 protocol = pdns::ProtoZero::Message::TransportProtocol::DoT;
137 }
138 else if (distProto == dnsdist::Protocol::DoH) {
139 protocol = pdns::ProtoZero::Message::TransportProtocol::DoH;
140 }
141 else if (distProto == dnsdist::Protocol::DNSCryptUDP) {
142 protocol = pdns::ProtoZero::Message::TransportProtocol::DNSCryptUDP;
143 }
144 else if (distProto == dnsdist::Protocol::DNSCryptTCP) {
145 protocol = pdns::ProtoZero::Message::TransportProtocol::DNSCryptTCP;
146 }
147
148 m.setRequest(d_dq.uniqueId ? *d_dq.uniqueId : getUniqueID(), d_requestor ? *d_requestor : *d_dq.remote, d_responder ? *d_responder : *d_dq.local, d_question ? d_question->d_name : *d_dq.qname, d_question ? d_question->d_type : d_dq.qtype, d_question ? d_question->d_class : d_dq.qclass, d_dq.getHeader()->id, protocol, d_bytes ? *d_bytes : d_dq.getData().size());
149
150 if (d_serverIdentity) {
151 m.setServerIdentity(*d_serverIdentity);
152 }
153 else if (d_ServerIdentityRef != nullptr) {
154 m.setServerIdentity(*d_ServerIdentityRef);
155 }
156
157 if (d_ednsSubnet) {
158 m.setEDNSSubnet(*d_ednsSubnet, 128);
159 }
160
161 m.startResponse();
162 if (d_queryTime) {
163 // coverity[store_truncates_time_t]
164 m.setQueryTime(d_queryTime->first, d_queryTime->second);
165 }
166 else {
167 m.setQueryTime(d_dq.queryTime->tv_sec, d_dq.queryTime->tv_nsec / 1000);
168 }
169
170 if (d_dr != nullptr) {
171 m.setResponseCode(d_rcode ? *d_rcode : d_dr->getHeader()->rcode);
172 m.addRRsFromPacket(reinterpret_cast<const char*>(d_dr->getData().data()), d_dr->getData().size(), d_includeCNAME);
173 }
174 else {
175 if (d_rcode) {
176 m.setResponseCode(*d_rcode);
177 }
178 }
179
180 for (const auto& rr : d_additionalRRs) {
181 m.addRR(rr.d_name, rr.d_type, rr.d_class, rr.d_ttl, rr.d_data);
182 }
183
184 for (const auto& tag : d_additionalTags) {
185 m.addPolicyTag(tag);
186 }
187
188 m.commitResponse();
189 }
190
191 #endif /* DISABLE_PROTOBUF */