Remove warnings
[anna.git] / example / diameter / pcapDecoder / main.cpp
index 65681d8..cdada35 100644 (file)
@@ -1,39 +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 {
@@ -146,7 +113,6 @@ public:
 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 ////////////////////////////////////////////////////////////////////////////////////
 
@@ -213,12 +179,10 @@ struct sniff_tcp {
 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 */
   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
 
@@ -290,10 +254,10 @@ void my_callback(u_char *useless, const struct pcap_pkthdr* pkthdr,
 }
 
 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));
@@ -304,7 +268,6 @@ bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) t
       msg += hexString;
       anna::Logger::debug(msg, ANNA_FILE_LOCATION);
     );
-
     anna::functions::fromHexString(hexString, db);
     // Close file
     infile.close();
@@ -316,10 +279,11 @@ bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) t
 
 
 void _exit(const std::string &message, int resultCode = 1) {
-  if (resultCode)
+  if(resultCode)
     std::cerr << message << std::endl << std::endl;
   else
     std::cout << message << std::endl << std::endl;
+
   exit(resultCode);
 }
 
@@ -327,108 +291,36 @@ void _exit(const std::string &message, int resultCode = 1) {
 //-------------------------------------------------------------------
 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 < 3) {
+  if(argc < 2) {
     std::string msg = "Usage: "; msg += exec;
-    msg += " <dictionaries> <input file> [--ignore-flags: non-strict validation]\n\n";
-    msg += "       dictionaries: list of comma-separated xml dictionaries (one or more can be provided).\n";
-    msg += "       Input file:   normally a pcap file, but hexadecimal content (colons allowed) can also be decoded (use '.hex' extension).";
+    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 dictionaries = argv[1];
-  std::string inputFile = argv[2];
-  bool isHex = (inputFile.substr(inputFile.find_last_of(".") + 1) == "hex");
+  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 optional = argv[3] ? argv[3] : "";
-  bool ignoreFlags = ((argc == 4) && (optional == "--ignore-flags"));
-  std::cout << "Dictionary(ies) provided: " << dictionaries << std::endl;
-  std::cout << "Input file provided:      " << inputFile << 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();
+  std::string optionals;
+  int indx = 2;
+  while(indx < argc) { optionals += " "; optionals += argv[indx]; indx++; }
 
-  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);
-      }
-    }
+  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));
 
-    codecEngine->setDictionary(d);
-    //LOGDEBUG(anna::Logger::debug(codecEngine->asString(), ANNA_FILE_LOCATION));
-
-    if(lst.size() > 1) {
-      std::string all_in_one = "./dictionary-all-in-one.xml";
-      std::ofstream out(all_in_one, std::ifstream::out);
-      std::string buffer = d->asXMLString();
-      out.write(buffer.c_str(), buffer.size());
-      out.close();
-      std::cout << "Written accumulated '" << all_in_one
-                << "' (provide it next time to be more comfortable)." << std::endl;
-    }
-  } catch(anna::RuntimeException &ex) {
-    _exit(ex.asString());
-  }
-
-  codecEngine->ignoreFlagsOnValidation(ignoreFlags);
-  // Tracing:
-  //if (cl.exists("trace"))
-  //   anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace")));
-
-  // Check hex content input file (look extension):
   anna::DataBlock db_aux(true);
-  if(isHex) {
-    if (!getDataBlockFromHexFile(inputFile, db_aux))
-      _exit("Error reading hex file provided");
-
-    try {
-      G_codecMsg.decode(db_aux);
-    } catch(RuntimeException &ex) {
-      _exit(ex.asString());
-    }
-
-    // Open output file:
-    outputFile += ".as.xml";
-    std::ofstream out(outputFile, std::ifstream::out);
-    out << G_codecMsg.asXMLString();
-
-    // Close output file:
-    out.close();
-
-    std::string msg = "Open 'file.trace' in order to see process traces.\n";
-    msg += "Open '"; msg += outputFile; msg += "' to see decoding results.";
-    _exit(msg, 0);
-  }
-
-  // Normal input: pcap file:
 
   // SNIFFING //////////////////////////////////////////////////////////////////////////////////////////////7
   //temporary packet buffers
-  struct pcap_pkthdr header; // The header that pcap gives us
-  const u_char *packet;      // The actual packet
+  //struct pcap_pkthdr header; // The header that pcap gives us
+  //const u_char *packet;      // The actual packet
   //------------------
   //open the pcap file
   pcap_t *handle;
@@ -437,6 +329,25 @@ int main(int argc, char **argv) {
 
   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;
 
@@ -448,10 +359,11 @@ int main(int argc, char **argv) {
   }
 
   pcap_close(handle);  //close the pcap file
+
   // Print payloads //////////////////////////////////////////////////////////////////////////////////////////////
   // Open output file:
   outputFile += ".report";
-  std::ofstream out(outputFile, std::ifstream::out);
+  std::ofstream out(outputFile.c_str(), std::ifstream::out);
 
   for(payloads_it it = G_payloads.begin(); it != G_payloads.end(); it++) {
     LOGDEBUG(
@@ -460,33 +372,31 @@ int main(int argc, char **argv) {
     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) {
-      _exit(ex.asString());
+    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 << G_codecMsg.asXMLString();
+    out << std::endl;
   }
 
   // Close output file:
   out.close();
-
-  std::string msg = "Open 'file.trace' in order to see process traces.\n";
-  msg += "Open '"; msg += outputFile; msg += "' to see decoding results.";
+  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);
 }