From 9a2428f9e8a5a585d738faaa942dc7ed695b348f Mon Sep 17 00:00:00 2001 From: Christian Herdtweck Date: Wed, 4 Mar 2015 17:29:07 +0100 Subject: [PATCH] got the tool feed_packet_data to compile and run and do reasonable stuff --- src/tools/feed_packet_data.cpp | 283 +++++++++++++++++++++++++++++----------- 1 files changed, 204 insertions(+), 79 deletions(-) diff --git a/src/tools/feed_packet_data.cpp b/src/tools/feed_packet_data.cpp index e8d4d1d..9c2d2aa 100644 --- a/src/tools/feed_packet_data.cpp +++ b/src/tools/feed_packet_data.cpp @@ -18,8 +18,12 @@ This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License. */ +#include +#include #include +#include #include +#include #include "icmp/icmppacketfactory.h" #include "tcp/tcpsegmentfactory.h" @@ -27,23 +31,48 @@ on this file might be covered by the GNU General Public License. using I2n::Logger::GlobalLogger; namespace po = boost::program_options; -//const uint32_t pcap_magic_number = 0xa1b2c3d4; -const char pcap_magic_bytes[] = {0xa1, 0xb2, 0xc3, 0xd4}; + +//------------------------------------------------------------------------------ +// constants const bool default_is_icmp = true; const bool default_is_v4 = true; +//const uint32_t pcap_magic_number = 0xa1b2c3d4; +typedef unsigned char byte; +const byte pcap_magic_bytes[] = {0xa1, 0xb2, 0xc3, 0xd4}; + +// pcap file header is 5 x uint32 + 2 x uint16 --> 24 bytes +const std::streamsize pcap_file_header_size = 24; + +// pcap file header is 4 x uint32 --> 16 bytes +const std::streamsize pcap_packet_header_size = 16; + + +//------------------------------------------------------------------------------ +// function declarations +void init_logger(); +void increase_verbosity(); +bool check_for_pcap_header(std::istream &input_stream); +void consume_pcap_file_header(std::istream &input_stream); +void consume_pcap_packet_header(std::istream &input_stream); +int read_packets(std::istream &input_stream, const bool, const bool, const int); + +//------------------------------------------------------------------------------ +// helper functions + void init_logger() { - // set default: log at level NOTICE to syslog and stderr - // to ensure that in case of faulty config, the error is noticed - I2n::Logger::enable_syslog( I2n::Logger::Facility::User ); + // set default: log at level NOTICE to stderr I2n::Logger::enable_stderr_log( true ); - I2n::Logger::set_log_level( I2n::Logger::LogLevel::Notice ); + //I2n::Logger::set_log_level( I2n::Logger::LogLevel::Notice ); + I2n::Logger::set_log_level( I2n::Logger::LogLevel::Debug ); + GlobalLogger.info() << "Logger initiated"; } void increase_verbosity() { I2n::Logger::set_log_level( I2n::Logger::LogLevel::Info ); + GlobalLogger.info() << "Increased verbosity"; } // determine whether is raw data or pcap by peeking at first 4 bytes @@ -53,118 +82,214 @@ bool check_for_pcap_header(std::istream &input_stream) bool is_pcap = true; for (peek_idx=0; peek_idx<4; ++peek_idx) { - if (file_reader.get() != pcap_magic_bytes[peek_idx]) + int val = input_stream.get(); + GlobalLogger.debug() << "Peeked value " << std::hex << val; + if (val != pcap_magic_bytes[3-peek_idx]) { is_pcap = false; break; } } for (int back_idx=peek_idx; back_idx > 0; --back_idx) - file_reader.unget(); + input_stream.unget(); if (is_pcap) GlobalLogger.info() << "File is pcap"; else GlobalLogger.info() << "File is not pcap"; return is_pcap; -} +} + +void consume_pcap_file_header(std::istream &input_stream) +{ + GlobalLogger.debug() << "Consuming pcap file header"; + char *buf = new char[pcap_file_header_size]; + input_stream.read(buf, pcap_file_header_size); + // could do some checking whether this data actually looks like a + // pcap header --> see ../icmp/icmppacketfactory.cpp + delete[] buf; +} + +void consume_pcap_packet_header(std::istream &input_stream) +{ + GlobalLogger.debug() << "Consuming pcap packet header"; + char *buf = new char[pcap_packet_header_size]; + input_stream.read(buf, pcap_packet_header_size); + // could do some checking whether this data actually looks like a + // pcap header --> see ../icmp/icmppacketfactory.cpp + delete[] buf; +} + + +int read_packets( std::istream &input_stream, const bool is_icmp, + const bool is_v4, + const int dump_mode ) +{ + // peek at start of stream to see if there is a pcap header + bool is_pcap = check_for_pcap_header(input_stream); + int next_val; + if (is_pcap) + consume_pcap_file_header(input_stream); + if ( !input_stream ) + { + GlobalLogger.notice() << "Failure consuming pcap file header!"; + return 2; + } + + // read from stream until it is empty + while (true) + { + if (is_pcap) + { + // assume that there is a packet header if stream had pcap header + consume_pcap_packet_header(input_stream); + if ( !input_stream ) + { + GlobalLogger.notice() <<"Failure consuming pcap packet header!"; + return 3; + } + } + // feed data to right factory + if (is_icmp) + { + IcmpPacketItem packet; + if (is_v4) + { + GlobalLogger.info() << "Trying to read ICMP v4 packet" + << std::endl; + packet = IcmpPacketFactory::create_icmp_packet( + boost::asio::ip::icmp::v4(), input_stream, dump_mode); + } + else // v6 + { + GlobalLogger.info() << "Trying to read ICMP v6 packet" + << std::endl; + packet = IcmpPacketFactory::create_icmp_packet( + boost::asio::ip::icmp::v6(), input_stream, dump_mode); + } + + if (packet) + GlobalLogger.notice() << "Succesfully created ICMP packet"; + else + { + GlobalLogger.notice() << "ICMP packet creation failed"; + return 4; + } + } + else // is tcp + { + TcpSegmentItem segment; + if (is_v4) + { + GlobalLogger.info() << "Trying to read TCP v4 packet" + << std::endl; + segment = TcpSegmentFactory::create_tcp_segment( + boost::asio::ip::tcp_raw_protocol::v4(), + input_stream); + } + else // v6 + { + GlobalLogger.info() << "Trying to read TCP v6 packet" + << std::endl; + segment = TcpSegmentFactory::create_tcp_segment( + boost::asio::ip::tcp_raw_protocol::v6(), + input_stream); + } + + if (segment) + GlobalLogger.notice() << "Succesfully created TCP segment"; + else + { + GlobalLogger.notice() << "TCP segment creation failed"; + return 4; + } + } + + if ( !input_stream ) + { + GlobalLogger.notice() << "Stream not good after reading!"; + return 5; + } + + // peek 1 byte to check whether we are at the end of stream + next_val = input_stream.get(); + if ( input_stream.eof() ) + { + GlobalLogger.info() << "Reached end of stream"; + break; + } + input_stream.unget(); + } //eo: while (input_stream) + + return 0; +} // eo: function read_packets + +//------------------------------------------------------------------------------ +/** @brief main function + * + * @returns 0 if all input resulted in good packets or the error number of the + * last failed packet + */ int main(int argc, char *argv[]) { // init logging init_logger(); - GlobalLogger.debug() << "logger initiated with default config"; bool is_icmp = default_is_icmp; bool is_v4 = default_is_v4; - std::istream input_stream; - bool is_pcap; - bool have_stream = false; - - IcmpPacketItem packet; - TcpSegmentItem segment; + int temp_val, return_val = 0; + int dump_mode = 0; // never dump - // convert arguments - std::vector args(argv, argv + argc); + if (argc == 1) + { + GlobalLogger.notice() << "No arguments! Start with mix of file names " + << "and flags"; + GlobalLogger.notice() << "Valid flags: -i[cmp], -t[cp], -[v]4 -[v]6; " + << "-- to read from stdin instead of file"; + return 1; + } - // loop over arguments + // convert arguments to vector of strings and loop over them + std::vector args(argv+1, argv + argc); BOOST_FOREACH (const std::string &arg, args) { + GlobalLogger.debug() << "Parsing next arg: " << arg; + // check if is some specification of data format if (arg == "-i" || arg == "-icmp" || arg == "i" || arg == "icmp") is_icmp = true; else if (arg == "-t" || arg == "-tcp" || arg == "t" || arg == "tcp") is_icmp = false; else if (arg == "-4" || arg == "-v4" || arg == "4" || arg == "v4") - is_v4 = false; + is_v4 = true; else if (arg == "-6" || arg == "-v6" || arg == "6" || arg == "v6") - is_v6 = false; + is_v4 = false; + else if (arg == "-v") + increase_verbosity(); else if (arg == "--") // read input from stdin { - if (have_stream) - input_stream.close(); GlobalLogger.info() << "Trying to read from stdin" << std::endl; - input_stream = std::cin; + temp_val = read_packets( std::cin, is_icmp, is_v4, dump_mode ); } else // assume is file name { - if (have_stream) - input_stream.close(); - GlobalLogger.info() << "Trying to read from " << file_name + GlobalLogger.info() << "Trying to read from " << arg << std::endl; - input_stream = file_reader(file_name, ios::in | ios::binary); + std::ifstream file_stream(arg.c_str(), std::ios::in | + std::ios::binary); + temp_val = read_packets( file_stream, is_icmp, is_v4, dump_mode); + file_stream.close(); } - // no stream yet --> check next arg - if (!have_stream) - continue; - - // read from stream until it is empty - while (input_stream) - { - is_pcap = check_for_pcap_header(input_stream); - // TODO consume that header: file header and/or packet header - // (maybe assume for now that there is only one data set per file) + if (temp_val != 0) + { + GlobalLogger.debug() << "Remember error value " << temp_val; + return_val = temp_val; + } + } //eo: loop over input-files - // feed data to right factory - if (is_icmp) - { - if (is_v4) - { - GlobalLogger.info() << "Creating ICMP v4 packet" - << std::endl; - packet = IcmpPacketFactory.create_icmp_packet( - boost::asio::ip::icmp::v4, input_stream); - } - else // v6 - { - GlobalLogger.info() << "Creating ICMP v6 packet" - << std::endl; - packet = IcmpPacketFactory.create_icmp_packet( - boost::asio::ip::icmp::v6, input_stream); - } - } - else // is tcp - { - if (is_v4) - { - GlobalLogger.info() << "Creating TCP v4 packet" - << std::endl; - segment = TcpSegmentFactory::create_tcp_segment( - boost::asio::ip::tcp_raw_protocol::v4, - input_stream); - } - else // v6 - { - GlobalLogger.info() << "Creating TCP v6 packet" - << std::endl; - segment = TcpSegmentFactory::create_tcp_segment( - boost::asio::ip::tcp_raw_protocol::v6, - input_stream); - } - } - } //eo: while (input_stream) + GlobalLogger.debug() << "End program with return value " << return_val; + return return_val; - input_stream.close(); - have_stream = false; - } //eo: loop over input-files } // eo: function main + -- 1.7.1