From 881071cc99207af49e4512ca59c6ed1fc57e5e95 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Tue, 15 Mar 2011 17:50:30 -0700 Subject: [PATCH 1/2] Extending conn_id with a globally unique identifiers. --- policy/bro.init | 1 + src/Conn.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ src/Conn.h | 7 +++++++ src/Hash.h | 2 +- src/util.cc | 20 ++++++++++++++++++++ src/util.h | 4 +--- 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/policy/bro.init b/policy/bro.init index b3f78f0689..03bdbc56ce 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -21,6 +21,7 @@ type conn_id: record { orig_p: port; resp_h: addr; resp_p: port; + uid: string; }; type icmp_conn: record { diff --git a/src/Conn.cc b/src/Conn.cc index 50afe41d0c..6cb24c3446 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -179,6 +179,8 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id) ++current_connections; ++total_connections; + uid = CalculateUID(); + TimerMgr::Tag* tag = current_iosrc->GetCurrentTag(); conn_timer_mgr = tag ? new TimerMgr::Tag(*tag) : 0; @@ -215,6 +217,43 @@ Connection::~Connection() --external_connections; } +uint64 Connection::uid_counter = 0; +uint64 Connection::uid_instance = 0; + +uint64 Connection::CalculateUID() + { + if ( uid_instance == 0 ) + { + // This is the first time we need a UID. Calculate the instance ID by + // hashing something likely to be unique. + struct { + char hostname[128]; + struct timeval time; + pid_t pid; + } unique; + + gethostname(unique.hostname, 128); + unique.hostname[sizeof(unique.hostname)-1] = '\0'; + gettimeofday(&unique.time, 0); + unique.pid = getpid(); + + uid_instance = HashKey::HashBytes(&unique, sizeof(unique)); + ++uid_instance; // Now it's larger than zero. + } + + // 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() { finished = 1; @@ -346,6 +385,10 @@ RecordVal* Connection::BuildConnVal() id_val->Assign(1, new PortVal(ntohs(orig_port), prot_type)); id_val->Assign(2, new AddrVal(resp_addr)); id_val->Assign(3, new PortVal(ntohs(resp_port), prot_type)); + + char tmp[16]; + id_val->Assign(4, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62))); + conn_val->Assign(0, id_val); orig_endp = new RecordVal(endpoint); diff --git a/src/Conn.h b/src/Conn.h index bbe3c2b3f6..1da1f97b57 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -279,6 +279,8 @@ public: void AddHistory(char code) { history += code; } + uint64 CalculateUID(); + void DeleteTimer(double t); // Sets the root of the analyzer tree as well as the primary PIA. @@ -368,6 +370,11 @@ protected: string history; uint32 hist_seen; + uint64 uid; // Globally unique connection ID. + + static uint64 uid_counter; // Counter for uids. + static uint64 uid_instance; // Once computed instance ID. + TransportLayerAnalyzer* root_analyzer; PIA* primary_PIA; }; diff --git a/src/Hash.h b/src/Hash.h index fa1f00f91f..9d6809edc7 100644 --- a/src/Hash.h +++ b/src/Hash.h @@ -11,7 +11,7 @@ #define UHASH_KEY_SIZE 32 -typedef unsigned int hash_t; +typedef uint64 hash_t; typedef enum { HASH_KEY_INT, diff --git a/src/util.cc b/src/util.cc index d8390a866c..ee5552899c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -340,6 +340,26 @@ int atoi_n(int len, const char* s, const char** end, int base, int& result) return 1; } +char* uitoa_n(uint64 value, char* str, int n, int base) + { + static char dig[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i = 0; + uint64 v; + char* p, *q; + char c; + + v = value; + + do { + str[i++] = dig[v % base]; + v /= base; + } while ( v && i < n ); + + str[i] = '\0'; + + return str; + } + int strstr_n(const int big_len, const u_char* big, const int little_len, const u_char* little) { diff --git a/src/util.h b/src/util.h index ab7cb3c6fe..df01e92af6 100644 --- a/src/util.h +++ b/src/util.h @@ -112,6 +112,7 @@ extern char* strcasestr(const char* s, const char* find); extern const char* strpbrk_n(size_t len, const char* s, const char* charset); extern int atoi_n(int len, const char* s, const char** end, int base, int& result); +extern char* uitoa_n(uint64 value, char* str, int n, int base); int strstr_n(const int big_len, const unsigned char* big, const int little_len, const unsigned char* little); extern int fputs(int len, const char* s, FILE* fp); @@ -151,9 +152,6 @@ extern void init_random_seed(uint32 seed, const char* load_file, extern uint64 rand64bit(); -#define UHASH_KEY_SIZE 32 -extern uint8 uhash_key[UHASH_KEY_SIZE]; - // Each event source that may generate events gets an internally unique ID. // This is always LOCAL for a local Bro. For remote event sources, it gets // assigned by the RemoteSerializer. From d84d4b8a5707483af6b15f91029f531bfb58d9fc Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Wed, 16 Mar 2011 14:25:49 -0700 Subject: [PATCH 2/2] Moving uid from conn_id to connection, and making output determistic if a hash seed is given. --- policy/bro.init | 2 +- src/Conn.cc | 45 ++++++++++++++++++++++++++++----------------- src/Net.cc | 1 + src/Net.h | 4 ++++ src/main.cc | 2 ++ src/util.cc | 4 ++-- 6 files changed, 38 insertions(+), 20 deletions(-) diff --git a/policy/bro.init b/policy/bro.init index 03bdbc56ce..371e6ec1f8 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -21,7 +21,6 @@ type conn_id: record { orig_p: port; resp_h: addr; resp_p: port; - uid: string; }; type icmp_conn: record { @@ -93,6 +92,7 @@ type connection: record { addl: string; hot: count; # how hot; 0 = don't know or not hot history: string; + uid: string; }; type SYN_packet: record { diff --git a/src/Conn.cc b/src/Conn.cc index 6cb24c3446..09a65f15be 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -222,23 +222,34 @@ uint64 Connection::uid_instance = 0; uint64 Connection::CalculateUID() { - if ( uid_instance == 0 ) + if ( uid_instance == 0 ) { - // This is the first time we need a UID. Calculate the instance ID by - // hashing something likely to be unique. - struct { - char hostname[128]; - struct timeval time; - pid_t pid; - } unique; + // This is the first time we need a UID. + if ( ! bro_deterministic_output ) + { + // In live mode, with determistic output not explicitly + // requested, calculate the instance ID by hashing something + // likely to be 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(); + gethostname(unique.hostname, 128); + unique.hostname[sizeof(unique.hostname)-1] = '\0'; + gettimeofday(&unique.time, 0); + unique.pid = getpid(); + unique.rnd = random(); - uid_instance = HashKey::HashBytes(&unique, sizeof(unique)); - ++uid_instance; // Now it's larger than zero. + 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. @@ -386,9 +397,6 @@ RecordVal* Connection::BuildConnVal() id_val->Assign(2, new AddrVal(resp_addr)); id_val->Assign(3, new PortVal(ntohs(resp_port), prot_type)); - char tmp[16]; - id_val->Assign(4, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62))); - conn_val->Assign(0, id_val); orig_endp = new RecordVal(endpoint); @@ -406,6 +414,9 @@ RecordVal* Connection::BuildConnVal() conn_val->Assign(6, new StringVal("")); // addl conn_val->Assign(7, new Val(0, TYPE_COUNT)); // hot conn_val->Assign(8, new StringVal("")); // history + + char tmp[16]; + conn_val->Assign(9, new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62))); } if ( root_analyzer ) diff --git a/src/Net.cc b/src/Net.cc index bc56556ee5..06bb581c0f 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -68,6 +68,7 @@ double processing_start_time = 0.0; // time started working on current pkt double bro_start_time = 0.0; // time Bro started. double bro_start_network_time; // timestamp of first packet double last_watchdog_proc_time = 0.0; // value of above during last watchdog +bool bro_deterministic_output = 0; // whether determistic output is desired bool terminating = false; // whether we're done reading and finishing up PacketSortGlobalPQ* packet_sorter = 0; diff --git a/src/Net.h b/src/Net.h index 87c0ce2499..88e2ce0dcf 100644 --- a/src/Net.h +++ b/src/Net.h @@ -73,6 +73,10 @@ extern double bro_start_time; // i.e. the timestamp of the first packet. extern double bro_start_network_time; +// True if determistic output is requested. This is set if the user specifies +// a seed for the random number generator. +extern bool bro_deterministic_output; + // True if we're a in the process of cleaning-up just before termination. extern bool terminating; diff --git a/src/main.cc b/src/main.cc index 22f8ee6976..11dfc34a07 100644 --- a/src/main.cc +++ b/src/main.cc @@ -667,6 +667,8 @@ int main(int argc, char** argv) bro_start_time = current_time(true); + bro_deterministic_output = (seed || seed_load_file); + init_random_seed(seed, seed_load_file, seed_save_file); // DEBUG_MSG("HMAC key: %s\n", md5_digest_print(shared_hmac_md5_key)); init_hash_function(); diff --git a/src/util.cc b/src/util.cc index ee5552899c..8df9188466 100644 --- a/src/util.cc +++ b/src/util.cc @@ -352,7 +352,7 @@ char* uitoa_n(uint64 value, char* str, int n, int base) do { str[i++] = dig[v % base]; - v /= base; + v /= base; } while ( v && i < n ); str[i] = '\0'; @@ -798,7 +798,7 @@ const char* bro_path() if ( ! path ) path = ".:" POLICYDEST ":" - POLICYDEST "/sigs:" + POLICYDEST "/sigs:" POLICYDEST "/time-machine:" POLICYDEST "/site";