]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/protobuf.cc
Merge pull request #8223 from PowerDNS/omoerbeek-patch-1
[thirdparty/pdns.git] / pdns / protobuf.cc
CommitLineData
d9d3f9c1 1
4898a348
RG
2#include "gettime.hh"
3#include "dnsparser.hh"
d9d3f9c1
RG
4#include "protobuf.hh"
5#include "dnsparser.hh"
6#include "gettime.hh"
7
4898a348 8void DNSProtoBufMessage::setType(DNSProtoBufMessageType type)
d9d3f9c1
RG
9{
10#ifdef HAVE_PROTOBUF
4898a348
RG
11 switch(type) {
12 case DNSProtoBufMessage::DNSProtoBufMessageType::Query:
13 d_message.set_type(PBDNSMessage_Type_DNSQueryType);
14 break;
15 case DNSProtoBufMessage::DNSProtoBufMessageType::Response:
16 d_message.set_type(PBDNSMessage_Type_DNSResponseType);
17 break;
18 case DNSProtoBufMessage::DNSProtoBufMessageType::OutgoingQuery:
19 d_message.set_type(PBDNSMessage_Type_DNSOutgoingQueryType);
20 break;
21 case DNSProtoBufMessage::DNSProtoBufMessageType::IncomingResponse:
22 d_message.set_type(PBDNSMessage_Type_DNSIncomingResponseType);
23 break;
24 default:
25 throw std::runtime_error("Unsupported protobuf type: "+std::to_string(type));
26 }
d9d3f9c1
RG
27#endif /* HAVE_PROTOBUF */
28}
29
4898a348
RG
30DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type)
31{
32 setType(type);
33}
34
d9d3f9c1
RG
35void DNSProtoBufMessage::setQuestion(const DNSName& qname, uint16_t qtype, uint16_t qclass)
36{
37#ifdef HAVE_PROTOBUF
38 PBDNSMessage_DNSQuestion* question = d_message.mutable_question();
39 if (question) {
da5bcd9d 40 if(!qname.empty())
41 question->set_qname(qname.toString());
d9d3f9c1
RG
42 question->set_qtype(qtype);
43 question->set_qclass(qclass);
44 }
45#endif /* HAVE_PROTOBUF */
46}
47
48void DNSProtoBufMessage::setBytes(size_t bytes)
49{
50#ifdef HAVE_PROTOBUF
51 d_message.set_inbytes(bytes);
52#endif /* HAVE_PROTOBUF */
53}
54
55void DNSProtoBufMessage::setResponseCode(uint8_t rcode)
56{
57#ifdef HAVE_PROTOBUF
58 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
59 if (response) {
60 response->set_rcode(rcode);
61 }
62#endif /* HAVE_PROTOBUF */
63}
64
57f8413e
RG
65void DNSProtoBufMessage::setNetworkErrorResponseCode()
66{
67#ifdef HAVE_PROTOBUF
68 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
69 if (response) {
70 /* special code meaning 'network error', like a timeout */
71 response->set_rcode(65536);
72 }
73#endif /* HAVE_PROTOBUF */
74}
75
d9d3f9c1
RG
76void DNSProtoBufMessage::setTime(time_t sec, uint32_t usec)
77{
78#ifdef HAVE_PROTOBUF
79 d_message.set_timesec(sec);
80 d_message.set_timeusec(usec);
81#endif /* HAVE_PROTOBUF */
82}
83
58307a85
RG
84void DNSProtoBufMessage::setQueryTime(time_t sec, uint32_t usec)
85{
86#ifdef HAVE_PROTOBUF
87 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
88 if (response) {
89 response->set_querytimesec(sec);
90 response->set_querytimeusec(usec);
91 }
92#endif /* HAVE_PROTOBUF */
93}
94
a94bc5d7 95void DNSProtoBufMessage::setEDNSSubnet(const Netmask& subnet, uint8_t mask)
d9d3f9c1
RG
96{
97#ifdef HAVE_PROTOBUF
98 if (!subnet.empty()) {
a94bc5d7
RG
99 ComboAddress ca(subnet.getNetwork());
100 ca.truncate(mask);
d9d3f9c1
RG
101 if (ca.sin4.sin_family == AF_INET) {
102 d_message.set_originalrequestorsubnet(&ca.sin4.sin_addr.s_addr, sizeof(ca.sin4.sin_addr.s_addr));
103 }
104 else if (ca.sin4.sin_family == AF_INET6) {
105 d_message.set_originalrequestorsubnet(&ca.sin6.sin6_addr.s6_addr, sizeof(ca.sin6.sin6_addr.s6_addr));
106 }
107 }
108#endif /* HAVE_PROTOBUF */
109}
110
e6956c91 111void DNSProtoBufMessage::addTag(const std::string& strValue)
26a6373d
SO
112{
113#ifdef HAVE_PROTOBUF
114
115 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
116 if (!response)
117 return;
118
e6956c91 119 response->add_tags(strValue);
26a6373d
SO
120
121#endif /* HAVE_PROTOBUF */
122}
123
ff09c374 124void DNSProtoBufMessage::addRR(const DNSName& qname, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& strBlob)
26a6373d
SO
125{
126#ifdef HAVE_PROTOBUF
127
128 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
129 if (!response)
130 return;
26a6373d 131 PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs();
29cd61cc 132 if (rr) {
ff09c374 133 rr->set_name(qname.toString());
29cd61cc
SO
134 rr->set_type(uType);
135 rr->set_class_(uClass);
136 rr->set_ttl(uTTL);
c959e01a 137 rr->set_rdata(strBlob.c_str(), strBlob.size());
29cd61cc 138 }
26a6373d
SO
139
140#endif /* HAVE_PROTOBUF */
141}
26a6373d 142
165c9030 143void DNSProtoBufMessage::addRRsFromPacket(const char* packet, const size_t len, bool includeCNAME)
d9d3f9c1
RG
144{
145#ifdef HAVE_PROTOBUF
146 if (len < sizeof(struct dnsheader))
147 return;
148
149 const struct dnsheader* dh = (const struct dnsheader*) packet;
150
151 if (ntohs(dh->ancount) == 0)
152 return;
153
154 if (ntohs(dh->qdcount) == 0)
155 return;
156
157 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
158 if (!response)
159 return;
160
78f56b38
RG
161 std::string packetStr(packet, len);
162 PacketReader pr(packetStr);
d9d3f9c1
RG
163
164 size_t idx = 0;
165 DNSName rrname;
166 uint16_t qdcount = ntohs(dh->qdcount);
167 uint16_t ancount = ntohs(dh->ancount);
168 uint16_t rrtype;
169 uint16_t rrclass;
170 string blob;
171 struct dnsrecordheader ah;
172
173 rrname = pr.getName();
174 rrtype = pr.get16BitInt();
175 rrclass = pr.get16BitInt();
176
177 /* consume remaining qd if any */
178 if (qdcount > 1) {
179 for(idx = 1; idx < qdcount; idx++) {
180 rrname = pr.getName();
181 rrtype = pr.get16BitInt();
182 rrclass = pr.get16BitInt();
183 (void) rrtype;
184 (void) rrclass;
185 }
186 }
187
188 /* parse AN */
189 for (idx = 0; idx < ancount; idx++) {
190 rrname = pr.getName();
191 pr.getDnsrecordheader(ah);
192
d9d3f9c1 193 if (ah.d_type == QType::A || ah.d_type == QType::AAAA) {
165c9030
RG
194 pr.xfrBlob(blob);
195
d9d3f9c1
RG
196 PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs();
197 if (rr) {
198 rr->set_name(rrname.toString());
199 rr->set_type(ah.d_type);
200 rr->set_class_(ah.d_class);
201 rr->set_ttl(ah.d_ttl);
202 rr->set_rdata(blob.c_str(), blob.length());
203 }
165c9030
RG
204 } else if (ah.d_type == QType::CNAME && includeCNAME) {
205 PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs();
206 if (rr) {
207 rr->set_name(rrname.toString());
208 rr->set_type(ah.d_type);
209 rr->set_class_(ah.d_class);
210 rr->set_ttl(ah.d_ttl);
211 DNSName target;
212 pr.xfrName(target, true);
213 rr->set_rdata(target.toString());
214 }
215 }
216 else {
217 pr.xfrBlob(blob);
d9d3f9c1
RG
218 }
219 }
220#endif /* HAVE_PROTOBUF */
221}
222
a94673ea
RG
223void DNSProtoBufMessage::setRequestor(const std::string& requestor)
224{
225#ifdef HAVE_PROTOBUF
226 d_message.set_from(requestor);
227#endif /* HAVE_PROTOBUF */
228}
229
230void DNSProtoBufMessage::setRequestor(const ComboAddress& requestor)
231{
232#ifdef HAVE_PROTOBUF
233 if (requestor.sin4.sin_family == AF_INET) {
234 d_message.set_from(&requestor.sin4.sin_addr.s_addr, sizeof(requestor.sin4.sin_addr.s_addr));
235 }
236 else if (requestor.sin4.sin_family == AF_INET6) {
237 d_message.set_from(&requestor.sin6.sin6_addr.s6_addr, sizeof(requestor.sin6.sin6_addr.s6_addr));
238 }
239#endif /* HAVE_PROTOBUF */
240}
241
67e31ebe
RG
242void DNSProtoBufMessage::setRequestorId(const std::string& requestorId)
243{
244#ifdef HAVE_PROTOBUF
245 d_message.set_requestorid(requestorId);
246#endif /* HAVE_PROTOBUF */
247}
248
590388d2
NC
249void DNSProtoBufMessage::setDeviceId(const std::string& deviceId)
250{
251#ifdef HAVE_PROTOBUF
252 d_message.set_deviceid(deviceId);
253#endif /* HAVE_PROTOBUF */
254}
255
0a6a45c8
CHB
256void DNSProtoBufMessage::setDeviceName(const std::string& deviceName)
257{
258#ifdef HAVE_PROTOBUF
259 d_message.set_devicename(deviceName);
260#endif /* HAVE_PROTOBUF */
261}
262
c165308b
RG
263void DNSProtoBufMessage::setServerIdentity(const std::string& serverId)
264{
265#ifdef HAVE_PROTOBUF
266 d_message.set_serveridentity(serverId);
267#endif /* HAVE_PROTOBUF */
268}
269
a94673ea
RG
270void DNSProtoBufMessage::setResponder(const std::string& responder)
271{
272#ifdef HAVE_PROTOBUF
b3261c20 273 d_message.set_to(responder);
a94673ea
RG
274#endif /* HAVE_PROTOBUF */
275}
276
277void DNSProtoBufMessage::setResponder(const ComboAddress& responder)
278{
279#ifdef HAVE_PROTOBUF
280 if (responder.sin4.sin_family == AF_INET) {
b3261c20 281 d_message.set_to(&responder.sin4.sin_addr.s_addr, sizeof(responder.sin4.sin_addr.s_addr));
a94673ea
RG
282 }
283 else if (responder.sin4.sin_family == AF_INET6) {
b3261c20 284 d_message.set_to(&responder.sin6.sin6_addr.s6_addr, sizeof(responder.sin6.sin6_addr.s6_addr));
a94673ea
RG
285 }
286#endif /* HAVE_PROTOBUF */
287}
288
d9d3f9c1
RG
289void DNSProtoBufMessage::serialize(std::string& data) const
290{
291#ifdef HAVE_PROTOBUF
292 d_message.SerializeToString(&data);
293#endif /* HAVE_PROTOBUF */
294}
295
296std::string DNSProtoBufMessage::toDebugString() const
297{
298#ifdef HAVE_PROTOBUF
299 return d_message.DebugString();
121c28e9
RG
300#else
301 return std::string();
d9d3f9c1
RG
302#endif /* HAVE_PROTOBUF */
303}
304
305#ifdef HAVE_PROTOBUF
306
307void DNSProtoBufMessage::setUUID(const boost::uuids::uuid& uuid)
308{
309 std::string* messageId = d_message.mutable_messageid();
310 messageId->resize(uuid.size());
311 std::copy(uuid.begin(), uuid.end(), messageId->begin());
312}
313
4898a348
RG
314void DNSProtoBufMessage::setInitialRequestID(const boost::uuids::uuid& uuid)
315{
316 std::string* messageId = d_message.mutable_initialrequestid();
317 messageId->resize(uuid.size());
318 std::copy(uuid.begin(), uuid.end(), messageId->begin());
319}
320
8623c19a 321void DNSProtoBufMessage::updateTime()
d9d3f9c1
RG
322{
323 struct timespec ts;
324 gettime(&ts, true);
325 setTime(ts.tv_sec, ts.tv_nsec / 1000);
8623c19a 326}
d9d3f9c1 327
8623c19a
RG
328void DNSProtoBufMessage::update(const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, bool isTCP, uint16_t id)
329{
330 updateTime();
d9d3f9c1
RG
331 setUUID(uuid);
332 d_message.set_id(ntohs(id));
333
4898a348
RG
334 if (requestor) {
335 d_message.set_socketfamily(requestor->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6);
336 }
337 else if (responder) {
338 d_message.set_socketfamily(responder->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6);
339 }
340
d9d3f9c1
RG
341 d_message.set_socketprotocol(isTCP ? PBDNSMessage_SocketProtocol_TCP : PBDNSMessage_SocketProtocol_UDP);
342
343 if (responder) {
a94673ea 344 setResponder(*responder);
d9d3f9c1
RG
345 }
346 if (requestor) {
a94673ea 347 setRequestor(*requestor);
d9d3f9c1
RG
348 }
349}
350
351
4898a348 352DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type, const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, const DNSName& domain, int qtype, uint16_t qclass, uint16_t qid, bool isTCP, size_t bytes)
d9d3f9c1 353{
4898a348 354 update(uuid, requestor, responder, isTCP, qid);
d9d3f9c1 355
4898a348 356 setType(type);
d9d3f9c1
RG
357
358 setBytes(bytes);
359 setQuestion(domain, qtype, qclass);
360}
361
29478011
RG
362void DNSProtoBufMessage::copyFrom(const DNSProtoBufMessage& msg)
363{
364 d_message.CopyFrom(msg.d_message);
365}
366
d9d3f9c1 367#endif /* HAVE_PROTOBUF */