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