]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnspcap.cc
Merge branch 'master' of github.com:PowerDNS/pdns
[thirdparty/pdns.git] / pdns / dnspcap.cc
CommitLineData
0b86fb59 1#define __FAVOR_BSD
ab06937b 2#include "dnspcap.hh"
11212b81 3#include <boost/format.hpp>
0b86fb59 4#include <fcntl.h>
ab06937b 5
61b26744 6#include "namespaces.hh"
ab06937b
BH
7PcapPacketReader::PcapPacketReader(const string& fname) : d_fname(fname)
8{
9 d_fp=fopen(fname.c_str(),"r");
10 if(!d_fp)
11 unixDie("Unable to open file");
12
0b86fb59
BH
13 int flags=fcntl(fileno(d_fp),F_GETFL,0);
14 fcntl(fileno(d_fp), F_SETFL,flags&(~O_NONBLOCK)); // bsd needs this in stdin (??)
ab06937b
BH
15
16 checkedFread(&d_pfh);
17
18 if(d_pfh.magic != 2712847316UL)
19 throw runtime_error((format("PCAP file %s has bad magic %x, should be %x") % fname % d_pfh.magic % 2712847316UL).str());
20
2acf3098
BH
21 if( d_pfh.linktype==1) {
22 d_skipMediaHeader=sizeof(struct ether_header);
23 } else if(d_pfh.linktype==113) {
24 d_skipMediaHeader=16;
25 }
26 else throw runtime_error((format("Unsupported link type %d") % d_pfh.linktype).str());
ab06937b 27
11212b81 28 d_runts = d_oversized = d_correctpackets = d_nonetheripudp = 0;
ab06937b
BH
29}
30
11212b81 31PcapPacketReader::~PcapPacketReader()
ab06937b
BH
32{
33 fclose(d_fp);
34}
35
36
37void PcapPacketReader::checkedFreadSize(void* ptr, size_t size)
38{
39 int ret=fread(ptr, 1, size, d_fp);
40 if(ret < 0)
41 unixDie( (format("Error reading %d bytes from %s") % size % d_fname).str());
42
43 if(!ret)
44 throw EofException();
45
46 if((size_t)ret != size)
47 throw EofException((format("Incomplete read from '%s', got only %d bytes") % d_fname % ret).str());
48}
49
50bool PcapPacketReader::getUDPPacket()
51try
52{
53 for(;;) {
54 checkedFread(&d_pheader);
e0333255
BH
55 if(!d_pheader.caplen)
56 continue;
3042f1ba 57
ab06937b
BH
58 if(d_pheader.caplen > sizeof(d_buffer)) {
59 d_oversized++;
3042f1ba 60 throw runtime_error((format("Can't handle a %d byte packet, have space for %d") % d_pheader.caplen % sizeof(d_buffer)).str());
ab06937b 61 }
3042f1ba 62
ab06937b 63 checkedFreadSize(d_buffer, d_pheader.caplen);
3042f1ba
BH
64
65 if(d_pheader.caplen!=d_pheader.len) {
66 d_runts++;
67 continue;
68 }
69
11212b81 70 d_ether=reinterpret_cast<struct ether_header*>(d_buffer);
2acf3098
BH
71 d_lcc=reinterpret_cast<struct pdns_lcc_header*>(d_buffer);
72
73 d_ip=reinterpret_cast<struct ip*>(d_buffer + d_skipMediaHeader);
bf32bff8 74 d_ip6=reinterpret_cast<struct ip6_hdr*>(d_buffer + d_skipMediaHeader);
49f61cba 75 uint16_t contentCode=0;
2acf3098
BH
76 if(d_pfh.linktype==1)
77 contentCode=ntohs(d_ether->ether_type);
78 else if(d_pfh.linktype==113)
79 contentCode=ntohs(d_lcc->lcc_protocol);
3042f1ba 80
2acf3098
BH
81 if(contentCode==0x0800 && d_ip->ip_p==17) { // udp
82 d_udp=reinterpret_cast<const struct udphdr*>(d_buffer + d_skipMediaHeader + 4 * d_ip->ip_hl);
ab06937b 83 d_payload = (unsigned char*)d_udp + sizeof(struct udphdr);
0b86fb59 84 d_len = ntohs(d_udp->uh_ulen) - sizeof(struct udphdr);
11212b81 85 d_correctpackets++;
ab06937b
BH
86 return true;
87 }
bf32bff8 88 if(contentCode==0x86dd && d_ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt==17) { // udpv6, we ignore anything with extension hdr
89 d_udp=reinterpret_cast<const struct udphdr*>(d_buffer + d_skipMediaHeader + sizeof(struct ip6_hdr));
90 d_payload = (unsigned char*)d_udp + sizeof(struct udphdr);
91 d_len = ntohs(d_udp->uh_ulen) - sizeof(struct udphdr);
92 d_correctpackets++;
93 return true;
94 }
95
11212b81
BH
96 else {
97 d_nonetheripudp++;
98 }
ab06937b
BH
99 }
100}
101catch(EofException) {
102 return false;
103}
104
a5d9353e 105ComboAddress PcapPacketReader::getSource() const
106{
107 ComboAddress ret;
108 if(d_ip->ip_v == 4) {
109 ret.sin4.sin_family = AF_INET;
110 ret.sin4.sin_addr = d_ip->ip_src;
111 ret.sin4.sin_port = d_udp->uh_sport; // should deal with TCP too!
112 } else {
113 ret.sin6.sin6_family = AF_INET6;
114 ret.sin6.sin6_addr = d_ip6->ip6_src;
115 ret.sin6.sin6_port = d_udp->uh_sport; // should deal with TCP too!
116 }
117 return ret;
118}
119
120ComboAddress PcapPacketReader::getDest() const
121{
122 ComboAddress ret;
123 if(d_ip->ip_v == 4) {
124 ret.sin4.sin_family = AF_INET;
125 ret.sin4.sin_addr = d_ip->ip_dst;
126 ret.sin4.sin_port = d_udp->uh_dport; // should deal with TCP too!
127 } else {
128 ret.sin6.sin6_family = AF_INET6;
129 ret.sin6.sin6_addr = d_ip6->ip6_dst;
130 ret.sin6.sin6_port = d_udp->uh_dport; // should deal with TCP too!
131 }
132 return ret;
133}
134
ab06937b
BH
135PcapPacketWriter::PcapPacketWriter(const string& fname, PcapPacketReader& ppr) : d_fname(fname), d_ppr(ppr)
136{
137 d_fp=fopen(fname.c_str(),"w");
138 if(!d_fp)
139 unixDie("Unable to open file");
140
0419f7af
BH
141 int flags=fcntl(fileno(d_fp),F_GETFL,0);
142 fcntl(fileno(d_fp), F_SETFL,flags&(~O_NONBLOCK)); // bsd needs this in stdin (??)
143
ab06937b 144 fwrite(&ppr.d_pfh, 1, sizeof(ppr.d_pfh), d_fp);
ab06937b
BH
145}
146
147void PcapPacketWriter::write()
148{
149 fwrite(&d_ppr.d_pheader, 1, sizeof(d_ppr.d_pheader), d_fp);
150 fwrite(d_ppr.d_buffer, 1, d_ppr.d_pheader.caplen, d_fp);
151}
152
11212b81 153PcapPacketWriter::~PcapPacketWriter()
ab06937b
BH
154{
155 fclose(d_fp);
156}