]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnspcap2protobuf.cc
Merge pull request #4090 from pieterlexis/issue-4085-rec_control-reload-lua-config
[thirdparty/pdns.git] / pdns / dnspcap2protobuf.cc
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 #include <boost/uuid/uuid.hpp>
5 #include <boost/uuid/uuid_generators.hpp>
6
7 #include "iputils.hh"
8 #include "misc.hh"
9 #include "dns.hh"
10 #include "dnspcap.hh"
11 #include "dnsparser.hh"
12 #include "protobuf.hh"
13
14 #include "statbag.hh"
15 StatBag S;
16
17 static void usage()
18 {
19 cerr<<"This program reads DNS queries and responses from a PCAP file and stores them into our protobuf format."<<endl;
20 cerr<<"Usage: dnspcap2protobuf PCAPFILE OUTFILE"<<endl;
21 }
22
23 int main(int argc, char **argv)
24 try {
25 for(int n=1 ; n < argc; ++n) {
26 if ((string) argv[n] == "--help") {
27 usage();
28 return EXIT_SUCCESS;
29 }
30
31 if ((string) argv[n] == "--version") {
32 cerr<<"dnspcap2protobuf "<<VERSION<<endl;
33 return EXIT_SUCCESS;
34 }
35 }
36
37 if(argc < 3) {
38 usage();
39 exit(EXIT_FAILURE);
40 }
41
42
43 PcapPacketReader pr(argv[1]);
44
45 FILE* fp = fopen(argv[2], "w");
46 if (!fp) {
47 cerr<<"Error opening output file "<<argv[2]<<": "<<strerror(errno)<<endl;
48 exit(EXIT_FAILURE);
49 }
50
51 int ind=0;
52 if(argc==4)
53 ind=atoi(argv[3]);
54
55 std::map<uint16_t,boost::uuids::uuid> ids;
56 boost::uuids::random_generator uuidGenerator;
57 try {
58 while (pr.getUDPPacket()) {
59 const dnsheader* dh=(dnsheader*)pr.d_payload;
60 if (!dh->qdcount)
61 continue;
62
63 if (pr.d_len < sizeof(dnsheader))
64 continue;
65
66 if(!dh->rd)
67 continue;
68
69 uint16_t qtype, qclass;
70 DNSName qname;
71 try {
72 qname=DNSName((const char*)pr.d_payload, pr.d_len, sizeof(dnsheader), false, &qtype, &qclass);
73 }
74 catch(const std::exception& e) {
75 cerr<<"Error while parsing qname: "<<e.what()<<endl;
76 continue;
77 }
78
79 boost::uuids::uuid uniqueId;
80 if (!dh->qr) {
81 uniqueId = uuidGenerator();
82 ids[dh->id] = uniqueId;
83 }
84 else {
85 const auto& it = ids.find(dh->id);
86 if (it != ids.end()) {
87 uniqueId = it->second;
88 }
89 else {
90 uniqueId = uuidGenerator();
91 }
92 }
93
94 const ComboAddress requestor = dh->qr ? pr.getDest() : pr.getSource();
95 const ComboAddress responder = dh->qr ? pr.getSource() : pr.getDest();
96 *((char*)&requestor.sin4.sin_addr.s_addr)|=ind;
97 *((char*)&responder.sin4.sin_addr.s_addr)|=ind;
98
99 DNSProtoBufMessage message(dh->qr ? DNSProtoBufMessage::DNSProtoBufMessageType::Response : DNSProtoBufMessage::DNSProtoBufMessageType::Query, uniqueId, &requestor, &responder, qname, qtype, qclass, dh->id, false, pr.d_len);
100 message.setTime(pr.d_pheader.ts.tv_sec, pr.d_pheader.ts.tv_usec);
101
102 if (dh->qr) {
103 message.setResponseCode(dh->rcode);
104 try {
105 message.addRRsFromPacket((const char*) dh, pr.d_len);
106 }
107 catch(std::exception& e)
108 {
109 cerr<<"Error parsing response records: "<<e.what()<<endl;
110 }
111 catch(const PDNSException& e)
112 {
113 cerr<<"Error parsing response records: "<<e.reason<<endl;
114 }
115 }
116
117 std::string str;
118 message.serialize(str);
119
120 uint16_t mlen = htons(str.length());
121 fwrite(&mlen, 1, sizeof(mlen), fp);
122 fwrite(str.c_str(), 1, str.length(), fp);
123 }
124 }
125 catch (const std::exception& e) {
126 cerr<<"Error while parsing the PCAP file: "<<e.what()<<endl;
127 fclose(fp);
128 exit(EXIT_FAILURE);
129 }
130
131 fclose(fp);
132 }
133 catch(const std::exception& e) {
134 cerr<<"Error opening PCAP file: "<<e.what()<<endl;
135 exit(EXIT_FAILURE);
136 }