dumping now into a .pcap file with nicer filename, so can analyze with wireshark
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 25 Feb 2015 14:34:16 +0000 (15:34 +0100)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Wed, 25 Feb 2015 14:34:16 +0000 (15:34 +0100)
src/icmp/icmppacketfactory.cpp

index 9ebd2cf..fe422bb 100644 (file)
@@ -20,7 +20,9 @@
 
 #include "icmp/icmppacketfactory.h"
 
+// for dumping packets
 #include <stdlib.h>
+#include <ctime>
 #include <iostream>
 #include <sstream>
 
@@ -40,6 +42,84 @@ using boost::asio::ip::icmp;
 using I2n::Logger::GlobalLogger;
 
 //-----------------------------------------------------------------------------
+// Dump of data packets to pcap files
+//-----------------------------------------------------------------------------
+#pragma pack(push, 1) // exact fit -- no padding of data in structs
+
+// pcap header for dumping of packet data
+// (http://wiki.wireshark.org/Development/LibpcapFileFormat)
+typedef struct pcap_hdr_s {
+        uint32_t magic_number;   /* magic number */
+        uint16_t version_major;  /* major version number */
+        uint16_t version_minor;  /* minor version number */
+        int32_t  thiszone;       /* GMT to local correction */
+        uint32_t sigfigs;        /* accuracy of timestamps */
+        uint32_t snaplen;        /* max length of captured packets, in octets */
+        uint32_t network;        /* data link type */
+} pcap_hdr_t;
+
+typedef struct pcaprec_hdr_s {
+        uint32_t ts_sec;         /* timestamp seconds */
+        uint32_t ts_usec;        /* timestamp microseconds */
+        uint32_t incl_len;       /* number of octets of packet saved in file */
+        uint32_t orig_len;       /* actual length of packet */
+} pcaprec_hdr_t;
+
+
+void dump_packet(const std::string &data)
+{
+    std::size_t data_size = data.size();
+
+    // create unique file name
+    std::stringstream temp_name;
+    temp_name << "/datastore/pingcheck.broken/icmp_";
+    time_t capture_time = time(0);
+    temp_name << capture_time;
+    temp_name << "_XXXXXX.pcap";
+    std::string temp_str = temp_name.str();
+    char *secure_filename = strdup(temp_str.c_str());
+    int fd = mkstemps(secure_filename, 5);   // 5 = ".pcap".length
+    if (fd == -1)
+    {
+        GlobalLogger.warning() << "Failed to create temp file!" << endl;
+        return;
+    }
+
+    // create a pcap header
+    pcap_hdr_t pcap_hdr;
+    pcap_hdr.magic_number = 0xa1b2c3d4;
+    pcap_hdr.version_major = 2;
+    pcap_hdr.version_minor = 4;
+    pcap_hdr.thiszone = 0;
+    pcap_hdr.sigfigs = 0;
+    pcap_hdr.snaplen = 40;
+    pcap_hdr.network = 101;   // LINKTYPE_RAW, according to
+                              // http://www.tcpdump.org/linktypes.html
+
+    // create a record (packet) header
+    pcaprec_hdr_t pcaprec_hdr;
+    pcaprec_hdr.ts_sec = static_cast<uint32_t>(capture_time);
+    pcaprec_hdr.ts_usec = 0;    // do not care about that precision
+    pcaprec_hdr.incl_len = data_size;
+    pcaprec_hdr.orig_len = data_size;
+
+    // create file pointer for file descriptor
+    FILE *fp = fdopen(fd, "w");
+
+    // write data
+    fwrite(&pcap_hdr, sizeof(pcap_hdr_t), 1, fp);
+    fwrite(&pcaprec_hdr, sizeof(pcaprec_hdr_t), 1, fp);
+    fwrite(data.c_str(), sizeof(char), data_size, fp);
+
+    // done -- clean up
+    fclose(fp);
+    close(fd);
+    GlobalLogger.debug() << "Dumped a copy of the data into "
+                         << secure_filename << endl;
+}
+#pragma pack(pop) // restore old value
+
+//-----------------------------------------------------------------------------
 // IcmpPacketFactory
 //-----------------------------------------------------------------------------
 
@@ -80,7 +160,6 @@ IcmpPacketItem IcmpPacketFactory::create_icmp_packet(
 
     // create buffer for saving data in it
     stringbuf data_backup;
-    size_t data_size;
 
     // read packet from stream, possibly copying data first
     if (dump_broken_packets)
@@ -88,9 +167,9 @@ IcmpPacketItem IcmpPacketFactory::create_icmp_packet(
         // read all data into backup
         ostream backup_filler(&data_backup);
         backup_filler << is.rdbuf();
-        data_size = data_backup.str().size();
-        GlobalLogger.debug() << "Copied ICMP raw data (" << data_size
-             << " bytes) for dumping in case of broken packet" << endl;
+        //GlobalLogger.debug() << "Copied ICMP raw data ("
+        //     << data_backup.str().size();
+        //     << " bytes) for dumping in case of broken packet" << endl;
 
         // create a new stream from backup buffer
         //   and use that in read
@@ -114,22 +193,9 @@ IcmpPacketItem IcmpPacketFactory::create_icmp_packet(
         icmp_packet.reset();    // --> (!icmp_packet) is true
     }
 
+    // dump data if had trouble with packet
     if (dump_broken_packets && !icmp_packet)
-    {
-        char secure_filename[] = "/datastore/pingcheck.broken/icmp_XXXXXX";
-        int fd = mkstemp(secure_filename);
-        if (fd == -1)
-            GlobalLogger.warning() << "Failed to create temp file!" << endl;
-        else
-        {
-            // write data
-            write(fd, data_backup.str().c_str(), data_size);
-            // to check od -t u1
-            close(fd);
-            GlobalLogger.debug() << "Dumped a copy of the data into "
-                                 << secure_filename << endl;
-        }
-    }
+        dump_packet(data_backup.str());
 
     return icmp_packet;
 }