2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
25 #include <boost/uuid/uuid.hpp>
26 #include <boost/uuid/uuid_generators.hpp>
30 #include "protobuf.hh"
33 #include "dnsparser.hh"
34 #include "protobuf.hh"
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
;
45 int main(int argc
, char **argv
)
47 for(int n
=1 ; n
< argc
; ++n
) {
48 if ((string
) argv
[n
] == "--help") {
53 if ((string
) argv
[n
] == "--version") {
54 cerr
<<"dnspcap2protobuf "<<VERSION
<<endl
;
65 PcapPacketReader
pr(argv
[1]);
67 FILE* fp
= fopen(argv
[2], "w");
69 cerr
<<"Error opening output file "<<argv
[2]<<": "<<strerror(errno
)<<endl
;
77 std::map
<uint16_t,std::pair
<boost::uuids::uuid
,struct timeval
> > ids
;
78 boost::uuids::random_generator uuidGenerator
;
80 while (pr
.getUDPPacket()) {
81 const dnsheader
* dh
=(dnsheader
*)pr
.d_payload
;
85 if (pr
.d_len
< sizeof(dnsheader
))
91 uint16_t qtype
, qclass
;
94 qname
=DNSName((const char*)pr
.d_payload
, pr
.d_len
, sizeof(dnsheader
), false, &qtype
, &qclass
);
96 catch(const std::exception
& e
) {
97 cerr
<<"Error while parsing qname: "<<e
.what()<<endl
;
101 boost::uuids::uuid uniqueId
;
102 struct timeval queryTime
= { 0, 0 };
103 bool hasQueryTime
= false;
105 queryTime
.tv_sec
= pr
.d_pheader
.ts
.tv_sec
;
106 queryTime
.tv_usec
= pr
.d_pheader
.ts
.tv_usec
;
107 uniqueId
= uuidGenerator();
108 ids
[dh
->id
] = std::make_pair(uniqueId
, queryTime
);
111 const auto& it
= ids
.find(dh
->id
);
112 if (it
!= ids
.end()) {
113 uniqueId
= it
->second
.first
;
114 queryTime
= it
->second
.second
;
118 uniqueId
= uuidGenerator();
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
;
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
);
131 message
.setResponseCode(dh
->rcode
);
133 message
.setQueryTime(queryTime
.tv_sec
, queryTime
.tv_usec
);
137 message
.addRRsFromPacket((const char*) dh
, pr
.d_len
, true);
139 catch(std::exception
& e
)
141 cerr
<<"Error parsing response records: "<<e
.what()<<endl
;
143 catch(const PDNSException
& e
)
145 cerr
<<"Error parsing response records: "<<e
.reason
<<endl
;
150 message
.serialize(str
);
152 uint16_t mlen
= htons(str
.length());
153 fwrite(&mlen
, 1, sizeof(mlen
), fp
);
154 fwrite(str
.c_str(), 1, str
.length(), fp
);
157 catch (const std::exception
& e
) {
158 cerr
<<"Error while parsing the PCAP file: "<<e
.what()<<endl
;
165 catch(const std::exception
& e
) {
166 cerr
<<"Error opening PCAP file: "<<e
.what()<<endl
;