Remove warnings
[anna.git] / example / diameter / pcapDecoder / main.cpp
index f3330b7..cdada35 100644 (file)
@@ -1,40 +1,11 @@
-// ANNA - Anna is Not Nothingness Anymore
-//
-// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
-//
-// http://redmine.teslayout.com/projects/anna-suite
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     *  Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Authors: eduardo.ramos.testillano@gmail.com
-//          cisco.tierra@gmail.com
-
-
-// Standard
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
 #include <pcap.h>
 #include <stdlib.h>
 #include <netinet/ip.h>
 #include <map>
 
 #include <anna/core/DataBlock.hpp>
-#include <anna/core/util/Tokenizer.hpp>
 #include <anna/core/functions.hpp>
 #include <anna/core/tracing/Logger.hpp>
 #include <anna/core/tracing/TraceWriter.hpp>
 #include <anna/core/RuntimeException.hpp>
-#include <anna/xml/xml.hpp>
-#include <anna/diameter/stack/Engine.hpp>
-#include <anna/diameter/codec/Engine.hpp>
-#include <anna/diameter/codec/Message.hpp>
-
-
 
 
 using namespace anna;
-using namespace anna::diameter;
-
 
 // Payload and frame metadata /////////////////////////////////////////////////////////////////////////////
 class Payload {
@@ -75,64 +37,89 @@ class Payload {
   size_t _diameterLength;
 
 public:
-  Payload() { reset(); }
+  Payload() {
+    reset();
+  }
 
   void setDiameterLength(size_t dl) {
-       if (_diameterLength == -1) {
-         _diameterLength=dl;
-          LOGDEBUG (Logger::debug(anna::functions::asString("Diameter message length: %d bytes", dl), ANNA_FILE_LOCATION));
-       }
+    if(_diameterLength == -1) {
+      _diameterLength = dl;
+      LOGDEBUG(
+        Logger::debug(anna::functions::asString("Diameter message length: %d bytes", dl), ANNA_FILE_LOCATION));
+    }
   }
 
-  void setSourceIP(const std::string &srcIP) throw() { _sourceIP = srcIP; }
-  void setDestinationIP(const std::string &dstIP) throw() { _destinationIP = dstIP; }
-  void setTimestamp(time_t ts) throw() { _timestamp = ts; }
-  void setTimestampU(int tsu) throw() { _timestampU = tsu; }
+  void setSourceIP(const std::string &srcIP) throw() {
+    _sourceIP = srcIP;
+  }
+  void setDestinationIP(const std::string &dstIP) throw() {
+    _destinationIP = dstIP;
+  }
+  void setTimestamp(time_t ts) throw() {
+    _timestamp = ts;
+  }
+  void setTimestampU(int tsu) throw() {
+    _timestampU = tsu;
+  }
   // Returns true if completed:
   bool appendData(const char *data, size_t size) throw(RuntimeException) {
-    LOGDEBUG (Logger::debug(anna::functions::asString("Appending %d bytes", size), ANNA_FILE_LOCATION));
+    LOGDEBUG(
+      Logger::debug(anna::functions::asString("Appending %d bytes", size), ANNA_FILE_LOCATION));
     _data.append(data, size);
-    if (_data.size() > _diameterLength) throw RuntimeException("Data overflow (unexpected offset exceed diameter message length)", ANNA_FILE_LOCATION);
-    if (_data.size() < _diameterLength) return false;
-    LOGDEBUG (anna::Logger::debug("Completed!", ANNA_FILE_LOCATION));
+
+    if(_data.size() > _diameterLength)
+      throw RuntimeException(
+        "Data overflow (unexpected offset exceed diameter message length)",
+        ANNA_FILE_LOCATION);
+
+    if(_data.size() < _diameterLength)
+      return false;
+
+    LOGDEBUG(anna::Logger::debug("Completed!", ANNA_FILE_LOCATION));
     return true;
   }
 
   void reset() throw() {
-         _sourceIP = "";
-         _destinationIP = "";
-         _timestamp = 0;
-         _timestampU = 0;
-         _data = "";
-         _diameterLength = -1; // not calculated yet
+    _sourceIP = "";
+    _destinationIP = "";
+    _timestamp = 0;
+    _timestampU = 0;
+    _data = "";
+    _diameterLength = -1; // not calculated yet
   }
 
-  const std::string &getSourceIP() const throw() { return _sourceIP; }
-  const std::string &getDestinationIP() const throw() { return _destinationIP; }
-  time_t getTimestamp() const throw() { return _timestamp; }
-  int getTimestampU() const throw() { return _timestampU; }
-  const std::string &getData() const throw() { return _data; }
-  std::string getDataAsHex() const throw() { return anna::functions::asHexString(anna::DataBlock(_data.c_str(), _data.size())); }
+  const std::string &getSourceIP() const throw() {
+    return _sourceIP;
+  }
+  const std::string &getDestinationIP() const throw() {
+    return _destinationIP;
+  }
+  time_t getTimestamp() const throw() {
+    return _timestamp;
+  }
+  int getTimestampU() const throw() {
+    return _timestampU;
+  }
+  const std::string &getData() const throw() {
+    return _data;
+  }
+  std::string getDataAsHex() const throw() {
+    return anna::functions::asHexString(
+             anna::DataBlock(_data.c_str(), _data.size()));
+  }
 };
 
-
-
 // Data maps //////////////////////////////////////////////////////////////////////////////////////////////
-typedef std::map <int /* frame */, Payload> payloads_t;
-typedef std::map <int /* frame */, Payload>::const_iterator payloads_it;
+typedef std::map < int /* frame */, Payload > payloads_t;
+typedef std::map < int /* frame */, Payload >::const_iterator payloads_it;
 payloads_t G_payloads;
-anna::diameter::codec::Message G_codecMsg;
-
-
-
-
 
 // Sniffing structures ////////////////////////////////////////////////////////////////////////////////////
 
 /* ethernet headers are always exactly 14 bytes */
 #define SIZE_ETHERNET 14
 /* Ethernet addresses are 6 bytes */
-#define ETHER_ADDR_LEN 6
+#define ETHER_ADDR_LEN  6
 
 /* Ethernet header */
 struct sniff_ethernet {
@@ -143,36 +130,36 @@ struct sniff_ethernet {
 
 /* IP header */
 struct sniff_ip {
-  u_char ip_vhl;               /* version << 4 | header length >> 2 */
-  u_char ip_tos;               /* type of service */
-  u_short ip_len;              /* total length */
-  u_short ip_id;               /* identification */
-  u_short ip_off;              /* fragment offset field */
-#define IP_RF 0x8000           /* reserved fragment flag */
-#define IP_DF 0x4000           /* dont fragment flag */
-#define IP_MF 0x2000           /* more fragments flag */
-#define IP_OFFMASK 0x1fff      /* mask for fragmenting bits */
-  u_char ip_ttl;               /* time to live */
-  u_char ip_p;         /* protocol */
-  u_short ip_sum;              /* checksum */
-  struct in_addr ip_src,ip_dst; /* source and dest address */
+  u_char ip_vhl; /* version << 4 | header length >> 2 */
+  u_char ip_tos; /* type of service */
+  u_short ip_len; /* total length */
+  u_short ip_id; /* identification */
+  u_short ip_off; /* fragment offset field */
+#define IP_RF 0x8000    /* reserved fragment flag */
+#define IP_DF 0x4000    /* dont fragment flag */
+#define IP_MF 0x2000    /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+  u_char ip_ttl; /* time to live */
+  u_char ip_p; /* protocol */
+  u_short ip_sum; /* checksum */
+  struct in_addr ip_src, ip_dst; /* source and dest address */
 };
 #define IP_OFF(ip)              (((ip)->ip_off) & IP_OFFMASK)
 #define IP_DF_VAL(ip)           ((((ip)->ip_off) & IP_DF) >> 14)
 #define IP_MF_VAL(ip)           ((((ip)->ip_off) & IP_MF) >> 13)
-#define IP_HL(ip)              (((ip)->ip_vhl) & 0x0f)
-#define IP_V(ip)               (((ip)->ip_vhl) >> 4)
+#define IP_HL(ip)   (((ip)->ip_vhl) & 0x0f)
+#define IP_V(ip)    (((ip)->ip_vhl) >> 4)
 
 /* TCP header */
 typedef u_int tcp_seq;
 
 struct sniff_tcp {
-  u_short th_sport;    /* source port */
-  u_short th_dport;    /* destination port */
-  tcp_seq th_seq;              /* sequence number */
-  tcp_seq th_ack;              /* acknowledgement number */
-  u_char th_offx2;     /* data offset, rsvd */
-#define TH_OFF(th)     (((th)->th_offx2 & 0xf0) >> 4)
+  u_short th_sport; /* source port */
+  u_short th_dport; /* destination port */
+  tcp_seq th_seq; /* sequence number */
+  tcp_seq th_ack; /* acknowledgement number */
+  u_char th_offx2; /* data offset, rsvd */
+#define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4)
   u_char th_flags;
 #define TH_FIN 0x01
 #define TH_SYN 0x02
@@ -183,26 +170,25 @@ struct sniff_tcp {
 #define TH_ECE 0x40
 #define TH_CWR 0x80
 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
-  u_short th_win;              /* window */
-  u_short th_sum;              /* checksum */
-  u_short th_urp;              /* urgent pointer */
+  u_short th_win; /* window */
+  u_short th_sum; /* checksum */
+  u_short th_urp; /* urgent pointer */
 };
 
 // Payload extraction /////////////////////////////////////////////////////////////////////////////////////
-u_char *getPayload(const u_char* packet, int packetSize, int &payloadSize, std::string &srcIp, std::string &dstIp, int &fragmentId, bool &dfFlag, bool &mfFlag, int &fragmentOffset) {
-
-  const struct sniff_ethernet *ethernet; /* The ethernet header */
+u_char *getPayload(const u_char* packet, int packetSize, int &payloadSize,
+                   std::string &srcIp, std::string &dstIp, int &fragmentId, bool &dfFlag,
+                   bool &mfFlag, int &fragmentOffset) {
   const struct sniff_ip *ip; /* The IP header */
   const struct sniff_tcp *tcp; /* The TCP header */
-
   u_int size_ip;
   u_int size_tcp;
-
-  ethernet = (struct sniff_ethernet*)(packet);
   ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
-  size_ip = IP_HL(ip)*4; // 4 bytes per 32 bits word
-  if (size_ip < 20) {
-    LOGDEBUG (Logger::debug(anna::functions::asString("Invalid IP header length: %d bytes", size_ip), ANNA_FILE_LOCATION));
+  size_ip = IP_HL(ip) * 4; // 4 bytes per 32 bits word
+
+  if(size_ip < 20) {
+    LOGDEBUG(
+      Logger::debug(anna::functions::asString("Invalid IP header length: %d bytes", size_ip), ANNA_FILE_LOCATION));
     return NULL;
   }
 
@@ -211,228 +197,206 @@ u_char *getPayload(const u_char* packet, int packetSize, int &payloadSize, std::
   srcIp = str;
   inet_ntop(AF_INET, &(ip->ip_dst), str, INET_ADDRSTRLEN);
   dstIp = str;
-
-  LOGDEBUG (Logger::debug(anna::functions::asString("ip_id: %d | ip_off: %d", ip->ip_id, ip->ip_off), ANNA_FILE_LOCATION));
+  LOGDEBUG(
+    Logger::debug(anna::functions::asString("ip_id: %d | ip_off: %d", ip->ip_id, ip->ip_off), ANNA_FILE_LOCATION));
   fragmentId = ip->ip_id;
   dfFlag = IP_DF_VAL(ip);
   mfFlag = IP_MF_VAL(ip);
   fragmentOffset = IP_OFF(ip);
-
-
   tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
-  size_tcp = TH_OFF(tcp)*4;
-  if (size_tcp < 20) {
-    LOGDEBUG (Logger::debug(anna::functions::asString("Invalid TCP header length: %d bytes", size_tcp), ANNA_FILE_LOCATION));
+  size_tcp = TH_OFF(tcp) * 4;
+
+  if(size_tcp < 20) {
+    LOGDEBUG(
+      Logger::debug(anna::functions::asString("Invalid TCP header length: %d bytes", size_tcp), ANNA_FILE_LOCATION));
     return NULL;
   }
 
   int payloadOffset = SIZE_ETHERNET + size_ip + size_tcp;
-  LOGDEBUG (Logger::debug(anna::functions::asString("PayloadOffset=%d", payloadOffset), ANNA_FILE_LOCATION));
+  LOGDEBUG(
+    Logger::debug(anna::functions::asString("PayloadOffset=%d", payloadOffset), ANNA_FILE_LOCATION));
   payloadSize = packetSize - payloadOffset;
   return ((u_char *)(packet + payloadOffset));
 }
 
 // Sniffing callback //////////////////////////////////////////////////////////////////////////////////////
-void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char* packet)
-{
-   static int count = 1;
-
-   static Payload auxPayload;
-
-   int packetSize = pkthdr->len;
-   int payloadSize;
-   std::string srcIp, dstIp;
-   int fragmentId, fragmentOffset;
-   bool dfFlag, mfFlag;
-   const u_char* payload = getPayload(packet, packetSize, payloadSize, srcIp, dstIp, fragmentId, dfFlag, mfFlag, fragmentOffset);
-   if (payload && (payloadSize > 0)) {
-     LOGDEBUG (
-       std::string msg;
-       msg += anna::functions::asString("\nFrame %d:", count);
-       msg += anna::functions::asHexString(anna::DataBlock((const char *)packet, pkthdr->len));
-       time_t time = pkthdr->ts.tv_sec;
-       msg += "\n";
-       msg += anna::functions::asString("\ntimestamp %d.%d", pkthdr->ts.tv_sec, pkthdr->ts.tv_usec);
-       msg += anna::functions::asString("\ndate %s", ctime(&time));
-       msg += anna::functions::asString("\ncaplen %d", pkthdr->caplen);
-       msg += anna::functions::asString("\npacketSize %d", packetSize);
-       msg += anna::functions::asString("\npayloadSize %d", payloadSize);
-       msg += "\nPayload:";
-       msg += anna::functions::asHexString(anna::DataBlock((const char *)payload, payloadSize));
-       msg += "\n";
-       msg += anna::functions::asString("\nsourceIP %s", srcIp.c_str());
-       msg += anna::functions::asString("\ndestinationIP %s", dstIp.c_str());
-       msg += "\n";
-       msg += anna::functions::asString("\nfragmentId %d:", fragmentId);
-       msg += anna::functions::asString("\nDF %s:", (dfFlag ? "1":"0"));
-       msg += anna::functions::asString("\nMF %s:", (mfFlag ? "1":"0"));
-       msg += anna::functions::asString("\nfragmentOffset %d:", fragmentOffset);
-
-       Logger::debug(msg, ANNA_FILE_LOCATION);
-     );
-
-     auxPayload.setDiameterLength((payload[1] << 16) + (payload[2] << 8) + payload[3]);
-     auxPayload.setSourceIP(srcIp);
-     auxPayload.setDestinationIP(dstIp);
-     auxPayload.setTimestamp(pkthdr->ts.tv_sec);
-     auxPayload.setTimestampU(pkthdr->ts.tv_usec);
-     bool completed = auxPayload.appendData((const char *)payload, payloadSize);
-     if (completed) {
-       G_payloads[count] = auxPayload;
-       auxPayload.reset();
-     }
+void my_callback(u_char *useless, const struct pcap_pkthdr* pkthdr,
+                 const u_char* packet) {
+  static int count = 1;
+  static Payload auxPayload;
+  int packetSize = pkthdr->len;
+  int payloadSize;
+  std::string srcIp, dstIp;
+  int fragmentId, fragmentOffset;
+  bool dfFlag, mfFlag;
+  const u_char* payload = getPayload(packet, packetSize, payloadSize, srcIp,
+                                     dstIp, fragmentId, dfFlag, mfFlag, fragmentOffset);
+
+  if(payload && (payloadSize > 0)) {
+    LOGDEBUG(
+      std::string msg; msg += anna::functions::asString("\nFrame %d:", count); msg += anna::functions::asHexString(anna::DataBlock((const char *)packet, pkthdr->len)); time_t time = pkthdr->ts.tv_sec; msg += "\n"; msg += anna::functions::asString("\ntimestamp %d.%d", pkthdr->ts.tv_sec, pkthdr->ts.tv_usec); msg += anna::functions::asString("\ndate %s", ctime(&time)); msg += anna::functions::asString("\ncaplen %d", pkthdr->caplen); msg += anna::functions::asString("\npacketSize %d", packetSize); msg += anna::functions::asString("\npayloadSize %d", payloadSize); msg += "\nPayload:"; msg += anna::functions::asHexString(anna::DataBlock((const char *)payload, payloadSize)); msg += "\n"; msg += anna::functions::asString("\nsourceIP %s", srcIp.c_str()); msg += anna::functions::asString("\ndestinationIP %s", dstIp.c_str()); msg += "\n"; msg += anna::functions::asString("\nfragmentId %d:", fragmentId); msg += anna::functions::asString("\nDF %s:", (dfFlag ? "1" : "0")); msg += anna::functions::asString("\nMF %s:", (mfFlag ? "1" : "0")); msg += anna::functions::asString("\nfragmentOffset %d:", fragmentOffset);
+      Logger::debug(msg, ANNA_FILE_LOCATION););
+    auxPayload.setDiameterLength(
+      (payload[1] << 16) + (payload[2] << 8) + payload[3]);
+    auxPayload.setSourceIP(srcIp);
+    auxPayload.setDestinationIP(dstIp);
+    auxPayload.setTimestamp(pkthdr->ts.tv_sec);
+    auxPayload.setTimestampU(pkthdr->ts.tv_usec);
+    bool completed = auxPayload.appendData((const char *) payload, payloadSize);
+
+    if(completed) {
+      G_payloads[count] = auxPayload;
+      auxPayload.reset();
+    }
   }
 
   count++;
 }
 
+bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) throw() {
+  // Get hex string
+  static char buffer[8192];
+  std::ifstream infile(pathfile.c_str(), std::ifstream::in);
+
+  if(infile.is_open()) {
+    infile >> buffer;
+    std::string hexString(buffer, strlen(buffer));
+    // Allow colon separator in hex string: we have to remove them before processing with 'fromHexString':
+    hexString.erase(std::remove(hexString.begin(), hexString.end(), ':'), hexString.end());
+    LOGDEBUG(
+      std::string msg = "Hex string (remove colons if exists): ";
+      msg += hexString;
+      anna::Logger::debug(msg, ANNA_FILE_LOCATION);
+    );
+    anna::functions::fromHexString(hexString, db);
+    // Close file
+    infile.close();
+    return true;
+  }
+
+  return false;
+}
+
+
+void _exit(const std::string &message, int resultCode = 1) {
+  if(resultCode)
+    std::cerr << message << std::endl << std::endl;
+  else
+    std::cout << message << std::endl << std::endl;
+
+  exit(resultCode);
+}
+
+
+//-------------------------------------------------------------------
+int main(int argc, char **argv) {
+  std::string exec = argv[0];
+  std::string execBN = exec.substr(exec.find_last_of("/") + 1);
+  std::string filetrace = execBN + ".trace";
+  std::cout << std::endl;
+
+  //check command line arguments
+  if(argc < 2) {
+    std::string msg = "Usage: "; msg += exec;
+    msg += " <pcap file> [--write-hex: to write hex files] [--debug: activates debug level traces (warning by default)]\n\n";
+    _exit(msg);
+  }
+
+  // Command-line parameters:
+  std::string inputFile = argv[1];
+  //bool isHex = (inputFile.substr(inputFile.find_last_of(".") + 1) == "hex");
+  std::string outputFile = inputFile; // extension will be added later
+  std::string optionals;
+  int indx = 2;
+  while(indx < argc) { optionals += " "; optionals += argv[indx]; indx++; }
+
+  bool debug = (optionals.find("--debug") != std::string::npos);
+  bool writeHex = (optionals.find("--write-hex") != std::string::npos);
+  Logger::setLevel(debug ? Logger::Debug:Logger::Warning);
+  Logger::initialize(execBN.c_str(), new TraceWriter(filetrace.c_str(), 2048000));
+
+  anna::DataBlock db_aux(true);
+
+  // SNIFFING //////////////////////////////////////////////////////////////////////////////////////////////7
+  //temporary packet buffers
+  //struct pcap_pkthdr header; // The header that pcap gives us
+  //const u_char *packet;      // The actual packet
+  //------------------
+  //open the pcap file
+  pcap_t *handle;
+  char errbuf[PCAP_ERRBUF_SIZE];        //not sure what to do with this, oh well
+  handle = pcap_open_offline(inputFile.c_str(), errbuf); //call pcap library function
+
+  if(handle == NULL) _exit(errbuf, 2);
+
+  // TODO: add filtering. At the moment, pcap must be previously filtered for diameter protocol ('tcp port 3868' or any other filter allowed)
+  /*
+  // Filtering:
+  std::string filter = ?????;
+  struct bpf_program _fp;
+  struct bpf_program *fp = &_fp;
+  bpf_u_int32 netmask = 4294967295; // FFFFFFFF
+
+  if (pcap_compile(handle, fp, (char*)(filter.c_str()), 1, netmask) == -1) {
+        std::cerr << "Couldn't compile the filter " << filter << std::endl;
+    return(2); 
+  }
 
+  if (pcap_setfilter(handle, fp) == -1) {
+    std::cerr << "Couldn't set the filter " << filter << std::endl; 
+    return(2); 
+  }
+  */
+
+  //begin processing the packets in this particular file
+  int packets = -1;
+
+  try {
+    while(packets != 0)
+      packets = pcap_dispatch(handle, -1, (pcap_handler) my_callback, NULL);
+  } catch(RuntimeException &ex) {
+    _exit(ex.asString());
+  }
+
+  pcap_close(handle);  //close the pcap file
+
+  // Print payloads //////////////////////////////////////////////////////////////////////////////////////////////
+  // Open output file:
+  outputFile += ".report";
+  std::ofstream out(outputFile.c_str(), std::ifstream::out);
+
+  for(payloads_it it = G_payloads.begin(); it != G_payloads.end(); it++) {
+    LOGDEBUG(
+      Logger::debug(anna::functions::asString("Dumping frame %d", it->first), ANNA_FILE_LOCATION));
+    time_t ts = (it->second).getTimestamp();
+    int tsu = (it->second).getTimestampU();
+    std::string ts_str = ctime(&ts);
+    ts_str.erase(ts_str.find("\n"));
+    out << "Frame:           " << anna::functions::asString(it->first) << std::endl;
+    out << "Date:            " << ts_str << std::endl;
+    out << "Timestamp:       " << anna::functions::asString((int)ts) << "."
+        << anna::functions::asString((int)tsu) << std::endl;
+    out << "Origin IP:       " << (it->second).getSourceIP() << std::endl;
+    out << "Destination IP:  " << (it->second).getDestinationIP() << std::endl;
+    out << "Destination IP:  " << (it->second).getDestinationIP() << std::endl;
+    out << "Hex String:      " << (it->second).getDataAsHex() << std::endl;
+
+    // Create hex file:
+    if (writeHex) {
+      std::string hexFile =  anna::functions::asString(it->first) + ".hex";
+      std::ofstream hex(hexFile.c_str(), std::ifstream::out);
+      hex << (it->second).getDataAsHex();
+      hex.close();
+    }
+
+    out << std::endl;
+  }
 
-//------------------------------------------------------------------- 
-int main(int argc, char **argv) 
-{ 
-   std::string exec = argv[0];
-
-   std::cout << std::endl;
-
-   //check command line arguments 
-   if (argc < 3) {
-     std::cout << "Usage: " << exec << " <list of comma-separated xml dictionaries> <pcap file> [--ignore-flags: non-strict validation]" << std::endl << std::endl;
-     return 1;
-   } 
-
-   // Command-line parameters:
-   std::string dictionaries = argv[1];
-   std::string pcapFile = argv[2];
-   std::string optional = argv[3];
-   bool ignoreFlags = ((argc == 4) && (optional == "--ignore-flags"));
-   std::cout << "Dictionary(ies) provided: " << dictionaries << std::endl;
-   std::cout << "Pcap file provided:       " << pcapFile << std::endl;
-   std::cout << "Validation kindness:      " << (ignoreFlags ? "non strict":"strict") << std::endl;
-
-   // Logger and engines:
-   Logger::setLevel(Logger::Debug);
-   Logger::initialize("pcapDecoder", new TraceWriter("file.trace", 2048000));
-   anna::diameter::codec::Engine *codecEngine = new anna::diameter::codec::Engine();
-   anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
-
-   try {
-      anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* stack id */);
-      // Analyze comma-separated list:
-      anna::Tokenizer lst;
-      lst.apply(dictionaries, ",");
-
-      if (lst.size() >= 1) { // always true (at least one, because -dictionary is mandatory)
-         anna::Tokenizer::const_iterator tok_min(lst.begin());
-         anna::Tokenizer::const_iterator tok_max(lst.end());
-         anna::Tokenizer::const_iterator tok_iter;
-         std::string pathFile;
-         d->allowUpdates();
-
-         for (tok_iter = tok_min; tok_iter != tok_max; tok_iter++) {
-            pathFile = anna::Tokenizer::data(tok_iter);
-            d->load(pathFile);
-         }
-      }
-
-      codecEngine->setDictionary(d);
-      //LOGDEBUG(anna::Logger::debug(codecEngine->asString(), ANNA_FILE_LOCATION));
-
-      if (lst.size() > 1) {
-        std::ofstream out("./dictionary.xml", std::ifstream::out);
-        std::string buffer = d->asXMLString();
-        out.write(buffer.c_str(), buffer.size());
-        out.close();
-        std::cout << "Written 'dictionary.xml' (provide it next time to be more comfortable)." << std::endl;
-      }
-
-   } catch (anna::RuntimeException &ex) {
-     std::cerr << ex.asString() << std::endl << std::endl;
-     return 1;
-   }
-
-   codecEngine->ignoreFlagsOnValidation(ignoreFlags);
-   // Tracing:
-   //if (cl.exists("trace"))
-   //   anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace")));
-
-
-
-   // SNIFFING //////////////////////////////////////////////////////////////////////////////////////////////7
-
-   //temporary packet buffers 
-   struct pcap_pkthdr header; // The header that pcap gives us 
-   const u_char *packet;      // The actual packet 
-
-   //------------------ 
-   //open the pcap file 
-   pcap_t *handle; 
-   char errbuf[PCAP_ERRBUF_SIZE];                    //not sure what to do with this, oh well
-   handle = pcap_open_offline(pcapFile.c_str(), errbuf);   //call pcap library function
-
-   if (handle == NULL) { 
-     std::cerr << errbuf << std::endl << std::endl;
-     return 2;
-   } 
-
-
-   //begin processing the packets in this particular file
-   int packets = -1;
-   try {
-     while (packets != 0)
-         packets = pcap_dispatch(handle, -1, (pcap_handler)my_callback, NULL);
-   }
-   catch (RuntimeException &ex) {
-     std::cerr << ex.asString() << std::endl << std::endl;
-     return 1;
-   }
-   pcap_close(handle);  //close the pcap file 
-
-   // Print payloads //////////////////////////////////////////////////////////////////////////////////////////////
-
-   // Open output file:
-   std::string output = pcapFile; output += ".report";
-   std::ofstream out(output, std::ifstream::out);
-   std::string xmlStr;
-   anna::DataBlock db_aux(true);
-
-   //out.write(str.c_str(), str.size());
-
-
-   for (payloads_it it = G_payloads.begin(); it != G_payloads.end(); it++) {
-        LOGDEBUG (Logger::debug(anna::functions::asString("Dumping frame %d", it->first), ANNA_FILE_LOCATION));
-       time_t ts = (it->second).getTimestamp();
-       int tsu = (it->second).getTimestampU();
-       std::string ts_str = ctime(&ts);
-       ts_str.erase (ts_str.find ("\n"));
-
-        out << std::endl;
-        out << "===================================================================================================" << std::endl;
-       out << "Date:           " << ts_str << std::endl;
-       out << "Timestamp:      " << std::to_string(ts) << "." << std::to_string(tsu) << std::endl;
-       out << "Origin IP:      " << (it->second).getSourceIP() << std::endl;
-       out << "Destination IP: " << (it->second).getDestinationIP() << std::endl;
-        out << std::endl;
-
-       // decode hex string:
-       anna::functions::fromHexString((it->second).getDataAsHex(), db_aux);
-        try {
-         G_codecMsg.decode(db_aux);
-        }
-        catch (RuntimeException &ex) {
-          std::cerr << ex.asString() << std::endl << std::endl;
-          return 1;
-        }
-       out << G_codecMsg.asXMLString();
-   }
-
-
-   // Close output file:
-   out.close();
-
-   std::cout << "Open 'file.trace' in order to see process traces." << std::endl;
-   std::cout << "Open '" << output << "' to see conversion results." << std::endl;
-   std::cout << std::endl;
-   return 0;
+  // Close output file:
+  out.close();
+  std::string msg = "Open '"; msg += filetrace; msg += "' in order to see process traces.\n";
+  msg += "Open '"; msg += outputFile; msg += "' to see decoding results.\n";
+  if (writeHex) msg += "Open '<frame number>.hex' to see specific frame data.";
+  _exit(msg, 0);
 }