// Convert the RangeEvaluation into the configured Code | // Convert the RangeEvaluation into the configured Code | ||||
switch(I.R) { | switch(I.R) { | ||||
case Unknown: // Unknown - not defined. | |||||
case Normal: // Benefit of the doubt. | |||||
case New: { // It is new to us. | |||||
case snfIPRange::Unknown: // Unknown - not defined. | |||||
case snfIPRange::Normal: // Benefit of the doubt. | |||||
case snfIPRange::New: { // It is new to us. | |||||
I.Code = 0; // Zero is the default - no code. | I.Code = 0; // Zero is the default - no code. | ||||
break; | break; | ||||
} | } | ||||
case White: { // This is a good guy. | |||||
case snfIPRange::White: { // This is a good guy. | |||||
I.Code = MyCFGPacket.Config()->WhiteRangeHandler.Symbol; | I.Code = MyCFGPacket.Config()->WhiteRangeHandler.Symbol; | ||||
break; | break; | ||||
} | } | ||||
case Caution: { // This is suspicious. | |||||
case snfIPRange::Caution: { // This is suspicious. | |||||
I.Code = MyCFGPacket.Config()->CautionRangeHandler.Symbol; | I.Code = MyCFGPacket.Config()->CautionRangeHandler.Symbol; | ||||
break; | break; | ||||
} | } | ||||
case Black: { // This is bad. | |||||
case snfIPRange::Black: { // This is bad. | |||||
I.Code = MyCFGPacket.Config()->BlackRangeHandler.Symbol; | I.Code = MyCFGPacket.Config()->BlackRangeHandler.Symbol; | ||||
break; | break; | ||||
} | } | ||||
case Truncate: { // Don't even bother looking. | |||||
case snfIPRange::Truncate: { // Don't even bother looking. | |||||
I.Code = MyCFGPacket.Config() | I.Code = MyCFGPacket.Config() | ||||
->gbudb_regions_black_truncate_symbol; | ->gbudb_regions_black_truncate_symbol; | ||||
break; | break; | ||||
// We will also emit a range identifier for pattern matches that might use it. | // We will also emit a range identifier for pattern matches that might use it. | ||||
switch(IPR) { | switch(IPR) { | ||||
case Unknown: { S << " Unknown"; break; } // Unknown - not defined. | |||||
case White: { S << " White"; break; } // This is a good guy. | |||||
case Normal: { S << " Normal"; break; } // Benefit of the doubt. | |||||
case New: { S << " New"; break; } // It is new to us. | |||||
case Caution: { S << " Caution"; break; } // This is suspicious. | |||||
case Black: { S << " Black"; break; } // This is bad. | |||||
case Truncate: { S << " Truncate"; break; } // Don't even bother looking. | |||||
case snfIPRange::Unknown: { S << " Unknown"; break; } // Unknown - not defined. | |||||
case snfIPRange::White: { S << " White"; break; } // This is a good guy. | |||||
case snfIPRange::Normal: { S << " Normal"; break; } // Benefit of the doubt. | |||||
case snfIPRange::New: { S << " New"; break; } // It is new to us. | |||||
case snfIPRange::Caution: { S << " Caution"; break; } // This is suspicious. | |||||
case snfIPRange::Black: { S << " Black"; break; } // This is bad. | |||||
case snfIPRange::Truncate: { S << " Truncate"; break; } // Don't even bother looking. | |||||
} | } | ||||
ScanData->SourceIPEvaluation = S.str(); // Capture the source IP eval. | ScanData->SourceIPEvaluation = S.str(); // Capture the source IP eval. | ||||
// range. If the Good flag is set the function always returns White so | // range. If the Good flag is set the function always returns White so | ||||
// here we only have to check for the Truncate flag. | // here we only have to check for the Truncate flag. | ||||
if(Truncate == IPR) { // If all of the conditions are met | |||||
if(snfIPRange::Truncate == IPR) { // If all of the conditions are met | |||||
ScanData->GBUdbTruncateTriggered = true; // then Truncate has been triggered. | ScanData->GBUdbTruncateTriggered = true; // then Truncate has been triggered. | ||||
ScanData->GBUdbPeekTriggered = LOGmgr->OkToPeek( // Since truncate was triggered, see if | ScanData->GBUdbPeekTriggered = LOGmgr->OkToPeek( // Since truncate was triggered, see if | ||||
CFGData->gbudb_regions_black_truncate_peek_one_in); // we would also trigger a peek. | CFGData->gbudb_regions_black_truncate_peek_one_in); // we would also trigger a peek. | ||||
switch(MyScanData.SourceIPRange()) { | switch(MyScanData.SourceIPRange()) { | ||||
case White: { // If the IP was in the white zone | |||||
case snfIPRange::White: { // If the IP was in the white zone | |||||
MyScanData.GBUdbWhiteTriggered = true; // mark that down. | MyScanData.GBUdbWhiteTriggered = true; // mark that down. | ||||
if(MyCFGPacket.Config()->WhiteRangeHandler.On_Off) { // If we're also turned on then | if(MyCFGPacket.Config()->WhiteRangeHandler.On_Off) { // If we're also turned on then | ||||
if( // do we need to force the symbol? | if( // do we need to force the symbol? | ||||
break; | break; | ||||
} | } | ||||
case Normal: { // If the IP is normal... | |||||
case snfIPRange::Normal: { // If the IP is normal... | |||||
MyScanData.GBUdbNormalTriggered = true; // Count the event. | MyScanData.GBUdbNormalTriggered = true; // Count the event. | ||||
break; // That's all. | break; // That's all. | ||||
} | } | ||||
case New: { | |||||
case snfIPRange::New: { | |||||
break; | break; | ||||
} | } | ||||
case Caution: { // If the IP is in the caution range. | |||||
case snfIPRange::Caution: { // If the IP is in the caution range. | |||||
MyScanData.GBUdbCautionTriggered = true; // Track that this range fired. | MyScanData.GBUdbCautionTriggered = true; // Track that this range fired. | ||||
if( | if( | ||||
MyCFGPacket.Config()->CautionRangeHandler.On_Off && // If we're also turned on and there | MyCFGPacket.Config()->CautionRangeHandler.On_Off && // If we're also turned on and there | ||||
// peek cases or if Truncate is turned off then Truncate might not | // peek cases or if Truncate is turned off then Truncate might not | ||||
// execute-- when that happens we need to fall back to Black behavior. | // execute-- when that happens we need to fall back to Black behavior. | ||||
case Truncate: // If the IP was in the truncate range | |||||
case Black: { // and/or If the IP is in the black range | |||||
case snfIPRange::Truncate: // If the IP was in the truncate range | |||||
case snfIPRange::Black: { // and/or If the IP is in the black range | |||||
MyScanData.GBUdbBlackTriggered = true; // mark that down. | MyScanData.GBUdbBlackTriggered = true; // mark that down. | ||||
if(MyScanData.GBUdbTruncateExecuted) { // If the truncate action was executed | if(MyScanData.GBUdbTruncateExecuted) { // If the truncate action was executed | ||||
break; | break; | ||||
} | } | ||||
case Unknown: // Unknown - most likely we couldn't | |||||
case snfIPRange::Unknown: // Unknown - most likely we couldn't | |||||
default: { // find a usable source. | default: { // find a usable source. | ||||
break; // Do nothing. | break; // Do nothing. | ||||
} | } |
snfIPRange snfCFGData::RangeEvaluation(GBUdbRecord& R) { // Returns the range for a GBUdbRecord. | snfIPRange snfCFGData::RangeEvaluation(GBUdbRecord& R) { // Returns the range for a GBUdbRecord. | ||||
if(Good == R.Flag()) { // If the flag on the IP is Good | if(Good == R.Flag()) { // If the flag on the IP is Good | ||||
return White; // then this IP is automatically white. | |||||
return snfIPRange::White; // then this IP is automatically white. | |||||
} else | } else | ||||
if(Bad == R.Flag()) { // If the flag on this IP is Bad | if(Bad == R.Flag()) { // If the flag on this IP is Bad | ||||
if(true == gbudb_regions_black_truncate_on_off) { // and truncate is turned on then | if(true == gbudb_regions_black_truncate_on_off) { // and truncate is turned on then | ||||
return Truncate; // the IP is automatically in the | |||||
return snfIPRange::Truncate; // the IP is automatically in the | |||||
} else { // truncate range. If truncate is off | } else { // truncate range. If truncate is off | ||||
return Black; // then this IP is automatically black. | |||||
return snfIPRange::Black; // then this IP is automatically black. | |||||
} | } | ||||
} | } | ||||
// If it's not so simple then get a | // If it's not so simple then get a | ||||
0.0 == p.Confidence && // by a zero confidence and | 0.0 == p.Confidence && // by a zero confidence and | ||||
0.0 == p.Probability // a zero probability, then | 0.0 == p.Probability // a zero probability, then | ||||
) { // the range point cannot be "in" | ) { // the range point cannot be "in" | ||||
return New; // any range. | |||||
return snfIPRange::New; // any range. | |||||
} | } | ||||
if(WhiteRangeHandler.isInWhite(p)) { // If it's in the white range, | if(WhiteRangeHandler.isInWhite(p)) { // If it's in the white range, | ||||
return White; // return White. | |||||
return snfIPRange::White; // return White. | |||||
} else // White has priority over all others. | } else // White has priority over all others. | ||||
if(BlackRangeHandler.isInBlack(p)) { // If it's in the black range then | if(BlackRangeHandler.isInBlack(p)) { // If it's in the black range then | ||||
if(p.Probability >= gbudb_regions_black_truncate_probability) { // determine if it's also in the truncate | if(p.Probability >= gbudb_regions_black_truncate_probability) { // determine if it's also in the truncate | ||||
return Truncate; // range, and if so - send back Truncate. | |||||
return snfIPRange::Truncate; // range, and if so - send back Truncate. | |||||
} else { // If not then we can send back a | } else { // If not then we can send back a | ||||
return Black; // normal black result. | |||||
return snfIPRange::Black; // normal black result. | |||||
} | } | ||||
} else // Black takes precedence over caution. | } else // Black takes precedence over caution. | ||||
if(CautionRangeHandler.isInBlack(p)) { // If we're in the caution range | if(CautionRangeHandler.isInBlack(p)) { // If we're in the caution range | ||||
return Caution; // then return caution. | |||||
return snfIPRange::Caution; // then return caution. | |||||
} // If none of those ranges matched then | } // If none of those ranges matched then | ||||
return Normal; // the IP is in the normal range. | |||||
return snfIPRange::Normal; // the IP is in the normal range. | |||||
} | } | ||||
//// snfCFGmgr ///////////////////////////////////////////////////////////////// | //// snfCFGmgr ///////////////////////////////////////////////////////////////// | ||||
InitLicenseId = (NULL==LicenseId)?"":LicenseId; // any time load() is called. | InitLicenseId = (NULL==LicenseId)?"":LicenseId; // any time load() is called. | ||||
InitAuthentication = (NULL==Authentication)?"":Authentication; | InitAuthentication = (NULL==Authentication)?"":Authentication; | ||||
} | } | ||||
//***************************************************************************** | |||||
//// IMPORTANT: If the authentication string is provided in the initialize() it | |||||
//// MUST NOT be put into D.node_authentication. | |||||
//***************************************************************************** | |||||
//// When the license ID and security string come from an OEM application they | |||||
//// may not appear in the configuration files. If that is the case we will assume | |||||
//// that they developer wants to keep the security string secret by encrypting it | |||||
//// in their application and providing it to SNF at runtime. In that case we will | |||||
//// not display the security key in the configuration log. | |||||
//// | |||||
//// To prevent hacking attempts, if the authentication information appears to be | |||||
//// provided by configuration data then we will build the string from that data. | |||||
//// that way an attacker can't trick the application into disclosing the true | |||||
//// authentication string -- they will only get out what they put in. | |||||
string SecurityKeyDisplayString(snfCFGData& D) { // Returns appropriate SecurityKey: data | |||||
string ConfigLogSecurityKey = "************************"; // Start with a masked display. | |||||
if(0 < D.node_authentication.length()) { // If auth info is in the config files then | |||||
ConfigLogSecurityKey = D.node_licenseid + D.node_authentication; // build up the key from that data so it | |||||
} // can be displayed in the config log. | |||||
return ConfigLogSecurityKey; | |||||
} | |||||
//***************************************************************************** | |||||
//// IMPORTANT: If the authentication string is provided in the initialize() it | |||||
//// MUST NOT be put into D.node_authentication. | |||||
//***************************************************************************** | |||||
//// When the license ID and security string come from an OEM application they | |||||
//// may not appear in the configuration files. If that is the case we will assume | |||||
//// that they developer wants to keep the security string secret by encrypting it | |||||
//// in their application and providing it to SNF at runtime. In that case we will | |||||
//// not display the security key in the configuration log. | |||||
//// | |||||
//// To prevent hacking attempts, if the authentication information appears to be | |||||
//// provided by configuration data then we will build the string from that data. | |||||
//// that way an attacker can't trick the application into disclosing the true | |||||
//// authentication string -- they will only get out what they put in. | |||||
string SecurityKeyDisplayString(snfCFGData& D) { // Returns appropriate SecurityKey: data | |||||
string ConfigLogSecurityKey = "************************"; // Start with a masked display. | |||||
if(0 < D.node_authentication.length()) { // If auth info is in the config files then | |||||
ConfigLogSecurityKey = D.node_licenseid + D.node_authentication; // build up the key from that data so it | |||||
} // can be displayed in the config log. | |||||
return ConfigLogSecurityKey; | |||||
} | |||||
void logCFGData(snfCFGData& D) { // Log interpreted cfg data (debug aid). | void logCFGData(snfCFGData& D) { // Log interpreted cfg data (debug aid). | ||||
try { | try { | ||||
string CFGLogPath; // Build the snf_cfg log path. | string CFGLogPath; // Build the snf_cfg log path. | ||||
CFGLogPath = D.paths_log_path + | CFGLogPath = D.paths_log_path + | ||||
D.node_licenseid + "_snf_engine_cfg.log"; | |||||
D.node_licenseid + "_snf_engine_cfg.log"; | |||||
ofstream cfgl(CFGLogPath.c_str(), ios::trunc); // Open and truncate the cfg log file. | ofstream cfgl(CFGLogPath.c_str(), ios::trunc); // Open and truncate the cfg log file. | ||||
cfgl // Report important cfg information. | cfgl // Report important cfg information. | ||||
} | } | ||||
//// The SecurityKey is built from the licenseID and the Authentication | //// The SecurityKey is built from the licenseID and the Authentication | ||||
if(InitLicenseIdIsProvided) { // If the LicenseID is OEM provided then | if(InitLicenseIdIsProvided) { // If the LicenseID is OEM provided then | ||||
CFGData.SecurityKey = InitLicenseId; // the first part of our security key is that. | |||||
CFGData.SecurityKey = InitLicenseId; // the first part of our security key is that. | |||||
CFGData.node_licenseid = InitLicenseId; // Also override any file-loaded license ID. | CFGData.node_licenseid = InitLicenseId; // Also override any file-loaded license ID. | ||||
} else { // If it was not provided then we will get | } else { // If it was not provided then we will get | ||||
CFGData.SecurityKey = CFGData.node_licenseid; // the LicenseID from our config file. | CFGData.SecurityKey = CFGData.node_licenseid; // the LicenseID from our config file. | ||||
} | } | ||||
string LicenseIDToUse = CFGData.SecurityKey; // Grab the License ID we want to use. | |||||
string LicenseIDToUse = CFGData.SecurityKey; // Grab the License ID we want to use. | |||||
if(InitAuthenticationIsProvided) { // If the Authentication has been provided then | if(InitAuthenticationIsProvided) { // If the Authentication has been provided then | ||||
CFGData.SecurityKey += InitAuthentication; // we use it for the second part of our | CFGData.SecurityKey += InitAuthentication; // we use it for the second part of our | ||||
if(InitPathIsRulebase) { // If the Rulebase path was provided | if(InitPathIsRulebase) { // If the Rulebase path was provided | ||||
CFGData.RuleFilePath = InitFileName; // then we have our rulebase path. | CFGData.RuleFilePath = InitFileName; // then we have our rulebase path. | ||||
} else { // If not then we must figure it out... | |||||
} else { // If not then we must figure it out... | |||||
CFGData.RuleFilePath = // We build the path from the base | CFGData.RuleFilePath = // We build the path from the base | ||||
CFGData.paths_rulebase_path + // rulebase path concattonated with | CFGData.paths_rulebase_path + // rulebase path concattonated with | ||||
LicenseIDToUse + // the license id concattonated with | LicenseIDToUse + // the license id concattonated with | ||||
SNFExt; // the rulebase extension. | |||||
SNFExt; // the rulebase extension. | |||||
} | } | ||||
// Once all of the configuration data is correct we make it active. | // Once all of the configuration data is correct we make it active. |
} | } | ||||
}; | }; | ||||
enum snfIPRange { // IP action ranges | |||||
enum class snfIPRange { // IP action ranges | |||||
Unknown, // Unknown - not defined. | Unknown, // Unknown - not defined. | ||||
White, // This is a good guy. | White, // This is a good guy. | ||||
Normal, // Benefit of the doubt. | Normal, // Benefit of the doubt. |
#include "snfLOGmgr.hpp" | #include "snfLOGmgr.hpp" | ||||
#include "../CodeDweller/threading.hpp" | #include "../CodeDweller/threading.hpp" | ||||
#include "../CodeDweller/timing.hpp" | #include "../CodeDweller/timing.hpp" | ||||
#include <unistd.h> | |||||
#include <sstream> | |||||
#include <unistd.h> | |||||
#include <sstream> | |||||
#include <iomanip> | #include <iomanip> | ||||
using namespace std; | using namespace std; | ||||
snfScanData::snfScanData(int ScanHorizon) : // How to create. | snfScanData::snfScanData(int ScanHorizon) : // How to create. | ||||
ReadyToClear(true), // Make sure initial clear will happen. | ReadyToClear(true), // Make sure initial clear will happen. | ||||
FilteredData(ScanHorizon, 0) { // Allocate the Filtered Data buffer. | |||||
FilteredData(ScanHorizon, 0) { // Allocate the Filtered Data buffer. | |||||
clear(); // Start with no data. | clear(); // Start with no data. | ||||
} | } | ||||
SourceIPOrdinal = -1; // There is no source IP because it | SourceIPOrdinal = -1; // There is no source IP because it | ||||
SourceIPFoundFlag = false; // has not yet been found. | SourceIPFoundFlag = false; // has not yet been found. | ||||
SourceIPRangeFlag = Unknown; // Range flag is not yet known. | |||||
SourceIPRangeFlag = snfIPRange::Unknown; // Range flag is not yet known. | |||||
SourceIPEvaluation.clear(); // No eval yet. | SourceIPEvaluation.clear(); // No eval yet. | ||||
myHeaderDirectiveSourceIP = 0UL; // Header directive source is empty now. | myHeaderDirectiveSourceIP = 0UL; // Header directive source is empty now. | ||||
const ThreadType snfLOGmgr::Type("snfLOGmgr"); // The thread's type. | const ThreadType snfLOGmgr::Type("snfLOGmgr"); // The thread's type. | ||||
snfLOGmgr::snfLOGmgr() : // Constructor for the LOG manager | snfLOGmgr::snfLOGmgr() : // Constructor for the LOG manager | ||||
Thread(snfLOGmgr::Type, "Log Manager"), // snfLOGmgr Type and Name. | |||||
Thread(snfLOGmgr::Type, "Log Manager"), // snfLOGmgr Type and Name. | |||||
Configured(false), // Not yet configured. | Configured(false), // Not yet configured. | ||||
TimeToDie(false), // Not yet time to die. | |||||
PeekEnableCounter(0), // No peeking yet. | |||||
SampleEnableCounter(0), // No sampling yet. | |||||
myNETmgr(NULL), // No NET mgr yet. | |||||
myGBUdb(NULL), // No GBUdb yet. | |||||
NewerRulebaseIsAvailable(false), // No newer rulebase yet. | |||||
TimeToDie(false), // Not yet time to die. | |||||
PeekEnableCounter(0), // No peeking yet. | |||||
SampleEnableCounter(0), // No sampling yet. | |||||
myNETmgr(NULL), // No NET mgr yet. | |||||
myGBUdb(NULL), // No GBUdb yet. | |||||
NewerRulebaseIsAvailable(false), // No newer rulebase yet. | |||||
SecondStatusLogger("Second Status Logger"), // Lazy writer for Second status. | SecondStatusLogger("Second Status Logger"), // Lazy writer for Second status. | ||||
MinuteStatusLogger("Minute Status Logger"), // Lazy writer for Minute status. | MinuteStatusLogger("Minute Status Logger"), // Lazy writer for Minute status. | ||||
HourStatusLogger("Hour Status Logger"), // Lazy writer for Hour status. | HourStatusLogger("Hour Status Logger"), // Lazy writer for Hour status. | ||||
} | } | ||||
} | } | ||||
// Black header | |||||
// Black header | |||||
const int AboveBandRange = 64; | const int AboveBandRange = 64; | ||||
if( | if( | ||||
CFGData.XHDRBlack_OnOff && // If the Black XHDR is on and | CFGData.XHDRBlack_OnOff && // If the Black XHDR is on and | ||||
0 < ScanData.CompositeFinalResult && // We have a nonzero result and | |||||
0 < ScanData.CompositeFinalResult && // We have a nonzero result and | |||||
AboveBandRange > ScanData.CompositeFinalResult && // it is not an above-band code and | AboveBandRange > ScanData.CompositeFinalResult && // it is not an above-band code and | ||||
!CFGData.TrainingWhiteRuleHandler.isListed( // it is not found in the training | !CFGData.TrainingWhiteRuleHandler.isListed( // it is not found in the training | ||||
ScanData.CompositeFinalResult) // white list then... | ScanData.CompositeFinalResult) // white list then... | ||||
<< "c=\'" << ScanData.SourceIPRecord().GBUdbData.Confidence() << "\' " | << "c=\'" << ScanData.SourceIPRecord().GBUdbData.Confidence() << "\' " | ||||
<< "p=\'" << ScanData.SourceIPRecord().GBUdbData.Probability() << "\' " | << "p=\'" << ScanData.SourceIPRecord().GBUdbData.Probability() << "\' " | ||||
<< "r=\'" << | << "r=\'" << | ||||
((Unknown == ScanData.SourceIPRange())? "Unknown" : | |||||
((White == ScanData.SourceIPRange())? "White" : | |||||
((Normal == ScanData.SourceIPRange())? "Normal" : | |||||
((New == ScanData.SourceIPRange())? "New" : | |||||
((Caution == ScanData.SourceIPRange())? "Caution" : | |||||
((Black == ScanData.SourceIPRange())? "Black" : | |||||
((Truncate == ScanData.SourceIPRange())? "Truncate" : | |||||
((snfIPRange::Unknown == ScanData.SourceIPRange())? "Unknown" : | |||||
((snfIPRange::White == ScanData.SourceIPRange())? "White" : | |||||
((snfIPRange::Normal == ScanData.SourceIPRange())? "Normal" : | |||||
((snfIPRange::New == ScanData.SourceIPRange())? "New" : | |||||
((snfIPRange::Caution == ScanData.SourceIPRange())? "Caution" : | |||||
((snfIPRange::Black == ScanData.SourceIPRange())? "Black" : | |||||
((snfIPRange::Truncate == ScanData.SourceIPRange())? "Truncate" : | |||||
"Fault"))))))) | "Fault"))))))) | ||||
<< "\'/>" | << "\'/>" | ||||
<< endl; | << endl; | ||||
<< "c=\'" << I.G.Confidence() << "\' " | << "c=\'" << I.G.Confidence() << "\' " | ||||
<< "p=\'" << I.G.Probability() << "\' " | << "p=\'" << I.G.Probability() << "\' " | ||||
<< "r=\'" << | << "r=\'" << | ||||
((Unknown == I.R)? "Unknown" : | |||||
((White == I.R)? "White" : | |||||
((Normal == I.R)? "Normal" : | |||||
((New == I.R)? "New" : | |||||
((Caution == I.R)? "Caution" : | |||||
((Black == I.R)? "Black" : | |||||
((Truncate == I.R)? "Truncate" : | |||||
((snfIPRange::Unknown == I.R)? "Unknown" : | |||||
((snfIPRange::White == I.R)? "White" : | |||||
((snfIPRange::Normal == I.R)? "Normal" : | |||||
((snfIPRange::New == I.R)? "New" : | |||||
((snfIPRange::Caution == I.R)? "Caution" : | |||||
((snfIPRange::Black == I.R)? "Black" : | |||||
((snfIPRange::Truncate == I.R)? "Truncate" : | |||||
"Fault"))))))) | "Fault"))))))) | ||||
<< "\' " | << "\' " | ||||
<< "a=\'" << Action << "\'" | << "a=\'" << Action << "\'" | ||||
} | } | ||||
string snfLOGmgr::Timestamp(time_t t) { // Convert time_t to a timestamp s. | string snfLOGmgr::Timestamp(time_t t) { // Convert time_t to a timestamp s. | ||||
stringstream TimestampBfr; | |||||
const string EmptyTimestamp = "00000000000000"; | |||||
stringstream TimestampBfr; | |||||
const string EmptyTimestamp = "00000000000000"; | |||||
string theTimeStamp = EmptyTimestamp; | string theTimeStamp = EmptyTimestamp; | ||||
tm* gmt; // Get a ptr to a tm structure. | tm* gmt; // Get a ptr to a tm structure. | ||||
gmt = gmtime(&t); // Fill it with UTC. | |||||
bool isValidGMT = (0 != gmt); | |||||
if(isValidGMT) { | |||||
TimestampBfr | |||||
<< setw(4) << (gmt->tm_year+1900) | |||||
<< setw(2) << setfill('0') << (gmt->tm_mon+1) | |||||
<< setw(2) << setfill('0') << (gmt->tm_mday) | |||||
<< setw(2) << setfill('0') << (gmt->tm_hour) | |||||
<< setw(2) << setfill('0') << (gmt->tm_min) | |||||
<< setw(2) << setfill('0') << (gmt->tm_sec) | |||||
; | |||||
theTimeStamp = TimestampBfr.str(); | |||||
} | |||||
gmt = gmtime(&t); // Fill it with UTC. | |||||
bool isValidGMT = (0 != gmt); | |||||
if(isValidGMT) { | |||||
TimestampBfr | |||||
<< setw(4) << (gmt->tm_year+1900) | |||||
<< setw(2) << setfill('0') << (gmt->tm_mon+1) | |||||
<< setw(2) << setfill('0') << (gmt->tm_mday) | |||||
<< setw(2) << setfill('0') << (gmt->tm_hour) | |||||
<< setw(2) << setfill('0') << (gmt->tm_min) | |||||
<< setw(2) << setfill('0') << (gmt->tm_sec) | |||||
; | |||||
theTimeStamp = TimestampBfr.str(); | |||||
} | |||||
return theTimeStamp; // Return a string. | return theTimeStamp; // Return a string. | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// 20090730_M - Moved persistent state aux saves to RecordSyncEvent. It makes | |||||
// sense for the persistent state to match the latext external record of state | |||||
// info. If SNFServer dies uncerimoneusly that is what we will remember. | |||||
int snfLOGmgr::SecsSinceStartup() { | |||||
return (int) difftime(Timestamp(), StartupTime); | |||||
} | |||||
// 20090730_M - Moved persistent state aux saves to RecordSyncEvent. It makes | |||||
// sense for the persistent state to match the latext external record of state | |||||
// info. If SNFServer dies uncerimoneusly that is what we will remember. | |||||
int snfLOGmgr::SecsSinceStartup() { | |||||
return (int) difftime(Timestamp(), StartupTime); | |||||
} | |||||
void snfLOGmgr::RecordSyncEvent() { // Sets timestamp of latest Sync. | void snfLOGmgr::RecordSyncEvent() { // Sets timestamp of latest Sync. | ||||
Status.LastSyncTime = Timestamp(); // Set the Sync time. | |||||
Status.LastSyncTime = Timestamp(); // Set the Sync time. | |||||
if(Configured) Status.store(PersistentFileName); // Store our persistent data. | if(Configured) Status.store(PersistentFileName); // Store our persistent data. | ||||
} | } | ||||
} | } | ||||
int snfLOGmgr::SecsSinceLastCondense() { // Gets seconds since latest Condense. | int snfLOGmgr::SecsSinceLastCondense() { // Gets seconds since latest Condense. | ||||
return (int) difftime(Timestamp(), Status.LastCondenseTime); | |||||
return (int) difftime(Timestamp(), Status.LastCondenseTime); | |||||
} | } | ||||
// Data in the multi-range sliding window is tracked in circular buffers. | // Data in the multi-range sliding window is tracked in circular buffers. |
// #include "tcp_watchdog.hpp" No longer using TCPWatchdog -- see below _M | // #include "tcp_watchdog.hpp" No longer using TCPWatchdog -- see below _M | ||||
using namespace std; | using namespace std; | ||||
///// utilities //////////////////////////////////////////////////////////////// | |||||
const int MSecsInSecs = 1000; // Multiplier - seconds to milliseconds. | |||||
unsigned long long int SecsAsMSecs(unsigned int Secs) { | |||||
return (MSecsInSecs * Secs); | |||||
} | |||||
///// utilities //////////////////////////////////////////////////////////////// | |||||
const int MSecsInSecs = 1000; // Multiplier - seconds to milliseconds. | |||||
unsigned long long int SecsAsMSecs(unsigned int Secs) { | |||||
return (MSecsInSecs * Secs); | |||||
} | |||||
//// snfNETmgr ///////////////////////////////////////////////////////////////// | //// snfNETmgr ///////////////////////////////////////////////////////////////// | ||||
snfNETmgr::snfNETmgr() : // Starting up the NETmgr | snfNETmgr::snfNETmgr() : // Starting up the NETmgr | ||||
Thread(snfNETmgr::Type, "NET Manager"), // Network manager and Name. | Thread(snfNETmgr::Type, "NET Manager"), // Network manager and Name. | ||||
myLOGmgr(NULL), // No LOGmgr yet. | |||||
myLOGmgr(NULL), // No LOGmgr yet. | |||||
isTimeToStop(false), // Not time to stop yet. | isTimeToStop(false), // Not time to stop yet. | ||||
isConfigured(false), // Not configured yet. | isConfigured(false), // Not configured yet. | ||||
SYNCTimer(30000), // Sync every 30 secs by default. | |||||
SyncSecsOverride(-1) { // Override is -1 (off) by default. | |||||
SYNCTimer(30000), // Sync every 30 secs by default. | |||||
SyncSecsOverride(-1) { // Override is -1 (off) by default. | |||||
run(); // Run the thread. | run(); // Run the thread. | ||||
} | } | ||||
XML << "<ip range=\'"; | XML << "<ip range=\'"; | ||||
string IPRange; | string IPRange; | ||||
switch(ScanData.SourceIPRange()) { | switch(ScanData.SourceIPRange()) { | ||||
case Unknown: { IPRange = "Unknown"; break; } // Unknown - not defined. | |||||
case White: { IPRange = "White"; break; } // This is a good guy. | |||||
case Normal: { IPRange = "Normal"; break; } // Benefit of the doubt. | |||||
case New: { IPRange = "New"; break; } // It is new to us. | |||||
case Caution: { IPRange = "Caution"; break; } // This is suspicious. | |||||
case Black: { IPRange = "Black"; break; } // This is bad. | |||||
case Truncate: { IPRange = "Truncate"; break; } // Don't even bother looking. | |||||
case snfIPRange::Unknown: { IPRange = "Unknown"; break; } // Unknown - not defined. | |||||
case snfIPRange::White: { IPRange = "White"; break; } // This is a good guy. | |||||
case snfIPRange::Normal: { IPRange = "Normal"; break; } // Benefit of the doubt. | |||||
case snfIPRange::New: { IPRange = "New"; break; } // It is new to us. | |||||
case snfIPRange::Caution: { IPRange = "Caution"; break; } // This is suspicious. | |||||
case snfIPRange::Black: { IPRange = "Black"; break; } // This is bad. | |||||
case snfIPRange::Truncate: { IPRange = "Truncate"; break; } // Don't even bother looking. | |||||
} | } | ||||
SocketAddress IP; | SocketAddress IP; |
<< "\' b=\'" << IPState.G.Bad() // Emit the bad count. | << "\' b=\'" << IPState.G.Bad() // Emit the bad count. | ||||
<< "\' g=\'" << IPState.G.Good() // Emit the good count. | << "\' g=\'" << IPState.G.Good() // Emit the good count. | ||||
<< "\' range=\'" | << "\' range=\'" | ||||
<< ((Unknown == IPState.R) ? "unknown" : | |||||
((White == IPState.R) ? "white" : | |||||
((Normal == IPState.R) ? "normal" : | |||||
((New == IPState.R) ? "new" : | |||||
((Caution == IPState.R) ? "caution" : | |||||
((Black == IPState.R) ? "black" : | |||||
((Truncate == IPState.R) ? "truncate" : "error"))))))) | |||||
<< ((snfIPRange::Unknown == IPState.R) ? "unknown" : | |||||
((snfIPRange::White == IPState.R) ? "white" : | |||||
((snfIPRange::Normal == IPState.R) ? "normal" : | |||||
((snfIPRange::New == IPState.R) ? "new" : | |||||
((snfIPRange::Caution == IPState.R) ? "caution" : | |||||
((snfIPRange::Black == IPState.R) ? "black" : | |||||
((snfIPRange::Truncate == IPState.R) ? "truncate" : "error"))))))) | |||||
<< "\' code=\'" << IPState.Code | << "\' code=\'" << IPState.Code | ||||
<< "\'" | << "\'" | ||||
<< "/></gbudb></xci></snf>" // Finish it up. | << "/></gbudb></xci></snf>" // Finish it up. | ||||
} | } | ||||
snfXCITCPChannel* snfXCImgr::BestAvailableChannel() { // Selects XCI channel w/ lowest queue. | snfXCITCPChannel* snfXCImgr::BestAvailableChannel() { // Selects XCI channel w/ lowest queue. | ||||
return LowestQueue( // Pick the lowest of the lowest. | |||||
return LowestQueue( // Pick the lowest of the lowest. | |||||
LowestQueue( | LowestQueue( | ||||
LowestQueue(C0, C1), | LowestQueue(C0, C1), | ||||
LowestQueue(C2, C3) | |||||
), | |||||
LowestQueue( | |||||
LowestQueue(C2, C3) | |||||
), | |||||
LowestQueue( | |||||
LowestQueue(C4, C5), | LowestQueue(C4, C5), | ||||
LowestQueue(C6, C7) | |||||
LowestQueue(C6, C7) | |||||
) | ) | ||||
); | ); | ||||
} | } | ||||
CFG_XCI_PORT(XCI_Default_Port), // default, and | CFG_XCI_PORT(XCI_Default_Port), // default, and | ||||
myHome(0), // nulled. | myHome(0), // nulled. | ||||
C0(0), C1(0), C2(0), C3(0), | C0(0), C1(0), C2(0), C3(0), | ||||
Listener(0), | |||||
XCI_UP(false), | |||||
Listener(0), | |||||
XCI_UP(false), | |||||
diagLoopCount(0), diagClientCount(0), | diagLoopCount(0), diagClientCount(0), | ||||
TimeToStop(true) { // We don't run until linkHome(). | TimeToStop(true) { // We don't run until linkHome(). | ||||
} | } |
#include <cstdlib> | #include <cstdlib> | ||||
#include <fstream> | #include <fstream> | ||||
#include <iostream> | #include <iostream> | ||||
#include <string> | |||||
#include <vector> | |||||
#include <string> | |||||
#include <vector> | |||||
#include "../CodeDweller/mangler.hpp" | #include "../CodeDweller/mangler.hpp" | ||||
#include "snf_engine.hpp" | #include "snf_engine.hpp" | ||||
void TokenMatrix::Load(const char* FileName) { // Initializes the token matrix by file name. | void TokenMatrix::Load(const char* FileName) { // Initializes the token matrix by file name. | ||||
ifstream MatrixFile(FileName,ios::binary); // Open the file. | ifstream MatrixFile(FileName,ios::binary); // Open the file. | ||||
if(MatrixFile.bad()) // If anything is wrong with the file | |||||
throw BadFile("TokenMatrix::Load() finds MatrixFile.bad()"); // then throw a bad file exception. | |||||
if(!MatrixFile.is_open() || MatrixFile.bad()) // If anything is wrong with the file | |||||
throw BadFile("TokenMatrix::Load()(MatrixFile==NULL || MatrixFile.bad())"); // then throw a bad file exception. | |||||
Load(MatrixFile); // Load the matrix from the file. | Load(MatrixFile); // Load the matrix from the file. | ||||
MatrixFile.close(); // Be nice and clean up our file. | MatrixFile.close(); // Be nice and clean up our file. | ||||
} | } | ||||
// TokenMatrix::Load(stream) | // TokenMatrix::Load(stream) | ||||
const AbortCheck CompatibleIntSizeCheck("TokenMatrix::Load():CompatibleIntSizeCheck(sizeof(unsigned int)==4)"); | |||||
const AbortCheck CompatibleIntSizeCheck("TokenMatrix::Load():CompatibleIntSizeCheck(sizeof(unsigned int)==4)"); | |||||
void TokenMatrix::Load(ifstream& F) { // Initializes the token matrix from a file. | void TokenMatrix::Load(ifstream& F) { // Initializes the token matrix from a file. | ||||
CompatibleIntSizeCheck(sizeof(unsigned int)==4); // Check our assumptions. | |||||
CompatibleIntSizeCheck(sizeof(unsigned int)==4); // Check our assumptions. | |||||
MatrixSize = 0; // Clear out the old Matrix Size and array. | MatrixSize = 0; // Clear out the old Matrix Size and array. | ||||
if(Matrix) delete Matrix; // that is, if there is an array. | if(Matrix) delete Matrix; // that is, if there is an array. | ||||
// Evaluator Implementations ////////////////////////////////////////////////////////////// | // Evaluator Implementations ////////////////////////////////////////////////////////////// | ||||
// 20030216 _M Optimization conversions | // 20030216 _M Optimization conversions | ||||
// 20140119 _M Deprecated by jump table in evaluator | // 20140119 _M Deprecated by jump table in evaluator | ||||
// inline int Evaluator::i_lower() { return myEvaluationMatrix->i_lower; } | // inline int Evaluator::i_lower() { return myEvaluationMatrix->i_lower; } | ||||
// inline bool Evaluator::i_isDigit() { return myEvaluationMatrix->i_isDigit; } | // inline bool Evaluator::i_isDigit() { return myEvaluationMatrix->i_isDigit; } | ||||
// Evaluator::Evaluator(position,evalmatrix) Constructor | // Evaluator::Evaluator(position,evalmatrix) Constructor | ||||
Evaluator::Evaluator(unsigned int s, EvaluationMatrix* m) | |||||
: myEvaluationMatrix(m), | |||||
JumpPoint(0), | |||||
Condition(DOING_OK), | |||||
NextEvaluator(NULL), | |||||
StreamStartPosition(s), | |||||
CurrentPosition(0), | |||||
Evaluator::Evaluator(unsigned int s, EvaluationMatrix* m) | |||||
: myEvaluationMatrix(m), | |||||
JumpPoint(0), | |||||
Condition(DOING_OK), | |||||
NextEvaluator(NULL), | |||||
StreamStartPosition(s), | |||||
CurrentPosition(0), | |||||
WildRunLength(0) { // Constructor... | WildRunLength(0) { // Constructor... | ||||
Matrix = myEvaluationMatrix->getTokens(); // Capture the token matrix I walk in. | Matrix = myEvaluationMatrix->getTokens(); // Capture the token matrix I walk in. | ||||
MatrixSize = myEvaluationMatrix->getMatrixSize(); // And get it's size. | |||||
MatrixSize = myEvaluationMatrix->getMatrixSize(); // And get it's size. | |||||
PositionLimit = MatrixSize - 256; | PositionLimit = MatrixSize - 256; | ||||
} | } | ||||
int Evaluator::xAnyInline() { return (JumpPoint + WILD_INLINE); } // Match Any byte but new line. | int Evaluator::xAnyInline() { return (JumpPoint + WILD_INLINE); } // Match Any byte but new line. | ||||
int Evaluator::xAnything() { return (JumpPoint + WILD_ANYTHING); } // Match Any character at all. | int Evaluator::xAnything() { return (JumpPoint + WILD_ANYTHING); } // Match Any character at all. | ||||
int Evaluator::xRunGateway() { return (JumpPoint + RUN_GATEWAY); } // Match the run-loop gateway. | int Evaluator::xRunGateway() { return (JumpPoint + RUN_GATEWAY); } // Match the run-loop gateway. | ||||
// void Evaluator::doFollowOrMakeBuddy() | |||||
void Evaluator::doFollowOrMakeBuddy(int xKey) { | |||||
bool shouldFollow = (FALLEN_OFF == Condition); // What should we do? | |||||
// void Evaluator::doFollowOrMakeBuddy() | |||||
void Evaluator::doFollowOrMakeBuddy(int xKey) { | |||||
bool shouldFollow = (FALLEN_OFF == Condition); // What should we do? | |||||
if(shouldFollow) { // This is how we follow | if(shouldFollow) { // This is how we follow | ||||
Condition = DOING_OK; | Condition = DOING_OK; | ||||
CurrentPosition = xKey + | CurrentPosition = xKey + | ||||
myEvaluationMatrix-> | myEvaluationMatrix-> | ||||
AddEvaluator(StreamStartPosition,Matrix[xKey].Vector+xKey); | AddEvaluator(StreamStartPosition,Matrix[xKey].Vector+xKey); | ||||
} | } | ||||
} | |||||
void Evaluator::tryFollowingPrecisePath(unsigned short int i) { | |||||
} | |||||
void Evaluator::tryFollowingPrecisePath(unsigned short int i) { | |||||
int xPrecise = JumpPoint + i; // Match Precise Character | int xPrecise = JumpPoint + i; // Match Precise Character | ||||
if(Matrix[xPrecise].Character() == i) { // If we've matched our path | |||||
if(Matrix[xPrecise].Character() == i) { // If we've matched our path | |||||
doFollowOrMakeBuddy(xPrecise); | doFollowOrMakeBuddy(xPrecise); | ||||
} | |||||
} | |||||
if(DOING_OK == Condition) WildRunLength = 0; | if(DOING_OK == Condition) WildRunLength = 0; | ||||
} | |||||
void Evaluator::tryFollowingNoCasePath(unsigned short int i) { | |||||
i = tolower(i); | |||||
} | |||||
void Evaluator::tryFollowingNoCasePath(unsigned short int i) { | |||||
i = tolower(i); | |||||
int xNoCase = JumpPoint + i; // Match caps to lower (case insensitive) | int xNoCase = JumpPoint + i; // Match caps to lower (case insensitive) | ||||
if(Matrix[xNoCase].Character()==i){ | if(Matrix[xNoCase].Character()==i){ | ||||
doFollowOrMakeBuddy(xNoCase); | doFollowOrMakeBuddy(xNoCase); | ||||
} | } | ||||
if(DOING_OK == Condition) WildRunLength = 0; | if(DOING_OK == Condition) WildRunLength = 0; | ||||
} | |||||
void Evaluator::tryFollowingWildAlphaPath() { | |||||
} | |||||
void Evaluator::tryFollowingWildAlphaPath() { | |||||
if(Matrix[xLetter()].Character()==WILD_LETTER){ | if(Matrix[xLetter()].Character()==WILD_LETTER){ | ||||
doFollowOrMakeBuddy(xLetter()); | doFollowOrMakeBuddy(xLetter()); | ||||
} | } | ||||
} | |||||
void Evaluator::tryFollowingWildDigitPath() { | |||||
} | |||||
void Evaluator::tryFollowingWildDigitPath() { | |||||
if(Matrix[xDigit()].Character()==WILD_DIGIT){ | if(Matrix[xDigit()].Character()==WILD_DIGIT){ | ||||
doFollowOrMakeBuddy(xDigit()); | doFollowOrMakeBuddy(xDigit()); | ||||
} | } | ||||
} | |||||
void Evaluator::tryFollowingWildNonWhitePath() { | |||||
} | |||||
void Evaluator::tryFollowingWildNonWhitePath() { | |||||
if(Matrix[xNonWhite()].Character()==WILD_NONWHITE){ | if(Matrix[xNonWhite()].Character()==WILD_NONWHITE){ | ||||
doFollowOrMakeBuddy(xNonWhite()); | doFollowOrMakeBuddy(xNonWhite()); | ||||
} | } | ||||
} | |||||
void Evaluator::tryFollowingWildWhitePath() { | |||||
} | |||||
void Evaluator::tryFollowingWildWhitePath() { | |||||
if(Matrix[xWhiteSpace()].Character()==WILD_WHITESPACE){ | if(Matrix[xWhiteSpace()].Character()==WILD_WHITESPACE){ | ||||
doFollowOrMakeBuddy(xWhiteSpace()); | doFollowOrMakeBuddy(xWhiteSpace()); | ||||
} | } | ||||
} | |||||
void Evaluator::tryFollowingWildInlinePath() { | |||||
} | |||||
void Evaluator::tryFollowingWildInlinePath() { | |||||
if(Matrix[xAnyInline()].Character()==WILD_INLINE){ | if(Matrix[xAnyInline()].Character()==WILD_INLINE){ | ||||
doFollowOrMakeBuddy(xAnyInline()); | doFollowOrMakeBuddy(xAnyInline()); | ||||
} | } | ||||
} | |||||
void Evaluator::tryFollowingWildAnythingPath() { | |||||
} | |||||
void Evaluator::tryFollowingWildAnythingPath() { | |||||
if(Matrix[xAnything()].Character()==WILD_ANYTHING){ | if(Matrix[xAnything()].Character()==WILD_ANYTHING){ | ||||
doFollowOrMakeBuddy(xAnything()); | doFollowOrMakeBuddy(xAnything()); | ||||
} | |||||
} | |||||
void Evaluator::doFollowerJumpTable(unsigned short int i) { | |||||
// tryFollowingPrecisePath(i); | |||||
// tryFollowingUppercasePath(); 0x41 - 0x5A | |||||
// tryFollowingWildAlphaPath(); 0x61 - 0x7A | |||||
// tryFollowingWildDigitPath(); 0x30 - 0x39 | |||||
// tryFollowingWildWhitePath(); 0x09 - 0x0D, 0x20 | |||||
// tryFollowingWildNonWhitePath(); > 0x20 | |||||
// tryFollowingWildInlinePath(); Not 0x0A, or 0x0D | |||||
switch(i) { | |||||
// These nnly match WildAnything because they conflict with special check values... | |||||
// NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, BS, TAB, LF, VT, FF, CR, SO, SI | |||||
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: | |||||
case 0x08: { | |||||
break; | |||||
} | |||||
// tab | |||||
case 0x09: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// LF, VT, FF, CR, SO, SI | |||||
case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: | |||||
// DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS, RS, US | |||||
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: | |||||
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildWhitePath(); | |||||
break; | |||||
} | |||||
// the final fronteer | |||||
case 0x20: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// ! " # $ % & ' ( ) * + , - . / | |||||
case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: | |||||
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// 0 - 9 | |||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: | |||||
case 0x38: case 0x39: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildDigitPath(); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// : ; < = > ? @ | |||||
case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: | |||||
case 0x40: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// A - Z | |||||
case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: | |||||
case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: | |||||
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: | |||||
case 0x58: case 0x59: case 0x5A: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingNoCasePath(i); | |||||
tryFollowingWildAlphaPath(); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// [ \ ] ^ _ ` | |||||
case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: | |||||
case 0x60: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// a - z | |||||
case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: | |||||
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F: | |||||
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: | |||||
case 0x78: case 0x79: case 0x7A: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildAlphaPath(); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// { | } ~ | |||||
case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
} | |||||
// high ascii | |||||
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: | |||||
case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: | |||||
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: | |||||
case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F: | |||||
case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7: | |||||
case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF: | |||||
case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: | |||||
case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: | |||||
case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: | |||||
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: | |||||
case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: case 0xD7: | |||||
case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: | |||||
case 0xE0: case 0xE1: case 0xE2: case 0xE3: case 0xE4: case 0xE5: case 0xE6: case 0xE7: | |||||
case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF: | |||||
case 0xF0: case 0xF1: case 0xF2: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7: | |||||
case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
} | |||||
tryFollowingWildAnythingPath(); | |||||
} | |||||
} | |||||
} | |||||
void Evaluator::doFollowerJumpTable(unsigned short int i) { | |||||
// tryFollowingPrecisePath(i); | |||||
// tryFollowingUppercasePath(); 0x41 - 0x5A | |||||
// tryFollowingWildAlphaPath(); 0x61 - 0x7A | |||||
// tryFollowingWildDigitPath(); 0x30 - 0x39 | |||||
// tryFollowingWildWhitePath(); 0x09 - 0x0D, 0x20 | |||||
// tryFollowingWildNonWhitePath(); > 0x20 | |||||
// tryFollowingWildInlinePath(); Not 0x0A, or 0x0D | |||||
switch(i) { | |||||
// These nnly match WildAnything because they conflict with special check values... | |||||
// NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, BS, TAB, LF, VT, FF, CR, SO, SI | |||||
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: | |||||
case 0x08: { | |||||
break; | |||||
} | |||||
// tab | |||||
case 0x09: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// LF, VT, FF, CR, SO, SI | |||||
case 0x0A: case 0x0B: case 0x0C: case 0x0D: case 0x0E: case 0x0F: | |||||
// DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS, RS, US | |||||
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: | |||||
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildWhitePath(); | |||||
break; | |||||
} | |||||
// the final fronteer | |||||
case 0x20: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// ! " # $ % & ' ( ) * + , - . / | |||||
case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: | |||||
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// 0 - 9 | |||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: | |||||
case 0x38: case 0x39: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildDigitPath(); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// : ; < = > ? @ | |||||
case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: | |||||
case 0x40: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// A - Z | |||||
case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: | |||||
case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: | |||||
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: | |||||
case 0x58: case 0x59: case 0x5A: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingNoCasePath(i); | |||||
tryFollowingWildAlphaPath(); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// [ \ ] ^ _ ` | |||||
case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: | |||||
case 0x60: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// a - z | |||||
case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: | |||||
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F: | |||||
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: | |||||
case 0x78: case 0x79: case 0x7A: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildAlphaPath(); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
// { | } ~ | |||||
case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
} | |||||
// high ascii | |||||
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: | |||||
case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: | |||||
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: | |||||
case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F: | |||||
case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7: | |||||
case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF: | |||||
case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: | |||||
case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: | |||||
case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: | |||||
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: | |||||
case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: case 0xD7: | |||||
case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: | |||||
case 0xE0: case 0xE1: case 0xE2: case 0xE3: case 0xE4: case 0xE5: case 0xE6: case 0xE7: | |||||
case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF: | |||||
case 0xF0: case 0xF1: case 0xF2: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7: | |||||
case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF: { | |||||
tryFollowingPrecisePath(i); | |||||
tryFollowingWildNonWhitePath(); | |||||
tryFollowingWildInlinePath(); | |||||
break; | |||||
} | |||||
} | |||||
tryFollowingWildAnythingPath(); | |||||
} | |||||
// Evaluator::EvaluateThis() | // Evaluator::EvaluateThis() | ||||
Evaluator::States Evaluator::EvaluateThis(unsigned short int i) { // Follow the this byte. | Evaluator::States Evaluator::EvaluateThis(unsigned short int i) { // Follow the this byte. | ||||
// First upgrade will be to DOING_OK, after that we launch buddies. | // First upgrade will be to DOING_OK, after that we launch buddies. | ||||
// explored. New evaluators are always added at the TOP of the list so we are always | // explored. New evaluators are always added at the TOP of the list so we are always | ||||
// guaranteed not to overdrive an evaluator and end up in a recursive race condition. | // guaranteed not to overdrive an evaluator and end up in a recursive race condition. | ||||
// 20140121_M The previous optimization with binary flags has been replaced with | |||||
// a jump table implementation. Now, each byte only excites behaviors that are | |||||
// possible for the current byte so only those paths will be tested. | |||||
// 20140121_M The previous optimization with binary flags has been replaced with | |||||
// a jump table implementation. Now, each byte only excites behaviors that are | |||||
// possible for the current byte so only those paths will be tested. | |||||
if(CurrentPosition >= PositionLimit) return Condition = OUT_OF_RANGE; | if(CurrentPosition >= PositionLimit) return Condition = OUT_OF_RANGE; | ||||
// Evaluation order, most-to-least specific with what is possible for that byte. | // Evaluation order, most-to-least specific with what is possible for that byte. | ||||
JumpPoint = CurrentPosition; | JumpPoint = CurrentPosition; | ||||
doFollowerJumpTable(i); // Excite followers based on this byte. | |||||
{ // Precise matches reset the wild run counter. | |||||
doFollowerJumpTable(i); // Excite followers based on this byte. | |||||
{ // Precise matches reset the wild run counter. | |||||
++WildRunLength; // Count up the run length. | ++WildRunLength; // Count up the run length. | ||||
if(WildRunLength >= MaxWildRunLength) // If we exceed the max then | if(WildRunLength >= MaxWildRunLength) // If we exceed the max then | ||||
return Condition = FALLEN_OFF; // we've fallen off the path | return Condition = FALLEN_OFF; // we've fallen off the path | ||||
} // and we do it immediately. | |||||
} // and we do it immediately. | |||||
// 20021112 _M | // 20021112 _M | ||||
// Beginning with version 2 of Message Sniffer we've implemented a new construct | // Beginning with version 2 of Message Sniffer we've implemented a new construct | ||||
// for run-loops that prevents any interference between rules where run-loops might | // for run-loops that prevents any interference between rules where run-loops might | ||||
--CountOfEvaluators; // Reduce our evaluator count. | --CountOfEvaluators; // Reduce our evaluator count. | ||||
} | } | ||||
Evaluator* findEvaluatorListTail(Evaluator* head) { | |||||
Evaluator* next = head; | |||||
while(NULL != (next->NextEvaluator)) next = next->NextEvaluator; | |||||
return next; | |||||
} | |||||
void EvaluationMatrix::dropAllEvaluators() { | |||||
bool haveActiveEvaluators = (NULL != EvaluatorList); | |||||
if(haveActiveEvaluators) { | |||||
Evaluator* tail = findEvaluatorListTail(EvaluatorList); | |||||
tail->NextEvaluator = EvaluatorCache; | |||||
EvaluatorCache = EvaluatorList; | |||||
} | |||||
PreviousEvaluator = NULL; | |||||
CurrentEvaluator = NULL; | |||||
EvaluatorList = NULL; | |||||
CountOfEvaluators = 0; | |||||
Evaluator* findEvaluatorListTail(Evaluator* head) { | |||||
Evaluator* next = head; | |||||
while(NULL != (next->NextEvaluator)) next = next->NextEvaluator; | |||||
return next; | |||||
} | } | ||||
void EvaluationMatrix::restartEngineAt(int newCharacterCount) { | |||||
dropAllEvaluators(); | |||||
CountOfCharacters = newCharacterCount; | |||||
} | |||||
void EvaluationMatrix::dropAllEvaluators() { | |||||
bool haveActiveEvaluators = (NULL != EvaluatorList); | |||||
if(haveActiveEvaluators) { | |||||
Evaluator* tail = findEvaluatorListTail(EvaluatorList); | |||||
tail->NextEvaluator = EvaluatorCache; | |||||
EvaluatorCache = EvaluatorList; | |||||
} | |||||
PreviousEvaluator = NULL; | |||||
CurrentEvaluator = NULL; | |||||
EvaluatorList = NULL; | |||||
CountOfEvaluators = 0; | |||||
} | |||||
void EvaluationMatrix::restartEngineAt(int newCharacterCount) { | |||||
dropAllEvaluators(); | |||||
CountOfCharacters = newCharacterCount; | |||||
} | |||||
// EvaluationMatrix::EvaluateThis() | // EvaluationMatrix::EvaluateThis() | ||||
// | // | ||||
// Next do some basic conversions and evaluations so they don't need to be done | // Next do some basic conversions and evaluations so they don't need to be done | ||||
// again within the evaluators. From now on the evaluators will look here for basic | // again within the evaluators. From now on the evaluators will look here for basic | ||||
// conversions and boolean check values rather than performing the checks themselves. | // conversions and boolean check values rather than performing the checks themselves. | ||||
// 20140119 _M deprecated by jump table in evaluator | // 20140119 _M deprecated by jump table in evaluator | ||||
// i_lower = tolower(i); // Convert i to lower case. | // i_lower = tolower(i); // Convert i to lower case. | ||||
// i_isDigit = isdigit(i); // Check for a digit. | // i_isDigit = isdigit(i); // Check for a digit. | ||||
return PassResult; // When we're finished, return the last known result. | return PassResult; // When we're finished, return the last known result. | ||||
} | } | ||||
void EvaluationMatrix::evaluateSegment(vector<unsigned char>& data, unsigned int start, unsigned int finish) { | |||||
restartEngineAt(start); | |||||
finish = (finish < data.size()) ? finish : data.size(); | |||||
for(unsigned int a = start; a < finish; a++) EvaluateThis(data[a]); | |||||
} | |||||
void EvaluationMatrix::evaluateSegment(vector<unsigned char>& data, unsigned int start, unsigned int finish) { | |||||
restartEngineAt(start); | |||||
finish = (finish < data.size()) ? finish : data.size(); | |||||
for(unsigned int a = start; a < finish; a++) EvaluateThis(data[a]); | |||||
} |