A new bif unique_id(prefix) that returns a string that's unique across

Bro instaces with high probablity.

"prefix" is a string that will be prepended to the returned ID.
This commit is contained in:
Robin Sommer 2011-06-07 17:28:20 -07:00
parent 4bdb94955d
commit 8266709e20
10 changed files with 96 additions and 59 deletions

View file

@ -216,56 +216,6 @@ Connection::~Connection()
--external_connections; --external_connections;
} }
uint64 Connection::uid_counter = 0;
uint64 Connection::uid_instance = 0;
uint64 Connection::CalculateNextUID()
{
if ( uid_instance == 0 )
{
// This is the first time we need a UID.
if ( ! have_random_seed() )
{
// If we don't need deterministic output (as
// indicated by a set seed), we calculate the
// instance ID by hashing something likely to be
// globally unique.
struct {
char hostname[128];
struct timeval time;
pid_t pid;
int rnd;
} unique;
gethostname(unique.hostname, 128);
unique.hostname[sizeof(unique.hostname)-1] = '\0';
gettimeofday(&unique.time, 0);
unique.pid = getpid();
unique.rnd = bro_random();
uid_instance = HashKey::HashBytes(&unique, sizeof(unique));
++uid_instance; // Now it's larger than zero.
}
else
// Generate determistic UIDs.
uid_instance = 1;
}
// Now calculate the unique ID for this connection.
struct {
uint64 counter;
hash_t instance;
} key;
key.counter = ++uid_counter;
key.instance = uid_instance;
uint64_t h = HashKey::HashBytes(&key, sizeof(key));
return h;
}
void Connection::Done() void Connection::Done()
{ {
finished = 1; finished = 1;
@ -417,7 +367,7 @@ RecordVal* Connection::BuildConnVal()
conn_val->Assign(8, new StringVal("")); // history conn_val->Assign(8, new StringVal("")); // history
if ( ! uid ) if ( ! uid )
uid = CalculateNextUID(); uid = calculate_unique_id();
char tmp[20]; char tmp[20];
conn_val->Assign(9, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62))); conn_val->Assign(9, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62)));

View file

