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