Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

GBUdb.hpp 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // GBUdb.hpp
  2. //
  3. // (C) Copyright 2006 - 2009 ARM Research Labs, LLC
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // Good, Bad, Ugly, Ignore IP database engine.
  7. ////////////////////////////////////////////////////////////////////////////////
  8. // Include M_GBUdb Only Once
  9. #ifndef M_GBUdb
  10. #define M_GBUdb
  11. #include "threading.hpp"
  12. #include <cmath>
  13. #include <cctype>
  14. #include <string>
  15. #include <sstream>
  16. #include <list>
  17. #include <cstdlib>
  18. using namespace std;
  19. const unsigned int GBUdbFlagsMask = 0xC0000000; // Top 2 bits are the flag.
  20. const unsigned int GBUdbIgnore = 0xC0000000; // Ignore is the 11 flag.
  21. const unsigned int GBUdbUgly = 0x00000000; // Ugly/Unknown is the 00 flag.
  22. const unsigned int GBUdbGood = 0x80000000; // Good is the 10 flag.
  23. const unsigned int GBUdbBad = 0x40000000; // Bad is the 01 flag.
  24. const unsigned int GBUdbGoodMask = 0x3FFF8000; // The good count is masked in this range.
  25. const unsigned int GBUdbBadMask = 0x00007FFF; // Tha bad count is masked here.
  26. const unsigned int GBUdbLimit = GBUdbBadMask; // When a count hits this, normalize in half.
  27. const unsigned int GBUdbGoodShift = 15; // Shift good counts this many bits.
  28. const unsigned int GBUdbMatchEntryBit = 0x80000000; // Match entry Index bit.
  29. const unsigned int GBUdbMatchUnusedBit = 0x40000000; // Unalocated Match entry Index bit.
  30. const unsigned int GBUdbMatchDataMask = 0x3fffffff; // IP Match data mask.
  31. enum GBUdbFlag { // A type for the GBUdb flag.
  32. Ignore = GBUdbIgnore, // Ignore
  33. Ugly = GBUdbUgly, // Ugly
  34. Good = GBUdbGood, // Good
  35. Bad = GBUdbBad // Bad
  36. };
  37. //// GBUdbLocking semantics
  38. //// When doForAllRecords() is called at the GBUdb level, we need to know how
  39. //// the GBUdb mutex should be handled.
  40. enum GBUdbLocking { // A type that describes locking semantics.
  41. Dataset, // Lock the through the entire operation.
  42. Record, // Lock and unlock for each record.
  43. None // Do not lock.
  44. };
  45. typedef unsigned int GBUdbIndex; // A type for Index values from records.
  46. const GBUdbIndex GBUdbUnknown = 0x00000000; // The unknown address.
  47. const int GBUdbRecordsPerNode = 256; // Records per node.
  48. const int GBUdbDefaultGrowNodes = 8192; // Default Nodes to grow.
  49. const int GBUdbDefaultArraySize = GBUdbRecordsPerNode * GBUdbDefaultGrowNodes; // Default initial Array size.
  50. const int GBUdbRootNodeOffset = 256; // First indexing node after node 0.
  51. const int GBUdbGrowthThreshold = 4; // Time to grow at this # free nodes.
  52. //// Node 0 is the go-nowhere node for when things fall off the index so it
  53. //// is coded to all GBUdbUnknown.
  54. //// The last node in the array is used for global statistics & allocation
  55. //// tables.
  56. const int GBUdbControlNodeOffset = -256; // Offset from end of data for control node.
  57. const int GBUdbNextFreeNodeOffset = GBUdbControlNodeOffset + 0; // Offset for next free node index.
  58. const int GBUdbMatchListOffset = GBUdbControlNodeOffset +1; // Offset for Match record allocation root.
  59. const int GBUdbIPCountOffset = GBUdbControlNodeOffset + 2; // Offset for count of IPs in GBUdb.
  60. // GBUdbRecord converts an ordinary unsigned long integer into a wealth of
  61. // useful information just by adding a collection of useful tools.
  62. class GBUdbRecord { // A GBUdb record is really just a
  63. public: // long integer, but it can be interpreted
  64. // lots of ways.
  65. unsigned int RawData; // The raw unsigned int goes here.
  66. GBUdbRecord(); // Initialize to zero.
  67. GBUdbFlag Flag(); // This returns the flag.
  68. GBUdbFlag Flag(GBUdbFlag f); // This sets and returns the flag.
  69. unsigned int Good(); // This returns the good count.
  70. unsigned int Good(unsigned int g); // This sets and returns the good count.
  71. unsigned int Bad(); // This returns the bad count.
  72. unsigned int Bad(unsigned int b); // This sets and returns the bad count.
  73. unsigned int addGood(unsigned int g = 1); // This increments the good count.
  74. unsigned int addBad(unsigned int b = 1); // This increments the bad count.
  75. GBUdbRecord& integrate(GBUdbRecord& A, int LocalWeight, int RemoteWeight); // This integrates another record.
  76. GBUdbIndex Index(); // This returns the record as an Index.
  77. GBUdbIndex Index(GBUdbIndex i); // This sets the record as an index.
  78. double Probability(); // Return +(bad) or -(good) probability.
  79. double Confidence(); // Return the confidence based on samples.
  80. };
  81. // Special events need to be recorded. For that job we have GBUdbAlerts
  82. const int UTCBufferSize = 16; // C string buffer size for UTC stamp.
  83. class GBUdbAlert {
  84. public:
  85. GBUdbAlert(); // Constructor sets timestamp & nulls.
  86. char UTC[UTCBufferSize]; // Time stamp for this alert.
  87. unsigned int IP; // IP for this alert.
  88. GBUdbRecord R; // GBUdbRecord for this alert.
  89. string toXML(); // Convert to an xml representation.
  90. };
  91. // Mass update kinds of operations are handled by providing a functor
  92. // of the type GBUdbOperator to the method doForAllRecords(). The functor is
  93. // called with every record in the GBUdb.
  94. //// Here is the virtual GBUdb Operator class.
  95. class GBUdbOperator {
  96. public:
  97. virtual GBUdbRecord& operator()(unsigned int IP, GBUdbRecord& R) = 0;
  98. };
  99. // GBUdbDataset manages a large array of GBUdb records and nodes. Nodes are
  100. // simulated data structures -- essentially arrays of GBUdbRecords that are
  101. // interpreted as Indexes so that each byte of a particular IP can be used
  102. // to follow the index through the tree to the final record that actually
  103. // represents the IPs data.
  104. // The last few records in the array are used to keep track of some basic
  105. // statistics including where the next node will come from. As with the GBUdb
  106. // record itself, it's all in how the data is interpreted. Using this strategy
  107. // of converting plain-old integers into various data types on the fly allows
  108. // us to allocate the entire structure as a single block and avoid much
  109. // page swapping behind the scenes.
  110. class GBUdbDataset {
  111. private:
  112. GBUdbRecord* DataArray; // Array of GBUdbRecords, nodes, etc.
  113. int MyArraySize; // The size of the array in records.
  114. string MyFileName; // CString for the file name.
  115. GBUdbIndex ixIPCount(); // Index of the IP count for this db.
  116. GBUdbIndex ixNextFreeNode(); // Index of the Next Free Node Index.
  117. GBUdbIndex ixMatchListRoot(); // Index of the Match List Root Index.
  118. GBUdbIndex newMatchRecord(unsigned int IP); // Allocate a new Match record for IP.
  119. GBUdbIndex newMatchNodeRoot(); // Allocate a new Match node.
  120. GBUdbIndex newNodeRoot(); // Allocates a new node, returns offset.
  121. void deleteMatchAt(GBUdbIndex I); // Recall match record at I for reuse.
  122. // invokeAt() Handles invocation at each node/octet using and managing MatchRecords as needed.
  123. GBUdbIndex invokeAt(GBUdbRecord& R, unsigned int IP, int Octet, bool ExtendMatches);
  124. int increaseIPCount(); // When we add an IP to the db.
  125. int decreaseIPCount(); // When we drop an IP from the db.
  126. void increaseIPCountIfNew(GBUdbRecord& R); // If R is GBUdbUnknown, IncreaseIPCount.
  127. bool isMatch(GBUdbIndex I); // True if record at I is a match record.
  128. bool isMatch(GBUdbIndex I, unsigned int IP); // True if record at I is a match for IP.
  129. GBUdbRecord& MatchedData(GBUdbIndex I); // Returns the data for the match at I.
  130. unsigned int EncodedMatch(unsigned int IP); // Returns encoded raw dat for a Match.
  131. //// In order to support binmodal indexing we must make sure that
  132. //// no octet3 data is mapped to the root record in an octet3 node. If
  133. //// it were so mapped then an octet2 evaluation might misinterpret the
  134. //// GBUdbFlag fields as a MatchRecord indicator and cause the data to
  135. //// become corrupted. To solve this problem, any time an octet2 node
  136. //// maps to an octet3 node and NOT a MatchRecord, the 0 record in the
  137. //// octet3 node must have no flags. Since x.x.x.0 is presumed to be the
  138. //// network address, and x.x.x.255 is presumed to be a broadcast address
  139. //// we cause both to map to a single record (the 255 record) where the
  140. //// Class C, B, or A data can be recorded and modified in safety. Since
  141. //// there is no need to track the brodcast and network address cases.
  142. //// separately there is no inherent conflict in this approach. The
  143. //// remapIP00toFF method performs this transform as needed in the
  144. //// readRecord() and invokeRecord() methods.
  145. unsigned int remapIP00toFF(unsigned int IP); // Remaps final octet 00 to FF if needed.
  146. GBUdbRecord MySafeUnknownRecord; // Safe unknown record to return.
  147. GBUdbRecord& SafeUnknownRecord(); // Clears and returns the Safe record.
  148. // doForAllNodes does its job by launching a recursive search algorythm
  149. // which is embodied in doAllAtNode(). The doAllAtNode() method is called
  150. // for the root node by doForAllRecords and searches through the tree depth
  151. // first to locate each active record in the GBUdb and call the Operator.
  152. // updateWorkingIP() uses progressive input from eacn level to determine
  153. // the effective IP for the node under test.
  154. void updateWorkingIP(unsigned int& WIP, int OctetValue, int Level);
  155. void doAllAtNode(GBUdbIndex I, GBUdbOperator& O, int NodeLevel, unsigned int WorkingIP);
  156. public:
  157. ~GBUdbDataset(); // Flush & shutdown a dataset.
  158. GBUdbDataset(const char* SetFileName); // Create with a name or no name (NULL).
  159. GBUdbDataset(GBUdbDataset& Original); // Copy constructor.
  160. class CouldNotGrow {}; // Thrown when grow() fails.
  161. class NoFreeNodes {}; // Thrown when newNodeRoot() fails.
  162. class MatchAllocationCorrupted {}; // Thrown when newMatchRecord() fails.
  163. GBUdbRecord& readRecord(unsigned int IP); // Read only - find a GBUdb record.
  164. GBUdbRecord& invokeRecord(unsigned int IP); // Create and/or Find a GBUdb record.
  165. bool dropRecord(unsigned int IP); // Drop an IP record. (true if we did)
  166. int ArraySize(); // Array size.
  167. int FreeNodes(); // Number of free nodes remaining.
  168. int IPCount(); // Number of IPs stored.
  169. const char* FileName(const char* NewName); // Set new file name w/ cstring.
  170. const char* FileName(); // Return the name.
  171. void grow(int HowManyNodes = GBUdbDefaultGrowNodes); // Grow (by number of nodes).
  172. void save(); // Flush the dataset to disk.
  173. void load(); // Read the dataset from disk.
  174. void doForAllRecords(GBUdbOperator& O); // Calls O(IP, Record) W/ every record.
  175. };
  176. // The GBUdb ojbect manages access to the GBUdb. For example, it will grow the
  177. // dataset when that is required, report new events, and generally serve as the
  178. // main access point for a given GBUdb. It even serializes multiple threads.
  179. //// Here is the actual GBUdb class.
  180. class GBUdb {
  181. private:
  182. Mutex MyMutex; // Data sync mutex.
  183. Mutex AlertsMutex; // Mutex for the alerts list.
  184. GBUdbDataset* MyDataset; // Array of records.
  185. int PostsCounter; // Counts good/bad posts.
  186. list<GBUdbAlert> MyAlerts; // Allerts list.
  187. void recordAlertFor(unsigned int IP, GBUdbRecord& R, unsigned int C); // Append an alert record if needed.
  188. public:
  189. GBUdb(); // Open/Create w/ no name.
  190. GBUdb(const char* FileName); // Open/Create w/ cstring or NULL.
  191. ~GBUdb(); // Shutdown
  192. const char* FileName(const char* NewName); // Set/Change the file name.
  193. const char* FileName(); // Return the FileName.
  194. void save(); // Save the data.
  195. void load(); // Load the data.
  196. GBUdbRecord addGood(unsigned int IP, int i = 1); // Count an IP as good.
  197. GBUdbRecord addBad(unsigned int IP, int i = 1); // Count an IP as bad.
  198. GBUdbRecord setGood(unsigned int IP); // Set the flag to Good for this IP.
  199. GBUdbRecord setBad(unsigned int IP); // Set the flag to Bad for this IP.
  200. GBUdbRecord setUgly(unsigned int IP); // Set the flag to Ugly for this IP.
  201. GBUdbRecord setIgnore(unsigned int IP); // Set the flag to Ignore for this IP.
  202. bool dropRecord(unsigned int IP); // Drop an IP record. (true if we did)
  203. GBUdbRecord getRecord(unsigned int IP); // Retrieve an IP record.
  204. GBUdbRecord setRecord(unsigned int IP, GBUdbRecord& R); // Store an IP record.
  205. GBUdbRecord adjustCounts(unsigned int IP, GBUdbRecord& R); // Adds counts from R to record for IP.
  206. void doForAllRecords(GBUdbOperator& O, GBUdbLocking L = Dataset); // Call the Operator w/ All records.
  207. void saveSnapshot(); // Saves a snapshot of the current db.
  208. void reduce(); // Reduce all counts by half.
  209. void compress(); // Remove any unknown records (reduced to zero).
  210. int readIgnoreList(const char* FileName = "GBUdbIgnoreList.txt"); // setIgnore for a list of IPs
  211. void GetAlerts(list<GBUdbAlert>& ListToFill); // Get all current alerts & clear.
  212. void ImportAlerts(list<GBUdbAlert>& PeerAlerts); // Default log2 alert import function.
  213. int IPCount(); // Number of IPs stored.
  214. int Size(); // Size of GBUdb in bytes.
  215. double Utilization(); // Utilization (percent).
  216. int Posts(); // Number of posts since last save.
  217. };
  218. //// Include inline method definitions /////////////////////////////////////////
  219. #include "GBUdb.inline.hpp"
  220. #endif
  221. // End of GBUdb Include Only Once
  222. ////////////////////////////////////////////////////////////////////////////////