mirror of
https://github.com/zeek/zeek.git
synced 2025-10-15 21:18:20 +00:00
Merge origin/master into topic/vladg/radius
This commit is contained in:
commit
df99f87dbf
617 changed files with 20195 additions and 5690 deletions
|
@ -1 +1 @@
|
|||
Subproject commit 12b5cb446c8128bb22e5cbd7baa7d53669539487
|
||||
Subproject commit 3b3e189dab3801cd0474dfdd376d9de633cd3766
|
|
@ -317,8 +317,9 @@ void Attributes::CheckAttr(Attr* a)
|
|||
break;
|
||||
|
||||
// Table defaults may be promotable.
|
||||
if ( (ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
|
||||
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType())) )
|
||||
if ( ytype && ytype->Tag() == TYPE_RECORD &&
|
||||
atype->Tag() == TYPE_RECORD &&
|
||||
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType()) )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ Base64Converter::Base64Converter(analyzer::Analyzer* arg_analyzer, const string&
|
|||
Base64Converter::~Base64Converter()
|
||||
{
|
||||
if ( base64_table != default_base64_table )
|
||||
delete base64_table;
|
||||
delete [] base64_table;
|
||||
}
|
||||
|
||||
int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
|
||||
|
|
|
@ -9,6 +9,9 @@ set(bro_ALL_GENERATED_OUTPUTS CACHE INTERNAL "automatically generated files" FO
|
|||
# This collects bif inputs that we'll load automatically.
|
||||
set(bro_AUTO_BIFS CACHE INTERNAL "BIFs for automatic inclusion" FORCE)
|
||||
|
||||
set(bro_BASE_BIF_SCRIPTS CACHE INTERNAL "Bro script stubs for BIFs in base distribution of Bro" FORCE)
|
||||
set(bro_PLUGIN_BIF_SCRIPTS CACHE INTERNAL "Bro script stubs for BIFs in Bro plugins" FORCE)
|
||||
|
||||
# If TRUE, use CMake's object libraries for sub-directories instead of
|
||||
# static libraries. This requires CMake >= 2.8.8.
|
||||
set(bro_HAVE_OBJECT_LIBRARIES FALSE)
|
||||
|
@ -293,7 +296,6 @@ set(bro_SRCS
|
|||
OpaqueVal.cc
|
||||
OSFinger.cc
|
||||
PacketFilter.cc
|
||||
PacketSort.cc
|
||||
PersistenceSerializer.cc
|
||||
PktSrc.cc
|
||||
PolicyFile.cc
|
||||
|
@ -336,11 +338,13 @@ set(bro_SRCS
|
|||
strsep.c
|
||||
modp_numtoa.c
|
||||
|
||||
threading/AsciiFormatter.cc
|
||||
threading/BasicThread.cc
|
||||
threading/Formatter.cc
|
||||
threading/Manager.cc
|
||||
threading/MsgThread.cc
|
||||
threading/SerialTypes.cc
|
||||
threading/formatters/Ascii.cc
|
||||
threading/formatters/JSON.cc
|
||||
|
||||
logging/Manager.cc
|
||||
logging/WriterBackend.cc
|
||||
|
@ -401,12 +405,12 @@ add_custom_target(generate_outputs)
|
|||
add_dependencies(generate_outputs generate_outputs_stage2)
|
||||
|
||||
# Build __load__.bro files for standard *.bif.bro.
|
||||
bro_bif_create_loader(bif_loader ${CMAKE_BINARY_DIR}/scripts/base/bif)
|
||||
bro_bif_create_loader(bif_loader "${bro_BASE_BIF_SCRIPTS}")
|
||||
add_dependencies(bif_loader ${bro_SUBDIRS})
|
||||
add_dependencies(bro bif_loader)
|
||||
|
||||
# Build __load__.bro files for plugins/*.bif.bro.
|
||||
bro_bif_create_loader(bif_loader_plugins ${CMAKE_BINARY_DIR}/scripts/base/bif/plugins)
|
||||
bro_bif_create_loader(bif_loader_plugins "${bro_PLUGIN_BIF_SCRIPTS}")
|
||||
add_dependencies(bif_loader_plugins ${bro_SUBDIRS})
|
||||
add_dependencies(bro bif_loader_plugins)
|
||||
|
||||
|
|
|
@ -127,12 +127,7 @@ ChunkedIOFd::~ChunkedIOFd()
|
|||
delete [] read_buffer;
|
||||
delete [] write_buffer;
|
||||
safe_close(fd);
|
||||
|
||||
if ( partial )
|
||||
{
|
||||
delete [] partial->data;
|
||||
delete partial;
|
||||
}
|
||||
delete partial;
|
||||
}
|
||||
|
||||
bool ChunkedIOFd::Write(Chunk* chunk)
|
||||
|
@ -169,10 +164,9 @@ bool ChunkedIOFd::Write(Chunk* chunk)
|
|||
|
||||
while ( left )
|
||||
{
|
||||
Chunk* part = new Chunk;
|
||||
uint32 sz = min<uint32>(BUFFER_SIZE - sizeof(uint32), left);
|
||||
Chunk* part = new Chunk(new char[sz], sz);
|
||||
|
||||
part->len = min<uint32>(BUFFER_SIZE - sizeof(uint32), left);
|
||||
part->data = new char[part->len];
|
||||
memcpy(part->data, p, part->len);
|
||||
left -= part->len;
|
||||
p += part->len;
|
||||
|
@ -181,9 +175,7 @@ bool ChunkedIOFd::Write(Chunk* chunk)
|
|||
return false;
|
||||
}
|
||||
|
||||
delete [] chunk->data;
|
||||
delete chunk;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -239,7 +231,6 @@ bool ChunkedIOFd::PutIntoWriteBuffer(Chunk* chunk)
|
|||
memcpy(write_buffer + write_len, chunk->data, len);
|
||||
write_len += len;
|
||||
|
||||
delete [] chunk->data;
|
||||
delete chunk;
|
||||
|
||||
if ( network_time - last_flush > 0.005 )
|
||||
|
@ -362,9 +353,7 @@ ChunkedIO::Chunk* ChunkedIOFd::ExtractChunk()
|
|||
|
||||
read_pos += sizeof(uint32);
|
||||
|
||||
Chunk* chunk = new Chunk;
|
||||
chunk->len = len;
|
||||
chunk->data = new char[real_len];
|
||||
Chunk* chunk = new Chunk(new char[real_len], len);
|
||||
memcpy(chunk->data, read_buffer + read_pos, real_len);
|
||||
read_pos += real_len;
|
||||
|
||||
|
@ -375,17 +364,13 @@ ChunkedIO::Chunk* ChunkedIOFd::ExtractChunk()
|
|||
|
||||
ChunkedIO::Chunk* ChunkedIOFd::ConcatChunks(Chunk* c1, Chunk* c2)
|
||||
{
|
||||
Chunk* c = new Chunk;
|
||||
|
||||
c->len = c1->len + c2->len;
|
||||
c->data = new char[c->len];
|
||||
uint32 sz = c1->len + c2->len;
|
||||
Chunk* c = new Chunk(new char[sz], sz);
|
||||
|
||||
memcpy(c->data, c1->data, c1->len);
|
||||
memcpy(c->data + c1->len, c2->data, c2->len);
|
||||
|
||||
delete [] c1->data;
|
||||
delete c1;
|
||||
delete [] c2->data;
|
||||
delete c2;
|
||||
|
||||
return c;
|
||||
|
@ -627,7 +612,6 @@ void ChunkedIOFd::Clear()
|
|||
while ( pending_head )
|
||||
{
|
||||
ChunkQueue* next = pending_head->next;
|
||||
delete [] pending_head->chunk->data;
|
||||
delete pending_head->chunk;
|
||||
delete pending_head;
|
||||
pending_head = next;
|
||||
|
@ -946,7 +930,6 @@ bool ChunkedIOSSL::Flush()
|
|||
--stats.pending;
|
||||
delete q;
|
||||
|
||||
delete [] c->data;
|
||||
delete c;
|
||||
|
||||
write_state = LEN;
|
||||
|
@ -1063,7 +1046,10 @@ bool ChunkedIOSSL::Read(Chunk** chunk, bool mayblock)
|
|||
}
|
||||
|
||||
if ( ! read_chunk->data )
|
||||
{
|
||||
read_chunk->data = new char[read_chunk->len];
|
||||
read_chunk->free_func = Chunk::free_func_delete;
|
||||
}
|
||||
|
||||
if ( ! ReadData(read_chunk->data, read_chunk->len, &error) )
|
||||
return ! error;
|
||||
|
@ -1123,7 +1109,6 @@ void ChunkedIOSSL::Clear()
|
|||
while ( write_head )
|
||||
{
|
||||
Queue* next = write_head->next;
|
||||
delete [] write_head->chunk->data;
|
||||
delete write_head->chunk;
|
||||
delete write_head;
|
||||
write_head = next;
|
||||
|
@ -1231,12 +1216,13 @@ bool CompressedChunkedIO::Read(Chunk** chunk, bool may_block)
|
|||
return false;
|
||||
}
|
||||
|
||||
delete [] (*chunk)->data;
|
||||
(*chunk)->free_func((*chunk)->data);
|
||||
|
||||
uncompressed_bytes_read += uncompressed_len;
|
||||
|
||||
(*chunk)->len = uncompressed_len;
|
||||
(*chunk)->data = uncompressed;
|
||||
(*chunk)->free_func = Chunk::free_func_delete;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1280,8 +1266,9 @@ bool CompressedChunkedIO::Write(Chunk* chunk)
|
|||
memcpy(compressed, chunk->data, chunk->len);
|
||||
*(uint32*) (compressed + chunk->len) = 0; // uncompressed_length
|
||||
|
||||
delete [] chunk->data;
|
||||
chunk->free_func(chunk->data);
|
||||
chunk->data = compressed;
|
||||
chunk->free_func = Chunk::free_func_delete;
|
||||
chunk->len += 4;
|
||||
|
||||
DBG_LOG(DBG_CHUNKEDIO, "zlib write pass-through: size=%d", chunk->len);
|
||||
|
@ -1322,8 +1309,9 @@ bool CompressedChunkedIO::Write(Chunk* chunk)
|
|||
|
||||
*(uint32*) zout.next_out = original_size; // uncompressed_length
|
||||
|
||||
delete [] chunk->data;
|
||||
chunk->free_func(chunk->data);
|
||||
chunk->data = compressed;
|
||||
chunk->free_func = Chunk::free_func_delete;
|
||||
chunk->len =
|
||||
((char*) zout.next_out - compressed) + sizeof(uint32);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#ifdef NEED_KRB5_H
|
||||
# include <krb5.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
@ -26,10 +26,28 @@ public:
|
|||
ChunkedIO();
|
||||
virtual ~ChunkedIO() { }
|
||||
|
||||
typedef struct {
|
||||
struct Chunk {
|
||||
typedef void (*FreeFunc)(char*);
|
||||
static void free_func_free(char* data) { free(data); }
|
||||
static void free_func_delete(char* data) { delete [] data; }
|
||||
|
||||
Chunk()
|
||||
: data(), len(), free_func(free_func_delete)
|
||||
{ }
|
||||
|
||||
// Takes ownership of data.
|
||||
Chunk(char* arg_data, uint32 arg_len,
|
||||
FreeFunc arg_ff = free_func_delete)
|
||||
: data(arg_data), len(arg_len), free_func(arg_ff)
|
||||
{ }
|
||||
|
||||
~Chunk()
|
||||
{ free_func(data); }
|
||||
|
||||
char* data;
|
||||
uint32 len;
|
||||
} Chunk;
|
||||
FreeFunc free_func;
|
||||
};
|
||||
|
||||
// Initialization before any I/O operation is performed. Returns false
|
||||
// on any form of error.
|
||||
|
|
18
src/Conn.cc
18
src/Conn.cc
|
@ -15,6 +15,7 @@
|
|||
#include "binpac.h"
|
||||
#include "TunnelEncapsulation.h"
|
||||
#include "analyzer/Analyzer.h"
|
||||
#include "analyzer/Manager.h"
|
||||
|
||||
void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer,
|
||||
int arg_do_expire)
|
||||
|
@ -722,8 +723,8 @@ TimerMgr* Connection::GetTimerMgr() const
|
|||
void Connection::FlipRoles()
|
||||
{
|
||||
IPAddr tmp_addr = resp_addr;
|
||||
orig_addr = resp_addr;
|
||||
resp_addr = tmp_addr;
|
||||
resp_addr = orig_addr;
|
||||
orig_addr = tmp_addr;
|
||||
|
||||
uint32 tmp_port = resp_port;
|
||||
resp_port = orig_port;
|
||||
|
@ -742,6 +743,8 @@ void Connection::FlipRoles()
|
|||
|
||||
if ( root_analyzer )
|
||||
root_analyzer->FlipRoles();
|
||||
|
||||
analyzer_mgr->ApplyScheduledAnalyzers(this);
|
||||
}
|
||||
|
||||
unsigned int Connection::MemoryAllocation() const
|
||||
|
@ -808,6 +811,17 @@ void Connection::Describe(ODesc* d) const
|
|||
d->NL();
|
||||
}
|
||||
|
||||
void Connection::IDString(ODesc* d) const
|
||||
{
|
||||
d->Add(orig_addr);
|
||||
d->AddRaw(":", 1);
|
||||
d->Add(ntohs(orig_port));
|
||||
d->AddRaw(" > ", 3);
|
||||
d->Add(resp_addr);
|
||||
d->AddRaw(":", 1);
|
||||
d->Add(ntohs(resp_port));
|
||||
}
|
||||
|
||||
bool Connection::Serialize(SerialInfo* info) const
|
||||
{
|
||||
return SerialObj::Serialize(info);
|
||||
|
|
|
@ -204,6 +204,7 @@ public:
|
|||
bool IsPersistent() { return persistent; }
|
||||
|
||||
void Describe(ODesc* d) const;
|
||||
void IDString(ODesc* d) const;
|
||||
|
||||
TimerMgr* GetTimerMgr() const;
|
||||
|
||||
|
|
28
src/DFA.cc
28
src/DFA.cc
|
@ -211,9 +211,10 @@ void DFA_State::Dump(FILE* f, DFA_Machine* m)
|
|||
|
||||
if ( accept )
|
||||
{
|
||||
for ( int i = 0; i < accept->length(); ++i )
|
||||
fprintf(f, "%s accept #%d",
|
||||
i > 0 ? "," : "", int((*accept)[i]));
|
||||
AcceptingSet::const_iterator it;
|
||||
|
||||
for ( it = accept->begin(); it != accept->end(); ++it )
|
||||
fprintf(f, "%s accept #%d", it == accept->begin() ? "" : ",", *it);
|
||||
}
|
||||
|
||||
fprintf(f, "\n");
|
||||
|
@ -285,7 +286,7 @@ unsigned int DFA_State::Size()
|
|||
{
|
||||
return sizeof(*this)
|
||||
+ pad_size(sizeof(DFA_State*) * num_sym)
|
||||
+ (accept ? pad_size(sizeof(int) * accept->length()) : 0)
|
||||
+ (accept ? pad_size(sizeof(int) * accept->size()) : 0)
|
||||
+ (nfa_states ? pad_size(sizeof(NFA_State*) * nfa_states->length()) : 0)
|
||||
+ (meta_ec ? meta_ec->Size() : 0)
|
||||
+ (centry ? padded_sizeof(CacheEntry) : 0);
|
||||
|
@ -470,33 +471,20 @@ int DFA_Machine::StateSetToDFA_State(NFA_state_list* state_set,
|
|||
return 0;
|
||||
|
||||
AcceptingSet* accept = new AcceptingSet;
|
||||
|
||||
for ( int i = 0; i < state_set->length(); ++i )
|
||||
{
|
||||
int acc = (*state_set)[i]->Accept();
|
||||
|
||||
if ( acc != NO_ACCEPT )
|
||||
{
|
||||
int j;
|
||||
for ( j = 0; j < accept->length(); ++j )
|
||||
if ( (*accept)[j] == acc )
|
||||
break;
|
||||
|
||||
if ( j >= accept->length() )
|
||||
// It's not already present.
|
||||
accept->append(acc);
|
||||
}
|
||||
accept->insert(acc);
|
||||
}
|
||||
|
||||
if ( accept->length() == 0 )
|
||||
if ( accept->empty() )
|
||||
{
|
||||
delete accept;
|
||||
accept = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
accept->sort(int_list_cmp);
|
||||
accept->resize(0);
|
||||
}
|
||||
|
||||
DFA_State* ds = new DFA_State(state_count++, ec, state_set, accept);
|
||||
d = dfa_state_cache->Insert(ds, hash);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <openssl/md5.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
|
@ -385,7 +386,6 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode)
|
|||
dns_mapping_altered = 0;
|
||||
|
||||
dm_rec = 0;
|
||||
dns_fake_count = 0;
|
||||
|
||||
cache_name = dir = 0;
|
||||
|
||||
|
@ -443,6 +443,33 @@ bool DNS_Mgr::Init()
|
|||
return true;
|
||||
}
|
||||
|
||||
static TableVal* fake_name_lookup_result(const char* name)
|
||||
{
|
||||
uint32 hash[4];
|
||||
MD5(reinterpret_cast<const u_char*>(name), strlen(name),
|
||||
reinterpret_cast<u_char*>(hash));
|
||||
ListVal* hv = new ListVal(TYPE_ADDR);
|
||||
hv->Append(new AddrVal(hash));
|
||||
TableVal* tv = hv->ConvertToSet();
|
||||
Unref(hv);
|
||||
return tv;
|
||||
}
|
||||
|
||||
static const char* fake_text_lookup_result(const char* name)
|
||||
{
|
||||
static char tmp[32 + 256];
|
||||
snprintf(tmp, sizeof(tmp), "fake_text_lookup_result_%s", name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static const char* fake_addr_lookup_result(const IPAddr& addr)
|
||||
{
|
||||
static char tmp[128];
|
||||
snprintf(tmp, sizeof(tmp), "fake_addr_lookup_result_%s",
|
||||
addr.AsString().c_str());
|
||||
return tmp;
|
||||
}
|
||||
|
||||
TableVal* DNS_Mgr::LookupHost(const char* name)
|
||||
{
|
||||
if ( ! nb_dns )
|
||||
|
@ -452,11 +479,7 @@ TableVal* DNS_Mgr::LookupHost(const char* name)
|
|||
Init();
|
||||
|
||||
if ( mode == DNS_FAKE )
|
||||
{
|
||||
ListVal* hv = new ListVal(TYPE_ADDR);
|
||||
hv->Append(new AddrVal(uint32(++dns_fake_count)));
|
||||
return hv->ConvertToSet();
|
||||
}
|
||||
return fake_name_lookup_result(name);
|
||||
|
||||
if ( mode != DNS_PRIME )
|
||||
{
|
||||
|
@ -960,7 +983,7 @@ const char* DNS_Mgr::LookupAddrInCache(const IPAddr& addr)
|
|||
return d->names ? d->names[0] : "<\?\?\?>";
|
||||
}
|
||||
|
||||
TableVal* DNS_Mgr::LookupNameInCache(string name)
|
||||
TableVal* DNS_Mgr::LookupNameInCache(const string& name)
|
||||
{
|
||||
HostMap::iterator it = host_mappings.find(name);
|
||||
if ( it == host_mappings.end() )
|
||||
|
@ -990,7 +1013,7 @@ TableVal* DNS_Mgr::LookupNameInCache(string name)
|
|||
return tv6;
|
||||
}
|
||||
|
||||
const char* DNS_Mgr::LookupTextInCache(string name)
|
||||
const char* DNS_Mgr::LookupTextInCache(const string& name)
|
||||
{
|
||||
TextMap::iterator it = text_mappings.find(name);
|
||||
if ( it == text_mappings.end() )
|
||||
|
@ -1010,17 +1033,37 @@ const char* DNS_Mgr::LookupTextInCache(string name)
|
|||
return d->names ? d->names[0] : "<\?\?\?>";
|
||||
}
|
||||
|
||||
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback,
|
||||
TableVal* result)
|
||||
{
|
||||
callback->Resolved(result);
|
||||
Unref(result);
|
||||
delete callback;
|
||||
}
|
||||
|
||||
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback,
|
||||
const char* result)
|
||||
{
|
||||
callback->Resolved(result);
|
||||
delete callback;
|
||||
}
|
||||
|
||||
void DNS_Mgr::AsyncLookupAddr(const IPAddr& host, LookupCallback* callback)
|
||||
{
|
||||
if ( ! did_init )
|
||||
Init();
|
||||
|
||||
if ( mode == DNS_FAKE )
|
||||
{
|
||||
resolve_lookup_cb(callback, fake_addr_lookup_result(host));
|
||||
return;
|
||||
}
|
||||
|
||||
// Do we already know the answer?
|
||||
const char* name = LookupAddrInCache(host);
|
||||
if ( name )
|
||||
{
|
||||
callback->Resolved(name);
|
||||
delete callback;
|
||||
resolve_lookup_cb(callback, name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1044,18 +1087,22 @@ void DNS_Mgr::AsyncLookupAddr(const IPAddr& host, LookupCallback* callback)
|
|||
IssueAsyncRequests();
|
||||
}
|
||||
|
||||
void DNS_Mgr::AsyncLookupName(string name, LookupCallback* callback)
|
||||
void DNS_Mgr::AsyncLookupName(const string& name, LookupCallback* callback)
|
||||
{
|
||||
if ( ! did_init )
|
||||
Init();
|
||||
|
||||
if ( mode == DNS_FAKE )
|
||||
{
|
||||
resolve_lookup_cb(callback, fake_name_lookup_result(name.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Do we already know the answer?
|
||||
TableVal* addrs = LookupNameInCache(name);
|
||||
if ( addrs )
|
||||
{
|
||||
callback->Resolved(addrs);
|
||||
Unref(addrs);
|
||||
delete callback;
|
||||
resolve_lookup_cb(callback, addrs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1079,13 +1126,25 @@ void DNS_Mgr::AsyncLookupName(string name, LookupCallback* callback)
|
|||
IssueAsyncRequests();
|
||||
}
|
||||
|
||||
void DNS_Mgr::AsyncLookupNameText(string name, LookupCallback* callback)
|
||||
void DNS_Mgr::AsyncLookupNameText(const string& name, LookupCallback* callback)
|
||||
{
|
||||
if ( ! did_init )
|
||||
Init();
|
||||
|
||||
if ( mode == DNS_FAKE )
|
||||
{
|
||||
resolve_lookup_cb(callback, fake_text_lookup_result(name.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Do we already know the answer?
|
||||
TableVal* addrs;
|
||||
const char* txt = LookupTextInCache(name);
|
||||
|
||||
if ( txt )
|
||||
{
|
||||
resolve_lookup_cb(callback, txt);
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncRequest* req = 0;
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ public:
|
|||
int Save();
|
||||
|
||||
const char* LookupAddrInCache(const IPAddr& addr);
|
||||
TableVal* LookupNameInCache(string name);
|
||||
const char* LookupTextInCache(string name);
|
||||
TableVal* LookupNameInCache(const string& name);
|
||||
const char* LookupTextInCache(const string& name);
|
||||
|
||||
// Support for async lookups.
|
||||
class LookupCallback {
|
||||
|
@ -77,8 +77,8 @@ public:
|
|||
};
|
||||
|
||||
void AsyncLookupAddr(const IPAddr& host, LookupCallback* callback);
|
||||
void AsyncLookupName(string name, LookupCallback* callback);
|
||||
void AsyncLookupNameText(string name, LookupCallback* callback);
|
||||
void AsyncLookupName(const string& name, LookupCallback* callback);
|
||||
void AsyncLookupNameText(const string& name, LookupCallback* callback);
|
||||
|
||||
struct Stats {
|
||||
unsigned long requests; // These count only async requests.
|
||||
|
@ -163,8 +163,6 @@ protected:
|
|||
|
||||
RecordType* dm_rec;
|
||||
|
||||
int dns_fake_count; // used to generate unique fake replies
|
||||
|
||||
typedef list<LookupCallback*> CallbackList;
|
||||
|
||||
struct AsyncRequest {
|
||||
|
|
|
@ -192,6 +192,7 @@ static void parse_function_name(vector<ParseLocationRec>& result,
|
|||
string fullname = make_full_var_name(current_module.c_str(), s.c_str());
|
||||
debug_msg("Function %s not defined.\n", fullname.c_str());
|
||||
plr.type = plrUnknown;
|
||||
Unref(id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -199,6 +200,7 @@ static void parse_function_name(vector<ParseLocationRec>& result,
|
|||
{
|
||||
debug_msg("Function %s not declared.\n", id->Name());
|
||||
plr.type = plrUnknown;
|
||||
Unref(id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -206,6 +208,7 @@ static void parse_function_name(vector<ParseLocationRec>& result,
|
|||
{
|
||||
debug_msg("Function %s declared but not defined.\n", id->Name());
|
||||
plr.type = plrUnknown;
|
||||
Unref(id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -216,9 +219,12 @@ static void parse_function_name(vector<ParseLocationRec>& result,
|
|||
{
|
||||
debug_msg("Function %s is a built-in function\n", id->Name());
|
||||
plr.type = plrUnknown;
|
||||
Unref(id);
|
||||
return;
|
||||
}
|
||||
|
||||
Unref(id);
|
||||
|
||||
Stmt* body = 0; // the particular body we care about; 0 = all
|
||||
|
||||
if ( bodies.size() == 1 )
|
||||
|
|
|
@ -33,10 +33,12 @@ enum DebugStream {
|
|||
NUM_DBGS // Has to be last
|
||||
};
|
||||
|
||||
#define DBG_LOG(args...) debug_logger.Log(args)
|
||||
#define DBG_LOG_VERBOSE(args...) \
|
||||
if ( debug_logger.IsVerbose() ) \
|
||||
debug_logger.Log(args)
|
||||
#define DBG_LOG(stream, args...) \
|
||||
if ( debug_logger.IsEnabled(stream) ) \
|
||||
debug_logger.Log(stream, args)
|
||||
#define DBG_LOG_VERBOSE(stream, args...) \
|
||||
if ( debug_logger.IsVerbose() && debug_logger.IsEnabled(stream) ) \
|
||||
debug_logger.Log(stream, args)
|
||||
#define DBG_PUSH(stream) debug_logger.PushIndent(stream)
|
||||
#define DBG_POP(stream) debug_logger.PopIndent(stream)
|
||||
|
||||
|
|
68
src/Desc.cc
68
src/Desc.cc
|
@ -216,18 +216,32 @@ void ODesc::Indent()
|
|||
}
|
||||
}
|
||||
|
||||
static const char hex_chars[] = "0123456789abcdef";
|
||||
|
||||
static const char* find_first_unprintable(ODesc* d, const char* bytes, unsigned int n)
|
||||
static bool starts_with(const char* str1, const char* str2, size_t len)
|
||||
{
|
||||
if ( d->IsBinary() )
|
||||
for ( size_t i = 0; i < len; ++i )
|
||||
if ( str1[i] != str2[i] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t ODesc::StartsWithEscapeSequence(const char* start, const char* end)
|
||||
{
|
||||
if ( escape_sequences.empty() )
|
||||
return 0;
|
||||
|
||||
while ( n-- )
|
||||
escape_set::const_iterator it;
|
||||
|
||||
for ( it = escape_sequences.begin(); it != escape_sequences.end(); ++it )
|
||||
{
|
||||
if ( ! isprint(*bytes) )
|
||||
return bytes;
|
||||
++bytes;
|
||||
const string& esc_str = *it;
|
||||
size_t esc_len = esc_str.length();
|
||||
|
||||
if ( start + esc_len > end )
|
||||
continue;
|
||||
|
||||
if ( starts_with(start, esc_str.c_str(), esc_len) )
|
||||
return esc_len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -235,21 +249,23 @@ static const char* find_first_unprintable(ODesc* d, const char* bytes, unsigned
|
|||
|
||||
pair<const char*, size_t> ODesc::FirstEscapeLoc(const char* bytes, size_t n)
|
||||
{
|
||||
pair<const char*, size_t> p(find_first_unprintable(this, bytes, n), 1);
|
||||
typedef pair<const char*, size_t> escape_pos;
|
||||
|
||||
string str(bytes, n);
|
||||
list<string>::const_iterator it;
|
||||
for ( it = escape_sequences.begin(); it != escape_sequences.end(); ++it )
|
||||
if ( IsBinary() )
|
||||
return escape_pos(0, 0);
|
||||
|
||||
for ( size_t i = 0; i < n; ++i )
|
||||
{
|
||||
size_t pos = str.find(*it);
|
||||
if ( pos != string::npos && (p.first == 0 || bytes + pos < p.first) )
|
||||
{
|
||||
p.first = bytes + pos;
|
||||
p.second = it->size();
|
||||
}
|
||||
if ( ! isprint(bytes[i]) )
|
||||
return escape_pos(bytes + i, 1);
|
||||
|
||||
size_t len = StartsWithEscapeSequence(bytes + i, bytes + n);
|
||||
|
||||
if ( len )
|
||||
return escape_pos(bytes + i, len);
|
||||
}
|
||||
|
||||
return p;
|
||||
return escape_pos(0, 0);
|
||||
}
|
||||
|
||||
void ODesc::AddBytes(const void* bytes, unsigned int n)
|
||||
|
@ -266,21 +282,11 @@ void ODesc::AddBytes(const void* bytes, unsigned int n)
|
|||
while ( s < e )
|
||||
{
|
||||
pair<const char*, size_t> p = FirstEscapeLoc(s, e - s);
|
||||
|
||||
if ( p.first )
|
||||
{
|
||||
AddBytesRaw(s, p.first - s);
|
||||
if ( p.second == 1 )
|
||||
{
|
||||
char hex[6] = "\\x00";
|
||||
hex[2] = hex_chars[((*p.first) & 0xf0) >> 4];
|
||||
hex[3] = hex_chars[(*p.first) & 0x0f];
|
||||
AddBytesRaw(hex, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
string esc_str = get_escaped_string(string(p.first, p.second), true);
|
||||
AddBytesRaw(esc_str.c_str(), esc_str.size());
|
||||
}
|
||||
get_escaped_string(this, p.first, p.second, true);
|
||||
s = p.first + p.second;
|
||||
}
|
||||
else
|
||||
|
|
26
src/Desc.h
26
src/Desc.h
|
@ -4,7 +4,7 @@
|
|||
#define descriptor_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include "BroString.h"
|
||||
|
@ -54,16 +54,16 @@ public:
|
|||
void SetFlush(int arg_do_flush) { do_flush = arg_do_flush; }
|
||||
|
||||
void EnableEscaping();
|
||||
void AddEscapeSequence(const char* s) { escape_sequences.push_back(s); }
|
||||
void AddEscapeSequence(const char* s) { escape_sequences.insert(s); }
|
||||
void AddEscapeSequence(const char* s, size_t n)
|
||||
{ escape_sequences.push_back(string(s, n)); }
|
||||
{ escape_sequences.insert(string(s, n)); }
|
||||
void AddEscapeSequence(const string & s)
|
||||
{ escape_sequences.push_back(s); }
|
||||
void RemoveEscapeSequence(const char* s) { escape_sequences.remove(s); }
|
||||
{ escape_sequences.insert(s); }
|
||||
void RemoveEscapeSequence(const char* s) { escape_sequences.erase(s); }
|
||||
void RemoveEscapeSequence(const char* s, size_t n)
|
||||
{ escape_sequences.remove(string(s, n)); }
|
||||
{ escape_sequences.erase(string(s, n)); }
|
||||
void RemoveEscapeSequence(const string & s)
|
||||
{ escape_sequences.remove(s); }
|
||||
{ escape_sequences.erase(s); }
|
||||
|
||||
void PushIndent();
|
||||
void PopIndent();
|
||||
|
@ -163,6 +163,15 @@ protected:
|
|||
*/
|
||||
pair<const char*, size_t> FirstEscapeLoc(const char* bytes, size_t n);
|
||||
|
||||
/**
|
||||
* @param start start of string to check for starting with an espace
|
||||
* sequence.
|
||||
* @param end one byte past the last character in the string.
|
||||
* @return The number of bytes in the escape sequence that the string
|
||||
* starts with.
|
||||
*/
|
||||
size_t StartsWithEscapeSequence(const char* start, const char* end);
|
||||
|
||||
desc_type type;
|
||||
desc_style style;
|
||||
|
||||
|
@ -171,7 +180,8 @@ protected:
|
|||
unsigned int size; // size of buffer in bytes
|
||||
|
||||
bool escape; // escape unprintable characters in output?
|
||||
list<string> escape_sequences; // additional sequences of chars to escape
|
||||
typedef set<string> escape_set;
|
||||
escape_set escape_sequences; // additional sequences of chars to escape
|
||||
|
||||
BroFile* f; // or the file we're using.
|
||||
|
||||
|
|
|
@ -39,7 +39,10 @@ FuncType* EventHandler::FType()
|
|||
if ( id->Type()->Tag() != TYPE_FUNC )
|
||||
return 0;
|
||||
|
||||
return type = id->Type()->AsFuncType();
|
||||
type = id->Type()->AsFuncType();
|
||||
Unref(id);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void EventHandler::SetLocalHandler(Func* f)
|
||||
|
|
70
src/Expr.cc
70
src/Expr.cc
|
@ -3392,22 +3392,12 @@ bool HasFieldExpr::DoUnserialize(UnserialInfo* info)
|
|||
return UNSERIALIZE(¬_used) && UNSERIALIZE_STR(&field_name, 0) && UNSERIALIZE(&field);
|
||||
}
|
||||
|
||||
RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list,
|
||||
BroType* arg_type)
|
||||
RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list)
|
||||
: UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list)
|
||||
{
|
||||
ctor_type = 0;
|
||||
|
||||
if ( IsError() )
|
||||
return;
|
||||
|
||||
if ( arg_type && arg_type->Tag() != TYPE_RECORD )
|
||||
{
|
||||
Error("bad record constructor type", arg_type);
|
||||
SetError();
|
||||
return;
|
||||
}
|
||||
|
||||
// Spin through the list, which should be comprised of
|
||||
// either record's or record-field-assign, and build up a
|
||||
// record type to associate with this constructor.
|
||||
|
@ -3447,17 +3437,11 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list,
|
|||
}
|
||||
}
|
||||
|
||||
ctor_type = new RecordType(record_types);
|
||||
|
||||
if ( arg_type )
|
||||
SetType(arg_type->Ref());
|
||||
else
|
||||
SetType(ctor_type->Ref());
|
||||
SetType(new RecordType(record_types));
|
||||
}
|
||||
|
||||
RecordConstructorExpr::~RecordConstructorExpr()
|
||||
{
|
||||
Unref(ctor_type);
|
||||
}
|
||||
|
||||
Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
||||
|
@ -3483,7 +3467,7 @@ Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const
|
|||
Val* RecordConstructorExpr::Fold(Val* v) const
|
||||
{
|
||||
ListVal* lv = v->AsListVal();
|
||||
RecordType* rt = ctor_type->AsRecordType();
|
||||
RecordType* rt = type->AsRecordType();
|
||||
|
||||
if ( lv->Length() != rt->NumFields() )
|
||||
Internal("inconsistency evaluating record constructor");
|
||||
|
@ -3493,19 +3477,6 @@ Val* RecordConstructorExpr::Fold(Val* v) const
|
|||
for ( int i = 0; i < lv->Length(); ++i )
|
||||
rv->Assign(i, lv->Index(i)->Ref());
|
||||
|
||||
if ( ! same_type(rt, type) )
|
||||
{
|
||||
RecordVal* new_val = rv->CoerceTo(type->AsRecordType());
|
||||
|
||||
if ( new_val )
|
||||
{
|
||||
Unref(rv);
|
||||
rv = new_val;
|
||||
}
|
||||
else
|
||||
Internal("record constructor coercion failed");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -3521,16 +3492,12 @@ IMPLEMENT_SERIAL(RecordConstructorExpr, SER_RECORD_CONSTRUCTOR_EXPR);
|
|||
bool RecordConstructorExpr::DoSerialize(SerialInfo* info) const
|
||||
{
|
||||
DO_SERIALIZE(SER_RECORD_CONSTRUCTOR_EXPR, UnaryExpr);
|
||||
SERIALIZE_OPTIONAL(ctor_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RecordConstructorExpr::DoUnserialize(UnserialInfo* info)
|
||||
{
|
||||
DO_UNSERIALIZE(UnaryExpr);
|
||||
BroType* t = 0;
|
||||
UNSERIALIZE_OPTIONAL(t, RecordType::Unserialize(info));
|
||||
ctor_type = t->AsRecordType();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3819,7 +3786,9 @@ VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list,
|
|||
if ( constructor_list->Exprs().length() == 0 )
|
||||
{
|
||||
// vector().
|
||||
SetType(new ::VectorType(base_type(TYPE_ANY)));
|
||||
// By default, assign VOID type here. A vector with
|
||||
// void type set is seen as an unspecified vector.
|
||||
SetType(new ::VectorType(base_type(TYPE_VOID)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4212,6 +4181,26 @@ RecordCoerceExpr::~RecordCoerceExpr()
|
|||
delete [] map;
|
||||
}
|
||||
|
||||
Val* RecordCoerceExpr::InitVal(const BroType* t, Val* aggr) const
|
||||
{
|
||||
Val* v = Eval(0);
|
||||
|
||||
if ( v )
|
||||
{
|
||||
RecordVal* rv = v->AsRecordVal();
|
||||
RecordVal* ar = rv->CoerceTo(t->AsRecordType(), aggr);
|
||||
|
||||
if ( ar )
|
||||
{
|
||||
Unref(rv);
|
||||
return ar;
|
||||
}
|
||||
}
|
||||
|
||||
Error("bad record initializer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Val* RecordCoerceExpr::Fold(Val* v) const
|
||||
{
|
||||
RecordVal* val = new RecordVal(Type()->AsRecordType());
|
||||
|
@ -4236,6 +4225,13 @@ Val* RecordCoerceExpr::Fold(Val* v) const
|
|||
|
||||
assert(rhs || Type()->AsRecordType()->FieldDecl(i)->FindAttr(ATTR_OPTIONAL));
|
||||
|
||||
if ( ! rhs )
|
||||
{
|
||||
// Optional field is missing.
|
||||
val->Assign(i, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
BroType* rhs_type = rhs->Type();
|
||||
RecordType* val_type = val->Type()->AsRecordType();
|
||||
BroType* field_type = val_type->FieldType(i);
|
||||
|
|
|
@ -753,7 +753,7 @@ protected:
|
|||
|
||||
class RecordConstructorExpr : public UnaryExpr {
|
||||
public:
|
||||
RecordConstructorExpr(ListExpr* constructor_list, BroType* arg_type = 0);
|
||||
RecordConstructorExpr(ListExpr* constructor_list);
|
||||
~RecordConstructorExpr();
|
||||
|
||||
protected:
|
||||
|
@ -766,8 +766,6 @@ protected:
|
|||
void ExprDescribe(ODesc* d) const;
|
||||
|
||||
DECLARE_SERIAL(RecordConstructorExpr);
|
||||
|
||||
RecordType* ctor_type; // type inferred from the ctor expression list args
|
||||
};
|
||||
|
||||
class TableConstructorExpr : public UnaryExpr {
|
||||
|
@ -878,6 +876,7 @@ protected:
|
|||
friend class Expr;
|
||||
RecordCoerceExpr() { map = 0; }
|
||||
|
||||
Val* InitVal(const BroType* t, Val* aggr) const;
|
||||
Val* Fold(Val* v) const;
|
||||
|
||||
DECLARE_SERIAL(RecordCoerceExpr);
|
||||
|
|
13
src/Frag.cc
13
src/Frag.cc
|
@ -97,9 +97,9 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt)
|
|||
// Linux MTU discovery for UDP can do this, for example.
|
||||
s->Weird("fragment_with_DF", ip);
|
||||
|
||||
int offset = ip->FragOffset();
|
||||
int len = ip->TotalLen();
|
||||
int hdr_len = ip->HdrLen();
|
||||
uint16 offset = ip->FragOffset();
|
||||
uint32 len = ip->TotalLen();
|
||||
uint16 hdr_len = ip->HdrLen();
|
||||
|
||||
if ( len < hdr_len )
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt)
|
|||
return;
|
||||
}
|
||||
|
||||
int upper_seq = offset + len - hdr_len;
|
||||
uint64 upper_seq = offset + len - hdr_len;
|
||||
|
||||
if ( ! offset )
|
||||
// Make sure to use the first fragment header's next field.
|
||||
|
@ -178,7 +178,7 @@ void FragReassembler::Weird(const char* name) const
|
|||
}
|
||||
}
|
||||
|
||||
void FragReassembler::Overlap(const u_char* b1, const u_char* b2, int n)
|
||||
void FragReassembler::Overlap(const u_char* b1, const u_char* b2, uint64 n)
|
||||
{
|
||||
if ( memcmp((const void*) b1, (const void*) b2, n) )
|
||||
Weird("fragment_inconsistency");
|
||||
|
@ -231,7 +231,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
return;
|
||||
|
||||
// We have it all. Compute the expected size of the fragment.
|
||||
int n = proto_hdr_len + frag_size;
|
||||
uint64 n = proto_hdr_len + frag_size;
|
||||
|
||||
// It's possible that we have blocks associated with this fragment
|
||||
// that exceed this size, if we saw MF fragments (which don't lead
|
||||
|
@ -260,6 +260,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */)
|
|||
reporter->InternalWarning("bad fragment reassembly");
|
||||
DeleteTimer();
|
||||
Expire(network_time);
|
||||
delete [] pkt_start;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,14 +34,14 @@ public:
|
|||
|
||||
protected:
|
||||
void BlockInserted(DataBlock* start_block);
|
||||
void Overlap(const u_char* b1, const u_char* b2, int n);
|
||||
void Overlap(const u_char* b1, const u_char* b2, uint64 n);
|
||||
void Weird(const char* name) const;
|
||||
|
||||
u_char* proto_hdr;
|
||||
IP_Hdr* reassembled_pkt;
|
||||
int proto_hdr_len;
|
||||
uint16 proto_hdr_len;
|
||||
NetSessions* s;
|
||||
int frag_size; // size of fully reassembled fragment
|
||||
uint64 frag_size; // size of fully reassembled fragment
|
||||
uint16 next_proto; // first IPv6 fragment header's next proto field
|
||||
HashKey* key;
|
||||
|
||||
|
|
|
@ -475,6 +475,7 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
|
|||
|
||||
type = id->Type()->Ref();
|
||||
id->SetVal(new Val(this));
|
||||
Unref(id);
|
||||
}
|
||||
|
||||
BuiltinFunc::~BuiltinFunc()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "IPAddr.h"
|
||||
|
@ -45,6 +46,14 @@ HashKey* BuildConnIDHashKey(const ConnID& id)
|
|||
return new HashKey(&key, sizeof(key));
|
||||
}
|
||||
|
||||
static inline uint32_t bit_mask32(int bottom_bits)
|
||||
{
|
||||
if ( bottom_bits >= 32 )
|
||||
return 0xffffffff;
|
||||
|
||||
return (((uint32_t) 1) << bottom_bits) - 1;
|
||||
}
|
||||
|
||||
void IPAddr::Mask(int top_bits_to_keep)
|
||||
{
|
||||
if ( top_bits_to_keep < 0 || top_bits_to_keep > 128 )
|
||||
|
@ -53,25 +62,20 @@ void IPAddr::Mask(int top_bits_to_keep)
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t tmp[4];
|
||||
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
|
||||
uint32_t mask_bits[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
|
||||
std::ldiv_t res = std::ldiv(top_bits_to_keep, 32);
|
||||
|
||||
int word = 3;
|
||||
int bits_to_chop = 128 - top_bits_to_keep;
|
||||
if ( res.quot < 4 )
|
||||
mask_bits[res.quot] =
|
||||
htonl(mask_bits[res.quot] & ~bit_mask32(32 - res.rem));
|
||||
|
||||
while ( bits_to_chop >= 32 )
|
||||
{
|
||||
tmp[word] = 0;
|
||||
--word;
|
||||
bits_to_chop -= 32;
|
||||
}
|
||||
for ( unsigned int i = res.quot + 1; i < 4; ++i )
|
||||
mask_bits[i] = 0;
|
||||
|
||||
uint32_t w = ntohl(tmp[word]);
|
||||
w >>= bits_to_chop;
|
||||
w <<= bits_to_chop;
|
||||
tmp[word] = htonl(w);
|
||||
uint32_t* p = reinterpret_cast<uint32_t*>(in6.s6_addr);
|
||||
|
||||
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
|
||||
for ( unsigned int i = 0; i < 4; ++i )
|
||||
p[i] &= mask_bits[i];
|
||||
}
|
||||
|
||||
void IPAddr::ReverseMask(int top_bits_to_chop)
|
||||
|
@ -82,25 +86,19 @@ void IPAddr::ReverseMask(int top_bits_to_chop)
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t tmp[4];
|
||||
memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr));
|
||||
uint32_t mask_bits[4] = { 0, 0, 0, 0 };
|
||||
std::ldiv_t res = std::ldiv(top_bits_to_chop, 32);
|
||||
|
||||
int word = 0;
|
||||
int bits_to_chop = top_bits_to_chop;
|
||||
if ( res.quot < 4 )
|
||||
mask_bits[res.quot] = htonl(bit_mask32(32 - res.rem));
|
||||
|
||||
while ( bits_to_chop >= 32 )
|
||||
{
|
||||
tmp[word] = 0;
|
||||
++word;
|
||||
bits_to_chop -= 32;
|
||||
}
|
||||
for ( unsigned int i = res.quot + 1; i < 4; ++i )
|
||||
mask_bits[i] = 0xffffffff;
|
||||
|
||||
uint32_t w = ntohl(tmp[word]);
|
||||
w <<= bits_to_chop;
|
||||
w >>= bits_to_chop;
|
||||
tmp[word] = htonl(w);
|
||||
uint32_t* p = reinterpret_cast<uint32_t*>(in6.s6_addr);
|
||||
|
||||
memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr));
|
||||
for ( unsigned int i = 0; i < 4; ++i )
|
||||
p[i] &= mask_bits[i];
|
||||
}
|
||||
|
||||
void IPAddr::Init(const std::string& s)
|
||||
|
|
81
src/Net.cc
81
src/Net.cc
|
@ -27,7 +27,6 @@
|
|||
#include "Reporter.h"
|
||||
#include "Net.h"
|
||||
#include "Anon.h"
|
||||
#include "PacketSort.h"
|
||||
#include "Serializer.h"
|
||||
#include "PacketDumper.h"
|
||||
|
||||
|
@ -58,8 +57,6 @@ double bro_start_network_time; // timestamp of first packet
|
|||
double last_watchdog_proc_time = 0.0; // value of above during last watchdog
|
||||
bool terminating = false; // whether we're done reading and finishing up
|
||||
|
||||
PacketSortGlobalPQ* packet_sorter = 0;
|
||||
|
||||
const struct pcap_pkthdr* current_hdr = 0;
|
||||
const u_char* current_pkt = 0;
|
||||
int current_dispatched = 0;
|
||||
|
@ -286,9 +283,6 @@ void net_init(name_list& interfaces, name_list& readfiles,
|
|||
|
||||
init_ip_addr_anonymizers();
|
||||
|
||||
if ( packet_sort_window > 0 )
|
||||
packet_sorter = new PacketSortGlobalPQ();
|
||||
|
||||
sessions = new NetSessions();
|
||||
|
||||
if ( do_watchdog )
|
||||
|
@ -313,14 +307,12 @@ void expire_timers(PktSrc* src_ps)
|
|||
|
||||
void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* pkt, int hdr_size,
|
||||
PktSrc* src_ps, PacketSortElement* pkt_elem)
|
||||
PktSrc* src_ps)
|
||||
{
|
||||
if ( ! bro_start_network_time )
|
||||
bro_start_network_time = t;
|
||||
|
||||
TimerMgr* tmgr =
|
||||
src_ps ? sessions->LookupTimerMgr(src_ps->GetCurrentTag())
|
||||
: timer_mgr;
|
||||
TimerMgr* tmgr = sessions->LookupTimerMgr(src_ps->GetCurrentTag());
|
||||
|
||||
// network_time never goes back.
|
||||
network_time = tmgr->Time() < t ? t : tmgr->Time();
|
||||
|
@ -351,7 +343,7 @@ void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr,
|
|||
}
|
||||
}
|
||||
|
||||
sessions->DispatchPacket(t, hdr, pkt, hdr_size, src_ps, pkt_elem);
|
||||
sessions->DispatchPacket(t, hdr, pkt, hdr_size, src_ps);
|
||||
mgr.Drain();
|
||||
|
||||
if ( sp )
|
||||
|
@ -367,62 +359,11 @@ void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr,
|
|||
current_pktsrc = 0;
|
||||
}
|
||||
|
||||
int process_packet_sorter(double latest_packet_time)
|
||||
{
|
||||
if ( ! packet_sorter )
|
||||
return 0;
|
||||
|
||||
double min_t = latest_packet_time - packet_sort_window;
|
||||
|
||||
int num_pkts_dispatched = 0;
|
||||
PacketSortElement* pkt_elem;
|
||||
|
||||
// Dispatch packets in the packet_sorter until timestamp min_t.
|
||||
// It's possible that zero or multiple packets are dispatched.
|
||||
while ( (pkt_elem = packet_sorter->RemoveMin(min_t)) != 0 )
|
||||
{
|
||||
net_packet_dispatch(pkt_elem->TimeStamp(),
|
||||
pkt_elem->Hdr(), pkt_elem->Pkt(),
|
||||
pkt_elem->HdrSize(), pkt_elem->Src(),
|
||||
pkt_elem);
|
||||
++num_pkts_dispatched;
|
||||
delete pkt_elem;
|
||||
}
|
||||
|
||||
return num_pkts_dispatched;
|
||||
}
|
||||
|
||||
void net_packet_arrival(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* pkt, int hdr_size,
|
||||
PktSrc* src_ps)
|
||||
{
|
||||
if ( packet_sorter )
|
||||
{
|
||||
// Note that when we enable packet sorter, there will
|
||||
// be a small window between the time packet arrives
|
||||
// to Bro and when it is processed ("dispatched"). We
|
||||
// define network_time to be the latest timestamp for
|
||||
// packets *dispatched* so far (usually that's the
|
||||
// timestamp of the current packet).
|
||||
|
||||
// Add the packet to the packet_sorter.
|
||||
packet_sorter->Add(
|
||||
new PacketSortElement(src_ps, t, hdr, pkt, hdr_size));
|
||||
|
||||
// Do we have any packets to dispatch from packet_sorter?
|
||||
process_packet_sorter(t);
|
||||
}
|
||||
else
|
||||
// Otherwise we dispatch the packet immediately
|
||||
net_packet_dispatch(t, hdr, pkt, hdr_size, src_ps, 0);
|
||||
}
|
||||
|
||||
void net_run()
|
||||
{
|
||||
set_processing_status("RUNNING", "net_run");
|
||||
|
||||
while ( io_sources.Size() ||
|
||||
(packet_sorter && ! packet_sorter->Empty()) ||
|
||||
(BifConst::exit_only_after_terminate && ! terminating) )
|
||||
{
|
||||
double ts;
|
||||
|
@ -445,14 +386,12 @@ void net_run()
|
|||
current_iosrc = src;
|
||||
|
||||
if ( src )
|
||||
src->Process(); // which will call net_packet_arrival()
|
||||
src->Process(); // which will call net_packet_dispatch()
|
||||
|
||||
else if ( reading_live && ! pseudo_realtime)
|
||||
{ // live but no source is currently active
|
||||
double ct = current_time();
|
||||
if ( packet_sorter && ! packet_sorter->Empty() )
|
||||
process_packet_sorter(ct);
|
||||
else if ( ! net_is_processing_suspended() )
|
||||
if ( ! net_is_processing_suspended() )
|
||||
{
|
||||
// Take advantage of the lull to get up to
|
||||
// date on timers and events.
|
||||
|
@ -462,15 +401,6 @@ void net_run()
|
|||
}
|
||||
}
|
||||
|
||||
else if ( packet_sorter && ! packet_sorter->Empty() )
|
||||
{
|
||||
// We are no longer reading live; done with all the
|
||||
// sources.
|
||||
// Drain packets remaining in the packet sorter.
|
||||
process_packet_sorter(
|
||||
network_time + packet_sort_window + 1000000);
|
||||
}
|
||||
|
||||
else if ( (have_pending_timers || using_communication) &&
|
||||
! pseudo_realtime )
|
||||
{
|
||||
|
@ -581,7 +511,6 @@ void net_delete()
|
|||
set_processing_status("TERMINATING", "net_delete");
|
||||
|
||||
delete sessions;
|
||||
delete packet_sorter;
|
||||
|
||||
for ( int i = 0; i < NUM_ADDR_ANONYMIZATION_METHODS; ++i )
|
||||
delete ip_anonymizer[i];
|
||||
|
|
|
@ -20,7 +20,7 @@ extern void net_run();
|
|||
extern void net_get_final_stats();
|
||||
extern void net_finish(int drain_events);
|
||||
extern void net_delete(); // Reclaim all memory, etc.
|
||||
extern void net_packet_arrival(double t, const struct pcap_pkthdr* hdr,
|
||||
extern void net_packet_dispatch(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* pkt, int hdr_size,
|
||||
PktSrc* src_ps);
|
||||
extern int net_packet_match(BPF_Program* fp, const u_char* pkt,
|
||||
|
|
|
@ -20,6 +20,8 @@ TableType* string_set;
|
|||
TableType* string_array;
|
||||
TableType* count_set;
|
||||
VectorType* string_vec;
|
||||
VectorType* mime_matches;
|
||||
RecordType* mime_match;
|
||||
|
||||
int watchdog_interval;
|
||||
|
||||
|
@ -47,8 +49,6 @@ int tcp_max_initial_window;
|
|||
int tcp_max_above_hole_without_any_acks;
|
||||
int tcp_excessive_data_without_further_acks;
|
||||
|
||||
RecordType* x509_type;
|
||||
|
||||
RecordType* socks_address;
|
||||
|
||||
double non_analyzed_lifetime;
|
||||
|
@ -155,8 +155,6 @@ int table_incremental_step;
|
|||
|
||||
RecordType* packet_type;
|
||||
|
||||
double packet_sort_window;
|
||||
|
||||
double connection_status_update_interval;
|
||||
|
||||
StringVal* state_dir;
|
||||
|
@ -331,6 +329,8 @@ void init_net_var()
|
|||
string_set = internal_type("string_set")->AsTableType();
|
||||
string_array = internal_type("string_array")->AsTableType();
|
||||
string_vec = internal_type("string_vec")->AsVectorType();
|
||||
mime_match = internal_type("mime_match")->AsRecordType();
|
||||
mime_matches = internal_type("mime_matches")->AsVectorType();
|
||||
|
||||
ignore_checksums = opt_internal_int("ignore_checksums");
|
||||
partial_connection_ok = opt_internal_int("partial_connection_ok");
|
||||
|
@ -355,8 +355,6 @@ void init_net_var()
|
|||
tcp_excessive_data_without_further_acks =
|
||||
opt_internal_int("tcp_excessive_data_without_further_acks");
|
||||
|
||||
x509_type = internal_type("X509")->AsRecordType();
|
||||
|
||||
socks_address = internal_type("SOCKS::Address")->AsRecordType();
|
||||
|
||||
non_analyzed_lifetime = opt_internal_double("non_analyzed_lifetime");
|
||||
|
@ -479,8 +477,6 @@ void init_net_var()
|
|||
|
||||
packet_type = internal_type("packet")->AsRecordType();
|
||||
|
||||
packet_sort_window = opt_internal_double("packet_sort_window");
|
||||
|
||||
orig_addr_anonymization = opt_internal_int("orig_addr_anonymization");
|
||||
resp_addr_anonymization = opt_internal_int("resp_addr_anonymization");
|
||||
other_addr_anonymization = opt_internal_int("other_addr_anonymization");
|
||||
|
|
|
@ -23,6 +23,8 @@ extern TableType* string_set;
|
|||
extern TableType* string_array;
|
||||
extern TableType* count_set;
|
||||
extern VectorType* string_vec;
|
||||
extern VectorType* mime_matches;
|
||||
extern RecordType* mime_match;
|
||||
|
||||
extern int watchdog_interval;
|
||||
|
||||
|
@ -50,8 +52,6 @@ extern int tcp_max_initial_window;
|
|||
extern int tcp_max_above_hole_without_any_acks;
|
||||
extern int tcp_excessive_data_without_further_acks;
|
||||
|
||||
extern RecordType* x509_type;
|
||||
|
||||
extern RecordType* socks_address;
|
||||
|
||||
extern double non_analyzed_lifetime;
|
||||
|
@ -158,8 +158,6 @@ extern int table_incremental_step;
|
|||
|
||||
extern RecordType* packet_type;
|
||||
|
||||
extern double packet_sort_window;
|
||||
|
||||
extern int orig_addr_anonymization, resp_addr_anonymization;
|
||||
extern int other_addr_anonymization;
|
||||
extern TableVal* preserve_orig_addr;
|
||||
|
|
|
@ -1,364 +0,0 @@
|
|||
#include "IP.h"
|
||||
#include "PacketSort.h"
|
||||
|
||||
const bool DEBUG_packetsort = false;
|
||||
|
||||
PacketSortElement::PacketSortElement(PktSrc* arg_src,
|
||||
double arg_timestamp, const struct pcap_pkthdr* arg_hdr,
|
||||
const u_char* arg_pkt, int arg_hdr_size)
|
||||
{
|
||||
src = arg_src;
|
||||
timestamp = arg_timestamp;
|
||||
hdr = *arg_hdr;
|
||||
hdr_size = arg_hdr_size;
|
||||
|
||||
pkt = new u_char[hdr.caplen];
|
||||
memcpy(pkt, arg_pkt, hdr.caplen);
|
||||
|
||||
is_tcp = 0;
|
||||
ip_hdr = 0;
|
||||
tcp_flags = 0;
|
||||
endp = 0;
|
||||
payload_length = 0;
|
||||
key = 0;
|
||||
|
||||
// Now check if it is a "parsable" TCP packet.
|
||||
uint32 caplen = hdr.caplen;
|
||||
uint32 tcp_offset;
|
||||
|
||||
if ( caplen >= sizeof(struct ip) + hdr_size )
|
||||
{
|
||||
const struct ip* ip = (const struct ip*) (pkt + hdr_size);
|
||||
if ( ip->ip_v == 4 )
|
||||
ip_hdr = new IP_Hdr(ip, false);
|
||||
else if ( ip->ip_v == 6 && (caplen >= sizeof(struct ip6_hdr) + hdr_size) )
|
||||
ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false, caplen - hdr_size);
|
||||
else
|
||||
// Weird will be generated later in NetSessions::NextPacket.
|
||||
return;
|
||||
|
||||
if ( ip_hdr->NextProto() == IPPROTO_TCP &&
|
||||
// Note: can't sort fragmented packets
|
||||
( ! ip_hdr->IsFragment() ) )
|
||||
{
|
||||
tcp_offset = hdr_size + ip_hdr->HdrLen();
|
||||
if ( caplen >= tcp_offset + sizeof(struct tcphdr) )
|
||||
{
|
||||
const struct tcphdr* tp = (const struct tcphdr*)
|
||||
(pkt + tcp_offset);
|
||||
|
||||
id.src_addr = ip_hdr->SrcAddr();
|
||||
id.dst_addr = ip_hdr->DstAddr();
|
||||
id.src_port = tp->th_sport;
|
||||
id.dst_port = tp->th_dport;
|
||||
id.is_one_way = 0;
|
||||
|
||||
endp = addr_port_canon_lt(id.src_addr,
|
||||
id.src_port,
|
||||
id.dst_addr,
|
||||
id.dst_port) ? 0 : 1;
|
||||
|
||||
seq[endp] = ntohl(tp->th_seq);
|
||||
|
||||
if ( tp->th_flags & TH_ACK )
|
||||
seq[1-endp] = ntohl(tp->th_ack);
|
||||
else
|
||||
seq[1-endp] = 0;
|
||||
|
||||
tcp_flags = tp->th_flags;
|
||||
|
||||
// DEBUG_MSG("%.6f: %u, %u\n", timestamp, seq[0], seq[1]);
|
||||
|
||||
payload_length = ip_hdr->PayloadLen() - tp->th_off * 4;
|
||||
|
||||
key = BuildConnIDHashKey(id);
|
||||
|
||||
is_tcp = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( DEBUG_packetsort && ! is_tcp )
|
||||
DEBUG_MSG("%.6f non-TCP packet\n", timestamp);
|
||||
}
|
||||
|
||||
PacketSortElement::~PacketSortElement()
|
||||
{
|
||||
delete [] pkt;
|
||||
delete ip_hdr;
|
||||
delete key;
|
||||
}
|
||||
|
||||
int PacketSortPQ::Timestamp_Cmp(PacketSortElement* a, PacketSortElement* b)
|
||||
{
|
||||
double d = a->timestamp - b->timestamp;
|
||||
|
||||
if ( d > 0 ) return 1;
|
||||
else if ( d < 0 ) return -1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
int PacketSortPQ::UpdatePQ(PacketSortElement* prev_e, PacketSortElement* new_e)
|
||||
{
|
||||
int index = prev_e->pq_index[pq_level];
|
||||
|
||||
new_e->pq_index[pq_level] = index;
|
||||
pq[index] = new_e;
|
||||
|
||||
if ( Cmp(prev_e, new_e) > 0 )
|
||||
return FixUp(new_e, index);
|
||||
else
|
||||
{
|
||||
FixDown(new_e, index);
|
||||
return index == 0;
|
||||
}
|
||||
}
|
||||
|
||||
int PacketSortPQ::AddToPQ(PacketSortElement* new_e)
|
||||
{
|
||||
int index = pq.size();
|
||||
|
||||
new_e->pq_index[pq_level] = index;
|
||||
pq.push_back(new_e);
|
||||
|
||||
return FixUp(new_e, index);
|
||||
}
|
||||
|
||||
int PacketSortPQ::RemoveFromPQ(PacketSortElement* prev_e)
|
||||
{
|
||||
if ( pq.size() > 1 )
|
||||
{
|
||||
PacketSortElement* new_e = pq[pq.size() - 1];
|
||||
pq.pop_back();
|
||||
return UpdatePQ(prev_e, new_e);
|
||||
}
|
||||
else
|
||||
{
|
||||
pq.pop_back();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void PacketSortPQ::Assign(int k, PacketSortElement* e)
|
||||
{
|
||||
pq[k] = e;
|
||||
e->pq_index[pq_level] = k;
|
||||
}
|
||||
|
||||
PacketSortConnPQ::~PacketSortConnPQ()
|
||||
{
|
||||
// Delete elements only in ConnPQ (not in GlobalPQ) to avoid
|
||||
// double delete.
|
||||
for ( int i = 0; i < (int) pq.size(); ++i )
|
||||
{
|
||||
delete pq[i];
|
||||
pq[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int PacketSortConnPQ::Cmp(PacketSortElement* a, PacketSortElement* b)
|
||||
{
|
||||
// Note: here we do not distinguish between packets without
|
||||
// an ACK and packets with seq/ack of 0. The later will sorted
|
||||
// only by their timestamps.
|
||||
|
||||
if ( a->seq[0] && b->seq[0] && a->seq[0] != b->seq[0] )
|
||||
return (a->seq[0] > b->seq[0]) ? 1 : -1;
|
||||
|
||||
else if ( a->seq[1] && b->seq[1] && a->seq[1] != b->seq[1] )
|
||||
return (a->seq[1] > b->seq[1]) ? 1 : -1;
|
||||
|
||||
else
|
||||
return Timestamp_Cmp(a, b);
|
||||
}
|
||||
|
||||
int PacketSortPQ::FixUp(PacketSortElement* e, int k)
|
||||
{
|
||||
if ( k == 0 )
|
||||
{
|
||||
Assign(0, e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parent = (k-1) / 2;
|
||||
if ( Cmp(pq[parent], e) > 0 )
|
||||
{
|
||||
Assign(k, pq[parent]);
|
||||
return FixUp(e, parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assign(k, e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PacketSortPQ::FixDown(PacketSortElement* e, int k)
|
||||
{
|
||||
uint32 kid = k * 2 + 1;
|
||||
|
||||
if ( kid >= pq.size() )
|
||||
{
|
||||
Assign(k, e);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( kid + 1 < pq.size() && Cmp(pq[kid], pq[kid+1]) > 0 )
|
||||
++kid;
|
||||
|
||||
if ( Cmp(e, pq[kid]) > 0 )
|
||||
{
|
||||
Assign(k, pq[kid]);
|
||||
FixDown(e, kid);
|
||||
}
|
||||
else
|
||||
Assign(k, e);
|
||||
}
|
||||
|
||||
|
||||
int PacketSortConnPQ::Add(PacketSortElement* e)
|
||||
{
|
||||
#if 0
|
||||
int endp = e->endp;
|
||||
uint32 end_seq = e->seq[endp] + e->payload_length;
|
||||
|
||||
int p = 1 - endp;
|
||||
if ( (e->tcp_flags & TH_RST) && ! (e->tcp_flags & TH_ACK) )
|
||||
{
|
||||
DEBUG_MSG("%.6f %c: %u -> %u\n",
|
||||
e->TimeStamp(), (p == endp) ? 'S' : 'A',
|
||||
e->seq[p], next_seq[p]);
|
||||
e->seq[p] = next_seq[p];
|
||||
}
|
||||
|
||||
if ( end_seq > next_seq[endp] )
|
||||
next_seq[endp] = end_seq;
|
||||
#endif
|
||||
|
||||
return AddToPQ(e);
|
||||
}
|
||||
|
||||
void PacketSortConnPQ::UpdateDeliveredSeq(int endp, int seq, int len, int ack)
|
||||
{
|
||||
if ( delivered_seq[endp] == 0 || delivered_seq[endp] == seq )
|
||||
delivered_seq[endp] = seq + len;
|
||||
if ( ack > delivered_seq[1 - endp] )
|
||||
delivered_seq[endp] = ack;
|
||||
}
|
||||
|
||||
bool PacketSortConnPQ::IsContentGapSafe(PacketSortElement* e)
|
||||
{
|
||||
int ack = e->seq[1 - e->endp];
|
||||
return ack <= delivered_seq[1 - e->endp];
|
||||
}
|
||||
|
||||
int PacketSortConnPQ::Remove(PacketSortElement* e)
|
||||
{
|
||||
int ret = RemoveFromPQ(e);
|
||||
UpdateDeliveredSeq(e->endp, e->seq[e->endp], e->payload_length,
|
||||
e->seq[1 - e->endp]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void DeleteConnPQ(void* p)
|
||||
{
|
||||
delete (PacketSortConnPQ*) p;
|
||||
}
|
||||
|
||||
PacketSortGlobalPQ::PacketSortGlobalPQ()
|
||||
{
|
||||
pq_level = GLOBAL_PQ;
|
||||
conn_pq_table.SetDeleteFunc(DeleteConnPQ);
|
||||
}
|
||||
|
||||
PacketSortGlobalPQ::~PacketSortGlobalPQ()
|
||||
{
|
||||
// Destruction of PacketSortConnPQ will delete all conn_pq's.
|
||||
}
|
||||
|
||||
int PacketSortGlobalPQ::Add(PacketSortElement* e)
|
||||
{
|
||||
if ( e->is_tcp )
|
||||
{
|
||||
// TCP packets are sorted by sequence numbers
|
||||
PacketSortConnPQ* conn_pq = FindConnPQ(e);
|
||||
PacketSortElement* prev_min = conn_pq->Min();
|
||||
|
||||
if ( conn_pq->Add(e) )
|
||||
{
|
||||
ASSERT(conn_pq->Min() != prev_min);
|
||||
|
||||
if ( prev_min )
|
||||
return UpdatePQ(prev_min, e);
|
||||
else
|
||||
return AddToPQ(e);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ASSERT(conn_pq->Min() == prev_min);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return AddToPQ(e);
|
||||
}
|
||||
|
||||
PacketSortElement* PacketSortGlobalPQ::RemoveMin(double timestamp)
|
||||
{
|
||||
PacketSortElement* e = Min();
|
||||
|
||||
if ( ! e )
|
||||
return 0;
|
||||
|
||||
if ( e->is_tcp )
|
||||
{
|
||||
PacketSortConnPQ* conn_pq = FindConnPQ(e);
|
||||
|
||||
#if 0
|
||||
// Note: the content gap safety check does not work
|
||||
// because we remove the state for a connection once
|
||||
// it has no packet in the priority queue.
|
||||
|
||||
// Do not deliver e if it arrives later than timestamp,
|
||||
// and is not content-gap-safe.
|
||||
if ( e->timestamp > timestamp &&
|
||||
! conn_pq->IsContentGapSafe(e) )
|
||||
return 0;
|
||||
#else
|
||||
if ( e->timestamp > timestamp )
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
conn_pq->Remove(e);
|
||||
PacketSortElement* new_e = conn_pq->Min();
|
||||
|
||||
if ( new_e )
|
||||
UpdatePQ(e, new_e);
|
||||
else
|
||||
{
|
||||
RemoveFromPQ(e);
|
||||
conn_pq_table.Remove(e->key);
|
||||
delete conn_pq;
|
||||
}
|
||||
}
|
||||
else
|
||||
RemoveFromPQ(e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
PacketSortConnPQ* PacketSortGlobalPQ::FindConnPQ(PacketSortElement* e)
|
||||
{
|
||||
if ( ! e->is_tcp )
|
||||
reporter->InternalError("cannot find a connection for an invalid id");
|
||||
|
||||
PacketSortConnPQ* pq = (PacketSortConnPQ*) conn_pq_table.Lookup(e->key);
|
||||
if ( ! pq )
|
||||
{
|
||||
pq = new PacketSortConnPQ();
|
||||
conn_pq_table.Insert(e->key, pq);
|
||||
}
|
||||
|
||||
return pq;
|
||||
}
|
132
src/PacketSort.h
132
src/PacketSort.h
|
@ -1,132 +0,0 @@
|
|||
#ifndef packetsort_h
|
||||
#define packetsort_h
|
||||
|
||||
// Timestamps can be imprecise and even inconsistent among packets
|
||||
// from different sources. This class tries to guess a "correct"
|
||||
// order by looking at TCP sequence numbers.
|
||||
//
|
||||
// In particular, it tries to eliminate "false" content gaps.
|
||||
|
||||
#include "Dict.h"
|
||||
#include "Conn.h"
|
||||
|
||||
enum {
|
||||
CONN_PQ,
|
||||
GLOBAL_PQ,
|
||||
NUM_OF_PQ_LEVEL,
|
||||
};
|
||||
|
||||
class PktSrc;
|
||||
|
||||
class PacketSortElement {
|
||||
public:
|
||||
PacketSortElement(PktSrc* src, double timestamp,
|
||||
const struct pcap_pkthdr* hdr,
|
||||
const u_char* pkt, int hdr_size);
|
||||
~PacketSortElement();
|
||||
|
||||
PktSrc* Src() const { return src; }
|
||||
double TimeStamp() const { return timestamp; }
|
||||
const struct pcap_pkthdr* Hdr() const { return &hdr; }
|
||||
const u_char* Pkt() const { return pkt; }
|
||||
int HdrSize() const { return hdr_size; }
|
||||
const IP_Hdr* IPHdr() const { return ip_hdr; }
|
||||
|
||||
protected:
|
||||
PktSrc* src;
|
||||
double timestamp;
|
||||
struct pcap_pkthdr hdr;
|
||||
u_char* pkt;
|
||||
int hdr_size;
|
||||
|
||||
IP_Hdr* ip_hdr;
|
||||
int is_tcp;
|
||||
ConnID id;
|
||||
uint32 seq[2]; // indexed by endpoint
|
||||
int tcp_flags;
|
||||
int endp; // 0 or 1
|
||||
int payload_length;
|
||||
|
||||
HashKey* key;
|
||||
|
||||
int pq_index[NUM_OF_PQ_LEVEL];
|
||||
|
||||
friend class PacketSortPQ;
|
||||
friend class PacketSortConnPQ;
|
||||
friend class PacketSortGlobalPQ;
|
||||
};
|
||||
|
||||
class PacketSortPQ {
|
||||
public:
|
||||
PacketSortPQ()
|
||||
{ pq_level = -1; }
|
||||
virtual ~PacketSortPQ() {}
|
||||
|
||||
PacketSortElement* Min() const { return (pq.size() > 0) ? pq[0] : 0; }
|
||||
|
||||
protected:
|
||||
virtual int Cmp(PacketSortElement* a, PacketSortElement* b) = 0;
|
||||
int Timestamp_Cmp(PacketSortElement* a, PacketSortElement* b);
|
||||
|
||||
int UpdatePQ(PacketSortElement* prev_e, PacketSortElement* new_e);
|
||||
int AddToPQ(PacketSortElement* e);
|
||||
int RemoveFromPQ(PacketSortElement* e);
|
||||
|
||||
void Assign(int k, PacketSortElement* e);
|
||||
int FixUp(PacketSortElement* e, int k);
|
||||
void FixDown(PacketSortElement* e, int k);
|
||||
|
||||
vector<PacketSortElement*> pq;
|
||||
int pq_level;
|
||||
};
|
||||
|
||||
// Sort by sequence numbers within a connection
|
||||
class PacketSortConnPQ : public PacketSortPQ {
|
||||
public:
|
||||
PacketSortConnPQ()
|
||||
{
|
||||
pq_level = CONN_PQ;
|
||||
delivered_seq[0] = delivered_seq[1] = 0;
|
||||
}
|
||||
~PacketSortConnPQ();
|
||||
|
||||
int Add(PacketSortElement* e);
|
||||
|
||||
int Remove(PacketSortElement* e);
|
||||
|
||||
bool IsContentGapSafe(PacketSortElement* e);
|
||||
|
||||
protected:
|
||||
int Cmp(PacketSortElement* a, PacketSortElement* b);
|
||||
void UpdateDeliveredSeq(int endp, int seq, int len, int ack);
|
||||
|
||||
int delivered_seq[2];
|
||||
};
|
||||
|
||||
declare(PDict, PacketSortConnPQ);
|
||||
|
||||
// Sort by timestamps.
|
||||
class PacketSortGlobalPQ : public PacketSortPQ {
|
||||
public:
|
||||
PacketSortGlobalPQ();
|
||||
~PacketSortGlobalPQ();
|
||||
|
||||
int Add(PacketSortElement* e);
|
||||
|
||||
int Empty() const { return conn_pq_table.Length() == 0; }
|
||||
|
||||
// Returns the next packet to dispatch if it arrives earlier than the
|
||||
// given timestamp, otherwise returns 0.
|
||||
// The packet, if to be returned, is also removed from the
|
||||
// priority queue.
|
||||
PacketSortElement* RemoveMin(double timestamp);
|
||||
|
||||
protected:
|
||||
int Cmp(PacketSortElement* a, PacketSortElement* b)
|
||||
{ return Timestamp_Cmp(a, b); }
|
||||
PacketSortConnPQ* FindConnPQ(PacketSortElement* e);
|
||||
|
||||
PDict(PacketSortConnPQ) conn_pq_table;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -229,12 +229,21 @@ void PktSrc::Process()
|
|||
{
|
||||
// MPLS carried over the ethernet frame.
|
||||
case 0x8847:
|
||||
// Remove the data link layer and denote a
|
||||
// header size of zero before the IP header.
|
||||
have_mpls = true;
|
||||
data += get_link_header_size(datalink);
|
||||
pkt_hdr_size = 0;
|
||||
break;
|
||||
|
||||
// VLAN carried over the ethernet frame.
|
||||
case 0x8100:
|
||||
data += get_link_header_size(datalink);
|
||||
|
||||
// Check for MPLS in VLAN.
|
||||
if ( ((data[2] << 8) + data[3]) == 0x8847 )
|
||||
have_mpls = true;
|
||||
|
||||
data += 4; // Skip the vlan header
|
||||
pkt_hdr_size = 0;
|
||||
|
||||
|
@ -274,8 +283,13 @@ void PktSrc::Process()
|
|||
protocol = (data[2] << 8) + data[3];
|
||||
|
||||
if ( protocol == 0x0281 )
|
||||
// MPLS Unicast
|
||||
{
|
||||
// MPLS Unicast. Remove the data link layer and
|
||||
// denote a header size of zero before the IP header.
|
||||
have_mpls = true;
|
||||
data += get_link_header_size(datalink);
|
||||
pkt_hdr_size = 0;
|
||||
}
|
||||
|
||||
else if ( protocol != 0x0021 && protocol != 0x0057 )
|
||||
{
|
||||
|
@ -290,12 +304,6 @@ void PktSrc::Process()
|
|||
|
||||
if ( have_mpls )
|
||||
{
|
||||
// Remove the data link layer
|
||||
data += get_link_header_size(datalink);
|
||||
|
||||
// Denote a header size of zero before the IP header
|
||||
pkt_hdr_size = 0;
|
||||
|
||||
// Skip the MPLS label stack.
|
||||
bool end_of_stack = false;
|
||||
|
||||
|
@ -309,13 +317,13 @@ void PktSrc::Process()
|
|||
if ( pseudo_realtime )
|
||||
{
|
||||
current_pseudo = CheckPseudoTime();
|
||||
net_packet_arrival(current_pseudo, &hdr, data, pkt_hdr_size, this);
|
||||
net_packet_dispatch(current_pseudo, &hdr, data, pkt_hdr_size, this);
|
||||
if ( ! first_wallclock )
|
||||
first_wallclock = current_time(true);
|
||||
}
|
||||
|
||||
else
|
||||
net_packet_arrival(current_timestamp, &hdr, data, pkt_hdr_size, this);
|
||||
net_packet_dispatch(current_timestamp, &hdr, data, pkt_hdr_size, this);
|
||||
|
||||
data = 0;
|
||||
}
|
||||
|
@ -661,7 +669,7 @@ PktDumper::PktDumper(const char* arg_filename, bool arg_append)
|
|||
if ( linktype < 0 )
|
||||
linktype = DLT_EN10MB;
|
||||
|
||||
pd = pcap_open_dead(linktype, 8192);
|
||||
pd = pcap_open_dead(linktype, snaplen);
|
||||
if ( ! pd )
|
||||
{
|
||||
Error("error for pcap_open_dead");
|
||||
|
|
42
src/RE.cc
42
src/RE.cc
|
@ -3,6 +3,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <utility>
|
||||
|
||||
#include "RE.h"
|
||||
#include "DFA.h"
|
||||
|
@ -266,6 +267,15 @@ void Specific_RE_Matcher::Dump(FILE* f)
|
|||
dfa->Dump(f);
|
||||
}
|
||||
|
||||
inline void RE_Match_State::AddMatches(const AcceptingSet& as,
|
||||
MatchPos position)
|
||||
{
|
||||
typedef std::pair<AcceptIdx, MatchPos> am_idx;
|
||||
|
||||
for ( AcceptingSet::const_iterator it = as.begin(); it != as.end(); ++it )
|
||||
accepted_matches.insert(am_idx(*it, position));
|
||||
}
|
||||
|
||||
bool RE_Match_State::Match(const u_char* bv, int n,
|
||||
bool bol, bool eol, bool clear)
|
||||
{
|
||||
|
@ -283,14 +293,9 @@ bool RE_Match_State::Match(const u_char* bv, int n,
|
|||
current_state = dfa->StartState();
|
||||
|
||||
const AcceptingSet* ac = current_state->Accept();
|
||||
|
||||
if ( ac )
|
||||
{
|
||||
loop_over_list(*ac, i)
|
||||
{
|
||||
accepted.append((*ac)[i]);
|
||||
match_pos.append(0);
|
||||
}
|
||||
}
|
||||
AddMatches(*ac, 0);
|
||||
}
|
||||
|
||||
else if ( clear )
|
||||
|
@ -301,7 +306,7 @@ bool RE_Match_State::Match(const u_char* bv, int n,
|
|||
|
||||
current_pos = 0;
|
||||
|
||||
int old_matches = accepted.length();
|
||||
size_t old_matches = accepted_matches.size();
|
||||
|
||||
int ec;
|
||||
int m = bol ? n + 1 : n;
|
||||
|
@ -324,25 +329,17 @@ bool RE_Match_State::Match(const u_char* bv, int n,
|
|||
break;
|
||||
}
|
||||
|
||||
if ( next_state->Accept() )
|
||||
{
|
||||
const AcceptingSet* ac = next_state->Accept();
|
||||
loop_over_list(*ac, i)
|
||||
{
|
||||
if ( ! accepted.is_member((*ac)[i]) )
|
||||
{
|
||||
accepted.append((*ac)[i]);
|
||||
match_pos.append(current_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
const AcceptingSet* ac = next_state->Accept();
|
||||
|
||||
if ( ac )
|
||||
AddMatches(*ac, current_pos);
|
||||
|
||||
++current_pos;
|
||||
|
||||
current_state = next_state;
|
||||
}
|
||||
|
||||
return accepted.length() != old_matches;
|
||||
return accepted_matches.size() != old_matches;
|
||||
}
|
||||
|
||||
int Specific_RE_Matcher::LongestMatch(const u_char* bv, int n)
|
||||
|
@ -399,7 +396,8 @@ unsigned int Specific_RE_Matcher::MemoryAllocation() const
|
|||
+ equiv_class.Size() - padded_sizeof(EquivClass)
|
||||
+ (dfa ? dfa->MemoryAllocation() : 0) // this is ref counted; consider the bytes here?
|
||||
+ padded_sizeof(*any_ccl)
|
||||
+ accepted->MemoryAllocation();
|
||||
+ padded_sizeof(*accepted)
|
||||
+ accepted->size() * padded_sizeof(AcceptingSet::key_type);
|
||||
}
|
||||
|
||||
RE_Matcher::RE_Matcher()
|
||||
|
|
20
src/RE.h
20
src/RE.h
|
@ -9,6 +9,9 @@
|
|||
#include "CCL.h"
|
||||
#include "EquivClass.h"
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <ctype.h>
|
||||
typedef int (*cce_func)(int);
|
||||
|
||||
|
@ -33,7 +36,10 @@ extern int re_lex(void);
|
|||
extern int clower(int);
|
||||
extern void synerr(const char str[]);
|
||||
|
||||
typedef int_list AcceptingSet;
|
||||
typedef int AcceptIdx;
|
||||
typedef std::set<AcceptIdx> AcceptingSet;
|
||||
typedef uint64 MatchPos;
|
||||
typedef std::map<AcceptIdx, MatchPos> AcceptingMatchSet;
|
||||
typedef name_list string_list;
|
||||
|
||||
typedef enum { MATCH_ANYWHERE, MATCH_EXACTLY, } match_type;
|
||||
|
@ -135,8 +141,8 @@ public:
|
|||
current_state = 0;
|
||||
}
|
||||
|
||||
const AcceptingSet* Accepted() const { return &accepted; }
|
||||
const int_list* MatchPositions() const { return &match_pos; }
|
||||
const AcceptingMatchSet& AcceptedMatches() const
|
||||
{ return accepted_matches; }
|
||||
|
||||
// Returns the number of bytes feeded into the matcher so far
|
||||
int Length() { return current_pos; }
|
||||
|
@ -149,16 +155,16 @@ public:
|
|||
{
|
||||
current_pos = -1;
|
||||
current_state = 0;
|
||||
accepted.clear();
|
||||
match_pos.clear();
|
||||
accepted_matches.clear();
|
||||
}
|
||||
|
||||
void AddMatches(const AcceptingSet& as, MatchPos position);
|
||||
|
||||
protected:
|
||||
DFA_Machine* dfa;
|
||||
int* ecs;
|
||||
|
||||
AcceptingSet accepted;
|
||||
int_list match_pos;
|
||||
AcceptingMatchSet accepted_matches;
|
||||
DFA_State* current_state;
|
||||
int current_pos;
|
||||
};
|
||||
|
|
|
@ -7,14 +7,9 @@
|
|||
#include "Reassem.h"
|
||||
#include "Serializer.h"
|
||||
|
||||
const bool DEBUG_reassem = false;
|
||||
static const bool DEBUG_reassem = false;
|
||||
|
||||
#ifdef DEBUG
|
||||
int reassem_seen_bytes = 0;
|
||||
int reassem_copied_bytes = 0;
|
||||
#endif
|
||||
|
||||
DataBlock::DataBlock(const u_char* data, int size, int arg_seq,
|
||||
DataBlock::DataBlock(const u_char* data, uint64 size, uint64 arg_seq,
|
||||
DataBlock* arg_prev, DataBlock* arg_next)
|
||||
{
|
||||
seq = arg_seq;
|
||||
|
@ -23,10 +18,6 @@ DataBlock::DataBlock(const u_char* data, int size, int arg_seq,
|
|||
|
||||
memcpy((void*) block, (const void*) data, size);
|
||||
|
||||
#ifdef DEBUG
|
||||
reassem_copied_bytes += size;
|
||||
#endif
|
||||
|
||||
prev = arg_prev;
|
||||
next = arg_next;
|
||||
|
||||
|
@ -38,9 +29,9 @@ DataBlock::DataBlock(const u_char* data, int size, int arg_seq,
|
|||
Reassembler::total_size += pad_size(size) + padded_sizeof(DataBlock);
|
||||
}
|
||||
|
||||
unsigned int Reassembler::total_size = 0;
|
||||
uint64 Reassembler::total_size = 0;
|
||||
|
||||
Reassembler::Reassembler(int init_seq, ReassemblerType arg_type)
|
||||
Reassembler::Reassembler(uint64 init_seq, ReassemblerType arg_type)
|
||||
{
|
||||
blocks = last_block = 0;
|
||||
trim_seq = last_reassem_seq = init_seq;
|
||||
|
@ -51,24 +42,20 @@ Reassembler::~Reassembler()
|
|||
ClearBlocks();
|
||||
}
|
||||
|
||||
void Reassembler::NewBlock(double t, int seq, int len, const u_char* data)
|
||||
void Reassembler::NewBlock(double t, uint64 seq, uint64 len, const u_char* data)
|
||||
{
|
||||
if ( len == 0 )
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
reassem_seen_bytes += len;
|
||||
#endif
|
||||
uint64 upper_seq = seq + len;
|
||||
|
||||
int upper_seq = seq + len;
|
||||
|
||||
if ( seq_delta(upper_seq, trim_seq) <= 0 )
|
||||
if ( upper_seq <= trim_seq )
|
||||
// Old data, don't do any work for it.
|
||||
return;
|
||||
|
||||
if ( seq_delta(seq, trim_seq) < 0 )
|
||||
if ( seq < trim_seq )
|
||||
{ // Partially old data, just keep the good stuff.
|
||||
int amount_old = seq_delta(trim_seq, seq);
|
||||
uint64 amount_old = trim_seq - seq;
|
||||
|
||||
data += amount_old;
|
||||
seq += amount_old;
|
||||
|
@ -86,42 +73,42 @@ void Reassembler::NewBlock(double t, int seq, int len, const u_char* data)
|
|||
BlockInserted(start_block);
|
||||
}
|
||||
|
||||
int Reassembler::TrimToSeq(int seq)
|
||||
uint64 Reassembler::TrimToSeq(uint64 seq)
|
||||
{
|
||||
int num_missing = 0;
|
||||
uint64 num_missing = 0;
|
||||
|
||||
// Do this accounting before looking for Undelivered data,
|
||||
// since that will alter last_reassem_seq.
|
||||
|
||||
if ( blocks )
|
||||
{
|
||||
if ( seq_delta(blocks->seq, last_reassem_seq) > 0 )
|
||||
if ( blocks->seq > last_reassem_seq )
|
||||
// An initial hole.
|
||||
num_missing += seq_delta(blocks->seq, last_reassem_seq);
|
||||
num_missing += blocks->seq - last_reassem_seq;
|
||||
}
|
||||
|
||||
else if ( seq_delta(seq, last_reassem_seq) > 0 )
|
||||
else if ( seq > last_reassem_seq )
|
||||
{ // Trimming data we never delivered.
|
||||
if ( ! blocks )
|
||||
// We won't have any accounting based on blocks
|
||||
// for this hole.
|
||||
num_missing += seq_delta(seq, last_reassem_seq);
|
||||
num_missing += seq - last_reassem_seq;
|
||||
}
|
||||
|
||||
if ( seq_delta(seq, last_reassem_seq) > 0 )
|
||||
if ( seq > last_reassem_seq )
|
||||
{
|
||||
// We're trimming data we never delivered.
|
||||
Undelivered(seq);
|
||||
}
|
||||
|
||||
while ( blocks && seq_delta(blocks->upper, seq) <= 0 )
|
||||
while ( blocks && blocks->upper <= seq )
|
||||
{
|
||||
DataBlock* b = blocks->next;
|
||||
|
||||
if ( b && seq_delta(b->seq, seq) <= 0 )
|
||||
if ( b && b->seq <= seq )
|
||||
{
|
||||
if ( blocks->upper != b->seq )
|
||||
num_missing += seq_delta(b->seq, blocks->upper);
|
||||
num_missing += b->seq - blocks->upper;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -129,7 +116,7 @@ int Reassembler::TrimToSeq(int seq)
|
|||
// Second half of test is for acks of FINs, which
|
||||
// don't get entered into the sequence space.
|
||||
if ( blocks->upper != seq && blocks->upper != seq - 1 )
|
||||
num_missing += seq_delta(seq, blocks->upper);
|
||||
num_missing += seq - blocks->upper;
|
||||
}
|
||||
|
||||
delete blocks;
|
||||
|
@ -150,7 +137,7 @@ int Reassembler::TrimToSeq(int seq)
|
|||
else
|
||||
last_block = 0;
|
||||
|
||||
if ( seq_delta(seq, trim_seq) > 0 )
|
||||
if ( seq > trim_seq )
|
||||
// seq is further ahead in the sequence space.
|
||||
trim_seq = seq;
|
||||
|
||||
|
@ -169,9 +156,9 @@ void Reassembler::ClearBlocks()
|
|||
last_block = 0;
|
||||
}
|
||||
|
||||
int Reassembler::TotalSize() const
|
||||
uint64 Reassembler::TotalSize() const
|
||||
{
|
||||
int size = 0;
|
||||
uint64 size = 0;
|
||||
|
||||
for ( DataBlock* b = blocks; b; b = b->next )
|
||||
size += b->Size();
|
||||
|
@ -184,18 +171,18 @@ void Reassembler::Describe(ODesc* d) const
|
|||
d->Add("reassembler");
|
||||
}
|
||||
|
||||
void Reassembler::Undelivered(int up_to_seq)
|
||||
void Reassembler::Undelivered(uint64 up_to_seq)
|
||||
{
|
||||
// TrimToSeq() expects this.
|
||||
last_reassem_seq = up_to_seq;
|
||||
}
|
||||
|
||||
DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper,
|
||||
DataBlock* Reassembler::AddAndCheck(DataBlock* b, uint64 seq, uint64 upper,
|
||||
const u_char* data)
|
||||
{
|
||||
if ( DEBUG_reassem )
|
||||
{
|
||||
DEBUG_MSG("%.6f Reassembler::AddAndCheck seq=%d, upper=%d\n",
|
||||
DEBUG_MSG("%.6f Reassembler::AddAndCheck seq=%"PRIu64", upper=%"PRIu64"\n",
|
||||
network_time, seq, upper);
|
||||
}
|
||||
|
||||
|
@ -209,10 +196,10 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper,
|
|||
|
||||
// Find the first block that doesn't come completely before the
|
||||
// new data.
|
||||
while ( b->next && seq_delta(b->upper, seq) <= 0 )
|
||||
while ( b->next && b->upper <= seq )
|
||||
b = b->next;
|
||||
|
||||
if ( seq_delta(b->upper, seq) <= 0 )
|
||||
if ( b->upper <= seq )
|
||||
{
|
||||
// b is the last block, and it comes completely before
|
||||
// the new block.
|
||||
|
@ -222,21 +209,20 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper,
|
|||
|
||||
DataBlock* new_b = 0;
|
||||
|
||||
if ( seq_delta(upper, b->seq) <= 0 )
|
||||
if ( upper <= b->seq )
|
||||
{
|
||||
// The new block comes completely before b.
|
||||
new_b = new DataBlock(data, seq_delta(upper, seq), seq,
|
||||
b->prev, b);
|
||||
new_b = new DataBlock(data, upper - seq, seq, b->prev, b);
|
||||
if ( b == blocks )
|
||||
blocks = new_b;
|
||||
return new_b;
|
||||
}
|
||||
|
||||
// The blocks overlap, complain.
|
||||
if ( seq_delta(seq, b->seq) < 0 )
|
||||
if ( seq < b->seq )
|
||||
{
|
||||
// The new block has a prefix that comes before b.
|
||||
int prefix_len = seq_delta(b->seq, seq);
|
||||
uint64 prefix_len = b->seq - seq;
|
||||
new_b = new DataBlock(data, prefix_len, seq, b->prev, b);
|
||||
if ( b == blocks )
|
||||
blocks = new_b;
|
||||
|
@ -247,11 +233,11 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper,
|
|||
else
|
||||
new_b = b;
|
||||
|
||||
int overlap_start = seq;
|
||||
int overlap_offset = seq_delta(overlap_start, b->seq);
|
||||
int new_b_len = seq_delta(upper, seq);
|
||||
int b_len = seq_delta(b->upper, overlap_start);
|
||||
int overlap_len = min(new_b_len, b_len);
|
||||
uint64 overlap_start = seq;
|
||||
uint64 overlap_offset = overlap_start - b->seq;
|
||||
uint64 new_b_len = upper - seq;
|
||||
uint64 b_len = b->upper - overlap_start;
|
||||
uint64 overlap_len = min(new_b_len, b_len);
|
||||
|
||||
Overlap(&b->block[overlap_offset], data, overlap_len);
|
||||
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
|
||||
class DataBlock {
|
||||
public:
|
||||
DataBlock(const u_char* data, int size, int seq,
|
||||
DataBlock(const u_char* data, uint64 size, uint64 seq,
|
||||
DataBlock* prev, DataBlock* next);
|
||||
|
||||
~DataBlock();
|
||||
|
||||
int Size() const { return upper - seq; }
|
||||
uint64 Size() const { return upper - seq; }
|
||||
|
||||
DataBlock* next; // next block with higher seq #
|
||||
DataBlock* prev; // previous block with lower seq #
|
||||
int seq, upper;
|
||||
uint64 seq, upper;
|
||||
u_char* block;
|
||||
};
|
||||
|
||||
|
@ -26,22 +26,22 @@ enum ReassemblerType { REASSEM_IP, REASSEM_TCP };
|
|||
|
||||
class Reassembler : public BroObj {
|
||||
public:
|
||||
Reassembler(int init_seq, ReassemblerType arg_type);
|
||||
Reassembler(uint64 init_seq, ReassemblerType arg_type);
|
||||
virtual ~Reassembler();
|
||||
|
||||
void NewBlock(double t, int seq, int len, const u_char* data);
|
||||
void NewBlock(double t, uint64 seq, uint64 len, const u_char* data);
|
||||
|
||||
// Throws away all blocks up to seq. Returns number of bytes
|
||||
// if not all in-sequence, 0 if they were.
|
||||
int TrimToSeq(int seq);
|
||||
uint64 TrimToSeq(uint64 seq);
|
||||
|
||||
// Delete all held blocks.
|
||||
void ClearBlocks();
|
||||
|
||||
int HasBlocks() const { return blocks != 0; }
|
||||
int LastReassemSeq() const { return last_reassem_seq; }
|
||||
uint64 LastReassemSeq() const { return last_reassem_seq; }
|
||||
|
||||
int TotalSize() const; // number of bytes buffered up
|
||||
uint64 TotalSize() const; // number of bytes buffered up
|
||||
|
||||
void Describe(ODesc* d) const;
|
||||
|
||||
|
@ -49,7 +49,7 @@ public:
|
|||
static Reassembler* Unserialize(UnserialInfo* info);
|
||||
|
||||
// Sum over all data buffered in some reassembler.
|
||||
static unsigned int TotalMemoryAllocation() { return total_size; }
|
||||
static uint64 TotalMemoryAllocation() { return total_size; }
|
||||
|
||||
protected:
|
||||
Reassembler() { }
|
||||
|
@ -58,20 +58,20 @@ protected:
|
|||
|
||||
friend class DataBlock;
|
||||
|
||||
virtual void Undelivered(int up_to_seq);
|
||||
virtual void Undelivered(uint64 up_to_seq);
|
||||
|
||||
virtual void BlockInserted(DataBlock* b) = 0;
|
||||
virtual void Overlap(const u_char* b1, const u_char* b2, int n) = 0;
|
||||
virtual void Overlap(const u_char* b1, const u_char* b2, uint64 n) = 0;
|
||||
|
||||
DataBlock* AddAndCheck(DataBlock* b, int seq,
|
||||
int upper, const u_char* data);
|
||||
DataBlock* AddAndCheck(DataBlock* b, uint64 seq,
|
||||
uint64 upper, const u_char* data);
|
||||
|
||||
DataBlock* blocks;
|
||||
DataBlock* last_block;
|
||||
int last_reassem_seq;
|
||||
int trim_seq; // how far we've trimmed
|
||||
uint64 last_reassem_seq;
|
||||
uint64 trim_seq; // how far we've trimmed
|
||||
|
||||
static unsigned int total_size;
|
||||
static uint64 total_size;
|
||||
};
|
||||
|
||||
inline DataBlock::~DataBlock()
|
||||
|
|
|
@ -372,10 +372,7 @@ static bool sendCMsg(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id)
|
|||
CMsg* msg = (CMsg*) new char[sizeof(CMsg)];
|
||||
new (msg) CMsg(msg_type, id);
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk;
|
||||
c->len = sizeof(CMsg);
|
||||
c->data = (char*) msg;
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk((char*)msg, sizeof(CMsg));
|
||||
return io->Write(c);
|
||||
}
|
||||
|
||||
|
@ -386,10 +383,7 @@ static ChunkedIO::Chunk* makeSerialMsg(RemoteSerializer::PeerID id)
|
|||
CMsg* msg = (CMsg*) new char[sizeof(CMsg)];
|
||||
new (msg) CMsg(MSG_SERIAL, id);
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk;
|
||||
c->len = sizeof(CMsg);
|
||||
c->data = (char*) msg;
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk((char*)msg, sizeof(CMsg));
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -424,7 +418,7 @@ static bool sendToIO(ChunkedIO* io, ChunkedIO::Chunk* c)
|
|||
}
|
||||
|
||||
static bool sendToIO(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id,
|
||||
const char* str, int len = -1)
|
||||
const char* str, int len = -1, bool delete_with_free = false)
|
||||
{
|
||||
if ( ! sendCMsg(io, msg_type, id) )
|
||||
{
|
||||
|
@ -432,9 +426,14 @@ static bool sendToIO(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id,
|
|||
return false;
|
||||
}
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk;
|
||||
c->len = len >= 0 ? len : strlen(str) + 1;
|
||||
c->data = const_cast<char*>(str);
|
||||
uint32 sz = len >= 0 ? len : strlen(str) + 1;
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk(const_cast<char*>(str), sz);
|
||||
|
||||
if ( delete_with_free )
|
||||
c->free_func = ChunkedIO::Chunk::free_func_free;
|
||||
else
|
||||
c->free_func = ChunkedIO::Chunk::free_func_delete;
|
||||
|
||||
return sendToIO(io, c);
|
||||
}
|
||||
|
||||
|
@ -455,10 +454,8 @@ static bool sendToIO(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id,
|
|||
for ( int i = 0; i < nargs; i++ )
|
||||
args[i] = htonl(va_arg(ap, uint32));
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk;
|
||||
c->len = sizeof(uint32) * nargs;
|
||||
c->data = (char*) args;
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk((char*)args,
|
||||
sizeof(uint32) * nargs);
|
||||
return sendToIO(io, c);
|
||||
}
|
||||
|
||||
|
@ -1466,7 +1463,7 @@ void RemoteSerializer::Process()
|
|||
current_pkt = p->pkt;
|
||||
current_pktsrc = 0;
|
||||
current_iosrc = this;
|
||||
sessions->NextPacket(p->time, p->hdr, p->pkt, p->hdr_size, 0);
|
||||
sessions->NextPacket(p->time, p->hdr, p->pkt, p->hdr_size);
|
||||
mgr.Drain();
|
||||
|
||||
current_hdr = 0; // done with these
|
||||
|
@ -1529,7 +1526,6 @@ bool RemoteSerializer::Poll(bool may_block)
|
|||
current_msgtype = msg->Type();
|
||||
current_args = 0;
|
||||
|
||||
delete [] c->data;
|
||||
delete c;
|
||||
|
||||
switch ( current_msgtype ) {
|
||||
|
@ -1592,7 +1588,6 @@ bool RemoteSerializer::Poll(bool may_block)
|
|||
msgstate = TYPE;
|
||||
bool result = DoMessage();
|
||||
|
||||
delete [] current_args->data;
|
||||
delete current_args;
|
||||
current_args = 0;
|
||||
|
||||
|
@ -1787,9 +1782,7 @@ void RemoteSerializer::PeerConnected(Peer* peer)
|
|||
*args++ = htonl(peer->our_runtime);
|
||||
strcpy((char*) args, peer->our_class.c_str());
|
||||
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk;
|
||||
c->len = len;
|
||||
c->data = data;
|
||||
ChunkedIO::Chunk* c = new ChunkedIO::Chunk(data, len);
|
||||
|
||||
if ( peer->our_class.size() )
|
||||
Log(LogInfo, fmt("sending class \"%s\"", peer->our_class.c_str()), peer);
|
||||
|
@ -2568,8 +2561,8 @@ bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal*
|
|||
goto error;
|
||||
|
||||
c = new ChunkedIO::Chunk;
|
||||
c->data = 0;
|
||||
c->len = fmt.EndWrite(&c->data);
|
||||
c->free_func = ChunkedIO::Chunk::free_func_free;
|
||||
|
||||
if ( ! SendToChild(c) )
|
||||
goto error;
|
||||
|
@ -2577,11 +2570,7 @@ bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal*
|
|||
return true;
|
||||
|
||||
error:
|
||||
if ( c )
|
||||
{
|
||||
delete [] c->data;
|
||||
delete c;
|
||||
}
|
||||
delete c;
|
||||
|
||||
FatalError(io->Error());
|
||||
return false;
|
||||
|
@ -2643,21 +2632,21 @@ bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, st
|
|||
{
|
||||
if ( ! FlushLogBuffer(peer) )
|
||||
{
|
||||
delete [] data;
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If the data is actually larger than our complete buffer, just send it out.
|
||||
if ( len > LOG_BUFFER_SIZE )
|
||||
return SendToChild(MSG_LOG_WRITE, peer, data, len);
|
||||
return SendToChild(MSG_LOG_WRITE, peer, data, len, true);
|
||||
|
||||
// Now we have space in the buffer, copy it into there.
|
||||
memcpy(peer->log_buffer + peer->log_buffer_used, data, len);
|
||||
peer->log_buffer_used += len;
|
||||
assert(peer->log_buffer_used <= LOG_BUFFER_SIZE);
|
||||
|
||||
delete [] data;
|
||||
free(data);
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -3112,14 +3101,19 @@ bool RemoteSerializer::SendCMsgToChild(char msg_type, Peer* peer)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RemoteSerializer::SendToChild(char type, Peer* peer, char* str, int len)
|
||||
bool RemoteSerializer::SendToChild(char type, Peer* peer, char* str, int len,
|
||||
bool delete_with_free)
|
||||
{
|
||||
DEBUG_COMM(fmt("parent: (->child) %s (#%" PRI_SOURCE_ID ", %s)", msgToStr(type), peer ? peer->id : PEER_NONE, str));
|
||||
|
||||
if ( child_pid && sendToIO(io, type, peer ? peer->id : PEER_NONE, str, len) )
|
||||
if ( child_pid && sendToIO(io, type, peer ? peer->id : PEER_NONE, str, len,
|
||||
delete_with_free) )
|
||||
return true;
|
||||
|
||||
delete [] str;
|
||||
if ( delete_with_free )
|
||||
free(str);
|
||||
else
|
||||
delete [] str;
|
||||
|
||||
if ( ! child_pid )
|
||||
return false;
|
||||
|
@ -3169,7 +3163,7 @@ bool RemoteSerializer::SendToChild(ChunkedIO::Chunk* c)
|
|||
if ( child_pid && sendToIO(io, c) )
|
||||
return true;
|
||||
|
||||
delete [] c->data;
|
||||
c->free_func(c->data);
|
||||
c->data = 0;
|
||||
|
||||
if ( ! child_pid )
|
||||
|
@ -3545,7 +3539,6 @@ bool SocketComm::ProcessParentMessage()
|
|||
parent_msgtype = msg->Type();
|
||||
parent_args = 0;
|
||||
|
||||
delete [] c->data;
|
||||
delete c;
|
||||
|
||||
switch ( parent_msgtype ) {
|
||||
|
@ -3600,7 +3593,6 @@ bool SocketComm::ProcessParentMessage()
|
|||
|
||||
if ( parent_args )
|
||||
{
|
||||
delete [] parent_args->data;
|
||||
delete parent_args;
|
||||
parent_args = 0;
|
||||
}
|
||||
|
@ -3900,7 +3892,6 @@ bool SocketComm::ProcessRemoteMessage(SocketComm::Peer* peer)
|
|||
peer->state = msg->Type();
|
||||
}
|
||||
|
||||
delete [] c->data;
|
||||
delete c;
|
||||
|
||||
break;
|
||||
|
|
|
@ -317,7 +317,8 @@ protected:
|
|||
|
||||
// Communication helpers
|
||||
bool SendCMsgToChild(char msg_type, Peer* peer);
|
||||
bool SendToChild(char type, Peer* peer, char* str, int len = -1);
|
||||
bool SendToChild(char type, Peer* peer, char* str, int len = -1,
|
||||
bool delete_with_free = false);
|
||||
bool SendToChild(char type, Peer* peer, int nargs, ...); // can send uints32 only
|
||||
bool SendToChild(ChunkedIO::Chunk* c);
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ Rule::~Rule()
|
|||
const char* Rule::TypeToString(Rule::PatternType type)
|
||||
{
|
||||
static const char* labels[] = {
|
||||
"Payload", "HTTP-REQUEST", "HTTP-REQUEST-BODY",
|
||||
"File Magic", "Payload", "HTTP-REQUEST", "HTTP-REQUEST-BODY",
|
||||
"HTTP-REQUEST-HEADER", "HTTP-REPLY-BODY",
|
||||
"HTTP-REPLY-HEADER", "FTP", "Finger",
|
||||
};
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
unsigned int Index() const { return idx; }
|
||||
|
||||
enum PatternType {
|
||||
PAYLOAD, HTTP_REQUEST, HTTP_REQUEST_BODY, HTTP_REQUEST_HEADER,
|
||||
FILE_MAGIC, PAYLOAD, HTTP_REQUEST, HTTP_REQUEST_BODY, HTTP_REQUEST_HEADER,
|
||||
HTTP_REPLY_BODY, HTTP_REPLY_HEADER, FTP, FINGER, TYPES,
|
||||
};
|
||||
|
||||
|
|
|
@ -35,6 +35,11 @@ void RuleActionEvent::PrintDebug()
|
|||
fprintf(stderr, " RuleActionEvent: |%s|\n", msg);
|
||||
}
|
||||
|
||||
void RuleActionMIME::PrintDebug()
|
||||
{
|
||||
fprintf(stderr, " RuleActionMIME: |%s|\n", mime);
|
||||
}
|
||||
|
||||
RuleActionAnalyzer::RuleActionAnalyzer(const char* arg_analyzer)
|
||||
{
|
||||
string str(arg_analyzer);
|
||||
|
|
|
@ -36,6 +36,31 @@ private:
|
|||
const char* msg;
|
||||
};
|
||||
|
||||
class RuleActionMIME : public RuleAction {
|
||||
public:
|
||||
RuleActionMIME(const char* arg_mime, int arg_strength = 0)
|
||||
{ mime = copy_string(arg_mime); strength = arg_strength; }
|
||||
|
||||
virtual ~RuleActionMIME()
|
||||
{ delete [] mime; }
|
||||
|
||||
virtual void DoAction(const Rule* parent, RuleEndpointState* state,
|
||||
const u_char* data, int len)
|
||||
{ }
|
||||
|
||||
virtual void PrintDebug();
|
||||
|
||||
string GetMIME() const
|
||||
{ return mime; }
|
||||
|
||||
int GetStrength() const
|
||||
{ return strength; }
|
||||
|
||||
private:
|
||||
const char* mime;
|
||||
int strength;
|
||||
};
|
||||
|
||||
// Base class for enable/disable actions.
|
||||
class RuleActionAnalyzer : public RuleAction {
|
||||
public:
|
||||
|
|
|
@ -186,6 +186,15 @@ RuleEndpointState::~RuleEndpointState()
|
|||
delete matched_text[j];
|
||||
}
|
||||
|
||||
RuleFileMagicState::~RuleFileMagicState()
|
||||
{
|
||||
loop_over_list(matchers, i)
|
||||
{
|
||||
delete matchers[i]->state;
|
||||
delete matchers[i];
|
||||
}
|
||||
}
|
||||
|
||||
RuleMatcher::RuleMatcher(int arg_RE_level)
|
||||
{
|
||||
root = new RuleHdrTest(RuleHdrTest::NOPROT, 0, 0, RuleHdrTest::EQ,
|
||||
|
@ -564,6 +573,137 @@ static inline bool compare(const vector<IPPrefix>& prefixes, const IPAddr& a,
|
|||
return false;
|
||||
}
|
||||
|
||||
RuleFileMagicState* RuleMatcher::InitFileMagic() const
|
||||
{
|
||||
RuleFileMagicState* state = new RuleFileMagicState();
|
||||
|
||||
if ( rule_bench == 3 )
|
||||
return state;
|
||||
|
||||
loop_over_list(root->psets[Rule::FILE_MAGIC], i)
|
||||
{
|
||||
RuleHdrTest::PatternSet* set = root->psets[Rule::FILE_MAGIC][i];
|
||||
assert(set->re);
|
||||
RuleFileMagicState::Matcher* m = new RuleFileMagicState::Matcher;
|
||||
m->state = new RE_Match_State(set->re);
|
||||
state->matchers.append(m);
|
||||
}
|
||||
|
||||
// Save some memory.
|
||||
state->matchers.resize(0);
|
||||
return state;
|
||||
}
|
||||
|
||||
bool RuleMatcher::AllRulePatternsMatched(const Rule* r, MatchPos matchpos,
|
||||
const AcceptingMatchSet& ams)
|
||||
{
|
||||
DBG_LOG(DBG_RULES, "Checking rule: %s", r->id);
|
||||
|
||||
// Check whether all patterns of the rule have matched.
|
||||
loop_over_list(r->patterns, j)
|
||||
{
|
||||
if ( ams.find(r->patterns[j]->id) == ams.end() )
|
||||
return false;
|
||||
|
||||
// See if depth is satisfied.
|
||||
if ( matchpos > r->patterns[j]->offset + r->patterns[j]->depth )
|
||||
return false;
|
||||
|
||||
// FIXME: How to check for offset ??? ###
|
||||
}
|
||||
|
||||
DBG_LOG(DBG_RULES, "All patterns of rule satisfied");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RuleMatcher::MIME_Matches* RuleMatcher::Match(RuleFileMagicState* state,
|
||||
const u_char* data, uint64 len,
|
||||
MIME_Matches* rval) const
|
||||
{
|
||||
if ( ! rval )
|
||||
rval = new MIME_Matches();
|
||||
|
||||
if ( ! state )
|
||||
{
|
||||
reporter->Warning("RuleFileMagicState not initialized yet.");
|
||||
return rval;
|
||||
}
|
||||
|
||||
if ( rule_bench >= 2 )
|
||||
return rval;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( debug_logger.IsEnabled(DBG_RULES) )
|
||||
{
|
||||
const char* s = fmt_bytes(reinterpret_cast<const char*>(data),
|
||||
min(40, static_cast<int>(len)));
|
||||
DBG_LOG(DBG_RULES, "Matching %s rules on |%s%s|",
|
||||
Rule::TypeToString(Rule::FILE_MAGIC), s,
|
||||
len > 40 ? "..." : "");
|
||||
}
|
||||
#endif
|
||||
|
||||
bool newmatch = false;
|
||||
|
||||
loop_over_list(state->matchers, x)
|
||||
{
|
||||
RuleFileMagicState::Matcher* m = state->matchers[x];
|
||||
|
||||
if ( m->state->Match(data, len, true, false, true) )
|
||||
newmatch = true;
|
||||
}
|
||||
|
||||
if ( ! newmatch )
|
||||
return rval;
|
||||
|
||||
DBG_LOG(DBG_RULES, "New pattern match found");
|
||||
|
||||
AcceptingMatchSet accepted_matches;
|
||||
|
||||
loop_over_list(state->matchers, y)
|
||||
{
|
||||
RuleFileMagicState::Matcher* m = state->matchers[y];
|
||||
const AcceptingMatchSet& ams = m->state->AcceptedMatches();
|
||||
accepted_matches.insert(ams.begin(), ams.end());
|
||||
}
|
||||
|
||||
// Find rules for which patterns have matched.
|
||||
set<Rule*> rule_matches;
|
||||
|
||||
for ( AcceptingMatchSet::const_iterator it = accepted_matches.begin();
|
||||
it != accepted_matches.end(); ++it )
|
||||
{
|
||||
AcceptIdx aidx = it->first;
|
||||
MatchPos mpos = it->second;
|
||||
|
||||
Rule* r = Rule::rule_table[aidx - 1];
|
||||
|
||||
if ( AllRulePatternsMatched(r, mpos, accepted_matches) )
|
||||
rule_matches.insert(r);
|
||||
}
|
||||
|
||||
for ( set<Rule*>::const_iterator it = rule_matches.begin();
|
||||
it != rule_matches.end(); ++it )
|
||||
{
|
||||
Rule* r = *it;
|
||||
|
||||
loop_over_list(r->actions, rai)
|
||||
{
|
||||
const RuleActionMIME* ram =
|
||||
dynamic_cast<const RuleActionMIME*>(r->actions[rai]);
|
||||
|
||||
if ( ! ram )
|
||||
continue;
|
||||
|
||||
set<string>& ss = (*rval)[ram->GetStrength()];
|
||||
ss.insert(ram->GetMIME());
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
RuleEndpointState* RuleMatcher::InitEndpoint(analyzer::Analyzer* analyzer,
|
||||
const IP_Hdr* ip, int caplen,
|
||||
RuleEndpointState* opposite,
|
||||
|
@ -742,66 +882,40 @@ void RuleMatcher::Match(RuleEndpointState* state, Rule::PatternType type,
|
|||
|
||||
DBG_LOG(DBG_RULES, "New pattern match found");
|
||||
|
||||
// Build a joined AcceptingSet.
|
||||
AcceptingSet accepted;
|
||||
int_list matchpos;
|
||||
AcceptingMatchSet accepted_matches;
|
||||
|
||||
loop_over_list(state->matchers, y)
|
||||
loop_over_list(state->matchers, y )
|
||||
{
|
||||
RuleEndpointState::Matcher* m = state->matchers[y];
|
||||
const AcceptingSet* ac = m->state->Accepted();
|
||||
|
||||
loop_over_list(*ac, k)
|
||||
{
|
||||
if ( ! accepted.is_member((*ac)[k]) )
|
||||
{
|
||||
accepted.append((*ac)[k]);
|
||||
matchpos.append((*m->state->MatchPositions())[k]);
|
||||
}
|
||||
}
|
||||
const AcceptingMatchSet& ams = m->state->AcceptedMatches();
|
||||
accepted_matches.insert(ams.begin(), ams.end());
|
||||
}
|
||||
|
||||
// Determine the rules for which all patterns have matched.
|
||||
// This code should be fast enough as long as there are only very few
|
||||
// matched patterns per connection (which is a plausible assumption).
|
||||
|
||||
rule_list matched;
|
||||
// Find rules for which patterns have matched.
|
||||
set<Rule*> rule_matches;
|
||||
|
||||
loop_over_list(accepted, i)
|
||||
for ( AcceptingMatchSet::const_iterator it = accepted_matches.begin();
|
||||
it != accepted_matches.end(); ++it )
|
||||
{
|
||||
Rule* r = Rule::rule_table[accepted[i] - 1];
|
||||
AcceptIdx aidx = it->first;
|
||||
MatchPos mpos = it->second;
|
||||
|
||||
DBG_LOG(DBG_RULES, "Checking rule: %s", r->id);
|
||||
Rule* r = Rule::rule_table[aidx - 1];
|
||||
|
||||
// Check whether all patterns of the rule have matched.
|
||||
loop_over_list(r->patterns, j)
|
||||
{
|
||||
if ( ! accepted.is_member(r->patterns[j]->id) )
|
||||
goto next_pattern;
|
||||
|
||||
// See if depth is satisfied.
|
||||
if ( (unsigned int) matchpos[i] >
|
||||
r->patterns[j]->offset + r->patterns[j]->depth )
|
||||
goto next_pattern;
|
||||
|
||||
DBG_LOG(DBG_RULES, "All patterns of rule satisfied");
|
||||
|
||||
// FIXME: How to check for offset ??? ###
|
||||
}
|
||||
|
||||
// If not already in the list of matching rules, add it.
|
||||
if ( ! matched.is_member(r) )
|
||||
matched.append(r);
|
||||
|
||||
next_pattern:
|
||||
continue;
|
||||
if ( AllRulePatternsMatched(r, mpos, accepted_matches) )
|
||||
rule_matches.insert(r);
|
||||
}
|
||||
|
||||
// Check which of the matching rules really belong to any of our nodes.
|
||||
|
||||
loop_over_list(matched, j)
|
||||
for ( set<Rule*>::const_iterator it = rule_matches.begin();
|
||||
it != rule_matches.end(); ++it )
|
||||
{
|
||||
Rule* r = matched[j];
|
||||
Rule* r = *it;
|
||||
|
||||
DBG_LOG(DBG_RULES, "Accepted rule: %s", r->id);
|
||||
|
||||
|
@ -1010,6 +1124,15 @@ void RuleMatcher::ClearEndpointState(RuleEndpointState* state)
|
|||
state->matchers[j]->state->Clear();
|
||||
}
|
||||
|
||||
void RuleMatcher::ClearFileMagicState(RuleFileMagicState* state) const
|
||||
{
|
||||
if ( rule_bench == 3 )
|
||||
return;
|
||||
|
||||
loop_over_list(state->matchers, j)
|
||||
state->matchers[j]->state->Clear();
|
||||
}
|
||||
|
||||
void RuleMatcher::PrintDebug()
|
||||
{
|
||||
loop_over_list(rules, i)
|
||||
|
@ -1163,7 +1286,10 @@ static Val* get_bro_val(const char* label)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return id->ID_Val();
|
||||
Val* rval = id->ID_Val();
|
||||
Unref(id);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include <limits.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "IPAddr.h"
|
||||
#include "BroString.h"
|
||||
|
@ -191,6 +195,30 @@ private:
|
|||
int_list matched_rules; // Rules for which all conditions have matched
|
||||
};
|
||||
|
||||
/**
|
||||
* A state object used for matching file magic signatures.
|
||||
*/
|
||||
class RuleFileMagicState {
|
||||
friend class RuleMatcher;
|
||||
public:
|
||||
~RuleFileMagicState();
|
||||
|
||||
private:
|
||||
// Ctor is private; use RuleMatcher::InitFileMagic() for
|
||||
// instantiation.
|
||||
RuleFileMagicState()
|
||||
{ }
|
||||
|
||||
struct Matcher {
|
||||
RE_Match_State* state;
|
||||
};
|
||||
|
||||
declare(PList, Matcher);
|
||||
typedef PList(Matcher) matcher_list;
|
||||
|
||||
matcher_list matchers;
|
||||
};
|
||||
|
||||
|
||||
// RuleMatcher is the main class which builds up the data structures
|
||||
// and performs the actual matching.
|
||||
|
@ -205,6 +233,42 @@ public:
|
|||
// Parse the given files and built up data structures.
|
||||
bool ReadFiles(const name_list& files);
|
||||
|
||||
/**
|
||||
* Inititialize a state object for matching file magic signatures.
|
||||
* @return A state object that can be used for file magic mime type
|
||||
* identification.
|
||||
*/
|
||||
RuleFileMagicState* InitFileMagic() const;
|
||||
|
||||
/**
|
||||
* Data structure containing a set of matching file magic signatures.
|
||||
* Ordered from greatest to least strength. Matches of the same strength
|
||||
* will be in the set in lexicographic order of the MIME type string.
|
||||
*/
|
||||
typedef map<int, set<string>, std::greater<int> > MIME_Matches;
|
||||
|
||||
/**
|
||||
* Matches a chunk of data against file magic signatures.
|
||||
* @param state A state object previously returned from
|
||||
* RuleMatcher::InitFileMagic()
|
||||
* @param data Chunk of data to match signatures against.
|
||||
* @param len Length of \a data in bytes.
|
||||
* @param matches An optional pre-existing match result object to
|
||||
* modify with additional matches. If it's a null
|
||||
* pointer, one will be instantiated and returned from
|
||||
* this method.
|
||||
* @return The results of the signature matching.
|
||||
*/
|
||||
MIME_Matches* Match(RuleFileMagicState* state, const u_char* data,
|
||||
uint64 len, MIME_Matches* matches = 0) const;
|
||||
|
||||
|
||||
/**
|
||||
* Resets a state object used with matching file magic signatures.
|
||||
* @param state The state object to reset to an initial condition.
|
||||
*/
|
||||
void ClearFileMagicState(RuleFileMagicState* state) const;
|
||||
|
||||
// Initialize the matching state for a endpoind of a connection based on
|
||||
// the given packet (which should be the first packet encountered for
|
||||
// this endpoint). If the matching is triggered by an PIA, a pointer to
|
||||
|
@ -297,6 +361,9 @@ private:
|
|||
|
||||
void DumpStateStats(BroFile* f, RuleHdrTest* hdr_test);
|
||||
|
||||
static bool AllRulePatternsMatched(const Rule* r, MatchPos matchpos,
|
||||
const AcceptingMatchSet& ams);
|
||||
|
||||
int RE_level;
|
||||
bool parse_error;
|
||||
RuleHdrTest* root;
|
||||
|
|
|
@ -62,6 +62,7 @@ protected:
|
|||
extern bool in_debug;
|
||||
|
||||
// If no_global is true, don't search in the default "global" namespace.
|
||||
// This passed ownership of a ref'ed ID to the caller.
|
||||
extern ID* lookup_ID(const char* name, const char* module,
|
||||
bool no_global = false, bool same_module_only=false);
|
||||
extern ID* install_ID(const char* name, const char* module_name,
|
||||
|
|
|
@ -111,6 +111,7 @@ SERIAL_VAL(ENTROPY_VAL, 19)
|
|||
SERIAL_VAL(TOPK_VAL, 20)
|
||||
SERIAL_VAL(BLOOMFILTER_VAL, 21)
|
||||
SERIAL_VAL(CARDINALITY_VAL, 22)
|
||||
SERIAL_VAL(X509_VAL, 23)
|
||||
|
||||
#define SERIAL_EXPR(name, val) SERIAL_CONST(name, val, EXPR)
|
||||
SERIAL_EXPR(EXPR, 1)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "Serializer.h"
|
||||
#include "Reporter.h"
|
||||
|
||||
const float SerializationFormat::GROWTH_FACTOR = 2.5;
|
||||
|
||||
SerializationFormat::SerializationFormat()
|
||||
: output(), output_size(), output_pos(), input(), input_len(), input_pos(),
|
||||
bytes_written(), bytes_read()
|
||||
|
@ -13,7 +15,7 @@ SerializationFormat::SerializationFormat()
|
|||
|
||||
SerializationFormat::~SerializationFormat()
|
||||
{
|
||||
delete [] output;
|
||||
free(output);
|
||||
}
|
||||
|
||||
void SerializationFormat::StartRead(char* data, uint32 arg_len)
|
||||
|
@ -33,13 +35,13 @@ void SerializationFormat::StartWrite()
|
|||
{
|
||||
if ( output && output_size > INITIAL_SIZE )
|
||||
{
|
||||
delete [] output;
|
||||
free(output);
|
||||
output = 0;
|
||||
}
|
||||
|
||||
if ( ! output )
|
||||
{
|
||||
output = new char[INITIAL_SIZE];
|
||||
output = (char*)safe_malloc(INITIAL_SIZE);
|
||||
output_size = INITIAL_SIZE;
|
||||
}
|
||||
|
||||
|
@ -49,9 +51,12 @@ void SerializationFormat::StartWrite()
|
|||
|
||||
uint32 SerializationFormat::EndWrite(char** data)
|
||||
{
|
||||
*data = new char[output_pos];
|
||||
memcpy(*data, output, output_pos);
|
||||
return output_pos;
|
||||
uint32 rval = output_pos;
|
||||
*data = output;
|
||||
output = 0;
|
||||
output_size = 0;
|
||||
output_pos = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool SerializationFormat::ReadData(void* b, size_t count)
|
||||
|
@ -75,11 +80,8 @@ bool SerializationFormat::WriteData(const void* b, size_t count)
|
|||
// Increase buffer if necessary.
|
||||
while ( output_pos + count > output_size )
|
||||
{
|
||||
output_size = output_pos + count + INITIAL_SIZE;
|
||||
char* tmp = new char[output_size];
|
||||
memcpy(tmp, output, output_pos);
|
||||
delete [] output;
|
||||
output = tmp;
|
||||
output_size *= GROWTH_FACTOR;
|
||||
output = (char*)safe_realloc(output, output_size);
|
||||
}
|
||||
|
||||
memcpy(output + output_pos, b, count);
|
||||
|
|
|
@ -44,7 +44,15 @@ public:
|
|||
|
||||
// Serialization.
|
||||
virtual void StartWrite();
|
||||
virtual uint32 EndWrite(char** data); // passes ownership
|
||||
|
||||
/**
|
||||
* Retrieves serialized data.
|
||||
* @param data A pointer that will be assigned to point at the internal
|
||||
* buffer containing serialized data. The memory should
|
||||
* be reclaimed using "free()".
|
||||
* @return The number of bytes in the buffer object assigned to \a data.
|
||||
*/
|
||||
virtual uint32 EndWrite(char** data);
|
||||
|
||||
virtual bool Write(int v, const char* tag) = 0;
|
||||
virtual bool Write(uint16 v, const char* tag) = 0;
|
||||
|
@ -74,6 +82,7 @@ protected:
|
|||
bool WriteData(const void* buf, size_t count);
|
||||
|
||||
static const uint32 INITIAL_SIZE = 65536;
|
||||
static const float GROWTH_FACTOR;
|
||||
char* output;
|
||||
uint32 output_size;
|
||||
uint32 output_pos;
|
||||
|
|
|
@ -81,6 +81,7 @@ bool Serializer::EndSerialization(SerialInfo* info)
|
|||
|
||||
ChunkedIO::Chunk* chunk = new ChunkedIO::Chunk;
|
||||
chunk->len = format->EndWrite(&chunk->data);
|
||||
chunk->free_func = ChunkedIO::Chunk::free_func_free;
|
||||
|
||||
if ( ! io->Write(chunk) )
|
||||
{
|
||||
|
@ -282,7 +283,6 @@ int Serializer::Unserialize(UnserialInfo* info, bool block)
|
|||
|
||||
if ( ! info->chunk )
|
||||
{ // only delete if we allocated it ourselves
|
||||
delete [] chunk->data;
|
||||
delete chunk;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ protected:
|
|||
|
||||
// This will be increased whenever there is an incompatible change
|
||||
// in the data format.
|
||||
static const uint32 DATA_FORMAT_VERSION = 24;
|
||||
static const uint32 DATA_FORMAT_VERSION = 25;
|
||||
|
||||
ChunkedIO* io;
|
||||
|
||||
|
|
245
src/Sessions.cc
245
src/Sessions.cc
|
@ -30,7 +30,6 @@
|
|||
#include "Discard.h"
|
||||
#include "RuleMatcher.h"
|
||||
|
||||
#include "PacketSort.h"
|
||||
#include "TunnelEncapsulation.h"
|
||||
|
||||
#include "analyzer/Manager.h"
|
||||
|
@ -168,7 +167,7 @@ void NetSessions::Done()
|
|||
|
||||
void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* pkt, int hdr_size,
|
||||
PktSrc* src_ps, PacketSortElement* pkt_elem)
|
||||
PktSrc* src_ps)
|
||||
{
|
||||
const struct ip* ip_hdr = 0;
|
||||
const u_char* ip_data = 0;
|
||||
|
@ -186,14 +185,13 @@ void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
hdr_size += encap_hdr_size;
|
||||
|
||||
if ( src_ps->FilterType() == TYPE_FILTER_NORMAL )
|
||||
NextPacket(t, hdr, pkt, hdr_size, pkt_elem);
|
||||
NextPacket(t, hdr, pkt, hdr_size);
|
||||
else
|
||||
NextPacketSecondary(t, hdr, pkt, hdr_size, src_ps);
|
||||
}
|
||||
|
||||
void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* const pkt, int hdr_size,
|
||||
PacketSortElement* pkt_elem)
|
||||
const u_char* const pkt, int hdr_size)
|
||||
{
|
||||
SegmentProfiler(segment_logger, "processing-packet");
|
||||
if ( pkt_profiler )
|
||||
|
@ -206,70 +204,58 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
if ( record_all_packets )
|
||||
DumpPacket(hdr, pkt);
|
||||
|
||||
if ( pkt_elem && pkt_elem->IPHdr() )
|
||||
// Fast path for "normal" IP packets if an IP_Hdr is
|
||||
// already extracted when doing PacketSort. Otherwise
|
||||
// the code below tries to extract the IP header, the
|
||||
// difference here is that header extraction in
|
||||
// PacketSort does not generate Weird events.
|
||||
// ### The following isn't really correct. What we *should*
|
||||
// do is understanding the different link layers in order to
|
||||
// find the network-layer protocol ID. That's a big
|
||||
// portability pain, though, unless we just assume everything's
|
||||
// Ethernet .... not great, given the potential need to deal
|
||||
// with PPP or FDDI (for some older traces). So instead
|
||||
// we look to see if what we have is consistent with an
|
||||
// IPv4 packet. If not, it's either ARP or IPv6 or weird.
|
||||
|
||||
DoNextPacket(t, hdr, pkt_elem->IPHdr(), pkt, hdr_size, 0);
|
||||
|
||||
else
|
||||
if ( hdr_size > static_cast<int>(hdr->caplen) )
|
||||
{
|
||||
// ### The following isn't really correct. What we *should*
|
||||
// do is understanding the different link layers in order to
|
||||
// find the network-layer protocol ID. That's a big
|
||||
// portability pain, though, unless we just assume everything's
|
||||
// Ethernet .... not great, given the potential need to deal
|
||||
// with PPP or FDDI (for some older traces). So instead
|
||||
// we look to see if what we have is consistent with an
|
||||
// IPv4 packet. If not, it's either ARP or IPv6 or weird.
|
||||
Weird("truncated_link_frame", hdr, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( hdr_size > static_cast<int>(hdr->caplen) )
|
||||
{
|
||||
Weird("truncated_link_frame", hdr, pkt);
|
||||
return;
|
||||
}
|
||||
uint32 caplen = hdr->caplen - hdr_size;
|
||||
if ( caplen < sizeof(struct ip) )
|
||||
{
|
||||
Weird("truncated_IP", hdr, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 caplen = hdr->caplen - hdr_size;
|
||||
if ( caplen < sizeof(struct ip) )
|
||||
const struct ip* ip = (const struct ip*) (pkt + hdr_size);
|
||||
|
||||
if ( ip->ip_v == 4 )
|
||||
{
|
||||
IP_Hdr ip_hdr(ip, false);
|
||||
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size, 0);
|
||||
}
|
||||
|
||||
else if ( ip->ip_v == 6 )
|
||||
{
|
||||
if ( caplen < sizeof(struct ip6_hdr) )
|
||||
{
|
||||
Weird("truncated_IP", hdr, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
const struct ip* ip = (const struct ip*) (pkt + hdr_size);
|
||||
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false, caplen);
|
||||
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size, 0);
|
||||
}
|
||||
|
||||
if ( ip->ip_v == 4 )
|
||||
{
|
||||
IP_Hdr ip_hdr(ip, false);
|
||||
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size, 0);
|
||||
}
|
||||
else if ( analyzer::arp::ARP_Analyzer::IsARP(pkt, hdr_size) )
|
||||
{
|
||||
if ( arp_analyzer )
|
||||
arp_analyzer->NextPacket(t, hdr, pkt, hdr_size);
|
||||
}
|
||||
|
||||
else if ( ip->ip_v == 6 )
|
||||
{
|
||||
if ( caplen < sizeof(struct ip6_hdr) )
|
||||
{
|
||||
Weird("truncated_IP", hdr, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false, caplen);
|
||||
DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size, 0);
|
||||
}
|
||||
|
||||
else if ( analyzer::arp::ARP_Analyzer::IsARP(pkt, hdr_size) )
|
||||
{
|
||||
if ( arp_analyzer )
|
||||
arp_analyzer->NextPacket(t, hdr, pkt, hdr_size);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Weird("unknown_packet_type", hdr, pkt);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Weird("unknown_packet_type", hdr, pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( dump_this_packet && ! record_all_packets )
|
||||
|
@ -376,6 +362,31 @@ int NetSessions::CheckConnectionTag(Connection* conn)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int gre_header_len(uint16 flags)
|
||||
{
|
||||
unsigned int len = 4; // Always has 2 byte flags and 2 byte protocol type.
|
||||
|
||||
if ( flags & 0x8000 )
|
||||
// Checksum/Reserved1 present.
|
||||
len += 4;
|
||||
|
||||
// Not considering routing presence bit since it's deprecated ...
|
||||
|
||||
if ( flags & 0x2000 )
|
||||
// Key present.
|
||||
len += 4;
|
||||
|
||||
if ( flags & 0x1000 )
|
||||
// Sequence present.
|
||||
len += 4;
|
||||
|
||||
if ( flags & 0x0080 )
|
||||
// Acknowledgement present.
|
||||
len += 4;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||
const IP_Hdr* ip_hdr, const u_char* const pkt,
|
||||
int hdr_size, const EncapsulationStack* encapsulation)
|
||||
|
@ -384,6 +395,15 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
const struct ip* ip4 = ip_hdr->IP4_Hdr();
|
||||
|
||||
uint32 len = ip_hdr->TotalLen();
|
||||
if ( len == 0 )
|
||||
{
|
||||
// TCP segmentation offloading can zero out the ip_len field.
|
||||
Weird("ip_hdr_len_zero", hdr, pkt, encapsulation);
|
||||
|
||||
// Cope with the zero'd out ip_len field by using the caplen.
|
||||
len = hdr->caplen - hdr_size;
|
||||
}
|
||||
|
||||
if ( hdr->len < len + hdr_size )
|
||||
{
|
||||
Weird("truncated_IP", hdr, pkt, encapsulation);
|
||||
|
@ -437,6 +457,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
}
|
||||
}
|
||||
|
||||
FragReassemblerTracker frt(this, f);
|
||||
|
||||
len -= ip_hdr_len; // remove IP header
|
||||
caplen -= ip_hdr_len;
|
||||
|
||||
|
@ -451,7 +473,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
vl->append(ip_hdr->BuildPktHdrVal());
|
||||
mgr.QueueEvent(esp_packet, vl);
|
||||
}
|
||||
Remove(f);
|
||||
|
||||
// Can't do more since upper-layer payloads are going to be encrypted.
|
||||
return;
|
||||
}
|
||||
|
@ -466,7 +488,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff )
|
||||
{
|
||||
Weird("bad_MH_checksum", hdr, pkt, encapsulation);
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -480,7 +501,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
if ( ip_hdr->NextProto() != IPPROTO_NONE )
|
||||
Weird("mobility_piggyback", hdr, pkt, encapsulation);
|
||||
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -488,10 +508,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
int proto = ip_hdr->NextProto();
|
||||
|
||||
if ( CheckHeaderTrunc(proto, len, caplen, hdr, pkt, encapsulation) )
|
||||
{
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
const u_char* data = ip_hdr->Payload();
|
||||
|
||||
|
@ -553,13 +570,100 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_GRE:
|
||||
{
|
||||
if ( ! BifConst::Tunnel::enable_gre )
|
||||
{
|
||||
Weird("GRE_tunnel", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 flags_ver = ntohs(*((uint16*)(data + 0)));
|
||||
uint16 proto_typ = ntohs(*((uint16*)(data + 2)));
|
||||
int gre_version = flags_ver & 0x0007;
|
||||
|
||||
if ( gre_version != 0 && gre_version != 1 )
|
||||
{
|
||||
Weird(fmt("unknown_gre_version_%d", gre_version), ip_hdr,
|
||||
encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gre_version == 0 )
|
||||
{
|
||||
if ( proto_typ != 0x0800 && proto_typ != 0x86dd )
|
||||
{
|
||||
// Not IPv4/IPv6 payload.
|
||||
Weird(fmt("unknown_gre_protocol_%"PRIu16, proto_typ), ip_hdr,
|
||||
encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
proto = (proto_typ == 0x0800) ? IPPROTO_IPV4 : IPPROTO_IPV6;
|
||||
}
|
||||
|
||||
else // gre_version == 1
|
||||
{
|
||||
if ( proto_typ != 0x880b )
|
||||
{
|
||||
// Enhanced GRE payload must be PPP.
|
||||
Weird("egre_protocol_type", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( flags_ver & 0x4000 )
|
||||
{
|
||||
// RFC 2784 deprecates the variable length routing field
|
||||
// specified by RFC 1701. It could be parsed here, but easiest
|
||||
// to just skip for now.
|
||||
Weird("gre_routing", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( flags_ver & 0x0078 )
|
||||
{
|
||||
// Expect last 4 bits of flags are reserved, undefined.
|
||||
Weird("unknown_gre_flags", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int gre_len = gre_header_len(flags_ver);
|
||||
unsigned int ppp_len = gre_version == 1 ? 1 : 0;
|
||||
|
||||
if ( len < gre_len + ppp_len || caplen < gre_len + ppp_len )
|
||||
{
|
||||
Weird("truncated_GRE", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gre_version == 1 )
|
||||
{
|
||||
int ppp_proto = *((uint8*)(data + gre_len));
|
||||
|
||||
if ( ppp_proto != 0x0021 && ppp_proto != 0x0057 )
|
||||
{
|
||||
Weird("non_ip_packet_in_egre", ip_hdr, encapsulation);
|
||||
return;
|
||||
}
|
||||
|
||||
proto = (ppp_proto == 0x0021) ? IPPROTO_IPV4 : IPPROTO_IPV6;
|
||||
}
|
||||
|
||||
data += gre_len + ppp_len;
|
||||
len -= gre_len + ppp_len;
|
||||
caplen -= gre_len + ppp_len;
|
||||
|
||||
// Treat GRE tunnel like IP tunnels, fallthrough to logic below now
|
||||
// that GRE header is stripped and only payload packet remains.
|
||||
}
|
||||
|
||||
case IPPROTO_IPV4:
|
||||
case IPPROTO_IPV6:
|
||||
{
|
||||
if ( ! BifConst::Tunnel::enable_ip )
|
||||
{
|
||||
Weird("IP_tunnel", ip_hdr, encapsulation);
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -567,7 +671,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
encapsulation->Depth() >= BifConst::Tunnel::max_depth )
|
||||
{
|
||||
Weird("exceeded_tunnel_max_depth", ip_hdr, encapsulation);
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -584,7 +687,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
if ( result != 0 )
|
||||
{
|
||||
delete inner;
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -611,7 +713,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
DoNextInnerPacket(t, hdr, inner, encapsulation,
|
||||
ip_tunnels[tunnel_idx].first);
|
||||
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -624,13 +725,11 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
encapsulation->LastType() == BifEnum::Tunnel::TEREDO ) )
|
||||
Weird("ipv6_no_next", hdr, pkt);
|
||||
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
Weird(fmt("unknown_protocol_%d", proto), hdr, pkt, encapsulation);
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -656,7 +755,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
if ( consistent < 0 )
|
||||
{
|
||||
delete h;
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -680,7 +778,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
if ( ! conn )
|
||||
{
|
||||
delete h;
|
||||
Remove(f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -712,7 +809,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
|
|||
{
|
||||
// Above we already recorded the fragment in its entirety.
|
||||
f->DeleteTimer();
|
||||
Remove(f);
|
||||
}
|
||||
|
||||
else if ( record_packet )
|
||||
|
@ -813,6 +909,9 @@ bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen,
|
|||
case IPPROTO_NONE:
|
||||
min_hdr_len = 0;
|
||||
break;
|
||||
case IPPROTO_GRE:
|
||||
min_hdr_len = 4;
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
case IPPROTO_ICMPV6:
|
||||
default:
|
||||
|
|
|
@ -28,7 +28,6 @@ declare(PDict,FragReassembler);
|
|||
|
||||
class Discarder;
|
||||
class PacketFilter;
|
||||
class PacketSortElement;
|
||||
|
||||
namespace analyzer { namespace stepping_stone { class SteppingStoneManager; } }
|
||||
namespace analyzer { namespace arp { class ARP_Analyzer; } }
|
||||
|
@ -74,7 +73,7 @@ public:
|
|||
// employing the packet sorter first.
|
||||
void DispatchPacket(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* const pkt, int hdr_size,
|
||||
PktSrc* src_ps, PacketSortElement* pkt_elem);
|
||||
PktSrc* src_ps);
|
||||
|
||||
void Done(); // call to drain events before destructing
|
||||
|
||||
|
@ -220,8 +219,7 @@ protected:
|
|||
uint8 tcp_flags, bool& flip_roles);
|
||||
|
||||
void NextPacket(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* const pkt, int hdr_size,
|
||||
PacketSortElement* pkt_elem);
|
||||
const u_char* const pkt, int hdr_size);
|
||||
|
||||
void NextPacketSecondary(double t, const struct pcap_pkthdr* hdr,
|
||||
const u_char* const pkt, int hdr_size,
|
||||
|
@ -286,6 +284,21 @@ protected:
|
|||
NetSessions::IPPair tunnel_idx;
|
||||
};
|
||||
|
||||
|
||||
class FragReassemblerTracker {
|
||||
public:
|
||||
FragReassemblerTracker(NetSessions* s, FragReassembler* f)
|
||||
: net_sessions(s), frag_reassembler(f)
|
||||
{ }
|
||||
|
||||
~FragReassemblerTracker()
|
||||
{ net_sessions->Remove(frag_reassembler); }
|
||||
|
||||
private:
|
||||
NetSessions* net_sessions;
|
||||
FragReassembler* frag_reassembler;
|
||||
};
|
||||
|
||||
// Manager for the currently active sessions.
|
||||
extern NetSessions* sessions;
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void ProfileLogger::Log()
|
|||
file->Write(fmt("%.06f Connections expired due to inactivity: %d\n",
|
||||
network_time, killed_by_inactivity));
|
||||
|
||||
file->Write(fmt("%.06f Total reassembler data: %dK\n", network_time,
|
||||
file->Write(fmt("%.06f Total reassembler data: %"PRIu64"K\n", network_time,
|
||||
Reassembler::TotalMemoryAllocation() / 1024));
|
||||
|
||||
// Signature engine.
|
||||
|
|
24
src/Type.cc
24
src/Type.cc
|
@ -131,7 +131,7 @@ BroType* BroType::Clone() const
|
|||
sinfo.cache = false;
|
||||
|
||||
this->Serialize(&sinfo);
|
||||
char* data = 0;
|
||||
char* data;
|
||||
uint32 len = form->EndWrite(&data);
|
||||
form->StartRead(data, len);
|
||||
|
||||
|
@ -141,7 +141,7 @@ BroType* BroType::Clone() const
|
|||
BroType* rval = this->Unserialize(&uinfo, false);
|
||||
assert(rval != this);
|
||||
|
||||
delete [] data;
|
||||
free(data);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -1449,6 +1449,7 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name,
|
|||
}
|
||||
else
|
||||
{
|
||||
Unref(id);
|
||||
reporter->Error("identifier or enumerator value in enumerated type definition already exists");
|
||||
SetError();
|
||||
return;
|
||||
|
@ -1626,6 +1627,23 @@ VectorType::~VectorType()
|
|||
Unref(yield_type);
|
||||
}
|
||||
|
||||
BroType* VectorType::YieldType()
|
||||
{
|
||||
// Work around the fact that we use void internally to mark a vector
|
||||
// as being unspecified. When looking at its yield type, we need to
|
||||
// return any as that's what other code historically expects for type
|
||||
// comparisions.
|
||||
if ( IsUnspecifiedVector() )
|
||||
{
|
||||
BroType* ret = ::base_type(TYPE_ANY);
|
||||
Unref(ret); // unref, because this won't be held by anyone.
|
||||
assert(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return yield_type;
|
||||
}
|
||||
|
||||
int VectorType::MatchesIndex(ListExpr*& index) const
|
||||
{
|
||||
expr_list& el = index->Exprs();
|
||||
|
@ -1645,7 +1663,7 @@ int VectorType::MatchesIndex(ListExpr*& index) const
|
|||
|
||||
bool VectorType::IsUnspecifiedVector() const
|
||||
{
|
||||
return yield_type->Tag() == TYPE_ANY;
|
||||
return yield_type->Tag() == TYPE_VOID;
|
||||
}
|
||||
|
||||
IMPLEMENT_SERIAL(VectorType, SER_VECTOR_TYPE);
|
||||
|
|
16
src/Type.h
16
src/Type.h
|
@ -73,6 +73,7 @@ class EnumType;
|
|||
class Serializer;
|
||||
class VectorType;
|
||||
class TypeType;
|
||||
class OpaqueType;
|
||||
|
||||
const int DOES_NOT_MATCH_INDEX = 0;
|
||||
const int MATCHES_INDEX_SCALAR = 1;
|
||||
|
@ -204,6 +205,18 @@ public:
|
|||
return (VectorType*) this;
|
||||
}
|
||||
|
||||
OpaqueType* AsOpaqueType()
|
||||
{
|
||||
CHECK_TYPE_TAG(TYPE_OPAQUE, "BroType::AsOpaqueType");
|
||||
return (OpaqueType*) this;
|
||||
}
|
||||
|
||||
const OpaqueType* AsOpaqueType() const
|
||||
{
|
||||
CHECK_TYPE_TAG(TYPE_OPAQUE, "BroType::AsOpaqueType");
|
||||
return (OpaqueType*) this;
|
||||
}
|
||||
|
||||
VectorType* AsVectorType()
|
||||
{
|
||||
CHECK_TYPE_TAG(TYPE_VECTOR, "BroType::AsVectorType");
|
||||
|
@ -572,7 +585,7 @@ class VectorType : public BroType {
|
|||
public:
|
||||
VectorType(BroType* t);
|
||||
virtual ~VectorType();
|
||||
BroType* YieldType() { return yield_type; }
|
||||
BroType* YieldType();
|
||||
|
||||
int MatchesIndex(ListExpr*& index) const;
|
||||
|
||||
|
@ -597,6 +610,7 @@ extern OpaqueType* entropy_type;
|
|||
extern OpaqueType* cardinality_type;
|
||||
extern OpaqueType* topk_type;
|
||||
extern OpaqueType* bloomfilter_type;
|
||||
extern OpaqueType* x509_opaque_type;
|
||||
|
||||
// Returns the BRO basic (non-parameterized) type with the given type.
|
||||
extern BroType* base_type(TypeTag tag);
|
||||
|
|
30
src/Val.cc
30
src/Val.cc
|
@ -32,7 +32,6 @@ Val::Val(Func* f)
|
|||
val.func_val = f;
|
||||
::Ref(val.func_val);
|
||||
type = f->FType()->Ref();
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -49,7 +48,6 @@ Val::Val(BroFile* f)
|
|||
assert(f->FType()->Tag() == TYPE_STRING);
|
||||
type = string_file_type->Ref();
|
||||
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -80,6 +78,7 @@ Val* Val::Clone() const
|
|||
CloneSerializer ss(form);
|
||||
SerialInfo sinfo(&ss);
|
||||
sinfo.cache = false;
|
||||
sinfo.include_locations = false;
|
||||
|
||||
if ( ! this->Serialize(&sinfo) )
|
||||
return 0;
|
||||
|
@ -92,8 +91,7 @@ Val* Val::Clone() const
|
|||
uinfo.cache = false;
|
||||
Val* clone = Unserialize(&uinfo, type);
|
||||
|
||||
delete [] data;
|
||||
|
||||
free(data);
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
@ -190,8 +188,6 @@ bool Val::DoSerialize(SerialInfo* info) const
|
|||
if ( ! type->Serialize(info) )
|
||||
return false;
|
||||
|
||||
SERIALIZE_OPTIONAL(attribs);
|
||||
|
||||
switch ( type->InternalType() ) {
|
||||
case TYPE_INTERNAL_VOID:
|
||||
info->s->Error("type is void");
|
||||
|
@ -251,9 +247,6 @@ bool Val::DoUnserialize(UnserialInfo* info)
|
|||
if ( ! (type = BroType::Unserialize(info)) )
|
||||
return false;
|
||||
|
||||
UNSERIALIZE_OPTIONAL(attribs,
|
||||
(RecordVal*) Val::Unserialize(info, TYPE_RECORD));
|
||||
|
||||
switch ( type->InternalType() ) {
|
||||
case TYPE_INTERNAL_VOID:
|
||||
info->s->Error("type is void");
|
||||
|
@ -1171,23 +1164,6 @@ ListVal::~ListVal()
|
|||
Unref(type);
|
||||
}
|
||||
|
||||
const char* ListVal::IncludedInString(const char* str) const
|
||||
{
|
||||
if ( tag != TYPE_STRING )
|
||||
Internal("non-string list in ListVal::IncludedInString");
|
||||
|
||||
loop_over_list(vals, i)
|
||||
{
|
||||
const char* vs = (const char*) (vals[i]->AsString()->Bytes());
|
||||
|
||||
const char* embedded = strstr(str, vs);
|
||||
if ( embedded )
|
||||
return embedded;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RE_Matcher* ListVal::BuildRE() const
|
||||
{
|
||||
if ( tag != TYPE_STRING )
|
||||
|
@ -3139,7 +3115,7 @@ bool VectorVal::DoUnserialize(UnserialInfo* info)
|
|||
for ( int i = 0; i < len; ++i )
|
||||
{
|
||||
Val* v;
|
||||
UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info, TYPE_ANY));
|
||||
UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info, TYPE_ANY)); // accept any type
|
||||
Assign(i, v);
|
||||
}
|
||||
|
||||
|
|
22
src/Val.h
22
src/Val.h
|
@ -80,7 +80,6 @@ public:
|
|||
{
|
||||
val.int_val = b;
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -90,7 +89,6 @@ public:
|
|||
{
|
||||
val.int_val = bro_int_t(i);
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -100,7 +98,6 @@ public:
|
|||
{
|
||||
val.uint_val = bro_uint_t(u);
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -110,7 +107,6 @@ public:
|
|||
{
|
||||
val.int_val = i;
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -120,7 +116,6 @@ public:
|
|||
{
|
||||
val.uint_val = u;
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -130,7 +125,6 @@ public:
|
|||
{
|
||||
val.double_val = d;
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -145,7 +139,6 @@ public:
|
|||
Val(BroType* t, bool type_type) // Extra arg to differentiate from protected version.
|
||||
{
|
||||
type = new TypeType(t->Ref());
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -155,7 +148,6 @@ public:
|
|||
{
|
||||
val.int_val = 0;
|
||||
type = base_type(TYPE_ERROR);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -364,7 +356,6 @@ protected:
|
|||
{
|
||||
val.string_val = s;
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -376,7 +367,6 @@ protected:
|
|||
Val(TypeTag t)
|
||||
{
|
||||
type = base_type(t);
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -385,7 +375,6 @@ protected:
|
|||
Val(BroType* t)
|
||||
{
|
||||
type = t->Ref();
|
||||
attribs = 0;
|
||||
#ifdef DEBUG
|
||||
bound_id = 0;
|
||||
#endif
|
||||
|
@ -400,7 +389,6 @@ protected:
|
|||
|
||||
BroValUnion val;
|
||||
BroType* type;
|
||||
RecordVal* attribs;
|
||||
|
||||
#ifdef DEBUG
|
||||
// For debugging, we keep the name of the ID to which a Val is bound.
|
||||
|
@ -656,6 +644,8 @@ protected:
|
|||
DECLARE_SERIAL(PatternVal);
|
||||
};
|
||||
|
||||
// ListVals are mainly used to index tables that have more than one
|
||||
// element in their index.
|
||||
class ListVal : public Val {
|
||||
public:
|
||||
ListVal(TypeTag t);
|
||||
|
@ -669,13 +659,6 @@ public:
|
|||
Val* Index(const int n) { return vals[n]; }
|
||||
const Val* Index(const int n) const { return vals[n]; }
|
||||
|
||||
// Returns offset of where str includes one of the strings in this
|
||||
// ListVal (which had better be a list of strings), nil if none.
|
||||
//
|
||||
// Assumes that all of the strings in the list are NUL-terminated
|
||||
// and do not have any embedded NULs.
|
||||
const char* IncludedInString(const char* str) const;
|
||||
|
||||
// Returns an RE_Matcher() that will match any string that
|
||||
// includes embedded within it one of the patterns listed
|
||||
// (as a string, e.g., "foo|bar") in this ListVal.
|
||||
|
@ -949,7 +932,6 @@ public:
|
|||
{
|
||||
val.int_val = i;
|
||||
type = t;
|
||||
attribs = 0;
|
||||
}
|
||||
|
||||
Val* SizeVal() const { return new Val(val.int_val, TYPE_INT); }
|
||||
|
|
27
src/Var.cc
27
src/Var.cc
|
@ -169,8 +169,14 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
|
|||
{
|
||||
Val* aggr;
|
||||
if ( t->Tag() == TYPE_RECORD )
|
||||
{
|
||||
aggr = new RecordVal(t->AsRecordType());
|
||||
|
||||
if ( init && t )
|
||||
// Have an initialization and type is not deduced.
|
||||
init = new RecordCoerceExpr(init, t->AsRecordType());
|
||||
}
|
||||
|
||||
else if ( t->Tag() == TYPE_TABLE )
|
||||
aggr = new TableVal(t->AsTableType(), id->Attrs());
|
||||
|
||||
|
@ -379,6 +385,8 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor,
|
|||
if ( arg_id && ! arg_id->IsGlobal() )
|
||||
arg_id->Error("argument name used twice");
|
||||
|
||||
Unref(arg_id);
|
||||
|
||||
arg_id = install_ID(arg_i->id, module_name, false, false);
|
||||
arg_id->SetType(arg_i->type->Ref());
|
||||
}
|
||||
|
@ -436,10 +444,13 @@ void end_func(Stmt* body, attr_list* attrs)
|
|||
Val* internal_val(const char* name)
|
||||
{
|
||||
ID* id = lookup_ID(name, GLOBAL_MODULE_NAME);
|
||||
|
||||
if ( ! id )
|
||||
reporter->InternalError("internal variable %s missing", name);
|
||||
|
||||
return id->ID_Val();
|
||||
Val* rval = id->ID_Val();
|
||||
Unref(id);
|
||||
return rval;
|
||||
}
|
||||
|
||||
Val* internal_const_val(const char* name)
|
||||
|
@ -451,13 +462,17 @@ Val* internal_const_val(const char* name)
|
|||
if ( ! id->IsConst() )
|
||||
reporter->InternalError("internal variable %s is not constant", name);
|
||||
|
||||
return id->ID_Val();
|
||||
Val* rval = id->ID_Val();
|
||||
Unref(id);
|
||||
return rval;
|
||||
}
|
||||
|
||||
Val* opt_internal_val(const char* name)
|
||||
{
|
||||
ID* id = lookup_ID(name, GLOBAL_MODULE_NAME);
|
||||
return id ? id->ID_Val() : 0;
|
||||
Val* rval = id ? id->ID_Val() : 0;
|
||||
Unref(id);
|
||||
return rval;
|
||||
}
|
||||
|
||||
double opt_internal_double(const char* name)
|
||||
|
@ -497,6 +512,8 @@ ListVal* internal_list_val(const char* name)
|
|||
return 0;
|
||||
|
||||
Val* v = id->ID_Val();
|
||||
Unref(id);
|
||||
|
||||
if ( v )
|
||||
{
|
||||
if ( v->Type()->Tag() == TYPE_LIST )
|
||||
|
@ -522,7 +539,9 @@ BroType* internal_type(const char* name)
|
|||
if ( ! id )
|
||||
reporter->InternalError("internal type %s missing", name);
|
||||
|
||||
return id->Type();
|
||||
BroType* rval = id->Type();
|
||||
Unref(id);
|
||||
return rval;
|
||||
}
|
||||
|
||||
Func* internal_func(const char* name)
|
||||
|
|
|
@ -203,17 +203,17 @@ void Analyzer::Done()
|
|||
finished = true;
|
||||
}
|
||||
|
||||
void Analyzer::NextPacket(int len, const u_char* data, bool is_orig, int seq,
|
||||
void Analyzer::NextPacket(int len, const u_char* data, bool is_orig, uint64 seq,
|
||||
const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
if ( skip )
|
||||
return;
|
||||
|
||||
// If we have support analyzers, we pass it to them.
|
||||
if ( is_orig && orig_supporters )
|
||||
orig_supporters->NextPacket(len, data, is_orig, seq, ip, caplen);
|
||||
else if ( ! is_orig && resp_supporters )
|
||||
resp_supporters->NextPacket(len, data, is_orig, seq, ip, caplen);
|
||||
SupportAnalyzer* next_sibling = FirstSupportAnalyzer(is_orig);
|
||||
|
||||
if ( next_sibling )
|
||||
next_sibling->NextPacket(len, data, is_orig, seq, ip, caplen);
|
||||
|
||||
else
|
||||
{
|
||||
try
|
||||
|
@ -232,11 +232,11 @@ void Analyzer::NextStream(int len, const u_char* data, bool is_orig)
|
|||
if ( skip )
|
||||
return;
|
||||
|
||||
// If we have support analyzers, we pass it to them.
|
||||
if ( is_orig && orig_supporters )
|
||||
orig_supporters->NextStream(len, data, is_orig);
|
||||
else if ( ! is_orig && resp_supporters )
|
||||
resp_supporters->NextStream(len, data, is_orig);
|
||||
SupportAnalyzer* next_sibling = FirstSupportAnalyzer(is_orig);
|
||||
|
||||
if ( next_sibling )
|
||||
next_sibling->NextStream(len, data, is_orig);
|
||||
|
||||
else
|
||||
{
|
||||
try
|
||||
|
@ -250,16 +250,16 @@ void Analyzer::NextStream(int len, const u_char* data, bool is_orig)
|
|||
}
|
||||
}
|
||||
|
||||
void Analyzer::NextUndelivered(int seq, int len, bool is_orig)
|
||||
void Analyzer::NextUndelivered(uint64 seq, int len, bool is_orig)
|
||||
{
|
||||
if ( skip )
|
||||
return;
|
||||
|
||||
// If we have support analyzers, we pass it to them.
|
||||
if ( is_orig && orig_supporters )
|
||||
orig_supporters->NextUndelivered(seq, len, is_orig);
|
||||
else if ( ! is_orig && resp_supporters )
|
||||
resp_supporters->NextUndelivered(seq, len, is_orig);
|
||||
SupportAnalyzer* next_sibling = FirstSupportAnalyzer(is_orig);
|
||||
|
||||
if ( next_sibling )
|
||||
next_sibling->NextUndelivered(seq, len, is_orig);
|
||||
|
||||
else
|
||||
{
|
||||
try
|
||||
|
@ -278,17 +278,16 @@ void Analyzer::NextEndOfData(bool is_orig)
|
|||
if ( skip )
|
||||
return;
|
||||
|
||||
// If we have support analyzers, we pass it to them.
|
||||
if ( is_orig && orig_supporters )
|
||||
orig_supporters->NextEndOfData(is_orig);
|
||||
else if ( ! is_orig && resp_supporters )
|
||||
resp_supporters->NextEndOfData(is_orig);
|
||||
SupportAnalyzer* next_sibling = FirstSupportAnalyzer(is_orig);
|
||||
|
||||
if ( next_sibling )
|
||||
next_sibling->NextEndOfData(is_orig);
|
||||
else
|
||||
EndOfData(is_orig);
|
||||
}
|
||||
|
||||
void Analyzer::ForwardPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq, const IP_Hdr* ip, int caplen)
|
||||
uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
if ( output_handler )
|
||||
output_handler->DeliverPacket(len, data, is_orig, seq,
|
||||
|
@ -336,7 +335,7 @@ void Analyzer::ForwardStream(int len, const u_char* data, bool is_orig)
|
|||
AppendNewChildren();
|
||||
}
|
||||
|
||||
void Analyzer::ForwardUndelivered(int seq, int len, bool is_orig)
|
||||
void Analyzer::ForwardUndelivered(uint64 seq, int len, bool is_orig)
|
||||
{
|
||||
if ( output_handler )
|
||||
output_handler->Undelivered(seq, len, is_orig);
|
||||
|
@ -558,31 +557,17 @@ void Analyzer::AddSupportAnalyzer(SupportAnalyzer* analyzer)
|
|||
|
||||
void Analyzer::RemoveSupportAnalyzer(SupportAnalyzer* analyzer)
|
||||
{
|
||||
SupportAnalyzer** head =
|
||||
analyzer->IsOrig() ? &orig_supporters : &resp_supporters;
|
||||
|
||||
SupportAnalyzer* prev = 0;
|
||||
SupportAnalyzer* s;
|
||||
for ( s = *head; s && s != analyzer; prev = s, s = s->sibling )
|
||||
;
|
||||
|
||||
if ( ! s )
|
||||
return;
|
||||
|
||||
if ( prev )
|
||||
prev->sibling = s->sibling;
|
||||
else
|
||||
*head = s->sibling;
|
||||
|
||||
DBG_LOG(DBG_ANALYZER, "%s removed support %s",
|
||||
DBG_LOG(DBG_ANALYZER, "%s disabled %s support analyzer %s",
|
||||
fmt_analyzer(this).c_str(),
|
||||
analyzer->IsOrig() ? "originator" : "responder",
|
||||
fmt_analyzer(analyzer).c_str());
|
||||
|
||||
if ( ! analyzer->finished )
|
||||
analyzer->Done();
|
||||
|
||||
delete analyzer;
|
||||
// We mark the analyzer as being removed here, which will prevent it
|
||||
// from being used further. However, we don't actually delete it
|
||||
// before the parent gets destroyed. While we woulc do that, it's a
|
||||
// bit tricky to do at the right time and it doesn't seem worth the
|
||||
// trouble.
|
||||
analyzer->removing = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -596,10 +581,23 @@ bool Analyzer::HasSupportAnalyzer(Tag tag, bool orig)
|
|||
return false;
|
||||
}
|
||||
|
||||
void Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq, const IP_Hdr* ip, int caplen)
|
||||
SupportAnalyzer* Analyzer::FirstSupportAnalyzer(bool orig)
|
||||
{
|
||||
DBG_LOG(DBG_ANALYZER, "%s DeliverPacket(%d, %s, %d, %p, %d) [%s%s]",
|
||||
SupportAnalyzer* sa = orig ? orig_supporters : resp_supporters;
|
||||
|
||||
if ( ! sa )
|
||||
return 0;
|
||||
|
||||
if ( ! sa->Removing() )
|
||||
return sa;
|
||||
|
||||
return sa->Sibling(true);
|
||||
}
|
||||
|
||||
void Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
|
||||
uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
DBG_LOG(DBG_ANALYZER, "%s DeliverPacket(%d, %s, %"PRIu64", %p, %d) [%s%s]",
|
||||
fmt_analyzer(this).c_str(), len, is_orig ? "T" : "F", seq, ip, caplen,
|
||||
fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : "");
|
||||
}
|
||||
|
@ -611,9 +609,9 @@ void Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
|
|||
fmt_bytes((const char*) data, min(40, len)), len > 40 ? "..." : "");
|
||||
}
|
||||
|
||||
void Analyzer::Undelivered(int seq, int len, bool is_orig)
|
||||
void Analyzer::Undelivered(uint64 seq, int len, bool is_orig)
|
||||
{
|
||||
DBG_LOG(DBG_ANALYZER, "%s Undelivered(%d, %d, %s)",
|
||||
DBG_LOG(DBG_ANALYZER, "%s Undelivered(%"PRIu64", %d, %s)",
|
||||
fmt_analyzer(this).c_str(), seq, len, is_orig ? "T" : "F");
|
||||
}
|
||||
|
||||
|
@ -782,16 +780,35 @@ void Analyzer::Weird(const char* name, const char* addl)
|
|||
conn->Weird(name, addl);
|
||||
}
|
||||
|
||||
SupportAnalyzer* SupportAnalyzer::Sibling(bool only_active) const
|
||||
{
|
||||
if ( ! only_active )
|
||||
return sibling;
|
||||
|
||||
SupportAnalyzer* next = sibling;
|
||||
while ( next && next->Removing() )
|
||||
next = next->sibling;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
void SupportAnalyzer::ForwardPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq, const IP_Hdr* ip, int caplen)
|
||||
uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
// We do not call parent's method, as we're replacing the functionality.
|
||||
|
||||
if ( GetOutputHandler() )
|
||||
{
|
||||
GetOutputHandler()->DeliverPacket(len, data, is_orig, seq,
|
||||
ip, caplen);
|
||||
else if ( sibling )
|
||||
return;
|
||||
}
|
||||
|
||||
SupportAnalyzer* next_sibling = Sibling(true);
|
||||
|
||||
if ( next_sibling )
|
||||
// Pass to next in chain.
|
||||
sibling->NextPacket(len, data, is_orig, seq, ip, caplen);
|
||||
next_sibling->NextPacket(len, data, is_orig, seq, ip, caplen);
|
||||
else
|
||||
// Finished with preprocessing - now it's the parent's turn.
|
||||
Parent()->DeliverPacket(len, data, is_orig, seq, ip, caplen);
|
||||
|
@ -800,26 +817,38 @@ void SupportAnalyzer::ForwardPacket(int len, const u_char* data, bool is_orig,
|
|||
void SupportAnalyzer::ForwardStream(int len, const u_char* data, bool is_orig)
|
||||
{
|
||||
// We do not call parent's method, as we're replacing the functionality.
|
||||
if ( GetOutputHandler() )
|
||||
GetOutputHandler()->DeliverStream(len, data, is_orig);
|
||||
|
||||
else if ( sibling )
|
||||
if ( GetOutputHandler() )
|
||||
{
|
||||
GetOutputHandler()->DeliverStream(len, data, is_orig);
|
||||
return;
|
||||
}
|
||||
|
||||
SupportAnalyzer* next_sibling = Sibling(true);
|
||||
|
||||
if ( next_sibling )
|
||||
// Pass to next in chain.
|
||||
sibling->NextStream(len, data, is_orig);
|
||||
next_sibling->NextStream(len, data, is_orig);
|
||||
else
|
||||
// Finished with preprocessing - now it's the parent's turn.
|
||||
Parent()->DeliverStream(len, data, is_orig);
|
||||
}
|
||||
|
||||
void SupportAnalyzer::ForwardUndelivered(int seq, int len, bool is_orig)
|
||||
void SupportAnalyzer::ForwardUndelivered(uint64 seq, int len, bool is_orig)
|
||||
{
|
||||
// We do not call parent's method, as we're replacing the functionality.
|
||||
if ( GetOutputHandler() )
|
||||
GetOutputHandler()->Undelivered(seq, len, is_orig);
|
||||
|
||||
else if ( sibling )
|
||||
if ( GetOutputHandler() )
|
||||
{
|
||||
GetOutputHandler()->Undelivered(seq, len, is_orig);
|
||||
return;
|
||||
}
|
||||
|
||||
SupportAnalyzer* next_sibling = Sibling(true);
|
||||
|
||||
if ( next_sibling )
|
||||
// Pass to next in chain.
|
||||
sibling->NextUndelivered(seq, len, is_orig);
|
||||
next_sibling->NextUndelivered(seq, len, is_orig);
|
||||
else
|
||||
// Finished with preprocessing - now it's the parent's turn.
|
||||
Parent()->Undelivered(seq, len, is_orig);
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
* Analyzer::DeliverPacket().
|
||||
*/
|
||||
virtual void DeliverPacket(int len, const u_char* data,
|
||||
bool orig, int seq,
|
||||
bool orig, uint64 seq,
|
||||
const IP_Hdr* ip, int caplen)
|
||||
{ }
|
||||
|
||||
|
@ -59,7 +59,7 @@ public:
|
|||
* Hook for receiving notification of stream gaps. Parameters are the
|
||||
* same as for Analyzer::Undelivered().
|
||||
*/
|
||||
virtual void Undelivered(int seq, int len, bool orig) { }
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig) { }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -143,7 +143,7 @@ public:
|
|||
* @param caplen The packet's capture length, if available.
|
||||
*/
|
||||
void NextPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq = -1, const IP_Hdr* ip = 0, int caplen = 0);
|
||||
uint64 seq = -1, const IP_Hdr* ip = 0, int caplen = 0);
|
||||
|
||||
/**
|
||||
* Passes stream input to the analyzer for processing. The analyzer
|
||||
|
@ -173,7 +173,7 @@ public:
|
|||
*
|
||||
* @param is_orig True if this is about originator-side input.
|
||||
*/
|
||||
void NextUndelivered(int seq, int len, bool is_orig);
|
||||
void NextUndelivered(uint64 seq, int len, bool is_orig);
|
||||
|
||||
/**
|
||||
* Reports a message boundary. This is a generic method that can be
|
||||
|
@ -195,7 +195,7 @@ public:
|
|||
* Parameters are the same as for NextPacket().
|
||||
*/
|
||||
virtual void ForwardPacket(int len, const u_char* data,
|
||||
bool orig, int seq,
|
||||
bool orig, uint64 seq,
|
||||
const IP_Hdr* ip, int caplen);
|
||||
|
||||
/**
|
||||
|
@ -212,7 +212,7 @@ public:
|
|||
*
|
||||
* Parameters are the same as for NextUndelivered().
|
||||
*/
|
||||
virtual void ForwardUndelivered(int seq, int len, bool orig);
|
||||
virtual void ForwardUndelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
/**
|
||||
* Forwards an end-of-data notification on to all child analyzers.
|
||||
|
@ -227,7 +227,7 @@ public:
|
|||
* Parameters are the same.
|
||||
*/
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
/**
|
||||
* Hook for accessing stream input for parsing. This is called by
|
||||
|
@ -241,7 +241,7 @@ public:
|
|||
* NextUndelivered() and can be overridden by derived classes.
|
||||
* Parameters are the same.
|
||||
*/
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
/**
|
||||
* Hook for accessing end-of-data notifications. This is called by
|
||||
|
@ -587,7 +587,7 @@ protected:
|
|||
void RemoveTimer(Timer* t);
|
||||
|
||||
/**
|
||||
* Returnsn true if the analyzer has associated an SupportAnalyzer of a given type.
|
||||
* Returns true if the analyzer has associated an SupportAnalyzer of a given type.
|
||||
*
|
||||
* @param tag The type to check for.
|
||||
*
|
||||
|
@ -595,6 +595,14 @@ protected:
|
|||
*/
|
||||
bool HasSupportAnalyzer(Tag tag, bool orig);
|
||||
|
||||
/**
|
||||
* Returns the first still active support analyzer for the given
|
||||
* direction, or null if none.
|
||||
*
|
||||
* @param orig True if asking about the originator side.
|
||||
*/
|
||||
SupportAnalyzer* FirstSupportAnalyzer(bool orig);
|
||||
|
||||
/**
|
||||
* Adds a a new child analyzer with the option whether to intialize
|
||||
* it. This is an internal method.
|
||||
|
@ -616,6 +624,12 @@ protected:
|
|||
*/
|
||||
void AppendNewChildren();
|
||||
|
||||
/**
|
||||
* Returns true if the analyzer has been flagged for removal and
|
||||
* shouldn't be used otherwise anymore.
|
||||
*/
|
||||
bool Removing() const { return removing; }
|
||||
|
||||
private:
|
||||
// Internal method to eventually delete a child analyzer that's
|
||||
// already Done().
|
||||
|
@ -718,6 +732,14 @@ public:
|
|||
*/
|
||||
bool IsOrig() const { return orig; }
|
||||
|
||||
/**
|
||||
* Returns the analyzer's next sibling, or null if none.
|
||||
*
|
||||
* only_active: If true, this will skip siblings that are still link
|
||||
* but flagged for removal.
|
||||
*/
|
||||
SupportAnalyzer* Sibling(bool only_active = false) const;
|
||||
|
||||
/**
|
||||
* Passes packet input to the next sibling SupportAnalyzer if any, or
|
||||
* on to the associated main analyzer if none. If however there's an
|
||||
|
@ -727,7 +749,7 @@ public:
|
|||
* Parameters same as for Analyzer::ForwardPacket.
|
||||
*/
|
||||
virtual void ForwardPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
/**
|
||||
* Passes stream input to the next sibling SupportAnalyzer if any, or
|
||||
|
@ -747,12 +769,7 @@ public:
|
|||
*
|
||||
* Parameters same as for Analyzer::ForwardPacket.
|
||||
*/
|
||||
virtual void ForwardUndelivered(int seq, int len, bool orig);
|
||||
|
||||
/**
|
||||
* Returns the analyzer next sibling, or null if none.
|
||||
*/
|
||||
SupportAnalyzer* Sibling() const { return sibling; }
|
||||
virtual void ForwardUndelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
protected:
|
||||
friend class Analyzer;
|
||||
|
|
|
@ -358,7 +358,6 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|||
udp::UDP_Analyzer* udp = 0;
|
||||
icmp::ICMP_Analyzer* icmp = 0;
|
||||
TransportLayerAnalyzer* root = 0;
|
||||
tag_set expected;
|
||||
pia::PIA* pia = 0;
|
||||
bool analyzed = false;
|
||||
bool check_port = false;
|
||||
|
@ -368,7 +367,6 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|||
case TRANSPORT_TCP:
|
||||
root = tcp = new tcp::TCP_Analyzer(conn);
|
||||
pia = new pia::PIA_TCP(conn);
|
||||
expected = GetScheduled(conn);
|
||||
check_port = true;
|
||||
DBG_ANALYZER(conn, "activated TCP analyzer");
|
||||
break;
|
||||
|
@ -376,7 +374,6 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|||
case TRANSPORT_UDP:
|
||||
root = udp = new udp::UDP_Analyzer(conn);
|
||||
pia = new pia::PIA_UDP(conn);
|
||||
expected = GetScheduled(conn);
|
||||
check_port = true;
|
||||
DBG_ANALYZER(conn, "activated UDP analyzer");
|
||||
break;
|
||||
|
@ -393,25 +390,12 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Any scheduled analyzer?
|
||||
for ( tag_set::iterator i = expected.begin(); i != expected.end(); i++ )
|
||||
{
|
||||
Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(*i, conn);
|
||||
|
||||
if ( analyzer )
|
||||
{
|
||||
root->AddChildAnalyzer(analyzer, false);
|
||||
|
||||
DBG_ANALYZER_ARGS(conn, "activated %s analyzer as scheduled",
|
||||
analyzer_mgr->GetComponentName(*i));
|
||||
}
|
||||
|
||||
}
|
||||
bool scheduled = ApplyScheduledAnalyzers(conn, false, root);
|
||||
|
||||
// Hmm... Do we want *just* the expected analyzer, or all
|
||||
// other potential analyzers as well? For now we only take
|
||||
// the scheduled ones.
|
||||
if ( expected.size() == 0 )
|
||||
if ( ! scheduled )
|
||||
{ // Let's see if it's a port we know.
|
||||
if ( check_port && ! dpd_ignore_ports )
|
||||
{
|
||||
|
@ -519,13 +503,6 @@ bool Manager::BuildInitialAnalyzerTree(Connection* conn)
|
|||
if ( ! analyzed )
|
||||
conn->SetLifetime(non_analyzed_lifetime);
|
||||
|
||||
for ( tag_set::iterator i = expected.begin(); i != expected.end(); i++ )
|
||||
{
|
||||
EnumVal* tag = i->AsEnumVal();
|
||||
Ref(tag);
|
||||
conn->Event(scheduled_analyzer_applied, 0, tag);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -636,3 +613,33 @@ Manager::tag_set Manager::GetScheduled(const Connection* conn)
|
|||
// eventually.
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Manager::ApplyScheduledAnalyzers(Connection* conn, bool init, TransportLayerAnalyzer* parent)
|
||||
{
|
||||
if ( ! parent )
|
||||
parent = conn->GetRootAnalyzer();
|
||||
|
||||
if ( ! parent )
|
||||
return false;
|
||||
|
||||
tag_set expected = GetScheduled(conn);
|
||||
|
||||
for ( tag_set::iterator it = expected.begin(); it != expected.end(); ++it )
|
||||
{
|
||||
Analyzer* analyzer = analyzer_mgr->InstantiateAnalyzer(*it, conn);
|
||||
|
||||
if ( ! analyzer )
|
||||
continue;
|
||||
|
||||
parent->AddChildAnalyzer(analyzer, init);
|
||||
|
||||
EnumVal* tag = it->AsEnumVal();
|
||||
Ref(tag);
|
||||
conn->Event(scheduled_analyzer_applied, 0, tag);
|
||||
|
||||
DBG_ANALYZER_ARGS(conn, "activated %s analyzer as scheduled",
|
||||
analyzer_mgr->GetComponentName(*it));
|
||||
}
|
||||
|
||||
return expected.size();
|
||||
}
|
||||
|
|
|
@ -292,6 +292,23 @@ public:
|
|||
TransportProto proto, const char* analyzer,
|
||||
double timeout);
|
||||
|
||||
/**
|
||||
* Searched for analyzers scheduled to be attached to a given connection
|
||||
* and then attaches them.
|
||||
*
|
||||
* @param conn The connection to which scheduled analyzers are attached.
|
||||
*
|
||||
* @param init True if the newly added analyzers should be
|
||||
* immediately initialized.
|
||||
*
|
||||
* @param root If given, the scheduled analyzers will become childs
|
||||
* of this; if not given the connection's root analyzer is used
|
||||
* instead.
|
||||
*
|
||||
* @return True if at least one scheduled analyzer was found.
|
||||
*/
|
||||
bool ApplyScheduledAnalyzers(Connection* conn, bool init_and_event = true, TransportLayerAnalyzer* parent = 0);
|
||||
|
||||
/**
|
||||
* Schedules a particular analyzer for an upcoming connection. Once
|
||||
* the connection is seen, BuildInitAnalyzerTree() will add the
|
||||
|
|
|
@ -29,6 +29,7 @@ add_subdirectory(pia)
|
|||
add_subdirectory(pop3)
|
||||
add_subdirectory(radius)
|
||||
add_subdirectory(rpc)
|
||||
add_subdirectory(snmp)
|
||||
add_subdirectory(smb)
|
||||
add_subdirectory(smtp)
|
||||
add_subdirectory(socks)
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
#endif
|
||||
|
||||
#include "NetVar.h"
|
||||
#include "PacketSort.h"
|
||||
|
||||
extern "C" {
|
||||
#include <pcap.h>
|
||||
}
|
||||
|
||||
namespace analyzer { namespace arp {
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ void AYIYA_Analyzer::Done()
|
|||
Event(udp_session_done);
|
||||
}
|
||||
|
||||
void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
void AYIYA_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ public:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new AYIYA_Analyzer(conn); }
|
||||
|
|
|
@ -46,7 +46,7 @@ void BackDoorEndpoint::FinalCheckForRlogin()
|
|||
}
|
||||
}
|
||||
|
||||
int BackDoorEndpoint::DataSent(double /* t */, int seq,
|
||||
int BackDoorEndpoint::DataSent(double /* t */, uint64 seq,
|
||||
int len, int caplen, const u_char* data,
|
||||
const IP_Hdr* /* ip */,
|
||||
const struct tcphdr* /* tp */)
|
||||
|
@ -60,8 +60,8 @@ int BackDoorEndpoint::DataSent(double /* t */, int seq,
|
|||
if ( endp->state == tcp::TCP_ENDPOINT_PARTIAL )
|
||||
is_partial = 1;
|
||||
|
||||
int ack = endp->AckSeq() - endp->StartSeq();
|
||||
int top_seq = seq + len;
|
||||
uint64 ack = endp->ToRelativeSeqSpace(endp->AckSeq(), endp->AckWraps());
|
||||
uint64 top_seq = seq + len;
|
||||
|
||||
if ( top_seq <= ack || top_seq <= max_top_seq )
|
||||
// There is no new data in this packet.
|
||||
|
@ -124,7 +124,7 @@ RecordVal* BackDoorEndpoint::BuildStats()
|
|||
return stats;
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForRlogin(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForRlogin(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
if ( rlogin_checking_done )
|
||||
return;
|
||||
|
@ -177,7 +177,7 @@ void BackDoorEndpoint::CheckForRlogin(int seq, int len, const u_char* data)
|
|||
|
||||
if ( seq < max_top_seq )
|
||||
{ // trim to just the new data
|
||||
int delta = max_top_seq - seq;
|
||||
int64 delta = max_top_seq - seq;
|
||||
seq += delta;
|
||||
data += delta;
|
||||
len -= delta;
|
||||
|
@ -255,7 +255,7 @@ void BackDoorEndpoint::RloginSignatureFound(int len)
|
|||
endp->TCP()->ConnectionEvent(rlogin_signature_found, vl);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForTelnet(int /* seq */, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForTelnet(uint64 /* seq */, int len, const u_char* data)
|
||||
{
|
||||
if ( len >= 3 &&
|
||||
data[0] == TELNET_IAC && IS_TELNET_NEGOTIATION_CMD(data[1]) )
|
||||
|
@ -346,7 +346,7 @@ void BackDoorEndpoint::TelnetSignatureFound(int len)
|
|||
endp->TCP()->ConnectionEvent(telnet_signature_found, vl);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForSSH(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
if ( seq == 1 && CheckForString("SSH-", data, len) && len > 4 &&
|
||||
(data[4] == '1' || data[4] == '2') )
|
||||
|
@ -363,8 +363,9 @@ void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data)
|
|||
|
||||
if ( seq > max_top_seq )
|
||||
{ // Estimate number of packets in the sequence gap
|
||||
int gap = seq - max_top_seq;
|
||||
num_pkts += int((gap + DEFAULT_MTU - 1) / DEFAULT_MTU);
|
||||
int64 gap = seq - max_top_seq;
|
||||
if ( gap > 0 )
|
||||
num_pkts += uint64((gap + DEFAULT_MTU - 1) / DEFAULT_MTU);
|
||||
}
|
||||
|
||||
++num_pkts;
|
||||
|
@ -388,7 +389,7 @@ void BackDoorEndpoint::CheckForSSH(int seq, int len, const u_char* data)
|
|||
}
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForRootBackdoor(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForRootBackdoor(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
// Check for root backdoor signature: an initial payload of
|
||||
// exactly "# ".
|
||||
|
@ -397,7 +398,7 @@ void BackDoorEndpoint::CheckForRootBackdoor(int seq, int len, const u_char* data
|
|||
SignatureFound(root_backdoor_signature_found);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForFTP(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForFTP(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
// Check for FTP signature
|
||||
//
|
||||
|
@ -429,7 +430,7 @@ void BackDoorEndpoint::CheckForFTP(int seq, int len, const u_char* data)
|
|||
SignatureFound(ftp_signature_found);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForNapster(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForNapster(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
// Check for Napster signature "GETfoobar" or "SENDfoobar" where
|
||||
// "foobar" is the Napster handle associated with the request
|
||||
|
@ -449,7 +450,7 @@ void BackDoorEndpoint::CheckForNapster(int seq, int len, const u_char* data)
|
|||
SignatureFound(napster_signature_found);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForSMTP(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForSMTP(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
const char* smtp_handshake[] = { "HELO", "EHLO", 0 };
|
||||
|
||||
|
@ -460,7 +461,7 @@ void BackDoorEndpoint::CheckForSMTP(int seq, int len, const u_char* data)
|
|||
SignatureFound(smtp_signature_found);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForIRC(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForIRC(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
if ( seq != 1 || is_partial )
|
||||
return;
|
||||
|
@ -475,7 +476,7 @@ void BackDoorEndpoint::CheckForIRC(int seq, int len, const u_char* data)
|
|||
SignatureFound(irc_signature_found);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForGnutella(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForGnutella(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
// After connecting to the server, the connecting client says:
|
||||
//
|
||||
|
@ -492,13 +493,13 @@ void BackDoorEndpoint::CheckForGnutella(int seq, int len, const u_char* data)
|
|||
SignatureFound(gnutella_signature_found);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForGaoBot(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForGaoBot(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
if ( seq == 1 && CheckForString("220 Bot Server (Win32)", data, len) )
|
||||
SignatureFound(gaobot_signature_found);
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForKazaa(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForKazaa(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
// *Some*, though not all, KaZaa connections begin with:
|
||||
//
|
||||
|
@ -565,7 +566,7 @@ int is_absolute_url(const u_char* data, int len)
|
|||
return *abs_url_sig_pos == '\0';
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForHTTP(int seq, int len, const u_char* data)
|
||||
void BackDoorEndpoint::CheckForHTTP(uint64 seq, int len, const u_char* data)
|
||||
{
|
||||
// According to the RFC, we should look for
|
||||
// '<method> SP <url> SP HTTP/<version> CR LF'
|
||||
|
@ -629,7 +630,7 @@ void BackDoorEndpoint::CheckForHTTP(int seq, int len, const u_char* data)
|
|||
}
|
||||
}
|
||||
|
||||
void BackDoorEndpoint::CheckForHTTPProxy(int /* seq */, int len,
|
||||
void BackDoorEndpoint::CheckForHTTPProxy(uint64 /* seq */, int len,
|
||||
const u_char* data)
|
||||
{
|
||||
// Proxy ONLY accepts absolute URI's: "The absoluteURI form is
|
||||
|
@ -713,7 +714,7 @@ void BackDoor_Analyzer::Init()
|
|||
}
|
||||
|
||||
void BackDoor_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq, const IP_Hdr* ip, int caplen)
|
||||
uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class BackDoorEndpoint {
|
|||
public:
|
||||
BackDoorEndpoint(tcp::TCP_Endpoint* e);
|
||||
|
||||
int DataSent(double t, int seq, int len, int caplen, const u_char* data,
|
||||
int DataSent(double t, uint64 seq, int len, int caplen, const u_char* data,
|
||||
const IP_Hdr* ip, const struct tcphdr* tp);
|
||||
|
||||
RecordVal* BuildStats();
|
||||
|
@ -22,23 +22,23 @@ public:
|
|||
void FinalCheckForRlogin();
|
||||
|
||||
protected:
|
||||
void CheckForRlogin(int seq, int len, const u_char* data);
|
||||
void CheckForRlogin(uint64 seq, int len, const u_char* data);
|
||||
void RloginSignatureFound(int len);
|
||||
|
||||
void CheckForTelnet(int seq, int len, const u_char* data);
|
||||
void CheckForTelnet(uint64 seq, int len, const u_char* data);
|
||||
void TelnetSignatureFound(int len);
|
||||
|
||||
void CheckForSSH(int seq, int len, const u_char* data);
|
||||
void CheckForFTP(int seq, int len, const u_char* data);
|
||||
void CheckForRootBackdoor(int seq, int len, const u_char* data);
|
||||
void CheckForNapster(int seq, int len, const u_char* data);
|
||||
void CheckForGnutella(int seq, int len, const u_char* data);
|
||||
void CheckForKazaa(int seq, int len, const u_char* data);
|
||||
void CheckForHTTP(int seq, int len, const u_char* data);
|
||||
void CheckForHTTPProxy(int seq, int len, const u_char* data);
|
||||
void CheckForSMTP(int seq, int len, const u_char* data);
|
||||
void CheckForIRC(int seq, int len, const u_char* data);
|
||||
void CheckForGaoBot(int seq, int len, const u_char* data);
|
||||
void CheckForSSH(uint64 seq, int len, const u_char* data);
|
||||
void CheckForFTP(uint64 seq, int len, const u_char* data);
|
||||
void CheckForRootBackdoor(uint64 seq, int len, const u_char* data);
|
||||
void CheckForNapster(uint64 seq, int len, const u_char* data);
|
||||
void CheckForGnutella(uint64 seq, int len, const u_char* data);
|
||||
void CheckForKazaa(uint64 seq, int len, const u_char* data);
|
||||
void CheckForHTTP(uint64 seq, int len, const u_char* data);
|
||||
void CheckForHTTPProxy(uint64 seq, int len, const u_char* data);
|
||||
void CheckForSMTP(uint64 seq, int len, const u_char* data);
|
||||
void CheckForIRC(uint64 seq, int len, const u_char* data);
|
||||
void CheckForGaoBot(uint64 seq, int len, const u_char* data);
|
||||
|
||||
void SignatureFound(EventHandlerPtr e, int do_orig = 0);
|
||||
|
||||
|
@ -48,11 +48,11 @@ protected:
|
|||
|
||||
tcp::TCP_Endpoint* endp;
|
||||
int is_partial;
|
||||
int max_top_seq;
|
||||
uint64 max_top_seq;
|
||||
|
||||
int rlogin_checking_done;
|
||||
int rlogin_num_null;
|
||||
int rlogin_string_separator_pos;
|
||||
uint64 rlogin_string_separator_pos;
|
||||
int rlogin_slash_seen;
|
||||
|
||||
uint32 num_pkts;
|
||||
|
@ -80,7 +80,7 @@ protected:
|
|||
// We support both packet and stream input, and can be instantiated
|
||||
// even if the TCP analyzer is not yet reassembling.
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
virtual void DeliverStream(int len, const u_char* data, bool is_orig);
|
||||
|
||||
void StatEvent();
|
||||
|
|
|
@ -68,7 +68,7 @@ void BitTorrent_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
|||
}
|
||||
}
|
||||
|
||||
void BitTorrent_Analyzer::Undelivered(int seq, int len, bool orig)
|
||||
void BitTorrent_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
virtual void EndpointEOF(bool is_orig);
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
|
|
|
@ -207,7 +207,7 @@ void BitTorrentTracker_Analyzer::ServerReply(int len, const u_char* data)
|
|||
}
|
||||
}
|
||||
|
||||
void BitTorrentTracker_Analyzer::Undelivered(int seq, int len, bool orig)
|
||||
void BitTorrentTracker_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
virtual void EndpointEOF(bool is_orig);
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
|
|
|
@ -36,7 +36,7 @@ void ConnSize_Analyzer::Done()
|
|||
Analyzer::Done();
|
||||
}
|
||||
|
||||
void ConnSize_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
void ConnSize_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
|
||||
uint64_t orig_bytes;
|
||||
|
|
|
@ -21,7 +21,7 @@ void DHCP_Analyzer::Done()
|
|||
}
|
||||
|
||||
void DHCP_Analyzer::DeliverPacket(int len, const u_char* data,
|
||||
bool orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
bool orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
interp->NewData(orig, data, data + len);
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new DHCP_Analyzer(conn); }
|
||||
|
|
|
@ -153,7 +153,7 @@ void DNP3_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
|||
}
|
||||
}
|
||||
|
||||
void DNP3_Analyzer::Undelivered(int seq, int len, bool orig)
|
||||
void DNP3_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
interp->NewGap(orig, len);
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
virtual void EndpointEOF(bool is_orig);
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
|
|
|
@ -32,6 +32,8 @@ event dnp3_application_response_header%(c: connection, is_orig: bool, fc: count,
|
|||
##
|
||||
## qua_field: qualifier field.
|
||||
##
|
||||
## number: TODO.
|
||||
##
|
||||
## rf_low: the structure of the range field depends on the qualified field.
|
||||
## In some cases, the range field contains only one logic part, e.g.,
|
||||
## number of objects, so only *rf_low* contains useful values.
|
||||
|
|
|
@ -137,18 +137,6 @@ int DNS_Interpreter::ParseQuestions(DNS_MsgInfo* msg,
|
|||
{
|
||||
int n = msg->qdcount;
|
||||
|
||||
if ( n == 0 )
|
||||
{
|
||||
// Generate event here because we won't go into ParseQuestion.
|
||||
EventHandlerPtr dns_event =
|
||||
msg->rcode == DNS_CODE_OK ?
|
||||
dns_query_reply : dns_rejected;
|
||||
BroString* question_name = new BroString("<no query>");
|
||||
|
||||
SendReplyOrRejectEvent(msg, dns_event, data, len, question_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ( n > 0 && ParseQuestion(msg, data, len, msg_start) )
|
||||
--n;
|
||||
return n == 0;
|
||||
|
@ -220,6 +208,7 @@ int DNS_Interpreter::ParseAnswer(DNS_MsgInfo* msg,
|
|||
int name_len = sizeof(name) - 1;
|
||||
|
||||
u_char* name_end = ExtractName(data, len, name, name_len, msg_start);
|
||||
|
||||
if ( ! name_end )
|
||||
return 0;
|
||||
|
||||
|
@ -287,7 +276,17 @@ int DNS_Interpreter::ParseAnswer(DNS_MsgInfo* msg,
|
|||
break;
|
||||
|
||||
case TYPE_SRV:
|
||||
status = ParseRR_SRV(msg, data, len, rdlength, msg_start);
|
||||
if ( ntohs(analyzer->Conn()->RespPort()) == 137 )
|
||||
{
|
||||
// This is an NBSTAT (NetBIOS NODE STATUS) record.
|
||||
// The SRV RFC reused the value that was already being
|
||||
// used for this.
|
||||
// We aren't parsing this yet.
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
status = ParseRR_SRV(msg, data, len, rdlength, msg_start);
|
||||
|
||||
break;
|
||||
|
||||
case TYPE_EDNS:
|
||||
|
@ -299,6 +298,16 @@ int DNS_Interpreter::ParseAnswer(DNS_MsgInfo* msg,
|
|||
break;
|
||||
|
||||
default:
|
||||
|
||||
if ( dns_unknown_reply && ! msg->skip_event )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
vl->append(analyzer->BuildConnVal());
|
||||
vl->append(msg->BuildHdrVal());
|
||||
vl->append(msg->BuildAnswerVal());
|
||||
analyzer->ConnectionEvent(dns_unknown_reply, vl);
|
||||
}
|
||||
|
||||
analyzer->Weird("DNS_RR_unknown_type");
|
||||
data += rdlength;
|
||||
len -= rdlength;
|
||||
|
@ -402,7 +411,9 @@ int DNS_Interpreter::ExtractLabel(const u_char*& data, int& len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ( label_len > 63 )
|
||||
if ( label_len > 63 &&
|
||||
// NetBIOS name service look ups can use longer labels.
|
||||
ntohs(analyzer->Conn()->RespPort()) != 137 )
|
||||
{
|
||||
analyzer->Weird("DNS_label_too_long");
|
||||
return 0;
|
||||
|
@ -635,15 +646,24 @@ int DNS_Interpreter::ParseRR_SRV(DNS_MsgInfo* msg,
|
|||
u_char* name_end = ExtractName(data, len, name, name_len, msg_start);
|
||||
if ( ! name_end )
|
||||
return 0;
|
||||
*name_end = 0; // terminate name so we can use it in snprintf()
|
||||
|
||||
if ( data - data_start != rdlength )
|
||||
analyzer->Weird("DNS_RR_length_mismatch");
|
||||
|
||||
// The following is just a placeholder.
|
||||
char buf[2048];
|
||||
safe_snprintf(buf, sizeof(buf), "SRV %s priority=%d weight=%d port=%d",
|
||||
name, priority, weight, port);
|
||||
if ( dns_SRV_reply && ! msg->skip_event )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
vl->append(analyzer->BuildConnVal());
|
||||
vl->append(msg->BuildHdrVal());
|
||||
vl->append(msg->BuildAnswerVal());
|
||||
vl->append(new StringVal(new BroString(name, name_end - name, 1)));
|
||||
vl->append(new Val(priority, TYPE_COUNT));
|
||||
vl->append(new Val(weight, TYPE_COUNT));
|
||||
vl->append(new Val(port, TYPE_COUNT));
|
||||
|
||||
analyzer->ConnectionEvent(dns_SRV_reply, vl);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -815,34 +835,61 @@ int DNS_Interpreter::ParseRR_HINFO(DNS_MsgInfo* msg,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static StringVal* extract_char_string(analyzer::Analyzer* analyzer,
|
||||
const u_char*& data, int& len, int& rdlen)
|
||||
{
|
||||
if ( rdlen <= 0 )
|
||||
return 0;
|
||||
|
||||
uint8 str_size = data[0];
|
||||
|
||||
--rdlen;
|
||||
--len;
|
||||
++data;
|
||||
|
||||
if ( str_size > rdlen )
|
||||
{
|
||||
analyzer->Weird("DNS_TXT_char_str_past_rdlen");
|
||||
return 0;
|
||||
}
|
||||
|
||||
StringVal* rval = new StringVal(str_size,
|
||||
reinterpret_cast<const char*>(data));
|
||||
|
||||
rdlen -= str_size;
|
||||
len -= str_size;
|
||||
data += str_size;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
int DNS_Interpreter::ParseRR_TXT(DNS_MsgInfo* msg,
|
||||
const u_char*& data, int& len, int rdlength,
|
||||
const u_char* msg_start)
|
||||
{
|
||||
int name_len = data[0];
|
||||
|
||||
char* name = new char[name_len];
|
||||
|
||||
memcpy(name, data+1, name_len);
|
||||
|
||||
data += rdlength;
|
||||
len -= rdlength;
|
||||
|
||||
if ( dns_TXT_reply && ! msg->skip_event )
|
||||
if ( ! dns_TXT_reply || msg->skip_event )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
|
||||
vl->append(analyzer->BuildConnVal());
|
||||
vl->append(msg->BuildHdrVal());
|
||||
vl->append(msg->BuildAnswerVal());
|
||||
vl->append(new StringVal(name_len, name));
|
||||
|
||||
analyzer->ConnectionEvent(dns_TXT_reply, vl);
|
||||
data += rdlength;
|
||||
len -= rdlength;
|
||||
return 1;
|
||||
}
|
||||
|
||||
delete [] name;
|
||||
VectorVal* char_strings = new VectorVal(string_vec);
|
||||
StringVal* char_string;
|
||||
|
||||
return 1;
|
||||
while ( (char_string = extract_char_string(analyzer, data, len, rdlength)) )
|
||||
char_strings->Assign(char_strings->Size(), char_string);
|
||||
|
||||
val_list* vl = new val_list;
|
||||
|
||||
vl->append(analyzer->BuildConnVal());
|
||||
vl->append(msg->BuildHdrVal());
|
||||
vl->append(msg->BuildAnswerVal());
|
||||
vl->append(char_strings);
|
||||
|
||||
analyzer->ConnectionEvent(dns_TXT_reply, vl);
|
||||
|
||||
return rdlength == 0;
|
||||
}
|
||||
|
||||
void DNS_Interpreter::SendReplyOrRejectEvent(DNS_MsgInfo* msg,
|
||||
|
@ -1126,7 +1173,7 @@ void DNS_Analyzer::Done()
|
|||
}
|
||||
|
||||
void DNS_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen)
|
||||
uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ public:
|
|||
~DNS_Analyzer();
|
||||
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
virtual void Init();
|
||||
virtual void Done();
|
||||
|
|
|
@ -50,7 +50,7 @@ event dns_message%(c: connection, is_orig: bool, msg: dns_msg, len: count%);
|
|||
event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%);
|
||||
|
||||
## Generated for DNS replies that reject a query. This event is raised if a DNS
|
||||
## reply either indicates failure via its status code or does not pass on any
|
||||
## reply indicates failure because it does not pass on any
|
||||
## answers to a query. Note that all of the event's parameters are parsed out of
|
||||
## the reply; there's no stateful correlation with the query.
|
||||
##
|
||||
|
@ -78,7 +78,7 @@ event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qcl
|
|||
## dns_skip_all_addl dns_skip_all_auth dns_skip_auth
|
||||
event dns_rejected%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%);
|
||||
|
||||
## Generated for DNS replies with an *ok* status code but no question section.
|
||||
## Generated for each entry in the Question section of a DNS reply.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Domain_Name_System>`__ for more
|
||||
## information about the DNS protocol. Bro analyzes both UDP and TCP DNS
|
||||
|
@ -376,7 +376,7 @@ event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string,
|
|||
## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
|
||||
## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
|
||||
## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
|
||||
event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%);
|
||||
event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, strs: string_vec%);
|
||||
|
||||
## Generated for DNS replies of type *SRV*. For replies with multiple answers,
|
||||
## an individual event of the corresponding type is raised for each.
|
||||
|
@ -392,6 +392,12 @@ event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%)
|
|||
##
|
||||
## ans: The type-independent part of the parsed answer record.
|
||||
##
|
||||
## priority: Priority of the SRV response.
|
||||
##
|
||||
## weight: Weight of the SRV response.
|
||||
##
|
||||
## p: Port of the SRV response.
|
||||
##
|
||||
## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
|
||||
## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
|
||||
## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request
|
||||
|
@ -399,7 +405,23 @@ event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%)
|
|||
## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply
|
||||
## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout
|
||||
## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth
|
||||
event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer%);
|
||||
event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer, target: string, priority: count, weight: count, p: count%);
|
||||
|
||||
## Generated on DNS reply resource records when the type of record is not one
|
||||
## that Bro knows how to parse and generate another more specific specific
|
||||
## event.
|
||||
##
|
||||
## c: The connection, which may be UDP or TCP depending on the type of the
|
||||
## transport-layer session being analyzed.
|
||||
##
|
||||
## msg: The parsed DNS message header.
|
||||
##
|
||||
## ans: The type-independent part of the parsed answer record.
|
||||
##
|
||||
## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl
|
||||
## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply
|
||||
## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_SRV_reply dns_end
|
||||
event dns_unknown_reply%(c: connection, msg: dns_msg, ans: dns_answer%);
|
||||
|
||||
## Generated for DNS replies of type *EDNS*. For replies with multiple answers,
|
||||
## an individual event of the corresponding type is raised for each.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "File.h"
|
||||
|
||||
#include "file_analysis/Manager.h"
|
||||
#include "RuleMatcher.h"
|
||||
#include "Reporter.h"
|
||||
#include "util.h"
|
||||
|
||||
|
@ -30,12 +31,25 @@ void File_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
|||
if ( buffer_len == BUFFER_SIZE )
|
||||
Identify();
|
||||
}
|
||||
return;
|
||||
|
||||
if ( orig )
|
||||
file_id_orig = file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(),
|
||||
orig, file_id_orig);
|
||||
else
|
||||
file_id_resp = file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(),
|
||||
orig, file_id_resp);
|
||||
}
|
||||
|
||||
void File_Analyzer::Undelivered(int seq, int len, bool orig)
|
||||
void File_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
|
||||
if ( orig )
|
||||
file_id_orig = file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig,
|
||||
file_id_orig);
|
||||
else
|
||||
file_id_resp = file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig,
|
||||
file_id_resp);
|
||||
}
|
||||
|
||||
void File_Analyzer::Done()
|
||||
|
@ -44,63 +58,29 @@ void File_Analyzer::Done()
|
|||
|
||||
if ( buffer_len && buffer_len != BUFFER_SIZE )
|
||||
Identify();
|
||||
|
||||
if ( ! file_id_orig.empty() )
|
||||
file_mgr->EndOfFile(file_id_orig);
|
||||
else
|
||||
file_mgr->EndOfFile(GetAnalyzerTag(), Conn(), true);
|
||||
|
||||
if ( ! file_id_resp.empty() )
|
||||
file_mgr->EndOfFile(file_id_resp);
|
||||
else
|
||||
file_mgr->EndOfFile(GetAnalyzerTag(), Conn(), false);
|
||||
}
|
||||
|
||||
void File_Analyzer::Identify()
|
||||
{
|
||||
const char* desc = bro_magic_buffer(magic_desc_cookie, buffer, buffer_len);
|
||||
const char* mime = bro_magic_buffer(magic_mime_cookie, buffer, buffer_len);
|
||||
|
||||
RuleMatcher::MIME_Matches matches;
|
||||
file_mgr->DetectMIME(reinterpret_cast<const u_char*>(buffer), buffer_len,
|
||||
&matches);
|
||||
string match = matches.empty() ? "<unknown>"
|
||||
: *(matches.begin()->second.begin());
|
||||
val_list* vl = new val_list;
|
||||
vl->append(BuildConnVal());
|
||||
vl->append(new StringVal(buffer_len, buffer));
|
||||
vl->append(new StringVal(desc ? desc : "<unknown>"));
|
||||
vl->append(new StringVal(mime ? mime : "<unknown>"));
|
||||
vl->append(new StringVal("<unknown>"));
|
||||
vl->append(new StringVal(match));
|
||||
ConnectionEvent(file_transferred, vl);
|
||||
}
|
||||
|
||||
IRC_Data::IRC_Data(Connection* conn)
|
||||
: File_Analyzer("IRC_Data", conn)
|
||||
{
|
||||
}
|
||||
|
||||
void IRC_Data::Done()
|
||||
{
|
||||
File_Analyzer::Done();
|
||||
file_mgr->EndOfFile(GetAnalyzerTag(), Conn());
|
||||
}
|
||||
|
||||
void IRC_Data::DeliverStream(int len, const u_char* data, bool orig)
|
||||
{
|
||||
File_Analyzer::DeliverStream(len, data, orig);
|
||||
file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(), orig);
|
||||
}
|
||||
|
||||
void IRC_Data::Undelivered(int seq, int len, bool orig)
|
||||
{
|
||||
File_Analyzer::Undelivered(seq, len, orig);
|
||||
file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig);
|
||||
}
|
||||
|
||||
FTP_Data::FTP_Data(Connection* conn)
|
||||
: File_Analyzer("FTP_Data", conn)
|
||||
{
|
||||
}
|
||||
|
||||
void FTP_Data::Done()
|
||||
{
|
||||
File_Analyzer::Done();
|
||||
file_mgr->EndOfFile(GetAnalyzerTag(), Conn());
|
||||
}
|
||||
|
||||
void FTP_Data::DeliverStream(int len, const u_char* data, bool orig)
|
||||
{
|
||||
File_Analyzer::DeliverStream(len, data, orig);
|
||||
file_mgr->DataIn(data, len, GetAnalyzerTag(), Conn(), orig);
|
||||
}
|
||||
|
||||
void FTP_Data::Undelivered(int seq, int len, bool orig)
|
||||
{
|
||||
File_Analyzer::Undelivered(seq, len, orig);
|
||||
file_mgr->Gap(seq, len, GetAnalyzerTag(), Conn(), orig);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
|
||||
void Undelivered(int seq, int len, bool orig);
|
||||
void Undelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
// static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
// { return new File_Analyzer(conn); }
|
||||
|
@ -28,17 +28,15 @@ protected:
|
|||
static const int BUFFER_SIZE = 1024;
|
||||
char buffer[BUFFER_SIZE];
|
||||
int buffer_len;
|
||||
string file_id_orig;
|
||||
string file_id_resp;
|
||||
};
|
||||
|
||||
class IRC_Data : public File_Analyzer {
|
||||
public:
|
||||
IRC_Data(Connection* conn);
|
||||
|
||||
virtual void Done();
|
||||
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
IRC_Data(Connection* conn)
|
||||
: File_Analyzer("IRC_Data", conn)
|
||||
{ }
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new IRC_Data(conn); }
|
||||
|
@ -46,13 +44,9 @@ public:
|
|||
|
||||
class FTP_Data : public File_Analyzer {
|
||||
public:
|
||||
FTP_Data(Connection* conn);
|
||||
|
||||
virtual void Done();
|
||||
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
FTP_Data(Connection* conn)
|
||||
: File_Analyzer("FTP_Data", conn)
|
||||
{ }
|
||||
|
||||
static Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new FTP_Data(conn); }
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
## TODO.
|
||||
## Generated when a TCP connection associated w/ file data transfer is seen
|
||||
## (e.g. as happens w/ FTP or IRC).
|
||||
##
|
||||
## c: The connection over which file data is transferred.
|
||||
##
|
||||
## prefix: Up to 1024 bytes of the file data.
|
||||
##
|
||||
## descr: Deprecated/unused argument.
|
||||
##
|
||||
## mime_type: MIME type of the file or "<unknown>" if no file magic signatures
|
||||
## matched.
|
||||
event file_transferred%(c: connection, prefix: string, descr: string, mime_type: string%);
|
||||
|
|
|
@ -23,7 +23,7 @@ void GTPv1_Analyzer::Done()
|
|||
Event(udp_session_done);
|
||||
}
|
||||
|
||||
void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
void GTPv1_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
try
|
||||
|
|
|
@ -12,7 +12,7 @@ public:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new GTPv1_Analyzer(conn); }
|
||||
|
|
|
@ -242,10 +242,17 @@ int HTTP_Entity::Undelivered(int64_t len)
|
|||
if ( end_of_data && in_header )
|
||||
return 0;
|
||||
|
||||
file_mgr->Gap(body_length, len,
|
||||
http_message->MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
http_message->MyHTTP_Analyzer()->Conn(),
|
||||
http_message->IsOrig());
|
||||
if ( is_partial_content )
|
||||
precomputed_file_id = file_mgr->Gap(body_length, len,
|
||||
http_message->MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
http_message->MyHTTP_Analyzer()->Conn(),
|
||||
http_message->IsOrig(), precomputed_file_id);
|
||||
else
|
||||
precomputed_file_id = file_mgr->Gap(body_length, len,
|
||||
http_message->MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
http_message->MyHTTP_Analyzer()->Conn(),
|
||||
http_message->IsOrig(),
|
||||
precomputed_file_id);
|
||||
|
||||
if ( chunked_transfer_state != NON_CHUNKED_TRANSFER )
|
||||
{
|
||||
|
@ -299,30 +306,33 @@ void HTTP_Entity::SubmitData(int len, const char* buf)
|
|||
if ( is_partial_content )
|
||||
{
|
||||
if ( send_size && instance_length > 0 )
|
||||
file_mgr->SetSize(instance_length,
|
||||
precomputed_file_id = file_mgr->SetSize(instance_length,
|
||||
http_message->MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
http_message->MyHTTP_Analyzer()->Conn(),
|
||||
http_message->IsOrig());
|
||||
http_message->IsOrig(), precomputed_file_id);
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(buf), len, offset,
|
||||
precomputed_file_id = file_mgr->DataIn(reinterpret_cast<const u_char*>(buf), len, offset,
|
||||
http_message->MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
http_message->MyHTTP_Analyzer()->Conn(),
|
||||
http_message->IsOrig());
|
||||
http_message->IsOrig(), precomputed_file_id);
|
||||
|
||||
offset += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( send_size && content_length > 0 )
|
||||
file_mgr->SetSize(content_length,
|
||||
precomputed_file_id = file_mgr->SetSize(content_length,
|
||||
http_message->MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
http_message->MyHTTP_Analyzer()->Conn(),
|
||||
http_message->IsOrig());
|
||||
http_message->IsOrig(),
|
||||
precomputed_file_id);
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(buf), len,
|
||||
precomputed_file_id = file_mgr->DataIn(reinterpret_cast<const u_char*>(buf),
|
||||
len,
|
||||
http_message->MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
http_message->MyHTTP_Analyzer()->Conn(),
|
||||
http_message->IsOrig());
|
||||
http_message->IsOrig(),
|
||||
precomputed_file_id);
|
||||
}
|
||||
|
||||
send_size = false;
|
||||
|
@ -573,9 +583,16 @@ void HTTP_Message::Done(const int interrupted, const char* detail)
|
|||
top_level->EndOfData();
|
||||
|
||||
if ( is_orig || MyHTTP_Analyzer()->HTTP_ReplyCode() != 206 )
|
||||
// multipart/byteranges may span multiple connections
|
||||
file_mgr->EndOfFile(MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
MyHTTP_Analyzer()->Conn(), is_orig);
|
||||
{
|
||||
// multipart/byteranges may span multiple connections, so don't EOF.
|
||||
HTTP_Entity* he = dynamic_cast<HTTP_Entity*>(top_level);
|
||||
|
||||
if ( he && ! he->FileID().empty() )
|
||||
file_mgr->EndOfFile(he->FileID());
|
||||
else
|
||||
file_mgr->EndOfFile(MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
MyHTTP_Analyzer()->Conn(), is_orig);
|
||||
}
|
||||
|
||||
if ( http_message_done )
|
||||
{
|
||||
|
@ -653,8 +670,15 @@ void HTTP_Message::EndEntity(mime::MIME_Entity* entity)
|
|||
Done();
|
||||
|
||||
else if ( is_orig || MyHTTP_Analyzer()->HTTP_ReplyCode() != 206 )
|
||||
file_mgr->EndOfFile(MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
MyHTTP_Analyzer()->Conn(), is_orig);
|
||||
{
|
||||
HTTP_Entity* he = dynamic_cast<HTTP_Entity*>(entity);
|
||||
|
||||
if ( he && ! he->FileID().empty() )
|
||||
file_mgr->EndOfFile(he->FileID());
|
||||
else
|
||||
file_mgr->EndOfFile(MyHTTP_Analyzer()->GetAnalyzerTag(),
|
||||
MyHTTP_Analyzer()->Conn(), is_orig);
|
||||
}
|
||||
}
|
||||
|
||||
void HTTP_Message::SubmitHeader(mime::MIME_Header* h)
|
||||
|
@ -879,6 +903,9 @@ HTTP_Analyzer::HTTP_Analyzer(Connection* conn)
|
|||
reply_code = 0;
|
||||
reply_reason_phrase = 0;
|
||||
|
||||
connect_request = false;
|
||||
pia = 0;
|
||||
|
||||
content_line_orig = new tcp::ContentLine_Analyzer(conn, true);
|
||||
AddSupportAnalyzer(content_line_orig);
|
||||
|
||||
|
@ -935,6 +962,14 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
|
|||
if ( TCP() && TCP()->IsPartial() )
|
||||
return;
|
||||
|
||||
if ( pia )
|
||||
{
|
||||
// There will be a PIA instance if this connection has been identified
|
||||
// as a connect proxy.
|
||||
ForwardStream(len, data, is_orig);
|
||||
return;
|
||||
}
|
||||
|
||||
const char* line = reinterpret_cast<const char*>(data);
|
||||
const char* end_of_line = line + len;
|
||||
|
||||
|
@ -1045,6 +1080,29 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
|
|||
|
||||
HTTP_Reply();
|
||||
|
||||
if ( connect_request && reply_code == 200 )
|
||||
{
|
||||
pia = new pia::PIA_TCP(Conn());
|
||||
|
||||
if ( AddChildAnalyzer(pia) )
|
||||
{
|
||||
pia->FirstPacket(true, 0);
|
||||
pia->FirstPacket(false, 0);
|
||||
|
||||
// This connection has transitioned to no longer
|
||||
// being http and the content line support analyzers
|
||||
// need to be removed.
|
||||
RemoveSupportAnalyzer(content_line_orig);
|
||||
RemoveSupportAnalyzer(content_line_resp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
// AddChildAnalyzer() will have deleted PIA.
|
||||
pia = 0;
|
||||
}
|
||||
|
||||
InitHTTPMessage(content_line,
|
||||
reply_message, is_orig,
|
||||
ExpectReplyMessageBody(),
|
||||
|
@ -1071,11 +1129,11 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
|
|||
}
|
||||
}
|
||||
|
||||
void HTTP_Analyzer::Undelivered(int seq, int len, bool is_orig)
|
||||
void HTTP_Analyzer::Undelivered(uint64 seq, int len, bool is_orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, is_orig);
|
||||
|
||||
// DEBUG_MSG("Undelivered from %d: %d bytes\n", seq, length);
|
||||
// DEBUG_MSG("Undelivered from %"PRIu64": %d bytes\n", seq, length);
|
||||
|
||||
HTTP_Message* msg =
|
||||
is_orig ? request_message : reply_message;
|
||||
|
@ -1087,7 +1145,7 @@ void HTTP_Analyzer::Undelivered(int seq, int len, bool is_orig)
|
|||
{
|
||||
if ( msg )
|
||||
msg->SubmitEvent(mime::MIME_EVENT_CONTENT_GAP,
|
||||
fmt("seq=%d, len=%d", seq, len));
|
||||
fmt("seq=%"PRIu64", len=%d", seq, len));
|
||||
}
|
||||
|
||||
// Check if the content gap falls completely within a message body
|
||||
|
@ -1380,6 +1438,12 @@ void HTTP_Analyzer::HTTP_Request()
|
|||
{
|
||||
ProtocolConfirmation();
|
||||
|
||||
const char* method = (const char*) request_method->AsString()->Bytes();
|
||||
int method_len = request_method->AsString()->Len();
|
||||
|
||||
if ( strcasecmp_n(method_len, method, "CONNECT") == 0 )
|
||||
connect_request = true;
|
||||
|
||||
if ( http_request )
|
||||
{
|
||||
val_list* vl = new val_list;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "analyzer/protocol/tcp/TCP.h"
|
||||
#include "analyzer/protocol/tcp/ContentLine.h"
|
||||
#include "analyzer/protocol/pia/PIA.h"
|
||||
#include "analyzer/protocol/zip/ZIP.h"
|
||||
#include "analyzer/protocol/mime/MIME.h"
|
||||
#include "binpac_bro.h"
|
||||
|
@ -45,6 +46,7 @@ public:
|
|||
int64_t BodyLength() const { return body_length; }
|
||||
int64_t HeaderLength() const { return header_length; }
|
||||
void SkipBody() { deliver_body = 0; }
|
||||
const string& FileID() const { return precomputed_file_id; }
|
||||
|
||||
protected:
|
||||
class UncompressedOutput;
|
||||
|
@ -64,6 +66,7 @@ protected:
|
|||
uint64_t offset;
|
||||
int64_t instance_length; // total length indicated by content-range
|
||||
bool send_size; // whether to send size indication to FAF
|
||||
std::string precomputed_file_id;
|
||||
|
||||
MIME_Entity* NewChildEntity() { return new HTTP_Entity(http_message, this, 1); }
|
||||
|
||||
|
@ -159,7 +162,7 @@ public:
|
|||
HTTP_Analyzer(Connection* conn);
|
||||
~HTTP_Analyzer();
|
||||
|
||||
void Undelivered(tcp::TCP_Endpoint* sender, int seq, int len);
|
||||
void Undelivered(tcp::TCP_Endpoint* sender, uint64 seq, int len);
|
||||
|
||||
void HTTP_Header(int is_orig, mime::MIME_Header* h);
|
||||
void HTTP_EntityData(int is_orig, const BroString* entity_data);
|
||||
|
@ -175,7 +178,7 @@ public:
|
|||
// Overriden from Analyzer.
|
||||
virtual void Done();
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
// Overriden from tcp::TCP_ApplicationAnalyzer
|
||||
virtual void EndpointEOF(bool is_orig);
|
||||
|
@ -236,6 +239,9 @@ protected:
|
|||
int connection_close;
|
||||
int request_ongoing, reply_ongoing;
|
||||
|
||||
bool connect_request;
|
||||
pia::PIA_TCP *pia;
|
||||
|
||||
Val* request_method;
|
||||
|
||||
// request_URI is in the original form (may contain '%<hex><hex>'
|
||||
|
|
|
@ -31,7 +31,7 @@ void ICMP_Analyzer::Done()
|
|||
}
|
||||
|
||||
void ICMP_Analyzer::DeliverPacket(int len, const u_char* data,
|
||||
bool is_orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
assert(ip);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ protected:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
virtual bool IsReuse(double t, const u_char* pkt);
|
||||
virtual unsigned int MemoryAllocation() const;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ InterConnEndpoint::InterConnEndpoint(tcp::TCP_Endpoint* e)
|
|||
|
||||
#define NORMAL_LINE_LENGTH 80
|
||||
|
||||
int InterConnEndpoint::DataSent(double t, int seq, int len, int caplen,
|
||||
int InterConnEndpoint::DataSent(double t, uint64 seq, int len, int caplen,
|
||||
const u_char* data, const IP_Hdr* /* ip */,
|
||||
const struct tcphdr* /* tp */)
|
||||
{
|
||||
|
@ -37,8 +37,8 @@ int InterConnEndpoint::DataSent(double t, int seq, int len, int caplen,
|
|||
if ( endp->state == tcp::TCP_ENDPOINT_PARTIAL )
|
||||
is_partial = 1;
|
||||
|
||||
int ack = endp->AckSeq() - endp->StartSeq();
|
||||
int top_seq = seq + len;
|
||||
uint64 ack = endp->ToRelativeSeqSpace(endp->AckSeq(), endp->AckWraps());
|
||||
uint64 top_seq = seq + len;
|
||||
|
||||
if ( top_seq <= ack || top_seq <= max_top_seq )
|
||||
// There is no new data in this packet
|
||||
|
@ -46,7 +46,7 @@ int InterConnEndpoint::DataSent(double t, int seq, int len, int caplen,
|
|||
|
||||
if ( seq < max_top_seq )
|
||||
{ // Only consider new data
|
||||
int amount_seen = max_top_seq - seq;
|
||||
int64 amount_seen = max_top_seq - seq;
|
||||
seq += amount_seen;
|
||||
data += amount_seen;
|
||||
len -= amount_seen;
|
||||
|
@ -184,7 +184,7 @@ void InterConn_Analyzer::Init()
|
|||
}
|
||||
|
||||
void InterConn_Analyzer::DeliverPacket(int len, const u_char* data,
|
||||
bool is_orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, is_orig,
|
||||
seq, ip, caplen);
|
||||
|
|
|
@ -13,7 +13,7 @@ class InterConnEndpoint : public BroObj {
|
|||
public:
|
||||
InterConnEndpoint(tcp::TCP_Endpoint* e);
|
||||
|
||||
int DataSent(double t, int seq, int len, int caplen, const u_char* data,
|
||||
int DataSent(double t, uint64 seq, int len, int caplen, const u_char* data,
|
||||
const IP_Hdr* ip, const struct tcphdr* tp);
|
||||
|
||||
RecordVal* BuildStats();
|
||||
|
@ -25,7 +25,7 @@ protected:
|
|||
|
||||
tcp::TCP_Endpoint* endp;
|
||||
double last_keystroke_time;
|
||||
int max_top_seq;
|
||||
uint64 max_top_seq;
|
||||
uint32 num_pkts;
|
||||
uint32 num_keystrokes_two_in_a_row;
|
||||
uint32 num_normal_interarrivals;
|
||||
|
@ -56,7 +56,7 @@ protected:
|
|||
// We support both packet and stream input and can be put in place even
|
||||
// if the TCP analyzer is not yet reassembling.
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool is_orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
virtual void DeliverStream(int len, const u_char* data, bool is_orig);
|
||||
|
||||
void StatEvent();
|
||||
|
|
|
@ -1044,6 +1044,7 @@ void MIME_Entity::DecodeQuotedPrintable(int len, const char* data)
|
|||
{
|
||||
DataOctet((a << 4) + b);
|
||||
legal = 1;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ void ModbusTCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
|||
interp->NewData(orig, data, data + len);
|
||||
}
|
||||
|
||||
void ModbusTCP_Analyzer::Undelivered(int seq, int len, bool orig)
|
||||
void ModbusTCP_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
interp->NewGap(orig, len);
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
virtual void Done();
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
virtual void EndpointEOF(bool is_orig);
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
|
|
|
@ -149,7 +149,7 @@ event modbus_write_single_register_response%(c: connection, headers: ModbusHeade
|
|||
##
|
||||
## start_address: The memory address of the first coil to be written.
|
||||
##
|
||||
## value: The values to be written to the coils.
|
||||
## coils: The values to be written to the coils.
|
||||
event modbus_write_multiple_coils_request%(c: connection, headers: ModbusHeaders, start_address: count, coils: ModbusCoils%);
|
||||
|
||||
## Generated for a Modbus write multiple coils response.
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
%header{
|
||||
VectorVal* bytestring_to_coils(bytestring coils, uint quantity);
|
||||
RecordVal* HeaderToBro(ModbusTCP_TransportHeader *header);
|
||||
VectorVal* create_vector_of_count();
|
||||
%}
|
||||
|
||||
%code{
|
||||
|
@ -30,6 +31,14 @@
|
|||
return modbus_header;
|
||||
}
|
||||
|
||||
VectorVal* create_vector_of_count()
|
||||
{
|
||||
VectorType* vt = new VectorType(base_type(TYPE_COUNT));
|
||||
VectorVal* vv = new VectorVal(vt);
|
||||
Unref(vt);
|
||||
return vv;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
refine flow ModbusTCP_Flow += {
|
||||
|
@ -367,7 +376,7 @@ refine flow ModbusTCP_Flow += {
|
|||
if ( ::modbus_read_file_record_request )
|
||||
{
|
||||
//TODO: this need to be a vector of some Reference Request record type
|
||||
//VectorVal *t = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
|
||||
//VectorVal *t = create_vector_of_count();
|
||||
//for ( unsigned int i = 0; i < (${message.references}->size()); ++i )
|
||||
// {
|
||||
// Val* r = new Val((${message.references[i].ref_type}), TYPE_COUNT);
|
||||
|
@ -393,7 +402,7 @@ refine flow ModbusTCP_Flow += {
|
|||
%{
|
||||
if ( ::modbus_read_file_record_response )
|
||||
{
|
||||
//VectorVal *t = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
|
||||
//VectorVal *t = create_vector_of_count();
|
||||
//for ( unsigned int i = 0; i < ${message.references}->size(); ++i )
|
||||
// {
|
||||
// //TODO: work the reference type in here somewhere
|
||||
|
@ -414,7 +423,7 @@ refine flow ModbusTCP_Flow += {
|
|||
%{
|
||||
if ( ::modbus_write_file_record_request )
|
||||
{
|
||||
//VectorVal* t = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
|
||||
//VectorVal* t = create_vector_of_count();
|
||||
//for ( unsigned int i = 0; i < (${message.references}->size()); ++i )
|
||||
// {
|
||||
// Val* r = new Val((${message.references[i].ref_type}), TYPE_COUNT);
|
||||
|
@ -447,7 +456,7 @@ refine flow ModbusTCP_Flow += {
|
|||
%{
|
||||
if ( ::modbus_write_file_record_response )
|
||||
{
|
||||
//VectorVal* t = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
|
||||
//VectorVal* t = create_vector_of_count();
|
||||
//for ( unsigned int i = 0; i < (${messages.references}->size()); ++i )
|
||||
// {
|
||||
// Val* r = new Val((${message.references[i].ref_type}), TYPE_COUNT);
|
||||
|
@ -589,7 +598,7 @@ refine flow ModbusTCP_Flow += {
|
|||
|
||||
if ( ::modbus_read_fifo_queue_response )
|
||||
{
|
||||
VectorVal* t = new VectorVal(new VectorType(base_type(TYPE_COUNT)));
|
||||
VectorVal* t = create_vector_of_count();
|
||||
for ( unsigned int i = 0; i < (${message.register_data})->size(); ++i )
|
||||
{
|
||||
Val* r = new Val(${message.register_data[i]}, TYPE_COUNT);
|
||||
|
|
|
@ -211,7 +211,7 @@ void Contents_NCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig
|
|||
}
|
||||
}
|
||||
|
||||
void Contents_NCP_Analyzer::Undelivered(int seq, int len, bool orig)
|
||||
void Contents_NCP_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
tcp::TCP_SupportAnalyzer::Undelivered(seq, len, orig);
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
virtual void Undelivered(int seq, int len, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
NCP_FrameBuffer buffer;
|
||||
NCP_Session* session;
|
||||
|
|
|
@ -513,7 +513,7 @@ void NetbiosSSN_Analyzer::ConnectionClosed(tcp::TCP_Endpoint* endpoint,
|
|||
}
|
||||
|
||||
void NetbiosSSN_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen)
|
||||
uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ public:
|
|||
|
||||
virtual void Done();
|
||||
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||
int seq, const IP_Hdr* ip, int caplen);
|
||||
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new NetbiosSSN_Analyzer(conn); }
|
||||
|
|
|
@ -25,7 +25,7 @@ void NTP_Analyzer::Done()
|
|||
Event(udp_session_done);
|
||||
}
|
||||
|
||||
void NTP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen)
|
||||
void NTP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||
{
|
||||
Analyzer::DeliverPacket(len, data, is_orig, seq, ip, caplen);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue