You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

snfmultidll.cpp 37KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. // SNFMultiDLL.cpp
  2. // Copyright (C) ARM Research Labs, LLC
  3. //
  4. // Provides a full SNFMulti engine with dynamic scanner allocation.
  5. #include <windows.h>
  6. #include <stdexcept>
  7. #include <cmath>
  8. #include "../SNFMulti/snfmulti.hpp"
  9. using namespace std;
  10. const char* SNF_DLL_VERSION = "SNFMulti DLL Version 3.0 Build: " __DATE__ " " __TIME__;
  11. const int snf_ERROR_NO_HANDLE = -1;
  12. const int snf_ERROR_SCAN_FAILED = -2;
  13. const int snf_ERROR_EXCEPTION = -3;
  14. const double snf_ReputationMehResult = 0.0; /* Don't know or don't care */
  15. const double snf_ReputationBadResult = 1.0; /* IP is pure evil */
  16. const double snf_ReputationGoodResult = -1.0; /* IP is pure good */
  17. ////////////////////////////////////////////////////////////////////////////////
  18. // Here we define the interface provided by this DLL.
  19. #define EXP __declspec(dllexport)
  20. extern "C" {
  21. BOOL WINAPI DllMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved ); // Main DLL setup function.
  22. EXP int setThrottle(int Threads); // Set scan thread limit.
  23. EXP int startupSNF(char* Path); // Start SNF with configuration.
  24. EXP int startupSNFAuthenticated(char* Path, char* Lic, char* Auth); // Start SNF with conf & auth.
  25. EXP int shutdownSNF(); // Shutdown SNF.
  26. EXP int testIP(unsigned long int IPToCheck); // Test the IP for a GBUdb range.
  27. EXP double getIPReputation(unsigned long int IPToCheck); // Get reputation figure for IP.
  28. EXP int scanBuffer(unsigned char* Bfr, int Length, char* Name, int Setup); // Scan msgBuffer, name, setup time.
  29. EXP int scanFile(char* FilePath, int Setup); // Scan msgFile, setup time.
  30. EXP int getScanXHeaders(int ScanHandle, char** Bfr, int* Length); // Get result & XHeaders.
  31. EXP int getScanXMLLog(int ScanHandle, char** Bfr, int* Length); // Get result & XML Log.
  32. EXP int getScanClassicLog(int ScanHandle, char** Bfr, int* Length); // Get result & Classic Log.
  33. EXP int getScanResult(int ScanHandle); // Get just the scan result.
  34. EXP int closeScan(int ScanHandle); // Close the scan result.
  35. }
  36. ////////////////////////////////////////////////////////////////////////////////
  37. // Here are the guts of the engine.
  38. //
  39. // A ScannerInstance encapsulates an snf_EngineHandler and buffers for the
  40. // scan results. The buffers can safely be passed back to the calling app.
  41. class ScannerInstance : public snf_EngineHandler { // Scanner Instance.
  42. private:
  43. int Ordinal; // Instance ordinal.
  44. int ScanResult; // Current scan result.
  45. string ScanXHeaders; // Buffered X-Headers.
  46. char* ScanXHeadersPtr; // Buffered X-Headers pointer.
  47. int ScanXHeadersLength; // Buffered X-Headers length.
  48. string ScanXMLLog; // Buffered XML Log.
  49. char* ScanXMLLogPtr; // Buffered XML Log pointer.
  50. int ScanXMLLogLength; // Buffered XML Log length.
  51. string ScanClassicLog; // Buffered Classic Log.
  52. char* ScanClassicLogPtr; // Buffered Classic Log pointer.
  53. int ScanClassicLogLength; // Buffered Classic Log length.
  54. void clearBuffers(); // Clears the buffers & result.
  55. public:
  56. ScannerInstance(snf_RulebaseHandler* RBH, int N); // Initialize w/ Rulebase & Ordinal
  57. ~ScannerInstance(); // Cleanup before going away.
  58. int scanBuffer(unsigned char* Bfr, int Length, char* Name, int Setup); // Scan message buffer, give handle.
  59. int scanFile(char* FilePath, int Setup); // Scan message file, give handle.
  60. int getScanXHeaders(char** Bfr, int* Length); // Return scan result & X headers.
  61. int getScanXMLLog(char** Bfr, int* Length); // Return scan result & XML log.
  62. int getScanClassicLog(char** Bfr, int* Length); // Return scan result & Classic log.
  63. int getScanResult(); // Return scan result.
  64. };
  65. const int XHeaderReserve = 4096; // Space to reserve for X headers.
  66. const int XMLLogReserve = 4096; // Space to reserve for XML log data.
  67. const int ClassicReserve = 4096; // Space to reserve for Classic log data.
  68. ScannerInstance::ScannerInstance(snf_RulebaseHandler* RBH, int N) : // Initialize.
  69. Ordinal(N), // Ordinal as assigned.
  70. ScanResult(snf_ERROR_UNKNOWN), // No good result yet.
  71. ScanXHeaders(0,XHeaderReserve), // Pre-allocate some space for our
  72. ScanXMLLog(0, XMLLogReserve), // result caching buffers (strings)
  73. ScanClassicLog(0, ClassicReserve) { // so we might not have to later.
  74. clearBuffers(); // Clear the buffers.
  75. open(RBH); // Open the engine handler.
  76. }
  77. ScannerInstance::~ScannerInstance() { // When shutting down
  78. close(); // close the engine handler
  79. clearBuffers(); // and clear the buffers.
  80. Ordinal = -1; // Invalidate our handle.
  81. }
  82. // In the C world, 0 cannot be a handle, so when we return a "handle" from
  83. // our scanXX() methods we must convert the scanner's ordinal into a "handle"
  84. // by adding 1. Later on when we get a scanner by it's handle, that function
  85. // reverses the conversion by subtracting 1 from the handle to get the ordinal.
  86. int ScannerInstance::
  87. scanBuffer(unsigned char* Bfr, int Length, char* Name, int Setup) { // Scan a message buffer.
  88. try { // Prepare to capture exceptions.
  89. clearBuffers(); // Clear the buffers first.
  90. ScanResult = scanMessage(Bfr, Length, Name, Setup); // Scan and capture the result.
  91. } // Translate exceptions into
  92. catch(snf_EngineHandler::FileError& e) { // result codes and capture them.
  93. ScanResult = snf_ERROR_MSG_FILE;
  94. }
  95. catch(snf_EngineHandler::XHDRError& e) {
  96. ScanResult = snf_ERROR_MSG_FILE;
  97. }
  98. catch(snf_EngineHandler::BadMatrix& e) {
  99. ScanResult = snf_ERROR_BAD_MATRIX;
  100. }
  101. catch(snf_EngineHandler::MaxEvals& e) {
  102. ScanResult = snf_ERROR_MAX_EVALS;
  103. }
  104. catch(snf_EngineHandler::AllocationError& e) {
  105. ScanResult = snf_ERROR_ALLOCATION;
  106. }
  107. catch(...) {
  108. ScanResult = snf_ERROR_UNKNOWN;
  109. }
  110. return (Ordinal + 1); // Return our handle.
  111. }
  112. int ScannerInstance::
  113. scanFile(char* FilePath, int Setup) { // Scan a message file.
  114. try { // Prepare to capture exceptions.
  115. clearBuffers(); // Clear the buffers first.
  116. ScanResult = scanMessageFile(FilePath, Setup); // Scan and capture the result.
  117. } // Translate exceptions into
  118. catch(snf_EngineHandler::FileError& e) { // result codes and capture them.
  119. ScanResult = snf_ERROR_MSG_FILE;
  120. }
  121. catch(snf_EngineHandler::XHDRError& e) {
  122. ScanResult = snf_ERROR_MSG_FILE;
  123. }
  124. catch(snf_EngineHandler::BadMatrix& e) {
  125. ScanResult = snf_ERROR_BAD_MATRIX;
  126. }
  127. catch(snf_EngineHandler::MaxEvals& e) {
  128. ScanResult = snf_ERROR_MAX_EVALS;
  129. }
  130. catch(snf_EngineHandler::AllocationError& e) {
  131. ScanResult = snf_ERROR_ALLOCATION;
  132. }
  133. catch(...) {
  134. ScanResult = snf_ERROR_UNKNOWN;
  135. }
  136. return (Ordinal + 1); // Return our handle.
  137. }
  138. void ScannerInstance::clearBuffers() { // Clear the buffers.
  139. ScanXHeaders.clear(); // Clear the buffer strings
  140. ScanXHeadersPtr = 0; // zero their pointers and
  141. ScanXHeadersLength = 0; // zero their lengths.
  142. ScanXMLLog.clear();
  143. ScanXMLLogPtr = 0;
  144. ScanXMLLogLength = 0;
  145. ScanClassicLog.clear();
  146. ScanClassicLogPtr = 0;
  147. ScanClassicLogLength = 0;
  148. ScanResult = snf_ERROR_UNKNOWN;
  149. }
  150. int ScannerInstance::getScanXHeaders(char** Bfr, int* Length) { // Return the result & X headers.
  151. if(0 == ScanXHeadersPtr) { // If we haven't already then
  152. ScanXHeaders = getXHDRs(); // capture the data.
  153. ScanXHeadersLength = ScanXHeaders.length();
  154. ScanXHeadersPtr = const_cast<char*>(ScanXHeaders.c_str());
  155. }
  156. *Bfr = ScanXHeadersPtr; // Pass the pointer and
  157. *Length = ScanXHeadersLength; // length back to the caller.
  158. return ScanResult; // Return the scan result.
  159. }
  160. int ScannerInstance::getScanXMLLog(char** Bfr, int* Length) { // Return the result & XML log.
  161. if(0 == ScanXMLLogPtr) { // If we haven't already then
  162. ScanXMLLog = getXMLLog(); // capture the data.
  163. ScanXMLLogPtr = const_cast<char*>(ScanXMLLog.c_str());
  164. ScanXMLLogLength = ScanXMLLog.length();
  165. }
  166. *Bfr = ScanXMLLogPtr; // Pass the pointer and
  167. *Length = ScanXMLLogLength; // length back to the caller.
  168. return ScanResult; // Return the scan result.
  169. }
  170. int ScannerInstance::getScanClassicLog(char** Bfr, int* Length) { // Return the result & Classic log.
  171. if(0 == ScanClassicLogPtr) { // If we haven't already then
  172. ScanClassicLog = getClassicLog(); // capture the data.
  173. ScanClassicLogPtr = const_cast<char*>(ScanClassicLog.c_str());
  174. ScanClassicLogLength = ScanClassicLog.length();
  175. }
  176. *Bfr = ScanClassicLogPtr; // Pass the pointer and
  177. *Length = ScanClassicLogLength; // length back to the caller.
  178. return ScanResult; // Return the scan result.
  179. }
  180. int ScannerInstance::getScanResult() { // Return the scan result only.
  181. return ScanResult; // Just like that.
  182. }
  183. // The snfScannerPool starts up and shuts down the rulebase engine and keeps
  184. // track of the ScannerInstances.
  185. class snfScannerPool { // Dynamically allocated scanner pool.
  186. private:
  187. codedweller::Mutex myMutex; // Protect the state of the pool.
  188. snf_RulebaseHandler* myRulebaseHandler; // This is our rulebase manager.
  189. vector<ScannerInstance*> ScannerPool; // This is a collection of scanners.
  190. codedweller::ProductionQueue<ScannerInstance*> AvailableScanners; // This is the available scanners queue.
  191. unsigned int ScanThreadLimit; // Maximum number of concurrent threads.
  192. public:
  193. snfScannerPool(); // This is how we are constructed.
  194. ~snfScannerPool(); // This is how we are destroyed.
  195. void Throttle(int ThreadLimit); // Set a Scan Thread Limit.
  196. void startup(char* ConfigurationPath); // Startup the engine w/ config.
  197. void startupAuthenticated(char* Path, char* Lic, char* Auth); // Startup engine w/ full auth.
  198. void shutdown(); // Shutdown the engine.
  199. int testIP(unsigned long int IPToCheck); // Test an IP against gbudb.
  200. double getIPReputation(unsigned long int IPToCheck); // This is how we get IP reps.
  201. ScannerInstance* grabScanner(); // Get a new (available) scanner.
  202. ScannerInstance* getScanner(int ScanHandle); // What scanner goes with this handle?
  203. void dropScanner(ScannerInstance* S); // When done with a scanner, drop it.
  204. };
  205. snfScannerPool Scanners; // Call our local pool "Scanners".
  206. snfScannerPool::snfScannerPool() : // When created, our
  207. myRulebaseHandler(0), // rulebase handler is 0.
  208. ScanThreadLimit(0) {} // There is no limit.
  209. snfScannerPool::~snfScannerPool() { // When destroyed we must
  210. shutdown(); // shutdown if needed.
  211. }
  212. void snfScannerPool::Throttle(int ThreadLimit) { // Set a scanner thread limit.
  213. ThreadLimit = (0 > ThreadLimit) ? 0 : ThreadLimit; // Throttle will be 0 or above.
  214. ScanThreadLimit = ThreadLimit;
  215. }
  216. void snfScannerPool::startup(char* ConfigurationPath) { // Start the engine with this config.
  217. codedweller::ScopeMutex StateIsInFlux(myMutex); // Protect our state data.
  218. if(myRulebaseHandler) return; // If we are started, do nothing.
  219. myRulebaseHandler = new snf_RulebaseHandler(); // Create a new rulebase handler.
  220. myRulebaseHandler->PlatformVersion(SNF_DLL_VERSION); // Record our version identification.
  221. myRulebaseHandler->open(ConfigurationPath, "", ""); // Open the rulebase with the config.
  222. }
  223. void snfScannerPool::startupAuthenticated(char* Path, char* Lic, char* Auth) { // Startup engine w/ full auth.
  224. codedweller::ScopeMutex StateIsInFlux(myMutex); // Protect our state data.
  225. if(myRulebaseHandler) return; // If we are started, do nothing.
  226. myRulebaseHandler = new snf_RulebaseHandler(); // Create a new rulebase handler.
  227. myRulebaseHandler->PlatformVersion(SNF_DLL_VERSION); // Record our version identification.
  228. myRulebaseHandler->open(Path, Lic, Auth); // Open rulebase with full auth.
  229. }
  230. void snfScannerPool::shutdown() { // Shutdown the engine.
  231. codedweller::ScopeMutex StateIsInFlux(myMutex); // Protect our state data.
  232. if(
  233. 0 == ScannerPool.size() &&
  234. 0 == AvailableScanners.size() &&
  235. 0 == myRulebaseHandler
  236. ) return; // If we are down don't bother.
  237. if(ScannerPool.size() != AvailableScanners.size()) throw false; // If some scanners are in use throw!
  238. for(
  239. vector<ScannerInstance*>::iterator iS = ScannerPool.begin(); // Destroy all of the scanner
  240. iS != ScannerPool.end(); // instances in the pool.
  241. iS++) delete (*iS);
  242. ScannerPool.clear(); // Empty the pool of pointers.
  243. while(0 < AvailableScanners.size()) AvailableScanners.take(); // Empty the available scanners.
  244. if(myRulebaseHandler) { // Safely destroy the rulebase handler.
  245. myRulebaseHandler->close(); // Close it first,
  246. delete myRulebaseHandler; // then delete it,
  247. myRulebaseHandler = 0; // then forget about it.
  248. }
  249. }
  250. int snfScannerPool::testIP(unsigned long int IPToCheck) { // This is how we test IPs.
  251. codedweller::ScopeMutex StayAsYouAre(myMutex); // Hold things steady while we do this.
  252. if(0 == myRulebaseHandler) return snf_ERROR_NO_HANDLE; // If we have no engine, punt!
  253. IPTestRecord Tester(IPToCheck); // Make up a test record for this IP.
  254. myRulebaseHandler->performIPTest(Tester); // Run it past the engine.
  255. return Tester.R; // IPRange is an enum, so use as an int.
  256. }
  257. double snfScannerPool::getIPReputation(unsigned long int IPToCheck) { // This is how we get IP reps.
  258. codedweller::ScopeMutex StayAsYouAre(myMutex); // Hold things steady while we do this.
  259. if(0 == myRulebaseHandler) return snf_ERROR_NO_HANDLE; // If we have no engine, punt!
  260. IPTestRecord Tester(IPToCheck); // Make up a test record for this IP.
  261. myRulebaseHandler->performIPTest(Tester); // Run it past the engine.
  262. // Now that we have a result from the engine let's translate the result.
  263. double Reputation = snf_ReputationMehResult; // Reputation figures are precise.
  264. switch(Tester.G.Flag()) { // Flags get priority in our translation.
  265. case Good: Reputation = snf_ReputationGoodResult; break; // A good flag means the IP is pure good.
  266. case Bad: Reputation = snf_ReputationBadResult; break; // A bad flag means the IP is pure evil.
  267. case Ignore: Reputation = snf_ReputationMehResult; break; // An ignore flag means we don't care.
  268. default: { // Ugly means we calculate the reputation
  269. Reputation = // figure from the statistics. Start by
  270. sqrt(fabs(Tester.G.Probability() * Tester.G.Confidence())); // combining the c & p figures then
  271. if(0 > Tester.G.Probability()) Reputation *= -1.0; // flip the sign if p is negative.
  272. }
  273. }
  274. return Reputation; // This is what we say about this IP.
  275. }
  276. // In order to balance off speed and safety we control access when starting
  277. // up, shutting down, or getting a new scanner. The grabScanner operation is
  278. // usually very fast.
  279. //
  280. // The the calling application behaves properly it will never attempt a scan
  281. // while attempting to shutdown, and will never attempt to shutdown while it
  282. // is performing a scan. If this conflict does occur then one of two cases
  283. // arise:
  284. //
  285. // The shutdown() thread grabs the mutex before the grabScanner() thread,
  286. // the engine is shutdown, then the grabScanner() thread finds the engine
  287. // is down and cannot return a scanner.
  288. //
  289. // The grabScanner() thread gets the mutex before the shutdown() thread,
  290. // a scanner is allocated, and the shutdown() thread discovers an imabalance
  291. // in the number of Available scanners and the number of scanners in the pool.
  292. // When it discovers that it will throw false and the C interface function will
  293. // return an error.
  294. ScannerInstance* snfScannerPool::grabScanner() { // Get the next available scanner.
  295. codedweller::ScopeMutex FreezeOurState(myMutex); // Don't change while I'm doing this.
  296. if(0 == myRulebaseHandler) return 0; // If we're not alive return nothing.
  297. if(1 > AvailableScanners.size()) { // No scanners? See about making one.
  298. if(
  299. 0 == ScanThreadLimit || // If there is no limit OR
  300. ScanThreadLimit > ScannerPool.size() // we have room for more scanners
  301. ) { // then we can make another one:
  302. ScannerInstance* NewScanner =
  303. new ScannerInstance(myRulebaseHandler, ScannerPool.size()); // Start up a new scanner and
  304. ScannerPool.push_back(NewScanner); // add it to the pool.
  305. AvailableScanners.give(NewScanner); // Make the new scanner available.
  306. } // If we have reached the limit on
  307. } // scanners we will wait for one.
  308. return AvailableScanners.take(); // Get a scanner from the pool.
  309. }
  310. // Since handles are one bigger than the ordinal (so 0 isn't a handle)
  311. // we must convert the ScanHandle we're given into a proper ordinal so
  312. // we can match the scanner's position in the pool. The reverse happens
  313. // upon scan requestes.
  314. ScannerInstance* snfScannerPool::getScanner(int ScanHandle) { // Get the scanner for this handle.
  315. ScannerInstance* S = 0; // We're gonna get a scanner.
  316. try { S = ScannerPool.at(ScanHandle - 1); } // Safely get the scanner at Ordinal.
  317. catch(...) { return 0; } // If something goes wrong, no scanner.
  318. return S; // Return the scanner we got.
  319. }
  320. void snfScannerPool::dropScanner(ScannerInstance* S) { // When done with a scanner, drop it.
  321. if( // If :
  322. 0 != S && // - we have a good scanner pointer and
  323. 0 != myRulebaseHandler // - we are not dead yet
  324. ) AvailableScanners.give(S); // then make the scanner available.
  325. }
  326. ////////////////////////////////////////////////////////////////////////////////
  327. // Interface Functions
  328. BOOL WINAPI DLLMain ( HINSTANCE hInst, DWORD wDataSeg, LPVOID lpvReserved ) {
  329. try {
  330. switch(wDataSeg) { // Handle setup & teardown msgs.
  331. case DLL_PROCESS_ATTACH: // If the DLL is being loaded
  332. return true; // return true. Nothing to do yet.
  333. break;
  334. case DLL_PROCESS_DETACH: // If the DLL is being dropped
  335. Scanners.shutdown(); // be sure we are shut down first.
  336. break;
  337. default: // For all other messages (thread stuff)
  338. return true; // we'll just return ok because
  339. break; // we don't have any of that here.
  340. }
  341. }
  342. catch(...) {}; // Do not throw exceptions.
  343. // We won't actually get here but we
  344. return false; // want to make the compiler happy :-)
  345. }
  346. EXP int setThrottle(int Threads) { // Set scan thread limit.
  347. try {
  348. Scanners.Throttle(Threads); // Set the throttle limit
  349. }
  350. catch(...) { return snf_ERROR_EXCEPTION; }
  351. return Threads; // and return the value.
  352. }
  353. EXP int startupSNF(char* Path) { // Start the engine.
  354. try { // Use a try block to translate
  355. Scanners.startup(Path); // exceptions into result codes.
  356. }
  357. catch(snf_RulebaseHandler::AuthenticationError &e) { // Catch and translage exceptions.
  358. return snf_ERROR_RULE_AUTH;
  359. }
  360. catch(snf_RulebaseHandler::AllocationError& e) {
  361. return snf_ERROR_ALLOCATION;
  362. }
  363. catch(snf_RulebaseHandler::FileError& e) {
  364. return snf_ERROR_RULE_FILE;
  365. }
  366. catch(...) {
  367. return snf_ERROR_EXCEPTION;
  368. }
  369. return snf_SUCCESS; // No exceptions, All happy :-)
  370. }
  371. EXP int startupSNFAuthenticated(char* Path, char* Lic, char* Auth) { // Start SNF with conf & auth.
  372. try { // Use a try block to translate
  373. Scanners.startupAuthenticated(Path, Lic, Auth); // exceptions into result codes.
  374. }
  375. catch(snf_RulebaseHandler::AuthenticationError &e) { // Catch and translage exceptions.
  376. return snf_ERROR_RULE_AUTH;
  377. }
  378. catch(snf_RulebaseHandler::AllocationError& e) {
  379. return snf_ERROR_ALLOCATION;
  380. }
  381. catch(snf_RulebaseHandler::FileError& e) {
  382. return snf_ERROR_RULE_FILE;
  383. }
  384. catch(...) {
  385. return snf_ERROR_EXCEPTION;
  386. }
  387. return snf_SUCCESS; // No exceptions, All happy :-)
  388. }
  389. EXP int shutdownSNF() { // Shut down the engine.
  390. try { // Use a try block to translate
  391. Scanners.shutdown(); // exceptions into result codes.
  392. }
  393. catch(snf_RulebaseHandler::AuthenticationError &e) { // Catch and translage exceptions.
  394. return snf_ERROR_RULE_AUTH;
  395. }
  396. catch(snf_RulebaseHandler::AllocationError& e) {
  397. return snf_ERROR_ALLOCATION;
  398. }
  399. catch(snf_RulebaseHandler::FileError& e) {
  400. return snf_ERROR_RULE_FILE;
  401. }
  402. catch(...) {
  403. return snf_ERROR_EXCEPTION;
  404. }
  405. return snf_SUCCESS; // No exceptions, All happy :-)
  406. }
  407. EXP int testIP(unsigned long int IPToCheck) { // Test the IP for a GBUdb range.
  408. int Result = snf_ERROR_EXCEPTION; // On panics return this.
  409. try {
  410. Result = Scanners.testIP(IPToCheck); // Testing an IP is easy.
  411. }
  412. catch(...) {} // Do not throw exceptions.
  413. return Result; // Return the result.
  414. }
  415. EXP double getIPReputation(unsigned long int IPToCheck) { // Get reputation figure for IP.
  416. double Result = snf_ReputationMehResult; // On panics return this.
  417. try {
  418. Result = Scanners.getIPReputation(IPToCheck); // Getting an IP rep is easy.
  419. }
  420. catch(...) {} // Do not throw exceptions.
  421. return Result; // Return the result.
  422. }
  423. EXP int scanBuffer(unsigned char* Bfr, int Length, char* Name, int Setup) { // Scan a message.
  424. ScannerInstance* myScanner = 0; // We need a scanner.
  425. try { myScanner = Scanners.grabScanner(); } // Safely get a scanner.
  426. catch(...) { return snf_ERROR_NO_HANDLE; } // If that fails, we're done.
  427. int ScannerHandle = snf_ERROR_NO_HANDLE; // We will return a handle.
  428. try { ScannerHandle = myScanner->scanBuffer(Bfr, Length, Name, Setup); } // Perform the scan.
  429. catch(...) { // If we get an unhandled
  430. Scanners.dropScanner(myScanner); // exception then drop the
  431. return snf_ERROR_SCAN_FAILED; // scanner and return the failure.
  432. } // If all goes well then
  433. return ScannerHandle; // return our scanner's handle.
  434. }
  435. EXP int scanFile(char* FilePath, int Setup) {
  436. ScannerInstance* myScanner = 0; // We need a scanner.
  437. try { myScanner = Scanners.grabScanner(); } // Safely get a scanner.
  438. catch(...) { return snf_ERROR_NO_HANDLE; } // If that fails, we're done.
  439. int ScannerHandle = snf_ERROR_NO_HANDLE; // We will return a handle.
  440. try { ScannerHandle = myScanner->scanFile(FilePath, Setup); } // Perform the scan.
  441. catch(...) { // If we get an unhandled
  442. Scanners.dropScanner(myScanner); // exception then drop the
  443. return snf_ERROR_SCAN_FAILED; // scanner and return the failure.
  444. } // If all goes well then
  445. return ScannerHandle; // return our scanner's handle.
  446. }
  447. EXP int getScanXHeaders(int ScanHandle, char** Bfr, int* Length) { // Return the XHeaders for a scan.
  448. ScannerInstance* myScanner = 0; // We need the scanner.
  449. try { myScanner = Scanners.getScanner(ScanHandle); } // Try to get the scanner by handle.
  450. catch(...) { return snf_ERROR_NO_HANDLE; } // If we can't, we're broken.
  451. if(0 == myScanner) return snf_ERROR_NO_HANDLE; // A zero pointer is also broken.
  452. int Result = snf_ERROR_EXCEPTION; // On panic return this error code.
  453. try {
  454. Result = myScanner->getScanXHeaders(Bfr, Length); // If we can, get our data.
  455. }
  456. catch(...) {} // Do not throw exceptions.
  457. return Result; // Return our result.
  458. }
  459. EXP int getScanXMLLog(int ScanHandle, char** Bfr, int* Length) { // Return the XML Log for a scan.
  460. ScannerInstance* myScanner = 0; // We need the scanner.
  461. try { myScanner = Scanners.getScanner(ScanHandle); } // Try to get the scanner by handle.
  462. catch(...) { return snf_ERROR_NO_HANDLE; } // If we can't, we're broken.
  463. if(0 == myScanner) return snf_ERROR_NO_HANDLE; // A zero pointer is also broken.
  464. int Result = snf_ERROR_EXCEPTION; // On panic return this error code.
  465. try {
  466. Result = myScanner->getScanXMLLog(Bfr, Length); // If we can, get our data.
  467. }
  468. catch(...) {} // Do not throw exceptions.
  469. return Result; // Return our result.
  470. }
  471. EXP int getScanClassicLog(int ScanHandle, char** Bfr, int* Length) { // Return the classic log for a scan.
  472. ScannerInstance* myScanner = 0; // We need the scanner.
  473. try { myScanner = Scanners.getScanner(ScanHandle); } // Try to get the scanner by handle.
  474. catch(...) { return snf_ERROR_NO_HANDLE; } // If we can't we're broken.
  475. if(0 == myScanner) return snf_ERROR_NO_HANDLE; // A zero pointer is also broken.
  476. int Result = snf_ERROR_EXCEPTION; // On panic return this error code.
  477. try {
  478. Result = myScanner->getScanClassicLog(Bfr, Length); // If we can, get our data.
  479. }
  480. catch(...) {} // Do not throw exceptions.
  481. return Result; // Return our result.
  482. }
  483. EXP int getScanResult(int ScanHandle) { // Return just the scan result.
  484. ScannerInstance* myScanner = 0; // We need the scanner.
  485. try { myScanner = Scanners.getScanner(ScanHandle); } // Try to get the scanner by handle.
  486. catch(...) { return snf_ERROR_NO_HANDLE; } // If we can't we're broken.
  487. if(0 == myScanner) return snf_ERROR_NO_HANDLE; // A zero pointer is also broken.
  488. return myScanner->getScanResult(); // If we can, get our data.
  489. }
  490. EXP int closeScan(int ScanHandle) { // Return the scanner to the pool.
  491. ScannerInstance* myScanner = 0; // We need the scanner.
  492. try { myScanner = Scanners.getScanner(ScanHandle); } // Try to get the scanner by handle.
  493. catch(...) { return snf_ERROR_NO_HANDLE; } // If we can't we're broken.
  494. if(0 == myScanner) return snf_ERROR_NO_HANDLE; // A zero pointer is also broken.
  495. try { Scanners.dropScanner(myScanner); } // If we can then drop the scanner.
  496. catch(...) { return snf_ERROR_EXCEPTION; } // Convert exceptions to a panic code.
  497. return snf_SUCCESS; // If all ok then return success.
  498. }