@ -303,8 +303,6 @@ public:
void SetUID(uint64 arg_uid) { uid = arg_uid; } void SetUID(uint64 arg_uid) { uid = arg_uid; }
static uint64 CalculateNextUID();
protected: protected:
Connection() { persistent = 0; } Connection() { persistent = 0; }
@ -363,9 +361,6 @@ protected:
PIA* primary_PIA; PIA* primary_PIA;
uint64 uid; // Globally unique connection ID. uint64 uid; // Globally unique connection ID.
static uint64 uid_counter; // Counter for uids.
static uint64 uid_instance; // Instance ID, computed once.
}; };
class ConnectionTimer : public Timer { class ConnectionTimer : public Timer {

View file

@ -620,7 +620,7 @@ void ConnCompressor::PktHdrToPendingConn(double time, const HashKey* key,
c->FIN = (tp->th_flags & TH_FIN) != 0; c->FIN = (tp->th_flags & TH_FIN) != 0;
c->RST = (tp->th_flags & TH_RST) != 0; c->RST = (tp->th_flags & TH_RST) != 0;
c->ACK = (tp->th_flags & TH_ACK) != 0; c->ACK = (tp->th_flags & TH_ACK) != 0;
c->uid = Connection::CalculateNextUID(); c->uid = calculate_unique_id();
c->num_bytes_ip = ip->TotalLen(); c->num_bytes_ip = ip->TotalLen();
c->num_pkts = 1; c->num_pkts = 1;
c->invalid = 0; c->invalid = 0;

View file

@ -3349,6 +3349,12 @@ function bro_has_ipv6%(%) : bool
#endif #endif
%} %}
function unique_id%(prefix: string%) : bool
%{
char tmp[20];
uint64 uid = calculate_unique_id();
return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString()));
%}
%%{ %%{
#include <openssl/x509.h> #include <openssl/x509.h>

View file

@ -344,15 +344,27 @@ template<class T> int atoi_n(int len, const char* s, const char** end, int base,
template int atoi_n<int>(int len, const char* s, const char** end, int base, int& result); template int atoi_n<int>(int len, const char* s, const char** end, int base, int& result);
template int atoi_n<int64_t>(int len, const char* s, const char** end, int base, int64_t& result); template int atoi_n<int64_t>(int len, const char* s, const char** end, int base, int64_t& result);
char* uitoa_n(uint64 value, char* str, int n, int base) char* uitoa_n(uint64 value, char* str, int n, int base, const char* prefix)
{ {
static char dig[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; static char dig[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
assert(n);
int i = 0; int i = 0;
uint64 v; uint64 v;
char* p, *q; char* p, *q;
char c; char c;
if ( prefix )
{
strncpy(str, prefix, n);
str[n-1] = '\0';
i += strlen(prefix);
}
if ( i >= n )
return str;
v = value; v = value;
do { do {
@ -1122,6 +1134,56 @@ int time_compare(struct timeval* tv_a, struct timeval* tv_b)
return tv_a->tv_sec - tv_b->tv_sec; 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.
uint64 calculate_unique_id()
{
if ( uid_instance == 0 )
{
// This is the first time we need a UID.
if ( ! have_random_seed() )
{
// If we don't need deterministic output (as
// indicated by a set seed), we calculate the
// instance ID by hashing something likely to be
// globally unique.
struct {
char hostname[128];
struct timeval time;
pid_t pid;
int rnd;
} unique;
gethostname(unique.hostname, 128);
unique.hostname[sizeof(unique.hostname)-1] = '\0';
gettimeofday(&unique.time, 0);
unique.pid = getpid();
unique.rnd = bro_random();
uid_instance = HashKey::HashBytes(&unique, sizeof(unique));
++uid_instance; // Now it's larger than zero.
}
else
// Generate determistic UIDs.
uid_instance = 1;
}
// Now calculate the unique ID.
struct {
uint64 counter;
hash_t instance;
} key;
key.counter = ++uid_counter;
key.instance = uid_instance;
uint64_t h = HashKey::HashBytes(&key, sizeof(key));
return h;
}
void out_of_memory(const char* where) void out_of_memory(const char* where)
{ {
fprintf( stderr, "bro: out of memory in %s.\n", where ); fprintf( stderr, "bro: out of memory in %s.\n", where );

View file

@ -111,7 +111,7 @@ extern char* strcasestr(const char* s, const char* find);
#endif #endif
extern const char* strpbrk_n(size_t len, const char* s, const char* charset); extern const char* strpbrk_n(size_t len, const char* s, const char* charset);
template<class T> int atoi_n(int len, const char* s, const char** end, int base, T& result); template<class T> int atoi_n(int len, const char* s, const char** end, int base, T& result);
extern char* uitoa_n(uint64 value, char* str, int n, int base); extern char* uitoa_n(uint64 value, char* str, int n, int base, const char* prefix=0);
int strstr_n(const int big_len, const unsigned char* big, int strstr_n(const int big_len, const unsigned char* big,
const int little_len, const unsigned char* little); const int little_len, const unsigned char* little);
extern int fputs(int len, const char* s, FILE* fp); extern int fputs(int len, const char* s, FILE* fp);
@ -233,6 +233,10 @@ extern struct timeval double_to_timeval(double t);
// Return > 0 if tv_a > tv_b, 0 if equal, < 0 if tv_a < tv_b. // Return > 0 if tv_a > tv_b, 0 if equal, < 0 if tv_a < tv_b.
extern int time_compare(struct timeval* tv_a, struct timeval* tv_b); 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.
extern uint64 calculate_unique_id();
// For now, don't use hash_maps - they're not fully portable. // For now, don't use hash_maps - they're not fully portable.
#if 0 #if 0
// Use for hash_map's string keys. // Use for hash_map's string keys.

View file

@ -0,0 +1 @@
6

View file

@ -0,0 +1,3 @@
A-UWkUyAuUGXf
B-56gKBmhBBB6
C-50da4BEzauh

View file

@ -0,0 +1,9 @@
#
# @TEST-EXEC: BRO_SEED_FILE= bro %INPUT 2>/dev/null >out
# @TEST-EXEC: BRO_SEED_FILE= bro %INPUT 2>/dev/null >>out
# @TEST-EXEC: cat out | sort | uniq | wc -l >count
# @TEST-EXEC: btest-diff count
print unique_id("A-");
print unique_id("B-");
print unique_id("C-");

View file

@ -0,0 +1,7 @@
#
# @TEST-EXEC: bro %INPUT >out
# @TEST-EXEC: btest-diff out
print unique_id("A-");
print unique_id("B-");
print unique_id("C-");