| 1 | #define __FAVOR_BSD |
|---|
| 2 | #include "dnspcap.hh" |
|---|
| 3 | #include <boost/format.hpp> |
|---|
| 4 | #include <fcntl.h> |
|---|
| 5 | |
|---|
| 6 | using namespace boost; |
|---|
| 7 | PcapPacketReader::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 | |
|---|
| 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 (??) |
|---|
| 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 | |
|---|
| 21 | if( d_pfh.linktype!=1) |
|---|
| 22 | throw runtime_error((format("Unsupported link type %d") % d_pfh.linktype).str()); |
|---|
| 23 | |
|---|
| 24 | d_runts = d_oversized = d_correctpackets = d_nonetheripudp = 0; |
|---|
| 25 | } |
|---|
| 26 | |
|---|
| 27 | PcapPacketReader::~PcapPacketReader() |
|---|
| 28 | { |
|---|
| 29 | fclose(d_fp); |
|---|
| 30 | } |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | void PcapPacketReader::checkedFreadSize(void* ptr, size_t size) |
|---|
| 34 | { |
|---|
| 35 | int ret=fread(ptr, 1, size, d_fp); |
|---|
| 36 | if(ret < 0) |
|---|
| 37 | unixDie( (format("Error reading %d bytes from %s") % size % d_fname).str()); |
|---|
| 38 | |
|---|
| 39 | if(!ret) |
|---|
| 40 | throw EofException(); |
|---|
| 41 | |
|---|
| 42 | if((size_t)ret != size) |
|---|
| 43 | throw EofException((format("Incomplete read from '%s', got only %d bytes") % d_fname % ret).str()); |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | bool PcapPacketReader::getUDPPacket() |
|---|
| 47 | try |
|---|
| 48 | { |
|---|
| 49 | for(;;) { |
|---|
| 50 | checkedFread(&d_pheader); |
|---|
| 51 | if(!d_pheader.caplen) |
|---|
| 52 | continue; |
|---|
| 53 | |
|---|
| 54 | if(d_pheader.caplen > sizeof(d_buffer)) { |
|---|
| 55 | d_oversized++; |
|---|
| 56 | throw runtime_error((format("Can't handle a %d byte packet, have space for %d") % d_pheader.caplen % sizeof(d_buffer)).str()); |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | checkedFreadSize(d_buffer, d_pheader.caplen); |
|---|
| 60 | |
|---|
| 61 | if(d_pheader.caplen!=d_pheader.len) { |
|---|
| 62 | d_runts++; |
|---|
| 63 | continue; |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | d_ether=reinterpret_cast<struct ether_header*>(d_buffer); |
|---|
| 67 | d_ip=reinterpret_cast<struct ip*>(d_buffer + sizeof(struct ether_header)); |
|---|
| 68 | |
|---|
| 69 | if(ntohs(d_ether->ether_type)==0x0800 && d_ip->ip_p==17) { // udp |
|---|
| 70 | d_udp=reinterpret_cast<const struct udphdr*>(d_buffer + sizeof(struct ether_header) + 4 * d_ip->ip_hl); |
|---|
| 71 | d_payload = (unsigned char*)d_udp + sizeof(struct udphdr); |
|---|
| 72 | d_len = ntohs(d_udp->uh_ulen) - sizeof(struct udphdr); |
|---|
| 73 | d_correctpackets++; |
|---|
| 74 | return true; |
|---|
| 75 | } |
|---|
| 76 | else { |
|---|
| 77 | d_nonetheripudp++; |
|---|
| 78 | } |
|---|
| 79 | } |
|---|
| 80 | } |
|---|
| 81 | catch(EofException) { |
|---|
| 82 | return false; |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | PcapPacketWriter::PcapPacketWriter(const string& fname, PcapPacketReader& ppr) : d_fname(fname), d_ppr(ppr) |
|---|
| 87 | { |
|---|
| 88 | d_fp=fopen(fname.c_str(),"w"); |
|---|
| 89 | if(!d_fp) |
|---|
| 90 | unixDie("Unable to open file"); |
|---|
| 91 | |
|---|
| 92 | fwrite(&ppr.d_pfh, 1, sizeof(ppr.d_pfh), d_fp); |
|---|
| 93 | |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | void PcapPacketWriter::write() |
|---|
| 97 | { |
|---|
| 98 | fwrite(&d_ppr.d_pheader, 1, sizeof(d_ppr.d_pheader), d_fp); |
|---|
| 99 | fwrite(d_ppr.d_buffer, 1, d_ppr.d_pheader.caplen, d_fp); |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | PcapPacketWriter::~PcapPacketWriter() |
|---|
| 103 | { |
|---|
| 104 | fclose(d_fp); |
|---|
| 105 | } |
|---|