]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnspcap.cc
44a720b35408bf878e18a7a06443b2818a7c0702
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.
27 #include <boost/format.hpp>
30 #include "namespaces.hh"
31 PcapPacketReader::PcapPacketReader(const string
& fname
) : d_fname(fname
)
33 d_fp
=fopen(fname
.c_str(),"r");
35 unixDie("Unable to open file " + fname
);
37 int flags
=fcntl(fileno(d_fp
),F_GETFL
,0);
38 fcntl(fileno(d_fp
), F_SETFL
,flags
&(~O_NONBLOCK
)); // bsd needs this in stdin (??)
42 if(d_pfh
.magic
!= 2712847316UL)
43 throw runtime_error((format("PCAP file %s has bad magic %x, should be %x") % fname
% d_pfh
.magic
% 2712847316UL).str());
45 if( d_pfh
.linktype
==1) {
46 d_skipMediaHeader
=sizeof(struct ether_header
);
48 else if(d_pfh
.linktype
==101) {
51 else if(d_pfh
.linktype
==113) {
54 else throw runtime_error((format("Unsupported link type %d") % d_pfh
.linktype
).str());
56 d_runts
= d_oversized
= d_correctpackets
= d_nonetheripudp
= 0;
59 PcapPacketReader::~PcapPacketReader()
65 void PcapPacketReader::checkedFreadSize(void* ptr
, size_t size
)
67 int ret
=fread(ptr
, 1, size
, d_fp
);
69 unixDie( (format("Error reading %d bytes from %s") % size
% d_fname
).str());
74 if((size_t)ret
!= size
)
75 throw EofException((format("Incomplete read from '%s', got only %d bytes") % d_fname
% ret
).str());
78 bool PcapPacketReader::getUDPPacket()
82 checkedFread(&d_pheader
);
83 if(!d_pheader
.caplen
) {
88 if(d_pheader
.caplen
> sizeof(d_buffer
)) {
90 throw runtime_error((format("Can't handle a %d byte packet, have space for %d") % d_pheader
.caplen
% sizeof(d_buffer
)).str());
93 checkedFreadSize(d_buffer
, d_pheader
.caplen
);
95 if(d_pheader
.caplen
< d_pheader
.len
) {
100 if (d_pheader
.caplen
< d_skipMediaHeader
) {
105 d_ip
=reinterpret_cast<struct ip
*>(d_buffer
+ d_skipMediaHeader
);
106 d_ip6
=reinterpret_cast<struct ip6_hdr
*>(d_buffer
+ d_skipMediaHeader
);
107 uint16_t contentCode
=0;
109 if(d_pfh
.linktype
==1) {
110 if (d_pheader
.caplen
< sizeof(*d_ether
)) {
114 d_ether
=reinterpret_cast<struct ether_header
*>(d_buffer
);
115 contentCode
=ntohs(d_ether
->ether_type
);
117 else if(d_pfh
.linktype
==101) {
118 if (d_pheader
.caplen
< (d_skipMediaHeader
+ sizeof(*d_ip
))) {
123 contentCode
= 0x0800;
125 contentCode
= 0x86dd;
127 else if(d_pfh
.linktype
==113) {
128 if (d_pheader
.caplen
< sizeof(*d_lcc
)) {
132 d_lcc
=reinterpret_cast<struct pdns_lcc_header
*>(d_buffer
);
133 contentCode
=ntohs(d_lcc
->lcc_protocol
);
136 if(contentCode
==0x0800 && d_ip
->ip_p
==17) { // udp
137 if (d_pheader
.caplen
< (d_skipMediaHeader
+ (4 * d_ip
->ip_hl
) + sizeof(*d_udp
))) {
141 d_udp
=reinterpret_cast<const struct udphdr
*>(d_buffer
+ d_skipMediaHeader
+ 4 * d_ip
->ip_hl
);
142 d_payload
= (unsigned char*)d_udp
+ sizeof(struct udphdr
);
143 d_len
= ntohs(d_udp
->uh_ulen
) - sizeof(struct udphdr
);
144 if (d_pheader
.caplen
< (d_skipMediaHeader
+ (4 * d_ip
->ip_hl
) + sizeof(*d_udp
) + d_len
)) {
148 if((const char*)d_payload
+ d_len
> d_buffer
+ d_pheader
.caplen
) {
155 else if(contentCode
==0x86dd && d_ip6
->ip6_ctlun
.ip6_un1
.ip6_un1_nxt
==17) { // udpv6, we ignore anything with extension hdr
156 if (d_pheader
.caplen
< (d_skipMediaHeader
+ sizeof(struct ip6_hdr
) + sizeof(struct udphdr
))) {
160 d_udp
=reinterpret_cast<const struct udphdr
*>(d_buffer
+ d_skipMediaHeader
+ sizeof(struct ip6_hdr
));
161 d_payload
= (unsigned char*)d_udp
+ sizeof(struct udphdr
);
162 d_len
= ntohs(d_udp
->uh_ulen
) - sizeof(struct udphdr
);
163 if (d_pheader
.caplen
< (d_skipMediaHeader
+ sizeof(struct ip6_hdr
) + sizeof(struct udphdr
) + d_len
)) {
167 if((const char*)d_payload
+ d_len
> d_buffer
+ d_pheader
.caplen
) {
180 catch(const EofException
&) {
184 ComboAddress
PcapPacketReader::getSource() const
187 if(d_ip
->ip_v
== 4) {
188 ret
.sin4
.sin_family
= AF_INET
;
189 ret
.sin4
.sin_addr
= d_ip
->ip_src
;
190 ret
.sin4
.sin_port
= d_udp
->uh_sport
; // should deal with TCP too!
192 ret
.sin6
.sin6_family
= AF_INET6
;
193 ret
.sin6
.sin6_addr
= d_ip6
->ip6_src
;
194 ret
.sin6
.sin6_port
= d_udp
->uh_sport
; // should deal with TCP too!
199 ComboAddress
PcapPacketReader::getDest() const
202 if(d_ip
->ip_v
== 4) {
203 ret
.sin4
.sin_family
= AF_INET
;
204 ret
.sin4
.sin_addr
= d_ip
->ip_dst
;
205 ret
.sin4
.sin_port
= d_udp
->uh_dport
; // should deal with TCP too!
207 ret
.sin6
.sin6_family
= AF_INET6
;
208 ret
.sin6
.sin6_addr
= d_ip6
->ip6_dst
;
209 ret
.sin6
.sin6_port
= d_udp
->uh_dport
; // should deal with TCP too!
214 PcapPacketWriter::PcapPacketWriter(const string
& fname
, const PcapPacketReader
& ppr
) : PcapPacketWriter(fname
)
219 PcapPacketWriter::PcapPacketWriter(const string
& fname
) : d_fname(fname
)
221 d_fp
=fopen(fname
.c_str(),"w");
223 unixDie("Unable to open file");
225 int flags
=fcntl(fileno(d_fp
),F_GETFL
,0);
226 fcntl(fileno(d_fp
), F_SETFL
,flags
&(~O_NONBLOCK
)); // bsd needs this in stdin (??)
229 void PcapPacketWriter::write()
236 fwrite(&d_ppr
->d_pfh
, 1, sizeof(d_ppr
->d_pfh
), d_fp
);
239 fwrite(&d_ppr
->d_pheader
, 1, sizeof(d_ppr
->d_pheader
), d_fp
);
240 fwrite(d_ppr
->d_buffer
, 1, d_ppr
->d_pheader
.caplen
, d_fp
);
243 PcapPacketWriter::~PcapPacketWriter()