// Authors: eduardo.ramos.testillano@gmail.com
// cisco.tierra@gmail.com
-
// Standard
#include <pcap.h>
#include <stdlib.h>
#include <anna/diameter/stack/Engine.hpp>
#include <anna/diameter/codec/Engine.hpp>
#include <anna/diameter/codec/Message.hpp>
-
-
+//#include <anna/diameter/defines.hpp> // typedef unsigned int ApplicationId;
+#include <anna/diameter/codec/functions.hpp> // ApplicationId anna::diameter::codec::functions::getApplicationId(const anna::DataBlock &) throw(anna::RuntimeException);
using namespace anna;
using namespace anna::diameter;
-
// Payload and frame metadata /////////////////////////////////////////////////////////////////////////////
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;
-
-
-
-
+anna::diameter::codec::Engine *G_codecEngine;
// 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 {
/* 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
#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) {
-
+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
- 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;
}
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;
+}
-//-------------------------------------------------------------------
-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));
+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);
+}
+
+// Decodes a diameter message coming from a datablock
+void decodeDataBlock(const anna::DataBlock &db, unsigned int & detectedApplicationId) throw() {
+ try {
+ detectedApplicationId = anna::diameter::codec::functions::getApplicationId(db);
+ G_codecEngine->setDictionary(detectedApplicationId);
+ G_codecMsg.decode(db);
+ } catch(RuntimeException &ex) {
+ _exit(ex.asString());
+ }
+}
- 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;
+
+//-------------------------------------------------------------------
+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) {
+ std::string msg = "Usage: "; msg += exec;
+ msg += " <stacks> <input file> [--no-validation] [--ignore-flags]\n\n";
+ msg += " stacks: <id1#dictionary1,id2#dictionary2,...,idN#dictionaryN>\n";
+ msg += " This is a list of comma-separated stacks defined by a #-separated pair <application-id#xml dictionary pathfile>\n";
+ msg += " If only one stack is provided, application-id could be omitted and then, all the messages will be decoded with the\n";
+ msg += " dictionary regardless the value of the application-id (the stack will be registered with id=0).\n";
+ msg += " Input file: normally a pcap file, but hexadecimal content (colons allowed) can also be decoded (use '.hex' extension).\n";
+ msg += " --no-validation: no validation is performed.\n";
+ msg += " --ignore-flags: wrong flags regarding dictionary are ignored in xml representation.";
+ _exit(msg);
+ }
+
+ // Command-line parameters:
+ std::string stacks = argv[1];
+ std::string inputFile = argv[2];
+ bool isHex = (inputFile.substr(inputFile.find_last_of(".") + 1) == "hex");
+ std::string outputFile = inputFile; // extension will be added later
+ std::string optionals;
+ int indx = 3;
+
+ while(indx < argc) { optionals += " "; optionals += argv[indx]; indx++; }
+
+ bool no_validation = (optionals.find("--no-validation") != std::string::npos);
+ bool ignore_flags = (optionals.find("--ignore-flags") != std::string::npos);
+ Logger::setLevel(Logger::Debug);
+ Logger::initialize(execBN.c_str(), new TraceWriter(filetrace.c_str(), 2048000));
+ G_codecEngine = new anna::diameter::codec::Engine();
+ anna::diameter::stack::Engine &stackEngine =
+ anna::diameter::stack::Engine::instantiate();
+
+ // Register stacks:
+ try {
+ anna::Tokenizer stacksTok;
+ stacksTok.apply(stacks, ",");
+ anna::Tokenizer::const_iterator stacks_it, stack_it;
+
+ for(stacks_it = stacksTok.begin(); stacks_it != stacksTok.end(); stacks_it++) {
+ std::string stack = anna::Tokenizer::data(stacks_it);
+ anna::Tokenizer stackTok;
+ stackTok.apply(stack, "#");
+
+ if(stackTok.size() == 1) {
+ if(stacksTok.size() != 1)
+ throw anna::RuntimeException("Application Id value is mandatory when more than one stack is going to be configured", ANNA_FILE_LOCATION);
+
+ anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* no matter */, stack); // the stack is the dictionary
+ G_codecEngine->setDictionary(d);
+ break;
}
- } 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;
+ if(stackTok.size() != 2)
+ throw anna::RuntimeException("Each stack must be in the form '<application-id>#<xml dictionary pathfile>'", ANNA_FILE_LOCATION);
+
+ stack_it = stackTok.begin();
+ unsigned int stackId = atoll(anna::Tokenizer::data(stack_it));
+ stack_it++;
+ std::string file = anna::Tokenizer::data(stack_it);
+ anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(stackId, file);
+ }
+
+ std::cout << "Stacks provided: " << std::endl;
+ std::cout << anna::functions::tab(stackEngine.asString(false /* light */));
+ std::cout << std::endl;
+ std::cout << "Input file provided: " << inputFile << std::endl;
+ std::cout << "Validation: " << (!no_validation ? "yes" : "no") << std::endl;
+ std::cout << "Ignore Flags: " << (ignore_flags ? "yes" : "no") << std::endl;
+ std::cout << std::endl;
+ } catch(anna::RuntimeException &ex) {
+ _exit(ex.asString());
+ }
+
+ // Validation kindness
+ if(no_validation) G_codecEngine->setValidationMode(anna::diameter::codec::EngineImpl::ValidationMode::Never);
+
+ if(ignore_flags) G_codecEngine->ignoreFlagsOnValidation(true);
+
+ // 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);
+ unsigned int detectedApplicationId;
+
+ if(isHex) {
+ if(!getDataBlockFromHexFile(inputFile, db_aux))
+ _exit("Error reading hex file provided");
+
+ // Decode datablock:
+ decodeDataBlock(db_aux, detectedApplicationId);
+ // 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
+ //------------------
+ //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);
+
+ //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, 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 << std::endl;
+ out
+ << "==================================================================================================="
+ << 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;
+ // decode hex string:
+ anna::functions::fromHexString((it->second).getDataAsHex(), db_aux);
+ // Decode datablock:
+ decodeDataBlock(db_aux, detectedApplicationId);
+ // Stack identification:
+ //out << "Application Id: " << detectedApplicationId << std::endl;
+ out << "Dictionary used: " << G_codecEngine->getDictionary()->getName() << std::endl;
+ out << std::endl;
+ 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);
}