got the tool feed_packet_data to compile and run and do reasonable stuff
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 4 Mar 2015 16:29:07 +0000 (17:29 +0100)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Fri, 13 Mar 2015 13:00:36 +0000 (14:00 +0100)
src/tools/feed_packet_data.cpp

index e8d4d1d..9c2d2aa 100644 (file)
@@ -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 <fstream>
+#include <ios>
 #include <logfunc.hpp>
+#include <boost/foreach.hpp>
 #include <boost/program_options.hpp>
+#include <boost/asio/ip/icmp.hpp>
 
 #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<std::string> 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<std::string> 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
+