]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnspcap.cc
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
==12) { // LOOP
51 else if(d_pfh
.linktype
==101) {
54 else if(d_pfh
.linktype
==113) {
57 else throw runtime_error((format("Unsupported link type %d") % d_pfh
.linktype
).str());
59 d_runts
= d_oversized
= d_correctpackets
= d_nonetheripudp
= 0;
62 PcapPacketReader::~PcapPacketReader()
68 void PcapPacketReader::checkedFreadSize(void* ptr
, size_t size
)
70 int ret
=fread(ptr
, 1, size
, d_fp
);
72 unixDie( (format("Error reading %d bytes from %s") % size
% d_fname
).str());
77 if((size_t)ret
!= size
)
78 throw EofException((format("Incomplete read from '%s', got only %d bytes") % d_fname
% ret
).str());
81 bool PcapPacketReader::getUDPPacket()
85 checkedFread(&d_pheader
);
86 if(!d_pheader
.caplen
) {
91 if(d_pheader
.caplen
> sizeof(d_buffer
)) {
93 throw runtime_error((format("Can't handle a %d byte packet, have space for %d") % d_pheader
.caplen
% sizeof(d_buffer
)).str());
96 checkedFreadSize(d_buffer
, d_pheader
.caplen
);
98 if(d_pheader
.caplen
< d_pheader
.len
) {
103 if (d_pheader
.caplen
< d_skipMediaHeader
) {
108 d_ip
=reinterpret_cast<struct ip
*>(d_buffer
+ d_skipMediaHeader
);
109 d_ip6
=reinterpret_cast<struct ip6_hdr
*>(d_buffer
+ d_skipMediaHeader
);
110 uint16_t contentCode
=0;
112 if(d_pfh
.linktype
==1) {
113 if (d_pheader
.caplen
< sizeof(*d_ether
)) {
117 d_ether
=reinterpret_cast<struct ether_header
*>(d_buffer
);
118 contentCode
=ntohs(d_ether
->ether_type
);
120 else if(d_pfh
.linktype
== 12) { // LOOP
121 if (d_pheader
.caplen
< (d_skipMediaHeader
+ sizeof(*d_ip
))) {
126 contentCode
= 0x0800;
128 contentCode
= 0x86dd;
130 else if(d_pfh
.linktype
==101) {
131 if (d_pheader
.caplen
< (d_skipMediaHeader
+ sizeof(*d_ip
))) {
136 contentCode
= 0x0800;
138 contentCode
= 0x86dd;
140 else if(d_pfh
.linktype
==113) {
141 if (d_pheader
.caplen
< sizeof(*d_lcc
)) {
145 d_lcc
=reinterpret_cast<struct pdns_lcc_header
*>(d_buffer
);
146 contentCode
=ntohs(d_lcc
->lcc_protocol
);
149 if(contentCode
==0x0800 && (d_pheader
.caplen
>= (d_skipMediaHeader
+ sizeof(*d_ip
))) && d_ip
->ip_p
==17) { // udp
150 if (d_pheader
.caplen
< (d_skipMediaHeader
+ (4 * d_ip
->ip_hl
) + sizeof(*d_udp
))) {
154 d_udp
=reinterpret_cast<const struct udphdr
*>(d_buffer
+ d_skipMediaHeader
+ 4 * d_ip
->ip_hl
);
155 d_payload
= (unsigned char*)d_udp
+ sizeof(struct udphdr
);
156 d_len
= ntohs(d_udp
->uh_ulen
) - sizeof(struct udphdr
);
157 if (d_pheader
.caplen
< (d_skipMediaHeader
+ (4 * d_ip
->ip_hl
) + sizeof(*d_udp
) + d_len
)) {
161 if((const char*)d_payload
+ d_len
> d_buffer
+ d_pheader
.caplen
) {
168 else if(contentCode
==0x86dd && (d_pheader
.caplen
>= (d_skipMediaHeader
+ sizeof(*d_ip6
))) && d_ip6
->ip6_ctlun
.ip6_un1
.ip6_un1_nxt
==17) { // udpv6, we ignore anything with extension hdr
169 if (d_pheader
.caplen
< (d_skipMediaHeader
+ sizeof(struct ip6_hdr
) + sizeof(struct udphdr
))) {
173 d_udp
=reinterpret_cast<const struct udphdr
*>(d_buffer
+ d_skipMediaHeader
+ sizeof(struct ip6_hdr
));
174 d_payload
= (unsigned char*)d_udp
+ sizeof(struct udphdr
);
175 d_len
= ntohs(d_udp
->uh_ulen
) - sizeof(struct udphdr
);
176 if (d_pheader
.caplen
< (d_skipMediaHeader
+ sizeof(struct ip6_hdr
) + sizeof(struct udphdr
) + d_len
)) {
180 if((const char*)d_payload
+ d_len
> d_buffer
+ d_pheader
.caplen
) {
193 catch(const EofException
&) {
197 ComboAddress
PcapPacketReader::getSource() const
200 if(d_ip
->ip_v
== 4) {
201 ret
.sin4
.sin_family
= AF_INET
;
202 ret
.sin4
.sin_addr
= d_ip
->ip_src
;
203 ret
.sin4
.sin_port
= d_udp
->uh_sport
; // should deal with TCP too!
205 ret
.sin6
.sin6_family
= AF_INET6
;
206 ret
.sin6
.sin6_addr
= d_ip6
->ip6_src
;
207 ret
.sin6
.sin6_port
= d_udp
->uh_sport
; // should deal with TCP too!
212 ComboAddress
PcapPacketReader::getDest() const
215 if(d_ip
->ip_v
== 4) {
216 ret
.sin4
.sin_family
= AF_INET
;
217 ret
.sin4
.sin_addr
= d_ip
->ip_dst
;
218 ret
.sin4
.sin_port
= d_udp
->uh_dport
; // should deal with TCP too!
220 ret
.sin6
.sin6_family
= AF_INET6
;
221 ret
.sin6
.sin6_addr
= d_ip6
->ip6_dst
;
222 ret
.sin6
.sin6_port
= d_udp
->uh_dport
; // should deal with TCP too!
227 PcapPacketWriter::PcapPacketWriter(const string
& fname
, const PcapPacketReader
& ppr
) : PcapPacketWriter(fname
)
232 PcapPacketWriter::PcapPacketWriter(const string
& fname
) : d_fname(fname
)
234 d_fp
=fopen(fname
.c_str(),"w");
236 unixDie("Unable to open file");
238 int flags
=fcntl(fileno(d_fp
),F_GETFL
,0);
239 fcntl(fileno(d_fp
), F_SETFL
,flags
&(~O_NONBLOCK
)); // bsd needs this in stdin (??)
242 void PcapPacketWriter::write()
249 fwrite(&d_ppr
->d_pfh
, 1, sizeof(d_ppr
->d_pfh
), d_fp
);
252 fwrite(&d_ppr
->d_pheader
, 1, sizeof(d_ppr
->d_pheader
), d_fp
);
253 fwrite(d_ppr
->d_buffer
, 1, d_ppr
->d_pheader
.caplen
, d_fp
);
256 PcapPacketWriter::~PcapPacketWriter()