X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=example%2Fdiameter%2FpcapDecoder%2Fmain.cpp;h=97474e8428a5cb9d2a32b241ddedb2c8220ee5d5;hb=5a6cba5fde2b2f538a7515f8293cc0a8d9589dfa;hp=8029b51ab1a5db2489f8bcf03704c7512fc9e6a5;hpb=3190f5702ccfcd2c42c51f4aa3217b249fead77f;p=anna.git diff --git a/example/diameter/pcapDecoder/main.cpp b/example/diameter/pcapDecoder/main.cpp index 8029b51..97474e8 100644 --- a/example/diameter/pcapDecoder/main.cpp +++ b/example/diameter/pcapDecoder/main.cpp @@ -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 #include #include @@ -46,18 +18,13 @@ #include #include -#include #include #include #include #include -#include -#include -#include -#include + using namespace anna; -using namespace anna::diameter; // Payload and frame metadata ///////////////////////////////////////////////////////////////////////////// class Payload { @@ -82,20 +49,20 @@ public: } } - void setSourceIP(const std::string &srcIP) throw() { + void setSourceIP(const std::string &srcIP) { _sourceIP = srcIP; } - void setDestinationIP(const std::string &dstIP) throw() { + void setDestinationIP(const std::string &dstIP) { _destinationIP = dstIP; } - void setTimestamp(time_t ts) throw() { + void setTimestamp(time_t ts) { _timestamp = ts; } - void setTimestampU(int tsu) throw() { + void setTimestampU(int tsu) { _timestampU = tsu; } // Returns true if completed: - bool appendData(const char *data, size_t size) throw(RuntimeException) { + bool appendData(const char *data, size_t size) noexcept(false) { LOGDEBUG( Logger::debug(anna::functions::asString("Appending %d bytes", size), ANNA_FILE_LOCATION)); _data.append(data, size); @@ -112,7 +79,7 @@ public: return true; } - void reset() throw() { + void reset() { _sourceIP = ""; _destinationIP = ""; _timestamp = 0; @@ -121,22 +88,22 @@ public: _diameterLength = -1; // not calculated yet } - const std::string &getSourceIP() const throw() { + const std::string &getSourceIP() const { return _sourceIP; } - const std::string &getDestinationIP() const throw() { + const std::string &getDestinationIP() const { return _destinationIP; } - time_t getTimestamp() const throw() { + time_t getTimestamp() const { return _timestamp; } - int getTimestampU() const throw() { + int getTimestampU() const { return _timestampU; } - const std::string &getData() const throw() { + const std::string &getData() const { return _data; } - std::string getDataAsHex() const throw() { + std::string getDataAsHex() const { return anna::functions::asHexString( anna::DataBlock(_data.c_str(), _data.size())); } @@ -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 @@ -289,7 +253,7 @@ void my_callback(u_char *useless, const struct pcap_pkthdr* pkthdr, count++; } -bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) throw() { +bool getDataBlockFromHexFile(const std::string &pathfile, anna::DataBlock &db) { // Get hex string static char buffer[8192]; std::ifstream infile(pathfile.c_str(), std::ifstream::in); @@ -327,106 +291,36 @@ void _exit(const std::string &message, int resultCode = 1) { //------------------------------------------------------------------- int main(int argc, char **argv) { std::string exec = argv[0]; - std::string filetrace = exec.substr(exec.find_last_of("/") + 1) + ".trace"; + 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 += " [--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 += " [--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(filetrace.c_str(), 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); - } - } + std::string optionals; + int indx = 2; + while(indx < argc) { optionals += " "; optionals += argv[indx]; indx++; } - 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()); - } + 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->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 '"; msg += filetrace; msg += "' 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; @@ -435,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; @@ -446,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( @@ -458,32 +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 '"; msg += filetrace; msg += "' in order to see process traces.\n"; - msg += "Open '"; msg += outputFile; msg += "' to see decoding results."; + msg += "Open '"; msg += outputFile; msg += "' to see decoding results.\n"; + if (writeHex) msg += "Open '.hex' to see specific frame data."; _exit(msg, 0); }