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