]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/protobuf.cc
Merge pull request #6143 from pieterlexis/doc-bench-db
[thirdparty/pdns.git] / pdns / protobuf.cc
1
2 #include "gettime.hh"
3 #include "dnsparser.hh"
4 #include "protobuf.hh"
5 #include "dnsparser.hh"
6 #include "gettime.hh"
7
8 void DNSProtoBufMessage::setType(DNSProtoBufMessageType type)
9 {
10 #ifdef HAVE_PROTOBUF
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 }
27 #endif /* HAVE_PROTOBUF */
28 }
29
30 DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type)
31 {
32 setType(type);
33 }
34
35 void 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) {
40 if(!qname.empty())
41 question->set_qname(qname.toString());
42 question->set_qtype(qtype);
43 question->set_qclass(qclass);
44 }
45 #endif /* HAVE_PROTOBUF */
46 }
47
48 void DNSProtoBufMessage::setBytes(size_t bytes)
49 {
50 #ifdef HAVE_PROTOBUF
51 d_message.set_inbytes(bytes);
52 #endif /* HAVE_PROTOBUF */
53 }
54
55 void 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
65 void DNSProtoBufMessage::setTime(time_t sec, uint32_t usec)
66 {
67 #ifdef HAVE_PROTOBUF
68 d_message.set_timesec(sec);
69 d_message.set_timeusec(usec);
70 #endif /* HAVE_PROTOBUF */
71 }
72
73 void DNSProtoBufMessage::setQueryTime(time_t sec, uint32_t usec)
74 {
75 #ifdef HAVE_PROTOBUF
76 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
77 if (response) {
78 response->set_querytimesec(sec);
79 response->set_querytimeusec(usec);
80 }
81 #endif /* HAVE_PROTOBUF */
82 }
83
84 void DNSProtoBufMessage::setEDNSSubnet(const Netmask& subnet, uint8_t mask)
85 {
86 #ifdef HAVE_PROTOBUF
87 if (!subnet.empty()) {
88 ComboAddress ca(subnet.getNetwork());
89 ca.truncate(mask);
90 if (ca.sin4.sin_family == AF_INET) {
91 d_message.set_originalrequestorsubnet(&ca.sin4.sin_addr.s_addr, sizeof(ca.sin4.sin_addr.s_addr));
92 }
93 else if (ca.sin4.sin_family == AF_INET6) {
94 d_message.set_originalrequestorsubnet(&ca.sin6.sin6_addr.s6_addr, sizeof(ca.sin6.sin6_addr.s6_addr));
95 }
96 }
97 #endif /* HAVE_PROTOBUF */
98 }
99
100 void DNSProtoBufMessage::addTag(const std::string& strValue)
101 {
102 #ifdef HAVE_PROTOBUF
103
104 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
105 if (!response)
106 return;
107
108 response->add_tags(strValue);
109
110 #endif /* HAVE_PROTOBUF */
111 }
112
113 void DNSProtoBufMessage::addRR(const DNSName& qname, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& strBlob)
114 {
115 #ifdef HAVE_PROTOBUF
116
117 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
118 if (!response)
119 return;
120 PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs();
121 if (rr) {
122 rr->set_name(qname.toString());
123 rr->set_type(uType);
124 rr->set_class_(uClass);
125 rr->set_ttl(uTTL);
126 rr->set_rdata(strBlob.c_str(), strBlob.size());
127 }
128
129 #endif /* HAVE_PROTOBUF */
130 }
131
132 void DNSProtoBufMessage::addRRsFromPacket(const char* packet, const size_t len, bool includeCNAME)
133 {
134 #ifdef HAVE_PROTOBUF
135 if (len < sizeof(struct dnsheader))
136 return;
137
138 const struct dnsheader* dh = (const struct dnsheader*) packet;
139
140 if (ntohs(dh->ancount) == 0)
141 return;
142
143 if (ntohs(dh->qdcount) == 0)
144 return;
145
146 PBDNSMessage_DNSResponse* response = d_message.mutable_response();
147 if (!response)
148 return;
149
150 vector<uint8_t> content(len - sizeof(dnsheader));
151 copy(packet + sizeof(dnsheader), packet + len, content.begin());
152 PacketReader pr(content);
153
154 size_t idx = 0;
155 DNSName rrname;
156 uint16_t qdcount = ntohs(dh->qdcount);
157 uint16_t ancount = ntohs(dh->ancount);
158 uint16_t rrtype;
159 uint16_t rrclass;
160 string blob;
161 struct dnsrecordheader ah;
162
163 rrname = pr.getName();
164 rrtype = pr.get16BitInt();
165 rrclass = pr.get16BitInt();
166
167 /* consume remaining qd if any */
168 if (qdcount > 1) {
169 for(idx = 1; idx < qdcount; idx++) {
170 rrname = pr.getName();
171 rrtype = pr.get16BitInt();
172 rrclass = pr.get16BitInt();
173 (void) rrtype;
174 (void) rrclass;
175 }
176 }
177
178 /* parse AN */
179 for (idx = 0; idx < ancount; idx++) {
180 rrname = pr.getName();
181 pr.getDnsrecordheader(ah);
182
183 if (ah.d_type == QType::A || ah.d_type == QType::AAAA) {
184 pr.xfrBlob(blob);
185
186 PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs();
187 if (rr) {
188 rr->set_name(rrname.toString());
189 rr->set_type(ah.d_type);
190 rr->set_class_(ah.d_class);
191 rr->set_ttl(ah.d_ttl);
192 rr->set_rdata(blob.c_str(), blob.length());
193 }
194 } else if (ah.d_type == QType::CNAME && includeCNAME) {
195 PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs();
196 if (rr) {
197 rr->set_name(rrname.toString());
198 rr->set_type(ah.d_type);
199 rr->set_class_(ah.d_class);
200 rr->set_ttl(ah.d_ttl);
201 DNSName target;
202 pr.xfrName(target, true);
203 rr->set_rdata(target.toString());
204 }
205 }
206 else {
207 pr.xfrBlob(blob);
208 }
209 }
210 #endif /* HAVE_PROTOBUF */
211 }
212
213 void DNSProtoBufMessage::setRequestor(const std::string& requestor)
214 {
215 #ifdef HAVE_PROTOBUF
216 d_message.set_from(requestor);
217 #endif /* HAVE_PROTOBUF */
218 }
219
220 void DNSProtoBufMessage::setRequestor(const ComboAddress& requestor)
221 {
222 #ifdef HAVE_PROTOBUF
223 if (requestor.sin4.sin_family == AF_INET) {
224 d_message.set_from(&requestor.sin4.sin_addr.s_addr, sizeof(requestor.sin4.sin_addr.s_addr));
225 }
226 else if (requestor.sin4.sin_family == AF_INET6) {
227 d_message.set_from(&requestor.sin6.sin6_addr.s6_addr, sizeof(requestor.sin6.sin6_addr.s6_addr));
228 }
229 #endif /* HAVE_PROTOBUF */
230 }
231
232 void DNSProtoBufMessage::setRequestorId(const std::string& requestorId)
233 {
234 #ifdef HAVE_PROTOBUF
235 d_message.set_requestorid(requestorId);
236 #endif /* HAVE_PROTOBUF */
237 }
238
239 void DNSProtoBufMessage::setDeviceId(const std::string& deviceId)
240 {
241 #ifdef HAVE_PROTOBUF
242 d_message.set_deviceid(deviceId);
243 #endif /* HAVE_PROTOBUF */
244 }
245
246 void DNSProtoBufMessage::setResponder(const std::string& responder)
247 {
248 #ifdef HAVE_PROTOBUF
249 d_message.set_to(responder);
250 #endif /* HAVE_PROTOBUF */
251 }
252
253 void DNSProtoBufMessage::setResponder(const ComboAddress& responder)
254 {
255 #ifdef HAVE_PROTOBUF
256 if (responder.sin4.sin_family == AF_INET) {
257 d_message.set_to(&responder.sin4.sin_addr.s_addr, sizeof(responder.sin4.sin_addr.s_addr));
258 }
259 else if (responder.sin4.sin_family == AF_INET6) {
260 d_message.set_to(&responder.sin6.sin6_addr.s6_addr, sizeof(responder.sin6.sin6_addr.s6_addr));
261 }
262 #endif /* HAVE_PROTOBUF */
263 }
264
265 void DNSProtoBufMessage::serialize(std::string& data) const
266 {
267 #ifdef HAVE_PROTOBUF
268 d_message.SerializeToString(&data);
269 #endif /* HAVE_PROTOBUF */
270 }
271
272 std::string DNSProtoBufMessage::toDebugString() const
273 {
274 #ifdef HAVE_PROTOBUF
275 return d_message.DebugString();
276 #else
277 return std::string();
278 #endif /* HAVE_PROTOBUF */
279 }
280
281 #ifdef HAVE_PROTOBUF
282
283 void DNSProtoBufMessage::setUUID(const boost::uuids::uuid& uuid)
284 {
285 std::string* messageId = d_message.mutable_messageid();
286 messageId->resize(uuid.size());
287 std::copy(uuid.begin(), uuid.end(), messageId->begin());
288 }
289
290 void DNSProtoBufMessage::setInitialRequestID(const boost::uuids::uuid& uuid)
291 {
292 std::string* messageId = d_message.mutable_initialrequestid();
293 messageId->resize(uuid.size());
294 std::copy(uuid.begin(), uuid.end(), messageId->begin());
295 }
296
297 void DNSProtoBufMessage::update(const boost::uuids::uuid& uuid, const ComboAddress* requestor, const ComboAddress* responder, bool isTCP, uint16_t id)
298 {
299 struct timespec ts;
300 gettime(&ts, true);
301 setTime(ts.tv_sec, ts.tv_nsec / 1000);
302
303 setUUID(uuid);
304 d_message.set_id(ntohs(id));
305
306 if (requestor) {
307 d_message.set_socketfamily(requestor->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6);
308 }
309 else if (responder) {
310 d_message.set_socketfamily(responder->sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6);
311 }
312
313 d_message.set_socketprotocol(isTCP ? PBDNSMessage_SocketProtocol_TCP : PBDNSMessage_SocketProtocol_UDP);
314
315 if (responder) {
316 setResponder(*responder);
317 }
318 if (requestor) {
319 setRequestor(*requestor);
320 }
321 }
322
323
324 DNSProtoBufMessage::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)
325 {
326 update(uuid, requestor, responder, isTCP, qid);
327
328 setType(type);
329
330 setBytes(bytes);
331 setQuestion(domain, qtype, qclass);
332 }
333
334 #endif /* HAVE_PROTOBUF */