]>
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 | ||
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 | ||
58307a85 RG |
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 | ||
a94bc5d7 | 84 | void DNSProtoBufMessage::setEDNSSubnet(const Netmask& subnet, uint8_t mask) |
d9d3f9c1 RG |
85 | { |
86 | #ifdef HAVE_PROTOBUF | |
87 | if (!subnet.empty()) { | |
a94bc5d7 RG |
88 | ComboAddress ca(subnet.getNetwork()); |
89 | ca.truncate(mask); | |
d9d3f9c1 RG |
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 | ||
e6956c91 | 100 | void DNSProtoBufMessage::addTag(const std::string& strValue) |
26a6373d SO |
101 | { |
102 | #ifdef HAVE_PROTOBUF | |
103 | ||
104 | PBDNSMessage_DNSResponse* response = d_message.mutable_response(); | |
105 | if (!response) | |
106 | return; | |
107 | ||
e6956c91 | 108 | response->add_tags(strValue); |
26a6373d SO |
109 | |
110 | #endif /* HAVE_PROTOBUF */ | |
111 | } | |
112 | ||
ff09c374 | 113 | void DNSProtoBufMessage::addRR(const DNSName& qname, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& strBlob) |
26a6373d SO |
114 | { |
115 | #ifdef HAVE_PROTOBUF | |
116 | ||
117 | PBDNSMessage_DNSResponse* response = d_message.mutable_response(); | |
118 | if (!response) | |
119 | return; | |
26a6373d | 120 | PBDNSMessage_DNSResponse_DNSRR* rr = response->add_rrs(); |
29cd61cc | 121 | if (rr) { |
ff09c374 | 122 | rr->set_name(qname.toString()); |
29cd61cc SO |
123 | rr->set_type(uType); |
124 | rr->set_class_(uClass); | |
125 | rr->set_ttl(uTTL); | |
c959e01a | 126 | rr->set_rdata(strBlob.c_str(), strBlob.size()); |
29cd61cc | 127 | } |
26a6373d SO |
128 | |
129 | #endif /* HAVE_PROTOBUF */ | |
130 | } | |
26a6373d | 131 | |
165c9030 | 132 | void DNSProtoBufMessage::addRRsFromPacket(const char* packet, const size_t len, bool includeCNAME) |
d9d3f9c1 RG |
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 | ||
d9d3f9c1 | 183 | if (ah.d_type == QType::A || ah.d_type == QType::AAAA) { |
165c9030 RG |
184 | pr.xfrBlob(blob); |
185 | ||
d9d3f9c1 RG |
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 | } | |
165c9030 RG |
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); | |
d9d3f9c1 RG |
208 | } |
209 | } | |
210 | #endif /* HAVE_PROTOBUF */ | |
211 | } | |
212 | ||
a94673ea RG |
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 | ||
67e31ebe RG |
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 | ||
590388d2 NC |
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 | ||
a94673ea RG |
246 | void DNSProtoBufMessage::setResponder(const std::string& responder) |
247 | { | |
248 | #ifdef HAVE_PROTOBUF | |
b3261c20 | 249 | d_message.set_to(responder); |
a94673ea RG |
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) { | |
b3261c20 | 257 | d_message.set_to(&responder.sin4.sin_addr.s_addr, sizeof(responder.sin4.sin_addr.s_addr)); |
a94673ea RG |
258 | } |
259 | else if (responder.sin4.sin_family == AF_INET6) { | |
b3261c20 | 260 | d_message.set_to(&responder.sin6.sin6_addr.s6_addr, sizeof(responder.sin6.sin6_addr.s6_addr)); |
a94673ea RG |
261 | } |
262 | #endif /* HAVE_PROTOBUF */ | |
263 | } | |
264 | ||
d9d3f9c1 RG |
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(); | |
121c28e9 RG |
276 | #else |
277 | return std::string(); | |
d9d3f9c1 RG |
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 | ||
4898a348 RG |
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 | ||
d9d3f9c1 RG |
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 | ||
4898a348 RG |
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 | ||
d9d3f9c1 RG |
313 | d_message.set_socketprotocol(isTCP ? PBDNSMessage_SocketProtocol_TCP : PBDNSMessage_SocketProtocol_UDP); |
314 | ||
315 | if (responder) { | |
a94673ea | 316 | setResponder(*responder); |
d9d3f9c1 RG |
317 | } |
318 | if (requestor) { | |
a94673ea | 319 | setRequestor(*requestor); |
d9d3f9c1 RG |
320 | } |
321 | } | |
322 | ||
323 | ||
4898a348 | 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) |
d9d3f9c1 | 325 | { |
4898a348 | 326 | update(uuid, requestor, responder, isTCP, qid); |
d9d3f9c1 | 327 | |
4898a348 | 328 | setType(type); |
d9d3f9c1 RG |
329 | |
330 | setBytes(bytes); | |
331 | setQuestion(domain, qtype, qclass); | |
332 | } | |
333 | ||
334 | #endif /* HAVE_PROTOBUF */ |