]>
Commit | Line | Data |
---|---|---|
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 | 8 | void 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 |
30 | DNSProtoBufMessage::DNSProtoBufMessage(DNSProtoBufMessageType type) |
31 | { | |
32 | setType(type); | |
33 | } | |
34 | ||
d9d3f9c1 RG |
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) { | |
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 | ||
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 | ||
57f8413e RG |
65 | void 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 |
76 | void 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 |
84 | void 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 | 95 | void 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 | 111 | void 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 | 124 | void 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 | 143 | void 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 |
223 | void DNSProtoBufMessage::setRequestor(const std::string& requestor) |
224 | { | |
225 | #ifdef HAVE_PROTOBUF | |
226 | d_message.set_from(requestor); | |
227 | #endif /* HAVE_PROTOBUF */ | |
228 | } | |
229 | ||
230 | void 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 |
242 | void 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 |
249 | void 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 |
256 | void 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 |
263 | void 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 |
270 | void 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 | ||
277 | void 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 |
289 | void DNSProtoBufMessage::serialize(std::string& data) const |
290 | { | |
291 | #ifdef HAVE_PROTOBUF | |
292 | d_message.SerializeToString(&data); | |
293 | #endif /* HAVE_PROTOBUF */ | |
294 | } | |
295 | ||
296 | std::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 | ||
307 | void 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 |
314 | void 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 | 321 | void 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 |
328 | void 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 | 352 | 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) |
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 |
362 | void DNSProtoBufMessage::copyFrom(const DNSProtoBufMessage& msg) |
363 | { | |
364 | d_message.CopyFrom(msg.d_message); | |
365 | } | |
366 | ||
d9d3f9c1 | 367 | #endif /* HAVE_PROTOBUF */ |