#include <iostream>
#include <string>
#include "data_structures/basic_types.h"
#include "data_structures/PacketFilter.h"
#include "data_structures/Aggregate.h"
#include "protocols/parsers/QcapAdaptor.h"
#include "data_structures/Packet.h"
#include "protocols/parsers/IPv4Demux.h"
#include "protocols/parsers/StreamedTCPParser.h"
#include "protocols/parsers/StreamedUDPParser.h"
#include "attributes/ByteCountAttribute.h"
#include "attributes/HistogramAttribute.h"
#include "protocols/datatypes/IPv4Filters.h"
#include "protocols/datatypes/TCPFilters.h"
#include <sys/times.h>
using namespace std;
int usage( void ) {
cerr << "Usage: test_harness <pcap>" << endl;
return 0;
}
int main( int argc, char **argv ) {
int printout_packets = 0;
int printout_conversations = 0;
int printout_histograms = 1;
int profile = 1;
struct tms checkpoint;
struct tms tms;
if( ( argc < 2 ) || ( argc > 2 ) ) {
usage();
exit(1);
}
if( profile ) {
times(&checkpoint);
cerr << "Profiling started" << endl;
}
PacketAttribute timestampAttrib( "frame.time" );
PacketAttribute capLenAttrib( "frame.cap_len" );
PacketAttribute pktLenAttrib( "frame.pkt_len" );
PacketAttribute ipSrcAttrib( "ip.src" );
PacketAttribute ipDstAttrib( "ip.dst" );
PacketAttribute ipProtoAttrib( "ip.proto" );
PacketAttribute tcpSrcAttrib( "tcp.srcport" );
PacketAttribute tcpDstAttrib( "tcp.dstport" );
const PacketFilter *const tcpFilter = IPv4Filters::IPV4_PROTO_TCP;
const PacketFilter *const udpFilter = IPv4Filters::IPV4_PROTO_UDP;
PacketFilter *icmpFilter = NULL;
icmpFilter = new SimplePacketFilter(
PacketAttribute( "ip.proto" ),
ConcretePacketAttributeValue<int>(1),
SimplePacketFilter::EQUAL );
PacketFilter *ozyFilter = new CompoundPacketFilter(
SimplePacketFilter(
PacketAttribute( "ip.src" ),
ConcretePacketAttributeValue<string>( "192.168.1.2" ),
SimplePacketFilter::EQUAL ),
SimplePacketFilter(
PacketAttribute( "ip.dst" ),
ConcretePacketAttributeValue<string>( "192.168.1.2" ),
SimplePacketFilter::EQUAL ),
CompoundPacketFilter::OR );
PacketFilter *ozyTcpFilter = NULL;
ozyTcpFilter = new CompoundPacketFilter(
*tcpFilter,
*ozyFilter,
CompoundPacketFilter::AND );
PacketFilter *shakespeareFilter = new CompoundPacketFilter(
SimplePacketFilter(
PacketAttribute( "ip.src" ),
ConcretePacketAttributeValue<string>( "134.117.225.11" ),
SimplePacketFilter::EQUAL ),
SimplePacketFilter(
PacketAttribute( "ip.dst" ),
ConcretePacketAttributeValue<string>( "134.117.225.11" ),
SimplePacketFilter::EQUAL ),
CompoundPacketFilter::OR );
PacketFilter *shakespeareUdpFilter = NULL;
shakespeareUdpFilter = new CompoundPacketFilter(
*shakespeareFilter,
*udpFilter,
CompoundPacketFilter::AND );
const PacketFilter *const sshFilter = TCPFilters::TCP_PORT_22_SSH;
const PacketFilter *const sshStreamFilter = TCPFilters::TCP_PORT_22_SSH_STREAM;
const PacketFilter *const wwwFilter = TCPFilters::TCP_PORT_80_WWW;
const PacketFilter *const wwwStreamFilter = TCPFilters::TCP_PORT_80_WWW_STREAM;
const PacketFilter *const imapsFilter = TCPFilters::TCP_PORT_993_IMAPS;
const PacketFilter *const imapsStreamFilter = TCPFilters::TCP_PORT_993_IMAPS_STREAM;
if( profile ) {
times(&tms);
cerr << "Built filters : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
string filename( argv[1] );
Trace ethTrace;
Trace ipFragTrace;
Trace ipTrace;
Decomposition ipDemuxed;
Decomposition tcpSessions;
Decomposition udpSessions;
ByteCountAttribute bytecount;
ByteCountAttribute bytecountPayload(false);
int lengthBounds[23] = {
0, 1, 2, 4, 5,
9, 19, 39, 49, 99,
179, 235, 268, 349, 449,
515, 548, 649, 999, 1379,
1380, 1431, 1472
};
Timeval delayBounds[8] = {
Timeval( 0.000001 ), Timeval( 0.0001 ), Timeval( 0.001 ), Timeval( 0.01 ), Timeval( 0.1 ),
Timeval( 1.0 ), Timeval( 10.0 ), Timeval( 64.0 )
};
Trace *ipTemplate = new Trace();
ipTemplate->addAttrib( "bytecount", bytecount );
IPv4Demux ipDemuxer( ipDemuxed, ipTemplate );
ipTrace.addListener( ipDemuxer );
Trace *tcpTemplate = new Trace();
tcpTemplate->addAttrib( "bytecount", bytecount );
tcpTemplate->addAttrib( "bytecount_payload", bytecountPayload );
tcpTemplate->addAttrib( "length_hist", HistogramAttribute<int>( PacketAttribute( "tcp.len" ), lengthBounds, 23 ) );
tcpTemplate->addAttrib( "delay_hist", HistogramAttribute<Timeval>( PacketAttribute( "frame.time_delta" ), delayBounds, 8 ) );
tcpSessions.addAttrib( "ssh_pkt_count", PacketCountAttribute( *sshFilter ) );
tcpSessions.addAttrib( "ssh_length_hist", HistogramAttribute<int>( *sshFilter, PacketAttribute( "tcp.len" ), lengthBounds, 23 ) );
tcpSessions.addAttrib( "ssh_delay_hist", HistogramAttribute<Timeval>( *sshFilter, PacketAttribute( "frame.time_delta" ), delayBounds, 8 ) );
tcpSessions.addAttrib( "www_pkt_count", PacketCountAttribute( *wwwFilter ) );
tcpSessions.addAttrib( "www_length_hist", HistogramAttribute<int>( *wwwFilter, PacketAttribute( "tcp.len" ), lengthBounds, 23 ) );
tcpSessions.addAttrib( "www_delay_hist", HistogramAttribute<Timeval>( *wwwFilter, PacketAttribute( "frame.time_delta" ), delayBounds, 8 ) );
tcpSessions.addAttrib( "imaps_pkt_count", PacketCountAttribute( *imapsFilter ) );
tcpSessions.addAttrib( "imaps_length_hist", HistogramAttribute<int>( *imapsFilter, PacketAttribute( "tcp.len" ), lengthBounds, 23 ) );
tcpSessions.addAttrib( "imaps_delay_hist", HistogramAttribute<Timeval>( *imapsFilter, PacketAttribute( "frame.time_delta" ), delayBounds, 8 ) );
StreamedTCPParser tcpParser( tcpSessions, tcpTemplate );
ipDemuxed.addListener( tcpParser );
Trace *udpTemplate = new Trace();
udpTemplate->addAttrib( "bytecount", bytecount );
StreamedUDPParser udpParser( udpSessions, udpTemplate );
ipDemuxed.addListener( udpParser );
if( profile ) {
times(&tms);
cerr << "Initialized aggregates : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
QcapAdaptor qcap(filename);
qcap.getIPTrace( ethTrace, ipFragTrace, ipTrace );
if( profile ) {
times(&tms);
cerr << "Built IPv4 trace : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
TraceIterator it = ethTrace.begin();
TraceIterator end = ethTrace.end();
if( printout_packets ) {
int count = 0;
while( it != end ) {
try {
cout << (*it).getAttrib(timestampAttrib) << ", ";
cout << (*it).getAttrib(capLenAttrib) << "/" ;
cout << (*it).getAttrib(pktLenAttrib) << " bytes";
} catch( runtime_error err ) {
cerr << "Error outputting packet attributes" << endl;
}
try {
cout << " : proto " << (*it).getAttrib(ipProtoAttrib) << ", ";
cout << (*it).getAttrib(ipSrcAttrib) << " -> " ;
cout << (*it).getAttrib(ipDstAttrib);
} catch( UnknownAttributeException unkAtt ) {
}
if( tcpFilter->match(it) ) {
cout << " TCP";
}
if( udpFilter->match(it) ) {
cout << " UDP";
}
if( icmpFilter->match(it) ) {
cout << " ICMP";
}
if( shakespeareUdpFilter->match(it) ) {
cout << " SHAKESPEARE_UDP";
}
if( ozyTcpFilter->match(it) ) {
cout << " OZYMANDIAS_TCP";
}
cout << endl;
count++;
++it;
}
cout << count << " packets." << endl;
}
cout << ethTrace.getAttrib("count") << " packets in trace." << endl;
if( profile ) {
times(&tms);
cerr << "Iterated through trace : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
if( printout_conversations ) {
map<StreamKeyWrapper, Aggregate*>::const_iterator decompIt = ipDemuxed.substreamsBegin();
cout << "== IPv4 conversations ==" << endl;
while( decompIt != ipDemuxed.substreamsEnd() ) {
Trace *ipv4Stream = dynamic_cast<Trace*>(decompIt->second);
cout << "** " << ipv4Stream->getStreamKey().toString()
<< ", " << ipv4Stream->getAttrib("count") << " packets"
<< ", " << ipv4Stream->getAttrib("bytecount") << " bytes"
<< endl;
++decompIt;
}
if( profile ) {
times(&tms);
cerr << "Iterated through IPv4 streams : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
}
if( printout_conversations ) {
map<StreamKeyWrapper, Aggregate*>::const_iterator tcpIt = tcpSessions.substreamsBegin();
cout << "== TCP conversations ==" << endl;
while( tcpIt != tcpSessions.substreamsEnd() ) {
Trace *tcpStream = dynamic_cast<Trace*>(tcpIt->second);
cout << "*** " << tcpStream->getStreamKey().toString()
<< ", " << tcpStream->getAttrib("count") << " packets"
<< ", " << tcpStream->getAttrib("bytecount") << " bytes"
<< ", " << tcpStream->getAttrib("bytecount_payload") << " bytes payload"
<< endl;
++tcpIt;
}
cout << "TCP packets: " << tcpSessions.getAttrib("count") << endl;
if( profile ) {
times(&tms);
cerr << "Iterated through TCP sessions : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
}
if( printout_conversations ) {
map<StreamKeyWrapper, Aggregate*>::const_iterator udpIt = udpSessions.substreamsBegin();
cout << "== UDP conversations ==" << endl;
while( udpIt != udpSessions.substreamsEnd() ) {
Trace *udpStream = dynamic_cast<Trace*>(udpIt->second);
cout << "*** " << udpStream->getStreamKey().toString()
<< ", " << udpStream->getAttrib("count") << " packets"
<< ", " << udpStream->getAttrib("bytecount") << " bytes"
<< endl;
++udpIt;
}
cout << "UDP packets: " << udpSessions.getAttrib("count") << endl;
if( profile ) {
times(&tms);
cerr << "Iterated through UDP sessions : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
}
if( printout_histograms ) {
Decomposition::const_iterator tcpIt = tcpSessions.substreamsBegin();
cout << "== SSH conversations ==" << endl;
cout << tcpSessions.getAttrib("ssh_pkt_count") << " SSH packets" << endl;
while( tcpIt != tcpSessions.substreamsEnd() ) {
Trace *tcpStream = dynamic_cast<Trace*>(tcpIt->second);
if( sshStreamFilter->match( tcpStream->getStreamKey() ) ) {
cout << "*** " << tcpStream->getStreamKey().toString()
<< ", " << tcpStream->getAttrib("count") << " packets"
<< ", " << tcpStream->getAttrib("bytecount") << " bytes"
<< ", " << tcpStream->getAttrib("bytecount_payload") << " bytes payload"
<< endl;
cout << "Length histogram: " << tcpStream->getAttrib("length_hist") << endl;
cout << "Delay histogram: " << tcpStream->getAttrib("delay_hist") << endl;
}
++tcpIt;
}
cout << tcpSessions.getAttrib("ssh_pkt_count") << " SSH packets" << endl;
cout << "-- SSH TCP payload length histogram --" << endl;
cout << tcpSessions.getAttrib("ssh_length_hist") << endl;
}
if( printout_histograms ) {
Decomposition::const_iterator tcpIt = tcpSessions.substreamsBegin();
cout << "== WWW conversations ==" << endl;
cout << tcpSessions.getAttrib("www_pkt_count") << " WWW packets" << endl;
while( tcpIt != tcpSessions.substreamsEnd() ) {
Trace *tcpStream = dynamic_cast<Trace*>(tcpIt->second);
if( wwwStreamFilter->match( tcpStream->getStreamKey() ) ) {
cout << "*** " << tcpStream->getStreamKey().toString()
<< ", " << tcpStream->getAttrib("count") << " packets"
<< ", " << tcpStream->getAttrib("bytecount") << " bytes"
<< ", " << tcpStream->getAttrib("bytecount_payload") << " bytes payload"
<< endl;
cout << "Length histogram: " << tcpStream->getAttrib("length_hist") << endl;
cout << "Delay histogram: " << tcpStream->getAttrib("delay_hist") << endl;
}
++tcpIt;
}
cout << "-- WWW TCP payload length histogram --" << endl;
cout << tcpSessions.getAttrib("www_length_hist") << endl;
if( profile ) {
times(&tms);
cerr << "Iterated through WWW sessions : "
<< ( tms.tms_utime - checkpoint.tms_utime ) << " user, "
<< ( tms.tms_stime - checkpoint.tms_stime ) << " sys" << endl;
checkpoint = tms;
}
}
if( printout_histograms ) {
Decomposition::const_iterator tcpIt = tcpSessions.substreamsBegin();
cout << "== IMAPS conversations ==" << endl;
cout << tcpSessions.getAttrib("imaps_pkt_count") << " IMAPS packets" << endl;
while( tcpIt != tcpSessions.substreamsEnd() ) {
Trace *tcpStream = dynamic_cast<Trace*>(tcpIt->second);
if( imapsStreamFilter->match( tcpStream->getStreamKey() ) ) {
cout << "*** " << tcpStream->getStreamKey().toString()
<< ", " << tcpStream->getAttrib("count") << " packets"
<< ", " << tcpStream->getAttrib("bytecount") << " bytes"
<< ", " << tcpStream->getAttrib("bytecount_payload") << " bytes payload"
<< endl;
cout << "Length histogram: " << tcpStream->getAttrib("length_hist") << endl;
cout << "Delay histogram: " << tcpStream->getAttrib("delay_hist") << endl;
}
++tcpIt;
}
cout << tcpSessions.getAttrib("imaps_pkt_count") << " IMAPS packets" << endl;
cout << "-- IMAPS TCP payload length histogram --" << endl;
cout << tcpSessions.getAttrib("imaps_length_hist") << endl;
}
delete ozyTcpFilter;
delete ozyFilter;
delete shakespeareUdpFilter;
delete shakespeareFilter;
delete icmpFilter;
exit(0);
}