statistics_db.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. #include "statistics_db.h"
  2. #include <iostream>
  3. #include <sstream>
  4. /**
  5. * Creates a new statistics_db object. Opens an existing database located at database_path. If not existing, creates
  6. * a new database at database_path.
  7. * @param database_path The file path of the database.
  8. */
  9. statistics_db::statistics_db(std::string database_path) {
  10. // Append file extension if not present
  11. if (database_path.find(".sqlite3") == database_path.npos) {
  12. database_path += ".sqlite3";
  13. }
  14. // creates the DB if not existing, opens the DB for read+write access
  15. db.reset(new SQLite::Database(database_path, SQLite::OPEN_CREATE | SQLite::OPEN_READWRITE));
  16. }
  17. /**
  18. * Writes the IP statistics into the database.
  19. * @param ipStatistics The IP statistics from class statistics.
  20. */
  21. void statistics_db::writeStatisticsIP(std::unordered_map<std::string, entry_ipStat> ipStatistics) {
  22. try {
  23. db->exec("DROP TABLE IF EXISTS ip_statistics");
  24. SQLite::Transaction transaction(*db);
  25. const char *createTable = "CREATE TABLE ip_statistics ( "
  26. "ipAddress TEXT, "
  27. "pktsReceived INTEGER, "
  28. "pktsSent INTEGER, "
  29. "kbytesReceived REAL, "
  30. "kbytesSent REAL, "
  31. "maxPktRate REAL,"
  32. "minPktRate REAL,"
  33. "class TEXT, "
  34. "srcAnomalyScore REAL, "
  35. "dstAnomalyScore REAL, "
  36. "PRIMARY KEY(ipAddress));";
  37. db->exec(createTable);
  38. SQLite::Statement query(*db, "INSERT INTO ip_statistics VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
  39. for (auto it = ipStatistics.begin(); it != ipStatistics.end(); ++it) {
  40. entry_ipStat e = it->second;
  41. query.bind(1, it->first);
  42. query.bind(2, (int) e.pkts_received);
  43. query.bind(3, (int) e.pkts_sent);
  44. query.bind(4, e.kbytes_received);
  45. query.bind(5, e.kbytes_sent);
  46. // Aidmar
  47. query.bind(6, e.max_pkt_rate);
  48. query.bind(7, e.min_pkt_rate);
  49. query.bind(8, e.ip_class);
  50. query.bind(9, e.sourceAnomalyScore);
  51. query.bind(10, e.destinationAnomalyScore);
  52. query.exec();
  53. query.reset();
  54. }
  55. transaction.commit();
  56. }
  57. catch (std::exception &e) {
  58. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  59. }
  60. }
  61. /**
  62. * Writes the TTL distribution into the database.
  63. * @param ttlDistribution The TTL distribution from class statistics.
  64. */
  65. void statistics_db::writeStatisticsTTL(std::unordered_map<ipAddress_ttl, int> ttlDistribution) {
  66. try {
  67. db->exec("DROP TABLE IF EXISTS ip_ttl");
  68. SQLite::Transaction transaction(*db);
  69. const char *createTable = "CREATE TABLE ip_ttl ("
  70. "ipAddress TEXT,"
  71. "ttlValue INTEGER,"
  72. "ttlCount INTEGER,"
  73. "PRIMARY KEY(ipAddress,ttlValue));";
  74. db->exec(createTable);
  75. SQLite::Statement query(*db, "INSERT INTO ip_ttl VALUES (?, ?, ?)");
  76. for (auto it = ttlDistribution.begin(); it != ttlDistribution.end(); ++it) {
  77. ipAddress_ttl e = it->first;
  78. query.bind(1, e.ipAddress);
  79. query.bind(2, e.ttlValue);
  80. query.bind(3, it->second);
  81. query.exec();
  82. query.reset();
  83. }
  84. transaction.commit();
  85. }
  86. catch (std::exception &e) {
  87. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  88. }
  89. }
  90. /**
  91. * Writes the protocol distribution into the database.
  92. * @param protocolDistribution The protocol distribution from class statistics.
  93. */
  94. void statistics_db::writeStatisticsProtocols(std::unordered_map<ipAddress_protocol, int> protocolDistribution) {
  95. try {
  96. db->exec("DROP TABLE IF EXISTS ip_protocols");
  97. SQLite::Transaction transaction(*db);
  98. const char *createTable = "CREATE TABLE ip_protocols ("
  99. "ipAddress TEXT,"
  100. "protocolName TEXT,"
  101. "protocolCount INTEGER,"
  102. "PRIMARY KEY(ipAddress,protocolName));";
  103. db->exec(createTable);
  104. SQLite::Statement query(*db, "INSERT INTO ip_protocols VALUES (?, ?, ?)");
  105. for (auto it = protocolDistribution.begin(); it != protocolDistribution.end(); ++it) {
  106. ipAddress_protocol e = it->first;
  107. query.bind(1, e.ipAddress);
  108. query.bind(2, e.protocol);
  109. query.bind(3, it->second);
  110. query.exec();
  111. query.reset();
  112. }
  113. transaction.commit();
  114. }
  115. catch (std::exception &e) {
  116. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  117. }
  118. }
  119. /**
  120. * Writes the port statistics into the database.
  121. * @param portsStatistics The ports statistics from class statistics.
  122. */
  123. void statistics_db::writeStatisticsPorts(std::unordered_map<ipAddress_inOut_port, int> portsStatistics) {
  124. try {
  125. db->exec("DROP TABLE IF EXISTS ip_ports");
  126. SQLite::Transaction transaction(*db);
  127. const char *createTable = "CREATE TABLE ip_ports ("
  128. "ipAddress TEXT,"
  129. "portDirection TEXT,"
  130. "portNumber INTEGER,"
  131. "portCount INTEGER,"
  132. "PRIMARY KEY(ipAddress,portDirection,portNumber));";
  133. db->exec(createTable);
  134. SQLite::Statement query(*db, "INSERT INTO ip_ports VALUES (?, ?, ?, ?)");
  135. for (auto it = portsStatistics.begin(); it != portsStatistics.end(); ++it) {
  136. ipAddress_inOut_port e = it->first;
  137. query.bind(1, e.ipAddress);
  138. query.bind(2, e.trafficDirection);
  139. query.bind(3, e.portNumber);
  140. query.bind(4, it->second);
  141. query.exec();
  142. query.reset();
  143. }
  144. transaction.commit();
  145. }
  146. catch (std::exception &e) {
  147. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  148. }
  149. }
  150. /**
  151. * Writes the IP address -> MAC address mapping into the database.
  152. * @param IpMacStatistics The IP address -> MAC address mapping from class statistics.
  153. */
  154. void statistics_db::writeStatisticsIpMac(std::unordered_map<std::string, std::string> IpMacStatistics) {
  155. try {
  156. db->exec("DROP TABLE IF EXISTS ip_mac");
  157. SQLite::Transaction transaction(*db);
  158. const char *createTable = "CREATE TABLE ip_mac ("
  159. "ipAddress TEXT,"
  160. "macAddress TEXT,"
  161. "PRIMARY KEY(ipAddress));";
  162. db->exec(createTable);
  163. SQLite::Statement query(*db, "INSERT INTO ip_mac VALUES (?, ?)");
  164. for (auto it = IpMacStatistics.begin(); it != IpMacStatistics.end(); ++it) {
  165. query.bind(1, it->first);
  166. query.bind(2, it->second);
  167. query.exec();
  168. query.reset();
  169. }
  170. transaction.commit();
  171. }
  172. catch (std::exception &e) {
  173. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  174. }
  175. }
  176. /**
  177. * Writes the MSS statistics into the database.
  178. * @param mssStatistics The MSS statistics from class statistics.
  179. */
  180. void statistics_db::writeStatisticsMss(std::unordered_map<std::string, int> mssStatistics) {
  181. try {
  182. db->exec("DROP TABLE IF EXISTS tcp_mss");
  183. SQLite::Transaction transaction(*db);
  184. const char *createTable = "CREATE TABLE tcp_mss ("
  185. "ipAddress TEXT,"
  186. "mss INTEGER);";
  187. db->exec(createTable);
  188. SQLite::Statement query(*db, "INSERT INTO tcp_mss VALUES (?, ?)");
  189. for (auto it = mssStatistics.begin(); it != mssStatistics.end(); ++it) {
  190. query.bind(1, it->first);
  191. query.bind(2, it->second);
  192. query.exec();
  193. query.reset();
  194. }
  195. transaction.commit();
  196. }
  197. catch (std::exception &e) {
  198. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  199. }
  200. }
  201. /**
  202. * Writes general file statistics into the database.
  203. * @param packetCount The number of packets in the PCAP file.
  204. * @param captureDuration The duration of the capture (format: SS.mmmmmm).
  205. * @param timestampFirstPkt The timestamp of the first packet in the PCAP file.
  206. * @param timestampLastPkt The timestamp of the last packet in the PCAP file.
  207. * @param avgPacketRate The average packet rate (#packets / capture duration).
  208. * @param avgPacketSize The average packet size.
  209. * @param avgPacketsSentPerHost The average packets sent per host.
  210. * @param avgBandwidthIn The average incoming bandwidth.
  211. * @param avgBandwidthOut The average outgoing bandwidth.
  212. */
  213. void statistics_db::writeStatisticsFile(int packetCount, float captureDuration, std::string timestampFirstPkt,
  214. std::string timestampLastPkt, float avgPacketRate, float avgPacketSize,
  215. float avgPacketsSentPerHost, float avgBandwidthIn, float avgBandwidthOut) {
  216. try {
  217. db->exec("DROP TABLE IF EXISTS file_statistics");
  218. SQLite::Transaction transaction(*db);
  219. const char *createTable = "CREATE TABLE file_statistics ("
  220. "packetCount INTEGER,"
  221. "captureDuration TEXT,"
  222. "timestampFirstPacket TEXT,"
  223. "timestampLastPacket TEXT,"
  224. "avgPacketRate REAL,"
  225. "avgPacketSize REAL,"
  226. "avgPacketsSentPerHost REAL,"
  227. "avgBandwidthIn REAL,"
  228. "avgBandwidthOut REAL);";
  229. db->exec(createTable);
  230. SQLite::Statement query(*db, "INSERT INTO file_statistics VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
  231. query.bind(1, packetCount);
  232. query.bind(2, captureDuration);
  233. query.bind(3, timestampFirstPkt);
  234. query.bind(4, timestampLastPkt);
  235. query.bind(5, avgPacketRate);
  236. query.bind(6, avgPacketSize);
  237. query.bind(7, avgPacketsSentPerHost);
  238. query.bind(8, avgBandwidthIn);
  239. query.bind(9, avgBandwidthOut);
  240. query.exec();
  241. transaction.commit();
  242. }
  243. catch (std::exception &e) {
  244. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  245. }
  246. }
  247. // Aidamr
  248. /**
  249. * Writes the MSS distribution into the database.
  250. * @param mssDistribution The MSS distribution from class statistics.
  251. */
  252. void statistics_db::writeStatisticsMss_dist(std::unordered_map<ipAddress_mss, int> mssDistribution) {
  253. try {
  254. db->exec("DROP TABLE IF EXISTS tcp_mss_dist");
  255. SQLite::Transaction transaction(*db);
  256. const char *createTable = "CREATE TABLE tcp_mss_dist ("
  257. "ipAddress TEXT,"
  258. "mssValue INTEGER,"
  259. "mssCount INTEGER,"
  260. "PRIMARY KEY(ipAddress,mssValue));";
  261. db->exec(createTable);
  262. SQLite::Statement query(*db, "INSERT INTO tcp_mss_dist VALUES (?, ?, ?)");
  263. for (auto it = mssDistribution.begin(); it != mssDistribution.end(); ++it) {
  264. ipAddress_mss e = it->first;
  265. query.bind(1, e.ipAddress);
  266. query.bind(2, e.mssValue);
  267. query.bind(3, it->second);
  268. query.exec();
  269. query.reset();
  270. }
  271. transaction.commit();
  272. }
  273. catch (std::exception &e) {
  274. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  275. }
  276. }
  277. // Aidamr
  278. /**
  279. * Writes the window size distribution into the database.
  280. * @param winDistribution The window size distribution from class statistics.
  281. */
  282. void statistics_db::writeStatisticsWin(std::unordered_map<ipAddress_win, int> winDistribution) {
  283. try {
  284. db->exec("DROP TABLE IF EXISTS tcp_syn_win");
  285. SQLite::Transaction transaction(*db);
  286. const char *createTable = "CREATE TABLE tcp_syn_win ("
  287. "ipAddress TEXT,"
  288. "winSize INTEGER,"
  289. "winCount INTEGER,"
  290. "PRIMARY KEY(ipAddress,winSize));";
  291. db->exec(createTable);
  292. SQLite::Statement query(*db, "INSERT INTO tcp_syn_win VALUES (?, ?, ?)");
  293. for (auto it = winDistribution.begin(); it != winDistribution.end(); ++it) {
  294. ipAddress_win e = it->first;
  295. query.bind(1, e.ipAddress);
  296. query.bind(2, e.winSize);
  297. query.bind(3, it->second);
  298. query.exec();
  299. query.reset();
  300. }
  301. transaction.commit();
  302. }
  303. catch (std::exception &e) {
  304. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  305. }
  306. }
  307. // Aidamr
  308. /**
  309. * Writes the conversation statistics into the database.
  310. * @param convStatistics The conversation from class statistics.
  311. */
  312. void statistics_db::writeStatisticsConv(std::unordered_map<conv, entry_convStat> convStatistics){
  313. try {
  314. db->exec("DROP TABLE IF EXISTS conv_statistics");
  315. SQLite::Transaction transaction(*db);
  316. const char *createTable = "CREATE TABLE conv_statistics ("
  317. "ipAddressA TEXT,"
  318. "portA INTEGER,"
  319. "ipAddressB TEXT,"
  320. "portB INTEGER,"
  321. "pkts_A_B INTEGER,"
  322. "pkts_B_A INTEGER,"
  323. "avgDelay INTEGER,"
  324. //"medianDelay TEXT,"
  325. "PRIMARY KEY(ipAddressA,portA,ipAddressB,portB));";
  326. db->exec(createTable);
  327. SQLite::Statement query(*db, "INSERT INTO conv_statistics VALUES (?, ?, ?, ?, ?, ?, ?)");
  328. for (auto it = convStatistics.begin(); it != convStatistics.end(); ++it) {
  329. conv f = it->first;
  330. entry_convStat e = it->second;
  331. // Compute the median delay
  332. //e.median_delay = e.pkts_delay[e.pkts_delay.size()/2];
  333. int sumDelay = 0;
  334. for(int i=0; (unsigned)i<e.pkts_delay.size();i++){
  335. sumDelay += e.pkts_delay[i].count();
  336. }
  337. if(e.pkts_delay.size()>0)
  338. e.avg_delay = (std::chrono::microseconds)sumDelay/e.pkts_delay.size(); // average
  339. else e.avg_delay = (std::chrono::microseconds)0;
  340. query.bind(1, f.ipAddressA);
  341. query.bind(2, f.portA);
  342. query.bind(3, f.ipAddressB);
  343. query.bind(4, f.portB);
  344. query.bind(5, (int) e.pkts_A_B);
  345. query.bind(6, (int) e.pkts_B_A);
  346. query.bind(7, (int) e.avg_delay.count());
  347. //query.bind(7, std::to_string(e.median_delay.count()));
  348. query.exec();
  349. query.reset();
  350. }
  351. transaction.commit();
  352. }
  353. catch (std::exception &e) {
  354. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  355. }
  356. }
  357. // Aidamr
  358. /**
  359. * Writes the interval statistics into the database.
  360. * @param intervalStatistics The interval entries from class statistics.
  361. */
  362. void statistics_db::writeStatisticsInterval(std::unordered_map<std::string, entry_intervalStat> intervalStatistics){
  363. try {
  364. db->exec("DROP TABLE IF EXISTS interval_statistics");
  365. SQLite::Transaction transaction(*db);
  366. const char *createTable = "CREATE TABLE interval_statistics ("
  367. "timestamp TEXT,"
  368. "pktsCount INTEGER,"
  369. "ipSrcEntropy REAL,"
  370. "ipDstEntropy REAL,"
  371. "ipSrcCumEntropy REAL,"
  372. "ipDstCumEntropy REAL,"
  373. "PRIMARY KEY(timestamp));";
  374. db->exec(createTable);
  375. SQLite::Statement query(*db, "INSERT INTO interval_statistics VALUES (?, ?, ?, ?, ?, ?)");
  376. for (auto it = intervalStatistics.begin(); it != intervalStatistics.end(); ++it) {
  377. std::string t = it->first;
  378. entry_intervalStat e = it->second;
  379. query.bind(1, t);
  380. query.bind(2, (int)e.pkts_count);
  381. query.bind(3, e.ip_src_entropy);
  382. query.bind(4, e.ip_dst_entropy);
  383. query.bind(5, e.ip_src_cum_entropy);
  384. query.bind(6, e.ip_dst_cum_entropy);
  385. query.exec();
  386. query.reset();
  387. }
  388. transaction.commit();
  389. }
  390. catch (std::exception &e) {
  391. std::cout << "Exception in statistics_db: " << e.what() << std::endl;
  392. }
  393. }