]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnspcap2protobuf.cc
Merge pull request #4017 from rgacogne/rec-istcp
[thirdparty/pdns.git] / pdns / dnspcap2protobuf.cc
CommitLineData
f9cad4da
RG
1#include <boost/uuid/uuid.hpp>
2#include <boost/uuid/uuid_generators.hpp>
f9cad4da 3
f483cc6d
RG
4#include "dnsmessage.pb.h"
5#include "iputils.hh"
6#include "misc.hh"
7#include "dns.hh"
8#include "dnspcap.hh"
9#include "dnsparser.hh"
10
11#include "statbag.hh"
12StatBag S;
13
14static void addRRs(const char* packet, const size_t len, PBDNSMessage_DNSResponse& response)
1b448d84 15try
f483cc6d
RG
16{
17 if (len < sizeof(struct dnsheader))
18 return;
19
20 const struct dnsheader* dh = (const struct dnsheader*) packet;
21
22 if (ntohs(dh->ancount) == 0)
23 return;
24
25 if (ntohs(dh->qdcount) == 0)
26 return;
27
28 vector<uint8_t> content(len - sizeof(dnsheader));
29 copy(packet + sizeof(dnsheader), packet + len, content.begin());
30 PacketReader pr(content);
31
32 size_t idx = 0;
33 DNSName rrname;
34 uint16_t qdcount = ntohs(dh->qdcount);
35 uint16_t ancount = ntohs(dh->ancount);
36 uint16_t rrtype;
37 uint16_t rrclass;
38 string blob;
39 struct dnsrecordheader ah;
40
41 rrname = pr.getName();
42 rrtype = pr.get16BitInt();
43 rrclass = pr.get16BitInt();
44
45 /* consume remaining qd if any */
46 if (qdcount > 1) {
47 for(idx = 1; idx < qdcount; idx++) {
48 rrname = pr.getName();
49 rrtype = pr.get16BitInt();
50 rrclass = pr.get16BitInt();
51 (void) rrtype;
52 (void) rrclass;
53 }
54 }
55
56 /* parse AN */
57 for (idx = 0; idx < ancount; idx++) {
58 rrname = pr.getName();
59 pr.getDnsrecordheader(ah);
60
61 pr.xfrBlob(blob);
62 if (ah.d_type == QType::A || ah.d_type == QType::AAAA) {
63 PBDNSMessage_DNSResponse_DNSRR* rr = response.add_rrs();
64 if (rr) {
65 rr->set_name(rrname.toString());
66 rr->set_type(ah.d_type);
67 rr->set_class_(ah.d_class);
68 rr->set_ttl(ah.d_ttl);
69 rr->set_rdata(blob.c_str(), blob.length());
70 }
71 }
72 }
73}
1b448d84 74catch(std::exception& e)
75{
76 cerr<<"Error parsing response records: "<<e.what()<<endl;
77}
f483cc6d
RG
78int main(int argc, char **argv)
79{
2718cbf4 80 if(argc < 3) {
f483cc6d
RG
81 cerr<<"This program reads DNS queries and responses from a PCAP file and stores them into our protobuf format."<<endl;
82 cerr<<"Usage: "<<argv[0]<<" <PCAP file> <out file>"<<endl;
83 exit(EXIT_FAILURE);
84 }
85
86 PcapPacketReader pr(argv[1]);
87
88 FILE* fp = fopen(argv[2], "w");
89 if (!fp) {
90 cerr<<"Error opening output file "<<argv[2]<<": "<<strerror(errno)<<endl;
91 exit(EXIT_FAILURE);
92 }
2718cbf4 93
94 int ind=0;
95 if(argc==4)
96 ind=atoi(argv[3]);
97
f9cad4da
RG
98 std::map<uint16_t,boost::uuids::uuid> ids;
99 boost::uuids::random_generator uuidGenerator;
f483cc6d
RG
100 while (pr.getUDPPacket()) {
101 const dnsheader* dh=(dnsheader*)pr.d_payload;
102 if (!dh->qdcount)
103 continue;
104
4c2862d4
RG
105 if (pr.d_len < sizeof(dnsheader))
106 continue;
107
d1f94072 108 if(!dh->rd)
2718cbf4 109 continue;
110
f483cc6d
RG
111 uint16_t qtype, qclass;
112 DNSName qname;
113 try {
114 qname=DNSName((const char*)pr.d_payload, pr.d_len, sizeof(dnsheader), false, &qtype, &qclass);
115 }
116 catch(const std::exception& e) {
117 cerr<<"Error while parsing qname: "<<e.what()<<endl;
118 continue;
119 }
120
121 PBDNSMessage message;
122 message.set_timesec(pr.d_pheader.ts.tv_sec);
123 message.set_timeusec(pr.d_pheader.ts.tv_usec);
124 message.set_id(ntohs(dh->id));
125 message.set_type(dh->qr ? PBDNSMessage_Type_DNSResponseType : PBDNSMessage_Type_DNSQueryType);
2718cbf4 126 const ComboAddress requestor = dh->qr ? pr.getDest() : pr.getSource();
127 const ComboAddress responder = dh->qr ? pr.getSource() : pr.getDest();
128
129 *((char*)&requestor.sin4.sin_addr.s_addr)|=ind;
130 *((char*)&responder.sin4.sin_addr.s_addr)|=ind;
131 message.set_socketfamily(requestor.sin4.sin_family == AF_INET ? PBDNSMessage_SocketFamily_INET : PBDNSMessage_SocketFamily_INET6);
f483cc6d
RG
132 // we handle UDP packets only for now
133 message.set_socketprotocol(PBDNSMessage_SocketProtocol_UDP);
2718cbf4 134 if (requestor.sin4.sin_family == AF_INET) {
135 message.set_from(&requestor.sin4.sin_addr.s_addr, sizeof(requestor.sin4.sin_addr.s_addr));
f483cc6d 136 }
2718cbf4 137 else if (requestor.sin4.sin_family == AF_INET6) {
138 message.set_from(&requestor.sin6.sin6_addr.s6_addr, sizeof(requestor.sin6.sin6_addr.s6_addr));
f483cc6d 139 }
2718cbf4 140 if (responder.sin4.sin_family == AF_INET) {
141 message.set_to(&responder.sin4.sin_addr.s_addr, sizeof(responder.sin4.sin_addr.s_addr));
f483cc6d 142 }
2718cbf4 143 else if (responder.sin4.sin_family == AF_INET6) {
144 message.set_to(&responder.sin6.sin6_addr.s6_addr, sizeof(responder.sin6.sin6_addr.s6_addr));
f483cc6d
RG
145 }
146 message.set_inbytes(pr.d_len);
147
148 PBDNSMessage_DNSQuestion question;
149 PBDNSMessage_DNSResponse response;
150 if (!dh->qr) {
f9cad4da
RG
151 boost::uuids::uuid uniqueId = uuidGenerator();
152 ids[dh->id] = uniqueId;
ec469dd7
RG
153 std::string* messageId = message.mutable_messageid();
154 messageId->resize(uniqueId.size());
155 std::copy(uniqueId.begin(), uniqueId.end(), messageId->begin());
f483cc6d
RG
156 }
157 else {
f9cad4da
RG
158 const auto& it = ids.find(dh->id);
159 if (it != ids.end()) {
ec469dd7
RG
160 std::string* messageId = message.mutable_messageid();
161 messageId->resize(it->second.size());
162 std::copy(it->second.begin(), it->second.end(), messageId->begin());
f9cad4da 163 }
ec469dd7 164
f483cc6d
RG
165 response.set_rcode(dh->rcode);
166 addRRs((const char*) dh, pr.d_len, response);
167 message.set_allocated_response(&response);
168 }
169
ec469dd7
RG
170 question.set_qname(qname.toString());
171 question.set_qtype(qtype);
172 question.set_qclass(qclass);
173 message.set_allocated_question(&question);
f483cc6d 174 std::string str;
f9cad4da 175 //cerr<<message.DebugString()<<endl;
f483cc6d 176 message.SerializeToString(&str);
1b448d84 177 uint16_t mlen = htons(str.length());
f483cc6d
RG
178 fwrite(&mlen, 1, sizeof(mlen), fp);
179 fwrite(str.c_str(), 1, str.length(), fp);
180 if (!dh->qr) {
181 message.release_question();
182 }
183 else {
184 message.release_response();
185 }
186 }
187 fclose(fp);
188}