]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnspcap2protobuf.cc
Merge pull request #5523 from rubenk/fix-typos-in-logmessage
[thirdparty/pdns.git] / pdns / dnspcap2protobuf.cc
CommitLineData
12471842
PL
1/*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
a4a74820
PL
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
f9cad4da
RG
25#include <boost/uuid/uuid.hpp>
26#include <boost/uuid/uuid_generators.hpp>
f9cad4da 27
f483cc6d
RG
28#include "iputils.hh"
29#include "misc.hh"
4898a348 30#include "protobuf.hh"
f483cc6d
RG
31#include "dns.hh"
32#include "dnspcap.hh"
33#include "dnsparser.hh"
d9d3f9c1 34#include "protobuf.hh"
f483cc6d
RG
35
36#include "statbag.hh"
37StatBag S;
38
d9d3f9c1 39static void usage()
a4a74820
PL
40{
41 cerr<<"This program reads DNS queries and responses from a PCAP file and stores them into our protobuf format."<<endl;
42 cerr<<"Usage: dnspcap2protobuf PCAPFILE OUTFILE"<<endl;
43}
44
f483cc6d 45int main(int argc, char **argv)
d7729968 46try {
a4a74820
PL
47 for(int n=1 ; n < argc; ++n) {
48 if ((string) argv[n] == "--help") {
49 usage();
50 return EXIT_SUCCESS;
51 }
52
53 if ((string) argv[n] == "--version") {
54 cerr<<"dnspcap2protobuf "<<VERSION<<endl;
55 return EXIT_SUCCESS;
56 }
57 }
58
2718cbf4 59 if(argc < 3) {
a4a74820 60 usage();
f483cc6d
RG
61 exit(EXIT_FAILURE);
62 }
63
a4a74820 64
f483cc6d
RG
65 PcapPacketReader pr(argv[1]);
66
67 FILE* fp = fopen(argv[2], "w");
68 if (!fp) {
69 cerr<<"Error opening output file "<<argv[2]<<": "<<strerror(errno)<<endl;
70 exit(EXIT_FAILURE);
71 }
2718cbf4 72
73 int ind=0;
74 if(argc==4)
75 ind=atoi(argv[3]);
76
58307a85 77 std::map<uint16_t,std::pair<boost::uuids::uuid,struct timeval> > ids;
f9cad4da 78 boost::uuids::random_generator uuidGenerator;
d7729968
RG
79 try {
80 while (pr.getUDPPacket()) {
81 const dnsheader* dh=(dnsheader*)pr.d_payload;
82 if (!dh->qdcount)
83 continue;
84
85 if (pr.d_len < sizeof(dnsheader))
86 continue;
87
88 if(!dh->rd)
89 continue;
90
91 uint16_t qtype, qclass;
92 DNSName qname;
93 try {
94 qname=DNSName((const char*)pr.d_payload, pr.d_len, sizeof(dnsheader), false, &qtype, &qclass);
95 }
96 catch(const std::exception& e) {
97 cerr<<"Error while parsing qname: "<<e.what()<<endl;
98 continue;
99 }
f483cc6d 100
d9d3f9c1 101 boost::uuids::uuid uniqueId;
58307a85
RG
102 struct timeval queryTime = { 0, 0 };
103 bool hasQueryTime = false;
d7729968 104 if (!dh->qr) {
58307a85
RG
105 queryTime.tv_sec = pr.d_pheader.ts.tv_sec;
106 queryTime.tv_usec = pr.d_pheader.ts.tv_usec;
d9d3f9c1 107 uniqueId = uuidGenerator();
58307a85 108 ids[dh->id] = std::make_pair(uniqueId, queryTime);
d7729968
RG
109 }
110 else {
111 const auto& it = ids.find(dh->id);
112 if (it != ids.end()) {
58307a85
RG
113 uniqueId = it->second.first;
114 queryTime = it->second.second;
115 hasQueryTime = true;
d9d3f9c1
RG
116 }
117 else {
118 uniqueId = uuidGenerator();
d7729968 119 }
f9cad4da 120 }
ec469dd7 121
d9d3f9c1
RG
122 const ComboAddress requestor = dh->qr ? pr.getDest() : pr.getSource();
123 const ComboAddress responder = dh->qr ? pr.getSource() : pr.getDest();
124 *((char*)&requestor.sin4.sin_addr.s_addr)|=ind;
125 *((char*)&responder.sin4.sin_addr.s_addr)|=ind;
126
127 DNSProtoBufMessage message(dh->qr ? DNSProtoBufMessage::DNSProtoBufMessageType::Response : DNSProtoBufMessage::DNSProtoBufMessageType::Query, uniqueId, &requestor, &responder, qname, qtype, qclass, dh->id, false, pr.d_len);
128 message.setTime(pr.d_pheader.ts.tv_sec, pr.d_pheader.ts.tv_usec);
129
130 if (dh->qr) {
131 message.setResponseCode(dh->rcode);
58307a85
RG
132 if (hasQueryTime) {
133 message.setQueryTime(queryTime.tv_sec, queryTime.tv_usec);
134 }
135
d9d3f9c1 136 try {
165c9030 137 message.addRRsFromPacket((const char*) dh, pr.d_len, true);
d9d3f9c1
RG
138 }
139 catch(std::exception& e)
140 {
141 cerr<<"Error parsing response records: "<<e.what()<<endl;
142 }
143 catch(const PDNSException& e)
144 {
145 cerr<<"Error parsing response records: "<<e.reason<<endl;
146 }
147 }
3bde188c 148
d7729968 149 std::string str;
d9d3f9c1
RG
150 message.serialize(str);
151
d7729968
RG
152 uint16_t mlen = htons(str.length());
153 fwrite(&mlen, 1, sizeof(mlen), fp);
154 fwrite(str.c_str(), 1, str.length(), fp);
155 }
156 }
157 catch (const std::exception& e) {
158 cerr<<"Error while parsing the PCAP file: "<<e.what()<<endl;
159 fclose(fp);
160 exit(EXIT_FAILURE);
f483cc6d 161 }
d7729968 162
f483cc6d
RG
163 fclose(fp);
164}
d7729968
RG
165catch(const std::exception& e) {
166 cerr<<"Error opening PCAP file: "<<e.what()<<endl;
167 exit(EXIT_FAILURE);
168}