Some working code. Adds UID pools classified by string. Just compiles

and runs; need to go back through and make sure this code is actually
doing what I want it to do.

Note: Added new function unique_id_from(pool: string, prefix: string)
that allows the user to explicitly specify a randomness pool to use when
generating unique IDs.
This commit is contained in:
Gilbert Clark gc355804@ohio.edu 2011-08-08 22:12:40 -07:00
parent f36310dc0e
commit 9322c063cc
10 changed files with 78 additions and 21 deletions

View file

@ -3414,10 +3414,16 @@ function bro_has_ipv6%(%) : bool
function unique_id%(prefix: string%) : string
%{
char tmp[20];
uint64 uid = calculate_unique_id();
uint64 uid = calculate_unique_id(BRO_SCRIPT_UID_POOL);
return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString()));
%}
function unique_id_from%(pool: string, prefix: string%) : string
%{
char tmp[20];
uint64 uid = calculate_unique_id(string((const char *)pool->Bytes(), pool->Len()));
return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString()));
%}
%%{
#include <openssl/x509.h>
#include <openssl/asn1.h>

View file

@ -1206,15 +1206,30 @@ int time_compare(struct timeval* tv_a, struct timeval* tv_b)
return tv_a->tv_sec - tv_b->tv_sec;
}
static uint64 uid_counter; // Counter for unique IDs.
static uint64 uid_instance; // Instance ID, computed once.
struct BroUidEntry
{
uint64 instance;
uint64 counter;
BroUidEntry(const uint64 i)
: instance(i), counter(0) { }
};
static std::map<string, BroUidEntry> uid_pool;
static const std::string default_pool = string(BRO_DEFAULT_UID_POOL);
uint64 calculate_unique_id()
{
if ( uid_instance == 0 )
{
// This is the first time we need a UID.
return calculate_unique_id(default_pool);
}
uint64 calculate_unique_id(const std::string& pool)
{
uint64 uid_instance = 0;
std::map<std::string, BroUidEntry>::iterator pool_iter = uid_pool.find(pool);
if ( pool_iter == uid_pool.end() )
{
// This is the first time we need a UID for this pool.
const size_t pool_sz = (pool.length() < 32) ? pool.length() : 32; //Only keep the first 32 characters of the pool name
if ( ! have_random_seed() )
{
// If we don't need deterministic output (as
@ -1222,14 +1237,16 @@ uint64 calculate_unique_id()
// instance ID by hashing something likely to be
// globally unique.
struct {
char hostname[128];
char hostname[96];
char pool[32];
struct timeval time;
pid_t pid;
int rnd;
} unique;
memset(&unique, 0, sizeof(unique)); // Make valgrind happy.
gethostname(unique.hostname, 128);
gethostname(unique.hostname, 96);
memcpy(unique.pool, pool.c_str(), pool_sz);
unique.hostname[sizeof(unique.hostname)-1] = '\0';
gettimeofday(&unique.time, 0);
unique.pid = getpid();
@ -1238,22 +1255,38 @@ uint64 calculate_unique_id()
uid_instance = HashKey::HashBytes(&unique, sizeof(unique));
++uid_instance; // Now it's larger than zero.
}
else
// Generate determistic UIDs.
uid_instance = 1;
{
// Generate determistic UIDs for each individual pool
uid_instance = HashKey::HashBytes(pool.c_str(), strnlen(pool.c_str(), pool_sz));
}
// Guarantee no collisions (keep hashing until we get a unique instance)
bool found_collision = true;
while(found_collision)
{
found_collision = false;
for(pool_iter = uid_pool.begin(); pool_iter != uid_pool.end(); ++pool_iter)
{
if(pool_iter->second.instance == uid_instance)
{
found_collision = true;
uid_instance = HashKey::HashBytes(&uid_instance, sizeof(uid_instance));
}
}
}
// Our instance is unique. Huzzah.
uid_pool.insert(std::make_pair(pool, BroUidEntry(uid_instance)));
pool_iter = uid_pool.end();
}
// Now calculate the unique ID.
struct {
uint64 counter;
hash_t instance;
} key;
if(pool_iter == uid_pool.end())
{
pool_iter = uid_pool.find(pool);
}
assert(pool_iter != uid_pool.end()); // After all that work, wouldn't it be a shame...?
++(pool_iter->second.counter);
key.counter = ++uid_counter;
key.instance = uid_instance;
uint64_t h = HashKey::HashBytes(&key, sizeof(key));
uint64_t h = HashKey::HashBytes(&(pool_iter->second), sizeof(pool_iter->second));
return h;
}

View file

@ -226,7 +226,10 @@ extern int time_compare(struct timeval* tv_a, struct timeval* tv_b);
// Returns an integer that's very likely to be unique, even across Bro
// instances.
#define BRO_DEFAULT_UID_POOL "bro"
#define BRO_SCRIPT_UID_POOL "bro script"
extern uint64 calculate_unique_id();
extern uint64 calculate_unique_id(const std::string& pool);
// For now, don't use hash_maps - they're not fully portable.
#if 0

View file

@ -7,3 +7,6 @@
print unique_id("A-");
print unique_id("B-");
print unique_id("C-");
print unique_id_from("alpha", "D-");
print unique_id_from("beta", "E-");
print unique_id_from("beta", "F-");

View file

@ -5,3 +5,6 @@
print unique_id("A-");
print unique_id("B-");
print unique_id("C-");
print unique_id_from("alpha", "D-");
print unique_id_from("beta", "E-");
print unique_id_from("beta", "F-");

View file

@ -1,4 +1,5 @@
[btest]
ProfileDir = profiles
TestDirs = doc bifs language core policy istate
TmpDir = %(testbase)s/.tmp
BaselineDir = %(testbase)s/Baseline

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash