Reformat the world

This commit is contained in:
Tim Wojtulewicz 2021-09-16 15:35:39 -07:00
parent 194cb24547
commit b2f171ec69
714 changed files with 35149 additions and 35203 deletions

View file

@ -1,36 +1,36 @@
#include "zeek/Anon.h" #include "zeek/Anon.h"
#include <stdlib.h>
#include <unistd.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h>
#include "zeek/util.h" #include "zeek/Event.h"
#include "zeek/net_util.h" #include "zeek/ID.h"
#include "zeek/Val.h" #include "zeek/IPAddr.h"
#include "zeek/NetVar.h" #include "zeek/NetVar.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/Scope.h" #include "zeek/Scope.h"
#include "zeek/ID.h" #include "zeek/Val.h"
#include "zeek/IPAddr.h" #include "zeek/net_util.h"
#include "zeek/Event.h" #include "zeek/util.h"
namespace zeek::detail { namespace zeek::detail
{
AnonymizeIPAddr* ip_anonymizer[NUM_ADDR_ANONYMIZATION_METHODS] = {nullptr}; AnonymizeIPAddr* ip_anonymizer[NUM_ADDR_ANONYMIZATION_METHODS] = {nullptr};
static uint32_t rand32() static uint32_t rand32()
{ {
return ((util::detail::random_number() & 0xffff) << 16) | (util::detail::random_number() & 0xffff); return ((util::detail::random_number() & 0xffff) << 16) |
(util::detail::random_number() & 0xffff);
} }
// From tcpdpriv. // From tcpdpriv.
static int bi_ffs(uint32_t value) static int bi_ffs(uint32_t value)
{ {
int add = 0; int add = 0;
static uint8_t bvals[] = { static uint8_t bvals[] = {0, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1};
0, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1
};
if ( (value & 0xFFFF0000) == 0 ) if ( (value & 0xFFFF0000) == 0 )
{ {
@ -57,7 +57,7 @@ static int bi_ffs(uint32_t value)
return add + bvals[value & 0xf]; return add + bvals[value & 0xf];
} }
#define first_n_bit_mask(n) (~(0xFFFFFFFFU >> n)) #define first_n_bit_mask(n) (~(0xFFFFFFFFU >> n))
ipaddr32_t AnonymizeIPAddr::Anonymize(ipaddr32_t addr) ipaddr32_t AnonymizeIPAddr::Anonymize(ipaddr32_t addr)
{ {
@ -82,16 +82,17 @@ bool AnonymizeIPAddr::PreservePrefix(ipaddr32_t /* input */, int /* num_bits */)
bool AnonymizeIPAddr::PreserveNet(ipaddr32_t input) bool AnonymizeIPAddr::PreserveNet(ipaddr32_t input)
{ {
switch ( addr_to_class(ntohl(input)) ) { switch ( addr_to_class(ntohl(input)) )
case 'A': {
return PreservePrefix(input, 8); case 'A':
case 'B': return PreservePrefix(input, 8);
return PreservePrefix(input, 16); case 'B':
case 'C': return PreservePrefix(input, 16);
return PreservePrefix(input, 24); case 'C':
default: return PreservePrefix(input, 24);
return false; default:
} return false;
}
} }
ipaddr32_t AnonymizeIPAddr_Seq::anonymize(ipaddr32_t /* input */) ipaddr32_t AnonymizeIPAddr_Seq::anonymize(ipaddr32_t /* input */)
@ -113,7 +114,6 @@ ipaddr32_t AnonymizeIPAddr_RandomMD5::anonymize(ipaddr32_t input)
return output; return output;
} }
// This code is from "On the Design and Performance of Prefix-Preserving // This code is from "On the Design and Performance of Prefix-Preserving
// IP Traffic Trace Anonymization", by Xu et al (IMW 2001) // IP Traffic Trace Anonymization", by Xu et al (IMW 2001)
// //
@ -130,13 +130,13 @@ ipaddr32_t AnonymizeIPAddr_PrefixMD5::anonymize(ipaddr32_t input)
{ {
// PAD(x_0 ... x_{i-1}) = x_0 ... x_{i-1} 1 0 ... 0 . // PAD(x_0 ... x_{i-1}) = x_0 ... x_{i-1} 1 0 ... 0 .
prefix.len = htonl(i + 1); prefix.len = htonl(i + 1);
prefix.prefix = htonl((input & ~(prefix_mask>>i)) | (1<<(31-i))); prefix.prefix = htonl((input & ~(prefix_mask >> i)) | (1 << (31 - i)));
// HK(PAD(x_0 ... x_{i-1})). // HK(PAD(x_0 ... x_{i-1})).
util::detail::hmac_md5(sizeof(prefix), (u_char*) &prefix, digest); util::detail::hmac_md5(sizeof(prefix), (u_char*)&prefix, digest);
// f_{i-1} = LSB(HK(PAD(x_0 ... x_{i-1}))). // f_{i-1} = LSB(HK(PAD(x_0 ... x_{i-1}))).
ipaddr32_t bit_mask = (digest[0] & 1) << (31-i); ipaddr32_t bit_mask = (digest[0] & 1) << (31 - i);
// x_i' = x_i ^ f_{i-1}. // x_i' = x_i ^ f_{i-1}.
output ^= bit_mask; output ^= bit_mask;
@ -148,7 +148,7 @@ ipaddr32_t AnonymizeIPAddr_PrefixMD5::anonymize(ipaddr32_t input)
AnonymizeIPAddr_A50::~AnonymizeIPAddr_A50() AnonymizeIPAddr_A50::~AnonymizeIPAddr_A50()
{ {
for ( auto& b : blocks ) for ( auto& b : blocks )
delete [] b; delete[] b;
} }
void AnonymizeIPAddr_A50::init() void AnonymizeIPAddr_A50::init()
@ -167,9 +167,7 @@ void AnonymizeIPAddr_A50::init()
bool AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits) bool AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits)
{ {
DEBUG_MSG("%s/%d\n", DEBUG_MSG("%s/%d\n", IPAddr(IPv4, &input, IPAddr::Network).AsString().c_str(), num_bits);
IPAddr(IPv4, &input, IPAddr::Network).AsString().c_str(),
num_bits);
if ( ! before_anonymization ) if ( ! before_anonymization )
{ {
@ -225,7 +223,7 @@ AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node_block()
blocks.push_back(block); blocks.push_back(block);
for ( int i = 1; i < block_size - 1; ++i ) for ( int i = 1; i < block_size - 1; ++i )
block[i].child[0] = &block[i+1]; block[i].child[0] = &block[i + 1];
block[block_size - 1].child[0] = nullptr; block[block_size - 1].child[0] = nullptr;
next_free_node = &block[1]; next_free_node = &block[1];
@ -247,7 +245,7 @@ inline AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node()
return new_node_block(); return new_node_block();
} }
inline void AnonymizeIPAddr_A50::free_node(Node *n) inline void AnonymizeIPAddr_A50::free_node(Node* n)
{ {
n->child[0] = next_free_node; n->child[0] = next_free_node;
next_free_node = n; next_free_node = n;
@ -261,8 +259,7 @@ ipaddr32_t AnonymizeIPAddr_A50::make_output(ipaddr32_t old_output, int swivel) c
else else
{ {
// Bits up to swivel are unchanged; bit swivel is flipped. // Bits up to swivel are unchanged; bit swivel is flipped.
ipaddr32_t known_part = ipaddr32_t known_part = ((old_output >> (32 - swivel)) ^ 1) << (32 - swivel);
((old_output >> (32 - swivel)) ^ 1) << (32 - swivel);
// Remainder of bits are random. // Remainder of bits are random.
return known_part | ((rand32() & 0x7FFFFFFF) >> swivel); return known_part | ((rand32() & 0x7FFFFFFF) >> swivel);
@ -299,11 +296,11 @@ AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::make_peer(ipaddr32_t a, Node* n)
down[bitvalue]->output = make_output(n->output, swivel); down[bitvalue]->output = make_output(n->output, swivel);
down[bitvalue]->child[0] = down[bitvalue]->child[1] = nullptr; down[bitvalue]->child[0] = down[bitvalue]->child[1] = nullptr;
*down[1 - bitvalue] = *n; // copy orig node down one level *down[1 - bitvalue] = *n; // copy orig node down one level
n->input = down[1]->input; // NB: 1s to the right (0s to the left) n->input = down[1]->input; // NB: 1s to the right (0s to the left)
n->output = down[1]->output; n->output = down[1]->output;
n->child[0] = down[0]; // point to children n->child[0] = down[0]; // point to children
n->child[1] = down[1]; n->child[1] = down[1];
return down[bitvalue]; return down[bitvalue];
@ -340,8 +337,7 @@ AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::find_node(ipaddr32_t a)
{ {
// swivel is the first bit in which the two children // swivel is the first bit in which the two children
// differ. // differ.
int swivel = int swivel = bi_ffs(n->child[0]->input ^ n->child[1]->input);
bi_ffs(n->child[0]->input ^ n->child[1]->input);
if ( bi_ffs(a ^ n->input) < swivel ) if ( bi_ffs(a ^ n->input) < swivel )
// Input differs earlier. // Input differs earlier.
@ -394,22 +390,23 @@ ipaddr32_t anonymize_ip(ipaddr32_t ip, enum ip_addr_anonymization_class_t cl)
int method = -1; int method = -1;
switch ( cl ) { switch ( cl )
case ORIG_ADDR: // client address {
preserve_addr = anon_preserve_orig_addr.get(); case ORIG_ADDR: // client address
method = orig_addr_anonymization; preserve_addr = anon_preserve_orig_addr.get();
break; method = orig_addr_anonymization;
break;
case RESP_ADDR: // server address case RESP_ADDR: // server address
preserve_addr = anon_preserve_resp_addr.get(); preserve_addr = anon_preserve_resp_addr.get();
method = resp_addr_anonymization; method = resp_addr_anonymization;
break; break;
default: default:
preserve_addr = anon_preserve_other_addr.get(); preserve_addr = anon_preserve_other_addr.get();
method = other_addr_anonymization; method = other_addr_anonymization;
break; break;
} }
ipaddr32_t new_ip = 0; ipaddr32_t new_ip = 0;
@ -442,12 +439,10 @@ ipaddr32_t anonymize_ip(ipaddr32_t ip, enum ip_addr_anonymization_class_t cl)
void log_anonymization_mapping(ipaddr32_t input, ipaddr32_t output) void log_anonymization_mapping(ipaddr32_t input, ipaddr32_t output)
{ {
if ( anonymization_mapping ) if ( anonymization_mapping )
event_mgr.Enqueue(anonymization_mapping, event_mgr.Enqueue(anonymization_mapping, make_intrusive<AddrVal>(input),
make_intrusive<AddrVal>(input), make_intrusive<AddrVal>(output));
make_intrusive<AddrVal>(output)
);
} }
#endif #endif
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -10,36 +10,40 @@
#pragma once #pragma once
#include <vector>
#include <map>
#include <cstdint> #include <cstdint>
#include <map>
#include <vector>
namespace zeek::detail { namespace zeek::detail
{
// TODO: Anon.h may not be the right place to put these functions ... // TODO: Anon.h may not be the right place to put these functions ...
enum ip_addr_anonymization_class_t { enum ip_addr_anonymization_class_t
ORIG_ADDR, // client address {
RESP_ADDR, // server address ORIG_ADDR, // client address
RESP_ADDR, // server address
OTHER_ADDR, OTHER_ADDR,
NUM_ADDR_ANONYMIZATION_CLASSES, NUM_ADDR_ANONYMIZATION_CLASSES,
}; };
enum ip_addr_anonymization_method_t { enum ip_addr_anonymization_method_t
{
KEEP_ORIG_ADDR, KEEP_ORIG_ADDR,
SEQUENTIALLY_NUMBERED, SEQUENTIALLY_NUMBERED,
RANDOM_MD5, RANDOM_MD5,
PREFIX_PRESERVING_A50, PREFIX_PRESERVING_A50,
PREFIX_PRESERVING_MD5, PREFIX_PRESERVING_MD5,
NUM_ADDR_ANONYMIZATION_METHODS, NUM_ADDR_ANONYMIZATION_METHODS,
}; };
typedef uint32_t ipaddr32_t; typedef uint32_t ipaddr32_t;
// NOTE: all addresses in parameters of *public* functions are in // NOTE: all addresses in parameters of *public* functions are in
// network order. // network order.
class AnonymizeIPAddr { class AnonymizeIPAddr
{
public: public:
virtual ~AnonymizeIPAddr() = default; virtual ~AnonymizeIPAddr() = default;
@ -53,47 +57,53 @@ public:
protected: protected:
std::map<ipaddr32_t, ipaddr32_t> mapping; std::map<ipaddr32_t, ipaddr32_t> mapping;
}; };
class AnonymizeIPAddr_Seq : public AnonymizeIPAddr { class AnonymizeIPAddr_Seq : public AnonymizeIPAddr
{
public: public:
AnonymizeIPAddr_Seq() { seq = 1; } AnonymizeIPAddr_Seq() { seq = 1; }
ipaddr32_t anonymize(ipaddr32_t addr) override; ipaddr32_t anonymize(ipaddr32_t addr) override;
protected: protected:
ipaddr32_t seq; ipaddr32_t seq;
}; };
class AnonymizeIPAddr_RandomMD5 : public AnonymizeIPAddr { class AnonymizeIPAddr_RandomMD5 : public AnonymizeIPAddr
{
public: public:
ipaddr32_t anonymize(ipaddr32_t addr) override; ipaddr32_t anonymize(ipaddr32_t addr) override;
}; };
class AnonymizeIPAddr_PrefixMD5 : public AnonymizeIPAddr { class AnonymizeIPAddr_PrefixMD5 : public AnonymizeIPAddr
{
public: public:
ipaddr32_t anonymize(ipaddr32_t addr) override; ipaddr32_t anonymize(ipaddr32_t addr) override;
protected: protected:
struct anon_prefix { struct anon_prefix
{
int len; int len;
ipaddr32_t prefix; ipaddr32_t prefix;
} prefix; } prefix;
}; };
class AnonymizeIPAddr_A50 : public AnonymizeIPAddr { class AnonymizeIPAddr_A50 : public AnonymizeIPAddr
{
public: public:
AnonymizeIPAddr_A50() { init(); } AnonymizeIPAddr_A50() { init(); }
~AnonymizeIPAddr_A50() override; ~AnonymizeIPAddr_A50() override;
ipaddr32_t anonymize(ipaddr32_t addr) override; ipaddr32_t anonymize(ipaddr32_t addr) override;
bool PreservePrefix(ipaddr32_t input, int num_bits) override; bool PreservePrefix(ipaddr32_t input, int num_bits) override;
protected: protected:
struct Node { struct Node
{
ipaddr32_t input; ipaddr32_t input;
ipaddr32_t output; ipaddr32_t output;
Node* child[2]; Node* child[2];
}; };
int method; int method;
int before_anonymization; int before_anonymization;
@ -118,7 +128,7 @@ protected:
ipaddr32_t make_output(ipaddr32_t, int) const; ipaddr32_t make_output(ipaddr32_t, int) const;
Node* make_peer(ipaddr32_t, Node*); Node* make_peer(ipaddr32_t, Node*);
Node* find_node(ipaddr32_t); Node* find_node(ipaddr32_t);
}; };
// The global IP anonymizers. // The global IP anonymizers.
extern AnonymizeIPAddr* ip_anonymizer[NUM_ADDR_ANONYMIZATION_METHODS]; extern AnonymizeIPAddr* ip_anonymizer[NUM_ADDR_ANONYMIZATION_METHODS];
@ -129,4 +139,4 @@ ipaddr32_t anonymize_ip(ipaddr32_t ip, enum ip_addr_anonymization_class_t cl);
#define LOG_ANONYMIZATION_MAPPING #define LOG_ANONYMIZATION_MAPPING
void log_anonymization_mapping(ipaddr32_t input, ipaddr32_t output); void log_anonymization_mapping(ipaddr32_t input, ipaddr32_t output);
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,47 +1,61 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Attr.h" #include "zeek/Attr.h"
#include "zeek/Expr.h"
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/Val.h" #include "zeek/Expr.h"
#include "zeek/IntrusivePtr.h" #include "zeek/IntrusivePtr.h"
#include "zeek/Val.h"
#include "zeek/input/Manager.h" #include "zeek/input/Manager.h"
#include "zeek/threading/SerialTypes.h" #include "zeek/threading/SerialTypes.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
const char* attr_name(AttrTag t) const char* attr_name(AttrTag t)
{ {
static const char* attr_names[int(NUM_ATTRS)] = { static const char* attr_names[int(NUM_ATTRS)] = {
"&optional", "&default", "&redef", "&optional",
"&add_func", "&delete_func", "&expire_func", "&default",
"&read_expire", "&write_expire", "&create_expire", "&redef",
"&raw_output", "&priority", "&add_func",
"&group", "&log", "&error_handler", "&type_column", "&delete_func",
"(&tracked)", "&on_change", "&broker_store", "&expire_func",
"&broker_allow_complex_type", "&backend", "&deprecated", "&read_expire",
"&is_assigned", "&is_used", "&write_expire",
"&create_expire",
"&raw_output",
"&priority",
"&group",
"&log",
"&error_handler",
"&type_column",
"(&tracked)",
"&on_change",
"&broker_store",
"&broker_allow_complex_type",
"&backend",
"&deprecated",
"&is_assigned",
"&is_used",
}; };
return attr_names[int(t)]; return attr_names[int(t)];
} }
Attr::Attr(AttrTag t, ExprPtr e) Attr::Attr(AttrTag t, ExprPtr e) : expr(std::move(e))
: expr(std::move(e))
{ {
tag = t; tag = t;
SetLocationInfo(&start_location, &end_location); SetLocationInfo(&start_location, &end_location);
} }
Attr::Attr(AttrTag t) Attr::Attr(AttrTag t) : Attr(t, nullptr) { }
: Attr(t, nullptr)
{
}
void Attr::SetAttrExpr(ExprPtr e) void Attr::SetAttrExpr(ExprPtr e)
{ expr = std::move(e); } {
expr = std::move(e);
}
std::string Attr::DeprecationMessage() const std::string Attr::DeprecationMessage() const
{ {
@ -71,7 +85,7 @@ void Attr::Describe(ODesc* d) const
void Attr::DescribeReST(ODesc* d, bool shorten) const void Attr::DescribeReST(ODesc* d, bool shorten) const
{ {
auto add_long_expr_string = [](ODesc* d, const std::string& s, bool shorten) auto add_long_expr_string = [](ODesc* d, const std::string& s, bool shorten)
{ {
constexpr auto max_expr_chars = 32; constexpr auto max_expr_chars = 32;
constexpr auto shortened_expr = "*...*"; constexpr auto shortened_expr = "*...*";
@ -93,7 +107,7 @@ void Attr::DescribeReST(ODesc* d, bool shorten) const
d->Add(s); d->Add(s);
d->Add("``"); d->Add("``");
} }
}; };
d->Add(":zeek:attr:`"); d->Add(":zeek:attr:`");
AddTag(d); AddTag(d);
@ -152,12 +166,11 @@ void Attr::AddTag(ODesc* d) const
} }
Attributes::Attributes(TypePtr t, bool arg_in_record, bool is_global) Attributes::Attributes(TypePtr t, bool arg_in_record, bool is_global)
: Attributes(std::vector<AttrPtr>{}, std::move(t), : Attributes(std::vector<AttrPtr>{}, std::move(t), arg_in_record, is_global)
arg_in_record, is_global) {
{} }
Attributes::Attributes(std::vector<AttrPtr> a, Attributes::Attributes(std::vector<AttrPtr> a, TypePtr t, bool arg_in_record, bool is_global)
TypePtr t, bool arg_in_record, bool is_global)
: type(std::move(t)) : type(std::move(t))
{ {
attrs.reserve(a.size()); attrs.reserve(a.size());
@ -177,22 +190,22 @@ Attributes::Attributes(std::vector<AttrPtr> a,
void Attributes::AddAttr(AttrPtr attr, bool is_redef) void Attributes::AddAttr(AttrPtr attr, bool is_redef)
{ {
auto acceptable_duplicate_attr = [](const AttrPtr& attr, const AttrPtr& existing) -> bool auto acceptable_duplicate_attr = [](const AttrPtr& attr, const AttrPtr& existing) -> bool
{ {
AttrTag new_tag = attr->Tag(); AttrTag new_tag = attr->Tag();
if ( new_tag == ATTR_DEPRECATED ) if ( new_tag == ATTR_DEPRECATED )
{ {
if ( ! attr->DeprecationMessage().empty() || if ( ! attr->DeprecationMessage().empty() ||
( existing && ! existing->DeprecationMessage().empty() ) ) (existing && ! existing->DeprecationMessage().empty()) )
return false; return false;
return true; return true;
} }
return new_tag == ATTR_LOG || new_tag == ATTR_OPTIONAL || new_tag == ATTR_REDEF || return new_tag == ATTR_LOG || new_tag == ATTR_OPTIONAL || new_tag == ATTR_REDEF ||
new_tag == ATTR_BROKER_STORE_ALLOW_COMPLEX || new_tag == ATTR_RAW_OUTPUT || new_tag == ATTR_BROKER_STORE_ALLOW_COMPLEX || new_tag == ATTR_RAW_OUTPUT ||
new_tag == ATTR_ERROR_HANDLER; new_tag == ATTR_ERROR_HANDLER;
}; };
// A `redef` is allowed to overwrite an existing attribute instead of // A `redef` is allowed to overwrite an existing attribute instead of
// flagging it as ambiguous. // flagging it as ambiguous.
@ -216,16 +229,14 @@ void Attributes::AddAttr(AttrPtr attr, bool is_redef)
// For ADD_FUNC or DEL_FUNC, add in an implicit REDEF, since // For ADD_FUNC or DEL_FUNC, add in an implicit REDEF, since
// those attributes only have meaning for a redefinable value. // those attributes only have meaning for a redefinable value.
if ( (attr->Tag() == ATTR_ADD_FUNC || attr->Tag() == ATTR_DEL_FUNC) && if ( (attr->Tag() == ATTR_ADD_FUNC || attr->Tag() == ATTR_DEL_FUNC) && ! Find(ATTR_REDEF) )
! Find(ATTR_REDEF) )
{ {
auto a = make_intrusive<Attr>(ATTR_REDEF); auto a = make_intrusive<Attr>(ATTR_REDEF);
attrs.emplace_back(std::move(a)); attrs.emplace_back(std::move(a));
} }
// For DEFAULT, add an implicit OPTIONAL if it's not a global. // For DEFAULT, add an implicit OPTIONAL if it's not a global.
if ( ! global_var && attr->Tag() == ATTR_DEFAULT && if ( ! global_var && attr->Tag() == ATTR_DEFAULT && ! Find(ATTR_OPTIONAL) )
! Find(ATTR_OPTIONAL) )
{ {
auto a = make_intrusive<Attr>(ATTR_OPTIONAL); auto a = make_intrusive<Attr>(ATTR_OPTIONAL);
attrs.emplace_back(std::move(a)); attrs.emplace_back(std::move(a));
@ -290,425 +301,420 @@ void Attributes::DescribeReST(ODesc* d, bool shorten) const
void Attributes::CheckAttr(Attr* a) void Attributes::CheckAttr(Attr* a)
{ {
switch ( a->Tag() ) { switch ( a->Tag() )
case ATTR_DEPRECATED:
case ATTR_REDEF:
case ATTR_IS_ASSIGNED:
case ATTR_IS_USED:
break;
case ATTR_OPTIONAL:
if ( global_var )
Error("&optional is not valid for global variables");
break;
case ATTR_ADD_FUNC:
case ATTR_DEL_FUNC:
{ {
bool is_add = a->Tag() == ATTR_ADD_FUNC; case ATTR_DEPRECATED:
case ATTR_REDEF:
const auto& at = a->GetExpr()->GetType(); case ATTR_IS_ASSIGNED:
if ( at->Tag() != TYPE_FUNC ) case ATTR_IS_USED:
{
a->GetExpr()->Error(
is_add ?
"&add_func must be a function" :
"&delete_func must be a function");
break; break;
}
FuncType* aft = at->AsFuncType(); case ATTR_OPTIONAL:
if ( ! same_type(aft->Yield(), type) ) if ( global_var )
{ Error("&optional is not valid for global variables");
a->GetExpr()->Error(
is_add ?
"&add_func function must yield same type as variable" :
"&delete_func function must yield same type as variable");
break; break;
}
}
break;
case ATTR_DEFAULT: case ATTR_ADD_FUNC:
{ case ATTR_DEL_FUNC:
// &default is allowed for global tables, since it's used in initialization
// of table fields. it's not allowed otherwise.
if ( global_var && ! type->IsTable() )
{
Error("&default is not valid for global variables except for tables");
break;
}
const auto& atype = a->GetExpr()->GetType();
if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) )
{
if ( same_type(atype, type) )
// Ok.
break;
// Record defaults may be promotable.
if ( (type->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(),
type->AsRecordType())) )
// Ok.
break;
if ( type->Tag() == TYPE_TABLE &&
type->AsTableType()->IsUnspecifiedTable() )
// Ok.
break;
auto e = check_and_promote_expr(a->GetExpr(), type);
if ( e )
{ {
a->SetAttrExpr(std::move(e)); bool is_add = a->Tag() == ATTR_ADD_FUNC;
// Ok.
break;
}
a->GetExpr()->Error("&default value has inconsistent type", type.get()); const auto& at = a->GetExpr()->GetType();
return; if ( at->Tag() != TYPE_FUNC )
}
TableType* tt = type->AsTableType();
const auto& ytype = tt->Yield();
if ( ! in_record )
{
// &default applies to the type itself.
if ( ! same_type(atype, ytype) )
{
// It can still be a default function.
if ( atype->Tag() == TYPE_FUNC )
{ {
FuncType* f = atype->AsFuncType(); a->GetExpr()->Error(is_add ? "&add_func must be a function"
if ( ! f->CheckArgs(tt->GetIndexTypes()) || : "&delete_func must be a function");
! same_type(f->Yield(), ytype) ) break;
Error("&default function type clash"); }
FuncType* aft = at->AsFuncType();
if ( ! same_type(aft->Yield(), type) )
{
a->GetExpr()->Error(
is_add ? "&add_func function must yield same type as variable"
: "&delete_func function must yield same type as variable");
break;
}
}
break;
case ATTR_DEFAULT:
{
// &default is allowed for global tables, since it's used in initialization
// of table fields. it's not allowed otherwise.
if ( global_var && ! type->IsTable() )
{
Error("&default is not valid for global variables except for tables");
break;
}
const auto& atype = a->GetExpr()->GetType();
if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) )
{
if ( same_type(atype, type) )
// Ok.
break;
// Record defaults may be promotable.
if ( (type->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(),
type->AsRecordType())) )
// Ok.
break;
if ( type->Tag() == TYPE_TABLE && type->AsTableType()->IsUnspecifiedTable() )
// Ok.
break;
auto e = check_and_promote_expr(a->GetExpr(), type);
if ( e )
{
a->SetAttrExpr(std::move(e));
// Ok.
break;
}
a->GetExpr()->Error("&default value has inconsistent type", type.get());
return;
}
TableType* tt = type->AsTableType();
const auto& ytype = tt->Yield();
if ( ! in_record )
{
// &default applies to the type itself.
if ( ! same_type(atype, ytype) )
{
// It can still be a default function.
if ( atype->Tag() == TYPE_FUNC )
{
FuncType* f = atype->AsFuncType();
if ( ! f->CheckArgs(tt->GetIndexTypes()) ||
! same_type(f->Yield(), ytype) )
Error("&default function type clash");
// Ok.
break;
}
// Table defaults may be promotable.
if ( (ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(),
ytype->AsRecordType())) )
// Ok.
break;
auto e = check_and_promote_expr(a->GetExpr(), ytype);
if ( e )
{
a->SetAttrExpr(std::move(e));
// Ok.
break;
}
Error("&default value has inconsistent type 2");
}
// Ok. // Ok.
break; break;
} }
// Table defaults may be promotable. else
if ( (ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(),
ytype->AsRecordType())) )
// Ok.
break;
auto e = check_and_promote_expr(a->GetExpr(), ytype);
if ( e )
{ {
a->SetAttrExpr(std::move(e)); // &default applies to record field.
// Ok.
break; if ( same_type(atype, type) )
// Ok.
break;
if ( (atype->Tag() == TYPE_TABLE &&
atype->AsTableType()->IsUnspecifiedTable()) )
{
auto e = check_and_promote_expr(a->GetExpr(), type);
if ( e )
{
a->SetAttrExpr(std::move(e));
break;
}
}
// Table defaults may be promotable.
if ( ytype && ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType()) )
// Ok.
break;
Error("&default value has inconsistent type");
} }
Error("&default value has inconsistent type 2");
} }
// Ok.
break; break;
}
else case ATTR_EXPIRE_READ:
{
// &default applies to record field.
if ( same_type(atype, type) )
// Ok.
break;
if ( (atype->Tag() == TYPE_TABLE && atype->AsTableType()->IsUnspecifiedTable()) )
{ {
auto e = check_and_promote_expr(a->GetExpr(), type); if ( Find(ATTR_BROKER_STORE) )
Error("&broker_store and &read_expire cannot be used simultaneously");
if ( e ) if ( Find(ATTR_BACKEND) )
Error("&backend and &read_expire cannot be used simultaneously");
}
// fallthrough
case ATTR_EXPIRE_WRITE:
case ATTR_EXPIRE_CREATE:
{
if ( type->Tag() != TYPE_TABLE )
{ {
a->SetAttrExpr(std::move(e)); Error("expiration only applicable to sets/tables");
break;
}
int num_expires = 0;
for ( const auto& a : attrs )
{
if ( a->Tag() == ATTR_EXPIRE_READ || a->Tag() == ATTR_EXPIRE_WRITE ||
a->Tag() == ATTR_EXPIRE_CREATE )
num_expires++;
}
if ( num_expires > 1 )
{
Error("set/table can only have one of &read_expire, &write_expire, "
"&create_expire");
break; break;
} }
} }
// Table defaults may be promotable.
if ( ytype && ytype->Tag() == TYPE_RECORD &&
atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType()) )
// Ok.
break;
Error("&default value has inconsistent type");
}
}
break;
case ATTR_EXPIRE_READ:
{
if ( Find(ATTR_BROKER_STORE) )
Error("&broker_store and &read_expire cannot be used simultaneously");
if ( Find(ATTR_BACKEND) )
Error("&backend and &read_expire cannot be used simultaneously");
}
// fallthrough
case ATTR_EXPIRE_WRITE:
case ATTR_EXPIRE_CREATE:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("expiration only applicable to sets/tables");
break;
}
int num_expires = 0;
for ( const auto& a : attrs )
{
if ( a->Tag() == ATTR_EXPIRE_READ ||
a->Tag() == ATTR_EXPIRE_WRITE ||
a->Tag() == ATTR_EXPIRE_CREATE )
num_expires++;
}
if ( num_expires > 1 )
{
Error("set/table can only have one of &read_expire, &write_expire, &create_expire");
break;
}
}
#if 0 #if 0
//### not easy to test this w/o knowing the ID. //### not easy to test this w/o knowing the ID.
if ( ! global_var ) if ( ! global_var )
Error("expiration not supported for local variables"); Error("expiration not supported for local variables");
#endif #endif
break;
case ATTR_EXPIRE_FUNC:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("expiration only applicable to tables");
break;
}
type->AsTableType()->CheckExpireFuncCompatibility({NewRef{}, a});
if ( Find(ATTR_BROKER_STORE ) )
Error("&broker_store and &expire_func cannot be used simultaneously");
if ( Find(ATTR_BACKEND ) )
Error("&backend and &expire_func cannot be used simultaneously");
break;
}
case ATTR_ON_CHANGE:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("&on_change only applicable to sets/tables");
break;
}
const auto& change_func = a->GetExpr();
if ( change_func->GetType()->Tag() != TYPE_FUNC || change_func->GetType()->AsFuncType()->Flavor() != FUNC_FLAVOR_FUNCTION )
Error("&on_change attribute is not a function");
const FuncType* c_ft = change_func->GetType()->AsFuncType();
if ( c_ft->Yield()->Tag() != TYPE_VOID )
{
Error("&on_change must not return a value");
break;
}
const TableType* the_table = type->AsTableType();
if ( the_table->IsUnspecifiedTable() )
break; break;
const auto& args = c_ft->ParamList()->GetTypes(); case ATTR_EXPIRE_FUNC:
const auto& t_indexes = the_table->GetIndexTypes();
if ( args.size() != ( type->IsSet() ? 2 : 3 ) + t_indexes.size() )
{
Error("&on_change function has incorrect number of arguments");
break;
}
if ( ! same_type(args[0], the_table->AsTableType()) )
{
Error("&on_change: first argument must be of same type as table");
break;
}
// can't check exact type here yet - the data structures don't exist yet.
if ( args[1]->Tag() != TYPE_ENUM )
{
Error("&on_change: second argument must be a TableChange enum");
break;
}
for ( size_t i = 0; i < t_indexes.size(); i++ )
{
if ( ! same_type(args[2+i], t_indexes[i]) )
{ {
Error("&on_change: index types do not match table"); if ( type->Tag() != TYPE_TABLE )
{
Error("expiration only applicable to tables");
break;
}
type->AsTableType()->CheckExpireFuncCompatibility({NewRef{}, a});
if ( Find(ATTR_BROKER_STORE) )
Error("&broker_store and &expire_func cannot be used simultaneously");
if ( Find(ATTR_BACKEND) )
Error("&backend and &expire_func cannot be used simultaneously");
break; break;
} }
}
if ( ! type->IsSet() ) case ATTR_ON_CHANGE:
if ( ! same_type(args[2+t_indexes.size()], the_table->Yield()) )
{ {
Error("&on_change: value type does not match table"); if ( type->Tag() != TYPE_TABLE )
{
Error("&on_change only applicable to sets/tables");
break;
}
const auto& change_func = a->GetExpr();
if ( change_func->GetType()->Tag() != TYPE_FUNC ||
change_func->GetType()->AsFuncType()->Flavor() != FUNC_FLAVOR_FUNCTION )
Error("&on_change attribute is not a function");
const FuncType* c_ft = change_func->GetType()->AsFuncType();
if ( c_ft->Yield()->Tag() != TYPE_VOID )
{
Error("&on_change must not return a value");
break;
}
const TableType* the_table = type->AsTableType();
if ( the_table->IsUnspecifiedTable() )
break;
const auto& args = c_ft->ParamList()->GetTypes();
const auto& t_indexes = the_table->GetIndexTypes();
if ( args.size() != (type->IsSet() ? 2 : 3) + t_indexes.size() )
{
Error("&on_change function has incorrect number of arguments");
break;
}
if ( ! same_type(args[0], the_table->AsTableType()) )
{
Error("&on_change: first argument must be of same type as table");
break;
}
// can't check exact type here yet - the data structures don't exist yet.
if ( args[1]->Tag() != TYPE_ENUM )
{
Error("&on_change: second argument must be a TableChange enum");
break;
}
for ( size_t i = 0; i < t_indexes.size(); i++ )
{
if ( ! same_type(args[2 + i], t_indexes[i]) )
{
Error("&on_change: index types do not match table");
break;
}
}
if ( ! type->IsSet() )
if ( ! same_type(args[2 + t_indexes.size()], the_table->Yield()) )
{
Error("&on_change: value type does not match table");
break;
}
}
break;
case ATTR_BACKEND:
{
if ( ! global_var || type->Tag() != TYPE_TABLE )
{
Error("&backend only applicable to global sets/tables");
break;
}
// cannot do better equality check - the Broker types are not
// actually existing yet when we are here. We will do that
// later - before actually attaching to a broker store
if ( a->GetExpr()->GetType()->Tag() != TYPE_ENUM )
{
Error("&backend must take an enum argument");
break;
}
// Only support atomic types for the moment, unless
// explicitly overriden
if ( ! type->AsTableType()->IsSet() &&
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
{
Error("&backend only supports atomic types as table value");
}
if ( Find(ATTR_EXPIRE_FUNC) )
Error("&backend and &expire_func cannot be used simultaneously");
if ( Find(ATTR_EXPIRE_READ) )
Error("&backend and &read_expire cannot be used simultaneously");
if ( Find(ATTR_BROKER_STORE) )
Error("&backend and &broker_store cannot be used simultaneously");
break; break;
} }
case ATTR_BROKER_STORE:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("&broker_store only applicable to sets/tables");
break;
}
if ( a->GetExpr()->GetType()->Tag() != TYPE_STRING )
{
Error("&broker_store must take a string argument");
break;
}
// Only support atomic types for the moment, unless
// explicitly overriden
if ( ! type->AsTableType()->IsSet() &&
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
{
Error("&broker_store only supports atomic types as table value");
}
if ( Find(ATTR_EXPIRE_FUNC) )
Error("&broker_store and &expire_func cannot be used simultaneously");
if ( Find(ATTR_EXPIRE_READ) )
Error("&broker_store and &read_expire cannot be used simultaneously");
if ( Find(ATTR_BACKEND) )
Error("&backend and &broker_store cannot be used simultaneously");
break;
}
case ATTR_BROKER_STORE_ALLOW_COMPLEX:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("&broker_allow_complex_type only applicable to sets/tables");
break;
}
}
case ATTR_TRACKED:
// FIXME: Check here for global ID?
break;
case ATTR_RAW_OUTPUT:
if ( type->Tag() != TYPE_FILE )
Error("&raw_output only applicable to files");
break;
case ATTR_PRIORITY:
Error("&priority only applicable to event bodies");
break;
case ATTR_GROUP:
if ( type->Tag() != TYPE_FUNC || type->AsFuncType()->Flavor() != FUNC_FLAVOR_EVENT )
Error("&group only applicable to events");
break;
case ATTR_ERROR_HANDLER:
if ( type->Tag() != TYPE_FUNC || type->AsFuncType()->Flavor() != FUNC_FLAVOR_EVENT )
Error("&error_handler only applicable to events");
break;
case ATTR_LOG:
if ( ! threading::Value::IsCompatibleType(type.get()) )
Error("&log applied to a type that cannot be logged");
break;
case ATTR_TYPE_COLUMN:
{
if ( type->Tag() != TYPE_PORT )
{
Error("type_column tag only applicable to ports");
break;
}
const auto& atype = a->GetExpr()->GetType();
if ( atype->Tag() != TYPE_STRING )
{
Error("type column needs to have a string argument");
break;
}
break;
}
default:
BadTag("Attributes::CheckAttr", attr_name(a->Tag()));
} }
break;
case ATTR_BACKEND:
{
if ( ! global_var || type->Tag() != TYPE_TABLE )
{
Error("&backend only applicable to global sets/tables");
break;
}
// cannot do better equality check - the Broker types are not
// actually existing yet when we are here. We will do that
// later - before actually attaching to a broker store
if ( a->GetExpr()->GetType()->Tag() != TYPE_ENUM )
{
Error("&backend must take an enum argument");
break;
}
// Only support atomic types for the moment, unless
// explicitly overriden
if ( ! type->AsTableType()->IsSet() &&
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
{
Error("&backend only supports atomic types as table value");
}
if ( Find(ATTR_EXPIRE_FUNC ) )
Error("&backend and &expire_func cannot be used simultaneously");
if ( Find(ATTR_EXPIRE_READ) )
Error("&backend and &read_expire cannot be used simultaneously");
if ( Find(ATTR_BROKER_STORE) )
Error("&backend and &broker_store cannot be used simultaneously");
break;
}
case ATTR_BROKER_STORE:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("&broker_store only applicable to sets/tables");
break;
}
if ( a->GetExpr()->GetType()->Tag() != TYPE_STRING )
{
Error("&broker_store must take a string argument");
break;
}
// Only support atomic types for the moment, unless
// explicitly overriden
if ( ! type->AsTableType()->IsSet() &&
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
{
Error("&broker_store only supports atomic types as table value");
}
if ( Find(ATTR_EXPIRE_FUNC ) )
Error("&broker_store and &expire_func cannot be used simultaneously");
if ( Find(ATTR_EXPIRE_READ) )
Error("&broker_store and &read_expire cannot be used simultaneously");
if ( Find(ATTR_BACKEND) )
Error("&backend and &broker_store cannot be used simultaneously");
break;
}
case ATTR_BROKER_STORE_ALLOW_COMPLEX:
{
if ( type->Tag() != TYPE_TABLE )
{
Error("&broker_allow_complex_type only applicable to sets/tables");
break;
}
}
case ATTR_TRACKED:
// FIXME: Check here for global ID?
break;
case ATTR_RAW_OUTPUT:
if ( type->Tag() != TYPE_FILE )
Error("&raw_output only applicable to files");
break;
case ATTR_PRIORITY:
Error("&priority only applicable to event bodies");
break;
case ATTR_GROUP:
if ( type->Tag() != TYPE_FUNC ||
type->AsFuncType()->Flavor() != FUNC_FLAVOR_EVENT )
Error("&group only applicable to events");
break;
case ATTR_ERROR_HANDLER:
if ( type->Tag() != TYPE_FUNC ||
type->AsFuncType()->Flavor() != FUNC_FLAVOR_EVENT )
Error("&error_handler only applicable to events");
break;
case ATTR_LOG:
if ( ! threading::Value::IsCompatibleType(type.get()) )
Error("&log applied to a type that cannot be logged");
break;
case ATTR_TYPE_COLUMN:
{
if ( type->Tag() != TYPE_PORT )
{
Error("type_column tag only applicable to ports");
break;
}
const auto& atype = a->GetExpr()->GetType();
if ( atype->Tag() != TYPE_STRING ) {
Error("type column needs to have a string argument");
break;
}
break;
}
default:
BadTag("Attributes::CheckAttr", attr_name(a->Tag()));
}
} }
bool Attributes::operator==(const Attributes& other) const bool Attributes::operator==(const Attributes& other) const
@ -744,4 +750,4 @@ bool Attributes::operator==(const Attributes& other) const
return true; return true;
} }
} }

View file

@ -2,28 +2,31 @@
#pragma once #pragma once
#include <vector>
#include <string> #include <string>
#include <vector>
#include "zeek/IntrusivePtr.h"
#include "zeek/Obj.h" #include "zeek/Obj.h"
#include "zeek/ZeekList.h" #include "zeek/ZeekList.h"
#include "zeek/IntrusivePtr.h"
// Note that there are two kinds of attributes: the kind (here) which // Note that there are two kinds of attributes: the kind (here) which
// modify expressions or supply metadata on types, and the kind that // modify expressions or supply metadata on types, and the kind that
// are extra metadata on every variable instance. // are extra metadata on every variable instance.
namespace zeek { namespace zeek
{
class Type; class Type;
using TypePtr = IntrusivePtr<Type>; using TypePtr = IntrusivePtr<Type>;
namespace detail { namespace detail
{
class Expr; class Expr;
using ExprPtr = IntrusivePtr<Expr>; using ExprPtr = IntrusivePtr<Expr>;
enum AttrTag { enum AttrTag
{
ATTR_OPTIONAL, ATTR_OPTIONAL,
ATTR_DEFAULT, ATTR_DEFAULT,
ATTR_REDEF, ATTR_REDEF,
@ -38,8 +41,8 @@ enum AttrTag {
ATTR_GROUP, ATTR_GROUP,
ATTR_LOG, ATTR_LOG,
ATTR_ERROR_HANDLER, ATTR_ERROR_HANDLER,
ATTR_TYPE_COLUMN, // for input framework ATTR_TYPE_COLUMN, // for input framework
ATTR_TRACKED, // hidden attribute, tracked by NotifierRegistry ATTR_TRACKED, // hidden attribute, tracked by NotifierRegistry
ATTR_ON_CHANGE, // for table change tracking ATTR_ON_CHANGE, // for table change tracking
ATTR_BROKER_STORE, // for Broker store backed tables ATTR_BROKER_STORE, // for Broker store backed tables
ATTR_BROKER_STORE_ALLOW_COMPLEX, // for Broker store backed tables ATTR_BROKER_STORE_ALLOW_COMPLEX, // for Broker store backed tables
@ -48,14 +51,15 @@ enum AttrTag {
ATTR_IS_ASSIGNED, // to suppress usage warnings ATTR_IS_ASSIGNED, // to suppress usage warnings
ATTR_IS_USED, // to suppress usage warnings ATTR_IS_USED, // to suppress usage warnings
NUM_ATTRS // this item should always be last NUM_ATTRS // this item should always be last
}; };
class Attr; class Attr;
using AttrPtr = IntrusivePtr<Attr>; using AttrPtr = IntrusivePtr<Attr>;
class Attributes; class Attributes;
using AttributesPtr = IntrusivePtr<Attributes>; using AttributesPtr = IntrusivePtr<Attributes>;
class Attr final : public Obj { class Attr final : public Obj
{
public: public:
static inline const AttrPtr nil; static inline const AttrPtr nil;
@ -64,10 +68,9 @@ public:
~Attr() override = default; ~Attr() override = default;
AttrTag Tag() const { return tag; } AttrTag Tag() const { return tag; }
const ExprPtr& GetExpr() const const ExprPtr& GetExpr() const { return expr; }
{ return expr; }
void SetAttrExpr(ExprPtr e); void SetAttrExpr(ExprPtr e);
@ -100,13 +103,13 @@ protected:
AttrTag tag; AttrTag tag;
ExprPtr expr; ExprPtr expr;
}; };
// Manages a collection of attributes. // Manages a collection of attributes.
class Attributes final : public Obj { class Attributes final : public Obj
{
public: public:
Attributes(std::vector<AttrPtr> a, TypePtr t, Attributes(std::vector<AttrPtr> a, TypePtr t, bool in_record, bool is_global);
bool in_record, bool is_global);
Attributes(TypePtr t, bool in_record, bool is_global); Attributes(TypePtr t, bool in_record, bool is_global);
~Attributes() override = default; ~Attributes() override = default;
@ -122,8 +125,7 @@ public:
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
void DescribeReST(ODesc* d, bool shorten = false) const; void DescribeReST(ODesc* d, bool shorten = false) const;
const std::vector<AttrPtr>& GetAttrs() const const std::vector<AttrPtr>& GetAttrs() const { return attrs; }
{ return attrs; }
bool operator==(const Attributes& other) const; bool operator==(const Attributes& other) const;
@ -135,7 +137,7 @@ protected:
bool in_record; bool in_record;
bool global_var; bool global_var;
}; };
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,21 +1,23 @@
#include "zeek/zeek-config.h" #include "zeek/Base64.h"
#include <math.h> #include <math.h>
#include "zeek/Base64.h"
#include "zeek/ZeekString.h"
#include "zeek/Reporter.h"
#include "zeek/Conn.h" #include "zeek/Conn.h"
#include "zeek/Reporter.h"
#include "zeek/ZeekString.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
int Base64Converter::default_base64_table[256]; int Base64Converter::default_base64_table[256];
const std::string Base64Converter::default_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const std::string Base64Converter::default_alphabet =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void Base64Converter::Encode(int len, const unsigned char* data, int* pblen, char** pbuf) void Base64Converter::Encode(int len, const unsigned char* data, int* pblen, char** pbuf)
{ {
int blen; int blen;
char *buf; char* buf;
if ( ! pbuf ) if ( ! pbuf )
reporter->InternalError("nil pointer to encoding result buffer"); reporter->InternalError("nil pointer to encoding result buffer");
@ -35,20 +37,19 @@ void Base64Converter::Encode(int len, const unsigned char* data, int* pblen, cha
*pblen = blen; *pblen = blen;
} }
for ( int i = 0, j = 0; (i < len) && ( j < blen ); ) for ( int i = 0, j = 0; (i < len) && (j < blen); )
{ {
uint32_t bit32 = data[i++] << 16; uint32_t bit32 = data[i++] << 16;
bit32 += (i++ < len ? data[i-1] : 0) << 8; bit32 += (i++ < len ? data[i - 1] : 0) << 8;
bit32 += i++ < len ? data[i-1] : 0; bit32 += i++ < len ? data[i - 1] : 0;
buf[j++] = alphabet[(bit32 >> 18) & 0x3f]; buf[j++] = alphabet[(bit32 >> 18) & 0x3f];
buf[j++] = alphabet[(bit32 >> 12) & 0x3f]; buf[j++] = alphabet[(bit32 >> 12) & 0x3f];
buf[j++] = (i == (len+2)) ? '=' : alphabet[(bit32 >> 6) & 0x3f]; buf[j++] = (i == (len + 2)) ? '=' : alphabet[(bit32 >> 6) & 0x3f];
buf[j++] = (i >= (len+1)) ? '=' : alphabet[bit32 & 0x3f]; buf[j++] = (i >= (len + 1)) ? '=' : alphabet[bit32 & 0x3f];
} }
} }
int* Base64Converter::InitBase64Table(const std::string& alphabet) int* Base64Converter::InitBase64Table(const std::string& alphabet)
{ {
assert(alphabet.size() == 64); assert(alphabet.size() == 64);
@ -111,7 +112,7 @@ Base64Converter::Base64Converter(Connection* arg_conn, const std::string& arg_al
Base64Converter::~Base64Converter() Base64Converter::~Base64Converter()
{ {
if ( base64_table != default_base64_table ) if ( base64_table != default_base64_table )
delete [] base64_table; delete[] base64_table;
} }
int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf) int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
@ -160,11 +161,8 @@ int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
if ( buf + num_octets > *pbuf + blen ) if ( buf + num_octets > *pbuf + blen )
break; break;
uint32_t bit32 = uint32_t bit32 = ((base64_group[0] & 0x3f) << 18) | ((base64_group[1] & 0x3f) << 12) |
((base64_group[0] & 0x3f) << 18) | ((base64_group[2] & 0x3f) << 6) | ((base64_group[3] & 0x3f));
((base64_group[1] & 0x3f) << 12) |
((base64_group[2] & 0x3f) << 6) |
((base64_group[3] & 0x3f));
if ( --num_octets >= 0 ) if ( --num_octets >= 0 )
*buf++ = char((bit32 >> 16) & 0xff); *buf++ = char((bit32 >> 16) & 0xff);
@ -173,7 +171,7 @@ int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
*buf++ = char((bit32 >> 8) & 0xff); *buf++ = char((bit32 >> 8) & 0xff);
if ( --num_octets >= 0 ) if ( --num_octets >= 0 )
*buf++ = char((bit32) & 0xff); *buf++ = char((bit32)&0xff);
if ( base64_padding > 0 ) if ( base64_padding > 0 )
base64_after_padding = 1; base64_after_padding = 1;
@ -188,13 +186,14 @@ int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
if ( data[dlen] == '=' ) if ( data[dlen] == '=' )
++base64_padding; ++base64_padding;
int k = base64_table[(unsigned char) data[dlen]]; int k = base64_table[(unsigned char)data[dlen]];
if ( k >= 0 ) if ( k >= 0 )
base64_group[base64_group_next++] = k; base64_group[base64_group_next++] = k;
else else
{ {
if ( ++errored == 1 ) if ( ++errored == 1 )
IllegalEncoding(util::fmt("character %d ignored by Base64 decoding", (int) (data[dlen]))); IllegalEncoding(
util::fmt("character %d ignored by Base64 decoding", (int)(data[dlen])));
} }
++dlen; ++dlen;
@ -212,7 +211,7 @@ int Base64Converter::Done(int* pblen, char** pbuf)
{ {
if ( base64_group_next < 4 ) if ( base64_group_next < 4 )
IllegalEncoding(util::fmt("incomplete base64 group, padding with %d bits of 0", IllegalEncoding(util::fmt("incomplete base64 group, padding with %d bits of 0",
(4-base64_group_next) * 6)); (4 - base64_group_next) * 6));
Decode(4 - base64_group_next, padding, pblen, pbuf); Decode(4 - base64_group_next, padding, pblen, pbuf);
return -1; return -1;
} }
@ -224,29 +223,28 @@ int Base64Converter::Done(int* pblen, char** pbuf)
} }
void Base64Converter::IllegalEncoding(const char* msg) void Base64Converter::IllegalEncoding(const char* msg)
{ {
// strncpy(error_msg, msg, sizeof(error_msg)); // strncpy(error_msg, msg, sizeof(error_msg));
if ( conn ) if ( conn )
conn->Weird("base64_illegal_encoding", msg); conn->Weird("base64_illegal_encoding", msg);
else else
reporter->Error("%s", msg); reporter->Error("%s", msg);
} }
String* decode_base64(const String* s, const String* a, Connection* conn) String* decode_base64(const String* s, const String* a, Connection* conn)
{ {
if ( a && a->Len() != 0 && a->Len() != 64 ) if ( a && a->Len() != 0 && a->Len() != 64 )
{ {
reporter->Error("base64 decoding alphabet is not 64 characters: %s", reporter->Error("base64 decoding alphabet is not 64 characters: %s", a->CheckString());
a->CheckString());
return nullptr; return nullptr;
} }
int buf_len = int((s->Len() + 3) / 4) * 3 + 1; int buf_len = int((s->Len() + 3) / 4) * 3 + 1;
int rlen2, rlen = buf_len; int rlen2, rlen = buf_len;
char* rbuf2, *rbuf = new char[rlen]; char *rbuf2, *rbuf = new char[rlen];
Base64Converter dec(conn, a ? a->CheckString() : ""); Base64Converter dec(conn, a ? a->CheckString() : "");
dec.Decode(s->Len(), (const char*) s->Bytes(), &rlen, &rbuf); dec.Decode(s->Len(), (const char*)s->Bytes(), &rlen, &rbuf);
if ( dec.Errored() ) if ( dec.Errored() )
goto err; goto err;
@ -259,10 +257,10 @@ String* decode_base64(const String* s, const String* a, Connection* conn)
rlen += rlen2; rlen += rlen2;
rbuf[rlen] = '\0'; rbuf[rlen] = '\0';
return new String(true, (u_char*) rbuf, rlen); return new String(true, (u_char*)rbuf, rlen);
err: err:
delete [] rbuf; delete[] rbuf;
return nullptr; return nullptr;
} }
@ -270,17 +268,16 @@ String* encode_base64(const String* s, const String* a, Connection* conn)
{ {
if ( a && a->Len() != 0 && a->Len() != 64 ) if ( a && a->Len() != 0 && a->Len() != 64 )
{ {
reporter->Error("base64 alphabet is not 64 characters: %s", reporter->Error("base64 alphabet is not 64 characters: %s", a->CheckString());
a->CheckString());
return nullptr; return nullptr;
} }
char* outbuf = nullptr; char* outbuf = nullptr;
int outlen = 0; int outlen = 0;
Base64Converter enc(conn, a ? a->CheckString() : ""); Base64Converter enc(conn, a ? a->CheckString() : "");
enc.Encode(s->Len(), (const unsigned char*) s->Bytes(), &outlen, &outbuf); enc.Encode(s->Len(), (const unsigned char*)s->Bytes(), &outlen, &outbuf);
return new String(true, (u_char*)outbuf, outlen); return new String(true, (u_char*)outbuf, outlen);
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,17 +1,21 @@
#pragma once #pragma once
#include "zeek/zeek-config.h"
#include <string> #include <string>
namespace zeek { #include "zeek/zeek-config.h"
namespace zeek
{
class String; class String;
class Connection; class Connection;
namespace detail { namespace detail
{
// Maybe we should have a base class for generic decoders? // Maybe we should have a base class for generic decoders?
class Base64Converter { class Base64Converter
{
public: public:
// <conn> is used for error reporting. If it is set to zero (as, // <conn> is used for error reporting. If it is set to zero (as,
// e.g., done by the built-in functions decode_base64() and // e.g., done by the built-in functions decode_base64() and
@ -38,9 +42,9 @@ public:
bool HasData() const { return base64_group_next != 0; } bool HasData() const { return base64_group_next != 0; }
// True if an error has occurred. // True if an error has occurred.
int Errored() const { return errored; } int Errored() const { return errored; }
const char* ErrorMsg() const { return error_msg; } const char* ErrorMsg() const { return error_msg; }
void IllegalEncoding(const char* msg); void IllegalEncoding(const char* msg);
protected: protected:
@ -57,13 +61,12 @@ protected:
int base64_padding; int base64_padding;
int base64_after_padding; int base64_after_padding;
int* base64_table; int* base64_table;
int errored; // if true, we encountered an error - skip further processing int errored; // if true, we encountered an error - skip further processing
Connection* conn; Connection* conn;
};
};
String* decode_base64(const String* s, const String* a = nullptr, Connection* conn = nullptr); String* decode_base64(const String* s, const String* a = nullptr, Connection* conn = nullptr);
String* encode_base64(const String* s, const String* a = nullptr, Connection* conn = nullptr); String* encode_base64(const String* s, const String* a = nullptr, Connection* conn = nullptr);
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,11 +1,12 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/BifReturnVal.h" #include "zeek/BifReturnVal.h"
#include "zeek/Val.h" #include "zeek/Val.h"
namespace zeek::detail { namespace zeek::detail
{
BifReturnVal::BifReturnVal(std::nullptr_t) noexcept BifReturnVal::BifReturnVal(std::nullptr_t) noexcept { }
{}
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,33 +2,34 @@
#pragma once #pragma once
#include "zeek/zeek-config.h"
#include "zeek/IntrusivePtr.h" #include "zeek/IntrusivePtr.h"
#include "zeek/zeek-config.h"
namespace zeek { namespace zeek
{
class Val; class Val;
using ValPtr = IntrusivePtr<Val>; using ValPtr = IntrusivePtr<Val>;
namespace detail { namespace detail
{
/** /**
* A simple wrapper class to use for the return value of BIFs so that * A simple wrapper class to use for the return value of BIFs so that
* they may return either a Val* or IntrusivePtr<Val> (the former could * they may return either a Val* or IntrusivePtr<Val> (the former could
* potentially be deprecated). * potentially be deprecated).
*/ */
class BifReturnVal { class BifReturnVal
{
public: public:
template <typename T> BifReturnVal(IntrusivePtr<T> v) noexcept : rval(AdoptRef{}, v.release())
template <typename T> {
BifReturnVal(IntrusivePtr<T> v) noexcept }
: rval(AdoptRef{}, v.release())
{ }
BifReturnVal(std::nullptr_t) noexcept; BifReturnVal(std::nullptr_t) noexcept;
ValPtr rval; ValPtr rval;
}; };
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,14 +1,15 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/CCL.h" #include "zeek/CCL.h"
#include <algorithm> #include <algorithm>
#include "zeek/RE.h"
#include "zeek/DFA.h" #include "zeek/DFA.h"
#include "zeek/RE.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
CCL::CCL() CCL::CCL()
{ {
@ -48,7 +49,8 @@ void CCL::Sort()
unsigned int CCL::MemoryAllocation() const unsigned int CCL::MemoryAllocation() const
{ {
return padded_sizeof(*this) + padded_sizeof(*syms) + util::pad_size(syms->size() * sizeof(int_list::value_type)); return padded_sizeof(*this) + padded_sizeof(*syms) +
util::pad_size(syms->size() * sizeof(int_list::value_type));
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -5,34 +5,40 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
namespace zeek::detail { namespace zeek::detail
{
using int_list = std::vector<std::intptr_t>; using int_list = std::vector<std::intptr_t>;
class CCL { class CCL
{
public: public:
CCL(); CCL();
~CCL(); ~CCL();
void Add(int sym); void Add(int sym);
void Negate(); void Negate();
bool IsNegated() { return negated != 0; } bool IsNegated() { return negated != 0; }
int Index() { return index; } int Index() { return index; }
void Sort(); void Sort();
int_list* Syms() { return syms; } int_list* Syms() { return syms; }
void ReplaceSyms(int_list* new_syms) void ReplaceSyms(int_list* new_syms)
{ delete syms; syms = new_syms; } {
delete syms;
syms = new_syms;
}
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const; "GHI-572.")]] unsigned int
MemoryAllocation() const;
protected: protected:
int_list* syms; int_list* syms;
int negated; int negated;
int index; int index;
}; };
} // namespace zeek::detail } // namespace zeek::detail

File diff suppressed because it is too large Load diff

View file

@ -4,21 +4,24 @@
#include <memory> #include <memory>
#include "zeek/Type.h"
#include "zeek/IntrusivePtr.h" #include "zeek/IntrusivePtr.h"
#include "zeek/Type.h"
namespace zeek { namespace zeek
{
class ListVal; class ListVal;
using ListValPtr = zeek::IntrusivePtr<ListVal>; using ListValPtr = zeek::IntrusivePtr<ListVal>;
} // namespace zeek } // namespace zeek
namespace zeek::detail { namespace zeek::detail
{
class HashKey; class HashKey;
class CompositeHash { class CompositeHash
{
public: public:
explicit CompositeHash(TypeListPtr composite_type); explicit CompositeHash(TypeListPtr composite_type);
~CompositeHash(); ~CompositeHash();
@ -30,24 +33,26 @@ public:
// Given a hash key, recover the values used to create it. // Given a hash key, recover the values used to create it.
ListValPtr RecoverVals(const HashKey& k) const; ListValPtr RecoverVals(const HashKey& k) const;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const { return padded_sizeof(*this) + util::pad_size(size); } "GHI-572.")]] unsigned int
MemoryAllocation() const
{
return padded_sizeof(*this) + util::pad_size(size);
}
protected: protected:
std::unique_ptr<HashKey> ComputeSingletonHash(const Val* v, bool type_check) const; std::unique_ptr<HashKey> ComputeSingletonHash(const Val* v, bool type_check) const;
// Computes the piece of the hash for Val*, returning the new kp. // Computes the piece of the hash for Val*, returning the new kp.
// Used as a helper for ComputeHash in the non-singleton case. // Used as a helper for ComputeHash in the non-singleton case.
char* SingleValHash(bool type_check, char* kp, Type* bt, Val* v, char* SingleValHash(bool type_check, char* kp, Type* bt, Val* v, bool optional) const;
bool optional) const;
// Recovers just one Val of possibly many; called from RecoverVals. // Recovers just one Val of possibly many; called from RecoverVals.
// Upon return, pval will point to the recovered Val of type t. // Upon return, pval will point to the recovered Val of type t.
// Returns and updated kp for the next Val. Calls reporter->InternalError() // Returns and updated kp for the next Val. Calls reporter->InternalError()
// upon errors, so there is no return value for invalid input. // upon errors, so there is no return value for invalid input.
const char* RecoverOneVal( const char* RecoverOneVal(const HashKey& k, const char* kp, const char* const k_end, Type* t,
const HashKey& k, const char* kp, const char* const k_end, ValPtr* pval, bool optional) const;
Type* t, ValPtr* pval, bool optional) const;
// Rounds the given pointer up to the nearest multiple of the // Rounds the given pointer up to the nearest multiple of the
// given size, if not already a multiple. // given size, if not already a multiple.
@ -61,44 +66,36 @@ protected:
// of the given size. // of the given size.
int SizeAlign(int offset, unsigned int size) const; int SizeAlign(int offset, unsigned int size) const;
template<class T> template <class T> T* AlignAndPadType(char* ptr) const
T* AlignAndPadType(char* ptr) const
{ {
return reinterpret_cast<T*>(AlignAndPad(ptr, sizeof(T))); return reinterpret_cast<T*>(AlignAndPad(ptr, sizeof(T)));
} }
template<class T> template <class T> const T* AlignType(const char* ptr) const
const T* AlignType(const char* ptr) const
{ {
return reinterpret_cast<const T*>(Align(ptr, sizeof(T))); return reinterpret_cast<const T*>(Align(ptr, sizeof(T)));
} }
template<class T> template <class T> int SizeAlignType(int offset) const { return SizeAlign(offset, sizeof(T)); }
int SizeAlignType(int offset) const
{
return SizeAlign(offset, sizeof(T));
}
// Compute the size of the composite key. If v is non-nil then // Compute the size of the composite key. If v is non-nil then
// the value is computed for the particular list of values. // the value is computed for the particular list of values.
// Returns 0 if the key has an indeterminant size (if v not given), // Returns 0 if the key has an indeterminant size (if v not given),
// or if v doesn't match the index type (if given). // or if v doesn't match the index type (if given).
int ComputeKeySize(const Val* v, bool type_check, int ComputeKeySize(const Val* v, bool type_check, bool calc_static_size) const;
bool calc_static_size) const;
int SingleTypeKeySize(Type*, const Val*, int SingleTypeKeySize(Type*, const Val*, bool type_check, int sz, bool optional,
bool type_check, int sz, bool optional,
bool calc_static_size) const; bool calc_static_size) const;
TypeListPtr type; TypeListPtr type;
char* key; // space for composite key char* key; // space for composite key
int size; int size;
bool is_singleton; // if just one type in index bool is_singleton; // if just one type in index
// If one type, but not normal "singleton", e.g. record. // If one type, but not normal "singleton", e.g. record.
bool is_complex_type; bool is_complex_type;
InternalTypeTag singleton_tag; InternalTypeTag singleton_tag;
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,36 +1,36 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Conn.h" #include "zeek/Conn.h"
#include <ctype.h>
#include <binpac.h> #include <binpac.h>
#include <ctype.h>
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/RunState.h"
#include "zeek/NetVar.h"
#include "zeek/Event.h" #include "zeek/Event.h"
#include "zeek/session/Manager.h" #include "zeek/NetVar.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/RunState.h"
#include "zeek/Timer.h" #include "zeek/Timer.h"
#include "zeek/iosource/IOSource.h"
#include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/TunnelEncapsulation.h" #include "zeek/TunnelEncapsulation.h"
#include "zeek/analyzer/Analyzer.h" #include "zeek/analyzer/Analyzer.h"
#include "zeek/analyzer/Manager.h" #include "zeek/analyzer/Manager.h"
#include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/iosource/IOSource.h" #include "zeek/iosource/IOSource.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.h" #include "zeek/packet_analysis/protocol/ip/SessionAdapter.h"
#include "zeek/packet_analysis/protocol/tcp/TCP.h" #include "zeek/packet_analysis/protocol/tcp/TCP.h"
#include "zeek/session/Manager.h"
#include "zeek/zeek-config.h"
namespace zeek { namespace zeek
{
uint64_t Connection::total_connections = 0; uint64_t Connection::total_connections = 0;
uint64_t Connection::current_connections = 0; uint64_t Connection::current_connections = 0;
Connection::Connection(const detail::ConnKey& k, double t, Connection::Connection(const detail::ConnKey& k, double t, const ConnTuple* id, uint32_t flow,
const ConnTuple* id, uint32_t flow, const Packet* pkt) const Packet* pkt)
: Session(t, connection_timeout, connection_status_update, : Session(t, connection_timeout, connection_status_update,
detail::connection_status_update_interval), detail::connection_status_update_interval),
key(k) key(k)
{ {
orig_addr = id->src_addr; orig_addr = id->src_addr;
@ -96,8 +96,7 @@ void Connection::CheckEncapsulation(const std::shared_ptr<EncapsulationStack>& a
if ( *encapsulation != *arg_encap ) if ( *encapsulation != *arg_encap )
{ {
if ( tunnel_changed ) if ( tunnel_changed )
EnqueueEvent(tunnel_changed, nullptr, GetVal(), EnqueueEvent(tunnel_changed, nullptr, GetVal(), arg_encap->ToVal());
arg_encap->ToVal());
encapsulation = std::make_shared<EncapsulationStack>(*arg_encap); encapsulation = std::make_shared<EncapsulationStack>(*arg_encap);
} }
@ -144,12 +143,10 @@ void Connection::Done()
} }
} }
void Connection::NextPacket(double t, bool is_orig, void Connection::NextPacket(double t, bool is_orig, const IP_Hdr* ip, int len, int caplen,
const IP_Hdr* ip, int len, int caplen, const u_char*& data, int& record_packet, int& record_content,
const u_char*& data,
int& record_packet, int& record_content,
// arguments for reproducing packets // arguments for reproducing packets
const Packet *pkt) const Packet* pkt)
{ {
run_state::current_timestamp = t; run_state::current_timestamp = t;
run_state::current_pkt = pkt; run_state::current_pkt = pkt;
@ -177,8 +174,7 @@ bool Connection::IsReuse(double t, const u_char* pkt)
return adapter && adapter->IsReuse(t, pkt); return adapter && adapter->IsReuse(t, pkt);
} }
bool Connection::ScaledHistoryEntry(char code, uint32_t& counter, bool Connection::ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold,
uint32_t& scaling_threshold,
uint32_t scaling_base) uint32_t scaling_base)
{ {
if ( ++counter == scaling_threshold ) if ( ++counter == scaling_threshold )
@ -202,8 +198,7 @@ bool Connection::ScaledHistoryEntry(char code, uint32_t& counter,
return false; return false;
} }
void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, uint32_t threshold)
uint32_t threshold)
{ {
if ( ! e ) if ( ! e )
return; return;
@ -213,11 +208,7 @@ void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig,
// and at this stage it's not a *multiple* instance. // and at this stage it's not a *multiple* instance.
return; return;
EnqueueEvent(e, nullptr, EnqueueEvent(e, nullptr, GetVal(), val_mgr->Bool(is_orig), val_mgr->Count(threshold));
GetVal(),
val_mgr->Bool(is_orig),
val_mgr->Count(threshold)
);
} }
const RecordValPtr& Connection::GetVal() const RecordValPtr& Connection::GetVal()
@ -257,8 +248,8 @@ const RecordValPtr& Connection::GetVal()
conn_val->Assign(1, std::move(orig_endp)); conn_val->Assign(1, std::move(orig_endp));
conn_val->Assign(2, std::move(resp_endp)); conn_val->Assign(2, std::move(resp_endp));
// 3 and 4 are set below. // 3 and 4 are set below.
conn_val->Assign(5, make_intrusive<TableVal>(id::string_set)); // service conn_val->Assign(5, make_intrusive<TableVal>(id::string_set)); // service
conn_val->Assign(6, val_mgr->EmptyString()); // history conn_val->Assign(6, val_mgr->EmptyString()); // history
if ( ! uid ) if ( ! uid )
uid.Set(zeek::detail::bits_per_uid); uid.Set(zeek::detail::bits_per_uid);
@ -273,13 +264,12 @@ const RecordValPtr& Connection::GetVal()
if ( inner_vlan != 0 ) if ( inner_vlan != 0 )
conn_val->Assign(10, inner_vlan); conn_val->Assign(10, inner_vlan);
} }
if ( adapter ) if ( adapter )
adapter->UpdateConnVal(conn_val.get()); adapter->UpdateConnVal(conn_val.get());
conn_val->AssignTime(3, start_time); // ### conn_val->AssignTime(3, start_time); // ###
conn_val->AssignInterval(4, last_time - start_time); conn_val->AssignInterval(4, last_time - start_time);
conn_val->Assign(6, history); conn_val->Assign(6, history);
@ -318,16 +308,15 @@ static inline bool is_version_sep(const char* s, const char* end)
{ {
return return
// foo-1.2.3 // foo-1.2.3
(s < end - 1 && ispunct(s[0]) && isdigit(s[1])) || (s < end - 1 && ispunct(s[0]) && isdigit(s[1])) ||
// foo-v1.2.3 // foo-v1.2.3
(s < end - 2 && ispunct(s[0]) && (s < end - 2 && ispunct(s[0]) && tolower(s[1]) == 'v' && isdigit(s[2])) ||
tolower(s[1]) == 'v' && isdigit(s[2])) ||
// foo 1.2.3 // foo 1.2.3
isspace(s[0]); isspace(s[0]);
} }
void Connection::Match(detail::Rule::PatternType type, const u_char* data, int len, void Connection::Match(detail::Rule::PatternType type, const u_char* data, int len, bool is_orig,
bool is_orig, bool bol, bool eol, bool clear_state) bool bol, bool eol, bool clear_state)
{ {
if ( primary_PIA ) if ( primary_PIA )
primary_PIA->Match(type, data, len, is_orig, bol, eol, clear_state); primary_PIA->Match(type, data, len, is_orig, bol, eol, clear_state);
@ -383,10 +372,10 @@ unsigned int Connection::MemoryAllocation() const
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return session::Session::MemoryAllocation() + padded_sizeof(*this) return session::Session::MemoryAllocation() + padded_sizeof(*this) +
+ (timers.MemoryAllocation() - padded_sizeof(timers)) (timers.MemoryAllocation() - padded_sizeof(timers)) +
+ (conn_val ? conn_val->MemoryAllocation() : 0) (conn_val ? conn_val->MemoryAllocation() : 0) +
+ (adapter ? adapter->MemoryAllocation(): 0) (adapter ? adapter->MemoryAllocation() : 0)
// primary_PIA is already contained in the analyzer tree. // primary_PIA is already contained in the analyzer tree.
; ;
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -404,7 +393,8 @@ void Connection::Describe(ODesc* d) const
{ {
session::Session::Describe(d); session::Session::Describe(d);
switch ( proto ) { switch ( proto )
{
case TRANSPORT_TCP: case TRANSPORT_TCP:
d->Add("TCP"); d->Add("TCP");
break; break;
@ -419,14 +409,12 @@ void Connection::Describe(ODesc* d) const
case TRANSPORT_UNKNOWN: case TRANSPORT_UNKNOWN:
d->Add("unknown"); d->Add("unknown");
reporter->InternalWarning( reporter->InternalWarning("unknown transport in Connction::Describe()");
"unknown transport in Connction::Describe()");
break; break;
default: default:
reporter->InternalError( reporter->InternalError("unhandled transport type in Connection::Describe");
"unhandled transport type in Connection::Describe");
} }
d->SP(); d->SP();
@ -455,8 +443,7 @@ void Connection::IDString(ODesc* d) const
d->Add(ntohs(resp_port)); d->Add(ntohs(resp_port));
} }
void Connection::SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, void Connection::SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia)
analyzer::pia::PIA* pia)
{ {
adapter = aa; adapter = aa;
primary_PIA = pia; primary_PIA = pia;
@ -477,12 +464,8 @@ void Connection::CheckFlowLabel(bool is_orig, uint32_t flow_label)
if ( connection_flow_label_changed && if ( connection_flow_label_changed &&
(is_orig ? saw_first_orig_packet : saw_first_resp_packet) ) (is_orig ? saw_first_orig_packet : saw_first_resp_packet) )
{ {
EnqueueEvent(connection_flow_label_changed, nullptr, EnqueueEvent(connection_flow_label_changed, nullptr, GetVal(), val_mgr->Bool(is_orig),
GetVal(), val_mgr->Count(my_flow_label), val_mgr->Count(flow_label));
val_mgr->Bool(is_orig),
val_mgr->Count(my_flow_label),
val_mgr->Count(flow_label)
);
} }
my_flow_label = flow_label; my_flow_label = flow_label;
@ -494,10 +477,9 @@ void Connection::CheckFlowLabel(bool is_orig, uint32_t flow_label)
saw_first_resp_packet = 1; saw_first_resp_packet = 1;
} }
bool Connection::PermitWeird(const char* name, uint64_t threshold, uint64_t rate, bool Connection::PermitWeird(const char* name, uint64_t threshold, uint64_t rate, double duration)
double duration)
{ {
return detail::PermitWeird(weird_state, name, threshold, rate, duration); return detail::PermitWeird(weird_state, name, threshold, rate, duration);
} }
} // namespace zeek } // namespace zeek

View file

@ -3,26 +3,25 @@
#pragma once #pragma once
#include <sys/types.h> #include <sys/types.h>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include "zeek/Dict.h" #include "zeek/Dict.h"
#include "zeek/Timer.h"
#include "zeek/Rule.h"
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/Rule.h"
#include "zeek/Timer.h"
#include "zeek/UID.h" #include "zeek/UID.h"
#include "zeek/WeirdState.h" #include "zeek/WeirdState.h"
#include "zeek/ZeekArgs.h" #include "zeek/ZeekArgs.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/session/Session.h"
#include "zeek/iosource/Packet.h"
#include "zeek/analyzer/Tag.h"
#include "zeek/analyzer/Analyzer.h" #include "zeek/analyzer/Analyzer.h"
#include "zeek/analyzer/Tag.h"
#include "zeek/iosource/Packet.h"
#include "zeek/session/Session.h"
namespace zeek { namespace zeek
{
class Connection; class Connection;
class EncapsulationStack; class EncapsulationStack;
@ -32,47 +31,59 @@ class RecordVal;
using ValPtr = IntrusivePtr<Val>; using ValPtr = IntrusivePtr<Val>;
using RecordValPtr = IntrusivePtr<RecordVal>; using RecordValPtr = IntrusivePtr<RecordVal>;
namespace session { class Manager; } namespace session
namespace detail { {
class Manager;
}
namespace detail
{
class Specific_RE_Matcher; class Specific_RE_Matcher;
class RuleEndpointState; class RuleEndpointState;
class RuleHdrTest; class RuleHdrTest;
} // namespace detail } // namespace detail
namespace analyzer { class Analyzer; } namespace analyzer
namespace packet_analysis::IP { class SessionAdapter; } {
class Analyzer;
}
namespace packet_analysis::IP
{
class SessionAdapter;
}
enum ConnEventToFlag { enum ConnEventToFlag
{
NUL_IN_LINE, NUL_IN_LINE,
SINGULAR_CR, SINGULAR_CR,
SINGULAR_LF, SINGULAR_LF,
NUM_EVENTS_TO_FLAG, NUM_EVENTS_TO_FLAG,
}; };
struct ConnTuple { struct ConnTuple
{
IPAddr src_addr; IPAddr src_addr;
IPAddr dst_addr; IPAddr dst_addr;
uint32_t src_port; uint32_t src_port;
uint32_t dst_port; uint32_t dst_port;
bool is_one_way; // if true, don't canonicalize order bool is_one_way; // if true, don't canonicalize order
TransportProto proto; TransportProto proto;
}; };
using ConnID [[deprecated("Remove in v5.1. Use zeek::ConnTuple.")]] = ConnTuple; using ConnID [[deprecated("Remove in v5.1. Use zeek::ConnTuple.")]] = ConnTuple;
static inline int addr_port_canon_lt(const IPAddr& addr1, uint32_t p1, static inline int addr_port_canon_lt(const IPAddr& addr1, uint32_t p1, const IPAddr& addr2,
const IPAddr& addr2, uint32_t p2) uint32_t p2)
{ {
return addr1 < addr2 || (addr1 == addr2 && p1 < p2); return addr1 < addr2 || (addr1 == addr2 && p1 < p2);
} }
class Connection final : public session::Session { class Connection final : public session::Session
{
public: public:
Connection(const detail::ConnKey& k, double t, const ConnTuple* id, uint32_t flow,
Connection(const detail::ConnKey& k, double t, const ConnTuple* id, const Packet* pkt);
uint32_t flow, const Packet* pkt);
~Connection() override; ~Connection() override;
/** /**
@ -101,34 +112,32 @@ public:
// If record_content is true, then its entire contents should // If record_content is true, then its entire contents should
// be recorded, otherwise just up through the transport header. // be recorded, otherwise just up through the transport header.
// Both are assumed set to true when called. // Both are assumed set to true when called.
void NextPacket(double t, bool is_orig, void NextPacket(double t, bool is_orig, const IP_Hdr* ip, int len, int caplen,
const IP_Hdr* ip, int len, int caplen, const u_char*& data, int& record_packet, int& record_content,
const u_char*& data,
int& record_packet, int& record_content,
// arguments for reproducing packets // arguments for reproducing packets
const Packet *pkt); const Packet* pkt);
// Keys are only considered valid for a connection when a // Keys are only considered valid for a connection when a
// connection is in the session map. If it is removed, the key // connection is in the session map. If it is removed, the key
// should be marked invalid. // should be marked invalid.
const detail::ConnKey& Key() const { return key; } const detail::ConnKey& Key() const { return key; }
session::detail::Key SessionKey(bool copy) const override session::detail::Key SessionKey(bool copy) const override
{ {
return session::detail::Key{ return session::detail::Key{&key, sizeof(key), session::detail::Key::CONNECTION_KEY_TYPE,
&key, sizeof(key), session::detail::Key::CONNECTION_KEY_TYPE, copy}; copy};
} }
const IPAddr& OrigAddr() const { return orig_addr; } const IPAddr& OrigAddr() const { return orig_addr; }
const IPAddr& RespAddr() const { return resp_addr; } const IPAddr& RespAddr() const { return resp_addr; }
uint32_t OrigPort() const { return orig_port; } uint32_t OrigPort() const { return orig_port; }
uint32_t RespPort() const { return resp_port; } uint32_t RespPort() const { return resp_port; }
void FlipRoles(); void FlipRoles();
analyzer::Analyzer* FindAnalyzer(analyzer::ID id); analyzer::Analyzer* FindAnalyzer(analyzer::ID id);
analyzer::Analyzer* FindAnalyzer(const analyzer::Tag& tag); // find first in tree. analyzer::Analyzer* FindAnalyzer(const analyzer::Tag& tag); // find first in tree.
analyzer::Analyzer* FindAnalyzer(const char* name); // find first in tree. analyzer::Analyzer* FindAnalyzer(const char* name); // find first in tree.
TransportProto ConnTransport() const { return proto; } TransportProto ConnTransport() const { return proto; }
std::string TransportIdentifier() const override std::string TransportIdentifier() const override
@ -158,8 +167,8 @@ public:
*/ */
void AppendAddl(const char* str); void AppendAddl(const char* str);
void Match(detail::Rule::PatternType type, const u_char* data, int len, void Match(detail::Rule::PatternType type, const u_char* data, int len, bool is_orig, bool bol,
bool is_orig, bool bol, bool eol, bool clear_state); bool eol, bool clear_state);
/** /**
* Generates connection removal event(s). * Generates connection removal event(s).
@ -167,7 +176,7 @@ public:
void RemovalEvent() override; void RemovalEvent() override;
void Weird(const char* name, const char* addl = "", const char* source = ""); void Weird(const char* name, const char* addl = "", const char* source = "");
bool DidWeird() const { return weird != 0; } bool DidWeird() const { return weird != 0; }
inline bool FlagEvent(ConnEventToFlag e) inline bool FlagEvent(ConnEventToFlag e)
{ {
@ -187,15 +196,15 @@ public:
// Statistics. // Statistics.
// Just a lower bound. // Just a lower bound.
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const override; "GHI-572.")]] unsigned int
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] MemoryAllocation() const override;
unsigned int MemoryAllocationVal() const override; [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] unsigned int
MemoryAllocationVal() const override;
static uint64_t TotalConnections() static uint64_t TotalConnections() { return total_connections; }
{ return total_connections; } static uint64_t CurrentConnections() { return current_connections; }
static uint64_t CurrentConnections()
{ return current_connections; }
// Returns true if the history was already seen, false otherwise. // Returns true if the history was already seen, false otherwise.
bool CheckHistory(uint32_t mask, char code) bool CheckHistory(uint32_t mask, char code)
@ -214,59 +223,54 @@ public:
// code if it has crossed the next scaling threshold. Scaling // code if it has crossed the next scaling threshold. Scaling
// is done in terms of powers of the third argument. // is done in terms of powers of the third argument.
// Returns true if the threshold was crossed, false otherwise. // Returns true if the threshold was crossed, false otherwise.
bool ScaledHistoryEntry(char code, uint32_t& counter, bool ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold,
uint32_t& scaling_threshold,
uint32_t scaling_base = 10); uint32_t scaling_base = 10);
void HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, void HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, uint32_t threshold);
uint32_t threshold);
void AddHistory(char code) { history += code; } void AddHistory(char code) { history += code; }
// Sets the root of the analyzer tree as well as the primary PIA. // Sets the root of the analyzer tree as well as the primary PIA.
void SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia); void SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia);
packet_analysis::IP::SessionAdapter* GetSessionAdapter() { return adapter; } packet_analysis::IP::SessionAdapter* GetSessionAdapter() { return adapter; }
analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; } analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; }
// Sets the transport protocol in use. // Sets the transport protocol in use.
void SetTransport(TransportProto arg_proto) { proto = arg_proto; } void SetTransport(TransportProto arg_proto) { proto = arg_proto; }
void SetUID(const UID &arg_uid) { uid = arg_uid; } void SetUID(const UID& arg_uid) { uid = arg_uid; }
UID GetUID() const { return uid; } UID GetUID() const { return uid; }
std::shared_ptr<EncapsulationStack> GetEncapsulation() const std::shared_ptr<EncapsulationStack> GetEncapsulation() const { return encapsulation; }
{ return encapsulation; }
void CheckFlowLabel(bool is_orig, uint32_t flow_label); void CheckFlowLabel(bool is_orig, uint32_t flow_label);
uint32_t GetOrigFlowLabel() { return orig_flow_label; } uint32_t GetOrigFlowLabel() { return orig_flow_label; }
uint32_t GetRespFlowLabel() { return resp_flow_label; } uint32_t GetRespFlowLabel() { return resp_flow_label; }
bool PermitWeird(const char* name, uint64_t threshold, uint64_t rate, bool PermitWeird(const char* name, uint64_t threshold, uint64_t rate, double duration);
double duration);
private: private:
friend class session::detail::Timer; friend class session::detail::Timer;
IPAddr orig_addr; IPAddr orig_addr;
IPAddr resp_addr; IPAddr resp_addr;
uint32_t orig_port, resp_port; // in network order uint32_t orig_port, resp_port; // in network order
TransportProto proto; TransportProto proto;
uint32_t orig_flow_label, resp_flow_label; // most recent IPv6 flow labels uint32_t orig_flow_label, resp_flow_label; // most recent IPv6 flow labels
uint32_t vlan, inner_vlan; // VLAN this connection traverses, if available uint32_t vlan, inner_vlan; // VLAN this connection traverses, if available
u_char orig_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer originator address, if available u_char orig_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer originator address, if available
u_char resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available u_char resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available
int suppress_event; // suppress certain events to once per conn. int suppress_event; // suppress certain events to once per conn.
RecordValPtr conn_val; RecordValPtr conn_val;
std::shared_ptr<EncapsulationStack> encapsulation; // tunnels std::shared_ptr<EncapsulationStack> encapsulation; // tunnels
detail::ConnKey key; detail::ConnKey key;
unsigned int weird:1; unsigned int weird : 1;
unsigned int finished:1; unsigned int finished : 1;
unsigned int saw_first_orig_packet:1, saw_first_resp_packet:1; unsigned int saw_first_orig_packet : 1, saw_first_resp_packet : 1;
uint32_t hist_seen; uint32_t hist_seen;
std::string history; std::string history;
@ -274,12 +278,12 @@ private:
packet_analysis::IP::SessionAdapter* adapter; packet_analysis::IP::SessionAdapter* adapter;
analyzer::pia::PIA* primary_PIA; analyzer::pia::PIA* primary_PIA;
UID uid; // Globally unique connection ID. UID uid; // Globally unique connection ID.
detail::WeirdStateMap weird_state; detail::WeirdStateMap weird_state;
// Count number of connections. // Count number of connections.
static uint64_t total_connections; static uint64_t total_connections;
static uint64_t current_connections; static uint64_t current_connections;
}; };
} // namespace zeek } // namespace zeek

View file

@ -1,19 +1,19 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/DFA.h"
#include "zeek/Desc.h"
#include "zeek/EquivClass.h"
#include "zeek/Hash.h"
#include "zeek/zeek-config.h" #include "zeek/zeek-config.h"
#include "zeek/DFA.h" namespace zeek::detail
#include "zeek/EquivClass.h" {
#include "zeek/Desc.h"
#include "zeek/Hash.h"
namespace zeek::detail {
unsigned int DFA_State::transition_counter = 0; unsigned int DFA_State::transition_counter = 0;
DFA_State::DFA_State(int arg_state_num, const EquivClass* ec, DFA_State::DFA_State(int arg_state_num, const EquivClass* ec, NFA_state_list* arg_nfa_states,
NFA_state_list* arg_nfa_states, AcceptingSet* arg_accept)
AcceptingSet* arg_accept)
{ {
state_num = arg_state_num; state_num = arg_state_num;
num_sym = ec->NumClasses(); num_sym = ec->NumClasses();
@ -31,7 +31,7 @@ DFA_State::DFA_State(int arg_state_num, const EquivClass* ec,
DFA_State::~DFA_State() DFA_State::~DFA_State()
{ {
delete [] xtions; delete[] xtions;
delete nfa_states; delete nfa_states;
delete accept; delete accept;
delete meta_ec; delete meta_ec;
@ -98,7 +98,7 @@ DFA_State* DFA_State::ComputeXtion(int sym, DFA_Machine* machine)
else else
{ {
delete ns; delete ns;
next_d = nullptr; // Jam next_d = nullptr; // Jam
} }
AddXtion(equiv_sym, next_d); AddXtion(equiv_sym, next_d);
@ -163,7 +163,7 @@ NFA_state_list* DFA_State::SymFollowSet(int ec_sym, const EquivClass* ec)
break; break;
} }
} }
} }
else if ( n->TransSym() == SYM_EPSILON ) else if ( n->TransSym() == SYM_EPSILON )
{ // do nothing { // do nothing
@ -241,15 +241,14 @@ void DFA_State::Dump(FILE* f, DFA_Machine* m)
if ( i == sym + 1 ) if ( i == sym + 1 )
sprintf(xbuf, "'%c'", r); sprintf(xbuf, "'%c'", r);
else else
sprintf(xbuf, "'%c'-'%c'", r, m->Rep(i-1)); sprintf(xbuf, "'%c'-'%c'", r, m->Rep(i - 1));
if ( s == DFA_UNCOMPUTED_STATE_PTR ) if ( s == DFA_UNCOMPUTED_STATE_PTR )
fprintf(f, "%stransition on %s to <uncomputed>", fprintf(f, "%stransition on %s to <uncomputed>", ++num_trans == 1 ? "\t" : "\n\t",
++num_trans == 1 ? "\t" : "\n\t", xbuf); xbuf);
else else
fprintf(f, "%stransition on %s to state %d", fprintf(f, "%stransition on %s to state %d", ++num_trans == 1 ? "\t" : "\n\t", xbuf,
++num_trans == 1 ? "\t" : "\n\t", xbuf, s->StateNum());
s->StateNum());
sym = i - 1; sym = i - 1;
} }
@ -283,11 +282,10 @@ void DFA_State::Stats(unsigned int* computed, unsigned int* uncomputed)
unsigned int DFA_State::Size() unsigned int DFA_State::Size()
{ {
return sizeof(*this) return sizeof(*this) + util::pad_size(sizeof(DFA_State*) * num_sym) +
+ util::pad_size(sizeof(DFA_State*) * num_sym) (accept ? util::pad_size(sizeof(int) * accept->size()) : 0) +
+ (accept ? util::pad_size(sizeof(int) * accept->size()) : 0) (nfa_states ? util::pad_size(sizeof(NFA_State*) * nfa_states->length()) : 0) +
+ (nfa_states ? util::pad_size(sizeof(NFA_State*) * nfa_states->length()) : 0) (meta_ec ? meta_ec->Size() : 0);
+ (meta_ec ? meta_ec->Size() : 0);
} }
DFA_State_Cache::DFA_State_Cache() DFA_State_Cache::DFA_State_Cache()
@ -324,8 +322,7 @@ DFA_State* DFA_State_Cache::Lookup(const NFA_state_list& nfas, DigestStr* digest
{ {
*p++ = '0' + (char)(id % 10); *p++ = '0' + (char)(id % 10);
id /= 10; id /= 10;
} } while ( id > 0 );
while ( id > 0 );
*p++ = '&'; *p++ = '&';
} }
} }
@ -428,15 +425,12 @@ unsigned int DFA_Machine::MemoryAllocation() const
// FIXME: Count *ec? // FIXME: Count *ec?
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return padded_sizeof(*this) return padded_sizeof(*this) + s.mem + padded_sizeof(*start_state) + nfa->MemoryAllocation();
+ s.mem
+ padded_sizeof(*start_state)
+ nfa->MemoryAllocation();
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} }
bool DFA_Machine::StateSetToDFA_State(NFA_state_list* state_set, bool DFA_Machine::StateSetToDFA_State(NFA_state_list* state_set, DFA_State*& d,
DFA_State*& d, const EquivClass* ec) const EquivClass* ec)
{ {
DigestStr digest; DigestStr digest;
d = dfa_state_cache->Lookup(*state_set, &digest); d = dfa_state_cache->Lookup(*state_set, &digest);
@ -475,4 +469,4 @@ int DFA_Machine::Rep(int sym)
return -1; return -1;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,6 +1,5 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#pragma once #pragma once
#include <assert.h> #include <assert.h>
@ -9,10 +8,11 @@
#include <string> #include <string>
#include "zeek/NFA.h" #include "zeek/NFA.h"
#include "zeek/RE.h" // for typedef AcceptingSet
#include "zeek/Obj.h" #include "zeek/Obj.h"
#include "zeek/RE.h" // for typedef AcceptingSet
namespace zeek::detail { namespace zeek::detail
{
class DFA_State; class DFA_State;
class DFA_Machine; class DFA_Machine;
@ -20,32 +20,33 @@ class DFA_Machine;
// Transitions to the uncomputed state indicate that we haven't yet // Transitions to the uncomputed state indicate that we haven't yet
// computed the state to go to. // computed the state to go to.
#define DFA_UNCOMPUTED_STATE -2 #define DFA_UNCOMPUTED_STATE -2
#define DFA_UNCOMPUTED_STATE_PTR ((DFA_State*) DFA_UNCOMPUTED_STATE) #define DFA_UNCOMPUTED_STATE_PTR ((DFA_State*)DFA_UNCOMPUTED_STATE)
class DFA_State : public Obj { class DFA_State : public Obj
{
public: public:
DFA_State(int state_num, const EquivClass* ec, DFA_State(int state_num, const EquivClass* ec, NFA_state_list* nfa_states,
NFA_state_list* nfa_states, AcceptingSet* accept); AcceptingSet* accept);
~DFA_State() override; ~DFA_State() override;
int StateNum() const { return state_num; } int StateNum() const { return state_num; }
int NFAStateNum() const { return nfa_states->length(); } int NFAStateNum() const { return nfa_states->length(); }
void AddXtion(int sym, DFA_State* next_state); void AddXtion(int sym, DFA_State* next_state);
inline DFA_State* Xtion(int sym, DFA_Machine* machine); inline DFA_State* Xtion(int sym, DFA_Machine* machine);
const AcceptingSet* Accept() const { return accept; } const AcceptingSet* Accept() const { return accept; }
void SymPartition(const EquivClass* ec); void SymPartition(const EquivClass* ec);
// ec_sym is an equivalence class, not a character. // ec_sym is an equivalence class, not a character.
NFA_state_list* SymFollowSet(int ec_sym, const EquivClass* ec); NFA_state_list* SymFollowSet(int ec_sym, const EquivClass* ec);
void SetMark(DFA_State* m) { mark = m; } void SetMark(DFA_State* m) { mark = m; }
DFA_State* Mark() const { return mark; } DFA_State* Mark() const { return mark; }
void ClearMarks(); void ClearMarks();
// Returns the equivalence classes of ec's corresponding to this state. // Returns the equivalence classes of ec's corresponding to this state.
const EquivClass* MetaECs() const { return meta_ec; } const EquivClass* MetaECs() const { return meta_ec; }
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
void Dump(FILE* f, DFA_Machine* m); void Dump(FILE* f, DFA_Machine* m);
@ -65,15 +66,16 @@ protected:
AcceptingSet* accept; AcceptingSet* accept;
NFA_state_list* nfa_states; NFA_state_list* nfa_states;
EquivClass* meta_ec; // which ec's make same transition EquivClass* meta_ec; // which ec's make same transition
DFA_State* mark; DFA_State* mark;
static unsigned int transition_counter; // see Xtion() static unsigned int transition_counter; // see Xtion()
}; };
using DigestStr = std::basic_string<u_char>; using DigestStr = std::basic_string<u_char>;
class DFA_State_Cache { class DFA_State_Cache
{
public: public:
DFA_State_Cache(); DFA_State_Cache();
~DFA_State_Cache(); ~DFA_State_Cache();
@ -84,9 +86,10 @@ public:
// Takes ownership of state; digest is the one returned by Lookup(). // Takes ownership of state; digest is the one returned by Lookup().
DFA_State* Insert(DFA_State* state, DigestStr digest); DFA_State* Insert(DFA_State* state, DigestStr digest);
int NumEntries() const { return states.size(); } int NumEntries() const { return states.size(); }
struct Stats { struct Stats
{
// Sum of all NFA states // Sum of all NFA states
unsigned int nfa_states; unsigned int nfa_states;
unsigned int dfa_states; unsigned int dfa_states;
@ -95,54 +98,55 @@ public:
unsigned int mem; unsigned int mem;
unsigned int hits; unsigned int hits;
unsigned int misses; unsigned int misses;
}; };
void GetStats(Stats* s); void GetStats(Stats* s);
private: private:
int hits; // Statistics int hits; // Statistics
int misses; int misses;
// Hash indexed by NFA states (MD5s of them, actually). // Hash indexed by NFA states (MD5s of them, actually).
std::map<DigestStr, DFA_State*> states; std::map<DigestStr, DFA_State*> states;
}; };
class DFA_Machine : public Obj { class DFA_Machine : public Obj
{
public: public:
DFA_Machine(NFA_Machine* n, EquivClass* ec); DFA_Machine(NFA_Machine* n, EquivClass* ec);
~DFA_Machine() override; ~DFA_Machine() override;
DFA_State* StartState() const { return start_state; } DFA_State* StartState() const { return start_state; }
int NumStates() const { return dfa_state_cache->NumEntries(); } int NumStates() const { return dfa_state_cache->NumEntries(); }
DFA_State_Cache* Cache() { return dfa_state_cache; } DFA_State_Cache* Cache() { return dfa_state_cache; }
int Rep(int sym); int Rep(int sym);
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
void Dump(FILE* f); void Dump(FILE* f);
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const; "GHI-572.")]] unsigned int
MemoryAllocation() const;
protected: protected:
friend class DFA_State; // for DFA_State::ComputeXtion friend class DFA_State; // for DFA_State::ComputeXtion
friend class DFA_State_Cache; friend class DFA_State_Cache;
int state_count; int state_count;
// The state list has to be sorted according to IDs. // The state list has to be sorted according to IDs.
bool StateSetToDFA_State(NFA_state_list* state_set, DFA_State*& d, bool StateSetToDFA_State(NFA_state_list* state_set, DFA_State*& d, const EquivClass* ec);
const EquivClass* ec); const EquivClass* EC() const { return ec; }
const EquivClass* EC() const { return ec; }
EquivClass* ec; // equivalence classes corresponding to NFAs EquivClass* ec; // equivalence classes corresponding to NFAs
DFA_State* start_state; DFA_State* start_state;
DFA_State_Cache* dfa_state_cache; DFA_State_Cache* dfa_state_cache;
NFA_Machine* nfa; NFA_Machine* nfa;
}; };
inline DFA_State* DFA_State::Xtion(int sym, DFA_Machine* machine) inline DFA_State* DFA_State::Xtion(int sym, DFA_Machine* machine)
{ {
@ -152,4 +156,4 @@ inline DFA_State* DFA_State::Xtion(int sym, DFA_Machine* machine)
return xtions[sym]; return xtions[sym];
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,88 +1,87 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/DNS_Mgr.h" #include "zeek/DNS_Mgr.h"
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h>
#include "zeek/zeek-config.h"
#ifdef TIME_WITH_SYS_TIME #ifdef TIME_WITH_SYS_TIME
# include <sys/time.h> #include <sys/time.h>
# include <time.h> #include <time.h>
#else #else
# ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> #include <sys/time.h>
# else #else
# include <time.h> #include <time.h>
# endif #endif
#endif #endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h> #include <errno.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_MEMORY_H #ifdef HAVE_MEMORY_H
#include <memory.h> #include <memory.h>
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <algorithm> #include <algorithm>
#include "zeek/ZeekString.h"
#include "zeek/Expr.h"
#include "zeek/Event.h" #include "zeek/Event.h"
#include "zeek/Expr.h"
#include "zeek/Hash.h"
#include "zeek/ID.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/NetVar.h"
#include "zeek/Reporter.h"
#include "zeek/RunState.h" #include "zeek/RunState.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/NetVar.h" #include "zeek/ZeekString.h"
#include "zeek/ID.h"
#include "zeek/Reporter.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/iosource/Manager.h" #include "zeek/iosource/Manager.h"
#include "zeek/Hash.h"
extern "C" { extern "C"
extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); {
extern int select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
#include <netdb.h> #include <netdb.h>
#include "zeek/nb_dns.h" #include "zeek/nb_dns.h"
} }
using namespace std; using namespace std;
namespace zeek::detail { namespace zeek::detail
{
class DNS_Mgr_Request { class DNS_Mgr_Request
{
public: public:
DNS_Mgr_Request(const char* h, int af, bool is_txt) DNS_Mgr_Request(const char* h, int af, bool is_txt)
: host(util::copy_string(h)), fam(af), qtype(is_txt ? 16 : 0), addr(), : host(util::copy_string(h)), fam(af), qtype(is_txt ? 16 : 0), addr(), request_pending()
request_pending() {
{ } }
DNS_Mgr_Request(const IPAddr& a) DNS_Mgr_Request(const IPAddr& a) : host(), fam(), qtype(), addr(a), request_pending() { }
: host(), fam(), qtype(), addr(a), request_pending()
{ }
~DNS_Mgr_Request() { delete [] host; } ~DNS_Mgr_Request() { delete[] host; }
// Returns nil if this was an address request. // Returns nil if this was an address request.
const char* ReqHost() const { return host; } const char* ReqHost() const { return host; }
const IPAddr& ReqAddr() const { return addr; } const IPAddr& ReqAddr() const { return addr; }
bool ReqIsTxt() const { return qtype == 16; } bool ReqIsTxt() const { return qtype == 16; }
int MakeRequest(nb_dns_info* nb_dns); int MakeRequest(nb_dns_info* nb_dns);
int RequestPending() const { return request_pending; } int RequestPending() const { return request_pending; }
void RequestDone() { request_pending = 0; } void RequestDone() { request_pending = 0; }
protected: protected:
char* host; // if non-nil, this is a host request char* host; // if non-nil, this is a host request
int fam; // address family query type for host requests int fam; // address family query type for host requests
int qtype; // Query type int qtype; // Query type
IPAddr addr; IPAddr addr;
int request_pending; int request_pending;
}; };
int DNS_Mgr_Request::MakeRequest(nb_dns_info* nb_dns) int DNS_Mgr_Request::MakeRequest(nb_dns_info* nb_dns)
{ {
@ -93,49 +92,47 @@ int DNS_Mgr_Request::MakeRequest(nb_dns_info* nb_dns)
char err[NB_DNS_ERRSIZE]; char err[NB_DNS_ERRSIZE];
if ( host ) if ( host )
return nb_dns_host_request2(nb_dns, host, fam, qtype, (void*) this, err) >= 0; return nb_dns_host_request2(nb_dns, host, fam, qtype, (void*)this, err) >= 0;
else else
{ {
const uint32_t* bytes; const uint32_t* bytes;
int len = addr.GetBytes(&bytes); int len = addr.GetBytes(&bytes);
return nb_dns_addr_request2(nb_dns, (char*) bytes, return nb_dns_addr_request2(nb_dns, (char*)bytes, len == 1 ? AF_INET : AF_INET6,
len == 1 ? AF_INET : AF_INET6, (void*) this, err) >= 0; (void*)this, err) >= 0;
} }
} }
class DNS_Mapping { class DNS_Mapping
{
public: public:
DNS_Mapping(const char* host, struct hostent* h, uint32_t ttl); DNS_Mapping(const char* host, struct hostent* h, uint32_t ttl);
DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32_t ttl); DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32_t ttl);
DNS_Mapping(FILE* f); DNS_Mapping(FILE* f);
bool NoMapping() const { return no_mapping; } bool NoMapping() const { return no_mapping; }
bool InitFailed() const { return init_failed; } bool InitFailed() const { return init_failed; }
~DNS_Mapping(); ~DNS_Mapping();
// Returns nil if this was an address request. // Returns nil if this was an address request.
const char* ReqHost() const { return req_host; } const char* ReqHost() const { return req_host; }
IPAddr ReqAddr() const { return req_addr; } IPAddr ReqAddr() const { return req_addr; }
string ReqStr() const string ReqStr() const { return req_host ? req_host : req_addr.AsString(); }
{
return req_host ? req_host : req_addr.AsString();
}
ListValPtr Addrs(); ListValPtr Addrs();
TableValPtr AddrsSet(); // addresses returned as a set TableValPtr AddrsSet(); // addresses returned as a set
StringValPtr Host(); StringValPtr Host();
double CreationTime() const { return creation_time; } double CreationTime() const { return creation_time; }
void Save(FILE* f) const; void Save(FILE* f) const;
bool Failed() const { return failed; } bool Failed() const { return failed; }
bool Valid() const { return ! failed; } bool Valid() const { return ! failed; }
bool Expired() const bool Expired() const
{ {
if ( req_host && num_addrs == 0) if ( req_host && num_addrs == 0 )
return false; // nothing to expire return false; // nothing to expire
return util::current_time() > (creation_time + req_ttl); return util::current_time() > (creation_time + req_ttl);
@ -163,14 +160,14 @@ protected:
double creation_time; double creation_time;
int map_type; int map_type;
bool no_mapping; // when initializing from a file, immediately hit EOF bool no_mapping; // when initializing from a file, immediately hit EOF
bool init_failed; bool init_failed;
bool failed; bool failed;
}; };
void DNS_Mgr_mapping_delete_func(void* v) void DNS_Mgr_mapping_delete_func(void* v)
{ {
delete (DNS_Mapping*) v; delete (DNS_Mapping*)v;
} }
static TableValPtr empty_addr_set() static TableValPtr empty_addr_set()
@ -217,13 +214,12 @@ DNS_Mapping::DNS_Mapping(FILE* f)
return; return;
} }
char req_buf[512+1], name_buf[512+1]; char req_buf[512 + 1], name_buf[512 + 1];
int is_req_host; int is_req_host;
int failed_local; int failed_local;
if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %" PRIu32, &creation_time, if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %" PRIu32, &creation_time, &is_req_host, req_buf,
&is_req_host, req_buf, &failed_local, name_buf, &map_type, &num_addrs, &failed_local, name_buf, &map_type, &num_addrs, &req_ttl) != 8 )
&req_ttl) != 8 )
return; return;
failed = static_cast<bool>(failed_local); failed = static_cast<bool>(failed_local);
@ -264,16 +260,16 @@ DNS_Mapping::DNS_Mapping(FILE* f)
DNS_Mapping::~DNS_Mapping() DNS_Mapping::~DNS_Mapping()
{ {
delete [] req_host; delete[] req_host;
if ( names ) if ( names )
{ {
for ( int i = 0; i < num_names; ++i ) for ( int i = 0; i < num_names; ++i )
delete [] names[i]; delete[] names[i];
delete [] names; delete[] names;
} }
delete [] addrs; delete[] addrs;
} }
ListValPtr DNS_Mapping::Addrs() ListValPtr DNS_Mapping::Addrs()
@ -292,7 +288,8 @@ ListValPtr DNS_Mapping::Addrs()
return addrs_val; return addrs_val;
} }
TableValPtr DNS_Mapping::AddrsSet() { TableValPtr DNS_Mapping::AddrsSet()
{
auto l = Addrs(); auto l = Addrs();
if ( ! l ) if ( ! l )
@ -327,7 +324,7 @@ void DNS_Mapping::Init(struct hostent* h)
} }
map_type = h->h_addrtype; map_type = h->h_addrtype;
num_names = 1; // for now, just use official name num_names = 1; // for now, just use official name
names = new char*[num_names]; names = new char*[num_names];
names[0] = h->h_name ? util::copy_string(h->h_name) : nullptr; names[0] = h->h_name ? util::copy_string(h->h_name) : nullptr;
@ -339,11 +336,9 @@ void DNS_Mapping::Init(struct hostent* h)
addrs = new IPAddr[num_addrs]; addrs = new IPAddr[num_addrs];
for ( int i = 0; i < num_addrs; ++i ) for ( int i = 0; i < num_addrs; ++i )
if ( h->h_addrtype == AF_INET ) if ( h->h_addrtype == AF_INET )
addrs[i] = IPAddr(IPv4, (uint32_t*)h->h_addr_list[i], addrs[i] = IPAddr(IPv4, (uint32_t*)h->h_addr_list[i], IPAddr::Network);
IPAddr::Network);
else if ( h->h_addrtype == AF_INET6 ) else if ( h->h_addrtype == AF_INET6 )
addrs[i] = IPAddr(IPv6, (uint32_t*)h->h_addr_list[i], addrs[i] = IPAddr(IPv6, (uint32_t*)h->h_addr_list[i], IPAddr::Network);
IPAddr::Network);
} }
else else
addrs = nullptr; addrs = nullptr;
@ -365,16 +360,14 @@ void DNS_Mapping::Clear()
void DNS_Mapping::Save(FILE* f) const void DNS_Mapping::Save(FILE* f) const
{ {
fprintf(f, "%.0f %d %s %d %s %d %d %" PRIu32"\n", creation_time, req_host != nullptr, fprintf(f, "%.0f %d %s %d %s %d %d %" PRIu32 "\n", creation_time, req_host != nullptr,
req_host ? req_host : req_addr.AsString().c_str(), req_host ? req_host : req_addr.AsString().c_str(), failed,
failed, (names && names[0]) ? names[0] : "*", (names && names[0]) ? names[0] : "*", map_type, num_addrs, req_ttl);
map_type, num_addrs, req_ttl);
for ( int i = 0; i < num_addrs; ++i ) for ( int i = 0; i < num_addrs; ++i )
fprintf(f, "%s\n", addrs[i].AsString().c_str()); fprintf(f, "%s\n", addrs[i].AsString().c_str());
} }
DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode) DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode)
{ {
did_init = false; did_init = false;
@ -395,8 +388,8 @@ DNS_Mgr::~DNS_Mgr()
if ( nb_dns ) if ( nb_dns )
nb_dns_finish(nb_dns); nb_dns_finish(nb_dns);
delete [] cache_name; delete[] cache_name;
delete [] dir; delete[] dir;
} }
void DNS_Mgr::InitSource() void DNS_Mgr::InitSource()
@ -480,8 +473,7 @@ static const char* fake_text_lookup_result(const char* name)
static const char* fake_addr_lookup_result(const IPAddr& addr) static const char* fake_addr_lookup_result(const IPAddr& addr)
{ {
static char tmp[128]; static char tmp[128];
snprintf(tmp, sizeof(tmp), "fake_addr_lookup_result_%s", snprintf(tmp, sizeof(tmp), "fake_addr_lookup_result_%s", addr.AsString().c_str());
addr.AsString().c_str());
return tmp; return tmp;
} }
@ -520,26 +512,27 @@ TableValPtr DNS_Mgr::LookupHost(const char* name)
} }
// Not found, or priming. // Not found, or priming.
switch ( mode ) { switch ( mode )
case DNS_PRIME: {
requests.push_back(new DNS_Mgr_Request(name, AF_INET, false)); case DNS_PRIME:
requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false)); requests.push_back(new DNS_Mgr_Request(name, AF_INET, false));
return empty_addr_set(); requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false));
return empty_addr_set();
case DNS_FORCE: case DNS_FORCE:
reporter->FatalError("can't find DNS entry for %s in cache", name); reporter->FatalError("can't find DNS entry for %s in cache", name);
return nullptr; return nullptr;
case DNS_DEFAULT: case DNS_DEFAULT:
requests.push_back(new DNS_Mgr_Request(name, AF_INET, false)); requests.push_back(new DNS_Mgr_Request(name, AF_INET, false));
requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false)); requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false));
Resolve(); Resolve();
return LookupHost(name); return LookupHost(name);
default: default:
reporter->InternalError("bad mode in DNS_Mgr::LookupHost"); reporter->InternalError("bad mode in DNS_Mgr::LookupHost");
return nullptr; return nullptr;
} }
} }
ValPtr DNS_Mgr::LookupAddr(const IPAddr& addr) ValPtr DNS_Mgr::LookupAddr(const IPAddr& addr)
@ -565,30 +558,28 @@ ValPtr DNS_Mgr::LookupAddr(const IPAddr& addr)
} }
// Not found, or priming. // Not found, or priming.
switch ( mode ) { switch ( mode )
case DNS_PRIME: {
requests.push_back(new DNS_Mgr_Request(addr)); case DNS_PRIME:
return make_intrusive<StringVal>("<none>"); requests.push_back(new DNS_Mgr_Request(addr));
return make_intrusive<StringVal>("<none>");
case DNS_FORCE: case DNS_FORCE:
reporter->FatalError("can't find DNS entry for %s in cache", reporter->FatalError("can't find DNS entry for %s in cache", addr.AsString().c_str());
addr.AsString().c_str()); return nullptr;
return nullptr;
case DNS_DEFAULT: case DNS_DEFAULT:
requests.push_back(new DNS_Mgr_Request(addr)); requests.push_back(new DNS_Mgr_Request(addr));
Resolve(); Resolve();
return LookupAddr(addr); return LookupAddr(addr);
default: default:
reporter->InternalError("bad mode in DNS_Mgr::LookupAddr"); reporter->InternalError("bad mode in DNS_Mgr::LookupAddr");
return nullptr; return nullptr;
} }
} }
void DNS_Mgr::Verify() void DNS_Mgr::Verify() { }
{
}
#define MAX_PENDING_REQUESTS 20 #define MAX_PENDING_REQUESTS 20
@ -628,8 +619,7 @@ void DNS_Mgr::Resolve()
} }
first_req = last_req + 1; first_req = last_req + 1;
num_pending = min(requests.length() - first_req, num_pending = min(requests.length() - first_req, MAX_PENDING_REQUESTS);
MAX_PENDING_REQUESTS);
last_req = first_req + num_pending - 1; last_req = first_req + num_pending - 1;
for ( i = first_req; i <= last_req; ++i ) for ( i = first_req; i <= last_req; ++i )
@ -642,12 +632,10 @@ void DNS_Mgr::Resolve()
struct nb_dns_result r; struct nb_dns_result r;
status = nb_dns_activity(nb_dns, &r, err); status = nb_dns_activity(nb_dns, &r, err);
if ( status < 0 ) if ( status < 0 )
reporter->Warning( reporter->Warning("NB-DNS error in DNS_Mgr::WaitForReplies (%s)", err);
"NB-DNS error in DNS_Mgr::WaitForReplies (%s)",
err);
else if ( status > 0 ) else if ( status > 0 )
{ {
DNS_Mgr_Request* dr = (DNS_Mgr_Request*) r.cookie; DNS_Mgr_Request* dr = (DNS_Mgr_Request*)r.cookie;
if ( dr->RequestPending() ) if ( dr->RequestPending() )
{ {
AddResult(dr, &r); AddResult(dr, &r);
@ -697,8 +685,7 @@ void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* dm)
event_mgr.Enqueue(e, BuildMappingVal(dm)); event_mgr.Enqueue(e, BuildMappingVal(dm));
} }
void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* dm, void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* dm, ListValPtr l1, ListValPtr l2)
ListValPtr l1, ListValPtr l2)
{ {
if ( ! e ) if ( ! e )
return; return;
@ -767,11 +754,9 @@ void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r)
HostMap::iterator it = host_mappings.find(dr->ReqHost()); HostMap::iterator it = host_mappings.find(dr->ReqHost());
if ( it == host_mappings.end() ) if ( it == host_mappings.end() )
{ {
host_mappings[dr->ReqHost()].first = host_mappings[dr->ReqHost()].first = new_dm->Type() == AF_INET ? new_dm : nullptr;
new_dm->Type() == AF_INET ? new_dm : nullptr;
host_mappings[dr->ReqHost()].second = host_mappings[dr->ReqHost()].second = new_dm->Type() == AF_INET ? nullptr : new_dm;
new_dm->Type() == AF_INET ? nullptr : new_dm;
} }
else else
{ {
@ -1029,15 +1014,13 @@ const char* DNS_Mgr::LookupTextInCache(const string& name)
return d->names ? d->names[0] : "<\?\?\?>"; return d->names ? d->names[0] : "<\?\?\?>";
} }
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback, static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback, TableValPtr result)
TableValPtr result)
{ {
callback->Resolved(result.get()); callback->Resolved(result.get());
delete callback; delete callback;
} }
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback, static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback, const char* result)
const char* result)
{ {
callback->Resolved(result); callback->Resolved(result);
delete callback; delete callback;
@ -1184,15 +1167,16 @@ void DNS_Mgr::IssueAsyncRequests()
if ( req->IsAddrReq() ) if ( req->IsAddrReq() )
success = DoRequest(nb_dns, new DNS_Mgr_Request(req->host)); success = DoRequest(nb_dns, new DNS_Mgr_Request(req->host));
else if ( req->is_txt ) else if ( req->is_txt )
success = DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), success =
AF_INET, req->is_txt)); DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), AF_INET, req->is_txt));
else else
{ {
// If only one request type succeeds, don't consider it a failure. // If only one request type succeeds, don't consider it a failure.
success = DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), success =
AF_INET, req->is_txt)); DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), AF_INET, req->is_txt));
success = DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), success =
AF_INET6, req->is_txt)) || success; DoRequest(nb_dns, new DNS_Mgr_Request(req->name.c_str(), AF_INET6, req->is_txt)) ||
success;
} }
if ( ! success ) if ( ! success )
@ -1241,7 +1225,6 @@ void DNS_Mgr::CheckAsyncAddrRequest(const IPAddr& addr, bool timeout)
// Don't delete the request. That will be done once it // Don't delete the request. That will be done once it
// eventually times out. // eventually times out.
} }
} }
void DNS_Mgr::CheckAsyncTextRequest(const char* host, bool timeout) void DNS_Mgr::CheckAsyncTextRequest(const char* host, bool timeout)
@ -1378,11 +1361,10 @@ void DNS_Mgr::Process()
else if ( status > 0 ) else if ( status > 0 )
{ {
DNS_Mgr_Request* dr = (DNS_Mgr_Request*) r.cookie; DNS_Mgr_Request* dr = (DNS_Mgr_Request*)r.cookie;
bool do_host_timeout = true; bool do_host_timeout = true;
if ( dr->ReqHost() && if ( dr->ReqHost() && host_mappings.find(dr->ReqHost()) == host_mappings.end() )
host_mappings.find(dr->ReqHost()) == host_mappings.end() )
// Don't timeout when this is the first result in an expected pair // Don't timeout when this is the first result in an expected pair
// (one result each for A and AAAA queries). // (one result each for A and AAAA queries).
do_host_timeout = false; do_host_timeout = false;
@ -1427,7 +1409,7 @@ int DNS_Mgr::AnswerAvailable(int timeout)
t.tv_sec = timeout; t.tv_sec = timeout;
t.tv_usec = 0; t.tv_usec = 0;
int status = select(fd+1, &read_fds, 0, 0, &t); int status = select(fd + 1, &read_fds, 0, 0, &t);
if ( status < 0 ) if ( status < 0 )
{ {
@ -1463,4 +1445,4 @@ void DNS_Mgr::Terminate()
iosource_mgr->UnregisterFd(nb_dns_fd(nb_dns), this); iosource_mgr->UnregisterFd(nb_dns_fd(nb_dns), this);
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,4 +1,4 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#pragma once #pragma once
@ -7,13 +7,14 @@
#include <queue> #include <queue>
#include <utility> #include <utility>
#include "zeek/List.h"
#include "zeek/EventHandler.h" #include "zeek/EventHandler.h"
#include "zeek/iosource/IOSource.h"
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
#include "zeek/List.h"
#include "zeek/iosource/IOSource.h"
#include "zeek/util.h" #include "zeek/util.h"
namespace zeek { namespace zeek
{
class EventHandler; class EventHandler;
class RecordType; class RecordType;
@ -26,30 +27,33 @@ using ValPtr = IntrusivePtr<Val>;
using ListValPtr = IntrusivePtr<ListVal>; using ListValPtr = IntrusivePtr<ListVal>;
using TableValPtr = IntrusivePtr<TableVal>; using TableValPtr = IntrusivePtr<TableVal>;
} // namespace zeek } // namespace zeek
// Defined in nb_dns.h // Defined in nb_dns.h
struct nb_dns_info; struct nb_dns_info;
struct nb_dns_result; struct nb_dns_result;
namespace zeek::detail { namespace zeek::detail
{
class DNS_Mgr_Request; class DNS_Mgr_Request;
using DNS_mgr_request_list = PList<DNS_Mgr_Request>; using DNS_mgr_request_list = PList<DNS_Mgr_Request>;
class DNS_Mapping; class DNS_Mapping;
enum DNS_MgrMode { enum DNS_MgrMode
DNS_PRIME, // used to prime the cache {
DNS_FORCE, // internal error if cache miss DNS_PRIME, // used to prime the cache
DNS_DEFAULT, // lookup names as they're requested DNS_FORCE, // internal error if cache miss
DNS_FAKE, // don't look up names, just return dummy results DNS_DEFAULT, // lookup names as they're requested
}; DNS_FAKE, // don't look up names, just return dummy results
};
// Number of seconds we'll wait for a reply. // Number of seconds we'll wait for a reply.
#define DNS_TIMEOUT 5 #define DNS_TIMEOUT 5
class DNS_Mgr final : public iosource::IOSource { class DNS_Mgr final : public iosource::IOSource
{
public: public:
explicit DNS_Mgr(DNS_MgrMode mode); explicit DNS_Mgr(DNS_MgrMode mode);
~DNS_Mgr() override; ~DNS_Mgr() override;
@ -64,7 +68,7 @@ public:
ValPtr LookupAddr(const IPAddr& addr); ValPtr LookupAddr(const IPAddr& addr);
// Define the directory where to store the data. // Define the directory where to store the data.
void SetDir(const char* arg_dir) { dir = util::copy_string(arg_dir); } void SetDir(const char* arg_dir) { dir = util::copy_string(arg_dir); }
void Verify(); void Verify();
void Resolve(); void Resolve();
@ -75,29 +79,31 @@ public:
const char* LookupTextInCache(const std::string& name); const char* LookupTextInCache(const std::string& name);
// Support for async lookups. // Support for async lookups.
class LookupCallback { class LookupCallback
{
public: public:
LookupCallback() { } LookupCallback() { }
virtual ~LookupCallback() { } virtual ~LookupCallback() { }
virtual void Resolved(const char* name) { }; virtual void Resolved(const char* name){};
virtual void Resolved(TableVal* addrs) { }; virtual void Resolved(TableVal* addrs){};
virtual void Timeout() = 0; virtual void Timeout() = 0;
}; };
void AsyncLookupAddr(const IPAddr& host, LookupCallback* callback); void AsyncLookupAddr(const IPAddr& host, LookupCallback* callback);
void AsyncLookupName(const std::string& name, LookupCallback* callback); void AsyncLookupName(const std::string& name, LookupCallback* callback);
void AsyncLookupNameText(const std::string& name, LookupCallback* callback); void AsyncLookupNameText(const std::string& name, LookupCallback* callback);
struct Stats { struct Stats
unsigned long requests; // These count only async requests. {
unsigned long requests; // These count only async requests.
unsigned long successful; unsigned long successful;
unsigned long failed; unsigned long failed;
unsigned long pending; unsigned long pending;
unsigned long cached_hosts; unsigned long cached_hosts;
unsigned long cached_addresses; unsigned long cached_addresses;
unsigned long cached_texts; unsigned long cached_texts;
}; };
void GetStats(Stats* stats); void GetStats(Stats* stats);
@ -108,8 +114,7 @@ protected:
friend class DNS_Mgr_Request; friend class DNS_Mgr_Request;
void Event(EventHandlerPtr e, DNS_Mapping* dm); void Event(EventHandlerPtr e, DNS_Mapping* dm);
void Event(EventHandlerPtr e, DNS_Mapping* dm, void Event(EventHandlerPtr e, DNS_Mapping* dm, ListValPtr l1, ListValPtr l2);
ListValPtr l1, ListValPtr l2);
void Event(EventHandlerPtr e, DNS_Mapping* old_dm, DNS_Mapping* new_dm); void Event(EventHandlerPtr e, DNS_Mapping* old_dm, DNS_Mapping* new_dm);
ValPtr BuildMappingVal(DNS_Mapping* dm); ValPtr BuildMappingVal(DNS_Mapping* dm);
@ -119,7 +124,7 @@ protected:
ListValPtr AddrListDelta(ListVal* al1, ListVal* al2); ListValPtr AddrListDelta(ListVal* al1, ListVal* al2);
void DumpAddrList(FILE* f, ListVal* al); void DumpAddrList(FILE* f, ListVal* al);
typedef std::map<std::string, std::pair<DNS_Mapping*, DNS_Mapping*> > HostMap; typedef std::map<std::string, std::pair<DNS_Mapping*, DNS_Mapping*>> HostMap;
typedef std::map<IPAddr, DNS_Mapping*> AddrMap; typedef std::map<IPAddr, DNS_Mapping*> AddrMap;
typedef std::map<std::string, DNS_Mapping*> TextMap; typedef std::map<std::string, DNS_Mapping*> TextMap;
void LoadCache(FILE* f); void LoadCache(FILE* f);
@ -143,7 +148,7 @@ protected:
// IOSource interface. // IOSource interface.
void Process() override; void Process() override;
void InitSource() override; void InitSource() override;
const char* Tag() override { return "DNS_Mgr"; } const char* Tag() override { return "DNS_Mgr"; }
double GetNextTimeout() override; double GetNextTimeout() override;
DNS_MgrMode mode; DNS_MgrMode mode;
@ -156,7 +161,7 @@ protected:
nb_dns_info* nb_dns; nb_dns_info* nb_dns;
char* cache_name; char* cache_name;
char* dir; // directory in which cache_name resides char* dir; // directory in which cache_name resides
bool did_init; bool did_init;
int asyncs_pending; int asyncs_pending;
@ -165,7 +170,8 @@ protected:
typedef std::list<LookupCallback*> CallbackList; typedef std::list<LookupCallback*> CallbackList;
struct AsyncRequest { struct AsyncRequest
{
double time; double time;
IPAddr host; IPAddr host;
std::string name; std::string name;
@ -175,12 +181,11 @@ protected:
AsyncRequest() : time(0.0), is_txt(false), processed(false) { } AsyncRequest() : time(0.0), is_txt(false), processed(false) { }
bool IsAddrReq() const { return name.empty(); } bool IsAddrReq() const { return name.empty(); }
void Resolved(const char* name) void Resolved(const char* name)
{ {
for ( CallbackList::iterator i = callbacks.begin(); for ( CallbackList::iterator i = callbacks.begin(); i != callbacks.end(); ++i )
i != callbacks.end(); ++i )
{ {
(*i)->Resolved(name); (*i)->Resolved(name);
delete *i; delete *i;
@ -191,8 +196,7 @@ protected:
void Resolved(TableVal* addrs) void Resolved(TableVal* addrs)
{ {
for ( CallbackList::iterator i = callbacks.begin(); for ( CallbackList::iterator i = callbacks.begin(); i != callbacks.end(); ++i )
i != callbacks.end(); ++i )
{ {
(*i)->Resolved(addrs); (*i)->Resolved(addrs);
delete *i; delete *i;
@ -203,8 +207,7 @@ protected:
void Timeout() void Timeout()
{ {
for ( CallbackList::iterator i = callbacks.begin(); for ( CallbackList::iterator i = callbacks.begin(); i != callbacks.end(); ++i )
i != callbacks.end(); ++i )
{ {
(*i)->Timeout(); (*i)->Timeout();
delete *i; delete *i;
@ -212,8 +215,7 @@ protected:
callbacks.clear(); callbacks.clear();
processed = true; processed = true;
} }
};
};
typedef std::map<IPAddr, AsyncRequest*> AsyncRequestAddrMap; typedef std::map<IPAddr, AsyncRequest*> AsyncRequestAddrMap;
AsyncRequestAddrMap asyncs_addrs; AsyncRequestAddrMap asyncs_addrs;
@ -227,21 +229,20 @@ protected:
typedef std::list<AsyncRequest*> QueuedList; typedef std::list<AsyncRequest*> QueuedList;
QueuedList asyncs_queued; QueuedList asyncs_queued;
struct AsyncRequestCompare { struct AsyncRequestCompare
bool operator()(const AsyncRequest* a, const AsyncRequest* b) {
{ bool operator()(const AsyncRequest* a, const AsyncRequest* b) { return a->time > b->time; }
return a->time > b->time; };
}
};
typedef std::priority_queue<AsyncRequest*, std::vector<AsyncRequest*>, AsyncRequestCompare> TimeoutQueue; typedef std::priority_queue<AsyncRequest*, std::vector<AsyncRequest*>, AsyncRequestCompare>
TimeoutQueue;
TimeoutQueue asyncs_timeouts; TimeoutQueue asyncs_timeouts;
unsigned long num_requests; unsigned long num_requests;
unsigned long successful; unsigned long successful;
unsigned long failed; unsigned long failed;
}; };
extern DNS_Mgr* dns_mgr; extern DNS_Mgr* dns_mgr;
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,37 +1,39 @@
// Implementation of breakpoints. // Implementation of breakpoints.
#include "zeek/zeek-config.h"
#include "zeek/DbgBreakpoint.h" #include "zeek/DbgBreakpoint.h"
#include <assert.h> #include <assert.h>
#include "zeek/Desc.h"
#include "zeek/ID.h"
#include "zeek/Debug.h" #include "zeek/Debug.h"
#include "zeek/Scope.h" #include "zeek/Desc.h"
#include "zeek/Frame.h" #include "zeek/Frame.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/Val.h" #include "zeek/ID.h"
#include "zeek/Reporter.h"
#include "zeek/Scope.h"
#include "zeek/Stmt.h" #include "zeek/Stmt.h"
#include "zeek/Timer.h" #include "zeek/Timer.h"
#include "zeek/Reporter.h" #include "zeek/Val.h"
#include "zeek/module_util.h" #include "zeek/module_util.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
// BreakpointTimer used for time-based breakpoints // BreakpointTimer used for time-based breakpoints
class BreakpointTimer final : public Timer { class BreakpointTimer final : public Timer
{
public: public:
BreakpointTimer(DbgBreakpoint* arg_bp, double arg_t) BreakpointTimer(DbgBreakpoint* arg_bp, double arg_t) : Timer(arg_t, TIMER_BREAKPOINT)
: Timer(arg_t, TIMER_BREAKPOINT) {
{ bp = arg_bp; } bp = arg_bp;
}
void Dispatch(double t, bool is_expire) override; void Dispatch(double t, bool is_expire) override;
protected: protected:
DbgBreakpoint* bp; DbgBreakpoint* bp;
}; };
void BreakpointTimer::Dispatch(double t, bool is_expire) void BreakpointTimer::Dispatch(double t, bool is_expire)
{ {
@ -41,7 +43,6 @@ void BreakpointTimer::Dispatch(double t, bool is_expire)
bp->ShouldBreak(t); bp->ShouldBreak(t);
} }
DbgBreakpoint::DbgBreakpoint() DbgBreakpoint::DbgBreakpoint()
{ {
kind = BP_STMT; kind = BP_STMT;
@ -61,7 +62,7 @@ DbgBreakpoint::DbgBreakpoint()
DbgBreakpoint::~DbgBreakpoint() DbgBreakpoint::~DbgBreakpoint()
{ {
SetEnable(false); // clean up any active state SetEnable(false); // clean up any active state
RemoveFromGlobalMap(); RemoveFromGlobalMap();
} }
@ -119,7 +120,6 @@ void DbgBreakpoint::RemoveFromStmt()
at_stmt->DecrBPCount(); at_stmt->DecrBPCount();
} }
bool DbgBreakpoint::SetLocation(ParseLocationRec plr, std::string_view loc_str) bool DbgBreakpoint::SetLocation(ParseLocationRec plr, std::string_view loc_str)
{ {
if ( plr.type == PLR_UNKNOWN ) if ( plr.type == PLR_UNKNOWN )
@ -141,8 +141,7 @@ bool DbgBreakpoint::SetLocation(ParseLocationRec plr, std::string_view loc_str)
} }
at_stmt = plr.stmt; at_stmt = plr.stmt;
snprintf(description, sizeof(description), "%s:%d", snprintf(description, sizeof(description), "%s:%d", source_filename, source_line);
source_filename, source_line);
debug_msg("Breakpoint %d set at %s\n", GetID(), Description()); debug_msg("Breakpoint %d set at %s\n", GetID(), Description());
} }
@ -151,12 +150,11 @@ bool DbgBreakpoint::SetLocation(ParseLocationRec plr, std::string_view loc_str)
{ {
std::string loc_s(loc_str); std::string loc_s(loc_str);
kind = BP_FUNC; kind = BP_FUNC;
function_name = make_full_var_name(current_module.c_str(), function_name = make_full_var_name(current_module.c_str(), loc_s.c_str());
loc_s.c_str());
at_stmt = plr.stmt; at_stmt = plr.stmt;
const Location* loc = at_stmt->GetLocationInfo(); const Location* loc = at_stmt->GetLocationInfo();
snprintf(description, sizeof(description), "%s at %s:%d", snprintf(description, sizeof(description), "%s at %s:%d", function_name.c_str(),
function_name.c_str(), loc->filename, loc->last_line); loc->filename, loc->last_line);
debug_msg("Breakpoint %d set at %s\n", GetID(), Description()); debug_msg("Breakpoint %d set at %s\n", GetID(), Description());
} }
@ -178,8 +176,7 @@ bool DbgBreakpoint::SetLocation(Stmt* stmt)
AddToGlobalMap(); AddToGlobalMap();
const Location* loc = stmt->GetLocationInfo(); const Location* loc = stmt->GetLocationInfo();
snprintf(description, sizeof(description), "%s:%d", snprintf(description, sizeof(description), "%s:%d", loc->filename, loc->last_line);
loc->filename, loc->last_line);
debug_msg("Breakpoint %d set at %s\n", GetID(), Description()); debug_msg("Breakpoint %d set at %s\n", GetID(), Description());
@ -204,19 +201,20 @@ bool DbgBreakpoint::Reset()
{ {
ParseLocationRec plr; ParseLocationRec plr;
switch ( kind ) { switch ( kind )
case BP_TIME: {
debug_msg("Time-based breakpoints not yet supported.\n"); case BP_TIME:
break; debug_msg("Time-based breakpoints not yet supported.\n");
break;
case BP_FUNC: case BP_FUNC:
case BP_STMT: case BP_STMT:
case BP_LINE: case BP_LINE:
plr.type = PLR_FUNCTION; plr.type = PLR_FUNCTION;
//### How to deal with wildcards? //### How to deal with wildcards?
//### perhaps save user choices?--tough... //### perhaps save user choices?--tough...
break; break;
} }
reporter->InternalError("DbgBreakpoint::Reset function incomplete."); reporter->InternalError("DbgBreakpoint::Reset function incomplete.");
@ -252,14 +250,13 @@ BreakCode DbgBreakpoint::HasHit()
if ( ! yes ) if ( ! yes )
{ {
debug_msg("Breakpoint condition '%s' invalid, removing condition.\n", debug_msg("Breakpoint condition '%s' invalid, removing condition.\n",
condition.c_str()); condition.c_str());
SetCondition(""); SetCondition("");
PrintHitMsg(); PrintHitMsg();
return BC_HIT; return BC_HIT;
} }
if ( ! IsIntegral(yes->GetType()->Tag()) && if ( ! IsIntegral(yes->GetType()->Tag()) && ! IsBool(yes->GetType()->Tag()) )
! IsBool(yes->GetType()->Tag()) )
{ {
PrintHitMsg(); PrintHitMsg();
debug_msg("Breakpoint condition should return an integral type"); debug_msg("Breakpoint condition should return an integral type");
@ -295,24 +292,25 @@ BreakCode DbgBreakpoint::ShouldBreak(Stmt* s)
if ( ! IsEnabled() ) if ( ! IsEnabled() )
return BC_NO_HIT; return BC_NO_HIT;
switch ( kind ) { switch ( kind )
case BP_STMT: {
case BP_FUNC: case BP_STMT:
if ( at_stmt != s ) case BP_FUNC:
return BC_NO_HIT; if ( at_stmt != s )
break; return BC_NO_HIT;
break;
case BP_LINE: case BP_LINE:
assert(s->GetLocationInfo()->first_line <= source_line && assert(s->GetLocationInfo()->first_line <= source_line &&
s->GetLocationInfo()->last_line >= source_line); s->GetLocationInfo()->last_line >= source_line);
break; break;
case BP_TIME: case BP_TIME:
assert(false); assert(false);
default: default:
reporter->InternalError("Invalid breakpoint type in DbgBreakpoint::ShouldBreak"); reporter->InternalError("Invalid breakpoint type in DbgBreakpoint::ShouldBreak");
} }
// If we got here, that means that the breakpoint could hit, // If we got here, that means that the breakpoint could hit,
// except potentially if it has a special condition or a repeat count. // except potentially if it has a special condition or a repeat count.
@ -324,7 +322,6 @@ BreakCode DbgBreakpoint::ShouldBreak(Stmt* s)
return code; return code;
} }
BreakCode DbgBreakpoint::ShouldBreak(double t) BreakCode DbgBreakpoint::ShouldBreak(double t)
{ {
if ( kind != BP_TIME ) if ( kind != BP_TIME )
@ -345,32 +342,32 @@ BreakCode DbgBreakpoint::ShouldBreak(double t)
void DbgBreakpoint::PrintHitMsg() void DbgBreakpoint::PrintHitMsg()
{ {
switch ( kind ) { switch ( kind )
case BP_STMT:
case BP_FUNC:
case BP_LINE:
{ {
ODesc d; case BP_STMT:
Frame* f = g_frame_stack.back(); case BP_FUNC:
const ScriptFunc* func = f->GetFunction(); case BP_LINE:
{
ODesc d;
Frame* f = g_frame_stack.back();
const ScriptFunc* func = f->GetFunction();
if ( func ) if ( func )
func->DescribeDebug (&d, f->GetFuncArgs()); func->DescribeDebug(&d, f->GetFuncArgs());
const Location* loc = at_stmt->GetLocationInfo(); const Location* loc = at_stmt->GetLocationInfo();
debug_msg("Breakpoint %d, %s at %s:%d\n", debug_msg("Breakpoint %d, %s at %s:%d\n", GetID(), d.Description(), loc->filename,
GetID(), d.Description(), loc->first_line);
loc->filename, loc->first_line); }
return;
case BP_TIME:
assert(false);
default:
reporter->InternalError("Missed a case in DbgBreakpoint::PrintHitMsg\n");
} }
return;
case BP_TIME:
assert(false);
default:
reporter->InternalError("Missed a case in DbgBreakpoint::PrintHitMsg\n");
}
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -3,34 +3,48 @@
#pragma once #pragma once
#include <string> #include <string>
#include "zeek/util.h" #include "zeek/util.h"
namespace zeek::detail { namespace zeek::detail
{
class Stmt; class Stmt;
class ParseLocationRec; class ParseLocationRec;
enum BreakCode { BC_NO_HIT, BC_HIT, BC_HIT_AND_DELETE }; enum BreakCode
class DbgBreakpoint { {
enum Kind { BP_STMT = 0, BP_FUNC, BP_LINE, BP_TIME }; BC_NO_HIT,
BC_HIT,
BC_HIT_AND_DELETE
};
class DbgBreakpoint
{
enum Kind
{
BP_STMT = 0,
BP_FUNC,
BP_LINE,
BP_TIME
};
public: public:
DbgBreakpoint(); DbgBreakpoint();
~DbgBreakpoint(); ~DbgBreakpoint();
int GetID() const { return BPID; } int GetID() const { return BPID; }
void SetID(int newID) { BPID = newID; } void SetID(int newID) { BPID = newID; }
// True if breakpoint could be set; false otherwise // True if breakpoint could be set; false otherwise
bool SetLocation(ParseLocationRec plr, std::string_view loc_str); bool SetLocation(ParseLocationRec plr, std::string_view loc_str);
bool SetLocation(Stmt* stmt); bool SetLocation(Stmt* stmt);
bool SetLocation(double time); bool SetLocation(double time);
bool Reset(); // cancel and re-apply bpt when restarting execution bool Reset(); // cancel and re-apply bpt when restarting execution
// Temporary = disable (remove?) the breakpoint right after it's hit. // Temporary = disable (remove?) the breakpoint right after it's hit.
bool IsTemporary() const { return temporary; } bool IsTemporary() const { return temporary; }
void SetTemporary(bool is_temporary) { temporary = is_temporary; } void SetTemporary(bool is_temporary) { temporary = is_temporary; }
// Feed it a Stmt* or a time and see if this breakpoint should // Feed it a Stmt* or a time and see if this breakpoint should
// hit. bcHitAndDelete means that it has hit, and should now be // hit. bcHitAndDelete means that it has hit, and should now be
@ -41,17 +55,17 @@ public:
BreakCode ShouldBreak(Stmt* s); BreakCode ShouldBreak(Stmt* s);
BreakCode ShouldBreak(double t); BreakCode ShouldBreak(double t);
const std::string& GetCondition() const { return condition; } const std::string& GetCondition() const { return condition; }
bool SetCondition(const std::string& new_condition); bool SetCondition(const std::string& new_condition);
int GetRepeatCount() const { return repeat_count; } int GetRepeatCount() const { return repeat_count; }
bool SetRepeatCount(int count); // implements function of ignore command in gdb bool SetRepeatCount(int count); // implements function of ignore command in gdb
bool IsEnabled() const { return enabled; } bool IsEnabled() const { return enabled; }
bool SetEnable(bool do_enable); bool SetEnable(bool do_enable);
// e.g. "FooBar() at foo.c:23" // e.g. "FooBar() at foo.c:23"
const char * Description() const { return description; } const char* Description() const { return description; }
protected: protected:
void AddToGlobalMap(); void AddToGlobalMap();
@ -60,27 +74,27 @@ protected:
void AddToStmt(); void AddToStmt();
void RemoveFromStmt(); void RemoveFromStmt();
BreakCode HasHit(); // a breakpoint hit, update state, return proper code. BreakCode HasHit(); // a breakpoint hit, update state, return proper code.
void PrintHitMsg(); // display reason when the breakpoint hits void PrintHitMsg(); // display reason when the breakpoint hits
Kind kind; Kind kind;
int32_t BPID; int32_t BPID;
char description[512]; char description[512];
std::string function_name; // location std::string function_name; // location
const char* source_filename; const char* source_filename;
int32_t source_line; int32_t source_line;
bool enabled; // ### comment this and next bool enabled; // ### comment this and next
bool temporary; bool temporary;
Stmt* at_stmt; Stmt* at_stmt;
double at_time; // break when the virtual time is this double at_time; // break when the virtual time is this
// Support for conditional and N'th time breakpoints. // Support for conditional and N'th time breakpoints.
int32_t repeat_count; // if positive, break after this many hits int32_t repeat_count; // if positive, break after this many hits
int32_t hit_count; // how many times it's been hit (w/o breaking) int32_t hit_count; // how many times it's been hit (w/o breaking)
std::string condition; // condition to evaluate; nil for none std::string condition; // condition to evaluate; nil for none
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,16 +2,18 @@
#pragma once #pragma once
namespace zeek::detail { namespace zeek::detail
{
class Expr; class Expr;
// Automatic displays: display these at each stoppage. // Automatic displays: display these at each stoppage.
class DbgDisplay { class DbgDisplay
{
public: public:
DbgDisplay(Expr* expr_to_display); DbgDisplay(Expr* expr_to_display);
bool IsEnabled() { return enabled; } bool IsEnabled() { return enabled; }
bool SetEnable(bool do_enable) bool SetEnable(bool do_enable)
{ {
bool old_value = enabled; bool old_value = enabled;
@ -19,11 +21,11 @@ public:
return old_value; return old_value;
} }
const Expr* Expression() const { return expression; } const Expr* Expression() const { return expression; }
protected: protected:
bool enabled; bool enabled;
Expr* expression; Expr* expression;
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,5 +1,4 @@
// Bro Debugger Help // Bro Debugger Help
#include "zeek/zeek-config.h"
#include "zeek/Debug.h" #include "zeek/Debug.h"
#include "zeek/zeek-config.h"

View file

@ -1,12 +1,13 @@
// Implementation of watches // Implementation of watches
#include "zeek/zeek-config.h"
#include "zeek/DbgWatch.h" #include "zeek/DbgWatch.h"
#include "zeek/Debug.h" #include "zeek/Debug.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
// Support classes // Support classes
DbgWatch::DbgWatch(zeek::Obj* var_to_watch) DbgWatch::DbgWatch(zeek::Obj* var_to_watch)
@ -19,4 +20,4 @@ DbgWatch::DbgWatch(Expr* expr_to_watch)
reporter->InternalError("DbgWatch unimplemented"); reporter->InternalError("DbgWatch unimplemented");
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -4,13 +4,18 @@
#include "zeek/util.h" #include "zeek/util.h"
namespace zeek { class Obj; } namespace zeek
{
class Obj;
}
namespace zeek::detail { namespace zeek::detail
{
class Expr; class Expr;
class DbgWatch { class DbgWatch
{
public: public:
explicit DbgWatch(Obj* var_to_watch); explicit DbgWatch(Obj* var_to_watch);
explicit DbgWatch(Expr* expr_to_watch); explicit DbgWatch(Expr* expr_to_watch);
@ -19,6 +24,6 @@ public:
protected: protected:
Obj* var; Obj* var;
Expr* expr; Expr* expr;
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,42 +1,41 @@
// Debugging support for Bro policy files. // Debugging support for Bro policy files.
#include "zeek/zeek-config.h"
#include "zeek/Debug.h" #include "zeek/Debug.h"
#include <stdio.h>
#include <stdarg.h>
#include <signal.h>
#include <ctype.h> #include <ctype.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string> #include <string>
#include "zeek/zeek-config.h"
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
#include <readline/readline.h>
#endif #endif
#include "zeek/util.h"
#include "zeek/DebugCmds.h"
#include "zeek/DbgBreakpoint.h" #include "zeek/DbgBreakpoint.h"
#include "zeek/ID.h" #include "zeek/DebugCmds.h"
#include "zeek/IntrusivePtr.h" #include "zeek/Desc.h"
#include "zeek/Expr.h" #include "zeek/Expr.h"
#include "zeek/Stmt.h"
#include "zeek/Frame.h" #include "zeek/Frame.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/ID.h"
#include "zeek/IntrusivePtr.h" #include "zeek/IntrusivePtr.h"
#include "zeek/Scope.h"
#include "zeek/PolicyFile.h" #include "zeek/PolicyFile.h"
#include "zeek/Desc.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/Scope.h"
#include "zeek/Stmt.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/module_util.h"
#include "zeek/input.h" #include "zeek/input.h"
#include "zeek/module_util.h"
#include "zeek/util.h"
extern "C" { extern "C"
{
#include "zeek/setsignal.h" #include "zeek/setsignal.h"
} }
using namespace std; using namespace std;
@ -63,11 +62,12 @@ struct yy_buffer_state;
typedef struct yy_buffer_state* YY_BUFFER_STATE; typedef struct yy_buffer_state* YY_BUFFER_STATE;
YY_BUFFER_STATE bro_scan_string(const char*); YY_BUFFER_STATE bro_scan_string(const char*);
extern YYLTYPE yylloc; // holds start line and column of token extern YYLTYPE yylloc; // holds start line and column of token
extern int line_number; extern int line_number;
extern const char* filename; extern const char* filename;
namespace zeek::detail { namespace zeek::detail
{
DebuggerState::DebuggerState() DebuggerState::DebuggerState()
{ {
@ -88,15 +88,13 @@ DebuggerState::~DebuggerState()
bool StmtLocMapping::StartsAfter(const StmtLocMapping* m2) bool StmtLocMapping::StartsAfter(const StmtLocMapping* m2)
{ {
if ( ! m2 ) if ( ! m2 )
reporter->InternalError("Assertion failed: m2 != 0"); reporter->InternalError("Assertion failed: m2 != 0");
return loc.first_line > m2->loc.first_line || return loc.first_line > m2->loc.first_line ||
(loc.first_line == m2->loc.first_line && (loc.first_line == m2->loc.first_line && loc.first_column > m2->loc.first_column);
loc.first_column > m2->loc.first_column);
} }
// Generic debug message output. // Generic debug message output.
int debug_msg(const char* fmt, ...) int debug_msg(const char* fmt, ...)
{ {
@ -110,7 +108,6 @@ int debug_msg(const char* fmt, ...)
return retval; return retval;
} }
// Trace message output // Trace message output
FILE* TraceState::SetTraceFile(const char* trace_filename) FILE* TraceState::SetTraceFile(const char* trace_filename)
@ -195,7 +192,6 @@ int TraceState::LogTrace(const char* fmt, ...)
return retval; return retval;
} }
// Helper functions. // Helper functions.
void get_first_statement(Stmt* list, Stmt*& first, Location& loc) void get_first_statement(Stmt* list, Stmt*& first, Location& loc)
{ {
@ -217,8 +213,8 @@ void get_first_statement(Stmt* list, Stmt*& first, Location& loc)
loc = *first->GetLocationInfo(); loc = *first->GetLocationInfo();
} }
static void parse_function_name(vector<ParseLocationRec>& result, static void parse_function_name(vector<ParseLocationRec>& result, ParseLocationRec& plr,
ParseLocationRec& plr, const string& s) const string& s)
{ // function name { // function name
const auto& id = lookup_ID(s.c_str(), current_module.c_str()); const auto& id = lookup_ID(s.c_str(), current_module.c_str());
@ -254,7 +250,7 @@ static void parse_function_name(vector<ParseLocationRec>& result,
return; return;
} }
Stmt* body = nullptr; // the particular body we care about; 0 = all Stmt* body = nullptr; // the particular body we care about; 0 = all
if ( bodies.size() == 1 ) if ( bodies.size() == 1 )
body = bodies[0].stmts.get(); body = bodies[0].stmts.get();
@ -263,13 +259,13 @@ static void parse_function_name(vector<ParseLocationRec>& result,
while ( true ) while ( true )
{ {
debug_msg("There are multiple definitions of that event handler.\n" debug_msg("There are multiple definitions of that event handler.\n"
"Please choose one of the following options:\n"); "Please choose one of the following options:\n");
for ( unsigned int i = 0; i < bodies.size(); ++i ) for ( unsigned int i = 0; i < bodies.size(); ++i )
{ {
Stmt* first; Stmt* first;
Location stmt_loc; Location stmt_loc;
get_first_statement(bodies[i].stmts.get(), first, stmt_loc); get_first_statement(bodies[i].stmts.get(), first, stmt_loc);
debug_msg("[%d] %s:%d\n", i+1, stmt_loc.filename, stmt_loc.first_line); debug_msg("[%d] %s:%d\n", i + 1, stmt_loc.filename, stmt_loc.first_line);
} }
debug_msg("[a] All of the above\n"); debug_msg("[a] All of the above\n");
@ -298,7 +294,7 @@ static void parse_function_name(vector<ParseLocationRec>& result,
} }
int option = atoi(input.c_str()); int option = atoi(input.c_str());
if ( option > 0 && option <= (int) bodies.size() ) if ( option > 0 && option <= (int)bodies.size() )
{ {
body = bodies[option - 1].stmts.get(); body = bodies[option - 1].stmts.get();
break; break;
@ -394,7 +390,7 @@ vector<ParseLocationRec> parse_location_string(const string& s)
auto iter = g_dbgfilemaps.find(loc_filename); auto iter = g_dbgfilemaps.find(loc_filename);
if ( iter == g_dbgfilemaps.end() ) if ( iter == g_dbgfilemaps.end() )
reporter->InternalError("Policy file %s should have been loaded\n", reporter->InternalError("Policy file %s should have been loaded\n",
loc_filename.data()); loc_filename.data());
if ( plr.line > how_many_lines_in(loc_filename.data()) ) if ( plr.line > how_many_lines_in(loc_filename.data()) )
{ {
@ -411,8 +407,7 @@ vector<ParseLocationRec> parse_location_string(const string& s)
if ( entry->Loc().first_line > plr.line ) if ( entry->Loc().first_line > plr.line )
break; break;
if ( plr.line >= entry->Loc().first_line && if ( plr.line >= entry->Loc().first_line && plr.line <= entry->Loc().last_line )
plr.line <= entry->Loc().last_line )
{ {
hit = entry; hit = entry;
break; break;
@ -428,7 +423,6 @@ vector<ParseLocationRec> parse_location_string(const string& s)
return result; return result;
} }
// Interactive debugging console. // Interactive debugging console.
static int dbg_dispatch_cmd(DebugCmd cmd_code, const vector<string>& args); static int dbg_dispatch_cmd(DebugCmd cmd_code, const vector<string>& args);
@ -458,7 +452,7 @@ void break_signal(int)
int dbg_init_debugger(const char* cmdfile) int dbg_init_debugger(const char* cmdfile)
{ {
if ( ! g_policy_debug ) if ( ! g_policy_debug )
return 0; // probably shouldn't have been called return 0; // probably shouldn't have been called
init_global_dbg_constants(); init_global_dbg_constants();
@ -469,7 +463,7 @@ int dbg_init_debugger(const char* cmdfile)
// ### Implement this // ### Implement this
debug_msg("Command files not supported. Using interactive mode.\n"); debug_msg("Command files not supported. Using interactive mode.\n");
// ### if ( interactive ) (i.e., not reading cmds from a file) // ### if ( interactive ) (i.e., not reading cmds from a file)
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
init_readline(); init_readline();
#endif #endif
@ -486,7 +480,6 @@ int dbg_shutdown_debugger()
return 1; return 1;
} }
// Umesh: I stole this code from libedit; I modified it here to use // Umesh: I stole this code from libedit; I modified it here to use
// <string>s to avoid memory management problems. The main command is returned // <string>s to avoid memory management problems. The main command is returned
// by the operation argument; the additional arguments are put in the // by the operation argument; the additional arguments are put in the
@ -501,9 +494,9 @@ void tokenize(const char* cstr, string& operation, vector<string>& arguments)
char delim = '\0'; char delim = '\0';
const string str(cstr); const string str(cstr);
for ( int i = 0; i < (signed int) str.length(); ++i ) for ( int i = 0; i < (signed int)str.length(); ++i )
{ {
while ( isspace((unsigned char) str[i]) ) while ( isspace((unsigned char)str[i]) )
++i; ++i;
int start = i; int start = i;
@ -512,7 +505,7 @@ void tokenize(const char* cstr, string& operation, vector<string>& arguments)
{ {
if ( str[i] == '\\' ) if ( str[i] == '\\' )
{ {
if ( i < (signed int) str.length() ) if ( i < (signed int)str.length() )
++i; ++i;
} }
@ -544,7 +537,6 @@ void tokenize(const char* cstr, string& operation, vector<string>& arguments)
} }
} }
// Given a command string, parse it and send the command to be dispatched. // Given a command string, parse it and send the command to be dispatched.
int dbg_execute_command(const char* cmd) int dbg_execute_command(const char* cmd)
{ {
@ -563,8 +555,7 @@ int dbg_execute_command(const char* cmd)
if ( ! entry ) if ( ! entry )
return 0; return 0;
const DebugCmdInfo* info = const DebugCmdInfo* info = (const DebugCmdInfo*)entry->data;
(const DebugCmdInfo*) entry->data;
if ( info && info->Repeatable() ) if ( info && info->Repeatable() )
{ {
@ -585,7 +576,7 @@ int dbg_execute_command(const char* cmd)
vector<string> arguments; vector<string> arguments;
tokenize(localcmd, opstring, arguments); tokenize(localcmd, opstring, arguments);
delete [] localcmd; delete[] localcmd;
// Make sure we know this op name. // Make sure we know this op name.
auto matching_cmds_buf = std::make_unique<const char*[]>(num_debug_cmds()); auto matching_cmds_buf = std::make_unique<const char*[]>(num_debug_cmds());
@ -614,7 +605,7 @@ int dbg_execute_command(const char* cmd)
for ( int i = 0; i < num_debug_cmds(); ++i ) for ( int i = 0; i < num_debug_cmds(); ++i )
if ( matching_cmds[i] ) if ( matching_cmds[i] )
{ {
cmd_code = (DebugCmd) i; cmd_code = (DebugCmd)i;
break; break;
} }
@ -628,9 +619,9 @@ int dbg_execute_command(const char* cmd)
* http://tiswww.case.edu/php/chet/readline/history.html * http://tiswww.case.edu/php/chet/readline/history.html
* suggests that it's safe to assume it's really const char*. * suggests that it's safe to assume it's really const char*.
*/ */
add_history((char *) cmd); add_history((char*)cmd);
HISTORY_STATE* state = history_get_history_state(); HISTORY_STATE* state = history_get_history_state();
state->entries[state->length-1]->data = (histdata_t *) get_debug_cmd_info(cmd_code); state->entries[state->length - 1]->data = (histdata_t*)get_debug_cmd_info(cmd_code);
} }
#endif #endif
@ -643,11 +634,11 @@ int dbg_execute_command(const char* cmd)
return retcode; return retcode;
const DebugCmdInfo* info = get_debug_cmd_info(cmd_code); const DebugCmdInfo* info = get_debug_cmd_info(cmd_code);
if ( ! info ) if ( ! info )
reporter->InternalError("Assertion failed: info"); reporter->InternalError("Assertion failed: info");
if ( ! info ) if ( ! info )
return -2; // ### yuck, why -2? return -2; // ### yuck, why -2?
return info->ResumeExecution(); return info->ResumeExecution();
} }
@ -655,85 +646,86 @@ int dbg_execute_command(const char* cmd)
// Call the appropriate function for the command. // Call the appropriate function for the command.
static int dbg_dispatch_cmd(DebugCmd cmd_code, const vector<string>& args) static int dbg_dispatch_cmd(DebugCmd cmd_code, const vector<string>& args)
{ {
switch ( cmd_code ) { switch ( cmd_code )
case dcHelp: {
dbg_cmd_help(cmd_code, args); case dcHelp:
break; dbg_cmd_help(cmd_code, args);
break;
case dcQuit: case dcQuit:
debug_msg("Program Terminating\n"); debug_msg("Program Terminating\n");
exit(0); exit(0);
case dcNext: case dcNext:
g_frame_stack.back()->BreakBeforeNextStmt(true); g_frame_stack.back()->BreakBeforeNextStmt(true);
step_or_next_pending = true; step_or_next_pending = true;
last_frame = g_frame_stack.back(); last_frame = g_frame_stack.back();
break; break;
case dcStep: case dcStep:
g_debugger_state.BreakBeforeNextStmt(true); g_debugger_state.BreakBeforeNextStmt(true);
step_or_next_pending = true; step_or_next_pending = true;
last_frame = g_frame_stack.back(); last_frame = g_frame_stack.back();
break; break;
case dcContinue: case dcContinue:
g_debugger_state.BreakBeforeNextStmt(false); g_debugger_state.BreakBeforeNextStmt(false);
debug_msg("Continuing.\n"); debug_msg("Continuing.\n");
break; break;
case dcFinish: case dcFinish:
g_frame_stack.back()->BreakOnReturn(true); g_frame_stack.back()->BreakOnReturn(true);
g_debugger_state.BreakBeforeNextStmt(false); g_debugger_state.BreakBeforeNextStmt(false);
break; break;
case dcBreak: case dcBreak:
dbg_cmd_break(cmd_code, args); dbg_cmd_break(cmd_code, args);
break; break;
case dcBreakCondition: case dcBreakCondition:
dbg_cmd_break_condition(cmd_code, args); dbg_cmd_break_condition(cmd_code, args);
break; break;
case dcDeleteBreak: case dcDeleteBreak:
case dcClearBreak: case dcClearBreak:
case dcDisableBreak: case dcDisableBreak:
case dcEnableBreak: case dcEnableBreak:
case dcIgnoreBreak: case dcIgnoreBreak:
dbg_cmd_break_set_state(cmd_code, args); dbg_cmd_break_set_state(cmd_code, args);
break; break;
case dcPrint: case dcPrint:
dbg_cmd_print(cmd_code, args); dbg_cmd_print(cmd_code, args);
break; break;
case dcBacktrace: case dcBacktrace:
return dbg_cmd_backtrace(cmd_code, args); return dbg_cmd_backtrace(cmd_code, args);
case dcFrame: case dcFrame:
case dcUp: case dcUp:
case dcDown: case dcDown:
return dbg_cmd_frame(cmd_code, args); return dbg_cmd_frame(cmd_code, args);
case dcInfo: case dcInfo:
return dbg_cmd_info(cmd_code, args); return dbg_cmd_info(cmd_code, args);
case dcList: case dcList:
return dbg_cmd_list(cmd_code, args); return dbg_cmd_list(cmd_code, args);
case dcDisplay: case dcDisplay:
case dcUndisplay: case dcUndisplay:
debug_msg("Command not yet implemented.\n"); debug_msg("Command not yet implemented.\n");
break; break;
case dcTrace: case dcTrace:
return dbg_cmd_trace(cmd_code, args); return dbg_cmd_trace(cmd_code, args);
default: default:
debug_msg("INTERNAL ERROR: " debug_msg("INTERNAL ERROR: "
"Got an unknown debugger command in DbgDispatchCmd: %d\n", "Got an unknown debugger command in DbgDispatchCmd: %d\n",
cmd_code); cmd_code);
return 0; return 0;
} }
return 0; return 0;
} }
@ -772,11 +764,10 @@ string get_context_description(const Stmt* stmt, const Frame* frame)
size_t buf_size = strlen(d.Description()) + strlen(loc.filename) + 1024; size_t buf_size = strlen(d.Description()) + strlen(loc.filename) + 1024;
char* buf = new char[buf_size]; char* buf = new char[buf_size];
snprintf(buf, buf_size, "In %s at %s:%d", snprintf(buf, buf_size, "In %s at %s:%d", d.Description(), loc.filename, loc.last_line);
d.Description(), loc.filename, loc.last_line);
string retval(buf); string retval(buf);
delete [] buf; delete[] buf;
return retval; return retval;
} }
@ -807,29 +798,27 @@ int dbg_handle_debug_input()
if ( ! step_or_next_pending || g_frame_stack.back() != last_frame ) if ( ! step_or_next_pending || g_frame_stack.back() != last_frame )
{ {
string context = string context = get_context_description(stmt, g_frame_stack.back());
get_context_description(stmt, g_frame_stack.back());
debug_msg("%s\n", context.c_str()); debug_msg("%s\n", context.c_str());
} }
step_or_next_pending = false; step_or_next_pending = false;
PrintLines(loc.filename, loc.first_line, PrintLines(loc.filename, loc.first_line, loc.last_line - loc.first_line + 1, true);
loc.last_line - loc.first_line + 1, true);
g_debugger_state.last_loc = loc; g_debugger_state.last_loc = loc;
do do
{ {
// readline returns a pointer to a buffer it allocates; it's // readline returns a pointer to a buffer it allocates; it's
// freed at the bottom. // freed at the bottom.
#ifdef HAVE_READLINE #ifdef HAVE_READLINE
input_line = readline(get_prompt()); input_line = readline(get_prompt());
#else #else
printf ("%s", get_prompt()); printf("%s", get_prompt());
// readline uses malloc, and we want to be consistent // readline uses malloc, and we want to be consistent
// with it. // with it.
input_line = (char*) util::safe_malloc(1024); input_line = (char*)util::safe_malloc(1024);
input_line[1023] = 0; input_line[1023] = 0;
// ### Maybe it's not always stdin. // ### Maybe it's not always stdin.
input_line = fgets(input_line, 1023, stdin); input_line = fgets(input_line, 1023, stdin);
@ -843,13 +832,12 @@ int dbg_handle_debug_input()
if ( input_line ) if ( input_line )
{ {
free(input_line); // this was malloc'ed free(input_line); // this was malloc'ed
input_line = nullptr; input_line = nullptr;
} }
else else
exit(0); exit(0);
} } while ( status == 0 );
while ( status == 0 );
// Clear out some state. ### Is there a better place? // Clear out some state. ### Is there a better place?
g_debugger_state.curr_frame_idx = 0; g_debugger_state.curr_frame_idx = 0;
@ -861,12 +849,10 @@ int dbg_handle_debug_input()
return 0; return 0;
} }
// Return true to continue execution, false to abort. // Return true to continue execution, false to abort.
bool pre_execute_stmt(Stmt* stmt, Frame* f) bool pre_execute_stmt(Stmt* stmt, Frame* f)
{ {
if ( ! g_policy_debug || if ( ! g_policy_debug || stmt->Tag() == STMT_LIST || stmt->Tag() == STMT_NULL )
stmt->Tag() == STMT_LIST || stmt->Tag() == STMT_NULL )
return true; return true;
if ( g_trace_state.DoTrace() ) if ( g_trace_state.DoTrace() )
@ -888,8 +874,7 @@ bool pre_execute_stmt(Stmt* stmt, Frame* f)
bool should_break = false; bool should_break = false;
if ( g_debugger_state.BreakBeforeNextStmt() || if ( g_debugger_state.BreakBeforeNextStmt() || f->BreakBeforeNextStmt() )
f->BreakBeforeNextStmt() )
{ {
if ( g_debugger_state.BreakBeforeNextStmt() ) if ( g_debugger_state.BreakBeforeNextStmt() )
g_debugger_state.BreakBeforeNextStmt(false); g_debugger_state.BreakBeforeNextStmt(false);
@ -912,7 +897,7 @@ bool pre_execute_stmt(Stmt* stmt, Frame* f)
for ( BPMapType::iterator i = p.first; i != p.second; ++i ) for ( BPMapType::iterator i = p.first; i != p.second; ++i )
{ {
int break_code = i->second->ShouldBreak(stmt); int break_code = i->second->ShouldBreak(stmt);
if ( break_code == 2 ) // ### 2? if ( break_code == 2 ) // ### 2?
{ {
i->second->SetEnable(false); i->second->SetEnable(false);
delete i->second; delete i->second;
@ -960,14 +945,14 @@ ValPtr dbg_eval_expr(const char* expr)
// Push the current frame's associated scope. // Push the current frame's associated scope.
// Note: g_debugger_state.curr_frame_idx is the user-visible number, // Note: g_debugger_state.curr_frame_idx is the user-visible number,
// while the array index goes in the opposite direction // while the array index goes in the opposite direction
int frame_idx = int frame_idx = (g_frame_stack.size() - 1) - g_debugger_state.curr_frame_idx;
(g_frame_stack.size() - 1) - g_debugger_state.curr_frame_idx;
if ( ! (frame_idx >= 0 && (unsigned) frame_idx < g_frame_stack.size()) ) if ( ! (frame_idx >= 0 && (unsigned)frame_idx < g_frame_stack.size()) )
reporter->InternalError("Assertion failed: frame_idx >= 0 && (unsigned) frame_idx < g_frame_stack.size()"); reporter->InternalError(
"Assertion failed: frame_idx >= 0 && (unsigned) frame_idx < g_frame_stack.size()");
Frame* frame = g_frame_stack[frame_idx]; Frame* frame = g_frame_stack[frame_idx];
if ( ! (frame) ) if ( ! (frame) )
reporter->InternalError("Assertion failed: frame"); reporter->InternalError("Assertion failed: frame");
const ScriptFunc* func = frame->GetFunction(); const ScriptFunc* func = frame->GetFunction();
@ -1009,11 +994,11 @@ ValPtr dbg_eval_expr(const char* expr)
delete g_curr_debug_expr; delete g_curr_debug_expr;
g_curr_debug_expr = nullptr; g_curr_debug_expr = nullptr;
delete [] g_curr_debug_error; delete[] g_curr_debug_error;
g_curr_debug_error = nullptr; g_curr_debug_error = nullptr;
in_debug = false; in_debug = false;
return result; return result;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,16 +2,17 @@
#pragma once #pragma once
#include <vector> #include <deque>
#include <map> #include <map>
#include <string> #include <string>
#include <deque> #include <vector>
#include "zeek/Obj.h" #include "zeek/Obj.h"
#include "zeek/StmtEnums.h" #include "zeek/StmtEnums.h"
#include "zeek/util.h" #include "zeek/util.h"
namespace zeek { namespace zeek
{
class Val; class Val;
template <class T> class IntrusivePtr; template <class T> class IntrusivePtr;
@ -19,7 +20,8 @@ using ValPtr = zeek::IntrusivePtr<Val>;
extern std::string current_module; extern std::string current_module;
namespace detail { namespace detail
{
class Frame; class Frame;
class Stmt; class Stmt;
@ -28,14 +30,20 @@ class DbgWatch;
class DbgDisplay; class DbgDisplay;
// This needs to be defined before we do the includes that come after it. // This needs to be defined before we do the includes that come after it.
enum ParseLocationRecType { PLR_UNKNOWN, PLR_FILE_AND_LINE, PLR_FUNCTION }; enum ParseLocationRecType
class ParseLocationRec { {
PLR_UNKNOWN,
PLR_FILE_AND_LINE,
PLR_FUNCTION
};
class ParseLocationRec
{
public: public:
ParseLocationRecType type; ParseLocationRecType type;
int32_t line; int32_t line;
Stmt* stmt; Stmt* stmt;
const char* filename; const char* filename;
}; };
class StmtLocMapping; class StmtLocMapping;
using Filemap = std::deque<StmtLocMapping*>; // mapping for a single file using Filemap = std::deque<StmtLocMapping*>; // mapping for a single file
@ -43,34 +51,41 @@ using Filemap = std::deque<StmtLocMapping*>; // mapping for a single file
using BPIDMapType = std::map<int, DbgBreakpoint*>; using BPIDMapType = std::map<int, DbgBreakpoint*>;
using BPMapType = std::multimap<const Stmt*, DbgBreakpoint*>; using BPMapType = std::multimap<const Stmt*, DbgBreakpoint*>;
class TraceState { class TraceState
{
public: public:
TraceState() { dbgtrace = false; trace_file = stderr; } TraceState()
{
dbgtrace = false;
trace_file = stderr;
}
// Returns previous filename. // Returns previous filename.
FILE* SetTraceFile(const char* trace_filename); FILE* SetTraceFile(const char* trace_filename);
bool DoTrace() const { return dbgtrace; } bool DoTrace() const { return dbgtrace; }
void TraceOn(); void TraceOn();
void TraceOff(); void TraceOff();
int LogTrace(const char* fmt, ...) __attribute__((format(printf, 2, 3)));; int LogTrace(const char* fmt, ...) __attribute__((format(printf, 2, 3)));
;
protected: protected:
bool dbgtrace; // print an execution trace bool dbgtrace; // print an execution trace
FILE* trace_file; FILE* trace_file;
}; };
extern TraceState g_trace_state; extern TraceState g_trace_state;
class DebuggerState { class DebuggerState
{
public: public:
DebuggerState(); DebuggerState();
~DebuggerState(); ~DebuggerState();
int NextBPID() { return next_bp_id++; } int NextBPID() { return next_bp_id++; }
int NextWatchID() { return next_watch_id++; } int NextWatchID() { return next_watch_id++; }
int NextDisplayID() { return next_display_id++; } int NextDisplayID() { return next_display_id++; }
bool BreakBeforeNextStmt() { return break_before_next_stmt; } bool BreakBeforeNextStmt() { return break_before_next_stmt; }
void BreakBeforeNextStmt(bool dobrk) { break_before_next_stmt = dobrk; } void BreakBeforeNextStmt(bool dobrk) { break_before_next_stmt = dobrk; }
@ -78,7 +93,6 @@ public:
bool BreakFromSignal() { return break_from_signal; } bool BreakFromSignal() { return break_from_signal; }
void BreakFromSignal(bool dobrk) { break_from_signal = dobrk; } void BreakFromSignal(bool dobrk) { break_from_signal = dobrk; }
// Temporary state: vanishes when execution resumes. // Temporary state: vanishes when execution resumes.
//### Umesh, why do these all need to be public? -- Vern //### Umesh, why do these all need to be public? -- Vern
@ -86,42 +100,47 @@ public:
// Which frame we're looking at; 0 = the innermost frame. // Which frame we're looking at; 0 = the innermost frame.
int curr_frame_idx; int curr_frame_idx;
bool already_did_list; // did we already do a 'list' command? bool already_did_list; // did we already do a 'list' command?
Location last_loc; // used by 'list'; the last location listed Location last_loc; // used by 'list'; the last location listed
BPIDMapType breakpoints; // BPID -> Breakpoint BPIDMapType breakpoints; // BPID -> Breakpoint
std::vector<DbgWatch*> watches; std::vector<DbgWatch*> watches;
std::vector<DbgDisplay*> displays; std::vector<DbgDisplay*> displays;
BPMapType breakpoint_map; // maps Stmt -> Breakpoints on it BPMapType breakpoint_map; // maps Stmt -> Breakpoints on it
protected: protected:
bool break_before_next_stmt; // trap into debugger (used for "step") bool break_before_next_stmt; // trap into debugger (used for "step")
bool break_from_signal; // was break caused by a signal? bool break_from_signal; // was break caused by a signal?
int next_bp_id, next_watch_id, next_display_id; int next_bp_id, next_watch_id, next_display_id;
private: private:
Frame* dbg_locals; // unused Frame* dbg_locals; // unused
}; };
// Source line -> statement mapping. // Source line -> statement mapping.
// (obj -> source line mapping available in object itself) // (obj -> source line mapping available in object itself)
class StmtLocMapping { class StmtLocMapping
{
public: public:
StmtLocMapping() { } StmtLocMapping() { }
StmtLocMapping(const Location* l, Stmt* s) { loc = *l; stmt = s; } StmtLocMapping(const Location* l, Stmt* s)
{
loc = *l;
stmt = s;
}
bool StartsAfter(const StmtLocMapping* m2); bool StartsAfter(const StmtLocMapping* m2);
const Location& Loc() const { return loc; } const Location& Loc() const { return loc; }
Stmt* Statement() const { return stmt; } Stmt* Statement() const { return stmt; }
protected: protected:
Location loc; Location loc;
Stmt* stmt; Stmt* stmt;
}; };
extern bool g_policy_debug; // enable debugging facility extern bool g_policy_debug; // enable debugging facility
extern DebuggerState g_debugger_state; extern DebuggerState g_debugger_state;
// //
@ -144,7 +163,6 @@ std::vector<ParseLocationRec> parse_location_string(const std::string& s);
// //
// Also add some hooks for UI? -- See GDB // Also add some hooks for UI? -- See GDB
// Debugging hooks. // Debugging hooks.
// Return true to continue execution, false to abort. // Return true to continue execution, false to abort.
@ -158,7 +176,7 @@ int dbg_init_debugger(const char* cmdfile = nullptr);
int dbg_shutdown_debugger(); int dbg_shutdown_debugger();
// Returns 1 if successful, 0 otherwise. // Returns 1 if successful, 0 otherwise.
int dbg_handle_debug_input(); // read a line and then have it executed int dbg_handle_debug_input(); // read a line and then have it executed
// Returns > 0 if execution should be resumed, 0 if another debug command // Returns > 0 if execution should be resumed, 0 if another debug command
// should be read, or < 0 if there was an error. // should be read, or < 0 if there was an error.
@ -170,12 +188,12 @@ ValPtr dbg_eval_expr(const char* expr);
// Get line that looks like "In FnFoo(arg = val) at File:Line". // Get line that looks like "In FnFoo(arg = val) at File:Line".
std::string get_context_description(const Stmt* stmt, const Frame* frame); std::string get_context_description(const Stmt* stmt, const Frame* frame);
extern Frame* g_dbg_locals; // variables created within debugger context extern Frame* g_dbg_locals; // variables created within debugger context
extern std::map<std::string, Filemap*> g_dbgfilemaps; // filename => filemap extern std::map<std::string, Filemap*> g_dbgfilemaps; // filename => filemap
// Perhaps add a code/priority argument to do selective output. // Perhaps add a code/priority argument to do selective output.
int debug_msg(const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); int debug_msg(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,32 +1,32 @@
// Support routines to help deal with Bro debugging commands and // Support routines to help deal with Bro debugging commands and
// implementation of most commands. // implementation of most commands.
#include "zeek/zeek-config.h"
#include "zeek/DebugCmds.h" #include "zeek/DebugCmds.h"
#include <sys/types.h> #include <assert.h>
#include <regex.h> #include <regex.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <sys/types.h>
#include "zeek/DebugCmdInfoConstants.cc"
#include "zeek/Debug.h"
#include "zeek/Desc.h"
#include "zeek/DbgBreakpoint.h" #include "zeek/DbgBreakpoint.h"
#include "zeek/ID.h" #include "zeek/Debug.h"
#include "zeek/DebugCmdInfoConstants.cc"
#include "zeek/Desc.h"
#include "zeek/Frame.h" #include "zeek/Frame.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/Stmt.h" #include "zeek/ID.h"
#include "zeek/Scope.h"
#include "zeek/Reporter.h"
#include "zeek/PolicyFile.h" #include "zeek/PolicyFile.h"
#include "zeek/Reporter.h"
#include "zeek/Scope.h"
#include "zeek/Stmt.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/util.h" #include "zeek/util.h"
#include "zeek/zeek-config.h"
using namespace std; using namespace std;
namespace zeek::detail { namespace zeek::detail
{
DebugCmdInfoQueue g_DebugCmdInfos; DebugCmdInfoQueue g_DebugCmdInfos;
@ -55,7 +55,7 @@ static void lookup_global_symbols_regex(const string& orig_regex, vector<ID*>& m
regex.push_back('$'); regex.push_back('$');
regex_t re; regex_t re;
if ( regcomp(&re, regex.c_str(), REG_EXTENDED|REG_NOSUB) ) if ( regcomp(&re, regex.c_str(), REG_EXTENDED | REG_NOSUB) )
{ {
debug_msg("Invalid regular expression: %s\n", regex.c_str()); debug_msg("Invalid regular expression: %s\n", regex.c_str());
return; return;
@ -69,7 +69,7 @@ static void lookup_global_symbols_regex(const string& orig_regex, vector<ID*>& m
{ {
ID* nextid = sym.second.get(); ID* nextid = sym.second.get();
if ( ! func_only || nextid->GetType()->Tag() == TYPE_FUNC ) if ( ! func_only || nextid->GetType()->Tag() == TYPE_FUNC )
if ( ! regexec (&re, nextid->Name(), 0, 0, 0) ) if ( ! regexec(&re, nextid->Name(), 0, 0, 0) )
matches.push_back(nextid); matches.push_back(nextid);
} }
} }
@ -87,7 +87,7 @@ static void choose_global_symbols_regex(const string& regex, vector<ID*>& choice
debug_msg("There were multiple matches, please choose:\n"); debug_msg("There were multiple matches, please choose:\n");
for ( size_t i = 0; i < choices.size(); i++ ) for ( size_t i = 0; i < choices.size(); i++ )
debug_msg("[%zu] %s\n", i+1, choices[i]->Name()); debug_msg("[%zu] %s\n", i + 1, choices[i]->Name());
debug_msg("[a] All of the above\n"); debug_msg("[a] All of the above\n");
debug_msg("[n] None of the above\n"); debug_msg("[n] None of the above\n");
@ -112,7 +112,7 @@ static void choose_global_symbols_regex(const string& regex, vector<ID*>& choice
return; return;
} }
int option = atoi(input.c_str()); int option = atoi(input.c_str());
if ( option > 0 && option <= (int) choices.size() ) if ( option > 0 && option <= (int)choices.size() )
{ {
ID* choice = choices[option - 1]; ID* choice = choices[option - 1];
choices.clear(); choices.clear();
@ -122,13 +122,11 @@ static void choose_global_symbols_regex(const string& regex, vector<ID*>& choice
} }
} }
// //
// DebugCmdInfo implementation // DebugCmdInfo implementation
// //
DebugCmdInfo::DebugCmdInfo(const DebugCmdInfo& info) DebugCmdInfo::DebugCmdInfo(const DebugCmdInfo& info) : cmd(info.cmd), helpstring(nullptr)
: cmd(info.cmd), helpstring(nullptr)
{ {
num_names = info.num_names; num_names = info.num_names;
names = info.names; names = info.names;
@ -136,11 +134,10 @@ DebugCmdInfo::DebugCmdInfo(const DebugCmdInfo& info)
repeatable = info.repeatable; repeatable = info.repeatable;
} }
DebugCmdInfo::DebugCmdInfo(DebugCmd arg_cmd, const char* const* arg_names, DebugCmdInfo::DebugCmdInfo(DebugCmd arg_cmd, const char* const* arg_names, int arg_num_names,
int arg_num_names, bool arg_resume_execution, bool arg_resume_execution, const char* const arg_helpstring,
const char* const arg_helpstring, bool arg_repeatable)
bool arg_repeatable) : cmd(arg_cmd), helpstring(arg_helpstring)
: cmd(arg_cmd), helpstring(arg_helpstring)
{ {
num_names = arg_num_names; num_names = arg_num_names;
resume_execution = arg_resume_execution; resume_execution = arg_resume_execution;
@ -150,11 +147,10 @@ DebugCmdInfo::DebugCmdInfo(DebugCmd arg_cmd, const char* const* arg_names,
names.push_back(arg_names[i]); names.push_back(arg_names[i]);
} }
const DebugCmdInfo* get_debug_cmd_info(DebugCmd cmd) const DebugCmdInfo* get_debug_cmd_info(DebugCmd cmd)
{ {
if ( (int) cmd < g_DebugCmdInfos.size() ) if ( (int)cmd < g_DebugCmdInfos.size() )
return g_DebugCmdInfos[(int) cmd]; return g_DebugCmdInfos[(int)cmd];
else else
return nullptr; return nullptr;
} }
@ -198,13 +194,11 @@ int find_all_matching_cmds(const string& prefix, const char* array_of_matches[])
// ------------------------------------------------------------ // ------------------------------------------------------------
// Implementation of some debugger commands // Implementation of some debugger commands
// Start, end bounds of which frame numbers to print // Start, end bounds of which frame numbers to print
static int dbg_backtrace_internal(int start, int end) static int dbg_backtrace_internal(int start, int end)
{ {
if ( start < 0 || end < 0 || if ( start < 0 || end < 0 || (unsigned)start >= g_frame_stack.size() ||
(unsigned) start >= g_frame_stack.size() || (unsigned)end >= g_frame_stack.size() )
(unsigned) end >= g_frame_stack.size() )
reporter->InternalError("Invalid stack frame index in DbgBacktraceInternal\n"); reporter->InternalError("Invalid stack frame index in DbgBacktraceInternal\n");
if ( start < end ) if ( start < end )
@ -220,14 +214,12 @@ static int dbg_backtrace_internal(int start, int end)
const Stmt* stmt = f ? f->GetNextStmt() : nullptr; const Stmt* stmt = f ? f->GetNextStmt() : nullptr;
string context = get_context_description(stmt, f); string context = get_context_description(stmt, f);
debug_msg("#%d %s\n", debug_msg("#%d %s\n", int(g_frame_stack.size() - 1 - i), context.c_str());
int(g_frame_stack.size() - 1 - i), context.c_str());
}; };
return 1; return 1;
} }
// Returns 0 for illegal arguments, or 1 on success. // Returns 0 for illegal arguments, or 1 on success.
int dbg_cmd_backtrace(DebugCmd cmd, const vector<string>& args) int dbg_cmd_backtrace(DebugCmd cmd, const vector<string>& args)
{ {
@ -239,7 +231,7 @@ int dbg_cmd_backtrace(DebugCmd cmd, const vector<string>& args)
if ( args.size() > 0 ) if ( args.size() > 0 )
{ {
int how_many; // determines how we traverse the frames int how_many; // determines how we traverse the frames
int valid_arg = sscanf(args[0].c_str(), "%i", &how_many); int valid_arg = sscanf(args[0].c_str(), "%i", &how_many);
if ( ! valid_arg ) if ( ! valid_arg )
{ {
@ -271,7 +263,6 @@ int dbg_cmd_backtrace(DebugCmd cmd, const vector<string>& args)
return dbg_backtrace_internal(start_iter, end_iter); return dbg_backtrace_internal(start_iter, end_iter);
} }
// Returns 0 if invalid args, else 1. // Returns 0 if invalid args, else 1.
int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args) int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args)
{ {
@ -295,8 +286,7 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args)
return 0; return 0;
} }
if ( idx < 0 || if ( idx < 0 || (unsigned int)idx >= g_frame_stack.size() )
(unsigned int) idx >= g_frame_stack.size() )
{ {
debug_msg("No frame %d", idx); debug_msg("No frame %d", idx);
return 0; return 0;
@ -319,8 +309,7 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args)
else if ( cmd == dcUp ) else if ( cmd == dcUp )
{ {
if ( (unsigned int)(g_debugger_state.curr_frame_idx + 1) == if ( (unsigned int)(g_debugger_state.curr_frame_idx + 1) == g_frame_stack.size() )
g_frame_stack.size() )
{ {
debug_msg("Outermost frame already selected\n"); debug_msg("Outermost frame already selected\n");
return 0; return 0;
@ -329,8 +318,7 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args)
++g_debugger_state.curr_frame_idx; ++g_debugger_state.curr_frame_idx;
} }
int user_frame_number = int user_frame_number = g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
// Set the current location to the new frame being looked at // Set the current location to the new frame being looked at
// for 'list', 'break', etc. // for 'list', 'break', etc.
@ -352,14 +340,13 @@ int dbg_cmd_help(DebugCmd cmd, const vector<string>& args)
debug_msg("Help summary: \n\n"); debug_msg("Help summary: \n\n");
for ( int i = 1; i < num_debug_cmds(); ++i ) for ( int i = 1; i < num_debug_cmds(); ++i )
{ {
const DebugCmdInfo* info = get_debug_cmd_info (DebugCmd(i)); const DebugCmdInfo* info = get_debug_cmd_info(DebugCmd(i));
debug_msg("%s -- %s\n", info->Names()[0], info->Helpstring()); debug_msg("%s -- %s\n", info->Names()[0], info->Helpstring());
} }
return -1; return -1;
} }
int dbg_cmd_break(DebugCmd cmd, const vector<string>& args) int dbg_cmd_break(DebugCmd cmd, const vector<string>& args)
{ {
assert(cmd == dcBreak); assert(cmd == dcBreak);
@ -370,9 +357,7 @@ int dbg_cmd_break(DebugCmd cmd, const vector<string>& args)
if ( args.empty() || args[0] == "if" ) if ( args.empty() || args[0] == "if" )
{ // break on next stmt { // break on next stmt
int user_frame_number = int user_frame_number = g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
g_frame_stack.size() - 1 -
g_debugger_state.curr_frame_idx;
Stmt* stmt = g_frame_stack[user_frame_number]->GetNextStmt(); Stmt* stmt = g_frame_stack[user_frame_number]->GetNextStmt();
if ( ! stmt ) if ( ! stmt )
@ -407,13 +392,10 @@ int dbg_cmd_break(DebugCmd cmd, const vector<string>& args)
else else
locstrings.push_back(args[0].c_str()); locstrings.push_back(args[0].c_str());
for ( unsigned int strindex = 0; strindex < locstrings.size(); for ( unsigned int strindex = 0; strindex < locstrings.size(); ++strindex )
++strindex )
{ {
debug_msg("Setting breakpoint on %s:\n", debug_msg("Setting breakpoint on %s:\n", locstrings[strindex].c_str());
locstrings[strindex].c_str()); vector<ParseLocationRec> plrs = parse_location_string(locstrings[strindex]);
vector<ParseLocationRec> plrs =
parse_location_string(locstrings[strindex]);
for ( const auto& plr : plrs ) for ( const auto& plr : plrs )
{ {
DbgBreakpoint* bp = new DbgBreakpoint(); DbgBreakpoint* bp = new DbgBreakpoint();
@ -482,9 +464,8 @@ int dbg_cmd_break_condition(DebugCmd cmd, const vector<string>& args)
// Change the state of a breakpoint. // Change the state of a breakpoint.
int dbg_cmd_break_set_state(DebugCmd cmd, const vector<string>& args) int dbg_cmd_break_set_state(DebugCmd cmd, const vector<string>& args)
{ {
assert(cmd == dcDeleteBreak || cmd == dcClearBreak || assert(cmd == dcDeleteBreak || cmd == dcClearBreak || cmd == dcDisableBreak ||
cmd == dcDisableBreak || cmd == dcEnableBreak || cmd == dcEnableBreak || cmd == dcIgnoreBreak);
cmd == dcIgnoreBreak);
if ( cmd == dcClearBreak || cmd == dcIgnoreBreak ) if ( cmd == dcClearBreak || cmd == dcIgnoreBreak )
{ {
@ -494,7 +475,7 @@ int dbg_cmd_break_set_state(DebugCmd cmd, const vector<string>& args)
if ( g_debugger_state.breakpoints.empty() ) if ( g_debugger_state.breakpoints.empty() )
{ {
debug_msg ("No breakpoints currently set.\n"); debug_msg("No breakpoints currently set.\n");
return -1; return -1;
} }
@ -516,31 +497,31 @@ int dbg_cmd_break_set_state(DebugCmd cmd, const vector<string>& args)
for ( auto bp_change : bps_to_change ) for ( auto bp_change : bps_to_change )
{ {
BPIDMapType::iterator result = BPIDMapType::iterator result = g_debugger_state.breakpoints.find(bp_change);
g_debugger_state.breakpoints.find(bp_change);
if ( result != g_debugger_state.breakpoints.end() ) if ( result != g_debugger_state.breakpoints.end() )
{ {
switch ( cmd ) { switch ( cmd )
case dcDisableBreak: {
g_debugger_state.breakpoints[bp_change]->SetEnable(false); case dcDisableBreak:
debug_msg("Breakpoint %d disabled\n", bp_change); g_debugger_state.breakpoints[bp_change]->SetEnable(false);
break; debug_msg("Breakpoint %d disabled\n", bp_change);
break;
case dcEnableBreak: case dcEnableBreak:
g_debugger_state.breakpoints[bp_change]->SetEnable(true); g_debugger_state.breakpoints[bp_change]->SetEnable(true);
debug_msg("Breakpoint %d enabled\n", bp_change); debug_msg("Breakpoint %d enabled\n", bp_change);
break; break;
case dcDeleteBreak: case dcDeleteBreak:
delete g_debugger_state.breakpoints[bp_change]; delete g_debugger_state.breakpoints[bp_change];
g_debugger_state.breakpoints.erase(bp_change); g_debugger_state.breakpoints.erase(bp_change);
debug_msg("Breakpoint %d deleted\n", bp_change); debug_msg("Breakpoint %d deleted\n", bp_change);
break; break;
default: default:
reporter->InternalError("Invalid command in DbgCmdBreakSetState\n"); reporter->InternalError("Invalid command in DbgCmdBreakSetState\n");
} }
} }
else else
@ -582,7 +563,6 @@ int dbg_cmd_print(DebugCmd cmd, const vector<string>& args)
return 1; return 1;
} }
// Get the debugger's state. // Get the debugger's state.
// Allowed arguments are: break (breakpoints), watch, display, source. // Allowed arguments are: break (breakpoints), watch, display, source.
int dbg_cmd_info(DebugCmd cmd, const vector<string>& args) int dbg_cmd_info(DebugCmd cmd, const vector<string>& args)
@ -604,16 +584,12 @@ int dbg_cmd_info(DebugCmd cmd, const vector<string>& args)
BPIDMapType::iterator iter; BPIDMapType::iterator iter;
for ( iter = g_debugger_state.breakpoints.begin(); for ( iter = g_debugger_state.breakpoints.begin();
iter != g_debugger_state.breakpoints.end(); iter != g_debugger_state.breakpoints.end(); ++iter )
++iter )
{ {
DbgBreakpoint* bp = (*iter).second; DbgBreakpoint* bp = (*iter).second;
debug_msg("%-4d%-15s%-5s%-4s%s\n", debug_msg("%-4d%-15s%-5s%-4s%s\n", bp->GetID(), "breakpoint",
bp->GetID(), bp->IsTemporary() ? "del" : "keep", bp->IsEnabled() ? "y" : "n",
"breakpoint", bp->Description());
bp->IsTemporary() ? "del" : "keep",
bp->IsEnabled() ? "y" : "n",
bp->Description());
} }
} }
@ -676,22 +652,18 @@ int dbg_cmd_list(DebugCmd cmd, const vector<string>& args)
pre_offset = 0; pre_offset = 0;
} }
if ( (int) pre_offset + if ( (int)pre_offset + (int)g_debugger_state.last_loc.first_line - (int)CENTER_IDX < 0 )
(int) g_debugger_state.last_loc.first_line -
(int) CENTER_IDX < 0 )
pre_offset = CENTER_IDX - g_debugger_state.last_loc.first_line; pre_offset = CENTER_IDX - g_debugger_state.last_loc.first_line;
g_debugger_state.last_loc.first_line += pre_offset; g_debugger_state.last_loc.first_line += pre_offset;
int last_line_in_file = int last_line_in_file = how_many_lines_in(g_debugger_state.last_loc.filename);
how_many_lines_in(g_debugger_state.last_loc.filename);
if ( g_debugger_state.last_loc.first_line > last_line_in_file ) if ( g_debugger_state.last_loc.first_line > last_line_in_file )
g_debugger_state.last_loc.first_line = last_line_in_file; g_debugger_state.last_loc.first_line = last_line_in_file;
PrintLines(g_debugger_state.last_loc.filename, PrintLines(g_debugger_state.last_loc.filename,
g_debugger_state.last_loc.first_line - CENTER_IDX, g_debugger_state.last_loc.first_line - CENTER_IDX, 10, true);
10, true);
g_debugger_state.already_did_list = true; g_debugger_state.already_did_list = true;
@ -704,8 +676,7 @@ int dbg_cmd_trace(DebugCmd cmd, const vector<string>& args)
if ( args.empty() ) if ( args.empty() )
{ {
debug_msg("Execution tracing is %s.\n", debug_msg("Execution tracing is %s.\n", g_trace_state.DoTrace() ? "on" : "off");
g_trace_state.DoTrace() ? "on" : "off" );
return 1; return 1;
} }
@ -725,4 +696,4 @@ int dbg_cmd_trace(DebugCmd cmd, const vector<string>& args)
return 0; return 0;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -4,31 +4,32 @@
#pragma once #pragma once
#include <stdlib.h> #include <stdlib.h>
#include <deque>
#include <string> #include <string>
#include <vector> #include <vector>
#include <deque>
// This file is generated during the build. // This file is generated during the build.
#include "DebugCmdConstants.h" #include "DebugCmdConstants.h"
namespace zeek::detail { namespace zeek::detail
{
class DebugCmdInfo { class DebugCmdInfo
{
public: public:
DebugCmdInfo(const DebugCmdInfo& info); DebugCmdInfo(const DebugCmdInfo& info);
DebugCmdInfo(DebugCmd cmd, const char* const* names, int num_names, DebugCmdInfo(DebugCmd cmd, const char* const* names, int num_names, bool resume_execution,
bool resume_execution, const char* const helpstring, const char* const helpstring, bool repeatable);
bool repeatable);
DebugCmdInfo() : helpstring(nullptr) {} DebugCmdInfo() : helpstring(nullptr) { }
int Cmd() const { return cmd; } int Cmd() const { return cmd; }
int NumNames() const { return num_names; } int NumNames() const { return num_names; }
const std::vector<const char *>& Names() const { return names; } const std::vector<const char*>& Names() const { return names; }
bool ResumeExecution() const { return resume_execution; } bool ResumeExecution() const { return resume_execution; }
const char* Helpstring() const { return helpstring; } const char* Helpstring() const { return helpstring; }
bool Repeatable() const { return repeatable; } bool Repeatable() const { return repeatable; }
protected: protected:
DebugCmd cmd; DebugCmd cmd;
@ -42,12 +43,12 @@ protected:
// Does entering a blank line repeat this command? // Does entering a blank line repeat this command?
bool repeatable; bool repeatable;
}; };
using DebugCmdInfoQueue = std::deque<DebugCmdInfo*>; using DebugCmdInfoQueue = std::deque<DebugCmdInfo*>;
extern DebugCmdInfoQueue g_DebugCmdInfos; extern DebugCmdInfoQueue g_DebugCmdInfos;
void init_global_dbg_constants (); void init_global_dbg_constants();
#define num_debug_cmds() (static_cast<int>(g_DebugCmdInfos.size())) #define num_debug_cmds() (static_cast<int>(g_DebugCmdInfos.size()))
@ -79,4 +80,4 @@ DbgCmdFn dbg_cmd_info;
DbgCmdFn dbg_cmd_list; DbgCmdFn dbg_cmd_list;
DbgCmdFn dbg_cmd_trace; DbgCmdFn dbg_cmd_trace;
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -11,29 +11,17 @@
zeek::detail::DebugLogger zeek::detail::debug_logger; zeek::detail::DebugLogger zeek::detail::debug_logger;
zeek::detail::DebugLogger& debug_logger = zeek::detail::debug_logger; zeek::detail::DebugLogger& debug_logger = zeek::detail::debug_logger;
namespace zeek::detail { namespace zeek::detail
{
// Same order here as in DebugStream. // Same order here as in DebugStream.
DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = { DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
{ "serial", 0, false }, {"serial", 0, false}, {"rules", 0, false}, {"string", 0, false},
{ "rules", 0, false }, {"notifiers", 0, false}, {"main-loop", 0, false}, {"dpd", 0, false},
{ "string", 0, false }, {"packet_analysis", 0, false}, {"file_analysis", 0, false}, {"tm", 0, false},
{ "notifiers", 0, false }, {"logging", 0, false}, {"input", 0, false}, {"threading", 0, false},
{ "main-loop", 0, false }, {"plugins", 0, false}, {"zeekygen", 0, false}, {"pktio", 0, false},
{ "dpd", 0, false }, {"broker", 0, false}, {"scripts", 0, false}, {"supervisor", 0, false}};
{ "packet_analysis", 0, false },
{ "file_analysis", 0, false },
{ "tm", 0, false },
{ "logging", 0, false },
{ "input", 0, false },
{ "threading", 0, false },
{ "plugins", 0, false },
{ "zeekygen", 0, false },
{ "pktio", 0, false },
{ "broker", 0, false },
{ "scripts", 0, false },
{ "supervisor", 0, false }
};
DebugLogger::DebugLogger() DebugLogger::DebugLogger()
{ {
@ -81,10 +69,11 @@ void DebugLogger::ShowStreamsHelp()
fprintf(stderr, "Available streams:\n"); fprintf(stderr, "Available streams:\n");
for ( int i = 0; i < NUM_DBGS; ++i ) for ( int i = 0; i < NUM_DBGS; ++i )
fprintf(stderr," %s\n", streams[i].prefix); fprintf(stderr, " %s\n", streams[i].prefix);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, " plugin-<plugin-name> (replace '::' in name with '-'; e.g., '-B plugin-Zeek-Netmap')\n"); fprintf(stderr, " plugin-<plugin-name> (replace '::' in name with '-'; e.g., '-B "
"plugin-Zeek-Netmap')\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Pseudo streams\n"); fprintf(stderr, "Pseudo streams\n");
fprintf(stderr, " verbose Increase verbosity.\n"); fprintf(stderr, " verbose Increase verbosity.\n");
@ -146,11 +135,11 @@ void DebugLogger::EnableStreams(const char* s)
reporter->FatalError("unknown debug stream '%s', try -B help.\n", tok); reporter->FatalError("unknown debug stream '%s', try -B help.\n", tok);
next: next:
tok = strtok(0, ","); tok = strtok(0, ",");
} }
delete [] tmp; delete[] tmp;
} }
void DebugLogger::Log(DebugStream stream, const char* fmt, ...) void DebugLogger::Log(DebugStream stream, const char* fmt, ...)
@ -160,8 +149,8 @@ void DebugLogger::Log(DebugStream stream, const char* fmt, ...)
if ( ! g->enabled ) if ( ! g->enabled )
return; return;
fprintf(file, "%17.06f/%17.06f [%s] ", fprintf(file, "%17.06f/%17.06f [%s] ", run_state::network_time, util::current_time(true),
run_state::network_time, util::current_time(true), g->prefix); g->prefix);
for ( int i = g->indent; i > 0; --i ) for ( int i = g->indent; i > 0; --i )
fputs(" ", file); fputs(" ", file);
@ -183,8 +172,8 @@ void DebugLogger::Log(const plugin::Plugin& plugin, const char* fmt, ...)
if ( enabled_streams.find(tok) == enabled_streams.end() ) if ( enabled_streams.find(tok) == enabled_streams.end() )
return; return;
fprintf(file, "%17.06f/%17.06f [plugin %s] ", fprintf(file, "%17.06f/%17.06f [plugin %s] ", run_state::network_time, util::current_time(true),
run_state::network_time, util::current_time(true), plugin.Name().c_str()); plugin.Name().c_str());
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@ -195,6 +184,6 @@ void DebugLogger::Log(const plugin::Plugin& plugin, const char* fmt, ...)
fflush(file); fflush(file);
} }
} // namespace zeek::detail } // namespace zeek::detail
#endif #endif

View file

@ -5,56 +5,64 @@
#ifdef DEBUG #ifdef DEBUG
#include <stdio.h>
#include <set>
#include <string>
#include "zeek/zeek-config.h" #include "zeek/zeek-config.h"
#include <stdio.h> #define DBG_LOG(stream, args...) \
#include <string> if ( ::zeek::detail::debug_logger.IsEnabled(stream) ) \
#include <set> ::zeek::detail::debug_logger.Log(stream, args)
#define DBG_LOG_VERBOSE(stream, args...) \
#define DBG_LOG(stream, args...) \ if ( ::zeek::detail::debug_logger.IsVerbose() && \
if ( ::zeek::detail::debug_logger.IsEnabled(stream) ) \ ::zeek::detail::debug_logger.IsEnabled(stream) ) \
::zeek::detail::debug_logger.Log(stream, args) ::zeek::detail::debug_logger.Log(stream, args)
#define DBG_LOG_VERBOSE(stream, args...) \
if ( ::zeek::detail::debug_logger.IsVerbose() && ::zeek::detail::debug_logger.IsEnabled(stream) ) \
::zeek::detail::debug_logger.Log(stream, args)
#define DBG_PUSH(stream) ::zeek::detail::debug_logger.PushIndent(stream) #define DBG_PUSH(stream) ::zeek::detail::debug_logger.PushIndent(stream)
#define DBG_POP(stream) ::zeek::detail::debug_logger.PopIndent(stream) #define DBG_POP(stream) ::zeek::detail::debug_logger.PopIndent(stream)
#define PLUGIN_DBG_LOG(plugin, args...) ::zeek::detail::debug_logger.Log(plugin, args) #define PLUGIN_DBG_LOG(plugin, args...) ::zeek::detail::debug_logger.Log(plugin, args)
namespace zeek { namespace zeek
{
namespace plugin { class Plugin; } namespace plugin
{
class Plugin;
}
// To add a new debugging stream, add a constant here as well as // To add a new debugging stream, add a constant here as well as
// an entry to DebugLogger::streams in DebugLogger.cc. // an entry to DebugLogger::streams in DebugLogger.cc.
enum DebugStream { enum DebugStream
DBG_SERIAL, // Serialization {
DBG_RULES, // Signature matching DBG_SERIAL, // Serialization
DBG_STRING, // String code DBG_RULES, // Signature matching
DBG_NOTIFIERS, // Notifiers DBG_STRING, // String code
DBG_MAINLOOP, // Main IOSource loop DBG_NOTIFIERS, // Notifiers
DBG_ANALYZER, // Analyzer framework DBG_MAINLOOP, // Main IOSource loop
DBG_PACKET_ANALYSIS, // Packet analysis DBG_ANALYZER, // Analyzer framework
DBG_FILE_ANALYSIS, // File analysis DBG_PACKET_ANALYSIS, // Packet analysis
DBG_TM, // Time-machine packet input via Brocolli DBG_FILE_ANALYSIS, // File analysis
DBG_LOGGING, // Logging streams DBG_TM, // Time-machine packet input via Brocolli
DBG_INPUT, // Input streams DBG_LOGGING, // Logging streams
DBG_THREADING, // Threading system DBG_INPUT, // Input streams
DBG_PLUGINS, // Plugin system DBG_THREADING, // Threading system
DBG_ZEEKYGEN, // Zeekygen DBG_PLUGINS, // Plugin system
DBG_PKTIO, // Packet sources and dumpers. DBG_ZEEKYGEN, // Zeekygen
DBG_BROKER, // Broker communication DBG_PKTIO, // Packet sources and dumpers.
DBG_SCRIPTS, // Script initialization DBG_BROKER, // Broker communication
DBG_SUPERVISOR, // Process supervisor DBG_SCRIPTS, // Script initialization
DBG_SUPERVISOR, // Process supervisor
NUM_DBGS // Has to be last NUM_DBGS // Has to be last
}; };
namespace detail { namespace detail
{
class DebugLogger { class DebugLogger
{
public: public:
// Output goes to stderr per default. // Output goes to stderr per default.
DebugLogger(); DebugLogger();
@ -63,26 +71,22 @@ public:
void OpenDebugLog(const char* filename = 0); void OpenDebugLog(const char* filename = 0);
void Log(DebugStream stream, const char* fmt, ...) __attribute__((format(printf, 3, 4))); void Log(DebugStream stream, const char* fmt, ...) __attribute__((format(printf, 3, 4)));
void Log(const plugin::Plugin& plugin, const char* fmt, ...) __attribute__((format(printf, 3, 4))); void Log(const plugin::Plugin& plugin, const char* fmt, ...)
__attribute__((format(printf, 3, 4)));
void PushIndent(DebugStream stream) void PushIndent(DebugStream stream) { ++streams[int(stream)].indent; }
{ ++streams[int(stream)].indent; } void PopIndent(DebugStream stream) { --streams[int(stream)].indent; }
void PopIndent(DebugStream stream)
{ --streams[int(stream)].indent; }
void EnableStream(DebugStream stream) void EnableStream(DebugStream stream) { streams[int(stream)].enabled = true; }
{ streams[int(stream)].enabled = true; } void DisableStream(DebugStream stream) { streams[int(stream)].enabled = false; }
void DisableStream(DebugStream stream)
{ streams[int(stream)].enabled = false; }
// Takes comma-seperated list of stream prefixes. // Takes comma-seperated list of stream prefixes.
void EnableStreams(const char* streams); void EnableStreams(const char* streams);
bool IsEnabled(DebugStream stream) const bool IsEnabled(DebugStream stream) const { return streams[int(stream)].enabled; }
{ return streams[int(stream)].enabled; }
void SetVerbose(bool arg_verbose) { verbose = arg_verbose; } void SetVerbose(bool arg_verbose) { verbose = arg_verbose; }
bool IsVerbose() const { return verbose; } bool IsVerbose() const { return verbose; }
void ShowStreamsHelp(); void ShowStreamsHelp();
@ -90,21 +94,22 @@ private:
FILE* file; FILE* file;
bool verbose; bool verbose;
struct Stream { struct Stream
{
const char* prefix; const char* prefix;
int indent; int indent;
bool enabled; bool enabled;
}; };
std::set<std::string> enabled_streams; std::set<std::string> enabled_streams;
static Stream streams[NUM_DBGS]; static Stream streams[NUM_DBGS];
}; };
extern DebugLogger debug_logger; extern DebugLogger debug_logger;
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek
#else #else
#define DBG_LOG(args...) #define DBG_LOG(args...)

View file

@ -1,22 +1,23 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include <stdlib.h>
#include <string.h>
#include "zeek/File.h"
#include "zeek/Reporter.h"
#include "zeek/ConvertUTF.h" #include "zeek/ConvertUTF.h"
#include "zeek/File.h"
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
#include "zeek/Reporter.h"
#include "zeek/zeek-config.h"
#define DEFAULT_SIZE 128 #define DEFAULT_SIZE 128
#define SLOP 10 #define SLOP 10
namespace zeek { namespace zeek
{
ODesc::ODesc(DescType t, File* arg_f) ODesc::ODesc(DescType t, File* arg_f)
{ {
@ -28,7 +29,7 @@ ODesc::ODesc(DescType t, File* arg_f)
{ {
size = DEFAULT_SIZE; size = DEFAULT_SIZE;
base = util::safe_malloc(size); base = util::safe_malloc(size);
((char*) base)[0] = '\0'; ((char*)base)[0] = '\0';
offset = 0; offset = 0;
} }
else else
@ -64,7 +65,7 @@ void ODesc::EnableEscaping()
escape = true; escape = true;
} }
void ODesc::EnableUTF8 () void ODesc::EnableUTF8()
{ {
utf8 = true; utf8 = true;
} }
@ -93,12 +94,11 @@ void ODesc::Add(const char* s, int do_indent)
{ {
unsigned int n = strlen(s); unsigned int n = strlen(s);
if ( do_indent && IsReadable() && offset > 0 && if ( do_indent && IsReadable() && offset > 0 && ((const char*)base)[offset - 1] == '\n' )
((const char*) base)[offset - 1] == '\n' )
Indent(); Indent();
if ( IsBinary() ) if ( IsBinary() )
AddBytes(s, n+1); AddBytes(s, n + 1);
else else
AddBytes(s, n); AddBytes(s, n);
} }
@ -169,13 +169,12 @@ void ODesc::Add(double d, bool no_exp)
Add(tmp); Add(tmp);
auto approx_equal = [](double a, double b, double tolerance = 1e-6) -> bool auto approx_equal = [](double a, double b, double tolerance = 1e-6) -> bool
{ {
auto v = a - b; auto v = a - b;
return v < 0 ? -v < tolerance : v < tolerance; return v < 0 ? -v < tolerance : v < tolerance;
}; };
if ( approx_equal(d, nearbyint(d), 1e-9) && if ( approx_equal(d, nearbyint(d), 1e-9) && isfinite(d) && ! strchr(tmp, 'e') )
isfinite(d) && ! strchr(tmp, 'e') )
// disambiguate from integer // disambiguate from integer
Add(".0"); Add(".0");
} }
@ -210,7 +209,7 @@ void ODesc::AddBytes(const String* s)
{ {
const char* str = s->Render(String::EXPANDED_STRING); const char* str = s->Render(String::EXPANDED_STRING);
Add(str); Add(str);
delete [] str; delete[] str;
} }
} }
else else
@ -294,17 +293,17 @@ std::pair<const char*, size_t> ODesc::FirstEscapeLoc(const char* bytes, size_t n
void ODesc::AddBytes(const void* bytes, unsigned int n) void ODesc::AddBytes(const void* bytes, unsigned int n)
{ {
if ( ! escape ) if ( ! escape )
{ {
AddBytesRaw(bytes, n); AddBytesRaw(bytes, n);
return; return;
} }
const char* s = (const char*) bytes; const char* s = (const char*)bytes;
const char* e = (const char*) bytes + n; const char* e = (const char*)bytes + n;
while ( s < e ) while ( s < e )
{ {
auto [ esc_start, esc_len ] = FirstEscapeLoc(s, e - s); auto [esc_start, esc_len] = FirstEscapeLoc(s, e - s);
if ( esc_start != nullptr ) if ( esc_start != nullptr )
{ {
@ -343,7 +342,7 @@ void ODesc::AddBytesRaw(const void* bytes, unsigned int n)
{ {
static bool write_failed = false; static bool write_failed = false;
if ( ! f->Write((const char*) bytes, n) ) if ( ! f->Write((const char*)bytes, n) )
{ {
if ( ! write_failed ) if ( ! write_failed )
// Most likely it's a "disk full" so report // Most likely it's a "disk full" so report
@ -364,10 +363,10 @@ void ODesc::AddBytesRaw(const void* bytes, unsigned int n)
// The following casting contortions are necessary because // The following casting contortions are necessary because
// simply using &base[offset] generates complaints about // simply using &base[offset] generates complaints about
// using a void* for pointer arithemtic. // using a void* for pointer arithemtic.
memcpy((void*) &((char*) base)[offset], bytes, n); memcpy((void*)&((char*)base)[offset], bytes, n);
offset += n; offset += n;
((char*) base)[offset] = '\0'; // ensure that always NUL-term. ((char*)base)[offset] = '\0'; // ensure that always NUL-term.
} }
} }
@ -389,7 +388,7 @@ void ODesc::Clear()
free(base); free(base);
size = DEFAULT_SIZE; size = DEFAULT_SIZE;
base = util::safe_malloc(size); base = util::safe_malloc(size);
((char*) base)[0] = '\0'; ((char*)base)[0] = '\0';
} }
} }
@ -415,7 +414,6 @@ bool ODesc::FindType(const Type* type)
return false; return false;
} }
std::string obj_desc(const Obj* o) std::string obj_desc(const Obj* o)
{ {
static ODesc d; static ODesc d;
@ -428,4 +426,4 @@ std::string obj_desc(const Obj* o)
return std::string(d.Description()); return std::string(d.Description());
} }
} // namespace zeek } // namespace zeek

View file

@ -3,95 +3,97 @@
#pragma once #pragma once
#include <sys/types.h> // for u_char #include <sys/types.h> // for u_char
#include <set> #include <set>
#include <utility>
#include <string> #include <string>
#include <utility>
#include "zeek/ZeekString.h" // for byte_vec #include "zeek/ZeekString.h" // for byte_vec
#include "zeek/util.h" // for bro_int_t #include "zeek/util.h" // for bro_int_t
namespace zeek { namespace zeek
{
class IPAddr; class IPAddr;
class IPPrefix; class IPPrefix;
class File; class File;
class Type; class Type;
enum DescType { enum DescType
{
DESC_READABLE, DESC_READABLE,
DESC_PORTABLE, DESC_PORTABLE,
DESC_BINARY, DESC_BINARY,
}; };
enum DescStyle { enum DescStyle
{
STANDARD_STYLE, STANDARD_STYLE,
RAW_STYLE, RAW_STYLE,
}; };
class ODesc { class ODesc
{
public: public:
explicit ODesc(DescType t=DESC_READABLE, File* f=nullptr); explicit ODesc(DescType t = DESC_READABLE, File* f = nullptr);
~ODesc(); ~ODesc();
bool IsReadable() const { return type == DESC_READABLE; } bool IsReadable() const { return type == DESC_READABLE; }
bool IsPortable() const { return type == DESC_PORTABLE; } bool IsPortable() const { return type == DESC_PORTABLE; }
bool IsBinary() const { return type == DESC_BINARY; } bool IsBinary() const { return type == DESC_BINARY; }
bool IsShort() const { return is_short; } bool IsShort() const { return is_short; }
void SetShort() { is_short = true; } void SetShort() { is_short = true; }
void SetShort(bool s) { is_short = s; } void SetShort(bool s) { is_short = s; }
// Whether we want to have quotes around strings. // Whether we want to have quotes around strings.
bool WantQuotes() const { return want_quotes; } bool WantQuotes() const { return want_quotes; }
void SetQuotes(bool q) { want_quotes = q; } void SetQuotes(bool q) { want_quotes = q; }
// Whether to ensure deterministic output (for example, when // Whether to ensure deterministic output (for example, when
// describing TableVal's). // describing TableVal's).
bool WantDeterminism() const { return want_determinism; } bool WantDeterminism() const { return want_determinism; }
void SetDeterminism(bool d) { want_determinism = d; } void SetDeterminism(bool d) { want_determinism = d; }
// Whether we want to print statistics like access time and execution // Whether we want to print statistics like access time and execution
// count where available. // count where available.
bool IncludeStats() const { return include_stats; } bool IncludeStats() const { return include_stats; }
void SetIncludeStats(bool s) { include_stats = s; } void SetIncludeStats(bool s) { include_stats = s; }
DescStyle Style() const { return style; } DescStyle Style() const { return style; }
void SetStyle(DescStyle s) { style = s; } void SetStyle(DescStyle s) { style = s; }
void SetFlush(bool arg_do_flush) { do_flush = arg_do_flush; } void SetFlush(bool arg_do_flush) { do_flush = arg_do_flush; }
void EnableEscaping(); void EnableEscaping();
void EnableUTF8(); void EnableUTF8();
void AddEscapeSequence(const char* s) { escape_sequences.insert(s); } void AddEscapeSequence(const char* s) { escape_sequences.insert(s); }
void AddEscapeSequence(const char* s, size_t n) void AddEscapeSequence(const char* s, size_t n) { escape_sequences.insert(std::string(s, n)); }
{ escape_sequences.insert(std::string(s, n)); } void AddEscapeSequence(const std::string& s) { escape_sequences.insert(s); }
void AddEscapeSequence(const std::string & s)
{ escape_sequences.insert(s); }
void RemoveEscapeSequence(const char* s) { escape_sequences.erase(s); } void RemoveEscapeSequence(const char* s) { escape_sequences.erase(s); }
void RemoveEscapeSequence(const char* s, size_t n) void RemoveEscapeSequence(const char* s, size_t n)
{ escape_sequences.erase(std::string(s, n)); } {
void RemoveEscapeSequence(const std::string & s) escape_sequences.erase(std::string(s, n));
{ escape_sequences.erase(s); } }
void RemoveEscapeSequence(const std::string& s) { escape_sequences.erase(s); }
void PushIndent(); void PushIndent();
void PopIndent(); void PopIndent();
void PopIndentNoNL(); void PopIndentNoNL();
int GetIndentLevel() const { return indent_level; } int GetIndentLevel() const { return indent_level; }
void ClearIndentLevel() { indent_level = 0; } void ClearIndentLevel() { indent_level = 0; }
int IndentSpaces() const { return indent_with_spaces; } int IndentSpaces() const { return indent_with_spaces; }
void SetIndentSpaces(int i) { indent_with_spaces = i; } void SetIndentSpaces(int i) { indent_with_spaces = i; }
void Add(const char* s, int do_indent=1); void Add(const char* s, int do_indent = 1);
void AddN(const char* s, int len) { AddBytes(s, len); } void AddN(const char* s, int len) { AddBytes(s, len); }
void Add(const std::string& s) { AddBytes(s.data(), s.size()); } void Add(const std::string& s) { AddBytes(s.data(), s.size()); }
void Add(int i); void Add(int i);
void Add(uint32_t u); void Add(uint32_t u);
void Add(int64_t i); void Add(int64_t i);
void Add(uint64_t u); void Add(uint64_t u);
void Add(double d, bool no_exp=false); void Add(double d, bool no_exp = false);
void Add(const IPAddr& addr); void Add(const IPAddr& addr);
void Add(const IPPrefix& prefix); void Add(const IPPrefix& prefix);
@ -101,13 +103,22 @@ public:
void AddBytes(const String* s); void AddBytes(const String* s);
void Add(const char* s1, const char* s2) void Add(const char* s1, const char* s2)
{ Add(s1); Add(s2); } {
Add(s1);
Add(s2);
}
void AddSP(const char* s1, const char* s2) void AddSP(const char* s1, const char* s2)
{ Add(s1); AddSP(s2); } {
Add(s1);
AddSP(s2);
}
void AddSP(const char* s ) void AddSP(const char* s)
{ Add(s); SP(); } {
Add(s);
SP();
}
void AddCount(bro_int_t n) void AddCount(bro_int_t n)
{ {
@ -118,23 +129,25 @@ public:
} }
} }
void SP() { void SP()
if ( ! IsBinary() ) {
Add(" ", 0); if ( ! IsBinary() )
} Add(" ", 0);
void NL() { }
if ( ! IsBinary() && ! is_short ) void NL()
Add("\n", 0); {
} if ( ! IsBinary() && ! is_short )
Add("\n", 0);
}
// Bypasses the escaping enabled via EnableEscaping(). // Bypasses the escaping enabled via EnableEscaping().
void AddRaw(const char* s, int len) { AddBytesRaw(s, len); } void AddRaw(const char* s, int len) { AddBytesRaw(s, len); }
void AddRaw(const std::string &s) { AddBytesRaw(s.data(), s.size()); } void AddRaw(const std::string& s) { AddBytesRaw(s.data(), s.size()); }
// Returns the description as a string. // Returns the description as a string.
const char* Description() const { return (const char*) base; } const char* Description() const { return (const char*)base; }
const u_char* Bytes() const { return (const u_char *) base; } const u_char* Bytes() const { return (const u_char*)base; }
byte_vec TakeBytes() byte_vec TakeBytes()
{ {
const void* t = base; const void* t = base;
@ -147,7 +160,7 @@ public:
return byte_vec(t); return byte_vec(t);
} }
int Len() const { return offset; } int Len() const { return offset; }
void Clear(); void Clear();
@ -191,12 +204,12 @@ protected:
DescType type; DescType type;
DescStyle style; DescStyle style;
void* base; // beginning of buffer void* base; // beginning of buffer
unsigned int offset; // where we are in the buffer unsigned int offset; // where we are in the buffer
unsigned int size; // size of buffer in bytes unsigned int size; // size of buffer in bytes
bool utf8; // whether valid utf-8 sequences may pass through unescaped bool utf8; // whether valid utf-8 sequences may pass through unescaped
bool escape; // escape unprintable characters in output? bool escape; // escape unprintable characters in output?
bool is_short; bool is_short;
bool want_quotes; bool want_quotes;
bool want_determinism; bool want_determinism;
@ -209,10 +222,10 @@ protected:
using escape_set = std::set<std::string>; using escape_set = std::set<std::string>;
escape_set escape_sequences; // additional sequences of chars to escape escape_set escape_sequences; // additional sequences of chars to escape
File* f; // or the file we're using. File* f; // or the file we're using.
std::set<const Type*> encountered_types; std::set<const Type*> encountered_types;
}; };
// Returns a string representation of an object's description. Used for // Returns a string representation of an object's description. Used for
// debugging and error messages. takes a bare pointer rather than an // debugging and error messages. takes a bare pointer rather than an
@ -221,4 +234,4 @@ protected:
class Obj; class Obj;
extern std::string obj_desc(const Obj* o); extern std::string obj_desc(const Obj* o);
} // namespace zeek } // namespace zeek

File diff suppressed because it is too large Load diff

View file

@ -3,31 +3,37 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <vector>
#include <memory> #include <memory>
#include <vector>
#include "zeek/Hash.h" #include "zeek/Hash.h"
// Type for function to be called when deleting elements. // Type for function to be called when deleting elements.
typedef void (*dict_delete_func)(void*); typedef void (*dict_delete_func)(void*);
namespace zeek { namespace zeek
{
class IterCookie; class IterCookie;
class Dictionary; class Dictionary;
enum DictOrder { ORDERED, UNORDERED }; enum DictOrder
{
ORDERED,
UNORDERED
};
// A dict_delete_func that just calls delete. // A dict_delete_func that just calls delete.
extern void generic_delete_func(void*); extern void generic_delete_func(void*);
namespace detail { namespace detail
{
class DictEntry; class DictEntry;
// Default number of hash buckets in dictionary. The dictionary will increase the size // Default number of hash buckets in dictionary. The dictionary will increase the size
// of the hash table as needed. // of the hash table as needed.
constexpr uint32_t HASH_MASK = 0xFFFFFFFF; //only lower 32 bits. constexpr uint32_t HASH_MASK = 0xFFFFFFFF; // only lower 32 bits.
// These four variables can be used to build different targets with -Dxxx for performance // These four variables can be used to build different targets with -Dxxx for performance
// or for debugging purposes. // or for debugging purposes.
@ -54,9 +60,9 @@ constexpr uint16_t TOO_FAR_TO_REACH = 0xFFFF;
/** /**
* An entry stored in the dictionary. * An entry stored in the dictionary.
*/ */
class DictEntry { class DictEntry
{
public: public:
#ifdef DEBUG #ifdef DEBUG
int bucket = 0; int bucket = 0;
#endif #endif
@ -72,10 +78,10 @@ public:
uint32_t hash = 0; uint32_t hash = 0;
void* value = nullptr; void* value = nullptr;
union { union {
char key_here[8]; //hold key len<=8. when over 8, it's a pointer to real keys. char key_here[8]; // hold key len<=8. when over 8, it's a pointer to real keys.
char* key; char* key;
}; };
DictEntry(void* arg_key, int key_size = 0, hash_t hash = 0, void* value = nullptr, DictEntry(void* arg_key, int key_size = 0, hash_t hash = 0, void* value = nullptr,
int16_t d = TOO_FAR_TO_REACH, bool copy_key = false) int16_t d = TOO_FAR_TO_REACH, bool copy_key = false)
@ -88,7 +94,7 @@ public:
{ {
memcpy(key_here, arg_key, key_size); memcpy(key_here, arg_key, key_size);
if ( ! copy_key ) if ( ! copy_key )
delete [] (char*)arg_key; //own the arg_key, now don't need it. delete[](char*) arg_key; // own the arg_key, now don't need it.
} }
else else
{ {
@ -104,7 +110,7 @@ public:
} }
} }
bool Empty() const { return distance == TOO_FAR_TO_REACH; } bool Empty() const { return distance == TOO_FAR_TO_REACH; }
void SetEmpty() void SetEmpty()
{ {
distance = TOO_FAR_TO_REACH; distance = TOO_FAR_TO_REACH;
@ -115,13 +121,13 @@ public:
value = nullptr; value = nullptr;
key_size = 0; key_size = 0;
bucket = 0; bucket = 0;
#endif//DEBUG #endif // DEBUG
} }
void Clear() void Clear()
{ {
if( key_size > 8 ) if ( key_size > 8 )
delete [] key; delete[] key;
SetEmpty(); SetEmpty();
} }
@ -131,27 +137,21 @@ public:
return std::make_unique<detail::HashKey>(GetKey(), key_size, hash); return std::make_unique<detail::HashKey>(GetKey(), key_size, hash);
} }
template <typename T> template <typename T> T GetValue() const { return static_cast<T>(value); }
T GetValue() const { return static_cast<T>(value); }
bool Equal(const char* arg_key, int arg_key_size, hash_t arg_hash) const bool Equal(const char* arg_key, int arg_key_size, hash_t arg_hash) const
{//only 40-bit hash comparison. { // only 40-bit hash comparison.
return ( 0 == ((hash ^ arg_hash) & HASH_MASK) ) return (0 == ((hash ^ arg_hash) & HASH_MASK)) && key_size == arg_key_size &&
&& key_size == arg_key_size && 0 == memcmp(GetKey(), arg_key, key_size); 0 == memcmp(GetKey(), arg_key, key_size);
} }
bool operator==(const DictEntry& r) const bool operator==(const DictEntry& r) const { return Equal(r.GetKey(), r.key_size, r.hash); }
{ bool operator!=(const DictEntry& r) const { return ! Equal(r.GetKey(), r.key_size, r.hash); }
return Equal(r.GetKey(), r.key_size, r.hash); };
}
bool operator!=(const DictEntry& r) const
{
return ! Equal(r.GetKey(), r.key_size, r.hash);
}
};
} // namespace detail } // namespace detail
class DictIterator { class DictIterator
{
public: public:
using value_type = detail::DictEntry; using value_type = detail::DictEntry;
using reference = detail::DictEntry&; using reference = detail::DictEntry&;
@ -171,13 +171,17 @@ public:
pointer operator->() { return curr; } pointer operator->() { return curr; }
DictIterator& operator++(); DictIterator& operator++();
DictIterator operator++(int) { auto temp(*this); ++*this; return temp; } DictIterator operator++(int)
{
auto temp(*this);
++*this;
return temp;
}
bool operator==( const DictIterator& that ) const { return curr == that.curr; } bool operator==(const DictIterator& that) const { return curr == that.curr; }
bool operator!=( const DictIterator& that ) const { return !(*this == that); } bool operator!=(const DictIterator& that) const { return ! (*this == that); }
private: private:
friend class Dictionary; friend class Dictionary;
DictIterator(const Dictionary* d, detail::DictEntry* begin, detail::DictEntry* end); DictIterator(const Dictionary* d, detail::DictEntry* begin, detail::DictEntry* end);
@ -185,9 +189,10 @@ private:
Dictionary* dict = nullptr; Dictionary* dict = nullptr;
detail::DictEntry* curr = nullptr; detail::DictEntry* curr = nullptr;
detail::DictEntry* end = nullptr; detail::DictEntry* end = nullptr;
}; };
class RobustDictIterator { class RobustDictIterator
{
public: public:
using value_type = detail::DictEntry; using value_type = detail::DictEntry;
using reference = detail::DictEntry&; using reference = detail::DictEntry&;
@ -195,20 +200,25 @@ public:
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag; using iterator_category = std::forward_iterator_tag;
RobustDictIterator() : curr(nullptr) {} RobustDictIterator() : curr(nullptr) { }
RobustDictIterator(Dictionary* d); RobustDictIterator(Dictionary* d);
RobustDictIterator(const RobustDictIterator& other); RobustDictIterator(const RobustDictIterator& other);
RobustDictIterator(RobustDictIterator&& other); RobustDictIterator(RobustDictIterator&& other);
~RobustDictIterator(); ~RobustDictIterator();
reference operator*() { return curr; } reference operator*() { return curr; }
pointer operator->() { return &curr; } pointer operator->() { return &curr; }
RobustDictIterator& operator++(); RobustDictIterator& operator++();
RobustDictIterator operator++(int) { auto temp(*this); ++*this; return temp; } RobustDictIterator operator++(int)
{
auto temp(*this);
++*this;
return temp;
}
bool operator==( const RobustDictIterator& that ) const { return curr == that.curr; } bool operator==(const RobustDictIterator& that) const { return curr == that.curr; }
bool operator!=( const RobustDictIterator& that ) const { return !(*this == that); } bool operator!=(const RobustDictIterator& that) const { return ! (*this == that); }
private: private:
friend class Dictionary; friend class Dictionary;
@ -225,7 +235,7 @@ private:
detail::DictEntry curr; detail::DictEntry curr;
Dictionary* dict = nullptr; Dictionary* dict = nullptr;
int next = -1; int next = -1;
}; };
/** /**
* A dictionary type that uses clustered hashing, a variation of Robinhood/Open Addressing * A dictionary type that uses clustered hashing, a variation of Robinhood/Open Addressing
@ -239,16 +249,18 @@ private:
* the keys but not the values. The dictionary size will be bounded at around 100K. 1M * the keys but not the values. The dictionary size will be bounded at around 100K. 1M
* entries is the absolute limit. Only Connections use that many entries, and that is rare. * entries is the absolute limit. Only Connections use that many entries, and that is rare.
*/ */
class Dictionary { class Dictionary
{
public: public:
explicit Dictionary(DictOrder ordering = UNORDERED, int initial_size = detail::DEFAULT_DICT_SIZE); explicit Dictionary(DictOrder ordering = UNORDERED,
int initial_size = detail::DEFAULT_DICT_SIZE);
~Dictionary(); ~Dictionary();
// Member functions for looking up a key, inserting/changing its // Member functions for looking up a key, inserting/changing its
// contents, and deleting it. These come in two flavors: one // contents, and deleting it. These come in two flavors: one
// which takes a zeek::detail::HashKey, and the other which takes a raw key, // which takes a zeek::detail::HashKey, and the other which takes a raw key,
// its size, and its (unmodulated) hash. // its size, and its (unmodulated) hash.
//lookup may move the key to right place if in the old zone to speed up the next lookup. // lookup may move the key to right place if in the old zone to speed up the next lookup.
void* Lookup(const detail::HashKey* key) const; void* Lookup(const detail::HashKey* key) const;
void* Lookup(const void* key, int key_size, detail::hash_t h) const; void* Lookup(const void* key, int key_size, detail::hash_t h) const;
@ -256,14 +268,17 @@ public:
// If iterators_invalidated is supplied, its value is set to true // If iterators_invalidated is supplied, its value is set to true
// if the removal may have invalidated any existing iterators. // if the removal may have invalidated any existing iterators.
void* Insert(detail::HashKey* key, void* val, bool* iterators_invalidated = nullptr) void* Insert(detail::HashKey* key, void* val, bool* iterators_invalidated = nullptr)
{ return Insert(key->TakeKey(), key->Size(), key->Hash(), val, false, iterators_invalidated); } {
return Insert(key->TakeKey(), key->Size(), key->Hash(), val, false, iterators_invalidated);
}
// If copy_key is true, then the key is copied, otherwise it's assumed // If copy_key is true, then the key is copied, otherwise it's assumed
// that it's a heap pointer that now belongs to the Dictionary to // that it's a heap pointer that now belongs to the Dictionary to
// manage as needed. // manage as needed.
// If iterators_invalidated is supplied, its value is set to true // If iterators_invalidated is supplied, its value is set to true
// if the removal may have invalidated any existing iterators. // if the removal may have invalidated any existing iterators.
void* Insert(void* key, int key_size, detail::hash_t hash, void* val, bool copy_key, bool* iterators_invalidated = nullptr); void* Insert(void* key, int key_size, detail::hash_t hash, void* val, bool copy_key,
bool* iterators_invalidated = nullptr);
// Removes the given element. Returns a pointer to the element in // Removes the given element. Returns a pointer to the element in
// case it needs to be deleted. Returns 0 if no such element exists. // case it needs to be deleted. Returns 0 if no such element exists.
@ -271,23 +286,23 @@ public:
// If iterators_invalidated is supplied, its value is set to true // If iterators_invalidated is supplied, its value is set to true
// if the removal may have invalidated any existing iterators. // if the removal may have invalidated any existing iterators.
void* Remove(const detail::HashKey* key, bool* iterators_invalidated = nullptr) void* Remove(const detail::HashKey* key, bool* iterators_invalidated = nullptr)
{ return Remove(key->Key(), key->Size(), key->Hash(), false, iterators_invalidated); } {
void* Remove(const void* key, int key_size, detail::hash_t hash, bool dont_delete = false, bool* iterators_invalidated = nullptr); return Remove(key->Key(), key->Size(), key->Hash(), false, iterators_invalidated);
}
void* Remove(const void* key, int key_size, detail::hash_t hash, bool dont_delete = false,
bool* iterators_invalidated = nullptr);
// Number of entries. // Number of entries.
int Length() const int Length() const { return num_entries; }
{ return num_entries; }
// Largest it's ever been. // Largest it's ever been.
int MaxLength() const int MaxLength() const { return max_entries; }
{ return max_entries; }
// Total number of entries ever. // Total number of entries ever.
uint64_t NumCumulativeInserts() const uint64_t NumCumulativeInserts() const { return cum_entries; }
{ return cum_entries; }
// True if the dictionary is ordered, false otherwise. // True if the dictionary is ordered, false otherwise.
int IsOrdered() const { return order != nullptr; } int IsOrdered() const { return order != nullptr; }
// If the dictionary is ordered then returns the n'th entry's value; // If the dictionary is ordered then returns the n'th entry's value;
// the second method also returns the key. The first entry inserted // the second method also returns the key. The first entry inserted
@ -316,14 +331,17 @@ public:
// //
// If return_hash is true, a HashKey for the entry is returned in h, // If return_hash is true, a HashKey for the entry is returned in h,
// which should be delete'd when no longer needed. // which should be delete'd when no longer needed.
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]] [[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
IterCookie* InitForIteration() const; "iteration.")]] IterCookie*
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]] InitForIteration() const;
void* NextEntry(detail::HashKey*& h, IterCookie*& cookie, bool return_hash) const; [[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]] "iteration.")]] void*
void StopIteration(IterCookie* cookie) const; NextEntry(detail::HashKey*& h, IterCookie*& cookie, bool return_hash) const;
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
"iteration.")]] void
StopIteration(IterCookie* cookie) const;
void SetDeleteFunc(dict_delete_func f) { delete_func = f; } void SetDeleteFunc(dict_delete_func f) { delete_func = f; }
// With a robust cookie, it is safe to change the dictionary while // With a robust cookie, it is safe to change the dictionary while
// iterating. This means that (i) we will eventually visit all // iterating. This means that (i) we will eventually visit all
@ -331,23 +349,25 @@ public:
// and (ii) we won't visit any still-unseen entries which are getting // and (ii) we won't visit any still-unseen entries which are getting
// removed. (We don't get this for free, so only use it if // removed. (We don't get this for free, so only use it if
// necessary.) // necessary.)
[[deprecated("Remove in v5.1. Use begin_robust() and the standard-library-compatible version of iteration.")]] [[deprecated("Remove in v5.1. Use begin_robust() and the standard-library-compatible version "
void MakeRobustCookie(IterCookie* cookie); "of iteration.")]] void
MakeRobustCookie(IterCookie* cookie);
// Remove all entries. // Remove all entries.
void Clear(); void Clear();
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
size_t MemoryAllocation() const; "GHI-572.")]] size_t
MemoryAllocation() const;
/// The capacity of the table, Buckets + Overflow Size. /// The capacity of the table, Buckets + Overflow Size.
int Capacity(bool expected = false) const; int Capacity(bool expected = false) const;
//Debugging // Debugging
#ifdef DEBUG #ifdef DEBUG
void AssertValid() const; void AssertValid() const;
#endif//DEBUG #endif // DEBUG
void Dump(int level=0) const; void Dump(int level = 0) const;
void DistanceStats(int& max_distance, int* distances = 0, int num_distances = 0) const; void DistanceStats(int& max_distance, int* distances = 0, int num_distances = 0) const;
void DumpKeys() const; void DumpKeys() const;
@ -362,12 +382,12 @@ public:
using reverse_iterator = std::reverse_iterator<iterator>; using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>; using const_reverse_iterator = std::reverse_iterator<const_iterator>;
iterator begin() { return { this, table, table + Capacity() }; } iterator begin() { return {this, table, table + Capacity()}; }
iterator end() { return { this, table + Capacity(), table + Capacity() }; } iterator end() { return {this, table + Capacity(), table + Capacity()}; }
const_iterator begin() const { return { this, table, table + Capacity() }; } const_iterator begin() const { return {this, table, table + Capacity()}; }
const_iterator end() const { return { this, table + Capacity(), table + Capacity() }; } const_iterator end() const { return {this, table + Capacity(), table + Capacity()}; }
const_iterator cbegin() { return { this, table, table + Capacity() }; } const_iterator cbegin() { return {this, table, table + Capacity()}; }
const_iterator cend() { return { this, table + Capacity(), table + Capacity() }; } const_iterator cend() { return {this, table + Capacity(), table + Capacity()}; }
RobustDictIterator begin_robust() { return MakeRobustIterator(); } RobustDictIterator begin_robust() { return MakeRobustIterator(); }
RobustDictIterator end_robust() { return RobustDictIterator(); } RobustDictIterator end_robust() { return RobustDictIterator(); }
@ -380,7 +400,7 @@ private:
/// Buckets of the table, not including overflow size. /// Buckets of the table, not including overflow size.
int Buckets(bool expected = false) const; int Buckets(bool expected = false) const;
//bucket math // bucket math
int Log2(int num) const; int Log2(int num) const;
int ThresholdEntries() const; int ThresholdEntries() const;
@ -419,47 +439,55 @@ private:
void Init(); void Init();
// Iteration // Iteration
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]] [[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
IterCookie* InitForIterationNonConst(); "iteration.")]] IterCookie*
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]] InitForIterationNonConst();
void* NextEntryNonConst(detail::HashKey*& h, IterCookie*& cookie, bool return_hash); [[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]] "iteration.")]] void*
void StopIterationNonConst(IterCookie* cookie); NextEntryNonConst(detail::HashKey*& h, IterCookie*& cookie, bool return_hash);
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
"iteration.")]] void
StopIterationNonConst(IterCookie* cookie);
//Lookup // Lookup
int LinearLookupIndex(const void* key, int key_size, detail::hash_t hash) const; int LinearLookupIndex(const void* key, int key_size, detail::hash_t hash) const;
int LookupIndex(const void* key, int key_size, detail::hash_t hash, int* insert_position = nullptr, int LookupIndex(const void* key, int key_size, detail::hash_t hash,
int* insert_distance = nullptr); int* insert_position = nullptr, int* insert_distance = nullptr);
int LookupIndex(const void* key, int key_size, detail::hash_t hash, int begin, int end, int LookupIndex(const void* key, int key_size, detail::hash_t hash, int begin, int end,
int* insert_position = nullptr, int* insert_distance = nullptr); int* insert_position = nullptr, int* insert_distance = nullptr);
/// Insert entry, Adjust cookies when necessary. /// Insert entry, Adjust cookies when necessary.
void InsertRelocateAndAdjust(detail::DictEntry& entry, int insert_position); void InsertRelocateAndAdjust(detail::DictEntry& entry, int insert_position);
/// insert entry into position, relocate other entries when necessary. /// insert entry into position, relocate other entries when necessary.
void InsertAndRelocate(detail::DictEntry& entry, int insert_position, int* last_affected_position = nullptr); void InsertAndRelocate(detail::DictEntry& entry, int insert_position,
int* last_affected_position = nullptr);
/// Adjust Cookies on Insert. /// Adjust Cookies on Insert.
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration and the version that takes a RobustDictIterator.")]] [[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration and the "
void AdjustOnInsert(IterCookie* c, const detail::DictEntry& entry, int insert_position, int last_affected_position); "version that takes a RobustDictIterator.")]] void
void AdjustOnInsert(RobustDictIterator* c, const detail::DictEntry& entry, AdjustOnInsert(IterCookie* c, const detail::DictEntry& entry, int insert_position,
int insert_position, int last_affected_position); int last_affected_position);
void AdjustOnInsert(RobustDictIterator* c, const detail::DictEntry& entry, int insert_position,
int last_affected_position);
///Remove, Relocate & Adjust cookies. /// Remove, Relocate & Adjust cookies.
detail::DictEntry RemoveRelocateAndAdjust(int position); detail::DictEntry RemoveRelocateAndAdjust(int position);
///Remove & Relocate /// Remove & Relocate
detail::DictEntry RemoveAndRelocate(int position, int* last_affected_position = nullptr); detail::DictEntry RemoveAndRelocate(int position, int* last_affected_position = nullptr);
///Adjust safe cookies after Removal of entry at position. /// Adjust safe cookies after Removal of entry at position.
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration and the version that takes a RobustDictIterator.")]] [[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration and the "
void AdjustOnRemove(IterCookie* c, const detail::DictEntry& entry, int position, int last_affected_position); "version that takes a RobustDictIterator.")]] void
void AdjustOnRemove(RobustDictIterator* c, const detail::DictEntry& entry, AdjustOnRemove(IterCookie* c, const detail::DictEntry& entry, int position,
int position, int last_affected_position); int last_affected_position);
void AdjustOnRemove(RobustDictIterator* c, const detail::DictEntry& entry, int position,
int last_affected_position);
bool Remapping() const { return remap_end >= 0;} //remap in reverse order. bool Remapping() const { return remap_end >= 0; } // remap in reverse order.
///One round of remap. /// One round of remap.
void Remap(); void Remap();
// Remap an item in position to a new position. Returns true if the relocation was // Remap an item in position to a new position. Returns true if the relocation was
@ -471,16 +499,18 @@ private:
bool HaveOnlyRobustIterators() const bool HaveOnlyRobustIterators() const
{ {
return (num_iterators == 0) || ((cookies ? cookies->size() : 0) + (iterators ? iterators->size() : 0) == num_iterators); return (num_iterators == 0) ||
((cookies ? cookies->size() : 0) + (iterators ? iterators->size() : 0) ==
num_iterators);
} }
RobustDictIterator MakeRobustIterator(); RobustDictIterator MakeRobustIterator();
detail::DictEntry GetNextRobustIteration(RobustDictIterator* iter); detail::DictEntry GetNextRobustIteration(RobustDictIterator* iter);
void IncrIters() { ++num_iterators; } void IncrIters() { ++num_iterators; }
void DecrIters() { --num_iterators; } void DecrIters() { --num_iterators; }
//alligned on 8-bytes with 4-leading bytes. 7*8=56 bytes a dictionary. // alligned on 8-bytes with 4-leading bytes. 7*8=56 bytes a dictionary.
// when sizeup but the current mapping is in progress. the current mapping will be ignored // when sizeup but the current mapping is in progress. the current mapping will be ignored
// as it will be remapped to new dict size anyway. however, the missed count is recorded // as it will be remapped to new dict size anyway. however, the missed count is recorded
@ -507,58 +537,64 @@ private:
// Order means the order of insertion. means no deletion until exit. will be inefficient. // Order means the order of insertion. means no deletion until exit. will be inefficient.
std::vector<detail::DictEntry>* order = nullptr; std::vector<detail::DictEntry>* order = nullptr;
}; };
/* /*
* Template specialization of Dictionary that stores pointers for values. * Template specialization of Dictionary that stores pointers for values.
*/ */
template<typename T> template <typename T> class PDict : public Dictionary
class PDict : public Dictionary { {
public: public:
explicit PDict(DictOrder ordering = UNORDERED, int initial_size = 0) : explicit PDict(DictOrder ordering = UNORDERED, int initial_size = 0)
Dictionary(ordering, initial_size) {} : Dictionary(ordering, initial_size)
{
}
T* Lookup(const char* key) const T* Lookup(const char* key) const
{ {
detail::HashKey h(key); detail::HashKey h(key);
return (T*) Dictionary::Lookup(&h); return (T*)Dictionary::Lookup(&h);
} }
T* Lookup(const detail::HashKey* key) const T* Lookup(const detail::HashKey* key) const { return (T*)Dictionary::Lookup(key); }
{ return (T*) Dictionary::Lookup(key); }
T* Insert(const char* key, T* val, bool* iterators_invalidated = nullptr) T* Insert(const char* key, T* val, bool* iterators_invalidated = nullptr)
{ {
detail::HashKey h(key); detail::HashKey h(key);
return (T*) Dictionary::Insert(&h, (void*) val, iterators_invalidated); return (T*)Dictionary::Insert(&h, (void*)val, iterators_invalidated);
} }
T* Insert(detail::HashKey* key, T* val, bool* iterators_invalidated = nullptr) T* Insert(detail::HashKey* key, T* val, bool* iterators_invalidated = nullptr)
{ return (T*) Dictionary::Insert(key, (void*) val, iterators_invalidated); } {
T* NthEntry(int n) const return (T*)Dictionary::Insert(key, (void*)val, iterators_invalidated);
{ return (T*) Dictionary::NthEntry(n); } }
T* NthEntry(int n) const { return (T*)Dictionary::NthEntry(n); }
T* NthEntry(int n, const char*& key) const T* NthEntry(int n, const char*& key) const
{ {
int key_len; int key_len;
return (T*) Dictionary::NthEntry(n, (const void*&) key, key_len); return (T*)Dictionary::NthEntry(n, (const void*&)key, key_len);
} }
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration.")]] [[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration.")]] T*
T* NextEntry(IterCookie*& cookie) const NextEntry(IterCookie*& cookie) const
{ {
detail::HashKey* h; detail::HashKey* h;
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return (T*) Dictionary::NextEntry(h, cookie, false); return (T*)Dictionary::NextEntry(h, cookie, false);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} }
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration.")]] [[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration.")]] T*
T* NextEntry(detail::HashKey*& h, IterCookie*& cookie) const NextEntry(detail::HashKey*& h, IterCookie*& cookie) const
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return (T*) Dictionary::NextEntry(h, cookie, true); return (T*)Dictionary::NextEntry(h, cookie, true);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} }
T* RemoveEntry(const detail::HashKey* key, bool* iterators_invalidated = nullptr) T* RemoveEntry(const detail::HashKey* key, bool* iterators_invalidated = nullptr)
{ return (T*) Remove(key->Key(), key->Size(), key->Hash(), false, iterators_invalidated); } {
return (T*)Remove(key->Key(), key->Size(), key->Hash(), false, iterators_invalidated);
}
T* RemoveEntry(const detail::HashKey& key, bool* iterators_invalidated = nullptr) T* RemoveEntry(const detail::HashKey& key, bool* iterators_invalidated = nullptr)
{ return (T*) Remove(key.Key(), key.Size(), key.Hash(), false, iterators_invalidated); } {
}; return (T*)Remove(key.Key(), key.Size(), key.Hash(), false, iterators_invalidated);
}
};
} // namespace zeek } // namespace zeek

View file

@ -1,20 +1,20 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Discard.h" #include "zeek/Discard.h"
#include <algorithm> #include <algorithm>
#include "zeek/ZeekString.h"
#include "zeek/RunState.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/Var.h"
#include "zeek/Val.h"
#include "zeek/IP.h" #include "zeek/IP.h"
#include "zeek/Reporter.h" // for InterpreterException #include "zeek/Reporter.h" // for InterpreterException
#include "zeek/RunState.h"
#include "zeek/Val.h"
#include "zeek/Var.h"
#include "zeek/ZeekString.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
Discarder::Discarder() Discarder::Discarder()
{ {
@ -26,9 +26,7 @@ Discarder::Discarder()
discarder_maxlen = static_cast<int>(id::find_val("discarder_maxlen")->AsCount()); discarder_maxlen = static_cast<int>(id::find_val("discarder_maxlen")->AsCount());
} }
Discarder::~Discarder() Discarder::~Discarder() { }
{
}
bool Discarder::IsActive() bool Discarder::IsActive()
{ {
@ -58,8 +56,7 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
} }
int proto = ip->NextProto(); int proto = ip->NextProto();
if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && proto != IPPROTO_ICMP )
proto != IPPROTO_ICMP )
// This is not a protocol we understand. // This is not a protocol we understand.
return false; return false;
@ -69,14 +66,13 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
return false; return false;
int ip_hdr_len = ip->HdrLen(); int ip_hdr_len = ip->HdrLen();
len -= ip_hdr_len; // remove IP header len -= ip_hdr_len; // remove IP header
caplen -= ip_hdr_len; caplen -= ip_hdr_len;
bool is_tcp = (proto == IPPROTO_TCP); bool is_tcp = (proto == IPPROTO_TCP);
bool is_udp = (proto == IPPROTO_UDP); bool is_udp = (proto == IPPROTO_UDP);
int min_hdr_len = is_tcp ? int min_hdr_len =
sizeof(struct tcphdr) : is_tcp ? sizeof(struct tcphdr) : (is_udp ? sizeof(struct udphdr) : sizeof(struct icmp));
(is_udp ? sizeof(struct udphdr) : sizeof(struct icmp));
if ( len < min_hdr_len || caplen < min_hdr_len ) if ( len < min_hdr_len || caplen < min_hdr_len )
// we don't have a complete protocol header // we don't have a complete protocol header
@ -90,7 +86,7 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
{ {
if ( check_tcp ) if ( check_tcp )
{ {
const struct tcphdr* tp = (const struct tcphdr*) data; const struct tcphdr* tp = (const struct tcphdr*)data;
int th_len = tp->th_off * 4; int th_len = tp->th_off * 4;
zeek::Args args{ zeek::Args args{
@ -114,8 +110,8 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
{ {
if ( check_udp ) if ( check_udp )
{ {
const struct udphdr* up = (const struct udphdr*) data; const struct udphdr* up = (const struct udphdr*)data;
int uh_len = sizeof (struct udphdr); int uh_len = sizeof(struct udphdr);
zeek::Args args{ zeek::Args args{
ip->ToPktHdrVal(), ip->ToPktHdrVal(),
@ -138,7 +134,7 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
{ {
if ( check_icmp ) if ( check_icmp )
{ {
const struct icmp* ih = (const struct icmp*) data; const struct icmp* ih = (const struct icmp*)data;
zeek::Args args{ip->ToPktHdrVal()}; zeek::Args args{ip->ToPktHdrVal()};
@ -168,4 +164,4 @@ Val* Discarder::BuildData(const u_char* data, int hdrlen, int len, int caplen)
return new StringVal(new String(data, len, true)); return new StringVal(new String(data, len, true));
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -7,16 +7,19 @@
#include "zeek/IntrusivePtr.h" #include "zeek/IntrusivePtr.h"
namespace zeek { namespace zeek
{
class IP_Hdr; class IP_Hdr;
class Val; class Val;
class Func; class Func;
using FuncPtr = IntrusivePtr<Func>; using FuncPtr = IntrusivePtr<Func>;
namespace detail { namespace detail
{
class Discarder { class Discarder
{
public: public:
Discarder(); Discarder();
~Discarder(); ~Discarder();
@ -35,7 +38,7 @@ protected:
// Maximum amount of application data passed to filtering functions. // Maximum amount of application data passed to filtering functions.
int discarder_maxlen; int discarder_maxlen;
}; };
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,12 +1,13 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/EquivClass.h" #include "zeek/EquivClass.h"
#include "zeek/CCL.h" #include "zeek/CCL.h"
#include "zeek/util.h" #include "zeek/util.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
EquivClass::EquivClass(int arg_size) EquivClass::EquivClass(int arg_size)
{ {
@ -38,11 +39,11 @@ EquivClass::EquivClass(int arg_size)
EquivClass::~EquivClass() EquivClass::~EquivClass()
{ {
delete [] fwd; delete[] fwd;
delete [] bck; delete[] bck;
delete [] equiv_class; delete[] equiv_class;
delete [] rep; delete[] rep;
delete [] ccl_flags; delete[] ccl_flags;
} }
void EquivClass::ConvertCCL(CCL* ccl) void EquivClass::ConvertCCL(CCL* ccl)
@ -163,7 +164,6 @@ void EquivClass::CCL_Use(CCL* ccl)
} }
} }
void EquivClass::UniqueChar(int sym) void EquivClass::UniqueChar(int sym)
{ {
// If until now the character has been a proper subset of // If until now the character has been a proper subset of
@ -183,7 +183,7 @@ void EquivClass::Dump(FILE* f)
{ {
fprintf(f, "%d symbols in EC yielded %d ecs\n", size, num_ecs); fprintf(f, "%d symbols in EC yielded %d ecs\n", size, num_ecs);
for ( int i = 0; i < size; ++i ) for ( int i = 0; i < size; ++i )
if ( SymEquivClass(i) != 0 ) // skip usually huge default ec if ( SymEquivClass(i) != 0 ) // skip usually huge default ec
fprintf(f, "map %d ('%c') -> %d\n", i, i, SymEquivClass(i)); fprintf(f, "map %d ('%c') -> %d\n", i, i, SymEquivClass(i));
} }
@ -192,4 +192,4 @@ int EquivClass::Size() const
return padded_sizeof(*this) + util::pad_size(sizeof(int) * size * (ccl_flags ? 5 : 4)); return padded_sizeof(*this) + util::pad_size(sizeof(int) * size * (ccl_flags ? 5 : 4));
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -4,11 +4,13 @@
#include <stdio.h> #include <stdio.h>
namespace zeek::detail { namespace zeek::detail
{
class CCL; class CCL;
class EquivClass { class EquivClass
{
public: public:
explicit EquivClass(int size); explicit EquivClass(int size);
~EquivClass(); ~EquivClass();
@ -22,26 +24,26 @@ public:
void ConvertCCL(CCL* ccl); void ConvertCCL(CCL* ccl);
bool IsRep(int sym) const { return rep[sym] == sym; } bool IsRep(int sym) const { return rep[sym] == sym; }
int EquivRep(int sym) const { return rep[sym]; } int EquivRep(int sym) const { return rep[sym]; }
int SymEquivClass(int sym) const { return equiv_class[sym]; } int SymEquivClass(int sym) const { return equiv_class[sym]; }
int* EquivClasses() const { return equiv_class; } int* EquivClasses() const { return equiv_class; }
int NumSyms() const { return size; } int NumSyms() const { return size; }
int NumClasses() const { return num_ecs; } int NumClasses() const { return num_ecs; }
void Dump(FILE* f); void Dump(FILE* f);
int Size() const; int Size() const;
protected: protected:
int size; // size of character set int size; // size of character set
int num_ecs; // size of equivalence classes int num_ecs; // size of equivalence classes
int* fwd; // forward list of different classes int* fwd; // forward list of different classes
int* bck; // backward list int* bck; // backward list
int* equiv_class; // symbol's equivalence class int* equiv_class; // symbol's equivalence class
int* rep; // representative for symbol's equivalence class int* rep; // representative for symbol's equivalence class
int* ccl_flags; int* ccl_flags;
int ec_nil, no_class, no_rep; int ec_nil, no_class, no_rep;
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,31 +1,27 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Event.h" #include "zeek/Event.h"
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/NetVar.h" #include "zeek/NetVar.h"
#include "zeek/RunState.h"
#include "zeek/Trigger.h" #include "zeek/Trigger.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/plugin/Manager.h"
#include "zeek/iosource/Manager.h" #include "zeek/iosource/Manager.h"
#include "zeek/iosource/PktSrc.h" #include "zeek/iosource/PktSrc.h"
#include "zeek/RunState.h" #include "zeek/plugin/Manager.h"
#include "zeek/zeek-config.h"
zeek::EventMgr zeek::event_mgr; zeek::EventMgr zeek::event_mgr;
zeek::EventMgr& mgr = zeek::event_mgr; zeek::EventMgr& mgr = zeek::event_mgr;
namespace zeek { namespace zeek
{
Event::Event(EventHandlerPtr arg_handler, zeek::Args arg_args, Event::Event(EventHandlerPtr arg_handler, zeek::Args arg_args, util::detail::SourceID arg_src,
util::detail::SourceID arg_src, analyzer::ID arg_aid, analyzer::ID arg_aid, Obj* arg_obj)
Obj* arg_obj) : handler(arg_handler), args(std::move(arg_args)), src(arg_src), aid(arg_aid), obj(arg_obj),
: handler(arg_handler),
args(std::move(arg_args)),
src(arg_src),
aid(arg_aid),
obj(arg_obj),
next_event(nullptr) next_event(nullptr)
{ {
if ( obj ) if ( obj )
@ -94,8 +90,7 @@ EventMgr::~EventMgr()
Unref(src_val); Unref(src_val);
} }
void EventMgr::Enqueue(const EventHandlerPtr& h, Args vl, void EventMgr::Enqueue(const EventHandlerPtr& h, Args vl, util::detail::SourceID src,
util::detail::SourceID src,
analyzer::ID aid, Obj* obj) analyzer::ID aid, Obj* obj)
{ {
QueueEvent(new Event(h, std::move(vl), src, aid, obj)); QueueEvent(new Event(h, std::move(vl), src, aid, obj));
@ -219,4 +214,4 @@ void EventMgr::InitPostScript()
reporter->FatalError("Failed to register event manager FD with iosource_mgr"); reporter->FatalError("Failed to register event manager FD with iosource_mgr");
} }
} // namespace zeek } // namespace zeek

View file

@ -5,30 +5,32 @@
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include "zeek/Flare.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/ZeekArgs.h"
#include "zeek/ZeekList.h" #include "zeek/ZeekList.h"
#include "zeek/analyzer/Analyzer.h" #include "zeek/analyzer/Analyzer.h"
#include "zeek/iosource/IOSource.h" #include "zeek/iosource/IOSource.h"
#include "zeek/Flare.h"
#include "zeek/ZeekArgs.h"
#include "zeek/IntrusivePtr.h"
namespace zeek { namespace zeek
{
class EventMgr; class EventMgr;
class Event final : public Obj { class Event final : public Obj
{
public: public:
Event(EventHandlerPtr handler, zeek::Args args, Event(EventHandlerPtr handler, zeek::Args args,
util::detail::SourceID src = util::detail::SOURCE_LOCAL, analyzer::ID aid = 0, util::detail::SourceID src = util::detail::SOURCE_LOCAL, analyzer::ID aid = 0,
Obj* obj = nullptr); Obj* obj = nullptr);
void SetNext(Event* n) { next_event = n; } void SetNext(Event* n) { next_event = n; }
Event* NextEvent() const { return next_event; } Event* NextEvent() const { return next_event; }
util::detail::SourceID Source() const { return src; } util::detail::SourceID Source() const { return src; }
analyzer::ID Analyzer() const { return aid; } analyzer::ID Analyzer() const { return aid; }
EventHandlerPtr Handler() const { return handler; } EventHandlerPtr Handler() const { return handler; }
const zeek::Args& Args() const { return args; } const zeek::Args& Args() const { return args; }
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
@ -45,9 +47,10 @@ protected:
analyzer::ID aid; analyzer::ID aid;
Obj* obj; Obj* obj;
Event* next_event; Event* next_event;
}; };
class EventMgr final : public Obj, public iosource::IOSource { class EventMgr final : public Obj, public iosource::IOSource
{
public: public:
EventMgr(); EventMgr();
~EventMgr() override; ~EventMgr() override;
@ -72,28 +75,27 @@ public:
* A version of Enqueue() taking a variable number of arguments. * A version of Enqueue() taking a variable number of arguments.
*/ */
template <class... Args> template <class... Args>
std::enable_if_t< std::enable_if_t<std::is_convertible_v<std::tuple_element_t<0, std::tuple<Args...>>, ValPtr>>
std::is_convertible_v<
std::tuple_element_t<0, std::tuple<Args...>>, ValPtr>>
Enqueue(const EventHandlerPtr& h, Args&&... args) Enqueue(const EventHandlerPtr& h, Args&&... args)
{ return Enqueue(h, zeek::Args{std::forward<Args>(args)...}); } {
return Enqueue(h, zeek::Args{std::forward<Args>(args)...});
}
void Dispatch(Event* event, bool no_remote = false); void Dispatch(Event* event, bool no_remote = false);
void Drain(); void Drain();
bool IsDraining() const { return draining; } bool IsDraining() const { return draining; }
bool HasEvents() const { return head != nullptr; } bool HasEvents() const { return head != nullptr; }
// Returns the source ID of last raised event. // Returns the source ID of last raised event.
util::detail::SourceID CurrentSource() const { return current_src; } util::detail::SourceID CurrentSource() const { return current_src; }
// Returns the ID of the analyzer which raised the last event, or 0 if // Returns the ID of the analyzer which raised the last event, or 0 if
// non-analyzer event. // non-analyzer event.
analyzer::ID CurrentAnalyzer() const { return current_aid; } analyzer::ID CurrentAnalyzer() const { return current_aid; }
int Size() const int Size() const { return num_events_queued - num_events_dispatched; }
{ return num_events_queued - num_events_dispatched; }
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
@ -115,8 +117,8 @@ protected:
RecordVal* src_val; RecordVal* src_val;
bool draining; bool draining;
detail::Flare queue_flare; detail::Flare queue_flare;
}; };
extern EventMgr event_mgr; extern EventMgr event_mgr;
} // namespace zeek } // namespace zeek

View file

@ -1,17 +1,17 @@
#include "zeek/EventHandler.h" #include "zeek/EventHandler.h"
#include "zeek/Event.h"
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/Event.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/Scope.h"
#include "zeek/NetVar.h"
#include "zeek/ID.h" #include "zeek/ID.h"
#include "zeek/NetVar.h"
#include "zeek/Scope.h"
#include "zeek/Var.h" #include "zeek/Var.h"
#include "zeek/broker/Manager.h"
#include "zeek/broker/Data.h" #include "zeek/broker/Data.h"
#include "zeek/broker/Manager.h"
namespace zeek { namespace zeek
{
EventHandler::EventHandler(std::string arg_name) EventHandler::EventHandler(std::string arg_name)
{ {
@ -24,9 +24,7 @@ EventHandler::EventHandler(std::string arg_name)
EventHandler::operator bool() const EventHandler::operator bool() const
{ {
return enabled && ((local && local->HasBodies()) return enabled && ((local && local->HasBodies()) || generate_always || ! auto_publish.empty());
|| generate_always
|| ! auto_publish.empty());
} }
const FuncTypePtr& EventHandler::GetType(bool check_export) const FuncTypePtr& EventHandler::GetType(bool check_export)
@ -34,8 +32,8 @@ const FuncTypePtr& EventHandler::GetType(bool check_export)
if ( type ) if ( type )
return type; return type;
const auto& id = detail::lookup_ID(name.data(), detail::current_module.c_str(), const auto& id =
false, false, check_export); detail::lookup_ID(name.data(), detail::current_module.c_str(), false, false, check_export);
if ( ! id ) if ( ! id )
return FuncType::nil; return FuncType::nil;
@ -48,7 +46,9 @@ const FuncTypePtr& EventHandler::GetType(bool check_export)
} }
void EventHandler::SetFunc(FuncPtr f) void EventHandler::SetFunc(FuncPtr f)
{ local = std::move(f); } {
local = std::move(f);
}
void EventHandler::Call(Args* vl, bool no_remote) void EventHandler::Call(Args* vl, bool no_remote)
{ {
@ -85,7 +85,7 @@ void EventHandler::Call(Args* vl, bool no_remote)
if ( valid_args ) if ( valid_args )
{ {
for ( auto it = auto_publish.begin(); ; ) for ( auto it = auto_publish.begin();; )
{ {
const auto& topic = *it; const auto& topic = *it;
++it; ++it;
@ -119,10 +119,10 @@ void EventHandler::NewEvent(Args* vl)
auto vargs = MakeCallArgumentVector(*vl, GetType()->Params()); auto vargs = MakeCallArgumentVector(*vl, GetType()->Params());
auto ev = new Event(new_event, { auto ev = new Event(new_event, {
make_intrusive<StringVal>(name), make_intrusive<StringVal>(name),
std::move(vargs), std::move(vargs),
}); });
event_mgr.Dispatch(ev); event_mgr.Dispatch(ev);
} }
} // namespace zeek } // namespace zeek

View file

@ -2,97 +2,98 @@
#pragma once #pragma once
#include <unordered_set>
#include <string> #include <string>
#include <unordered_set>
#include "zeek/ZeekList.h"
#include "zeek/ZeekArgs.h"
#include "zeek/Type.h" #include "zeek/Type.h"
#include "zeek/ZeekArgs.h"
#include "zeek/ZeekList.h"
namespace zeek { namespace zeek
{
class Func; class Func;
using FuncPtr = IntrusivePtr<Func>; using FuncPtr = IntrusivePtr<Func>;
class EventHandler { class EventHandler
{
public: public:
explicit EventHandler(std::string name); explicit EventHandler(std::string name);
const char* Name() { return name.data(); } const char* Name() { return name.data(); }
const FuncPtr& GetFunc() const FuncPtr& GetFunc() { return local; }
{ return local; }
const FuncTypePtr& GetType(bool check_export = true); const FuncTypePtr& GetType(bool check_export = true);
void SetFunc(FuncPtr f); void SetFunc(FuncPtr f);
void AutoPublish(std::string topic) void AutoPublish(std::string topic) { auto_publish.insert(std::move(topic)); }
{
auto_publish.insert(std::move(topic));
}
void AutoUnpublish(const std::string& topic) void AutoUnpublish(const std::string& topic) { auto_publish.erase(topic); }
{
auto_publish.erase(topic);
}
void Call(zeek::Args* vl, bool no_remote = false); void Call(zeek::Args* vl, bool no_remote = false);
// Returns true if there is at least one local or remote handler. // Returns true if there is at least one local or remote handler.
explicit operator bool() const; explicit operator bool() const;
void SetUsed() { used = true; } void SetUsed() { used = true; }
bool Used() { return used; } bool Used() { return used; }
// Handlers marked as error handlers will not be called recursively to // Handlers marked as error handlers will not be called recursively to
// avoid infinite loops if they trigger a similar error themselves. // avoid infinite loops if they trigger a similar error themselves.
void SetErrorHandler() { error_handler = true; } void SetErrorHandler() { error_handler = true; }
bool ErrorHandler() { return error_handler; } bool ErrorHandler() { return error_handler; }
void SetEnable(bool arg_enable) { enabled = arg_enable; } void SetEnable(bool arg_enable) { enabled = arg_enable; }
// Flags the event as interesting even if there is no body defined. In // Flags the event as interesting even if there is no body defined. In
// particular, this will then still pass the event on to plugins. // particular, this will then still pass the event on to plugins.
void SetGenerateAlways() { generate_always = true; } void SetGenerateAlways() { generate_always = true; }
bool GenerateAlways() { return generate_always; } bool GenerateAlways() { return generate_always; }
private: private:
void NewEvent(zeek::Args* vl); // Raise new_event() meta event. void NewEvent(zeek::Args* vl); // Raise new_event() meta event.
std::string name; std::string name;
FuncPtr local; FuncPtr local;
FuncTypePtr type; FuncTypePtr type;
bool used; // this handler is indeed used somewhere bool used; // this handler is indeed used somewhere
bool enabled; bool enabled;
bool error_handler; // this handler reports error messages. bool error_handler; // this handler reports error messages.
bool generate_always; bool generate_always;
std::unordered_set<std::string> auto_publish; std::unordered_set<std::string> auto_publish;
}; };
// Encapsulates a ptr to an event handler to overload the boolean operator. // Encapsulates a ptr to an event handler to overload the boolean operator.
class EventHandlerPtr { class EventHandlerPtr
{
public: public:
EventHandlerPtr(EventHandler* p = nullptr) { handler = p; } EventHandlerPtr(EventHandler* p = nullptr) { handler = p; }
EventHandlerPtr(const EventHandlerPtr& h) { handler = h.handler; } EventHandlerPtr(const EventHandlerPtr& h) { handler = h.handler; }
const EventHandlerPtr& operator=(EventHandler* p) const EventHandlerPtr& operator=(EventHandler* p)
{ handler = p; return *this; } {
handler = p;
return *this;
}
const EventHandlerPtr& operator=(const EventHandlerPtr& h) const EventHandlerPtr& operator=(const EventHandlerPtr& h)
{ handler = h.handler; return *this; } {
handler = h.handler;
return *this;
}
bool operator==(const EventHandlerPtr& h) const bool operator==(const EventHandlerPtr& h) const { return handler == h.handler; }
{ return handler == h.handler; }
EventHandler* Ptr() { return handler; } EventHandler* Ptr() { return handler; }
explicit operator bool() const { return handler && *handler; } explicit operator bool() const { return handler && *handler; }
EventHandler* operator->() { return handler; } EventHandler* operator->() { return handler; }
const EventHandler* operator->() const { return handler; } const EventHandler* operator->() const { return handler; }
private: private:
EventHandler* handler; EventHandler* handler;
}; };
} // namespace zeek } // namespace zeek

View file

@ -1,9 +1,10 @@
#include "zeek/EventLauncher.h"
#include "zeek/Conn.h"
#include "zeek/Event.h"
#include "zeek/File.h"
#include "zeek/NetVar.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/analyzer/Analyzer.h" #include "zeek/analyzer/Analyzer.h"
#include "zeek/EventLauncher.h"
#include "zeek/Event.h"
#include "zeek/NetVar.h"
#include "zeek/Conn.h"
#include "zeek/File.h"
#include "event.bif.func_def" #include "event.bif.func_def"

View file

@ -1,10 +1,12 @@
#include "zeek/EventRegistry.h" #include "zeek/EventRegistry.h"
#include "zeek/EventHandler.h" #include "zeek/EventHandler.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/RE.h" #include "zeek/RE.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
namespace zeek { namespace zeek
{
EventRegistry::EventRegistry() = default; EventRegistry::EventRegistry() = default;
EventRegistry::~EventRegistry() noexcept = default; EventRegistry::~EventRegistry() noexcept = default;
@ -103,9 +105,7 @@ void EventRegistry::PrintDebug()
{ {
EventHandler* v = entry.second.get(); EventHandler* v = entry.second.get();
fprintf(stderr, "Registered event %s (%s handler / %s)\n", v->Name(), fprintf(stderr, "Registered event %s (%s handler / %s)\n", v->Name(),
v->GetFunc() ? "local" : "no", v->GetFunc() ? "local" : "no", *v ? "active" : "not active");
*v ? "active" : "not active"
);
} }
} }
@ -123,4 +123,4 @@ void EventRegistry::SetErrorHandler(std::string_view name)
std::string(name).c_str()); std::string(name).c_str());
} }
} // namespace zeek } // namespace zeek

View file

@ -2,22 +2,24 @@
#pragma once #pragma once
#include "zeek/zeek-config.h"
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <vector> #include <vector>
namespace zeek { #include "zeek/zeek-config.h"
namespace zeek
{
class EventHandler; class EventHandler;
class EventHandlerPtr; class EventHandlerPtr;
class RE_Matcher; class RE_Matcher;
// The registry keeps track of all events that we provide or handle. // The registry keeps track of all events that we provide or handle.
class EventRegistry { class EventRegistry
{
public: public:
EventRegistry(); EventRegistry();
~EventRegistry() noexcept; ~EventRegistry() noexcept;
@ -53,8 +55,8 @@ public:
private: private:
std::map<std::string, std::unique_ptr<EventHandler>, std::less<>> handlers; std::map<std::string, std::unique_ptr<EventHandler>, std::less<>> handlers;
}; };
extern EventRegistry* event_registry; extern EventRegistry* event_registry;
} // namespace zeek } // namespace zeek

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,37 +1,38 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/File.h" #include "zeek/File.h"
#include <sys/types.h> #include <sys/types.h>
#include "zeek/zeek-config.h"
#ifdef TIME_WITH_SYS_TIME #ifdef TIME_WITH_SYS_TIME
# include <sys/time.h> #include <sys/time.h>
# include <time.h> #include <time.h>
#else #else
# ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> #include <sys/time.h>
# else #else
# include <time.h> #include <time.h>
# endif
#endif #endif
#endif
#include <errno.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <algorithm> #include <algorithm>
#include "zeek/Attr.h" #include "zeek/Attr.h"
#include "zeek/Type.h" #include "zeek/Desc.h"
#include "zeek/Event.h"
#include "zeek/Expr.h" #include "zeek/Expr.h"
#include "zeek/NetVar.h" #include "zeek/NetVar.h"
#include "zeek/RunState.h"
#include "zeek/Event.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/Desc.h" #include "zeek/RunState.h"
#include "zeek/Type.h"
#include "zeek/Var.h" #include "zeek/Var.h"
namespace zeek { namespace zeek
{
std::list<std::pair<std::string, File*>> File::open_files; std::list<std::pair<std::string, File*>> File::open_files;
@ -159,8 +160,8 @@ File::~File()
Close(); Close();
Unref(attrs); Unref(attrs);
delete [] name; delete[] name;
delete [] access; delete[] access;
#ifdef USE_PERFTOOLS_DEBUG #ifdef USE_PERFTOOLS_DEBUG
heap_checker->UnIgnoreObject(this); heap_checker->UnIgnoreObject(this);
@ -231,7 +232,7 @@ bool File::Close()
void File::Unlink() void File::Unlink()
{ {
for ( auto it = open_files.begin(); it != open_files.end(); ++it) for ( auto it = open_files.begin(); it != open_files.end(); ++it )
{ {
if ( (*it).second == this ) if ( (*it).second == this )
{ {
@ -294,7 +295,7 @@ RecordVal* File::Rotate()
Unlink(); Unlink();
fclose(f); fclose(f);
f = nullptr; f = nullptr;
Open(newf); Open(newf);
@ -350,11 +351,11 @@ double File::Size()
FilePtr File::Get(const char* name) FilePtr File::Get(const char* name)
{ {
for ( const auto &el : open_files ) for ( const auto& el : open_files )
if ( el.first == name ) if ( el.first == name )
return {NewRef{}, el.second}; return {NewRef{}, el.second};
return make_intrusive<File>(name, "w"); return make_intrusive<File>(name, "w");
} }
} // namespace zeek } // namespace zeek

View file

@ -3,7 +3,6 @@
#pragma once #pragma once
#include <fcntl.h> #include <fcntl.h>
#include <list> #include <list>
#include <string> #include <string>
#include <utility> #include <utility>
@ -15,16 +14,18 @@
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/util.h" #include "zeek/util.h"
namespace zeek { namespace zeek
{
namespace detail { namespace detail
{
class PrintStmt; class PrintStmt;
class Attributes; class Attributes;
extern void do_print_stmt(const std::vector<ValPtr>& vals); extern void do_print_stmt(const std::vector<ValPtr>& vals);
} // namespace detail; } // namespace detail;
class RecordVal; class RecordVal;
class Type; class Type;
@ -33,7 +34,8 @@ using TypePtr = IntrusivePtr<Type>;
class File; class File;
using FilePtr = IntrusivePtr<File>; using FilePtr = IntrusivePtr<File>;
class File final : public Obj { class File final : public Obj
{
public: public:
explicit File(FILE* arg_f); explicit File(FILE* arg_f);
File(FILE* arg_f, const char* filename, const char* access); File(FILE* arg_f, const char* filename, const char* access);
@ -45,19 +47,18 @@ public:
// Returns false if an error occured. // Returns false if an error occured.
bool Write(const char* data, int len = 0); bool Write(const char* data, int len = 0);
void Flush() { fflush(f); } void Flush() { fflush(f); }
FILE* Seek(long position); // seek to absolute position FILE* Seek(long position); // seek to absolute position
void SetBuf(bool buffered); // false=line buffered, true=fully buffered void SetBuf(bool buffered); // false=line buffered, true=fully buffered
const TypePtr& GetType() const const TypePtr& GetType() const { return t; }
{ return t; }
// Whether the file is open in a general sense; it might // Whether the file is open in a general sense; it might
// not be open as a Unix file due to our management of // not be open as a Unix file due to our management of
// a finite number of FDs. // a finite number of FDs.
bool IsOpen() const { return is_open; } bool IsOpen() const { return is_open; }
// Returns true if the close made sense, false if it was already // Returns true if the close made sense, false if it was already
// closed, not active, or whatever. // closed, not active, or whatever.
@ -80,14 +81,13 @@ public:
// Get the file with the given name, opening it if it doesn't yet exist. // Get the file with the given name, opening it if it doesn't yet exist.
static FilePtr Get(const char* name); static FilePtr Get(const char* name);
void EnableRawOutput() { raw_output = true; } void EnableRawOutput() { raw_output = true; }
bool IsRawOutput() const { return raw_output; } bool IsRawOutput() const { return raw_output; }
protected: protected:
friend void detail::do_print_stmt(const std::vector<ValPtr>& vals); friend void detail::do_print_stmt(const std::vector<ValPtr>& vals);
File() { Init(); } File() { Init(); }
void Init(); void Init();
/** /**
@ -114,7 +114,7 @@ protected:
char* access; char* access;
detail::Attributes* attrs; detail::Attributes* attrs;
double open_time; double open_time;
bool is_open; // whether the file is open in a general sense bool is_open; // whether the file is open in a general sense
bool buffered; bool buffered;
bool raw_output; bool raw_output;
@ -122,6 +122,6 @@ protected:
private: private:
static std::list<std::pair<std::string, File*>> open_files; static std::list<std::pair<std::string, File*>> open_files;
}; };
} // namespace zeek } // namespace zeek

View file

@ -2,18 +2,16 @@
#include "zeek/Flare.h" #include "zeek/Flare.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
namespace zeek::detail { namespace zeek::detail
Flare::Flare()
: pipe(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK)
{ {
}
Flare::Flare() : pipe(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK) { }
[[noreturn]] static void bad_pipe_op(const char* which, bool signal_safe) [[noreturn]] static void bad_pipe_op(const char* which, bool signal_safe)
{ {
@ -36,7 +34,7 @@ void Flare::Fire(bool signal_safe)
{ {
char tmp = 0; char tmp = 0;
for ( ; ; ) for ( ;; )
{ {
int n = write(pipe.WriteFD(), &tmp, 1); int n = write(pipe.WriteFD(), &tmp, 1);
@ -66,7 +64,7 @@ int Flare::Extinguish(bool signal_safe)
int rval = 0; int rval = 0;
char tmp[256]; char tmp[256];
for ( ; ; ) for ( ;; )
{ {
int n = read(pipe.ReadFD(), &tmp, sizeof(tmp)); int n = read(pipe.ReadFD(), &tmp, sizeof(tmp));
@ -91,4 +89,4 @@ int Flare::Extinguish(bool signal_safe)
return rval; return rval;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -4,11 +4,12 @@
#include "zeek/Pipe.h" #include "zeek/Pipe.h"
namespace zeek::detail { namespace zeek::detail
{
class Flare { class Flare
{
public: public:
/** /**
* Create a flare object that can be used to signal a "ready" status via * Create a flare object that can be used to signal a "ready" status via
* a file descriptor that may be integrated with select(), poll(), etc. * a file descriptor that may be integrated with select(), poll(), etc.
@ -21,7 +22,7 @@ public:
* @return a file descriptor that will become ready if the flare has been * @return a file descriptor that will become ready if the flare has been
* Fire()'d and not yet Extinguished()'d. * Fire()'d and not yet Extinguished()'d.
*/ */
int FD() const { return pipe.ReadFD(); } int FD() const { return pipe.ReadFD(); }
/** /**
* Put the object in the "ready" state. * Put the object in the "ready" state.
@ -41,6 +42,6 @@ public:
private: private:
Pipe pipe; Pipe pipe;
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,19 +1,20 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Frag.h" #include "zeek/Frag.h"
#include "zeek/Hash.h" #include "zeek/Hash.h"
#include "zeek/IP.h" #include "zeek/IP.h"
#include "zeek/NetVar.h" #include "zeek/NetVar.h"
#include "zeek/session/Manager.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/RunState.h" #include "zeek/RunState.h"
#include "zeek/session/Manager.h"
#include "zeek/zeek-config.h"
constexpr uint32_t MIN_ACCEPTABLE_FRAG_SIZE = 64; constexpr uint32_t MIN_ACCEPTABLE_FRAG_SIZE = 64;
constexpr uint32_t MAX_ACCEPTABLE_FRAG_SIZE = 64000; constexpr uint32_t MAX_ACCEPTABLE_FRAG_SIZE = 64000;
namespace zeek::detail { namespace zeek::detail
{
FragTimer::~FragTimer() FragTimer::~FragTimer()
{ {
@ -29,9 +30,8 @@ void FragTimer::Dispatch(double t, bool /* is_expire */)
reporter->InternalWarning("fragment timer dispatched w/o reassembler"); reporter->InternalWarning("fragment timer dispatched w/o reassembler");
} }
FragReassembler::FragReassembler(session::Manager* arg_s, FragReassembler::FragReassembler(session::Manager* arg_s, const std::unique_ptr<IP_Hdr>& ip,
const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt, const u_char* pkt, const FragReassemblerKey& k, double t)
const FragReassemblerKey& k, double t)
: Reassembler(0, REASSEM_FRAG) : Reassembler(0, REASSEM_FRAG)
{ {
s = arg_s; s = arg_s;
@ -41,9 +41,9 @@ FragReassembler::FragReassembler(session::Manager* arg_s,
if ( ip4 ) if ( ip4 )
{ {
proto_hdr_len = ip->HdrLen(); proto_hdr_len = ip->HdrLen();
proto_hdr = new u_char[64]; // max IP header + slop proto_hdr = new u_char[64]; // max IP header + slop
// Don't do a structure copy - need to pick up options, too. // Don't do a structure copy - need to pick up options, too.
memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len); memcpy((void*)proto_hdr, (const void*)ip4, proto_hdr_len);
} }
else else
{ {
@ -53,7 +53,7 @@ FragReassembler::FragReassembler(session::Manager* arg_s,
} }
reassembled_pkt = nullptr; reassembled_pkt = nullptr;
frag_size = 0; // flag meaning "not known" frag_size = 0; // flag meaning "not known"
next_proto = ip->NextProto(); next_proto = ip->NextProto();
if ( frag_timeout != 0.0 ) if ( frag_timeout != 0.0 )
@ -70,11 +70,10 @@ FragReassembler::FragReassembler(session::Manager* arg_s,
FragReassembler::~FragReassembler() FragReassembler::~FragReassembler()
{ {
DeleteTimer(); DeleteTimer();
delete [] proto_hdr; delete[] proto_hdr;
} }
void FragReassembler::AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip, void FragReassembler::AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt)
const u_char* pkt)
{ {
const struct ip* ip4 = ip->IP4_Hdr(); const struct ip* ip4 = ip->IP4_Hdr();
@ -82,16 +81,15 @@ void FragReassembler::AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip,
{ {
if ( ip4->ip_p != ((const struct ip*)proto_hdr)->ip_p || if ( ip4->ip_p != ((const struct ip*)proto_hdr)->ip_p ||
ip4->ip_hl != ((const struct ip*)proto_hdr)->ip_hl ) ip4->ip_hl != ((const struct ip*)proto_hdr)->ip_hl )
// || ip4->ip_tos != proto_hdr->ip_tos // || ip4->ip_tos != proto_hdr->ip_tos
// don't check TOS, there's at least one stack that actually // don't check TOS, there's at least one stack that actually
// uses different values, and it's hard to see an associated // uses different values, and it's hard to see an associated
// attack. // attack.
s->Weird("fragment_protocol_inconsistency", ip.get()); s->Weird("fragment_protocol_inconsistency", ip.get());
} }
else else
{ {
if ( ip->NextProto() != next_proto || if ( ip->NextProto() != next_proto || ip->HdrLen() - 8 != proto_hdr_len )
ip->HdrLen() - 8 != proto_hdr_len )
s->Weird("fragment_protocol_inconsistency", ip.get()); s->Weird("fragment_protocol_inconsistency", ip.get());
// TODO: more detailed unfrag header consistency checks? // TODO: more detailed unfrag header consistency checks?
} }
@ -183,7 +181,7 @@ void FragReassembler::Weird(const char* name) const
void FragReassembler::Overlap(const u_char* b1, const u_char* b2, uint64_t n) void FragReassembler::Overlap(const u_char* b1, const u_char* b2, uint64_t n)
{ {
if ( memcmp((const void*) b1, (const void*) b2, n) ) if ( memcmp((const void*)b1, (const void*)b2, n) )
Weird("fragment_inconsistency"); Weird("fragment_inconsistency");
else else
Weird("fragment_overlap"); Weird("fragment_overlap");
@ -254,7 +252,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
// for a more recent one. // for a more recent one.
u_char* pkt = new u_char[n]; u_char* pkt = new u_char[n];
memcpy((void*) pkt, (const void*) proto_hdr, proto_hdr_len); memcpy((void*)pkt, (const void*)proto_hdr, proto_hdr_len);
u_char* pkt_start = pkt; u_char* pkt_start = pkt;
@ -280,7 +278,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
reporter->InternalWarning("bad fragment reassembly"); reporter->InternalWarning("bad fragment reassembly");
DeleteTimer(); DeleteTimer();
Expire(run_state::network_time); Expire(run_state::network_time);
delete [] pkt_start; delete[] pkt_start;
return; return;
} }
@ -293,7 +291,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
if ( version == 4 ) if ( version == 4 )
{ {
struct ip* reassem4 = (struct ip*) pkt_start; struct ip* reassem4 = (struct ip*)pkt_start;
reassem4->ip_len = htons(frag_size + proto_hdr_len); reassem4->ip_len = htons(frag_size + proto_hdr_len);
reassembled_pkt = std::make_unique<IP_Hdr>(reassem4, true, true); reassembled_pkt = std::make_unique<IP_Hdr>(reassem4, true, true);
DeleteTimer(); DeleteTimer();
@ -301,7 +299,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
else if ( version == 6 ) else if ( version == 6 )
{ {
struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start; struct ip6_hdr* reassem6 = (struct ip6_hdr*)pkt_start;
reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40); reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40);
const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n); const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n);
reassembled_pkt = std::make_unique<IP_Hdr>(reassem6, true, n, chain, true); reassembled_pkt = std::make_unique<IP_Hdr>(reassem6, true, n, chain, true);
@ -310,9 +308,8 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
else else
{ {
reporter->InternalWarning("bad IP version in fragment reassembly: %d", reporter->InternalWarning("bad IP version in fragment reassembly: %d", version);
version); delete[] pkt_start;
delete [] pkt_start;
} }
} }
@ -320,7 +317,7 @@ void FragReassembler::Expire(double t)
{ {
block_list.Clear(); block_list.Clear();
expire_timer->ClearReassembler(); expire_timer->ClearReassembler();
expire_timer = nullptr; // timer manager will delete it expire_timer = nullptr; // timer manager will delete it
fragment_mgr->Remove(this); fragment_mgr->Remove(this);
} }
@ -331,7 +328,7 @@ void FragReassembler::DeleteTimer()
{ {
expire_timer->ClearReassembler(); expire_timer->ClearReassembler();
timer_mgr->Cancel(expire_timer); timer_mgr->Cancel(expire_timer);
expire_timer = nullptr; // timer manager will delete it expire_timer = nullptr; // timer manager will delete it
} }
} }
@ -388,4 +385,4 @@ uint32_t FragmentManager::MemoryAllocation() const
return fragments.size() * (sizeof(FragmentMap::key_type) + sizeof(FragmentMap::value_type)); return fragments.size() * (sizeof(FragmentMap::key_type) + sizeof(FragmentMap::value_type));
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -5,38 +5,44 @@
#include <sys/types.h> // for u_char #include <sys/types.h> // for u_char
#include <tuple> #include <tuple>
#include "zeek/util.h" // for bro_uint_t
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
#include "zeek/Reassem.h" #include "zeek/Reassem.h"
#include "zeek/Timer.h" #include "zeek/Timer.h"
#include "zeek/util.h" // for bro_uint_t
namespace zeek { namespace zeek
{
class IP_Hdr; class IP_Hdr;
namespace session { class Manager; } namespace session
{
class Manager;
}
namespace detail { namespace detail
{
class FragReassembler; class FragReassembler;
class FragTimer; class FragTimer;
using FragReassemblerKey = std::tuple<IPAddr, IPAddr, bro_uint_t>; using FragReassemblerKey = std::tuple<IPAddr, IPAddr, bro_uint_t>;
class FragReassembler : public Reassembler { class FragReassembler : public Reassembler
{
public: public:
FragReassembler(session::Manager* s, const std::unique_ptr<IP_Hdr>& ip, FragReassembler(session::Manager* s, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt,
const u_char* pkt, const FragReassemblerKey& k, double t); const FragReassemblerKey& k, double t);
~FragReassembler() override; ~FragReassembler() override;
void AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt); void AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt);
void Expire(double t); void Expire(double t);
void DeleteTimer(); void DeleteTimer();
void ClearTimer() { expire_timer = nullptr; } void ClearTimer() { expire_timer = nullptr; }
std::unique_ptr<IP_Hdr> ReassembledPkt() { return std::move(reassembled_pkt); } std::unique_ptr<IP_Hdr> ReassembledPkt() { return std::move(reassembled_pkt); }
const FragReassemblerKey& Key() const { return key; } const FragReassemblerKey& Key() const { return key; }
protected: protected:
void BlockInserted(DataBlockMap::const_iterator it) override; void BlockInserted(DataBlockMap::const_iterator it) override;
@ -46,67 +52,63 @@ protected:
u_char* proto_hdr; u_char* proto_hdr;
std::unique_ptr<IP_Hdr> reassembled_pkt; std::unique_ptr<IP_Hdr> reassembled_pkt;
session::Manager* s; session::Manager* s;
uint64_t frag_size; // size of fully reassembled fragment uint64_t frag_size; // size of fully reassembled fragment
FragReassemblerKey key; FragReassemblerKey key;
uint16_t next_proto; // first IPv6 fragment header's next proto field uint16_t next_proto; // first IPv6 fragment header's next proto field
uint16_t proto_hdr_len; uint16_t proto_hdr_len;
FragTimer* expire_timer; FragTimer* expire_timer;
}; };
class FragTimer final : public Timer { class FragTimer final : public Timer
{
public: public:
FragTimer(FragReassembler* arg_f, double arg_t) FragTimer(FragReassembler* arg_f, double arg_t) : Timer(arg_t, TIMER_FRAG) { f = arg_f; }
: Timer(arg_t, TIMER_FRAG)
{ f = arg_f; }
~FragTimer() override; ~FragTimer() override;
void Dispatch(double t, bool is_expire) override; void Dispatch(double t, bool is_expire) override;
// Break the association between this timer and its creator. // Break the association between this timer and its creator.
void ClearReassembler() { f = nullptr; } void ClearReassembler() { f = nullptr; }
protected: protected:
FragReassembler* f; FragReassembler* f;
}; };
class FragmentManager { class FragmentManager
{
public: public:
FragmentManager() = default; FragmentManager() = default;
~FragmentManager(); ~FragmentManager();
FragReassembler* NextFragment(double t, const std::unique_ptr<IP_Hdr>& ip, FragReassembler* NextFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt);
const u_char* pkt);
void Clear(); void Clear();
void Remove(detail::FragReassembler* f); void Remove(detail::FragReassembler* f);
size_t Size() const { return fragments.size(); } size_t Size() const { return fragments.size(); }
size_t MaxFragments() const { return max_fragments; } size_t MaxFragments() const { return max_fragments; }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
uint32_t MemoryAllocation() const; "GHI-572.")]] uint32_t
MemoryAllocation() const;
private: private:
using FragmentMap = std::map<detail::FragReassemblerKey, detail::FragReassembler*>; using FragmentMap = std::map<detail::FragReassemblerKey, detail::FragReassembler*>;
FragmentMap fragments; FragmentMap fragments;
size_t max_fragments = 0; size_t max_fragments = 0;
}; };
extern FragmentManager* fragment_mgr; extern FragmentManager* fragment_mgr;
class FragReassemblerTracker { class FragReassemblerTracker
{
public: public:
FragReassemblerTracker(FragReassembler* f) FragReassemblerTracker(FragReassembler* f) : frag_reassembler(f) { }
: frag_reassembler(f)
{ }
~FragReassemblerTracker() ~FragReassemblerTracker() { fragment_mgr->Remove(frag_reassembler); }
{ fragment_mgr->Remove(frag_reassembler); }
private: private:
FragReassembler* frag_reassembler; FragReassembler* frag_reassembler;
}; };
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -4,16 +4,17 @@
#include <broker/error.hh> #include <broker/error.hh>
#include "zeek/broker/Data.h"
#include "zeek/Func.h"
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/Func.h"
#include "zeek/ID.h"
#include "zeek/Trigger.h" #include "zeek/Trigger.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/ID.h" #include "zeek/broker/Data.h"
std::vector<zeek::detail::Frame*> g_frame_stack; std::vector<zeek::detail::Frame*> g_frame_stack;
namespace zeek::detail { namespace zeek::detail
{
Frame::Frame(int arg_size, const ScriptFunc* func, const zeek::Args* fn_args) Frame::Frame(int arg_size, const ScriptFunc* func, const zeek::Args* fn_args)
{ {
@ -37,8 +38,7 @@ Frame::Frame(int arg_size, const ScriptFunc* func, const zeek::Args* fn_args)
// go away until the function itself goes away, which can only be // go away until the function itself goes away, which can only be
// after this frame does. // after this frame does.
captures = function ? function->GetCapturesFrame() : nullptr; captures = function ? function->GetCapturesFrame() : nullptr;
captures_offset_map = captures_offset_map = function ? function->GetCapturesOffsetMap() : nullptr;
function ? function->GetCapturesOffsetMap() : nullptr;
current_offset = 0; current_offset = 0;
} }
@ -178,10 +178,10 @@ void Frame::Describe(ODesc* d) const
d->Add(size); d->Add(size);
for ( int i = 0; i < size; ++i ) for ( int i = 0; i < size; ++i )
{ {
d->Add(frame[i].val != nullptr); d->Add(frame[i].val != nullptr);
d->SP(); d->SP();
} }
} }
for ( int i = 0; i < size; ++i ) for ( int i = 0; i < size; ++i )
@ -270,7 +270,8 @@ Frame* Frame::SelectiveClone(const IDPList& selection, ScriptFunc* func) const
} }
if ( ! frame[id->Offset() + current_offset].val ) if ( ! frame[id->Offset() + current_offset].val )
reporter->InternalError("Attempted to clone an id ('%s') with no associated value.", id->Name()); reporter->InternalError("Attempted to clone an id ('%s') with no associated value.",
id->Name());
CloneNonFuncElement(id->Offset(), func, other); CloneNonFuncElement(id->Offset(), func, other);
} }
@ -334,7 +335,8 @@ broker::expected<broker::data> Frame::SerializeClosureFrame(const IDPList& selec
if ( them.length() ) if ( them.length() )
{ {
if ( ! closure ) if ( ! closure )
reporter->InternalError("Attempting to serialize values from a frame that does not exist."); reporter->InternalError(
"Attempting to serialize values from a frame that does not exist.");
rval.emplace_back(std::string("ClosureFrame")); rval.emplace_back(std::string("ClosureFrame"));
@ -380,7 +382,7 @@ broker::expected<broker::data> Frame::SerializeClosureFrame(const IDPList& selec
if ( ! expected ) if ( ! expected )
return broker::ec::invalid_data; return broker::ec::invalid_data;
broker::vector val_tuple {std::move(*expected), static_cast<broker::integer>(tag)}; broker::vector val_tuple{std::move(*expected), static_cast<broker::integer>(tag)};
body[location] = val_tuple; body[location] = val_tuple;
} }
@ -404,8 +406,7 @@ broker::expected<broker::data> Frame::SerializeCopyFrame()
return broker::ec::invalid_data; return broker::ec::invalid_data;
TypeTag tag = val->GetType()->Tag(); TypeTag tag = val->GetType()->Tag();
broker::vector val_tuple {std::move(*expected), broker::vector val_tuple{std::move(*expected), static_cast<broker::integer>(tag)};
static_cast<broker::integer>(tag)};
body.emplace_back(std::move(val_tuple)); body.emplace_back(std::move(val_tuple));
} }
@ -415,7 +416,7 @@ broker::expected<broker::data> Frame::SerializeCopyFrame()
} }
std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data, std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data,
const std::optional<FuncType::CaptureList>& captures) const std::optional<FuncType::CaptureList>& captures)
{ {
if ( data.size() == 0 ) if ( data.size() == 0 )
return std::make_pair(true, nullptr); return std::make_pair(true, nullptr);
@ -458,7 +459,7 @@ std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data,
return std::make_pair(false, nullptr); return std::make_pair(false, nullptr);
broker::integer g = *has_type; broker::integer g = *has_type;
Type t( static_cast<TypeTag>(g) ); Type t(static_cast<TypeTag>(g));
auto val = Broker::detail::data_to_val(std::move(val_tuple[0]), &t); auto val = Broker::detail::data_to_val(std::move(val_tuple[0]), &t);
if ( ! val ) if ( ! val )
@ -470,7 +471,6 @@ std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data,
return std::make_pair(true, std::move(rf)); return std::make_pair(true, std::move(rf));
} }
// Code to support deprecated semantics: // Code to support deprecated semantics:
IDPList outer_ids; IDPList outer_ids;
@ -572,7 +572,7 @@ std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data,
return std::make_pair(false, nullptr); return std::make_pair(false, nullptr);
broker::integer g = *has_type; broker::integer g = *has_type;
Type t( static_cast<TypeTag>(g) ); Type t(static_cast<TypeTag>(g));
auto val = Broker::detail::data_to_val(std::move(val_tuple[0]), &t); auto val = Broker::detail::data_to_val(std::move(val_tuple[0]), &t);
if ( ! val ) if ( ! val )
@ -590,10 +590,10 @@ void Frame::AddKnownOffsets(const IDPList& ids)
offset_map = std::make_unique<OffsetMap>(); offset_map = std::make_unique<OffsetMap>();
std::transform(ids.begin(), ids.end(), std::inserter(*offset_map, offset_map->end()), std::transform(ids.begin(), ids.end(), std::inserter(*offset_map, offset_map->end()),
[] (const ID* id) -> std::pair<std::string, int> [](const ID* id) -> std::pair<std::string, int>
{ {
return std::make_pair(std::string(id->Name()), id->Offset()); return std::make_pair(std::string(id->Name()), id->Offset());
}); });
} }
void Frame::CaptureClosure(Frame* c, IDPList arg_outer_ids) void Frame::CaptureClosure(Frame* c, IDPList arg_outer_ids)
@ -643,7 +643,10 @@ void Frame::ClearElement(int n)
bool Frame::IsOuterID(const ID* in) const bool Frame::IsOuterID(const ID* in) const
{ {
return std::any_of(outer_ids.begin(), outer_ids.end(), return std::any_of(outer_ids.begin(), outer_ids.end(),
[&in](ID* id)-> bool { return strcmp(id->Name(), in->Name()) == 0; }); [&in](ID* id) -> bool
{
return strcmp(id->Name(), in->Name()) == 0;
});
} }
broker::expected<broker::data> Frame::SerializeIDList(const IDPList& in) broker::expected<broker::data> Frame::SerializeIDList(const IDPList& in)
@ -661,20 +664,21 @@ broker::expected<broker::data> Frame::SerializeIDList(const IDPList& in)
return {std::move(rval)}; return {std::move(rval)};
} }
broker::expected<broker::data> broker::expected<broker::data> Frame::SerializeOffsetMap(const OffsetMap& in)
Frame::SerializeOffsetMap(const OffsetMap& in)
{ {
broker::vector rval; broker::vector rval;
std::for_each(in.begin(), in.end(), std::for_each(in.begin(), in.end(),
[&rval] (const std::pair<std::string, int>& e) [&rval](const std::pair<std::string, int>& e)
{ rval.emplace_back(e.first); rval.emplace_back(e.second);}); {
rval.emplace_back(e.first);
rval.emplace_back(e.second);
});
return {std::move(rval)}; return {std::move(rval)};
} }
std::pair<bool, IDPList> std::pair<bool, IDPList> Frame::UnserializeIDList(const broker::vector& data)
Frame::UnserializeIDList(const broker::vector& data)
{ {
IDPList rval; IDPList rval;
if ( data.size() % 2 != 0 ) if ( data.size() % 2 != 0 )
@ -725,14 +729,14 @@ Frame::UnserializeOffsetMap(const broker::vector& data)
if ( ! key ) if ( ! key )
return std::make_pair(false, std::move(rval)); return std::make_pair(false, std::move(rval));
auto offset = broker::get_if<broker::integer>(data[i+1]); auto offset = broker::get_if<broker::integer>(data[i + 1]);
if ( ! offset ) if ( ! offset )
return std::make_pair(false, std::move(rval)); return std::make_pair(false, std::move(rval));
rval.insert( {std::move(*key), std::move(*offset)} ); rval.insert({std::move(*key), std::move(*offset)});
} }
return std::make_pair(true, std::move(rval)); return std::make_pair(true, std::move(rval));
} }
} }

View file

@ -2,43 +2,46 @@
#pragma once #pragma once
#include <unordered_map>
#include <string>
#include <utility>
#include <vector>
#include <memory>
#include <optional>
#include <broker/data.hh> #include <broker/data.hh>
#include <broker/expected.hh> #include <broker/expected.hh>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "zeek/ZeekList.h" // for typedef val_list #include "zeek/IntrusivePtr.h"
#include "zeek/Obj.h" #include "zeek/Obj.h"
#include "zeek/Type.h" #include "zeek/Type.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/ZeekArgs.h" #include "zeek/ZeekArgs.h"
#include "zeek/ZeekList.h" // for typedef val_list
namespace zeek { namespace zeek
{
using ValPtr = IntrusivePtr<Val>; using ValPtr = IntrusivePtr<Val>;
namespace detail { namespace detail
{
class CallExpr; class CallExpr;
class ScriptFunc; class ScriptFunc;
using IDPtr = IntrusivePtr<ID>; using IDPtr = IntrusivePtr<ID>;
namespace trigger { namespace trigger
{
class Trigger; class Trigger;
using TriggerPtr = IntrusivePtr<Trigger>; using TriggerPtr = IntrusivePtr<Trigger>;
} }
class Frame; class Frame;
using FramePtr = IntrusivePtr<Frame>; using FramePtr = IntrusivePtr<Frame>;
class Frame : public Obj { class Frame : public Obj
{
public: public:
/** /**
* Constructs a new frame belonging to *func* with *fn_args* * Constructs a new frame belonging to *func* with *fn_args*
@ -83,8 +86,7 @@ public:
* @param v the value to associate it with * @param v the value to associate it with
*/ */
void SetElement(const ID* id, ValPtr v); void SetElement(const ID* id, ValPtr v);
void SetElement(const IDPtr& id, ValPtr v) void SetElement(const IDPtr& id, ValPtr v) { SetElement(id.get(), std::move(v)); }
{ SetElement(id.get(), std::move(v)); }
/** /**
* Gets the value associated with *id* and returns it. Returns * Gets the value associated with *id* and returns it. Returns
@ -93,8 +95,7 @@ public:
* @param id the id who's value to retreive * @param id the id who's value to retreive
* @return the value associated with *id* * @return the value associated with *id*
*/ */
const ValPtr& GetElementByID(const IDPtr& id) const const ValPtr& GetElementByID(const IDPtr& id) const { return GetElementByID(id.get()); }
{ return GetElementByID(id.get()); }
/** /**
* Adjusts the current offset being used for frame accesses. * Adjusts the current offset being used for frame accesses.
@ -103,7 +104,7 @@ public:
* @param incr Amount by which to increase the frame offset. * @param incr Amount by which to increase the frame offset.
* Use a negative value to shrink the offset. * Use a negative value to shrink the offset.
*/ */
void AdjustOffset(int incr) { current_offset += incr; } void AdjustOffset(int incr) { current_offset += incr; }
/** /**
* Resets all of the indexes from [*startIdx, frame_size) in * Resets all of the indexes from [*startIdx, frame_size) in
@ -120,43 +121,40 @@ public:
/** /**
* @return the function that the frame is associated with. * @return the function that the frame is associated with.
*/ */
const ScriptFunc* GetFunction() const { return function; } const ScriptFunc* GetFunction() const { return function; }
/** /**
* @return the arguments passed to the function that this frame * @return the arguments passed to the function that this frame
* is associated with. * is associated with.
*/ */
const Args* GetFuncArgs() const { return func_args; } const Args* GetFuncArgs() const { return func_args; }
/** /**
* Change the function that the frame is associated with. * Change the function that the frame is associated with.
* *
* @param func the function for the frame to be associated with. * @param func the function for the frame to be associated with.
*/ */
void SetFunction(ScriptFunc* func) { function = func; } void SetFunction(ScriptFunc* func) { function = func; }
/** /**
* Sets the next statement to be executed in the context of the frame. * Sets the next statement to be executed in the context of the frame.
* *
* @param stmt the statement to set it to. * @param stmt the statement to set it to.
*/ */
void SetNextStmt(Stmt* stmt) { next_stmt = stmt; } void SetNextStmt(Stmt* stmt) { next_stmt = stmt; }
/** /**
* @return the next statement to be executed in the context of the frame. * @return the next statement to be executed in the context of the frame.
*/ */
Stmt* GetNextStmt() const { return next_stmt; } Stmt* GetNextStmt() const { return next_stmt; }
/** Used to implement "next" command in debugger. */ /** Used to implement "next" command in debugger. */
void BreakBeforeNextStmt(bool should_break) void BreakBeforeNextStmt(bool should_break) { break_before_next_stmt = should_break; }
{ break_before_next_stmt = should_break; } bool BreakBeforeNextStmt() const { return break_before_next_stmt; }
bool BreakBeforeNextStmt() const
{ return break_before_next_stmt; }
/** Used to implement "finish" command in debugger. */ /** Used to implement "finish" command in debugger. */
void BreakOnReturn(bool should_break) void BreakOnReturn(bool should_break) { break_on_return = should_break; }
{ break_on_return = should_break; } bool BreakOnReturn() const { return break_on_return; }
bool BreakOnReturn() const { return break_on_return; }
/** /**
* Performs a deep copy of all the values in the current frame. If * Performs a deep copy of all the values in the current frame. If
@ -233,8 +231,8 @@ public:
* reflects captures with copy-semantics rather than deprecated * reflects captures with copy-semantics rather than deprecated
* reference semantics. * reference semantics.
*/ */
static std::pair<bool, FramePtr> Unserialize(const broker::vector& data, static std::pair<bool, FramePtr>
const std::optional<FuncType::CaptureList>& captures); Unserialize(const broker::vector& data, const std::optional<FuncType::CaptureList>& captures);
/** /**
* Sets the IDs that the frame knows offsets for. These offsets will * Sets the IDs that the frame knows offsets for. These offsets will
@ -257,17 +255,17 @@ public:
// the trigger needs to be registered. // the trigger needs to be registered.
void SetTrigger(trigger::TriggerPtr arg_trigger); void SetTrigger(trigger::TriggerPtr arg_trigger);
void ClearTrigger(); void ClearTrigger();
trigger::Trigger* GetTrigger() const { return trigger.get(); } trigger::Trigger* GetTrigger() const { return trigger.get(); }
void SetCall(const CallExpr* arg_call) { call = arg_call; } void SetCall(const CallExpr* arg_call) { call = arg_call; }
void ClearCall() { call = nullptr; } void ClearCall() { call = nullptr; }
const CallExpr* GetCall() const { return call; } const CallExpr* GetCall() const { return call; }
void SetCallLoc(const Location* loc) { call_loc = loc; } void SetCallLoc(const Location* loc) { call_loc = loc; }
const detail::Location* GetCallLocation() const; const detail::Location* GetCallLocation() const;
void SetDelayed() { delayed = true; } void SetDelayed() { delayed = true; }
bool HasDelayed() const { return delayed; } bool HasDelayed() const { return delayed; }
/** /**
* Track a new function that refers to this frame for use as a closure. * Track a new function that refers to this frame for use as a closure.
@ -279,15 +277,15 @@ public:
void AddFunctionWithClosureRef(ScriptFunc* func); void AddFunctionWithClosureRef(ScriptFunc* func);
private: private:
using OffsetMap = std::unordered_map<std::string, int>; using OffsetMap = std::unordered_map<std::string, int>;
struct Element { struct Element
{
ValPtr val; ValPtr val;
// Weak reference is used to prevent circular reference memory leaks // Weak reference is used to prevent circular reference memory leaks
// in lambdas/closures. // in lambdas/closures.
bool weak_ref; bool weak_ref;
}; };
const ValPtr& GetElementByID(const ID* id) const; const ValPtr& GetElementByID(const ID* id) const;
@ -321,20 +319,17 @@ private:
bool IsCaptureID(const ID* in) const; bool IsCaptureID(const ID* in) const;
/** Serializes an offset_map */ /** Serializes an offset_map */
static broker::expected<broker::data> static broker::expected<broker::data> SerializeOffsetMap(const OffsetMap& in);
SerializeOffsetMap(const OffsetMap& in);
/** Serializes an IDPList */ /** Serializes an IDPList */
static broker::expected<broker::data> static broker::expected<broker::data> SerializeIDList(const IDPList& in);
SerializeIDList(const IDPList& in);
/** Unserializes an offset map. */ /** Unserializes an offset map. */
static std::pair<bool, std::unordered_map<std::string, int>> static std::pair<bool, std::unordered_map<std::string, int>>
UnserializeOffsetMap(const broker::vector& data); UnserializeOffsetMap(const broker::vector& data);
/** Unserializes an IDPList. */ /** Unserializes an IDPList. */
static std::pair<bool, IDPList> static std::pair<bool, IDPList> UnserializeIDList(const broker::vector& data);
UnserializeIDList(const broker::vector& data);
/** The number of vals that can be stored in this frame. */ /** The number of vals that can be stored in this frame. */
int size; int size;
@ -392,13 +387,13 @@ private:
trigger::TriggerPtr trigger; trigger::TriggerPtr trigger;
const CallExpr* call = nullptr; const CallExpr* call = nullptr;
const Location* call_loc = nullptr; // only needed if call is nil const Location* call_loc = nullptr; // only needed if call is nil
std::unique_ptr<std::vector<ScriptFunc*>> functions_with_closure_frame_reference; std::unique_ptr<std::vector<ScriptFunc*>> functions_with_closure_frame_reference;
}; };
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek
/** /**
* If we stopped using this and instead just made a struct of the information * If we stopped using this and instead just made a struct of the information

View file

@ -1,59 +1,55 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#include "zeek/zeek-config.h"
#ifdef TIME_WITH_SYS_TIME #ifdef TIME_WITH_SYS_TIME
# include <sys/time.h> #include <sys/time.h>
# include <time.h> #include <time.h>
#else #else
# ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> #include <sys/time.h>
# else #else
# include <time.h> #include <time.h>
# endif #endif
#endif #endif
#include <sys/resource.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <sys/param.h>
#include <netdb.h>
#include <unistd.h>
#include <signal.h>
#include <algorithm>
#include <broker/error.hh> #include <broker/error.hh>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <unistd.h>
#include <algorithm>
#include "zeek/Base64.h" #include "zeek/Base64.h"
#include "zeek/Debug.h" #include "zeek/Debug.h"
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/Event.h"
#include "zeek/Expr.h" #include "zeek/Expr.h"
#include "zeek/Stmt.h"
#include "zeek/Scope.h"
#include "zeek/RunState.h"
#include "zeek/NetVar.h"
#include "zeek/File.h" #include "zeek/File.h"
#include "zeek/Frame.h" #include "zeek/Frame.h"
#include "zeek/NetVar.h"
#include "zeek/RE.h"
#include "zeek/Reporter.h"
#include "zeek/RunState.h"
#include "zeek/Scope.h"
#include "zeek/Stmt.h"
#include "zeek/Traverse.h"
#include "zeek/Var.h" #include "zeek/Var.h"
#include "zeek/analyzer/protocol/tcp/TCP.h" #include "zeek/analyzer/protocol/tcp/TCP.h"
#include "zeek/session/Manager.h"
#include "zeek/RE.h"
#include "zeek/Event.h"
#include "zeek/Traverse.h"
#include "zeek/Reporter.h"
#include "zeek/plugin/Manager.h"
#include "zeek/module_util.h"
#include "zeek/iosource/PktSrc.h"
#include "zeek/iosource/PktDumper.h" #include "zeek/iosource/PktDumper.h"
#include "zeek/iosource/PktSrc.h"
#include "zeek/module_util.h"
#include "zeek/plugin/Manager.h"
#include "zeek/session/Manager.h"
// Ignore clang-format's reordering of include files here so that it doesn't // Ignore clang-format's reordering of include files here so that it doesn't
// break what symbols are available when, which keeps the build from breaking. // break what symbols are available when, which keeps the build from breaking.
@ -77,16 +73,18 @@
#include "CPP-load.bif.func_def" #include "CPP-load.bif.func_def"
// clang-format on // clang-format on
extern RETSIGTYPE sig_handler(int signo); extern RETSIGTYPE sig_handler(int signo);
namespace zeek::detail { namespace zeek::detail
{
std::vector<CallInfo> call_stack; std::vector<CallInfo> call_stack;
bool did_builtin_init = false; bool did_builtin_init = false;
std::vector<void (*)()> bif_initializers; std::vector<void (*)()> bif_initializers;
static const std::pair<bool, zeek::ValPtr> empty_hook_result(false, nullptr); static const std::pair<bool, zeek::ValPtr> empty_hook_result(false, nullptr);
} // namespace zeek::detail } // namespace zeek::detail
namespace zeek { namespace zeek
{
std::string render_call_stack() std::string render_call_stack()
{ {
@ -149,8 +147,8 @@ Func::Func(Kind arg_kind) : kind(arg_kind)
Func::~Func() = default; Func::~Func() = default;
void Func::AddBody(detail::StmtPtr /* new_body */, void Func::AddBody(detail::StmtPtr /* new_body */,
const std::vector<detail::IDPtr>& /* new_inits */, const std::vector<detail::IDPtr>& /* new_inits */, size_t /* new_frame_size */,
size_t /* new_frame_size */, int /* priority */) int /* priority */)
{ {
Internal("Func::AddBody called"); Internal("Func::AddBody called");
} }
@ -242,8 +240,7 @@ void Func::CopyStateInto(Func* other) const
other->unique_id = unique_id; other->unique_id = unique_id;
} }
void Func::CheckPluginResult(bool handled, const ValPtr& hook_result, void Func::CheckPluginResult(bool handled, const ValPtr& hook_result, FunctionFlavor flavor) const
FunctionFlavor flavor) const
{ {
// Helper function factoring out this code from ScriptFunc:Call() for // Helper function factoring out this code from ScriptFunc:Call() for
// better readability. // better readability.
@ -251,54 +248,57 @@ void Func::CheckPluginResult(bool handled, const ValPtr& hook_result,
if ( ! handled ) if ( ! handled )
{ {
if ( hook_result ) if ( hook_result )
reporter->InternalError("plugin set processed flag to false but actually returned a value"); reporter->InternalError(
"plugin set processed flag to false but actually returned a value");
// The plugin result hasn't been processed yet (read: fall // The plugin result hasn't been processed yet (read: fall
// into ::Call method). // into ::Call method).
return; return;
} }
switch ( flavor ) { switch ( flavor )
case FUNC_FLAVOR_EVENT:
if ( hook_result )
reporter->InternalError("plugin returned non-void result for event %s",
this->Name());
break;
case FUNC_FLAVOR_HOOK:
if ( hook_result->GetType()->Tag() != TYPE_BOOL )
reporter->InternalError("plugin returned non-bool for hook %s",
this->Name());
break;
case FUNC_FLAVOR_FUNCTION:
{ {
const auto& yt = GetType()->Yield(); case FUNC_FLAVOR_EVENT:
if ( (! yt) || yt->Tag() == TYPE_VOID )
{
if ( hook_result ) if ( hook_result )
reporter->InternalError("plugin returned non-void result for void method %s", reporter->InternalError("plugin returned non-void result for event %s",
this->Name()); this->Name());
}
else if ( hook_result && hook_result->GetType()->Tag() != yt->Tag() && yt->Tag() != TYPE_ANY ) break;
{
reporter->InternalError("plugin returned wrong type (got %d, expecting %d) for %s",
hook_result->GetType()->Tag(), yt->Tag(), this->Name());
}
break; case FUNC_FLAVOR_HOOK:
if ( hook_result->GetType()->Tag() != TYPE_BOOL )
reporter->InternalError("plugin returned non-bool for hook %s", this->Name());
break;
case FUNC_FLAVOR_FUNCTION:
{
const auto& yt = GetType()->Yield();
if ( (! yt) || yt->Tag() == TYPE_VOID )
{
if ( hook_result )
reporter->InternalError(
"plugin returned non-void result for void method %s", this->Name());
}
else if ( hook_result && hook_result->GetType()->Tag() != yt->Tag() &&
yt->Tag() != TYPE_ANY )
{
reporter->InternalError(
"plugin returned wrong type (got %d, expecting %d) for %s",
hook_result->GetType()->Tag(), yt->Tag(), this->Name());
}
break;
}
} }
} }
}
namespace detail { namespace detail
{
ScriptFunc::ScriptFunc(const IDPtr& arg_id, StmtPtr arg_body, ScriptFunc::ScriptFunc(const IDPtr& arg_id, StmtPtr arg_body, const std::vector<IDPtr>& aggr_inits,
const std::vector<IDPtr>& aggr_inits,
size_t arg_frame_size, int priority) size_t arg_frame_size, int priority)
: Func(SCRIPT_FUNC) : Func(SCRIPT_FUNC)
{ {
@ -316,8 +316,8 @@ ScriptFunc::ScriptFunc(const IDPtr& arg_id, StmtPtr arg_body,
} }
} }
ScriptFunc::ScriptFunc(std::string _name, FuncTypePtr ft, ScriptFunc::ScriptFunc(std::string _name, FuncTypePtr ft, std::vector<StmtPtr> bs,
std::vector<StmtPtr> bs, std::vector<int> priorities) std::vector<int> priorities)
{ {
name = std::move(_name); name = std::move(_name);
frame_size = ft->ParamList()->GetTypes().size(); frame_size = ft->ParamList()->GetTypes().size();
@ -355,7 +355,10 @@ ScriptFunc::~ScriptFunc()
bool ScriptFunc::IsPure() const bool ScriptFunc::IsPure() const
{ {
return std::all_of(bodies.begin(), bodies.end(), return std::all_of(bodies.begin(), bodies.end(),
[](const Body& b) { return b.stmts->IsPure(); }); [](const Body& b)
{
return b.stmts->IsPure();
});
} }
ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
@ -368,9 +371,8 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
if ( sample_logger ) if ( sample_logger )
sample_logger->FunctionSeen(this); sample_logger->FunctionSeen(this);
auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(
HookCallFunction(this, parent, args), HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result);
empty_hook_result);
CheckPluginResult(handled, hook_result, Flavor()); CheckPluginResult(handled, hook_result, Flavor());
@ -396,7 +398,7 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
f->SetCall(parent->GetCall()); f->SetCall(parent->GetCall());
} }
g_frame_stack.push_back(f.get()); // used for backtracing g_frame_stack.push_back(f.get()); // used for backtracing
const CallExpr* call_expr = parent ? parent->GetCall() : nullptr; const CallExpr* call_expr = parent ? parent->GetCall() : nullptr;
call_stack.emplace_back(CallInfo{call_expr, this, *args}); call_stack.emplace_back(CallInfo{call_expr, this, *args});
@ -405,8 +407,8 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
ODesc d; ODesc d;
DescribeDebug(&d, args); DescribeDebug(&d, args);
g_trace_state.LogTrace("%s called: %s\n", g_trace_state.LogTrace("%s called: %s\n", GetType()->FlavorString().c_str(),
GetType()->FlavorString().c_str(), d.Description()); d.Description());
} }
StmtFlowType flow = FLOW_NEXT; StmtFlowType flow = FLOW_NEXT;
@ -483,11 +485,10 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
// Warn if the function returns something, but we returned from // Warn if the function returns something, but we returned from
// the function without an explicit return, or without a value. // the function without an explicit return, or without a value.
else if ( GetType()->Yield() && GetType()->Yield()->Tag() != TYPE_VOID && else if ( GetType()->Yield() && GetType()->Yield()->Tag() != TYPE_VOID &&
(flow != FLOW_RETURN /* we fell off the end */ || (flow != FLOW_RETURN /* we fell off the end */ ||
! result /* explicit return with no result */) && ! result /* explicit return with no result */) &&
! f->HasDelayed() ) ! f->HasDelayed() )
reporter->Warning("non-void function returning without a value: %s", reporter->Warning("non-void function returning without a value: %s", Name());
Name());
if ( result && g_trace_state.DoTrace() ) if ( result && g_trace_state.DoTrace() )
{ {
@ -552,8 +553,7 @@ void ScriptFunc::SetCaptures(Frame* f)
} }
} }
void ScriptFunc::AddBody(StmtPtr new_body, void ScriptFunc::AddBody(StmtPtr new_body, const std::vector<IDPtr>& new_inits,
const std::vector<IDPtr>& new_inits,
size_t new_frame_size, int priority) size_t new_frame_size, int priority)
{ {
if ( new_frame_size > frame_size ) if ( new_frame_size > frame_size )
@ -634,8 +634,7 @@ bool ScriptFunc::HasCopySemantics() const
void ScriptFunc::SetClosureFrame(Frame* f) void ScriptFunc::SetClosureFrame(Frame* f)
{ {
if ( closure ) if ( closure )
reporter->InternalError("Tried to override closure for ScriptFunc %s.", reporter->InternalError("Tried to override closure for ScriptFunc %s.", Name());
Name());
// Have to use weak references initially because otherwise Ref'ing the // Have to use weak references initially because otherwise Ref'ing the
// original frame creates a circular reference: the function holds a // original frame creates a circular reference: the function holds a
@ -674,14 +673,13 @@ bool ScriptFunc::DeserializeCaptures(const broker::vector& data)
{ {
auto result = Frame::Unserialize(data, GetType()->GetCaptures()); auto result = Frame::Unserialize(data, GetType()->GetCaptures());
ASSERT(result.first); ASSERT(result.first);
SetCaptures(result.second.release()); SetCaptures(result.second.release());
return true; return true;
} }
FuncPtr ScriptFunc::DoClone() FuncPtr ScriptFunc::DoClone()
{ {
// ScriptFunc could hold a closure. In this case a clone of it must // ScriptFunc could hold a closure. In this case a clone of it must
@ -726,9 +724,7 @@ void ScriptFunc::Describe(ODesc* d) const
} }
} }
StmtPtr ScriptFunc::AddInits( StmtPtr ScriptFunc::AddInits(StmtPtr body, const std::vector<IDPtr>& inits)
StmtPtr body,
const std::vector<IDPtr>& inits)
{ {
if ( inits.empty() ) if ( inits.empty() )
return body; return body;
@ -740,9 +736,8 @@ StmtPtr ScriptFunc::AddInits(
return stmt_series; return stmt_series;
} }
BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, bool arg_is_pure)
bool arg_is_pure) : Func(BUILTIN_FUNC)
: Func(BUILTIN_FUNC)
{ {
func = arg_func; func = arg_func;
name = make_full_var_name(GLOBAL_MODULE_NAME, arg_name); name = make_full_var_name(GLOBAL_MODULE_NAME, arg_name);
@ -759,9 +754,7 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
id->SetConst(); id->SetConst();
} }
BuiltinFunc::~BuiltinFunc() BuiltinFunc::~BuiltinFunc() { }
{
}
bool BuiltinFunc::IsPure() const bool BuiltinFunc::IsPure() const
{ {
@ -778,9 +771,8 @@ ValPtr BuiltinFunc::Invoke(Args* args, Frame* parent) const
if ( sample_logger ) if ( sample_logger )
sample_logger->FunctionSeen(this); sample_logger->FunctionSeen(this);
auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION, auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(
HookCallFunction(this, parent, args), HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result);
empty_hook_result);
CheckPluginResult(handled, hook_result, FUNC_FLAVOR_FUNCTION); CheckPluginResult(handled, hook_result, FUNC_FLAVOR_FUNCTION);
@ -819,7 +811,7 @@ void BuiltinFunc::Describe(ODesc* d) const
bool check_built_in_call(BuiltinFunc* f, CallExpr* call) bool check_built_in_call(BuiltinFunc* f, CallExpr* call)
{ {
if ( f->TheFunc() != BifFunc::fmt_bif) if ( f->TheFunc() != BifFunc::fmt_bif )
return true; return true;
const ExprPList& args = call->Args()->Exprs(); const ExprPList& args = call->Args()->Exprs();
@ -862,7 +854,8 @@ bool check_built_in_call(BuiltinFunc* f, CallExpr* call)
if ( args.length() != num_fmt + 1 ) if ( args.length() != num_fmt + 1 )
{ {
call->Error("mismatch between format string to util::fmt() and number of arguments passed"); call->Error(
"mismatch between format string to util::fmt() and number of arguments passed");
return false; return false;
} }
} }
@ -924,7 +917,7 @@ function_ingredients::function_ingredients(ScopePtr scope, StmtPtr body)
static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind) static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind)
{ {
auto emit = [=](const CallExpr* ce) auto emit = [=](const CallExpr* ce)
{ {
if ( ce ) if ( ce )
{ {
if ( unwind ) if ( unwind )
@ -933,8 +926,7 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind)
{ {
ODesc d; ODesc d;
arg->Describe(&d); arg->Describe(&d);
reporter->ExprRuntimeError(ce, "%s (%s), during call:", msg, reporter->ExprRuntimeError(ce, "%s (%s), during call:", msg, d.Description());
d.Description());
} }
else else
reporter->ExprRuntimeError(ce, "%s", msg); reporter->ExprRuntimeError(ce, "%s", msg);
@ -959,8 +951,7 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind)
reporter->Error("%s", msg); reporter->Error("%s", msg);
} }
} }
}; };
if ( call_stack.empty() ) if ( call_stack.empty() )
{ {
@ -980,7 +971,9 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind)
} }
auto starts_with_double_underscore = [](const std::string& name) -> bool auto starts_with_double_underscore = [](const std::string& name) -> bool
{ return name.size() > 2 && name[0] == '_' && name[1] == '_'; }; {
return name.size() > 2 && name[0] == '_' && name[1] == '_';
};
std::string last_func = last_call.func->Name(); std::string last_func = last_call.func->Name();
auto pos = last_func.find_first_of("::"); auto pos = last_func.find_first_of("::");
@ -1055,21 +1048,20 @@ void init_primary_bifs()
var_sizes = id::find_type("var_sizes")->AsTableType(); var_sizes = id::find_type("var_sizes")->AsTableType();
#include "zeek.bif.func_init"
#include "stats.bif.func_init"
#include "reporter.bif.func_init"
#include "strings.bif.func_init"
#include "option.bif.func_init"
#include "supervisor.bif.func_init"
#include "packet_analysis.bif.func_init"
#include "CPP-load.bif.func_init" #include "CPP-load.bif.func_init"
#include "option.bif.func_init"
#include "packet_analysis.bif.func_init"
#include "reporter.bif.func_init"
#include "stats.bif.func_init"
#include "strings.bif.func_init"
#include "supervisor.bif.func_init"
#include "zeek.bif.func_init"
init_builtin_types(); init_builtin_types();
did_builtin_init = true; did_builtin_init = true;
} }
} // namespace detail } // namespace detail
void emit_builtin_error(const char* msg) void emit_builtin_error(const char* msg)
{ {
@ -1086,4 +1078,4 @@ void emit_builtin_error(const char* msg, Obj* arg)
zeek::detail::emit_builtin_error_common(msg, arg, false); zeek::detail::emit_builtin_error_common(msg, arg, false);
} }
} // namespace zeek } // namespace zeek

View file

@ -2,38 +2,42 @@
#pragma once #pragma once
#include <utility>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <utility>
#include <vector>
#include "zeek/ZeekList.h" #include "zeek/BifReturnVal.h"
#include "zeek/Stmt.h"
#include "zeek/Obj.h" #include "zeek/Obj.h"
#include "zeek/Scope.h" #include "zeek/Scope.h"
#include "zeek/Type.h" /* for function_flavor */ #include "zeek/Stmt.h"
#include "zeek/TraverseTypes.h" #include "zeek/TraverseTypes.h"
#include "zeek/Type.h" /* for function_flavor */
#include "zeek/ZeekArgs.h" #include "zeek/ZeekArgs.h"
#include "zeek/BifReturnVal.h" #include "zeek/ZeekList.h"
namespace caf { namespace caf
{
template <class> class expected; template <class> class expected;
} }
namespace broker { namespace broker
{
class data; class data;
using vector = std::vector<data>; using vector = std::vector<data>;
using caf::expected; using caf::expected;
} }
namespace zeek { namespace zeek
{
class Val; class Val;
class FuncType; class FuncType;
namespace detail { namespace detail
{
class Scope; class Scope;
class Stmt; class Stmt;
@ -46,34 +50,41 @@ using StmtPtr = IntrusivePtr<Stmt>;
class ScriptFunc; class ScriptFunc;
} // namespace detail } // namespace detail
class Func; class Func;
using FuncPtr = IntrusivePtr<Func>; using FuncPtr = IntrusivePtr<Func>;
class Func : public Obj { class Func : public Obj
{
public: public:
static inline const FuncPtr nil; static inline const FuncPtr nil;
enum Kind { SCRIPT_FUNC, BUILTIN_FUNC }; enum Kind
{
SCRIPT_FUNC,
BUILTIN_FUNC
};
explicit Func(Kind arg_kind); explicit Func(Kind arg_kind);
~Func() override; ~Func() override;
virtual bool IsPure() const = 0; virtual bool IsPure() const = 0;
FunctionFlavor Flavor() const { return GetType()->Flavor(); } FunctionFlavor Flavor() const { return GetType()->Flavor(); }
struct Body { struct Body
{
detail::StmtPtr stmts; detail::StmtPtr stmts;
int priority; int priority;
bool operator<(const Body& other) const bool operator<(const Body& other) const
{ return priority > other.priority; } // reverse sort {
}; return priority > other.priority;
} // reverse sort
};
const std::vector<Body>& GetBodies() const { return bodies; } const std::vector<Body>& GetBodies() const { return bodies; }
bool HasBodies() const { return bodies.size(); } bool HasBodies() const { return bodies.size(); }
/** /**
* Calls a Zeek function. * Calls a Zeek function.
@ -81,16 +92,14 @@ public:
* @param parent the frame from which the function is being called. * @param parent the frame from which the function is being called.
* @return the return value of the function call. * @return the return value of the function call.
*/ */
virtual ValPtr Invoke( virtual ValPtr Invoke(zeek::Args* args, detail::Frame* parent = nullptr) const = 0;
zeek::Args* args, detail::Frame* parent = nullptr) const = 0;
/** /**
* A version of Invoke() taking a variable number of individual arguments. * A version of Invoke() taking a variable number of individual arguments.
*/ */
template <class... Args> template <class... Args>
std::enable_if_t< std::enable_if_t<std::is_convertible_v<std::tuple_element_t<0, std::tuple<Args...>>, ValPtr>,
std::is_convertible_v<std::tuple_element_t<0, std::tuple<Args...>>, ValPtr>, ValPtr>
ValPtr>
Invoke(Args&&... args) const Invoke(Args&&... args) const
{ {
auto zargs = zeek::Args{std::forward<Args>(args)...}; auto zargs = zeek::Args{std::forward<Args>(args)...};
@ -98,20 +107,18 @@ public:
} }
// Add a new event handler to an existing function (event). // Add a new event handler to an existing function (event).
virtual void AddBody(detail::StmtPtr new_body, virtual void AddBody(detail::StmtPtr new_body, const std::vector<detail::IDPtr>& new_inits,
const std::vector<detail::IDPtr>& new_inits,
size_t new_frame_size, int priority = 0); size_t new_frame_size, int priority = 0);
virtual void SetScope(detail::ScopePtr newscope); virtual void SetScope(detail::ScopePtr newscope);
virtual detail::ScopePtr GetScope() const { return scope; } virtual detail::ScopePtr GetScope() const { return scope; }
const FuncTypePtr& GetType() const const FuncTypePtr& GetType() const { return type; }
{ return type; }
Kind GetKind() const { return kind; } Kind GetKind() const { return kind; }
const char* Name() const { return name.c_str(); } const char* Name() const { return name.c_str(); }
void SetName(const char* arg_name) { name = arg_name; } void SetName(const char* arg_name) { name = arg_name; }
void Describe(ODesc* d) const override = 0; void Describe(ODesc* d) const override = 0;
virtual void DescribeDebug(ODesc* d, const zeek::Args* args) const; virtual void DescribeDebug(ODesc* d, const zeek::Args* args) const;
@ -122,7 +129,9 @@ public:
uint32_t GetUniqueFuncID() const { return unique_id; } uint32_t GetUniqueFuncID() const { return unique_id; }
static const FuncPtr& GetFuncPtrByID(uint32_t id) static const FuncPtr& GetFuncPtrByID(uint32_t id)
{ return id >= unique_ids.size() ? Func::nil : unique_ids[id]; } {
return id >= unique_ids.size() ? Func::nil : unique_ids[id];
}
protected: protected:
Func(); Func();
@ -131,8 +140,7 @@ protected:
void CopyStateInto(Func* other) const; void CopyStateInto(Func* other) const;
// Helper function for checking result of plugin hook. // Helper function for checking result of plugin hook.
void CheckPluginResult(bool handled, const ValPtr& hook_result, void CheckPluginResult(bool handled, const ValPtr& hook_result, FunctionFlavor flavor) const;
FunctionFlavor flavor) const;
std::vector<Body> bodies; std::vector<Body> bodies;
detail::ScopePtr scope; detail::ScopePtr scope;
@ -141,19 +149,20 @@ protected:
FuncTypePtr type; FuncTypePtr type;
std::string name; std::string name;
static inline std::vector<FuncPtr> unique_ids; static inline std::vector<FuncPtr> unique_ids;
}; };
namespace detail { namespace detail
{
class ScriptFunc : public Func { class ScriptFunc : public Func
{
public: public:
ScriptFunc(const IDPtr& id, StmtPtr body, ScriptFunc(const IDPtr& id, StmtPtr body, const std::vector<IDPtr>& inits, size_t frame_size,
const std::vector<IDPtr>& inits, int priority);
size_t frame_size, int priority);
// For compiled scripts. // For compiled scripts.
ScriptFunc(std::string name, FuncTypePtr ft, ScriptFunc(std::string name, FuncTypePtr ft, std::vector<StmtPtr> bodies,
std::vector<StmtPtr> bodies, std::vector<int> priorities); std::vector<int> priorities);
~ScriptFunc() override; ~ScriptFunc() override;
@ -176,7 +185,7 @@ public:
* *
* @return internal frame kept by the function for persisting captures * @return internal frame kept by the function for persisting captures
*/ */
Frame* GetCapturesFrame() const { return captures_frame; } Frame* GetCapturesFrame() const { return captures_frame; }
// Same definition as in Frame.h. // Same definition as in Frame.h.
using OffsetMap = std::unordered_map<std::string, int>; using OffsetMap = std::unordered_map<std::string, int>;
@ -186,8 +195,7 @@ public:
* *
* @return pointer to mapping of captures to slots * @return pointer to mapping of captures to slots
*/ */
const OffsetMap* GetCapturesOffsetMap() const const OffsetMap* GetCapturesOffsetMap() const { return captures_offset_mapping; }
{ return captures_offset_mapping; }
// The following "Closure" methods implement the deprecated // The following "Closure" methods implement the deprecated
// capture-by-reference functionality. // capture-by-reference functionality.
@ -233,9 +241,8 @@ public:
*/ */
bool DeserializeCaptures(const broker::vector& data); bool DeserializeCaptures(const broker::vector& data);
void AddBody(StmtPtr new_body, void AddBody(StmtPtr new_body, const std::vector<IDPtr>& new_inits, size_t new_frame_size,
const std::vector<IDPtr>& new_inits, int priority) override;
size_t new_frame_size, int priority) override;
/** /**
* Replaces the given current instance of a function body with * Replaces the given current instance of a function body with
@ -245,17 +252,16 @@ public:
* @param old_body Body to replace. * @param old_body Body to replace.
* @param new_body New body to use; can be nil. * @param new_body New body to use; can be nil.
*/ */
void ReplaceBody(const detail::StmtPtr& old_body, void ReplaceBody(const detail::StmtPtr& old_body, detail::StmtPtr new_body);
detail::StmtPtr new_body);
StmtPtr CurrentBody() const { return current_body; } StmtPtr CurrentBody() const { return current_body; }
int CurrentPriority() const { return current_priority; } int CurrentPriority() const { return current_priority; }
/** /**
* Returns the function's frame size. * Returns the function's frame size.
* @return The number of ValPtr slots in the function's frame. * @return The number of ValPtr slots in the function's frame.
*/ */
int FrameSize() const { return frame_size; } int FrameSize() const { return frame_size; }
/** /**
* Changes the function's frame size to a new size - used for * Changes the function's frame size to a new size - used for
@ -263,20 +269,17 @@ public:
* *
* @param new_size The frame size the function should use. * @param new_size The frame size the function should use.
*/ */
void SetFrameSize(int new_size) { frame_size = new_size; } void SetFrameSize(int new_size) { frame_size = new_size; }
/** Sets this function's outer_id list. */ /** Sets this function's outer_id list. */
void SetOuterIDs(IDPList ids) void SetOuterIDs(IDPList ids) { outer_ids = std::move(ids); }
{ outer_ids = std::move(ids); }
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
protected: protected:
ScriptFunc() : Func(SCRIPT_FUNC) {} ScriptFunc() : Func(SCRIPT_FUNC) { }
StmtPtr AddInits( StmtPtr AddInits(StmtPtr body, const std::vector<IDPtr>& inits);
StmtPtr body,
const std::vector<IDPtr>& inits);
/** /**
* Clones this function along with its closures. * Clones this function along with its closures.
@ -323,39 +326,46 @@ private:
// ... and its priority. // ... and its priority.
int current_priority = 0; int current_priority = 0;
}; };
using built_in_func = BifReturnVal (*)(Frame* frame, const Args* args); using built_in_func = BifReturnVal (*)(Frame* frame, const Args* args);
class BuiltinFunc final : public Func { class BuiltinFunc final : public Func
{
public: public:
BuiltinFunc(built_in_func func, const char* name, bool is_pure); BuiltinFunc(built_in_func func, const char* name, bool is_pure);
~BuiltinFunc() override; ~BuiltinFunc() override;
bool IsPure() const override; bool IsPure() const override;
ValPtr Invoke(zeek::Args* args, Frame* parent) const override; ValPtr Invoke(zeek::Args* args, Frame* parent) const override;
built_in_func TheFunc() const { return func; } built_in_func TheFunc() const { return func; }
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
protected: protected:
BuiltinFunc() { func = nullptr; is_pure = 0; } BuiltinFunc()
{
func = nullptr;
is_pure = 0;
}
built_in_func func; built_in_func func;
bool is_pure; bool is_pure;
}; };
extern bool check_built_in_call(BuiltinFunc* f, CallExpr* call); extern bool check_built_in_call(BuiltinFunc* f, CallExpr* call);
struct CallInfo { struct CallInfo
{
const CallExpr* call; const CallExpr* call;
const Func* func; const Func* func;
const zeek::Args& args; const zeek::Args& args;
}; };
// Struct that collects all the specifics defining a Func. Used for ScriptFuncs // Struct that collects all the specifics defining a Func. Used for ScriptFuncs
// with closures. // with closures.
struct function_ingredients { struct function_ingredients
{
// Gathers all of the information from a scope and a function body needed // Gathers all of the information from a scope and a function body needed
// to build a function. // to build a function.
@ -367,7 +377,7 @@ struct function_ingredients {
int frame_size; int frame_size;
int priority; int priority;
ScopePtr scope; ScopePtr scope;
}; };
extern std::vector<CallInfo> call_stack; extern std::vector<CallInfo> call_stack;
@ -388,7 +398,7 @@ extern void emit_builtin_exception(const char* msg);
extern void emit_builtin_exception(const char* msg, const ValPtr& arg); extern void emit_builtin_exception(const char* msg, const ValPtr& arg);
extern void emit_builtin_exception(const char* msg, Obj* arg); extern void emit_builtin_exception(const char* msg, Obj* arg);
} // namespace detail } // namespace detail
extern std::string render_call_stack(); extern std::string render_call_stack();
@ -397,4 +407,4 @@ extern void emit_builtin_error(const char* msg);
extern void emit_builtin_error(const char* msg, const ValPtr&); extern void emit_builtin_error(const char* msg, const ValPtr&);
extern void emit_builtin_error(const char* msg, Obj* arg); extern void emit_builtin_error(const char* msg, Obj* arg);
} // namespace zeek } // namespace zeek

View file

@ -1,45 +1,56 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Hash.h" #include "zeek/Hash.h"
#include <highwayhash/sip_hash.h>
#include <highwayhash/highwayhash_target.h> #include <highwayhash/highwayhash_target.h>
#include <highwayhash/instruction_sets.h> #include <highwayhash/instruction_sets.h>
#include <highwayhash/sip_hash.h>
#include "zeek/digest.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/ZeekString.h"
#include "zeek/Val.h" // needed for const.bif #include "zeek/Val.h" // needed for const.bif
#include "zeek/ZeekString.h"
#include "zeek/digest.h"
#include "zeek/zeek-config.h"
#include "const.bif.netvar_h" #include "const.bif.netvar_h"
namespace zeek::detail { namespace zeek::detail
{
alignas(32) uint64_t KeyedHash::shared_highwayhash_key[4]; alignas(32) uint64_t KeyedHash::shared_highwayhash_key[4];
alignas(32) uint64_t KeyedHash::cluster_highwayhash_key[4]; alignas(32) uint64_t KeyedHash::cluster_highwayhash_key[4];
alignas(16) unsigned long long KeyedHash::shared_siphash_key[2]; alignas(16) unsigned long long KeyedHash::shared_siphash_key[2];
// we use the following lines to not pull in the highwayhash headers in Hash.h - but to check the types did not change underneath us. // we use the following lines to not pull in the highwayhash headers in Hash.h - but to check the
static_assert(std::is_same<hash64_t, highwayhash::HHResult64>::value, "Highwayhash return values must match hash_x_t"); // types did not change underneath us.
static_assert(std::is_same<hash128_t, highwayhash::HHResult128>::value, "Highwayhash return values must match hash_x_t"); static_assert(std::is_same<hash64_t, highwayhash::HHResult64>::value,
static_assert(std::is_same<hash256_t, highwayhash::HHResult256>::value, "Highwayhash return values must match hash_x_t"); "Highwayhash return values must match hash_x_t");
static_assert(std::is_same<hash128_t, highwayhash::HHResult128>::value,
"Highwayhash return values must match hash_x_t");
static_assert(std::is_same<hash256_t, highwayhash::HHResult256>::value,
"Highwayhash return values must match hash_x_t");
void KeyedHash::InitializeSeeds(const std::array<uint32_t, SEED_INIT_SIZE>& seed_data) void KeyedHash::InitializeSeeds(const std::array<uint32_t, SEED_INIT_SIZE>& seed_data)
{ {
static_assert(std::is_same<decltype(KeyedHash::shared_siphash_key), highwayhash::SipHashState::Key>::value, "Highwayhash Key is not unsigned long long[2]"); static_assert(std::is_same<decltype(KeyedHash::shared_siphash_key),
static_assert(std::is_same<decltype(KeyedHash::shared_highwayhash_key), highwayhash::HHKey>::value, "Highwayhash HHKey is not uint64_t[4]"); highwayhash::SipHashState::Key>::value,
"Highwayhash Key is not unsigned long long[2]");
static_assert(
std::is_same<decltype(KeyedHash::shared_highwayhash_key), highwayhash::HHKey>::value,
"Highwayhash HHKey is not uint64_t[4]");
if ( seeds_initialized ) if ( seeds_initialized )
return; return;
// leaving this at being generated by md5, allowing user scripts that use hmac_md5 functionality // leaving this at being generated by md5, allowing user scripts that use hmac_md5 functionality
// to get the same hash values as before. For now. // to get the same hash values as before. For now.
internal_md5((const u_char*) seed_data.data(), sizeof(seed_data) - 16, shared_hmac_md5_key); // The last 128 bits of buf are for siphash internal_md5((const u_char*)seed_data.data(), sizeof(seed_data) - 16,
// yes, we use the same buffer twice to initialize two different keys. This should not really be a shared_hmac_md5_key); // The last 128 bits of buf are for siphash
// security problem of any kind: hmac-md5 is not really used anymore - and even if it was, the hashes // yes, we use the same buffer twice to initialize two different keys. This should not really be
// should not reveal any information about their initialization vector. // a security problem of any kind: hmac-md5 is not really used anymore - and even if it was, the
// hashes should not reveal any information about their initialization vector.
static_assert(sizeof(shared_highwayhash_key) == SHA256_DIGEST_LENGTH); static_assert(sizeof(shared_highwayhash_key) == SHA256_DIGEST_LENGTH);
calculate_digest(Hash_SHA256, (const u_char*) seed_data.data(), sizeof(seed_data) - 16, reinterpret_cast<unsigned char*>(shared_highwayhash_key)); calculate_digest(Hash_SHA256, (const u_char*)seed_data.data(), sizeof(seed_data) - 16,
reinterpret_cast<unsigned char*>(shared_highwayhash_key));
memcpy(shared_siphash_key, reinterpret_cast<const char*>(seed_data.data()) + 64, 16); memcpy(shared_siphash_key, reinterpret_cast<const char*>(seed_data.data()) + 64, 16);
seeds_initialized = true; seeds_initialized = true;
@ -47,39 +58,45 @@ void KeyedHash::InitializeSeeds(const std::array<uint32_t, SEED_INIT_SIZE>& seed
void KeyedHash::InitOptions() void KeyedHash::InitOptions()
{ {
calculate_digest(Hash_SHA256, BifConst::digest_salt->Bytes(), BifConst::digest_salt->Len(), reinterpret_cast<unsigned char*>(cluster_highwayhash_key)); calculate_digest(Hash_SHA256, BifConst::digest_salt->Bytes(), BifConst::digest_salt->Len(),
reinterpret_cast<unsigned char*>(cluster_highwayhash_key));
} }
hash64_t KeyedHash::Hash64(const void* bytes, uint64_t size) hash64_t KeyedHash::Hash64(const void* bytes, uint64_t size)
{ {
return highwayhash::SipHash(shared_siphash_key, reinterpret_cast<const char *>(bytes), size); return highwayhash::SipHash(shared_siphash_key, reinterpret_cast<const char*>(bytes), size);
} }
void KeyedHash::Hash128(const void* bytes, uint64_t size, hash128_t* result) void KeyedHash::Hash128(const void* bytes, uint64_t size, hash128_t* result)
{ {
highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(shared_highwayhash_key, reinterpret_cast<const char *>(bytes), size, result); highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(
shared_highwayhash_key, reinterpret_cast<const char*>(bytes), size, result);
} }
void KeyedHash::Hash256(const void* bytes, uint64_t size, hash256_t* result) void KeyedHash::Hash256(const void* bytes, uint64_t size, hash256_t* result)
{ {
highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(shared_highwayhash_key, reinterpret_cast<const char *>(bytes), size, result); highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(
shared_highwayhash_key, reinterpret_cast<const char*>(bytes), size, result);
} }
hash64_t KeyedHash::StaticHash64(const void* bytes, uint64_t size) hash64_t KeyedHash::StaticHash64(const void* bytes, uint64_t size)
{ {
hash64_t result = 0; hash64_t result = 0;
highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(cluster_highwayhash_key, reinterpret_cast<const char *>(bytes), size, &result); highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(
cluster_highwayhash_key, reinterpret_cast<const char*>(bytes), size, &result);
return result; return result;
} }
void KeyedHash::StaticHash128(const void* bytes, uint64_t size, hash128_t* result) void KeyedHash::StaticHash128(const void* bytes, uint64_t size, hash128_t* result)
{ {
highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(cluster_highwayhash_key, reinterpret_cast<const char *>(bytes), size, result); highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(
cluster_highwayhash_key, reinterpret_cast<const char*>(bytes), size, result);
} }
void KeyedHash::StaticHash256(const void* bytes, uint64_t size, hash256_t* result) void KeyedHash::StaticHash256(const void* bytes, uint64_t size, hash256_t* result)
{ {
highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(cluster_highwayhash_key, reinterpret_cast<const char *>(bytes), size, result); highwayhash::InstructionSets::Run<highwayhash::HighwayHash>(
cluster_highwayhash_key, reinterpret_cast<const char*>(bytes), size, result);
} }
void init_hash_function() void init_hash_function()
@ -92,7 +109,7 @@ void init_hash_function()
HashKey::HashKey(bro_int_t i) HashKey::HashKey(bro_int_t i)
{ {
key_u.i = i; key_u.i = i;
key = (void*) &key_u; key = (void*)&key_u;
size = sizeof(i); size = sizeof(i);
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
@ -100,7 +117,7 @@ HashKey::HashKey(bro_int_t i)
HashKey::HashKey(bro_uint_t u) HashKey::HashKey(bro_uint_t u)
{ {
key_u.i = bro_int_t(u); key_u.i = bro_int_t(u);
key = (void*) &key_u; key = (void*)&key_u;
size = sizeof(u); size = sizeof(u);
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
@ -108,7 +125,7 @@ HashKey::HashKey(bro_uint_t u)
HashKey::HashKey(uint32_t u) HashKey::HashKey(uint32_t u)
{ {
key_u.u32 = u; key_u.u32 = u;
key = (void*) &key_u; key = (void*)&key_u;
size = sizeof(u); size = sizeof(u);
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
@ -116,19 +133,19 @@ HashKey::HashKey(uint32_t u)
HashKey::HashKey(const uint32_t u[], int n) HashKey::HashKey(const uint32_t u[], int n)
{ {
size = n * sizeof(u[0]); size = n * sizeof(u[0]);
key = (void*) u; key = (void*)u;
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
HashKey::HashKey(double d) HashKey::HashKey(double d)
{ {
union { union {
double d; double d;
int i[2]; int i[2];
} u; } u;
key_u.d = u.d = d; key_u.d = u.d = d;
key = (void*) &key_u; key = (void*)&key_u;
size = sizeof(d); size = sizeof(d);
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
@ -136,22 +153,22 @@ HashKey::HashKey(double d)
HashKey::HashKey(const void* p) HashKey::HashKey(const void* p)
{ {
key_u.p = p; key_u.p = p;
key = (void*) &key_u; key = (void*)&key_u;
size = sizeof(p); size = sizeof(p);
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
HashKey::HashKey(const char* s) HashKey::HashKey(const char* s)
{ {
size = strlen(s); // note - skip final \0 size = strlen(s); // note - skip final \0
key = (void*) s; key = (void*)s;
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
HashKey::HashKey(const String* s) HashKey::HashKey(const String* s)
{ {
size = s->Len(); size = s->Len();
key = (void*) s->Bytes(); key = (void*)s->Bytes();
hash = HashBytes(key, size); hash = HashBytes(key, size);
} }
@ -162,7 +179,7 @@ HashKey::HashKey(int copy_key, void* arg_key, int arg_size)
if ( copy_key ) if ( copy_key )
{ {
key = (void*) new char[size]; key = (void*)new char[size];
memcpy(key, arg_key, size); memcpy(key, arg_key, size);
} }
else else
@ -179,8 +196,7 @@ HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash)
is_our_dynamic = true; is_our_dynamic = true;
} }
HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash, HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash, bool /* dont_copy */)
bool /* dont_copy */)
{ {
size = arg_size; size = arg_size;
hash = arg_hash; hash = arg_hash;
@ -208,7 +224,7 @@ void* HashKey::TakeKey()
void* HashKey::CopyKey(const void* k, int s) const void* HashKey::CopyKey(const void* k, int s) const
{ {
void* k_copy = (void*) new char[s]; void* k_copy = (void*)new char[s];
memcpy(k_copy, k, s); memcpy(k_copy, k, s);
return k_copy; return k_copy;
} }
@ -218,4 +234,4 @@ hash_t HashKey::HashBytes(const void* bytes, int size)
return KeyedHash::Hash64(bytes, size); return KeyedHash::Hash64(bytes, size);
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -9,12 +9,13 @@
* We use these kinds of hashes heavily internally - e.g. for scriptland hash generation. * We use these kinds of hashes heavily internally - e.g. for scriptland hash generation.
* It is important that these hashes are not easily guessable to prevent complexity attacks. * It is important that these hashes are not easily guessable to prevent complexity attacks.
* *
* The HashKey class is the actual class that is used to generate Hash keys that are used internally, * The HashKey class is the actual class that is used to generate Hash keys that are used
* e.g. for lookups in hash-tables; the Hashes are also used for connection ID generation. * internally, e.g. for lookups in hash-tables; the Hashes are also used for connection ID
* generation.
* *
* This means that the hashes created by most functions in this file will be different each run, unless * This means that the hashes created by most functions in this file will be different each run,
* a seed file is used. There are a few functions that create hashes that are static over runs * unless a seed file is used. There are a few functions that create hashes that are static over
* and use an installation-wide seed value; these are specifically called out. * runs and use an installation-wide seed value; these are specifically called out.
*/ */
#pragma once #pragma once
@ -26,26 +27,33 @@
// to allow bro_md5_hmac access to the hmac seed // to allow bro_md5_hmac access to the hmac seed
#include "zeek/ZeekArgs.h" #include "zeek/ZeekArgs.h"
namespace zeek { class String; } namespace zeek
namespace zeek::detail { {
class String;
}
namespace zeek::detail
{
class Frame; class Frame;
class BifReturnVal; class BifReturnVal;
} }
namespace zeek::BifFunc { namespace zeek::BifFunc
extern zeek::detail::BifReturnVal md5_hmac_bif(zeek::detail::Frame* frame, const zeek::Args*); {
} extern zeek::detail::BifReturnVal md5_hmac_bif(zeek::detail::Frame* frame, const zeek::Args*);
}
namespace zeek::detail { namespace zeek::detail
{
typedef uint64_t hash_t; typedef uint64_t hash_t;
typedef uint64_t hash64_t; typedef uint64_t hash64_t;
typedef uint64_t hash128_t[2]; typedef uint64_t hash128_t[2];
typedef uint64_t hash256_t[4]; typedef uint64_t hash256_t[4];
class KeyedHash { class KeyedHash
{
public: public:
/** /**
* Generate a 64 bit digest hash. * Generate a 64 bit digest hash.
@ -193,19 +201,23 @@ public:
private: private:
// actually HHKey. This key changes each start (unless a seed is specified) // actually HHKey. This key changes each start (unless a seed is specified)
alignas(32) static uint64_t shared_highwayhash_key[4]; alignas(32) static uint64_t shared_highwayhash_key[4];
// actually HHKey. This key is installation specific and sourced from the digest_salt script-level const. // actually HHKey. This key is installation specific and sourced from the digest_salt
// script-level const.
alignas(32) static uint64_t cluster_highwayhash_key[4]; alignas(32) static uint64_t cluster_highwayhash_key[4];
// actually HH_U64, which has the same type. This key changes each start (unless a seed is specified) // actually HH_U64, which has the same type. This key changes each start (unless a seed is
// specified)
alignas(16) static unsigned long long shared_siphash_key[2]; alignas(16) static unsigned long long shared_siphash_key[2];
// This key changes each start (unless a seed is specified) // This key changes each start (unless a seed is specified)
inline static uint8_t shared_hmac_md5_key[16]; inline static uint8_t shared_hmac_md5_key[16];
inline static bool seeds_initialized = false; inline static bool seeds_initialized = false;
friend void util::detail::hmac_md5(size_t size, const unsigned char* bytes, unsigned char digest[16]); friend void util::detail::hmac_md5(size_t size, const unsigned char* bytes,
unsigned char digest[16]);
friend BifReturnVal BifFunc::md5_hmac_bif(zeek::detail::Frame* frame, const Args*); friend BifReturnVal BifFunc::md5_hmac_bif(zeek::detail::Frame* frame, const Args*);
}; };
typedef enum { typedef enum
{
HASH_KEY_INT, HASH_KEY_INT,
HASH_KEY_DOUBLE, HASH_KEY_DOUBLE,
HASH_KEY_STRING HASH_KEY_STRING
@ -213,7 +225,8 @@ typedef enum {
constexpr int NUM_HASH_KEYS = HASH_KEY_STRING + 1; constexpr int NUM_HASH_KEYS = HASH_KEY_STRING + 1;
class HashKey { class HashKey
{
public: public:
explicit HashKey(bro_int_t i); explicit HashKey(bro_int_t i);
explicit HashKey(bro_uint_t u); explicit HashKey(bro_uint_t u);
@ -226,7 +239,7 @@ public:
~HashKey() ~HashKey()
{ {
if ( is_our_dynamic ) if ( is_our_dynamic )
delete [] (char *) key; delete[](char*) key;
} }
// Create a HashKey given all of its components. "key" is assumed // Create a HashKey given all of its components. "key" is assumed
@ -257,30 +270,35 @@ public:
// we give them a copy of it. // we give them a copy of it.
void* TakeKey(); void* TakeKey();
const void* Key() const { return key; } const void* Key() const { return key; }
int Size() const { return size; } int Size() const { return size; }
hash_t Hash() const { return hash; } hash_t Hash() const { return hash; }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const { return padded_sizeof(*this) + util::pad_size(size); } "GHI-572.")]] unsigned int
MemoryAllocation() const
{
return padded_sizeof(*this) + util::pad_size(size);
}
static hash_t HashBytes(const void* bytes, int size); static hash_t HashBytes(const void* bytes, int size);
protected: protected:
void* CopyKey(const void* key, int size) const; void* CopyKey(const void* key, int size) const;
union { union {
bro_int_t i; bro_int_t i;
uint32_t u32; uint32_t u32;
double d; double d;
const void* p; const void* p;
} key_u; } key_u;
void* key; void* key;
hash_t hash; hash_t hash;
int size; int size;
bool is_our_dynamic = false; bool is_our_dynamic = false;
}; };
extern void init_hash_function(); extern void init_hash_function();
} // namespace zeek::detail } // namespace zeek::detail

142
src/ID.cc
View file

@ -1,28 +1,29 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/ID.h" #include "zeek/ID.h"
#include "zeek/Attr.h" #include "zeek/Attr.h"
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/Expr.h"
#include "zeek/Dict.h" #include "zeek/Dict.h"
#include "zeek/EventRegistry.h" #include "zeek/EventRegistry.h"
#include "zeek/Expr.h"
#include "zeek/File.h"
#include "zeek/Func.h" #include "zeek/Func.h"
#include "zeek/Scope.h" #include "zeek/Scope.h"
#include "zeek/Type.h"
#include "zeek/File.h"
#include "zeek/Traverse.h" #include "zeek/Traverse.h"
#include "zeek/Type.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/zeekygen/Manager.h"
#include "zeek/zeekygen/IdentifierInfo.h"
#include "zeek/zeekygen/ScriptInfo.h"
#include "zeek/zeekygen/utils.h"
#include "zeek/module_util.h" #include "zeek/module_util.h"
#include "zeek/script_opt/IDOptInfo.h" #include "zeek/script_opt/IDOptInfo.h"
#include "zeek/zeek-config.h"
#include "zeek/zeekygen/IdentifierInfo.h"
#include "zeek/zeekygen/Manager.h"
#include "zeek/zeekygen/ScriptInfo.h"
#include "zeek/zeekygen/utils.h"
namespace zeek { namespace zeek
{
RecordTypePtr id::conn_id; RecordTypePtr id::conn_id;
RecordTypePtr id::endpoint; RecordTypePtr id::endpoint;
@ -46,8 +47,7 @@ const TypePtr& id::find_type(std::string_view name)
auto id = zeek::detail::global_scope()->Find(name); auto id = zeek::detail::global_scope()->Find(name);
if ( ! id ) if ( ! id )
reporter->InternalError("Failed to find type named: %s", reporter->InternalError("Failed to find type named: %s", std::string(name).data());
std::string(name).data());
return id->GetType(); return id->GetType();
} }
@ -57,8 +57,7 @@ const ValPtr& id::find_val(std::string_view name)
auto id = zeek::detail::global_scope()->Find(name); auto id = zeek::detail::global_scope()->Find(name);
if ( ! id ) if ( ! id )
reporter->InternalError("Failed to find variable named: %s", reporter->InternalError("Failed to find variable named: %s", std::string(name).data());
std::string(name).data());
return id->GetVal(); return id->GetVal();
} }
@ -68,12 +67,11 @@ const ValPtr& id::find_const(std::string_view name)
auto id = zeek::detail::global_scope()->Find(name); auto id = zeek::detail::global_scope()->Find(name);
if ( ! id ) if ( ! id )
reporter->InternalError("Failed to find variable named: %s", reporter->InternalError("Failed to find variable named: %s", std::string(name).data());
std::string(name).data());
if ( ! id->IsConst() ) if ( ! id->IsConst() )
reporter->InternalError("Variable is not 'const', but expected to be: %s", reporter->InternalError("Variable is not 'const', but expected to be: %s",
std::string(name).data()); std::string(name).data());
return id->GetVal(); return id->GetVal();
} }
@ -87,7 +85,7 @@ FuncPtr id::find_func(std::string_view name)
if ( ! IsFunc(v->GetType()->Tag()) ) if ( ! IsFunc(v->GetType()->Tag()) )
reporter->InternalError("Expected variable '%s' to be a function", reporter->InternalError("Expected variable '%s' to be a function",
std::string(name).data()); std::string(name).data());
return v.get()->As<FuncVal*>()->AsFuncPtr(); return v.get()->As<FuncVal*>()->AsFuncPtr();
} }
@ -107,7 +105,8 @@ void id::detail::init_types()
index_vec = id::find_type<VectorType>("index_vec"); index_vec = id::find_type<VectorType>("index_vec");
} }
namespace detail { namespace detail
{
ID::ID(const char* arg_name, IDScope arg_scope, bool arg_is_export) ID::ID(const char* arg_name, IDScope arg_scope, bool arg_is_export)
{ {
@ -129,7 +128,7 @@ ID::ID(const char* arg_name, IDScope arg_scope, bool arg_is_export)
ID::~ID() ID::~ID()
{ {
delete [] name; delete[] name;
delete opt_info; delete opt_info;
} }
@ -157,8 +156,7 @@ void ID::SetVal(ValPtr v)
UpdateValID(); UpdateValID();
#endif #endif
if ( type && val && if ( type && val && type->Tag() == TYPE_FUNC &&
type->Tag() == TYPE_FUNC &&
type->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT ) type->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT )
{ {
EventHandler* handler = event_registry->Lookup(name); EventHandler* handler = event_registry->Lookup(name);
@ -186,9 +184,8 @@ void ID::SetVal(ValPtr v, InitClass c)
return; return;
} }
if ( type->Tag() != TYPE_TABLE && if ( type->Tag() != TYPE_TABLE && (type->Tag() != TYPE_PATTERN || c == INIT_REMOVE) &&
(type->Tag() != TYPE_PATTERN || c == INIT_REMOVE) && (type->Tag() != TYPE_VECTOR || c == INIT_REMOVE) )
(type->Tag() != TYPE_VECTOR || c == INIT_REMOVE) )
{ {
if ( c == INIT_EXTRA ) if ( c == INIT_EXTRA )
Error("+= initializer only applies to tables, sets, vectors and patterns", v.get()); Error("+= initializer only applies to tables, sets, vectors and patterns", v.get());
@ -226,7 +223,8 @@ void ID::SetVal(ExprPtr ev, InitClass c)
if ( ! val ) if ( ! val )
{ {
Error(zeek::util::fmt("%s initializer applied to ID without value", Error(zeek::util::fmt("%s initializer applied to ID without value",
c == INIT_EXTRA ? "+=" : "-="), this); c == INIT_EXTRA ? "+=" : "-="),
this);
return; return;
} }
@ -373,8 +371,7 @@ TraversalCode ID::Traverse(TraversalCallback* cb) const
} }
// FIXME: Perhaps we should be checking at other than global scope. // FIXME: Perhaps we should be checking at other than global scope.
else if ( val && IsFunc(val->GetType()->Tag()) && else if ( val && IsFunc(val->GetType()->Tag()) && cb->current_scope == detail::global_scope() )
cb->current_scope == detail::global_scope() )
{ {
tc = val->AsFunc()->Traverse(cb); tc = val->AsFunc()->Traverse(cb);
HANDLE_TC_STMT_PRE(tc); HANDLE_TC_STMT_PRE(tc);
@ -448,26 +445,27 @@ void ID::DescribeReSTShort(ODesc* d) const
{ {
TypeTag t = type->Tag(); TypeTag t = type->Tag();
switch ( t ) { switch ( t )
case TYPE_TABLE: {
d->Add(type->IsSet() ? "set" : type_name(t)); case TYPE_TABLE:
break; d->Add(type->IsSet() ? "set" : type_name(t));
break;
case TYPE_FUNC: case TYPE_FUNC:
d->Add(type->AsFuncType()->FlavorString().c_str()); d->Add(type->AsFuncType()->FlavorString().c_str());
break; break;
case TYPE_ENUM: case TYPE_ENUM:
if ( is_type ) if ( is_type )
d->Add(type_name(t));
else
d->Add(zeekygen_mgr->GetEnumTypeName(Name()).c_str());
break;
default:
d->Add(type_name(t)); d->Add(type_name(t));
else break;
d->Add(zeekygen_mgr->GetEnumTypeName(Name()).c_str()); }
break;
default:
d->Add(type_name(t));
break;
}
} }
d->Add("`"); d->Add("`");
@ -529,8 +527,7 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const
{ {
auto ft = type->AsFuncType(); auto ft = type->AsFuncType();
if ( ft->Flavor() == FUNC_FLAVOR_EVENT || if ( ft->Flavor() == FUNC_FLAVOR_EVENT || ft->Flavor() == FUNC_FLAVOR_HOOK )
ft->Flavor() == FUNC_FLAVOR_HOOK )
{ {
const auto& protos = ft->Prototypes(); const auto& protos = ft->Prototypes();
@ -568,42 +565,40 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const
d->NL(); d->NL();
} }
if ( val && type && if ( val && type && type->Tag() != TYPE_FUNC && type->InternalType() != TYPE_INTERNAL_VOID &&
type->Tag() != TYPE_FUNC &&
type->InternalType() != TYPE_INTERNAL_VOID &&
// Values within Version module are likely to include a // Values within Version module are likely to include a
// constantly-changing version number and be a frequent // constantly-changing version number and be a frequent
// source of error/desynchronization, so don't include them. // source of error/desynchronization, so don't include them.
ModuleName() != "Version" ) ModuleName() != "Version" )
{ {
d->Add(":Default:"); d->Add(":Default:");
auto ii = zeekygen_mgr->GetIdentifierInfo(Name()); auto ii = zeekygen_mgr->GetIdentifierInfo(Name());
auto redefs = ii->GetRedefs(); auto redefs = ii->GetRedefs();
const auto& iv = ! redefs.empty() && ii->InitialVal() ? ii->InitialVal() const auto& iv = ! redefs.empty() && ii->InitialVal() ? ii->InitialVal() : val;
: val;
if ( type->InternalType() == TYPE_INTERNAL_OTHER ) if ( type->InternalType() == TYPE_INTERNAL_OTHER )
{ {
switch ( type->Tag() ) { switch ( type->Tag() )
case TYPE_TABLE: {
if ( iv->AsTable()->Length() == 0 ) case TYPE_TABLE:
{ if ( iv->AsTable()->Length() == 0 )
d->Add(" ``{}``"); {
d->NL(); d->Add(" ``{}``");
break; d->NL();
} break;
// Fall-through. }
// Fall-through.
default: default:
d->NL(); d->NL();
d->PushIndent(); d->PushIndent();
d->Add("::"); d->Add("::");
d->NL(); d->NL();
d->PushIndent(); d->PushIndent();
iv->DescribeReST(d); iv->DescribeReST(d);
d->PopIndent(); d->PopIndent();
d->PopIndent(); d->PopIndent();
} }
} }
else else
@ -675,12 +670,11 @@ std::vector<Func*> ID::GetOptionHandlers() const
return v; return v;
} }
void IDOptInfo::AddInitExpr(ExprPtr init_expr) void IDOptInfo::AddInitExpr(ExprPtr init_expr)
{ {
init_exprs.emplace_back(std::move(init_expr)); init_exprs.emplace_back(std::move(init_expr));
} }
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

119
src/ID.h
View file

@ -7,12 +7,13 @@
#include <string_view> #include <string_view>
#include <vector> #include <vector>
#include "zeek/Obj.h"
#include "zeek/Attr.h" #include "zeek/Attr.h"
#include "zeek/Notifier.h" #include "zeek/Notifier.h"
#include "zeek/Obj.h"
#include "zeek/TraverseTypes.h" #include "zeek/TraverseTypes.h"
namespace zeek { namespace zeek
{
class Func; class Func;
class Val; class Val;
@ -29,23 +30,36 @@ using EnumTypePtr = IntrusivePtr<EnumType>;
using ValPtr = IntrusivePtr<Val>; using ValPtr = IntrusivePtr<Val>;
using FuncPtr = IntrusivePtr<Func>; using FuncPtr = IntrusivePtr<Func>;
} }
namespace zeek::detail { namespace zeek::detail
{
class Attributes; class Attributes;
class Expr; class Expr;
using ExprPtr = IntrusivePtr<Expr>; using ExprPtr = IntrusivePtr<Expr>;
enum InitClass { INIT_NONE, INIT_FULL, INIT_EXTRA, INIT_REMOVE, }; enum InitClass
enum IDScope { SCOPE_FUNCTION, SCOPE_MODULE, SCOPE_GLOBAL }; {
INIT_NONE,
INIT_FULL,
INIT_EXTRA,
INIT_REMOVE,
};
enum IDScope
{
SCOPE_FUNCTION,
SCOPE_MODULE,
SCOPE_GLOBAL
};
class ID; class ID;
using IDPtr = IntrusivePtr<ID>; using IDPtr = IntrusivePtr<ID>;
class IDOptInfo; class IDOptInfo;
class ID final : public Obj, public notifier::detail::Modifiable { class ID final : public Obj, public notifier::detail::Modifiable
{
public: public:
static inline const IDPtr nil; static inline const IDPtr nil;
@ -53,53 +67,48 @@ public:
~ID() override; ~ID() override;
const char* Name() const { return name; } const char* Name() const { return name; }
int Scope() const { return scope; } int Scope() const { return scope; }
bool IsGlobal() const { return scope != SCOPE_FUNCTION; } bool IsGlobal() const { return scope != SCOPE_FUNCTION; }
bool IsExport() const { return is_export; } bool IsExport() const { return is_export; }
void SetExport() { is_export = true; } void SetExport() { is_export = true; }
std::string ModuleName() const; std::string ModuleName() const;
void SetType(TypePtr t); void SetType(TypePtr t);
const TypePtr& GetType() const const TypePtr& GetType() const { return type; }
{ return type; }
template <class T> template <class T> IntrusivePtr<T> GetType() const { return cast_intrusive<T>(type); }
IntrusivePtr<T> GetType() const
{ return cast_intrusive<T>(type); }
bool IsType() const bool IsType() const { return is_type; }
{ return is_type; }
void MakeType() { is_type = true; } void MakeType() { is_type = true; }
void SetVal(ValPtr v); void SetVal(ValPtr v);
void SetVal(ValPtr v, InitClass c); void SetVal(ValPtr v, InitClass c);
void SetVal(ExprPtr ev, InitClass c); void SetVal(ExprPtr ev, InitClass c);
bool HasVal() const { return val != nullptr; } bool HasVal() const { return val != nullptr; }
const ValPtr& GetVal() const const ValPtr& GetVal() const { return val; }
{ return val; }
void ClearVal(); void ClearVal();
void SetConst() { is_const = true; } void SetConst() { is_const = true; }
bool IsConst() const { return is_const; } bool IsConst() const { return is_const; }
void SetOption(); void SetOption();
bool IsOption() const { return is_option; } bool IsOption() const { return is_option; }
void SetEnumConst() { is_enum_const = true; } void SetEnumConst() { is_enum_const = true; }
bool IsEnumConst() const { return is_enum_const; } bool IsEnumConst() const { return is_enum_const; }
void SetOffset(int arg_offset) { offset = arg_offset; } void SetOffset(int arg_offset) { offset = arg_offset; }
int Offset() const { return offset; } int Offset() const { return offset; }
bool IsRedefinable() const; bool IsRedefinable() const;
@ -108,8 +117,7 @@ public:
void RemoveAttr(AttrTag a); void RemoveAttr(AttrTag a);
void UpdateValAttrs(); void UpdateValAttrs();
const AttributesPtr& GetAttrs() const const AttributesPtr& GetAttrs() const { return attrs; }
{ return attrs; }
const AttrPtr& GetAttr(AttrTag t) const; const AttrPtr& GetAttr(AttrTag t) const;
@ -128,20 +136,17 @@ public:
void DescribeReST(ODesc* d, bool roles_only = false) const; void DescribeReST(ODesc* d, bool roles_only = false) const;
void DescribeReSTShort(ODesc* d) const; void DescribeReSTShort(ODesc* d) const;
bool DoInferReturnType() const bool DoInferReturnType() const { return infer_return_type; }
{ return infer_return_type; } void SetInferReturnType(bool infer) { infer_return_type = infer; }
void SetInferReturnType(bool infer)
{ infer_return_type = infer; }
virtual TraversalCode Traverse(TraversalCallback* cb) const; virtual TraversalCode Traverse(TraversalCallback* cb) const;
bool HasOptionHandlers() const bool HasOptionHandlers() const { return ! option_handlers.empty(); }
{ return !option_handlers.empty(); }
void AddOptionHandler(FuncPtr callback, int priority); void AddOptionHandler(FuncPtr callback, int priority);
std::vector<Func*> GetOptionHandlers() const; std::vector<Func*> GetOptionHandlers() const;
IDOptInfo* GetOptInfo() const { return opt_info; } IDOptInfo* GetOptInfo() const { return opt_info; }
protected: protected:
void EvalFunc(ExprPtr ef, ExprPtr ev); void EvalFunc(ExprPtr ef, ExprPtr ev);
@ -168,12 +173,12 @@ protected:
// via the associated pointer, to allow it to be modified in // via the associated pointer, to allow it to be modified in
// contexts where the ID is itself "const". // contexts where the ID is itself "const".
IDOptInfo* opt_info; IDOptInfo* opt_info;
};
}; } // namespace zeek::detail
} // namespace zeek::detail namespace zeek::id
{
namespace zeek::id {
/** /**
* Lookup an ID in the global module and return it, if one exists; * Lookup an ID in the global module and return it, if one exists;
@ -197,9 +202,10 @@ const TypePtr& find_type(std::string_view name);
* @param name The identifier name to lookup * @param name The identifier name to lookup
* @return The type of the identifier. * @return The type of the identifier.
*/ */
template<class T> template <class T> IntrusivePtr<T> find_type(std::string_view name)
IntrusivePtr<T> find_type(std::string_view name) {
{ return cast_intrusive<T>(find_type(name)); } return cast_intrusive<T>(find_type(name));
}
/** /**
* Lookup an ID by its name and return its value. A fatal occurs if the ID * Lookup an ID by its name and return its value. A fatal occurs if the ID
@ -215,9 +221,10 @@ const ValPtr& find_val(std::string_view name);
* @param name The identifier name to lookup * @param name The identifier name to lookup
* @return The current value of the identifier. * @return The current value of the identifier.
*/ */
template<class T> template <class T> IntrusivePtr<T> find_val(std::string_view name)
IntrusivePtr<T> find_val(std::string_view name) {
{ return cast_intrusive<T>(find_val(name)); } return cast_intrusive<T>(find_val(name));
}
/** /**
* Lookup an ID by its name and return its value. A fatal occurs if the ID * Lookup an ID by its name and return its value. A fatal occurs if the ID
@ -233,9 +240,10 @@ const ValPtr& find_const(std::string_view name);
* @param name The identifier name to lookup * @param name The identifier name to lookup
* @return The current value of the identifier. * @return The current value of the identifier.
*/ */
template<class T> template <class T> IntrusivePtr<T> find_const(std::string_view name)
IntrusivePtr<T> find_const(std::string_view name) {
{ return cast_intrusive<T>(find_const(name)); } return cast_intrusive<T>(find_const(name));
}
/** /**
* Lookup an ID by its name and return the function it references. * Lookup an ID by its name and return the function it references.
@ -257,9 +265,10 @@ extern TableTypePtr count_set;
extern VectorTypePtr string_vec; extern VectorTypePtr string_vec;
extern VectorTypePtr index_vec; extern VectorTypePtr index_vec;
namespace detail { namespace detail
{
void init_types(); void init_types();
} // namespace detail } // namespace detail
} // namespace zeek::id } // namespace zeek::id

824
src/IP.cc
View file

@ -2,18 +2,19 @@
#include "zeek/IP.h" #include "zeek/IP.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
#include <netinet/in.h>
#include <sys/types.h>
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
#include "zeek/Reporter.h"
#include "zeek/Type.h" #include "zeek/Type.h"
#include "zeek/Val.h" #include "zeek/Val.h"
#include "zeek/Var.h" #include "zeek/Var.h"
#include "zeek/ZeekString.h" #include "zeek/ZeekString.h"
#include "zeek/Reporter.h"
namespace zeek { namespace zeek
{
static VectorValPtr BuildOptionsVal(const u_char* data, int len) static VectorValPtr BuildOptionsVal(const u_char* data, int len)
{ {
@ -22,7 +23,7 @@ static VectorValPtr BuildOptionsVal(const u_char* data, int len)
while ( len > 0 ) while ( len > 0 )
{ {
static auto ip6_option_type = id::find_type<RecordType>("ip6_option"); static auto ip6_option_type = id::find_type<RecordType>("ip6_option");
const struct ip6_opt* opt = (const struct ip6_opt*) data; const struct ip6_opt* opt = (const struct ip6_opt*)data;
auto rv = make_intrusive<RecordVal>(ip6_option_type); auto rv = make_intrusive<RecordVal>(ip6_option_type);
rv->Assign(0, opt->ip6o_type); rv->Assign(0, opt->ip6o_type);
@ -54,251 +55,265 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
{ {
RecordValPtr rv; RecordValPtr rv;
switch ( type ) { switch ( type )
case IPPROTO_IPV6:
{ {
static auto ip6_hdr_type = id::find_type<RecordType>("ip6_hdr"); case IPPROTO_IPV6:
rv = make_intrusive<RecordVal>(ip6_hdr_type); {
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data; static auto ip6_hdr_type = id::find_type<RecordType>("ip6_hdr");
rv->Assign(0, (ntohl(ip6->ip6_flow) & 0x0ff00000)>>20); rv = make_intrusive<RecordVal>(ip6_hdr_type);
rv->Assign(1, ntohl(ip6->ip6_flow) & 0x000fffff); const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
rv->Assign(2, ntohs(ip6->ip6_plen)); rv->Assign(0, (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20);
rv->Assign(3, ip6->ip6_nxt); rv->Assign(1, ntohl(ip6->ip6_flow) & 0x000fffff);
rv->Assign(4, ip6->ip6_hlim); rv->Assign(2, ntohs(ip6->ip6_plen));
rv->Assign(5, make_intrusive<AddrVal>(IPAddr(ip6->ip6_src))); rv->Assign(3, ip6->ip6_nxt);
rv->Assign(6, make_intrusive<AddrVal>(IPAddr(ip6->ip6_dst))); rv->Assign(4, ip6->ip6_hlim);
if ( ! chain ) rv->Assign(5, make_intrusive<AddrVal>(IPAddr(ip6->ip6_src)));
chain = make_intrusive<VectorVal>( rv->Assign(6, make_intrusive<AddrVal>(IPAddr(ip6->ip6_dst)));
id::find_type<VectorType>("ip6_ext_hdr_chain")); if ( ! chain )
rv->Assign(7, std::move(chain)); chain =
} make_intrusive<VectorVal>(id::find_type<VectorType>("ip6_ext_hdr_chain"));
break; rv->Assign(7, std::move(chain));
}
case IPPROTO_HOPOPTS:
{
static auto ip6_hopopts_type = id::find_type<RecordType>("ip6_hopopts");
rv = make_intrusive<RecordVal>(ip6_hopopts_type);
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
rv->Assign(0, hbh->ip6h_nxt);
rv->Assign(1, hbh->ip6h_len);
uint16_t off = 2 * sizeof(uint8_t);
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
}
break;
case IPPROTO_DSTOPTS:
{
static auto ip6_dstopts_type = id::find_type<RecordType>("ip6_dstopts");
rv = make_intrusive<RecordVal>(ip6_dstopts_type);
const struct ip6_dest* dst = (const struct ip6_dest*)data;
rv->Assign(0, dst->ip6d_nxt);
rv->Assign(1, dst->ip6d_len);
uint16_t off = 2 * sizeof(uint8_t);
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
}
break;
case IPPROTO_ROUTING:
{
static auto ip6_routing_type = id::find_type<RecordType>("ip6_routing");
rv = make_intrusive<RecordVal>(ip6_routing_type);
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
rv->Assign(0, rt->ip6r_nxt);
rv->Assign(1, rt->ip6r_len);
rv->Assign(2, rt->ip6r_type);
rv->Assign(3, rt->ip6r_segleft);
uint16_t off = 4 * sizeof(uint8_t);
rv->Assign(4, new String(data + off, Length() - off, true));
}
break;
case IPPROTO_FRAGMENT:
{
static auto ip6_fragment_type = id::find_type<RecordType>("ip6_fragment");
rv = make_intrusive<RecordVal>(ip6_fragment_type);
const struct ip6_frag* frag = (const struct ip6_frag*)data;
rv->Assign(0, frag->ip6f_nxt);
rv->Assign(1, frag->ip6f_reserved);
rv->Assign(2, (ntohs(frag->ip6f_offlg) & 0xfff8)>>3);
rv->Assign(3, (ntohs(frag->ip6f_offlg) & 0x0006)>>1);
rv->Assign(4, static_cast<bool>(ntohs(frag->ip6f_offlg) & 0x0001));
rv->Assign(5, ntohl(frag->ip6f_ident));
}
break;
case IPPROTO_AH:
{
static auto ip6_ah_type = id::find_type<RecordType>("ip6_ah");
rv = make_intrusive<RecordVal>(ip6_ah_type);
rv->Assign(0, ((ip6_ext*)data)->ip6e_nxt);
rv->Assign(1, ((ip6_ext*)data)->ip6e_len);
rv->Assign(2, ntohs(((uint16_t*)data)[1]));
rv->Assign(3, ntohl(((uint32_t*)data)[1]));
if ( Length() >= 12 )
{
// Sequence Number and ICV fields can only be extracted if
// Payload Len was non-zero for this header.
rv->Assign(4, ntohl(((uint32_t*)data)[2]));
uint16_t off = 3 * sizeof(uint32_t);
rv->Assign(5, new String(data + off, Length() - off, true));
}
}
break;
case IPPROTO_ESP:
{
static auto ip6_esp_type = id::find_type<RecordType>("ip6_esp");
rv = make_intrusive<RecordVal>(ip6_esp_type);
const uint32_t* esp = (const uint32_t*)data;
rv->Assign(0, ntohl(esp[0]));
rv->Assign(1, ntohl(esp[1]));
}
break;
case IPPROTO_MOBILITY:
{
static auto ip6_mob_type = id::find_type<RecordType>("ip6_mobility_hdr");
rv = make_intrusive<RecordVal>(ip6_mob_type);
const struct ip6_mobility* mob = (const struct ip6_mobility*) data;
rv->Assign(0, mob->ip6mob_payload);
rv->Assign(1, mob->ip6mob_len);
rv->Assign(2, mob->ip6mob_type);
rv->Assign(3, mob->ip6mob_rsv);
rv->Assign(4, ntohs(mob->ip6mob_chksum));
static auto ip6_mob_msg_type = id::find_type<RecordType>("ip6_mobility_msg");
auto msg = make_intrusive<RecordVal>(ip6_mob_msg_type);
msg->Assign(0, mob->ip6mob_type);
uint16_t off = sizeof(ip6_mobility);
const u_char* msg_data = data + off;
static auto ip6_mob_brr_type = id::find_type<RecordType>("ip6_mobility_brr");
static auto ip6_mob_hoti_type = id::find_type<RecordType>("ip6_mobility_hoti");
static auto ip6_mob_coti_type = id::find_type<RecordType>("ip6_mobility_coti");
static auto ip6_mob_hot_type = id::find_type<RecordType>("ip6_mobility_hot");
static auto ip6_mob_cot_type = id::find_type<RecordType>("ip6_mobility_cot");
static auto ip6_mob_bu_type = id::find_type<RecordType>("ip6_mobility_bu");
static auto ip6_mob_back_type = id::find_type<RecordType>("ip6_mobility_back");
static auto ip6_mob_be_type = id::find_type<RecordType>("ip6_mobility_be");
switch ( mob->ip6mob_type ) {
case 0:
{
auto m = make_intrusive<RecordVal>(ip6_mob_brr_type);
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
off += sizeof(uint16_t);
m->Assign(1, BuildOptionsVal(data + off, Length() - off));
msg->Assign(1, std::move(m));
}
break; break;
case 1: case IPPROTO_HOPOPTS:
{ {
auto m = make_intrusive<RecordVal>(ip6_mob_hoti_type); static auto ip6_hopopts_type = id::find_type<RecordType>("ip6_hopopts");
m->Assign(0, ntohs(*((uint16_t*)msg_data))); rv = make_intrusive<RecordVal>(ip6_hopopts_type);
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t))))); const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
off += sizeof(uint16_t) + sizeof(uint64_t); rv->Assign(0, hbh->ip6h_nxt);
m->Assign(2, BuildOptionsVal(data + off, Length() - off)); rv->Assign(1, hbh->ip6h_len);
msg->Assign(2, std::move(m)); uint16_t off = 2 * sizeof(uint8_t);
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
}
break; break;
}
case 2: case IPPROTO_DSTOPTS:
{ {
auto m = make_intrusive<RecordVal>(ip6_mob_coti_type); static auto ip6_dstopts_type = id::find_type<RecordType>("ip6_dstopts");
m->Assign(0, ntohs(*((uint16_t*)msg_data))); rv = make_intrusive<RecordVal>(ip6_dstopts_type);
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t))))); const struct ip6_dest* dst = (const struct ip6_dest*)data;
off += sizeof(uint16_t) + sizeof(uint64_t); rv->Assign(0, dst->ip6d_nxt);
m->Assign(2, BuildOptionsVal(data + off, Length() - off)); rv->Assign(1, dst->ip6d_len);
msg->Assign(3, std::move(m)); uint16_t off = 2 * sizeof(uint8_t);
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
}
break; break;
}
case 3: case IPPROTO_ROUTING:
{ {
auto m = make_intrusive<RecordVal>(ip6_mob_hot_type); static auto ip6_routing_type = id::find_type<RecordType>("ip6_routing");
m->Assign(0, ntohs(*((uint16_t*)msg_data))); rv = make_intrusive<RecordVal>(ip6_routing_type);
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t))))); const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
m->Assign(2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t))))); rv->Assign(0, rt->ip6r_nxt);
off += sizeof(uint16_t) + 2 * sizeof(uint64_t); rv->Assign(1, rt->ip6r_len);
m->Assign(3, BuildOptionsVal(data + off, Length() - off)); rv->Assign(2, rt->ip6r_type);
msg->Assign(4, std::move(m)); rv->Assign(3, rt->ip6r_segleft);
uint16_t off = 4 * sizeof(uint8_t);
rv->Assign(4, new String(data + off, Length() - off, true));
}
break; break;
}
case 4: case IPPROTO_FRAGMENT:
{ {
auto m = make_intrusive<RecordVal>(ip6_mob_cot_type); static auto ip6_fragment_type = id::find_type<RecordType>("ip6_fragment");
m->Assign(0, ntohs(*((uint16_t*)msg_data))); rv = make_intrusive<RecordVal>(ip6_fragment_type);
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t))))); const struct ip6_frag* frag = (const struct ip6_frag*)data;
m->Assign(2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t))))); rv->Assign(0, frag->ip6f_nxt);
off += sizeof(uint16_t) + 2 * sizeof(uint64_t); rv->Assign(1, frag->ip6f_reserved);
m->Assign(3, BuildOptionsVal(data + off, Length() - off)); rv->Assign(2, (ntohs(frag->ip6f_offlg) & 0xfff8) >> 3);
msg->Assign(5, std::move(m)); rv->Assign(3, (ntohs(frag->ip6f_offlg) & 0x0006) >> 1);
rv->Assign(4, static_cast<bool>(ntohs(frag->ip6f_offlg) & 0x0001));
rv->Assign(5, ntohl(frag->ip6f_ident));
}
break; break;
}
case 5: case IPPROTO_AH:
{ {
auto m = make_intrusive<RecordVal>(ip6_mob_bu_type); static auto ip6_ah_type = id::find_type<RecordType>("ip6_ah");
m->Assign(0, ntohs(*((uint16_t*)msg_data))); rv = make_intrusive<RecordVal>(ip6_ah_type);
m->Assign(1, static_cast<bool>(ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x8000)); rv->Assign(0, ((ip6_ext*)data)->ip6e_nxt);
m->Assign(2, static_cast<bool>(ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x4000)); rv->Assign(1, ((ip6_ext*)data)->ip6e_len);
m->Assign(3, static_cast<bool>(ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x2000)); rv->Assign(2, ntohs(((uint16_t*)data)[1]));
m->Assign(4, static_cast<bool>(ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x1000)); rv->Assign(3, ntohl(((uint32_t*)data)[1]));
m->Assign(5, ntohs(*((uint16_t*)(msg_data + 2*sizeof(uint16_t)))));
off += 3 * sizeof(uint16_t);
m->Assign(6, BuildOptionsVal(data + off, Length() - off));
msg->Assign(6, std::move(m));
break;
}
case 6: if ( Length() >= 12 )
{ {
auto m = make_intrusive<RecordVal>(ip6_mob_back_type); // Sequence Number and ICV fields can only be extracted if
m->Assign(0, *((uint8_t*)msg_data)); // Payload Len was non-zero for this header.
m->Assign(1, static_cast<bool>(*((uint8_t*)(msg_data + sizeof(uint8_t))) & 0x80)); rv->Assign(4, ntohl(((uint32_t*)data)[2]));
m->Assign(2, ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t))))); uint16_t off = 3 * sizeof(uint32_t);
m->Assign(3, ntohs(*((uint16_t*)(msg_data + 2*sizeof(uint16_t))))); rv->Assign(5, new String(data + off, Length() - off, true));
off += 3 * sizeof(uint16_t); }
m->Assign(4, BuildOptionsVal(data + off, Length() - off)); }
msg->Assign(7, std::move(m));
break; break;
}
case 7: case IPPROTO_ESP:
{ {
auto m = make_intrusive<RecordVal>(ip6_mob_be_type); static auto ip6_esp_type = id::find_type<RecordType>("ip6_esp");
m->Assign(0, *((uint8_t*)msg_data)); rv = make_intrusive<RecordVal>(ip6_esp_type);
const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16_t)); const uint32_t* esp = (const uint32_t*)data;
m->Assign(1, make_intrusive<AddrVal>(IPAddr(*hoa))); rv->Assign(0, ntohl(esp[0]));
off += sizeof(uint16_t) + sizeof(in6_addr); rv->Assign(1, ntohl(esp[1]));
m->Assign(2, BuildOptionsVal(data + off, Length() - off)); }
msg->Assign(8, std::move(m)); break;
case IPPROTO_MOBILITY:
{
static auto ip6_mob_type = id::find_type<RecordType>("ip6_mobility_hdr");
rv = make_intrusive<RecordVal>(ip6_mob_type);
const struct ip6_mobility* mob = (const struct ip6_mobility*)data;
rv->Assign(0, mob->ip6mob_payload);
rv->Assign(1, mob->ip6mob_len);
rv->Assign(2, mob->ip6mob_type);
rv->Assign(3, mob->ip6mob_rsv);
rv->Assign(4, ntohs(mob->ip6mob_chksum));
static auto ip6_mob_msg_type = id::find_type<RecordType>("ip6_mobility_msg");
auto msg = make_intrusive<RecordVal>(ip6_mob_msg_type);
msg->Assign(0, mob->ip6mob_type);
uint16_t off = sizeof(ip6_mobility);
const u_char* msg_data = data + off;
static auto ip6_mob_brr_type = id::find_type<RecordType>("ip6_mobility_brr");
static auto ip6_mob_hoti_type = id::find_type<RecordType>("ip6_mobility_hoti");
static auto ip6_mob_coti_type = id::find_type<RecordType>("ip6_mobility_coti");
static auto ip6_mob_hot_type = id::find_type<RecordType>("ip6_mobility_hot");
static auto ip6_mob_cot_type = id::find_type<RecordType>("ip6_mobility_cot");
static auto ip6_mob_bu_type = id::find_type<RecordType>("ip6_mobility_bu");
static auto ip6_mob_back_type = id::find_type<RecordType>("ip6_mobility_back");
static auto ip6_mob_be_type = id::find_type<RecordType>("ip6_mobility_be");
switch ( mob->ip6mob_type )
{
case 0:
{
auto m = make_intrusive<RecordVal>(ip6_mob_brr_type);
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
off += sizeof(uint16_t);
m->Assign(1, BuildOptionsVal(data + off, Length() - off));
msg->Assign(1, std::move(m));
}
break;
case 1:
{
auto m = make_intrusive<RecordVal>(ip6_mob_hoti_type);
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
off += sizeof(uint16_t) + sizeof(uint64_t);
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
msg->Assign(2, std::move(m));
break;
}
case 2:
{
auto m = make_intrusive<RecordVal>(ip6_mob_coti_type);
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
off += sizeof(uint16_t) + sizeof(uint64_t);
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
msg->Assign(3, std::move(m));
break;
}
case 3:
{
auto m = make_intrusive<RecordVal>(ip6_mob_hot_type);
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
m->Assign(2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) +
sizeof(uint64_t)))));
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
msg->Assign(4, std::move(m));
break;
}
case 4:
{
auto m = make_intrusive<RecordVal>(ip6_mob_cot_type);
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
m->Assign(2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) +
sizeof(uint64_t)))));
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
msg->Assign(5, std::move(m));
break;
}
case 5:
{
auto m = make_intrusive<RecordVal>(ip6_mob_bu_type);
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
m->Assign(1, static_cast<bool>(
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
0x8000));
m->Assign(2, static_cast<bool>(
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
0x4000));
m->Assign(3, static_cast<bool>(
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
0x2000));
m->Assign(4, static_cast<bool>(
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
0x1000));
m->Assign(5, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
off += 3 * sizeof(uint16_t);
m->Assign(6, BuildOptionsVal(data + off, Length() - off));
msg->Assign(6, std::move(m));
break;
}
case 6:
{
auto m = make_intrusive<RecordVal>(ip6_mob_back_type);
m->Assign(0, *((uint8_t*)msg_data));
m->Assign(1, static_cast<bool>(
*((uint8_t*)(msg_data + sizeof(uint8_t))) & 0x80));
m->Assign(2, ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))));
m->Assign(3, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
off += 3 * sizeof(uint16_t);
m->Assign(4, BuildOptionsVal(data + off, Length() - off));
msg->Assign(7, std::move(m));
break;
}
case 7:
{
auto m = make_intrusive<RecordVal>(ip6_mob_be_type);
m->Assign(0, *((uint8_t*)msg_data));
const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16_t));
m->Assign(1, make_intrusive<AddrVal>(IPAddr(*hoa)));
off += sizeof(uint16_t) + sizeof(in6_addr);
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
msg->Assign(8, std::move(m));
break;
}
default:
reporter->Weird("unknown_mobility_type", util::fmt("%d", mob->ip6mob_type));
break;
}
rv->Assign(5, std::move(msg));
}
break; break;
}
default: default:
reporter->Weird("unknown_mobility_type", util::fmt("%d", mob->ip6mob_type));
break; break;
} }
rv->Assign(5, std::move(msg));
}
break;
default:
break;
}
return rv; return rv;
} }
RecordValPtr IPv6_Hdr::ToVal() const RecordValPtr IPv6_Hdr::ToVal() const
{ return ToVal(nullptr); } {
return ToVal(nullptr);
}
IPAddr IP_Hdr::IPHeaderSrcAddr() const IPAddr IP_Hdr::IPHeaderSrcAddr() const
{ {
@ -366,104 +381,106 @@ RecordValPtr IP_Hdr::ToPktHdrVal(RecordValPtr pkt_hdr, int sindex) const
const u_char* data = Payload(); const u_char* data = Payload();
int proto = NextProto(); int proto = NextProto();
switch ( proto ) { switch ( proto )
case IPPROTO_TCP:
{ {
const struct tcphdr* tp = (const struct tcphdr*) data; case IPPROTO_TCP:
auto tcp_hdr = make_intrusive<RecordVal>(tcp_hdr_type); {
const struct tcphdr* tp = (const struct tcphdr*)data;
auto tcp_hdr = make_intrusive<RecordVal>(tcp_hdr_type);
int tcp_hdr_len = tp->th_off * 4; int tcp_hdr_len = tp->th_off * 4;
int data_len = PayloadLen() - tcp_hdr_len; int data_len = PayloadLen() - tcp_hdr_len;
tcp_hdr->Assign(0, val_mgr->Port(ntohs(tp->th_sport), TRANSPORT_TCP)); tcp_hdr->Assign(0, val_mgr->Port(ntohs(tp->th_sport), TRANSPORT_TCP));
tcp_hdr->Assign(1, val_mgr->Port(ntohs(tp->th_dport), TRANSPORT_TCP)); tcp_hdr->Assign(1, val_mgr->Port(ntohs(tp->th_dport), TRANSPORT_TCP));
tcp_hdr->Assign(2, ntohl(tp->th_seq)); tcp_hdr->Assign(2, ntohl(tp->th_seq));
tcp_hdr->Assign(3, ntohl(tp->th_ack)); tcp_hdr->Assign(3, ntohl(tp->th_ack));
tcp_hdr->Assign(4, tcp_hdr_len); tcp_hdr->Assign(4, tcp_hdr_len);
tcp_hdr->Assign(5, data_len); tcp_hdr->Assign(5, data_len);
tcp_hdr->Assign(6, tp->th_x2); tcp_hdr->Assign(6, tp->th_x2);
tcp_hdr->Assign(7, tp->th_flags); tcp_hdr->Assign(7, tp->th_flags);
tcp_hdr->Assign(8, ntohs(tp->th_win)); tcp_hdr->Assign(8, ntohs(tp->th_win));
pkt_hdr->Assign(sindex + 2, std::move(tcp_hdr)); pkt_hdr->Assign(sindex + 2, std::move(tcp_hdr));
break; break;
}
case IPPROTO_UDP:
{
const struct udphdr* up = (const struct udphdr*)data;
auto udp_hdr = make_intrusive<RecordVal>(udp_hdr_type);
udp_hdr->Assign(0, val_mgr->Port(ntohs(up->uh_sport), TRANSPORT_UDP));
udp_hdr->Assign(1, val_mgr->Port(ntohs(up->uh_dport), TRANSPORT_UDP));
udp_hdr->Assign(2, ntohs(up->uh_ulen));
pkt_hdr->Assign(sindex + 3, std::move(udp_hdr));
break;
}
case IPPROTO_ICMP:
{
const struct icmp* icmpp = (const struct icmp*)data;
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
icmp_hdr->Assign(0, icmpp->icmp_type);
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
break;
}
case IPPROTO_ICMPV6:
{
const struct icmp6_hdr* icmpp = (const struct icmp6_hdr*)data;
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
icmp_hdr->Assign(0, icmpp->icmp6_type);
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
break;
}
default:
{
// This is not a protocol we understand.
break;
}
} }
case IPPROTO_UDP:
{
const struct udphdr* up = (const struct udphdr*) data;
auto udp_hdr = make_intrusive<RecordVal>(udp_hdr_type);
udp_hdr->Assign(0, val_mgr->Port(ntohs(up->uh_sport), TRANSPORT_UDP));
udp_hdr->Assign(1, val_mgr->Port(ntohs(up->uh_dport), TRANSPORT_UDP));
udp_hdr->Assign(2, ntohs(up->uh_ulen));
pkt_hdr->Assign(sindex + 3, std::move(udp_hdr));
break;
}
case IPPROTO_ICMP:
{
const struct icmp* icmpp = (const struct icmp *) data;
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
icmp_hdr->Assign(0, icmpp->icmp_type);
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
break;
}
case IPPROTO_ICMPV6:
{
const struct icmp6_hdr* icmpp = (const struct icmp6_hdr*) data;
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
icmp_hdr->Assign(0, icmpp->icmp6_type);
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
break;
}
default:
{
// This is not a protocol we understand.
break;
}
}
return pkt_hdr; return pkt_hdr;
} }
static inline bool isIPv6ExtHeader(uint8_t type) static inline bool isIPv6ExtHeader(uint8_t type)
{ {
switch (type) { switch ( type )
case IPPROTO_HOPOPTS: {
case IPPROTO_ROUTING: case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS: case IPPROTO_ROUTING:
case IPPROTO_FRAGMENT: case IPPROTO_DSTOPTS:
case IPPROTO_AH: case IPPROTO_FRAGMENT:
case IPPROTO_ESP: case IPPROTO_AH:
case IPPROTO_MOBILITY: case IPPROTO_ESP:
return true; case IPPROTO_MOBILITY:
default: return true;
return false; default:
} return false;
}
} }
IPv6_Hdr_Chain::~IPv6_Hdr_Chain() IPv6_Hdr_Chain::~IPv6_Hdr_Chain()
{ {
for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; for ( size_t i = 0; i < chain.size(); ++i )
delete chain[i];
delete homeAddr; delete homeAddr;
delete finalDst; delete finalDst;
} }
void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len, void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len, bool set_next, uint16_t next)
bool set_next, uint16_t next)
{ {
length = 0; length = 0;
uint8_t current_type, next_type; uint8_t current_type, next_type;
next_type = IPPROTO_IPV6; next_type = IPPROTO_IPV6;
const u_char* hdrs = (const u_char*) ip6; const u_char* hdrs = (const u_char*)ip6;
if ( total_len < (int)sizeof(struct ip6_hdr) ) if ( total_len < (int)sizeof(struct ip6_hdr) )
{ {
@ -501,20 +518,18 @@ void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len,
// Check for routing headers and remember final destination address. // Check for routing headers and remember final destination address.
if ( current_type == IPPROTO_ROUTING ) if ( current_type == IPPROTO_ROUTING )
ProcessRoutingHeader((const struct ip6_rthdr*) hdrs, cur_len); ProcessRoutingHeader((const struct ip6_rthdr*)hdrs, cur_len);
// Only Mobile IPv6 has a destination option we care about right now. // Only Mobile IPv6 has a destination option we care about right now.
if ( current_type == IPPROTO_DSTOPTS ) if ( current_type == IPPROTO_DSTOPTS )
ProcessDstOpts((const struct ip6_dest*) hdrs, cur_len); ProcessDstOpts((const struct ip6_dest*)hdrs, cur_len);
hdrs += cur_len; hdrs += cur_len;
length += cur_len; length += cur_len;
total_len -= cur_len; total_len -= cur_len;
} while ( current_type != IPPROTO_FRAGMENT && } while ( current_type != IPPROTO_FRAGMENT && current_type != IPPROTO_ESP &&
current_type != IPPROTO_ESP && current_type != IPPROTO_MOBILITY && isIPv6ExtHeader(next_type) );
current_type != IPPROTO_MOBILITY &&
isIPv6ExtHeader(next_type) );
} }
bool IPv6_Hdr_Chain::IsFragment() const bool IPv6_Hdr_Chain::IsFragment() const
@ -525,7 +540,7 @@ bool IPv6_Hdr_Chain::IsFragment() const
return false; return false;
} }
return chain[chain.size()-1]->Type() == IPPROTO_FRAGMENT; return chain[chain.size() - 1]->Type() == IPPROTO_FRAGMENT;
} }
IPAddr IPv6_Hdr_Chain::SrcAddr() const IPAddr IPv6_Hdr_Chain::SrcAddr() const
@ -567,39 +582,40 @@ void IPv6_Hdr_Chain::ProcessRoutingHeader(const struct ip6_rthdr* r, uint16_t le
// Last 16 bytes of header (for all known types) is the address we want. // Last 16 bytes of header (for all known types) is the address we want.
const in6_addr* addr = (const in6_addr*)(((const u_char*)r) + len - 16); const in6_addr* addr = (const in6_addr*)(((const u_char*)r) + len - 16);
switch ( r->ip6r_type ) { switch ( r->ip6r_type )
case 0: // Defined by RFC 2460, deprecated by RFC 5095
{ {
if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 ) case 0: // Defined by RFC 2460, deprecated by RFC 5095
{ {
if ( r->ip6r_len % 2 == 0 ) if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 )
finalDst = new IPAddr(*addr); {
else if ( r->ip6r_len % 2 == 0 )
reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len"); finalDst = new IPAddr(*addr);
} else
reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len");
}
// Always raise a weird since this type is deprecated. // Always raise a weird since this type is deprecated.
reporter->Weird(SrcAddr(), DstAddr(), "routing0_hdr"); reporter->Weird(SrcAddr(), DstAddr(), "routing0_hdr");
}
break;
case 2: // Defined by Mobile IPv6 RFC 6275.
{
if ( r->ip6r_segleft > 0 )
{
if ( r->ip6r_len == 2 )
finalDst = new IPAddr(*addr);
else
reporter->Weird(SrcAddr(), DstAddr(), "bad_routing2_len");
}
}
break;
default:
reporter->Weird(SrcAddr(), DstAddr(), "unknown_routing_type",
util::fmt("%d", r->ip6r_type));
break;
} }
break;
case 2: // Defined by Mobile IPv6 RFC 6275.
{
if ( r->ip6r_segleft > 0 )
{
if ( r->ip6r_len == 2 )
finalDst = new IPAddr(*addr);
else
reporter->Weird(SrcAddr(), DstAddr(), "bad_routing2_len");
}
}
break;
default:
reporter->Weird(SrcAddr(), DstAddr(), "unknown_routing_type",
util::fmt("%d", r->ip6r_type));
break;
}
} }
void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16_t len) void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16_t len)
@ -610,53 +626,56 @@ void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16_t len)
// https://datatracker.ietf.org/doc/html/rfc8200#section-4.6 // https://datatracker.ietf.org/doc/html/rfc8200#section-4.6
assert(len >= 2); assert(len >= 2);
const u_char* data = (const u_char*) d; const u_char* data = (const u_char*)d;
len -= 2 * sizeof(uint8_t); len -= 2 * sizeof(uint8_t);
data += 2* sizeof(uint8_t); data += 2 * sizeof(uint8_t);
while ( len > 0 ) while ( len > 0 )
{ {
const struct ip6_opt* opt = (const struct ip6_opt*) data; const struct ip6_opt* opt = (const struct ip6_opt*)data;
switch ( opt->ip6o_type ) { switch ( opt->ip6o_type )
case 0:
// If option type is zero, it's a Pad0 and can be just a single
// byte in width. Skip over it.
data += sizeof(uint8_t);
len -= sizeof(uint8_t);
break;
default:
{ {
// Double-check that the len can hold the whole option structure. case 0:
// Otherwise we get a buffer-overflow when we check the option_len. // If option type is zero, it's a Pad0 and can be just a single
// Also check that it holds everything for the option itself. // byte in width. Skip over it.
if ( len < sizeof(struct ip6_opt) || data += sizeof(uint8_t);
len < sizeof(struct ip6_opt) + opt->ip6o_len ) len -= sizeof(uint8_t);
{
reporter->Weird(SrcAddr(), DstAddr(), "bad_ipv6_dest_opt_len");
len = 0;
break; break;
} default:
if ( opt->ip6o_type == 201 ) // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
{
if ( opt->ip6o_len == sizeof(struct in6_addr) )
{ {
if ( homeAddr ) // Double-check that the len can hold the whole option structure.
reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts"); // Otherwise we get a buffer-overflow when we check the option_len.
else // Also check that it holds everything for the option itself.
homeAddr = new IPAddr(*((const in6_addr*)(data + sizeof(struct ip6_opt)))); if ( len < sizeof(struct ip6_opt) ||
} len < sizeof(struct ip6_opt) + opt->ip6o_len )
else {
reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len"); reporter->Weird(SrcAddr(), DstAddr(), "bad_ipv6_dest_opt_len");
} len = 0;
break;
}
data += sizeof(struct ip6_opt) + opt->ip6o_len; if ( opt->ip6o_type ==
len -= sizeof(struct ip6_opt) + opt->ip6o_len; 201 ) // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
{
if ( opt->ip6o_len == sizeof(struct in6_addr) )
{
if ( homeAddr )
reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts");
else
homeAddr =
new IPAddr(*((const in6_addr*)(data + sizeof(struct ip6_opt))));
}
else
reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len");
}
data += sizeof(struct ip6_opt) + opt->ip6o_len;
len -= sizeof(struct ip6_opt) + opt->ip6o_len;
}
break;
} }
break;
} }
} }
}
VectorValPtr IPv6_Hdr_Chain::ToVal() const VectorValPtr IPv6_Hdr_Chain::ToVal() const
{ {
@ -677,32 +696,33 @@ VectorValPtr IPv6_Hdr_Chain::ToVal() const
uint8_t type = chain[i]->Type(); uint8_t type = chain[i]->Type();
ext_hdr->Assign(0, type); ext_hdr->Assign(0, type);
switch (type) { switch ( type )
case IPPROTO_HOPOPTS: {
ext_hdr->Assign(1, std::move(v)); case IPPROTO_HOPOPTS:
break; ext_hdr->Assign(1, std::move(v));
case IPPROTO_DSTOPTS: break;
ext_hdr->Assign(2, std::move(v)); case IPPROTO_DSTOPTS:
break; ext_hdr->Assign(2, std::move(v));
case IPPROTO_ROUTING: break;
ext_hdr->Assign(3, std::move(v)); case IPPROTO_ROUTING:
break; ext_hdr->Assign(3, std::move(v));
case IPPROTO_FRAGMENT: break;
ext_hdr->Assign(4, std::move(v)); case IPPROTO_FRAGMENT:
break; ext_hdr->Assign(4, std::move(v));
case IPPROTO_AH: break;
ext_hdr->Assign(5, std::move(v)); case IPPROTO_AH:
break; ext_hdr->Assign(5, std::move(v));
case IPPROTO_ESP: break;
ext_hdr->Assign(6, std::move(v)); case IPPROTO_ESP:
break; ext_hdr->Assign(6, std::move(v));
case IPPROTO_MOBILITY: break;
ext_hdr->Assign(7, std::move(v)); case IPPROTO_MOBILITY:
break; ext_hdr->Assign(7, std::move(v));
default: break;
reporter->InternalWarning("IPv6_Hdr_Chain bad header %d", type); default:
continue; reporter->InternalWarning("IPv6_Hdr_Chain bad header %d", type);
} continue;
}
rval->Assign(rval->Size(), std::move(ext_hdr)); rval->Assign(rval->Size(), std::move(ext_hdr));
} }
@ -717,7 +737,7 @@ IP_Hdr* IP_Hdr::Copy() const
if ( ip4 ) if ( ip4 )
{ {
memcpy(new_hdr, ip4, HdrLen()); memcpy(new_hdr, ip4, HdrLen());
return new IP_Hdr((const struct ip*) new_hdr, true); return new IP_Hdr((const struct ip*)new_hdr, true);
} }
memcpy(new_hdr, ip6, HdrLen()); memcpy(new_hdr, ip6, HdrLen());
@ -756,4 +776,4 @@ IPv6_Hdr_Chain* IPv6_Hdr_Chain::Copy(const ip6_hdr* new_hdr) const
return rval; return rval;
} }
} // namespace zeek } // namespace zeek

225
src/IP.h
View file

@ -2,11 +2,11 @@
#pragma once #pragma once
#include "zeek/zeek-config.h"
#include <sys/types.h> // for u_char
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/ip.h> #include <netinet/ip.h>
#include <sys/types.h> // for u_char
#include "zeek/zeek-config.h"
#ifdef HAVE_NETINET_IP6_H #ifdef HAVE_NETINET_IP6_H
#include <netinet/ip6.h> #include <netinet/ip6.h>
@ -16,7 +16,8 @@
#include "zeek/IntrusivePtr.h" #include "zeek/IntrusivePtr.h"
namespace zeek { namespace zeek
{
class IPAddr; class IPAddr;
class RecordVal; class RecordVal;
@ -24,54 +25,60 @@ class VectorVal;
using RecordValPtr = IntrusivePtr<RecordVal>; using RecordValPtr = IntrusivePtr<RecordVal>;
using VectorValPtr = IntrusivePtr<VectorVal>; using VectorValPtr = IntrusivePtr<VectorVal>;
namespace detail { class FragReassembler; } namespace detail
{
class FragReassembler;
}
#ifndef IPPROTO_MOBILITY #ifndef IPPROTO_MOBILITY
#define IPPROTO_MOBILITY 135 #define IPPROTO_MOBILITY 135
#endif #endif
struct ip6_mobility { struct ip6_mobility
{
uint8_t ip6mob_payload; uint8_t ip6mob_payload;
uint8_t ip6mob_len; uint8_t ip6mob_len;
uint8_t ip6mob_type; uint8_t ip6mob_type;
uint8_t ip6mob_rsv; uint8_t ip6mob_rsv;
uint16_t ip6mob_chksum; uint16_t ip6mob_chksum;
}; };
/** /**
* Base class for IPv6 header/extensions. * Base class for IPv6 header/extensions.
*/ */
class IPv6_Hdr { class IPv6_Hdr
{
public: public:
/** /**
* Construct an IPv6 header or extension header from assigned type number. * Construct an IPv6 header or extension header from assigned type number.
*/ */
IPv6_Hdr(uint8_t t, const u_char* d) : type(t), data(d) {} IPv6_Hdr(uint8_t t, const u_char* d) : type(t), data(d) { }
/** /**
* Replace the value of the next protocol field. * Replace the value of the next protocol field.
*/ */
void ChangeNext(uint8_t next_type) void ChangeNext(uint8_t next_type)
{ {
switch ( type ) { switch ( type )
case IPPROTO_IPV6: {
((ip6_hdr*)data)->ip6_nxt = next_type; case IPPROTO_IPV6:
break; ((ip6_hdr*)data)->ip6_nxt = next_type;
case IPPROTO_HOPOPTS: break;
case IPPROTO_DSTOPTS: case IPPROTO_HOPOPTS:
case IPPROTO_ROUTING: case IPPROTO_DSTOPTS:
case IPPROTO_FRAGMENT: case IPPROTO_ROUTING:
case IPPROTO_AH: case IPPROTO_FRAGMENT:
case IPPROTO_MOBILITY: case IPPROTO_AH:
((ip6_ext*)data)->ip6e_nxt = next_type; case IPPROTO_MOBILITY:
break; ((ip6_ext*)data)->ip6e_nxt = next_type;
case IPPROTO_ESP: break;
default: case IPPROTO_ESP:
break; default:
} break;
}
} }
~IPv6_Hdr() {} ~IPv6_Hdr() { }
/** /**
* Returns the assigned IPv6 extension header type number of the header * Returns the assigned IPv6 extension header type number of the header
@ -79,20 +86,21 @@ public:
*/ */
uint8_t NextHdr() const uint8_t NextHdr() const
{ {
switch ( type ) { switch ( type )
case IPPROTO_IPV6: {
return ((ip6_hdr*)data)->ip6_nxt; case IPPROTO_IPV6:
case IPPROTO_HOPOPTS: return ((ip6_hdr*)data)->ip6_nxt;
case IPPROTO_DSTOPTS: case IPPROTO_HOPOPTS:
case IPPROTO_ROUTING: case IPPROTO_DSTOPTS:
case IPPROTO_FRAGMENT: case IPPROTO_ROUTING:
case IPPROTO_AH: case IPPROTO_FRAGMENT:
case IPPROTO_MOBILITY: case IPPROTO_AH:
return ((ip6_ext*)data)->ip6e_nxt; case IPPROTO_MOBILITY:
case IPPROTO_ESP: return ((ip6_ext*)data)->ip6e_nxt;
default: case IPPROTO_ESP:
return IPPROTO_NONE; default:
} return IPPROTO_NONE;
}
} }
/** /**
@ -100,23 +108,24 @@ public:
*/ */
uint16_t Length() const uint16_t Length() const
{ {
switch ( type ) { switch ( type )
case IPPROTO_IPV6: {
return 40; case IPPROTO_IPV6:
case IPPROTO_HOPOPTS: return 40;
case IPPROTO_DSTOPTS: case IPPROTO_HOPOPTS:
case IPPROTO_ROUTING: case IPPROTO_DSTOPTS:
case IPPROTO_MOBILITY: case IPPROTO_ROUTING:
return 8 + 8 * ((ip6_ext*)data)->ip6e_len; case IPPROTO_MOBILITY:
case IPPROTO_FRAGMENT: return 8 + 8 * ((ip6_ext*)data)->ip6e_len;
return 8; case IPPROTO_FRAGMENT:
case IPPROTO_AH: return 8;
return 8 + 4 * ((ip6_ext*)data)->ip6e_len; case IPPROTO_AH:
case IPPROTO_ESP: return 8 + 4 * ((ip6_ext*)data)->ip6e_len;
return 8; //encrypted payload begins after 8 bytes case IPPROTO_ESP:
default: return 8; // encrypted payload begins after 8 bytes
return 0; default:
} return 0;
}
} }
/** /**
@ -138,15 +147,15 @@ public:
protected: protected:
uint8_t type; uint8_t type;
const u_char* data; const u_char* data;
}; };
class IPv6_Hdr_Chain { class IPv6_Hdr_Chain
{
public: public:
/** /**
* Initializes the header chain from an IPv6 header structure. * Initializes the header chain from an IPv6 header structure.
*/ */
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, int len) IPv6_Hdr_Chain(const struct ip6_hdr* ip6, int len) { Init(ip6, len, false); }
{ Init(ip6, len, false); }
~IPv6_Hdr_Chain(); ~IPv6_Hdr_Chain();
@ -180,29 +189,28 @@ public:
* Returns pointer to fragment header structure if the chain contains one. * Returns pointer to fragment header structure if the chain contains one.
*/ */
const struct ip6_frag* GetFragHdr() const const struct ip6_frag* GetFragHdr() const
{ return IsFragment() ? {
(const struct ip6_frag*)chain[chain.size()-1]->Data(): nullptr; } return IsFragment() ? (const struct ip6_frag*)chain[chain.size() - 1]->Data() : nullptr;
}
/** /**
* If the header chain is a fragment, returns the offset in number of bytes * If the header chain is a fragment, returns the offset in number of bytes
* relative to the start of the Fragmentable Part of the original packet. * relative to the start of the Fragmentable Part of the original packet.
*/ */
uint16_t FragOffset() const uint16_t FragOffset() const
{ return IsFragment() ? {
(ntohs(GetFragHdr()->ip6f_offlg) & 0xfff8) : 0; } return IsFragment() ? (ntohs(GetFragHdr()->ip6f_offlg) & 0xfff8) : 0;
}
/** /**
* If the header chain is a fragment, returns the identification field. * If the header chain is a fragment, returns the identification field.
*/ */
uint32_t ID() const uint32_t ID() const { return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; }
{ return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; }
/** /**
* If the header chain is a fragment, returns the M (more fragments) flag. * If the header chain is a fragment, returns the M (more fragments) flag.
*/ */
int MF() const int MF() const { return IsFragment() ? (ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
{ return IsFragment() ?
(ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
/** /**
* If the chain contains a Destination Options header with a Home Address * If the chain contains a Destination Options header with a Home Address
@ -236,15 +244,16 @@ protected:
* the first next protocol pointer field that points to a fragment header. * the first next protocol pointer field that points to a fragment header.
*/ */
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16_t next, int len) IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16_t next, int len)
{ Init(ip6, len, true, next); } {
Init(ip6, len, true, next);
}
/** /**
* Initializes the header chain from an IPv6 header structure of a given * Initializes the header chain from an IPv6 header structure of a given
* length, possibly setting the first next protocol pointer field that * length, possibly setting the first next protocol pointer field that
* points to a fragment header. * points to a fragment header.
*/ */
void Init(const struct ip6_hdr* ip6, int total_len, bool set_next, void Init(const struct ip6_hdr* ip6, int total_len, bool set_next, uint16_t next = 0);
uint16_t next = 0);
/** /**
* Process a routing header and allocate/remember the final destination * Process a routing header and allocate/remember the final destination
@ -275,13 +284,14 @@ protected:
* non-zero segments left. * non-zero segments left.
*/ */
IPAddr* finalDst = nullptr; IPAddr* finalDst = nullptr;
}; };
/** /**
* A class that wraps either an IPv4 or IPv6 packet and abstracts methods * A class that wraps either an IPv4 or IPv6 packet and abstracts methods
* for inquiring about common features between the two. * for inquiring about common features between the two.
*/ */
class IP_Hdr { class IP_Hdr
{
public: public:
/** /**
* Construct the header wrapper from an IPv4 packet. Caller must have * Construct the header wrapper from an IPv4 packet. Caller must have
@ -290,7 +300,7 @@ public:
* @param arg_del whether to take ownership of \a arg_ip4 pointer's memory. * @param arg_del whether to take ownership of \a arg_ip4 pointer's memory.
* @param reassembled whether this header is for a reassembled packet. * @param reassembled whether this header is for a reassembled packet.
*/ */
IP_Hdr(const struct ip* arg_ip4, bool arg_del, bool reassembled=false) IP_Hdr(const struct ip* arg_ip4, bool arg_del, bool reassembled = false)
: ip4(arg_ip4), del(arg_del), reassembled(reassembled) : ip4(arg_ip4), del(arg_del), reassembled(reassembled)
{ {
} }
@ -307,10 +317,10 @@ public:
* @param c an already-constructed header chain to take ownership of. * @param c an already-constructed header chain to take ownership of.
* @param reassembled whether this header is for a reassembled packet. * @param reassembled whether this header is for a reassembled packet.
*/ */
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len, IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len, const IPv6_Hdr_Chain* c = nullptr,
const IPv6_Hdr_Chain* c = nullptr, bool reassembled=false) bool reassembled = false)
: ip6(arg_ip6), ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len)), : ip6(arg_ip6), ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len)), del(arg_del),
del(arg_del), reassembled(reassembled) reassembled(reassembled)
{ {
} }
@ -330,20 +340,20 @@ public:
if ( del ) if ( del )
{ {
delete [] (struct ip*) ip4; delete[](struct ip*) ip4;
delete [] (struct ip6_hdr*) ip6; delete[](struct ip6_hdr*) ip6;
} }
} }
/** /**
* If an IPv4 packet is wrapped, return a pointer to it, else null. * If an IPv4 packet is wrapped, return a pointer to it, else null.
*/ */
const struct ip* IP4_Hdr() const { return ip4; } const struct ip* IP4_Hdr() const { return ip4; }
/** /**
* If an IPv6 packet is wrapped, return a pointer to it, else null. * If an IPv6 packet is wrapped, return a pointer to it, else null.
*/ */
const struct ip6_hdr* IP6_Hdr() const { return ip6; } const struct ip6_hdr* IP6_Hdr() const { return ip6; }
/** /**
* Returns the source address held in the IP header. * Returns the source address held in the IP header.
@ -377,9 +387,9 @@ public:
const u_char* Payload() const const u_char* Payload() const
{ {
if ( ip4 ) if ( ip4 )
return ((const u_char*) ip4) + ip4->ip_hl * 4; return ((const u_char*)ip4) + ip4->ip_hl * 4;
return ((const u_char*) ip6) + ip6_hdrs->TotalLength(); return ((const u_char*)ip6) + ip6_hdrs->TotalLength();
} }
/** /**
@ -390,10 +400,10 @@ public:
{ {
if ( ip4 ) if ( ip4 )
return nullptr; return nullptr;
else if ( (*ip6_hdrs)[ip6_hdrs->Size()-1]->Type() != IPPROTO_MOBILITY ) else if ( (*ip6_hdrs)[ip6_hdrs->Size() - 1]->Type() != IPPROTO_MOBILITY )
return nullptr; return nullptr;
else else
return (const ip6_mobility*)(*ip6_hdrs)[ip6_hdrs->Size()-1]->Data(); return (const ip6_mobility*)(*ip6_hdrs)[ip6_hdrs->Size() - 1]->Data();
} }
/** /**
@ -422,8 +432,7 @@ public:
/** /**
* Returns length of IP packet header (includes extension headers for IPv6). * Returns length of IP packet header (includes extension headers for IPv6).
*/ */
uint16_t HdrLen() const uint16_t HdrLen() const { return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); }
{ return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); }
/** /**
* For IPv6 header chains, returns the type of the last header in the chain. * For IPv6 header chains, returns the type of the last header in the chain.
@ -435,7 +444,7 @@ public:
size_t i = ip6_hdrs->Size(); size_t i = ip6_hdrs->Size();
if ( i > 0 ) if ( i > 0 )
return (*ip6_hdrs)[i-1]->Type(); return (*ip6_hdrs)[i - 1]->Type();
return IPPROTO_NONE; return IPPROTO_NONE;
} }
@ -452,7 +461,7 @@ public:
size_t i = ip6_hdrs->Size(); size_t i = ip6_hdrs->Size();
if ( i > 0 ) if ( i > 0 )
return (*ip6_hdrs)[i-1]->NextHdr(); return (*ip6_hdrs)[i - 1]->NextHdr();
return IPPROTO_NONE; return IPPROTO_NONE;
} }
@ -460,54 +469,50 @@ public:
/** /**
* Returns the IPv4 Time to Live or IPv6 Hop Limit field. * Returns the IPv4 Time to Live or IPv6 Hop Limit field.
*/ */
unsigned char TTL() const unsigned char TTL() const { return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
{ return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
/** /**
* Returns whether the IP header indicates this packet is a fragment. * Returns whether the IP header indicates this packet is a fragment.
*/ */
bool IsFragment() const bool IsFragment() const
{ return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : {
ip6_hdrs->IsFragment(); } return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : ip6_hdrs->IsFragment();
}
/** /**
* Returns the fragment packet's offset in relation to the original * Returns the fragment packet's offset in relation to the original
* packet in bytes. * packet in bytes.
*/ */
uint16_t FragOffset() const uint16_t FragOffset() const
{ return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : {
ip6_hdrs->FragOffset(); } return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : ip6_hdrs->FragOffset();
}
/** /**
* Returns the fragment packet's identification field. * Returns the fragment packet's identification field.
*/ */
uint32_t ID() const uint32_t ID() const { return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); }
{ return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); }
/** /**
* Returns whether a fragment packet's "More Fragments" field is set. * Returns whether a fragment packet's "More Fragments" field is set.
*/ */
int MF() const int MF() const { return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); }
{ return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); }
/** /**
* Returns whether a fragment packet's "Don't Fragment" field is set. * Returns whether a fragment packet's "Don't Fragment" field is set.
* Note that IPv6 has no such field. * Note that IPv6 has no such field.
*/ */
int DF() const int DF() const { return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; }
{ return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; }
/** /**
* Returns value of an IPv6 header's flow label field or 0 if it's IPv4. * Returns value of an IPv6 header's flow label field or 0 if it's IPv4.
*/ */
uint32_t FlowLabel() const uint32_t FlowLabel() const { return ip4 ? 0 : (ntohl(ip6->ip6_flow) & 0x000fffff); }
{ return ip4 ? 0 : (ntohl(ip6->ip6_flow) & 0x000fffff); }
/** /**
* Returns number of IP headers in packet (includes IPv6 extension headers). * Returns number of IP headers in packet (includes IPv6 extension headers).
*/ */
size_t NumHeaders() const size_t NumHeaders() const { return ip4 ? 1 : ip6_hdrs->Size(); }
{ return ip4 ? 1 : ip6_hdrs->Size(); }
/** /**
* Returns an ip_hdr or ip6_hdr_chain RecordVal. * Returns an ip_hdr or ip6_hdr_chain RecordVal.
@ -534,6 +539,6 @@ private:
const IPv6_Hdr_Chain* ip6_hdrs = nullptr; const IPv6_Hdr_Chain* ip6_hdrs = nullptr;
bool del = false; bool del = false;
bool reassembled = false; bool reassembled = false;
}; };
} // namespace zeek } // namespace zeek

View file

@ -1,34 +1,35 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/IPAddr.h"
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
#include <vector> #include <vector>
#include "zeek/IPAddr.h"
#include "zeek/Reporter.h"
#include "zeek/ZeekString.h"
#include "zeek/Conn.h" #include "zeek/Conn.h"
#include "zeek/Hash.h" #include "zeek/Hash.h"
#include "zeek/bro_inet_ntop.h" #include "zeek/Reporter.h"
#include "zeek/ZeekString.h"
#include "zeek/analyzer/Manager.h" #include "zeek/analyzer/Manager.h"
#include "zeek/bro_inet_ntop.h"
namespace zeek { namespace zeek
{
const IPAddr IPAddr::v4_unspecified = IPAddr(in4_addr{}); const IPAddr IPAddr::v4_unspecified = IPAddr(in4_addr{});
const IPAddr IPAddr::v6_unspecified = IPAddr(); const IPAddr IPAddr::v6_unspecified = IPAddr();
namespace detail { namespace detail
{
ConnKey::ConnKey(const IPAddr& src, const IPAddr& dst, uint16_t src_port, ConnKey::ConnKey(const IPAddr& src, const IPAddr& dst, uint16_t src_port, uint16_t dst_port,
uint16_t dst_port, TransportProto t, bool one_way) TransportProto t, bool one_way)
: transport(t) : transport(t)
{ {
// Lookup up connection based on canonical ordering, which is // Lookup up connection based on canonical ordering, which is
// the smaller of <src addr, src port> and <dst addr, dst port> // the smaller of <src addr, src port> and <dst addr, dst port>
// followed by the other. // followed by the other.
if ( one_way || if ( one_way || addr_port_canon_lt(src, src_port, dst, dst_port) )
addr_port_canon_lt(src, src_port, dst, dst_port)
)
{ {
ip1 = src.in6; ip1 = src.in6;
ip2 = dst.in6; ip2 = dst.in6;
@ -45,8 +46,7 @@ ConnKey::ConnKey(const IPAddr& src, const IPAddr& dst, uint16_t src_port,
} }
ConnKey::ConnKey(const ConnTuple& id) ConnKey::ConnKey(const ConnTuple& id)
: ConnKey(id.src_addr, id.dst_addr, id.src_port, id.dst_port, : ConnKey(id.src_addr, id.dst_addr, id.src_port, id.dst_port, id.proto, id.is_one_way)
id.proto, id.is_one_way)
{ {
} }
@ -64,7 +64,7 @@ ConnKey& ConnKey::operator=(const ConnKey& rhs)
return *this; return *this;
} }
} // namespace detail } // namespace detail
IPAddr::IPAddr(const String& s) IPAddr::IPAddr(const String& s)
{ {
@ -81,7 +81,7 @@ static inline uint32_t bit_mask32(int bottom_bits)
if ( bottom_bits >= 32 ) if ( bottom_bits >= 32 )
return 0xffffffff; return 0xffffffff;
return (((uint32_t) 1) << bottom_bits) - 1; return (((uint32_t)1) << bottom_bits) - 1;
} }
void IPAddr::Mask(int top_bits_to_keep) void IPAddr::Mask(int top_bits_to_keep)
@ -92,12 +92,11 @@ void IPAddr::Mask(int top_bits_to_keep)
return; return;
} }
uint32_t mask_bits[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }; uint32_t mask_bits[4] = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
std::ldiv_t res = std::ldiv(top_bits_to_keep, 32); std::ldiv_t res = std::ldiv(top_bits_to_keep, 32);
if ( res.quot < 4 ) if ( res.quot < 4 )
mask_bits[res.quot] = mask_bits[res.quot] = htonl(mask_bits[res.quot] & ~bit_mask32(32 - res.rem));
htonl(mask_bits[res.quot] & ~bit_mask32(32 - res.rem));
for ( unsigned int i = res.quot + 1; i < 4; ++i ) for ( unsigned int i = res.quot + 1; i < 4; ++i )
mask_bits[i] = 0; mask_bits[i] = 0;
@ -116,7 +115,7 @@ void IPAddr::ReverseMask(int top_bits_to_chop)
return; return;
} }
uint32_t mask_bits[4] = { 0, 0, 0, 0 }; uint32_t mask_bits[4] = {0, 0, 0, 0};
std::ldiv_t res = std::ldiv(top_bits_to_chop, 32); std::ldiv_t res = std::ldiv(top_bits_to_chop, 32);
if ( res.quot < 4 ) if ( res.quot < 4 )
@ -144,7 +143,7 @@ bool IPAddr::ConvertString(const char* s, in6_addr* result)
// that can't e.g. handle leading zeroes. // that can't e.g. handle leading zeroes.
int a[4]; int a[4];
int n = 0; int n = 0;
int match_count = sscanf(s, "%d.%d.%d.%d%n", a+0, a+1, a+2, a+3, &n); int match_count = sscanf(s, "%d.%d.%d.%d%n", a + 0, a + 1, a + 2, a + 3, &n);
if ( match_count != 4 ) if ( match_count != 4 )
return false; return false;
@ -200,15 +199,14 @@ std::string IPAddr::AsHexString() const
if ( GetFamily() == IPv4 ) if ( GetFamily() == IPv4 )
{ {
uint32_t* p = (uint32_t*) &in6.s6_addr[12]; uint32_t* p = (uint32_t*)&in6.s6_addr[12];
snprintf(buf, sizeof(buf), "%08x", (uint32_t) ntohl(*p)); snprintf(buf, sizeof(buf), "%08x", (uint32_t)ntohl(*p));
} }
else else
{ {
uint32_t* p = (uint32_t*) in6.s6_addr; uint32_t* p = (uint32_t*)in6.s6_addr;
snprintf(buf, sizeof(buf), "%08x%08x%08x%08x", snprintf(buf, sizeof(buf), "%08x%08x%08x%08x", (uint32_t)ntohl(p[0]), (uint32_t)ntohl(p[1]),
(uint32_t) ntohl(p[0]), (uint32_t) ntohl(p[1]), (uint32_t)ntohl(p[2]), (uint32_t)ntohl(p[3]));
(uint32_t) ntohl(p[2]), (uint32_t) ntohl(p[3]));
} }
return buf; return buf;
@ -219,7 +217,7 @@ std::string IPAddr::PtrName() const
if ( GetFamily() == IPv4 ) if ( GetFamily() == IPv4 )
{ {
char buf[256]; char buf[256];
uint32_t* p = (uint32_t*) &in6.s6_addr[12]; uint32_t* p = (uint32_t*)&in6.s6_addr[12];
uint32_t a = ntohl(*p); uint32_t a = ntohl(*p);
uint32_t a3 = (a >> 24) & 0xff; uint32_t a3 = (a >> 24) & 0xff;
uint32_t a2 = (a >> 16) & 0xff; uint32_t a2 = (a >> 16) & 0xff;
@ -232,15 +230,15 @@ std::string IPAddr::PtrName() const
{ {
static const char hex_digit[] = "0123456789abcdef"; static const char hex_digit[] = "0123456789abcdef";
std::string ptr_name("ip6.arpa"); std::string ptr_name("ip6.arpa");
uint32_t* p = (uint32_t*) in6.s6_addr; uint32_t* p = (uint32_t*)in6.s6_addr;
for ( unsigned int i = 0; i < 4; ++i ) for ( unsigned int i = 0; i < 4; ++i )
{ {
uint32_t a = ntohl(p[i]); uint32_t a = ntohl(p[i]);
for ( unsigned int j = 1; j <=8; ++j ) for ( unsigned int j = 1; j <= 8; ++j )
{ {
ptr_name.insert(0, 1, '.'); ptr_name.insert(0, 1, '.');
ptr_name.insert(0, 1, hex_digit[(a >> (32-j*4)) & 0x0f]); ptr_name.insert(0, 1, hex_digit[(a >> (32 - j * 4)) & 0x0f]);
} }
} }
@ -248,8 +246,7 @@ std::string IPAddr::PtrName() const
} }
} }
IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length) IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length) : prefix(in4), length(96 + length)
: prefix(in4), length(96 + length)
{ {
if ( length > 32 ) if ( length > 32 )
{ {
@ -260,8 +257,7 @@ IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length)
prefix.Mask(this->length); prefix.Mask(this->length);
} }
IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length) IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length) : prefix(in6), length(length)
: prefix(in6), length(length)
{ {
if ( length > 128 ) if ( length > 128 )
{ {
@ -289,8 +285,7 @@ bool IPAddr::CheckPrefixLength(uint8_t length, bool len_is_v6_relative) const
return true; return true;
} }
IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length, bool len_is_v6_relative) IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length, bool len_is_v6_relative) : prefix(addr)
: prefix(addr)
{ {
if ( prefix.CheckPrefixLength(length, len_is_v6_relative) ) if ( prefix.CheckPrefixLength(length, len_is_v6_relative) )
{ {
@ -318,15 +313,16 @@ std::string IPPrefix::AsString() const
else else
modp_uitoa10(length, l); modp_uitoa10(length, l);
return prefix.AsString() +"/" + l; return prefix.AsString() + "/" + l;
} }
std::unique_ptr<detail::HashKey> IPPrefix::MakeHashKey() const std::unique_ptr<detail::HashKey> IPPrefix::MakeHashKey() const
{ {
struct { struct
{
in6_addr ip; in6_addr ip;
uint32_t len; uint32_t len;
} key; } key;
key.ip = prefix.in6; key.ip = prefix.in6;
key.len = Length(); key.len = Length();
@ -359,4 +355,4 @@ bool IPPrefix::ConvertString(const char* text, IPPrefix* result)
return true; return true;
} }
} // namespace zeek } // namespace zeek

View file

@ -2,36 +2,39 @@
#pragma once #pragma once
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h>
#include <cstring> #include <cstring>
#include <string>
#include <memory> #include <memory>
#include <string>
#include "zeek/threading/SerialTypes.h" #include "zeek/threading/SerialTypes.h"
using in4_addr = in_addr; using in4_addr = in_addr;
namespace zeek { namespace zeek
{
class String; class String;
struct ConnTuple; struct ConnTuple;
namespace detail { namespace detail
{
class HashKey; class HashKey;
struct ConnKey { struct ConnKey
{
in6_addr ip1; in6_addr ip1;
in6_addr ip2; in6_addr ip2;
uint16_t port1; uint16_t port1;
uint16_t port2; uint16_t port2;
TransportProto transport; TransportProto transport;
ConnKey(const IPAddr& src, const IPAddr& dst, uint16_t src_port, ConnKey(const IPAddr& src, const IPAddr& dst, uint16_t src_port, uint16_t dst_port,
uint16_t dst_port, TransportProto t, bool one_way); TransportProto t, bool one_way);
ConnKey(const ConnTuple& conn); ConnKey(const ConnTuple& conn);
ConnKey(const ConnKey& rhs) { *this = rhs; } ConnKey(const ConnKey& rhs) { *this = rhs; }
bool operator<(const ConnKey& rhs) const { return memcmp(this, &rhs, sizeof(ConnKey)) < 0; } bool operator<(const ConnKey& rhs) const { return memcmp(this, &rhs, sizeof(ConnKey)) < 0; }
bool operator<=(const ConnKey& rhs) const { return memcmp(this, &rhs, sizeof(ConnKey)) <= 0; } bool operator<=(const ConnKey& rhs) const { return memcmp(this, &rhs, sizeof(ConnKey)) <= 0; }
@ -41,16 +44,17 @@ struct ConnKey {
bool operator>(const ConnKey& rhs) const { return memcmp(this, &rhs, sizeof(ConnKey)) > 0; } bool operator>(const ConnKey& rhs) const { return memcmp(this, &rhs, sizeof(ConnKey)) > 0; }
ConnKey& operator=(const ConnKey& rhs); ConnKey& operator=(const ConnKey& rhs);
}; };
using ConnIDKey [[deprecated("Remove in v5.1. Use zeek::detail::ConnKey.")]] = ConnKey; using ConnIDKey [[deprecated("Remove in v5.1. Use zeek::detail::ConnKey.")]] = ConnKey;
} // namespace detail } // namespace detail
/** /**
* Class storing both IPv4 and IPv6 addresses. * Class storing both IPv4 and IPv6 addresses.
*/ */
class IPAddr { class IPAddr
{
public: public:
/** /**
* Address family. * Address family.
@ -60,15 +64,16 @@ public:
/** /**
* Byte order. * Byte order.
*/ */
enum ByteOrder { Host, Network }; enum ByteOrder
{
Host,
Network
};
/** /**
* Constructs the unspecified IPv6 address (all 128 bits zeroed). * Constructs the unspecified IPv6 address (all 128 bits zeroed).
*/ */
IPAddr() IPAddr() { memset(in6.s6_addr, 0, sizeof(in6.s6_addr)); }
{
memset(in6.s6_addr, 0, sizeof(in6.s6_addr));
}
/** /**
* Constructs an address instance from an IPv4 address. * Constructs an address instance from an IPv4 address.
@ -94,10 +99,7 @@ public:
* @param s String containing an IP address as either a dotted IPv4 * @param s String containing an IP address as either a dotted IPv4
* address or a hex IPv6 address. * address or a hex IPv6 address.
*/ */
IPAddr(const std::string& s) IPAddr(const std::string& s) { Init(s.data()); }
{
Init(s.data());
}
/** /**
* Constructs an address instance from a string representation. * Constructs an address instance from a string representation.
@ -105,10 +107,7 @@ public:
* @param s ASCIIZ string containing an IP address as either a * @param s ASCIIZ string containing an IP address as either a
* dotted IPv4 address or a hex IPv6 address. * dotted IPv4 address or a hex IPv6 address.
*/ */
IPAddr(const char* s) IPAddr(const char* s) { Init(s); }
{
Init(s);
}
/** /**
* Constructs an address instance from a string representation. * Constructs an address instance from a string representation.
@ -135,7 +134,7 @@ public:
/** /**
* Copy constructor. * Copy constructor.
*/ */
IPAddr(const IPAddr& other) : in6(other.in6) { }; IPAddr(const IPAddr& other) : in6(other.in6){};
/** /**
* Destructor. * Destructor.
@ -175,8 +174,8 @@ public:
bool IsBroadcast() const bool IsBroadcast() const
{ {
if ( GetFamily() == IPv4 ) if ( GetFamily() == IPv4 )
return ((in6.s6_addr[12] == 0xff) && (in6.s6_addr[13] == 0xff) return ((in6.s6_addr[12] == 0xff) && (in6.s6_addr[13] == 0xff) &&
&& (in6.s6_addr[14] == 0xff) && (in6.s6_addr[15] == 0xff)); (in6.s6_addr[14] == 0xff) && (in6.s6_addr[15] == 0xff));
return false; return false;
} }
@ -197,12 +196,12 @@ public:
{ {
if ( GetFamily() == IPv4 ) if ( GetFamily() == IPv4 )
{ {
*bytes = (uint32_t*) &in6.s6_addr[12]; *bytes = (uint32_t*)&in6.s6_addr[12];
return 1; return 1;
} }
else else
{ {
*bytes = (uint32_t*) in6.s6_addr; *bytes = (uint32_t*)in6.s6_addr;
return 4; return 4;
} }
} }
@ -348,10 +347,7 @@ public:
return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) == 0; return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) == 0;
} }
friend bool operator!=(const IPAddr& addr1, const IPAddr& addr2) friend bool operator!=(const IPAddr& addr1, const IPAddr& addr2) { return ! (addr1 == addr2); }
{
return ! (addr1 == addr2);
}
/** /**
* Comparison operator IP addresses. This defines a well-defined order for * Comparison operator IP addresses. This defines a well-defined order for
@ -368,15 +364,9 @@ public:
return addr1 < addr2 || addr1 == addr2; return addr1 < addr2 || addr1 == addr2;
} }
friend bool operator>=(const IPAddr& addr1, const IPAddr& addr2) friend bool operator>=(const IPAddr& addr1, const IPAddr& addr2) { return ! (addr1 < addr2); }
{
return ! ( addr1 < addr2 );
}
friend bool operator>(const IPAddr& addr1, const IPAddr& addr2) friend bool operator>(const IPAddr& addr1, const IPAddr& addr2) { return ! (addr1 <= addr2); }
{
return ! ( addr1 <= addr2 );
}
/** /**
* Converts the address into the type used internally by the * Converts the address into the type used internally by the
@ -384,8 +374,12 @@ public:
*/ */
void ConvertToThreadingValue(threading::Value::addr_t* v) const; void ConvertToThreadingValue(threading::Value::addr_t* v) const;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const { return padded_sizeof(*this); } "GHI-572.")]] unsigned int
MemoryAllocation() const
{
return padded_sizeof(*this);
}
/** /**
* Check if an IP prefix length would be valid against this IP address. * Check if an IP prefix length would be valid against this IP address.
@ -450,10 +444,8 @@ private:
in6_addr in6; // IPv6 or v4-to-v6-mapped address in6_addr in6; // IPv6 or v4-to-v6-mapped address
// Top 96 bits of a v4-mapped-addr. // Top 96 bits of a v4-mapped-addr.
static constexpr uint8_t v4_mapped_prefix[12] = { 0, 0, 0, 0, static constexpr uint8_t v4_mapped_prefix[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
0, 0, 0, 0, };
0, 0, 0xff, 0xff };
};
inline IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order) inline IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order)
{ {
@ -464,7 +456,7 @@ inline IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order)
if ( order == Host ) if ( order == Host )
{ {
uint32_t* p = (uint32_t*) &in6.s6_addr[12]; uint32_t* p = (uint32_t*)&in6.s6_addr[12];
*p = htonl(*p); *p = htonl(*p);
} }
} }
@ -475,9 +467,9 @@ inline IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order)
if ( order == Host ) if ( order == Host )
{ {
for ( unsigned int i = 0; i < 4; ++ i) for ( unsigned int i = 0; i < 4; ++i )
{ {
uint32_t* p = (uint32_t*) &in6.s6_addr[i*4]; uint32_t* p = (uint32_t*)&in6.s6_addr[i * 4];
*p = htonl(*p); *p = htonl(*p);
} }
} }
@ -490,33 +482,32 @@ inline bool IPAddr::IsLoopback() const
return in6.s6_addr[12] == 127; return in6.s6_addr[12] == 127;
else else
return ((in6.s6_addr[0] == 0) && (in6.s6_addr[1] == 0) return ((in6.s6_addr[0] == 0) && (in6.s6_addr[1] == 0) && (in6.s6_addr[2] == 0) &&
&& (in6.s6_addr[2] == 0) && (in6.s6_addr[3] == 0) (in6.s6_addr[3] == 0) && (in6.s6_addr[4] == 0) && (in6.s6_addr[5] == 0) &&
&& (in6.s6_addr[4] == 0) && (in6.s6_addr[5] == 0) (in6.s6_addr[6] == 0) && (in6.s6_addr[7] == 0) && (in6.s6_addr[8] == 0) &&
&& (in6.s6_addr[6] == 0) && (in6.s6_addr[7] == 0) (in6.s6_addr[9] == 0) && (in6.s6_addr[10] == 0) && (in6.s6_addr[11] == 0) &&
&& (in6.s6_addr[8] == 0) && (in6.s6_addr[9] == 0) (in6.s6_addr[12] == 0) && (in6.s6_addr[13] == 0) && (in6.s6_addr[14] == 0) &&
&& (in6.s6_addr[10] == 0) && (in6.s6_addr[11] == 0) (in6.s6_addr[15] == 1));
&& (in6.s6_addr[12] == 0) && (in6.s6_addr[13] == 0)
&& (in6.s6_addr[14] == 0) && (in6.s6_addr[15] == 1));
} }
inline void IPAddr::ConvertToThreadingValue(threading::Value::addr_t* v) const inline void IPAddr::ConvertToThreadingValue(threading::Value::addr_t* v) const
{ {
v->family = GetFamily(); v->family = GetFamily();
switch ( v->family ) { switch ( v->family )
{
case IPv4: case IPv4:
CopyIPv4(&v->in.in4); CopyIPv4(&v->in.in4);
return; return;
case IPv6: case IPv6:
CopyIPv6(&v->in.in6); CopyIPv6(&v->in.in6);
return; return;
// Can't be reached. // Can't be reached.
abort(); abort();
} }
} }
/** /**
@ -524,9 +515,8 @@ inline void IPAddr::ConvertToThreadingValue(threading::Value::addr_t* v) const
* (i.e., \c 192.168.1.1/16 and \c FD00::/8. * (i.e., \c 192.168.1.1/16 and \c FD00::/8.
*/ */
class IPPrefix class IPPrefix
{ {
public: public:
/** /**
* Constructs a prefix 0/0. * Constructs a prefix 0/0.
*/ */
@ -565,14 +555,12 @@ public:
* \a length is expected to range from 0 to 128 even if \a addr is IPv4, * \a length is expected to range from 0 to 128 even if \a addr is IPv4,
* meaning that the mask is to apply to the IPv4-mapped-IPv6 representation. * meaning that the mask is to apply to the IPv4-mapped-IPv6 representation.
*/ */
IPPrefix(const IPAddr& addr, uint8_t length, IPPrefix(const IPAddr& addr, uint8_t length, bool len_is_v6_relative = false);
bool len_is_v6_relative = false);
/** /**
* Copy constructor. * Copy constructor.
*/ */
IPPrefix(const IPPrefix& other) IPPrefix(const IPPrefix& other) : prefix(other.prefix), length(other.length) { }
: prefix(other.prefix), length(other.length) { }
/** /**
* Destructor. * Destructor.
@ -589,10 +577,7 @@ public:
* Returns the bit length of the prefix, relative to the 32 bits * Returns the bit length of the prefix, relative to the 32 bits
* of an IPv4 prefix or relative to the 128 bits of an IPv6 prefix. * of an IPv4 prefix or relative to the 128 bits of an IPv6 prefix.
*/ */
uint8_t Length() const uint8_t Length() const { return prefix.GetFamily() == IPv4 ? length - 96 : length; }
{
return prefix.GetFamily() == IPv4 ? length - 96 : length;
}
/** /**
* Returns the bit length of the prefix always relative to a full * Returns the bit length of the prefix always relative to a full
@ -609,7 +594,7 @@ public:
{ {
IPAddr p(addr); IPAddr p(addr);
p.Mask(length); p.Mask(length);
return p == prefix; return p == prefix;
} }
/** /**
* Assignment operator. * Assignment operator.
@ -630,7 +615,7 @@ public:
*/ */
std::string AsString() const; std::string AsString() const;
operator std::string() const { return AsString(); } operator std::string() const { return AsString(); }
/** /**
* Returns a key that can be used to lookup the IP Prefix in a hash table. * Returns a key that can be used to lookup the IP Prefix in a hash table.
@ -647,8 +632,12 @@ public:
prefix.ConvertToThreadingValue(&v->prefix); prefix.ConvertToThreadingValue(&v->prefix);
} }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const { return padded_sizeof(*this); } "GHI-572.")]] unsigned int
MemoryAllocation() const
{
return padded_sizeof(*this);
}
/** /**
* Comparison operator for IP prefix. * Comparison operator for IP prefix.
@ -658,10 +647,7 @@ public:
return net1.Prefix() == net2.Prefix() && net1.Length() == net2.Length(); return net1.Prefix() == net2.Prefix() && net1.Length() == net2.Length();
} }
friend bool operator!=(const IPPrefix& net1, const IPPrefix& net2) friend bool operator!=(const IPPrefix& net1, const IPPrefix& net2) { return ! (net1 == net2); }
{
return ! (net1 == net2);
}
/** /**
* Comparison operator IP prefixes. This defines a well-defined order for * Comparison operator IP prefixes. This defines a well-defined order for
@ -685,15 +671,9 @@ public:
return net1 < net2 || net1 == net2; return net1 < net2 || net1 == net2;
} }
friend bool operator>=(const IPPrefix& net1, const IPPrefix& net2) friend bool operator>=(const IPPrefix& net1, const IPPrefix& net2) { return ! (net1 < net2); }
{
return ! (net1 < net2 );
}
friend bool operator>(const IPPrefix& net1, const IPPrefix& net2) friend bool operator>(const IPPrefix& net1, const IPPrefix& net2) { return ! (net1 <= net2); }
{
return ! ( net1 <= net2 );
}
/** /**
* Converts an IPv4 or IPv6 prefix string into a network address prefix structure. * Converts an IPv4 or IPv6 prefix string into a network address prefix structure.
@ -718,8 +698,8 @@ public:
} }
private: private:
IPAddr prefix; // We store it as an address with the non-prefix bits masked out via Mask(). IPAddr prefix; // We store it as an address with the non-prefix bits masked out via Mask().
uint8_t length = 0; // The bit length of the prefix relative to full IPv6 addr. uint8_t length = 0; // The bit length of the prefix relative to full IPv6 addr.
}; };
} // namespace zeek } // namespace zeek

View file

@ -1,12 +1,14 @@
#include "zeek/zeek-config.h"
#include "zeek/IntSet.h" #include "zeek/IntSet.h"
#include "zeek/zeek-config.h"
#ifdef HAVE_MEMORY_H #ifdef HAVE_MEMORY_H
#include <memory.h> #include <memory.h>
#endif #endif
#include <stdlib.h> #include <stdlib.h>
namespace zeek::detail { namespace zeek::detail
{
void IntSet::Expand(unsigned int i) void IntSet::Expand(unsigned int i)
{ {
@ -16,9 +18,9 @@ void IntSet::Expand(unsigned int i)
memset(newset, 0, newsize); memset(newset, 0, newsize);
memcpy(newset, set, size); memcpy(newset, set, size);
delete [] set; delete[] set;
size = newsize; size = newsize;
set = newset; set = newset;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -8,9 +8,11 @@
#include <string.h> #include <string.h>
namespace zeek::detail { namespace zeek::detail
{
class IntSet { class IntSet
{
public: public:
// n is a hint for the value of the largest integer. // n is a hint for the value of the largest integer.
explicit IntSet(unsigned int n = 1); explicit IntSet(unsigned int n = 1);
@ -38,7 +40,7 @@ inline IntSet::IntSet(unsigned int n)
inline IntSet::~IntSet() inline IntSet::~IntSet()
{ {
delete [] set; delete[] set;
} }
inline void IntSet::Insert(unsigned int i) inline void IntSet::Insert(unsigned int i)
@ -67,4 +69,4 @@ inline void IntSet::Clear()
memset(set, 0, size); memset(set, 0, size);
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,23 +2,28 @@
#pragma once #pragma once
#include <functional>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <functional>
namespace zeek { namespace zeek
{
/** /**
* A tag class for the #IntrusivePtr constructor which means: adopt * A tag class for the #IntrusivePtr constructor which means: adopt
* the reference from the caller. * the reference from the caller.
*/ */
struct AdoptRef {}; struct AdoptRef
{
};
/** /**
* A tag class for the #IntrusivePtr constructor which means: create a * A tag class for the #IntrusivePtr constructor which means: create a
* new reference to the object. * new reference to the object.
*/ */
struct NewRef {}; struct NewRef
{
};
/** /**
* An intrusive, reference counting smart pointer implementation. Much like * An intrusive, reference counting smart pointer implementation. Much like
@ -42,8 +47,8 @@ struct NewRef {};
* should use a smart pointer whenever possible to reduce boilerplate code and * should use a smart pointer whenever possible to reduce boilerplate code and
* increase robustness of the code (in particular w.r.t. exceptions). * increase robustness of the code (in particular w.r.t. exceptions).
*/ */
template <class T> template <class T> class IntrusivePtr
class IntrusivePtr { {
public: public:
// -- member types // -- member types
@ -74,10 +79,7 @@ public:
* *
* @param raw_ptr Pointer to the shared object. * @param raw_ptr Pointer to the shared object.
*/ */
constexpr IntrusivePtr(AdoptRef, pointer raw_ptr) noexcept constexpr IntrusivePtr(AdoptRef, pointer raw_ptr) noexcept : ptr_(raw_ptr) { }
: ptr_(raw_ptr)
{
}
/** /**
* Constructs a new intrusive pointer for managing the lifetime of the object * Constructs a new intrusive pointer for managing the lifetime of the object
@ -87,8 +89,7 @@ public:
* *
* @param raw_ptr Pointer to the shared object. * @param raw_ptr Pointer to the shared object.
*/ */
IntrusivePtr(NewRef, pointer raw_ptr) noexcept IntrusivePtr(NewRef, pointer raw_ptr) noexcept : ptr_(raw_ptr)
: ptr_(raw_ptr)
{ {
if ( ptr_ ) if ( ptr_ )
Ref(ptr_); Ref(ptr_);
@ -99,10 +100,7 @@ public:
// nop // nop
} }
IntrusivePtr(const IntrusivePtr& other) noexcept IntrusivePtr(const IntrusivePtr& other) noexcept : IntrusivePtr(NewRef{}, other.get()) { }
: IntrusivePtr(NewRef{}, other.get())
{
}
template <class U, class = std::enable_if_t<std::is_convertible_v<U*, T*>>> template <class U, class = std::enable_if_t<std::is_convertible_v<U*, T*>>>
IntrusivePtr(IntrusivePtr<U> other) noexcept : ptr_(other.release()) IntrusivePtr(IntrusivePtr<U> other) noexcept : ptr_(other.release())
@ -116,10 +114,7 @@ public:
Unref(ptr_); Unref(ptr_);
} }
void swap(IntrusivePtr& other) noexcept void swap(IntrusivePtr& other) noexcept { std::swap(ptr_, other.ptr_); }
{
std::swap(ptr_, other.ptr_);
}
friend void swap(IntrusivePtr& a, IntrusivePtr& b) noexcept friend void swap(IntrusivePtr& a, IntrusivePtr& b) noexcept
{ {
@ -132,10 +127,7 @@ public:
* intrusive pointer to @c nullptr. * intrusive pointer to @c nullptr.
* @returns the raw pointer without modifying the reference count. * @returns the raw pointer without modifying the reference count.
*/ */
pointer release() noexcept pointer release() noexcept { return std::exchange(ptr_, nullptr); }
{
return std::exchange(ptr_, nullptr);
}
IntrusivePtr& operator=(const IntrusivePtr& other) noexcept IntrusivePtr& operator=(const IntrusivePtr& other) noexcept
{ {
@ -160,34 +152,19 @@ public:
return *this; return *this;
} }
pointer get() const noexcept pointer get() const noexcept { return ptr_; }
{
return ptr_;
}
pointer operator->() const noexcept pointer operator->() const noexcept { return ptr_; }
{
return ptr_;
}
reference operator*() const noexcept reference operator*() const noexcept { return *ptr_; }
{
return *ptr_;
}
bool operator!() const noexcept bool operator!() const noexcept { return ! ptr_; }
{
return !ptr_;
}
explicit operator bool() const noexcept explicit operator bool() const noexcept { return ptr_ != nullptr; }
{
return ptr_ != nullptr;
}
private: private:
pointer ptr_ = nullptr; pointer ptr_ = nullptr;
}; };
/** /**
* Convenience function for creating a reference counted object and wrapping it * Convenience function for creating a reference counted object and wrapping it
@ -197,8 +174,7 @@ private:
* @note This function assumes that any @c T starts with a reference count of 1. * @note This function assumes that any @c T starts with a reference count of 1.
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T, class... Ts> template <class T, class... Ts> IntrusivePtr<T> make_intrusive(Ts&&... args)
IntrusivePtr<T> make_intrusive(Ts&&... args)
{ {
// Assumes that objects start with a reference count of 1! // Assumes that objects start with a reference count of 1!
return {AdoptRef{}, new T(std::forward<Ts>(args)...)}; return {AdoptRef{}, new T(std::forward<Ts>(args)...)};
@ -210,8 +186,7 @@ IntrusivePtr<T> make_intrusive(Ts&&... args)
* @param p The pointer of type @c U to cast to another type, @c T. * @param p The pointer of type @c U to cast to another type, @c T.
* @return The pointer, as cast to type @c T. * @return The pointer, as cast to type @c T.
*/ */
template <class T, class U> template <class T, class U> IntrusivePtr<T> cast_intrusive(IntrusivePtr<U> p) noexcept
IntrusivePtr<T> cast_intrusive(IntrusivePtr<U> p) noexcept
{ {
return {AdoptRef{}, static_cast<T*>(p.release())}; return {AdoptRef{}, static_cast<T*>(p.release())};
} }
@ -221,68 +196,68 @@ IntrusivePtr<T> cast_intrusive(IntrusivePtr<U> p) noexcept
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator==(const zeek::IntrusivePtr<T>& x, std::nullptr_t)
bool operator==(const zeek::IntrusivePtr<T>& x, std::nullptr_t) { {
return !x; return ! x;
} }
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator==(std::nullptr_t, const zeek::IntrusivePtr<T>& x)
bool operator==(std::nullptr_t, const zeek::IntrusivePtr<T>& x) { {
return !x; return ! x;
} }
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator!=(const zeek::IntrusivePtr<T>& x, std::nullptr_t)
bool operator!=(const zeek::IntrusivePtr<T>& x, std::nullptr_t) { {
return static_cast<bool>(x); return static_cast<bool>(x);
} }
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator!=(std::nullptr_t, const zeek::IntrusivePtr<T>& x)
bool operator!=(std::nullptr_t, const zeek::IntrusivePtr<T>& x) { {
return static_cast<bool>(x); return static_cast<bool>(x);
} }
// -- comparison to raw pointer ------------------------------------------------ // -- comparison to raw pointer ------------------------------------------------
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator==(const zeek::IntrusivePtr<T>& x, const T* y)
bool operator==(const zeek::IntrusivePtr<T>& x, const T* y) { {
return x.get() == y; return x.get() == y;
} }
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator==(const T* x, const zeek::IntrusivePtr<T>& y)
bool operator==(const T* x, const zeek::IntrusivePtr<T>& y) { {
return x == y.get(); return x == y.get();
} }
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator!=(const zeek::IntrusivePtr<T>& x, const T* y)
bool operator!=(const zeek::IntrusivePtr<T>& x, const T* y) { {
return x.get() != y; return x.get() != y;
} }
/** /**
* @relates IntrusivePtr * @relates IntrusivePtr
*/ */
template <class T> template <class T> bool operator!=(const T* x, const zeek::IntrusivePtr<T>& y)
bool operator!=(const T* x, const zeek::IntrusivePtr<T>& y) { {
return x != y.get(); return x != y.get();
} }
// -- comparison to intrusive pointer ------------------------------------------ // -- comparison to intrusive pointer ------------------------------------------
@ -294,7 +269,7 @@ bool operator!=(const T* x, const zeek::IntrusivePtr<T>& y) {
*/ */
template <class T, class U> template <class T, class U>
auto operator==(const zeek::IntrusivePtr<T>& x, const zeek::IntrusivePtr<U>& y) auto operator==(const zeek::IntrusivePtr<T>& x, const zeek::IntrusivePtr<U>& y)
-> decltype(x.get() == y.get()) -> decltype(x.get() == y.get())
{ {
return x.get() == y.get(); return x.get() == y.get();
} }
@ -304,19 +279,23 @@ auto operator==(const zeek::IntrusivePtr<T>& x, const zeek::IntrusivePtr<U>& y)
*/ */
template <class T, class U> template <class T, class U>
auto operator!=(const zeek::IntrusivePtr<T>& x, const zeek::IntrusivePtr<U>& y) auto operator!=(const zeek::IntrusivePtr<T>& x, const zeek::IntrusivePtr<U>& y)
-> decltype(x.get() != y.get()) -> decltype(x.get() != y.get())
{ {
return x.get() != y.get(); return x.get() != y.get();
} }
} // namespace zeek } // namespace zeek
// -- hashing ------------------------------------------------ // -- hashing ------------------------------------------------
namespace std { namespace std
template <class T> struct hash<zeek::IntrusivePtr<T>> { {
template <class T> struct hash<zeek::IntrusivePtr<T>>
{
// Hash of intrusive pointer is the same as hash of the raw pointer it holds. // Hash of intrusive pointer is the same as hash of the raw pointer it holds.
size_t operator()(const zeek::IntrusivePtr<T>& v) const noexcept size_t operator()(const zeek::IntrusivePtr<T>& v) const noexcept
{ return std::hash<T*>{}(v.get()); } {
}; return std::hash<T*>{}(v.get());
} }
};
}

View file

@ -1,4 +1,5 @@
#include "zeek/List.h" #include "zeek/List.h"
#include "zeek/3rdparty/doctest.h" #include "zeek/3rdparty/doctest.h"
TEST_CASE("list construction") TEST_CASE("list construction")
@ -13,7 +14,7 @@ TEST_CASE("list construction")
TEST_CASE("list operation") TEST_CASE("list operation")
{ {
zeek::List<int> list({ 1, 2, 3 }); zeek::List<int> list({1, 2, 3});
CHECK(list.size() == 3); CHECK(list.size() == 3);
CHECK(list.max() == 3); CHECK(list.max() == 3);
CHECK(list[0] == 1); CHECK(list[0] == 1);
@ -85,14 +86,14 @@ TEST_CASE("list operation")
TEST_CASE("list iteration") TEST_CASE("list iteration")
{ {
zeek::List<int> list({ 1, 2, 3, 4}); zeek::List<int> list({1, 2, 3, 4});
int index = 1; int index = 1;
for ( int v : list ) for ( int v : list )
CHECK(v == index++); CHECK(v == index++);
index = 1; index = 1;
for ( auto it = list.begin(); it != list.end(); index++, ++it) for ( auto it = list.begin(); it != list.end(); index++, ++it )
CHECK(*it == index); CHECK(*it == index);
} }

View file

@ -20,24 +20,29 @@
// sizeof(data) <= sizeof(void*). // sizeof(data) <= sizeof(void*).
#include <stdarg.h> #include <stdarg.h>
#include <cassert>
#include <initializer_list> #include <initializer_list>
#include <iterator> #include <iterator>
#include <utility> #include <utility>
#include <cassert>
#include "zeek/util.h" #include "zeek/util.h"
namespace zeek { namespace zeek
{
enum class ListOrder : int { ORDERED, UNORDERED }; enum class ListOrder : int
{
ORDERED,
UNORDERED
};
template<typename T, ListOrder Order = ListOrder::ORDERED> template <typename T, ListOrder Order = ListOrder::ORDERED> class List
class List { {
public: public:
constexpr static int DEFAULT_LIST_SIZE = 10; constexpr static int DEFAULT_LIST_SIZE = 10;
constexpr static int LIST_GROWTH_FACTOR = 2; constexpr static int LIST_GROWTH_FACTOR = 2;
~List() { free(entries); } ~List() { free(entries); }
explicit List(int size = 0) explicit List(int size = 0)
{ {
num_entries = 0; num_entries = 0;
@ -51,7 +56,7 @@ public:
max_entries = size; max_entries = size;
entries = (T*) util::safe_malloc(max_entries * sizeof(T)); entries = (T*)util::safe_malloc(max_entries * sizeof(T));
} }
List(const List& b) List(const List& b)
@ -60,7 +65,7 @@ public:
num_entries = b.num_entries; num_entries = b.num_entries;
if ( max_entries ) if ( max_entries )
entries = (T*) util::safe_malloc(max_entries * sizeof(T)); entries = (T*)util::safe_malloc(max_entries * sizeof(T));
else else
entries = nullptr; entries = nullptr;
@ -81,11 +86,11 @@ public:
List(const T* arr, int n) List(const T* arr, int n)
{ {
num_entries = max_entries = n; num_entries = max_entries = n;
entries = (T*) util::safe_malloc(max_entries * sizeof(T)); entries = (T*)util::safe_malloc(max_entries * sizeof(T));
memcpy(entries, arr, n * sizeof(T)); memcpy(entries, arr, n * sizeof(T));
} }
List(std::initializer_list<T> il) : List(il.begin(), il.size()) {} List(std::initializer_list<T> il) : List(il.begin(), il.size()) { }
List& operator=(const List& b) List& operator=(const List& b)
{ {
@ -98,7 +103,7 @@ public:
num_entries = b.num_entries; num_entries = b.num_entries;
if ( max_entries ) if ( max_entries )
entries = (T *) util::safe_malloc(max_entries * sizeof(T)); entries = (T*)util::safe_malloc(max_entries * sizeof(T));
else else
entries = nullptr; entries = nullptr;
@ -124,12 +129,9 @@ public:
} }
// Return nth ent of list (do not remove). // Return nth ent of list (do not remove).
T& operator[](int i) const T& operator[](int i) const { return entries[i]; }
{
return entries[i];
}
void clear() // remove all entries void clear() // remove all entries
{ {
free(entries); free(entries);
entries = nullptr; entries = nullptr;
@ -139,16 +141,16 @@ public:
bool empty() const noexcept { return num_entries == 0; } bool empty() const noexcept { return num_entries == 0; }
size_t size() const noexcept { return num_entries; } size_t size() const noexcept { return num_entries; }
int length() const { return num_entries; } int length() const { return num_entries; }
int max() const { return max_entries; } int max() const { return max_entries; }
int resize(int new_size = 0) // 0 => size to fit current number of entries int resize(int new_size = 0) // 0 => size to fit current number of entries
{ {
if ( new_size < num_entries ) if ( new_size < num_entries )
new_size = num_entries; // do not lose any entries new_size = num_entries; // do not lose any entries
if ( new_size != max_entries ) if ( new_size != max_entries )
{ {
entries = (T*) util::safe_realloc((void*) entries, sizeof(T) * new_size); entries = (T*)util::safe_realloc((void*)entries, sizeof(T) * new_size);
if ( entries ) if ( entries )
max_entries = new_size; max_entries = new_size;
else else
@ -158,9 +160,12 @@ public:
return max_entries; return max_entries;
} }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated(
int MemoryAllocation() const "Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] int
{ return padded_sizeof(*this) + util::pad_size(max_entries * sizeof(T)); } MemoryAllocation() const
{
return padded_sizeof(*this) + util::pad_size(max_entries * sizeof(T));
}
void push_front(const T& a) void push_front(const T& a)
{ {
@ -168,7 +173,7 @@ public:
resize(max_entries ? max_entries * LIST_GROWTH_FACTOR : DEFAULT_LIST_SIZE); resize(max_entries ? max_entries * LIST_GROWTH_FACTOR : DEFAULT_LIST_SIZE);
for ( int i = num_entries; i > 0; --i ) for ( int i = num_entries; i > 0; --i )
entries[i] = entries[i-1]; // move all pointers up one entries[i] = entries[i - 1]; // move all pointers up one
++num_entries; ++num_entries;
entries[0] = a; entries[0] = a;
@ -182,20 +187,20 @@ public:
entries[num_entries++] = a; entries[num_entries++] = a;
} }
void pop_front() { remove_nth(0); } void pop_front() { remove_nth(0); }
void pop_back() { remove_nth(num_entries-1); } void pop_back() { remove_nth(num_entries - 1); }
T& front() { return entries[0]; } T& front() { return entries[0]; }
T& back() { return entries[num_entries-1]; } T& back() { return entries[num_entries - 1]; }
// The append method is maintained for historical/compatibility reasons. // The append method is maintained for historical/compatibility reasons.
// (It's commonly used in the event generation API) // (It's commonly used in the event generation API)
void append(const T& a) // add to end of list void append(const T& a) // add to end of list
{ {
push_back(a); push_back(a);
} }
bool remove(const T& a) // delete entry from list bool remove(const T& a) // delete entry from list
{ {
int pos = member_pos(a); int pos = member_pos(a);
if ( pos != -1 ) if ( pos != -1 )
@ -207,9 +212,9 @@ public:
return false; return false;
} }
T remove_nth(int n) // delete nth entry from list T remove_nth(int n) // delete nth entry from list
{ {
assert(n >=0 && n < num_entries); assert(n >= 0 && n < num_entries);
T old_ent = entries[n]; T old_ent = entries[n];
@ -221,7 +226,7 @@ public:
--num_entries; --num_entries;
for ( ; n < num_entries; ++n ) for ( ; n < num_entries; ++n )
entries[n] = entries[n+1]; entries[n] = entries[n + 1];
} }
else else
{ {
@ -249,7 +254,7 @@ public:
return (i == length()) ? -1 : i; return (i == length()) ? -1 : i;
} }
T replace(int ent_index, const T& new_ent) // replace entry #i with a new value T replace(int ent_index, const T& new_ent) // replace entry #i with a new value
{ {
if ( ent_index < 0 ) if ( ent_index < 0 )
return T{}; return T{};
@ -298,7 +303,6 @@ public:
const_reverse_iterator crend() const { return rend(); } const_reverse_iterator crend() const { return rend(); }
protected: protected:
// This could essentially be an std::vector if we wanted. Some // This could essentially be an std::vector if we wanted. Some
// reasons to maybe not refactor to use std::vector ? // reasons to maybe not refactor to use std::vector ?
// //
@ -328,17 +332,15 @@ protected:
int num_entries; int num_entries;
}; };
// Specialization of the List class to store pointers of a type. // Specialization of the List class to store pointers of a type.
template<typename T, ListOrder Order = ListOrder::ORDERED> template <typename T, ListOrder Order = ListOrder::ORDERED> using PList = List<T*, Order>;
using PList = List<T*, Order>;
// Popular type of list: list of strings. // Popular type of list: list of strings.
using name_list = PList<char>; using name_list = PList<char>;
} // namespace zeek } // namespace zeek
// Macro to visit each list element in turn. // Macro to visit each list element in turn.
#define loop_over_list(list, iterator) \ #define loop_over_list(list, iterator) \
int iterator; \ int iterator; \
for ( iterator = 0; iterator < (list).length(); ++iterator ) for ( iterator = 0; iterator < (list).length(); ++iterator )

View file

@ -1,6 +1,5 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/NFA.h" #include "zeek/NFA.h"
#include <algorithm> #include <algorithm>
@ -8,8 +7,10 @@
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/EquivClass.h" #include "zeek/EquivClass.h"
#include "zeek/IntSet.h" #include "zeek/IntSet.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
static int nfa_state_id = 0; static int nfa_state_id = 0;
@ -159,9 +160,8 @@ unsigned int NFA_State::TotalMemoryAllocation() const
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return padded_sizeof(*this) return padded_sizeof(*this) + xtions.MemoryAllocation() - padded_sizeof(xtions) +
+ xtions.MemoryAllocation() - padded_sizeof(xtions) (epsclosure ? epsclosure->MemoryAllocation() : 0);
+ (epsclosure ? epsclosure->MemoryAllocation() : 0);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} }
@ -219,7 +219,7 @@ void NFA_Machine::LinkCopies(int n)
for ( i = 0; i < n; ++i ) for ( i = 0; i < n; ++i )
AppendMachine(copies[i]); AppendMachine(copies[i]);
delete [] copies; delete[] copies;
} }
NFA_Machine* NFA_Machine::DuplicateMachine() NFA_Machine* NFA_Machine::DuplicateMachine()
@ -243,7 +243,7 @@ void NFA_Machine::AppendMachine(NFA_Machine* m)
final_state->AddXtion(m->FirstState()); final_state->AddXtion(m->FirstState());
final_state = m->FinalState(); final_state = m->FinalState();
Ref(m->FirstState()); // so states stay around after the following Ref(m->FirstState()); // so states stay around after the following
Unref(m); Unref(m);
} }
@ -332,7 +332,6 @@ NFA_Machine* make_alternate(NFA_Machine* m1, NFA_Machine* m2)
return new NFA_Machine(first, last); return new NFA_Machine(first, last);
} }
NFA_state_list* epsilon_closure(NFA_state_list* states) NFA_state_list* epsilon_closure(NFA_state_list* states)
{ {
// We just keep one of this as it may get quite large. // We just keep one of this as it may get quite large.
@ -375,4 +374,4 @@ bool NFA_state_cmp_neg(const NFA_State* v1, const NFA_State* v2)
return false; return false;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,8 +2,8 @@
#pragma once #pragma once
#include "zeek/Obj.h"
#include "zeek/List.h" #include "zeek/List.h"
#include "zeek/Obj.h"
#define NO_ACCEPT 0 #define NO_ACCEPT 0
@ -16,11 +16,13 @@
#define SYM_EPSILON 259 #define SYM_EPSILON 259
#define SYM_CCL 260 #define SYM_CCL 260
namespace zeek { namespace zeek
{
class Func; class Func;
namespace detail { namespace detail
{
class CCL; class CCL;
class EquivClass; class EquivClass;
@ -28,33 +30,34 @@ class EquivClass;
class NFA_State; class NFA_State;
using NFA_state_list = PList<NFA_State>; using NFA_state_list = PList<NFA_State>;
class NFA_State : public Obj { class NFA_State : public Obj
{
public: public:
NFA_State(int sym, EquivClass* ec); NFA_State(int sym, EquivClass* ec);
explicit NFA_State(CCL* ccl); explicit NFA_State(CCL* ccl);
~NFA_State() override; ~NFA_State() override;
void AddXtion(NFA_State* next_state) { xtions.push_back(next_state); } void AddXtion(NFA_State* next_state) { xtions.push_back(next_state); }
NFA_state_list* Transitions() { return &xtions; } NFA_state_list* Transitions() { return &xtions; }
void AddXtionsTo(NFA_state_list* ns); void AddXtionsTo(NFA_state_list* ns);
void SetAccept(int accept_val) { accept = accept_val; } void SetAccept(int accept_val) { accept = accept_val; }
int Accept() const { return accept; } int Accept() const { return accept; }
// Returns a deep copy of this NFA state and everything it points // Returns a deep copy of this NFA state and everything it points
// to. Upon return, each state's marker is set to point to its // to. Upon return, each state's marker is set to point to its
// copy. // copy.
NFA_State* DeepCopy(); NFA_State* DeepCopy();
void SetMark(NFA_State* m) { mark = m; } void SetMark(NFA_State* m) { mark = m; }
NFA_State* Mark() const { return mark; } NFA_State* Mark() const { return mark; }
void ClearMarks(); void ClearMarks();
void SetFirstTransIsBackRef() { first_trans_is_back_ref = true; } void SetFirstTransIsBackRef() { first_trans_is_back_ref = true; }
int TransSym() const { return sym; } int TransSym() const { return sym; }
CCL* TransCCL() const { return ccl; } CCL* TransCCL() const { return ccl; }
int ID() const { return id; } int ID() const { return id; }
NFA_state_list* EpsilonClosure(); NFA_state_list* EpsilonClosure();
@ -62,13 +65,14 @@ public:
void Dump(FILE* f); void Dump(FILE* f);
// Recursivly count all the reachable states. // Recursivly count all the reachable states.
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int TotalMemoryAllocation() const; "GHI-572.")]] unsigned int
TotalMemoryAllocation() const;
protected: protected:
int sym; // if SYM_CCL, then use ccl int sym; // if SYM_CCL, then use ccl
int id; // number that uniquely identifies this state int id; // number that uniquely identifies this state
CCL* ccl; // if nil, then use sym CCL* ccl; // if nil, then use sym
int accept; int accept;
// Whether the first transition points backwards. Used // Whether the first transition points backwards. Used
@ -78,34 +82,40 @@ protected:
NFA_state_list xtions; NFA_state_list xtions;
NFA_state_list* epsclosure; NFA_state_list* epsclosure;
NFA_State* mark; NFA_State* mark;
}; };
class EpsilonState : public NFA_State { class EpsilonState : public NFA_State
{
public: public:
EpsilonState() : NFA_State(SYM_EPSILON, nullptr) { } EpsilonState() : NFA_State(SYM_EPSILON, nullptr) { }
}; };
class NFA_Machine : public Obj { class NFA_Machine : public Obj
{
public: public:
explicit NFA_Machine(NFA_State* first, NFA_State* final = nullptr); explicit NFA_Machine(NFA_State* first, NFA_State* final = nullptr);
~NFA_Machine() override; ~NFA_Machine() override;
NFA_State* FirstState() const { return first_state; } NFA_State* FirstState() const { return first_state; }
void SetFinalState(NFA_State* final) { final_state = final; } void SetFinalState(NFA_State* final) { final_state = final; }
NFA_State* FinalState() const { return final_state; } NFA_State* FinalState() const { return final_state; }
void AddAccept(int accept_val); void AddAccept(int accept_val);
void MakeClosure() { MakePositiveClosure(); MakeOptional(); } void MakeClosure()
{
MakePositiveClosure();
MakeOptional();
}
void MakeOptional(); void MakeOptional();
void MakePositiveClosure(); void MakePositiveClosure();
// re{lower,upper}; upper can be NO_UPPER_BOUND = infinity. // re{lower,upper}; upper can be NO_UPPER_BOUND = infinity.
void MakeRepl(int lower, int upper); void MakeRepl(int lower, int upper);
void MarkBOL() { bol = 1; } void MarkBOL() { bol = 1; }
void MarkEOL() { eol = 1; } void MarkEOL() { eol = 1; }
NFA_Machine* DuplicateMachine(); NFA_Machine* DuplicateMachine();
void LinkCopies(int n); void LinkCopies(int n);
@ -118,8 +128,9 @@ public:
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
void Dump(FILE* f); void Dump(FILE* f);
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const "GHI-572.")]] unsigned int
MemoryAllocation() const
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@ -131,7 +142,7 @@ protected:
NFA_State* first_state; NFA_State* first_state;
NFA_State* final_state; NFA_State* final_state;
int bol, eol; int bol, eol;
}; };
extern NFA_Machine* make_alternate(NFA_Machine* m1, NFA_Machine* m2); extern NFA_Machine* make_alternate(NFA_Machine* m1, NFA_Machine* m2);
@ -145,5 +156,5 @@ extern NFA_state_list* epsilon_closure(NFA_state_list* states);
// For sorting NFA states based on their ID fields (decreasing) // For sorting NFA states based on their ID fields (decreasing)
extern bool NFA_state_cmp_neg(const NFA_State* v1, const NFA_State* v2); extern bool NFA_state_cmp_neg(const NFA_State* v1, const NFA_State* v2);
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,12 +1,12 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/NetVar.h" #include "zeek/NetVar.h"
#include "zeek/Var.h"
#include "zeek/EventHandler.h" #include "zeek/EventHandler.h"
#include "zeek/Val.h"
#include "zeek/ID.h" #include "zeek/ID.h"
#include "zeek/Val.h"
#include "zeek/Var.h"
#include "zeek/zeek-config.h"
zeek::RecordType* conn_id; zeek::RecordType* conn_id;
zeek::RecordType* endpoint; zeek::RecordType* endpoint;
@ -105,7 +105,8 @@ zeek::StringVal* cmd_line_bpf_filter;
zeek::StringVal* global_hash_seed; zeek::StringVal* global_hash_seed;
namespace zeek::detail { namespace zeek::detail
{
int watchdog_interval; int watchdog_interval;
@ -192,7 +193,8 @@ int record_all_packets;
bro_uint_t bits_per_uid; bro_uint_t bits_per_uid;
} // namespace zeek::detail. The namespace has be closed here before we include the netvar_def files. } // namespace zeek::detail. The namespace has be closed here before we include the netvar_def
// files.
// Because of how the BIF include files are built with namespaces already in them, // Because of how the BIF include files are built with namespaces already in them,
// these files need to be included separately before the namespace is opened below. // these files need to be included separately before the namespace is opened below.
@ -205,9 +207,9 @@ static void bif_init_event_handlers()
static void bif_init_net_var() static void bif_init_net_var()
{ {
#include "const.bif.netvar_init" #include "const.bif.netvar_init"
#include "packet_analysis.bif.netvar_init"
#include "reporter.bif.netvar_init" #include "reporter.bif.netvar_init"
#include "supervisor.bif.netvar_init" #include "supervisor.bif.netvar_init"
#include "packet_analysis.bif.netvar_init"
} }
static void init_bif_types() static void init_bif_types()
@ -216,14 +218,15 @@ static void init_bif_types()
} }
#include "const.bif.netvar_def" #include "const.bif.netvar_def"
#include "types.bif.netvar_def"
#include "event.bif.netvar_def" #include "event.bif.netvar_def"
#include "packet_analysis.bif.netvar_def"
#include "reporter.bif.netvar_def" #include "reporter.bif.netvar_def"
#include "supervisor.bif.netvar_def" #include "supervisor.bif.netvar_def"
#include "packet_analysis.bif.netvar_def" #include "types.bif.netvar_def"
// Re-open the namespace now that the bif headers are all included. // Re-open the namespace now that the bif headers are all included.
namespace zeek::detail { namespace zeek::detail
{
void init_event_handlers() void init_event_handlers()
{ {
@ -268,8 +271,10 @@ void init_net_var()
tcp_partial_close_delay = id::find_val("tcp_partial_close_delay")->AsInterval(); tcp_partial_close_delay = id::find_val("tcp_partial_close_delay")->AsInterval();
tcp_max_initial_window = id::find_val("tcp_max_initial_window")->AsCount(); tcp_max_initial_window = id::find_val("tcp_max_initial_window")->AsCount();
tcp_max_above_hole_without_any_acks = id::find_val("tcp_max_above_hole_without_any_acks")->AsCount(); tcp_max_above_hole_without_any_acks =
tcp_excessive_data_without_further_acks = id::find_val("tcp_excessive_data_without_further_acks")->AsCount(); id::find_val("tcp_max_above_hole_without_any_acks")->AsCount();
tcp_excessive_data_without_further_acks =
id::find_val("tcp_excessive_data_without_further_acks")->AsCount();
tcp_max_old_segments = id::find_val("tcp_max_old_segments")->AsCount(); tcp_max_old_segments = id::find_val("tcp_max_old_segments")->AsCount();
non_analyzed_lifetime = id::find_val("non_analyzed_lifetime")->AsInterval(); non_analyzed_lifetime = id::find_val("non_analyzed_lifetime")->AsInterval();
@ -280,15 +285,11 @@ void init_net_var()
tcp_storm_thresh = id::find_val("tcp_storm_thresh")->AsCount(); tcp_storm_thresh = id::find_val("tcp_storm_thresh")->AsCount();
tcp_storm_interarrival_thresh = id::find_val("tcp_storm_interarrival_thresh")->AsInterval(); tcp_storm_interarrival_thresh = id::find_val("tcp_storm_interarrival_thresh")->AsInterval();
tcp_content_deliver_all_orig = tcp_content_deliver_all_orig = bool(id::find_val("tcp_content_deliver_all_orig")->AsBool());
bool(id::find_val("tcp_content_deliver_all_orig")->AsBool()); tcp_content_deliver_all_resp = bool(id::find_val("tcp_content_deliver_all_resp")->AsBool());
tcp_content_deliver_all_resp =
bool(id::find_val("tcp_content_deliver_all_resp")->AsBool());
udp_content_deliver_all_orig = udp_content_deliver_all_orig = bool(id::find_val("udp_content_deliver_all_orig")->AsBool());
bool(id::find_val("udp_content_deliver_all_orig")->AsBool()); udp_content_deliver_all_resp = bool(id::find_val("udp_content_deliver_all_resp")->AsBool());
udp_content_deliver_all_resp =
bool(id::find_val("udp_content_deliver_all_resp")->AsBool());
udp_content_delivery_ports_use_resp = udp_content_delivery_ports_use_resp =
bool(id::find_val("udp_content_delivery_ports_use_resp")->AsBool()); bool(id::find_val("udp_content_delivery_ports_use_resp")->AsBool());
@ -345,4 +346,4 @@ void init_net_var()
timer_mgr_inactivity_timeout = id::find_val("timer_mgr_inactivity_timeout")->AsInterval(); timer_mgr_inactivity_timeout = id::find_val("timer_mgr_inactivity_timeout")->AsInterval();
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,11 +2,12 @@
#pragma once #pragma once
#include "zeek/Val.h"
#include "zeek/EventRegistry.h" #include "zeek/EventRegistry.h"
#include "zeek/Stats.h" #include "zeek/Stats.h"
#include "zeek/Val.h"
namespace zeek::detail { namespace zeek::detail
{
extern int watchdog_interval; extern int watchdog_interval;
@ -101,11 +102,11 @@ extern void init_event_handlers();
extern void init_net_var(); extern void init_net_var();
extern void init_builtin_types(); extern void init_builtin_types();
} // namespace zeek::detail } // namespace zeek::detail
#include "const.bif.netvar_h" #include "const.bif.netvar_h"
#include "types.bif.netvar_h"
#include "event.bif.netvar_h" #include "event.bif.netvar_h"
#include "packet_analysis.bif.netvar_h"
#include "reporter.bif.netvar_h" #include "reporter.bif.netvar_h"
#include "supervisor.bif.netvar_h" #include "supervisor.bif.netvar_h"
#include "packet_analysis.bif.netvar_h" #include "types.bif.netvar_h"

View file

@ -1,13 +1,15 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/Notifier.h"
#include <set> #include <set>
#include "zeek/Notifier.h"
#include "zeek/DebugLogger.h" #include "zeek/DebugLogger.h"
zeek::notifier::detail::Registry zeek::notifier::detail::registry; zeek::notifier::detail::Registry zeek::notifier::detail::registry;
namespace zeek::notifier::detail { namespace zeek::notifier::detail
{
Receiver::Receiver() Receiver::Receiver()
{ {
@ -86,4 +88,4 @@ Modifiable::~Modifiable()
registry.Unregister(this); registry.Unregister(this);
} }
} // namespace zeek::notifier::detail } // namespace zeek::notifier::detail

View file

@ -7,15 +7,17 @@
#pragma once #pragma once
#include <unordered_map>
#include <cstdint> #include <cstdint>
#include <unordered_map>
namespace zeek::notifier::detail { namespace zeek::notifier::detail
{
class Modifiable; class Modifiable;
/** Interface class for receivers of notifications. */ /** Interface class for receivers of notifications. */
class Receiver { class Receiver
{
public: public:
Receiver(); Receiver();
virtual ~Receiver(); virtual ~Receiver();
@ -32,10 +34,11 @@ public:
* no further modifications can possibly occur. * no further modifications can possibly occur.
*/ */
virtual void Terminate() { } virtual void Terminate() { }
}; };
/** Singleton class tracking all notification requests globally. */ /** Singleton class tracking all notification requests globally. */
class Registry { class Registry
{
public: public:
~Registry(); ~Registry();
@ -86,7 +89,7 @@ private:
typedef std::unordered_multimap<Modifiable*, Receiver*> ModifiableMap; typedef std::unordered_multimap<Modifiable*, Receiver*> ModifiableMap;
ModifiableMap registrations; ModifiableMap registrations;
}; };
/** /**
* Singleton object tracking all global notification requests. * Singleton object tracking all global notification requests.
@ -97,7 +100,8 @@ extern Registry registry;
* Base class for objects that can trigger notifications to receivers when * Base class for objects that can trigger notifications to receivers when
* modified. * modified.
*/ */
class Modifiable { class Modifiable
{
public: public:
/** /**
* Calling this method signals to all registered receivers that the * Calling this method signals to all registered receivers that the
@ -116,6 +120,6 @@ protected:
// Number of currently registered receivers. // Number of currently registered receivers.
uint64_t num_receivers = 0; uint64_t num_receivers = 0;
}; };
} // namespace zeek::notifier::detail } // namespace zeek::notifier::detail

View file

@ -1,17 +1,19 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Obj.h" #include "zeek/Obj.h"
#include <stdlib.h> #include <stdlib.h>
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/Func.h"
#include "zeek/File.h" #include "zeek/File.h"
#include "zeek/Func.h"
#include "zeek/plugin/Manager.h" #include "zeek/plugin/Manager.h"
#include "zeek/zeek-config.h"
namespace zeek { namespace zeek
namespace detail { {
namespace detail
{
Location start_location("<start uninitialized>", 0, 0, 0, 0); Location start_location("<start uninitialized>", 0, 0, 0, 0);
Location end_location("<end uninitialized>", 0, 0, 0, 0); Location end_location("<end uninitialized>", 0, 0, 0, 0);
@ -44,14 +46,13 @@ void Location::Describe(ODesc* d) const
bool Location::operator==(const Location& l) const bool Location::operator==(const Location& l) const
{ {
if ( filename == l.filename || if ( filename == l.filename || (filename && l.filename && util::streq(filename, l.filename)) )
(filename && l.filename && util::streq(filename, l.filename)) )
return first_line == l.first_line && last_line == l.last_line; return first_line == l.first_line && last_line == l.last_line;
else else
return false; return false;
} }
} // namespace detail } // namespace detail
int Obj::suppress_errors = 0; int Obj::suppress_errors = 0;
@ -63,7 +64,8 @@ Obj::~Obj()
delete location; delete location;
} }
void Obj::Warn(const char* msg, const Obj* obj2, bool pinpoint_only, const detail::Location* expr_location) const void Obj::Warn(const char* msg, const Obj* obj2, bool pinpoint_only,
const detail::Location* expr_location) const
{ {
ODesc d; ODesc d;
DoMsg(&d, msg, obj2, pinpoint_only, expr_location); DoMsg(&d, msg, obj2, pinpoint_only, expr_location);
@ -71,7 +73,8 @@ void Obj::Warn(const char* msg, const Obj* obj2, bool pinpoint_only, const detai
reporter->PopLocation(); reporter->PopLocation();
} }
void Obj::Error(const char* msg, const Obj* obj2, bool pinpoint_only, const detail::Location* expr_location) const void Obj::Error(const char* msg, const Obj* obj2, bool pinpoint_only,
const detail::Location* expr_location) const
{ {
if ( suppress_errors ) if ( suppress_errors )
return; return;
@ -146,8 +149,7 @@ bool Obj::SetLocationInfo(const detail::Location* start, const detail::Location*
delete location; delete location;
location = new detail::Location(start->filename, location = new detail::Location(start->filename, start->first_line, end->last_line,
start->first_line, end->last_line,
start->first_column, end->last_column); start->first_column, end->last_column);
return true; return true;
@ -162,8 +164,8 @@ void Obj::UpdateLocationEndInfo(const detail::Location& end)
location->last_column = end.last_column; location->last_column = end.last_column;
} }
void Obj::DoMsg(ODesc* d, const char s1[], const Obj* obj2, void Obj::DoMsg(ODesc* d, const char s1[], const Obj* obj2, bool pinpoint_only,
bool pinpoint_only, const detail::Location* expr_location) const const detail::Location* expr_location) const
{ {
d->SetShort(); d->SetShort();
@ -172,7 +174,7 @@ void Obj::DoMsg(ODesc* d, const char s1[], const Obj* obj2,
const detail::Location* loc2 = nullptr; const detail::Location* loc2 = nullptr;
if ( obj2 && obj2->GetLocationInfo() != &detail::no_location && if ( obj2 && obj2->GetLocationInfo() != &detail::no_location &&
*obj2->GetLocationInfo() != *GetLocationInfo() ) *obj2->GetLocationInfo() != *GetLocationInfo() )
loc2 = obj2->GetLocationInfo(); loc2 = obj2->GetLocationInfo();
else if ( expr_location ) else if ( expr_location )
loc2 = expr_location; loc2 = expr_location;
@ -209,7 +211,7 @@ void bad_ref(int type)
void obj_delete_func(void* v) void obj_delete_func(void* v)
{ {
Unref((Obj*) v); Unref((Obj*)v);
} }
} // namespace zeek } // namespace zeek

View file

@ -2,36 +2,38 @@
#pragma once #pragma once
#include "zeek/zeek-config.h"
#include <limits.h> #include <limits.h>
namespace zeek { #include "zeek/zeek-config.h"
namespace zeek
{
class ODesc; class ODesc;
namespace detail { namespace detail
{
class Location final { class Location final
{
public: public:
constexpr Location(const char* fname, int line_f, int line_l, int col_f, int col_l) noexcept
constexpr Location(const char* fname, int line_f, int line_l, : filename(fname), first_line(line_f), last_line(line_l), first_column(col_f),
int col_f, int col_l) noexcept last_column(col_l)
:filename(fname), first_line(line_f), last_line(line_l), {
first_column(col_f), last_column(col_l) {} }
Location() = default; Location() = default;
void Describe(ODesc* d) const; void Describe(ODesc* d) const;
bool operator==(const Location& l) const; bool operator==(const Location& l) const;
bool operator!=(const Location& l) const bool operator!=(const Location& l) const { return ! (*this == l); }
{ return ! (*this == l); }
const char* filename = nullptr; const char* filename = nullptr;
int first_line = 0, last_line = 0; int first_line = 0, last_line = 0;
int first_column = 0, last_column = 0; int first_column = 0, last_column = 0;
}; };
#define YYLTYPE zeek::detail::yyltype #define YYLTYPE zeek::detail::yyltype
typedef Location yyltype; typedef Location yyltype;
@ -56,9 +58,10 @@ inline void set_location(const Location start, const Location end)
end_location = end; end_location = end;
} }
} // namespace detail } // namespace detail
class Obj { class Obj
{
public: public:
Obj() Obj()
{ {
@ -83,39 +86,39 @@ public:
virtual ~Obj(); virtual ~Obj();
/* disallow copying */ /* disallow copying */
Obj(const Obj &) = delete; Obj(const Obj&) = delete;
Obj &operator=(const Obj &) = delete; Obj& operator=(const Obj&) = delete;
// Report user warnings/errors. If obj2 is given, then it's // Report user warnings/errors. If obj2 is given, then it's
// included in the message, though if pinpoint_only is non-zero, // included in the message, though if pinpoint_only is non-zero,
// then obj2 is only used to pinpoint the location. // then obj2 is only used to pinpoint the location.
void Warn(const char* msg, const Obj* obj2 = nullptr, void Warn(const char* msg, const Obj* obj2 = nullptr, bool pinpoint_only = false,
bool pinpoint_only = false, const detail::Location* expr_location = nullptr) const; const detail::Location* expr_location = nullptr) const;
void Error(const char* msg, const Obj* obj2 = nullptr, void Error(const char* msg, const Obj* obj2 = nullptr, bool pinpoint_only = false,
bool pinpoint_only = false, const detail::Location* expr_location = nullptr) const; const detail::Location* expr_location = nullptr) const;
// Report internal errors. // Report internal errors.
void BadTag(const char* msg, const char* t1 = nullptr, void BadTag(const char* msg, const char* t1 = nullptr, const char* t2 = nullptr) const;
const char* t2 = nullptr) const; #define CHECK_TAG(t1, t2, text, tag_to_text_func) \
#define CHECK_TAG(t1, t2, text, tag_to_text_func) \ { \
{ \ if ( t1 != t2 ) \
if ( t1 != t2 ) \ BadTag(text, tag_to_text_func(t1), tag_to_text_func(t2)); \
BadTag(text, tag_to_text_func(t1), tag_to_text_func(t2)); \ }
}
[[noreturn]] void Internal(const char* msg) const; [[noreturn]] void Internal(const char* msg) const;
void InternalWarning(const char* msg) const; void InternalWarning(const char* msg) const;
virtual void Describe(ODesc* d) const { /* FIXME: Add code */ }; virtual void Describe(ODesc* d) const {/* FIXME: Add code */};
void AddLocation(ODesc* d) const; void AddLocation(ODesc* d) const;
// Get location info for debugging. // Get location info for debugging.
virtual const detail::Location* GetLocationInfo() const virtual const detail::Location* GetLocationInfo() const
{ return location ? location : &detail::no_location; } {
return location ? location : &detail::no_location;
}
virtual bool SetLocationInfo(const detail::Location* loc) virtual bool SetLocationInfo(const detail::Location* loc) { return SetLocationInfo(loc, loc); }
{ return SetLocationInfo(loc, loc); }
// Location = range from start to end. // Location = range from start to end.
virtual bool SetLocationInfo(const detail::Location* start, const detail::Location* end); virtual bool SetLocationInfo(const detail::Location* start, const detail::Location* end);
@ -125,30 +128,30 @@ public:
virtual void UpdateLocationEndInfo(const detail::Location& end); virtual void UpdateLocationEndInfo(const detail::Location& end);
// Enable notification of plugins when this objects gets destroyed. // Enable notification of plugins when this objects gets destroyed.
void NotifyPluginsOnDtor() { notify_plugins = true; } void NotifyPluginsOnDtor() { notify_plugins = true; }
int RefCnt() const { return ref_cnt; } int RefCnt() const { return ref_cnt; }
// Helper class to temporarily suppress errors // Helper class to temporarily suppress errors
// as long as there exist any instances. // as long as there exist any instances.
class SuppressErrors { class SuppressErrors
{
public: public:
SuppressErrors() { ++Obj::suppress_errors; } SuppressErrors() { ++Obj::suppress_errors; }
~SuppressErrors() { --Obj::suppress_errors; } ~SuppressErrors() { --Obj::suppress_errors; }
}; };
void Print() const; void Print() const;
protected: protected:
detail::Location* location; // all that matters in real estate detail::Location* location; // all that matters in real estate
private: private:
friend class SuppressErrors; friend class SuppressErrors;
void DoMsg(ODesc* d, const char s1[], const Obj* obj2 = nullptr, void DoMsg(ODesc* d, const char s1[], const Obj* obj2 = nullptr, bool pinpoint_only = false,
bool pinpoint_only = false, const detail::Location* expr_location = nullptr) const; const detail::Location* expr_location = nullptr) const;
void PinPoint(ODesc* d, const Obj* obj2 = nullptr, void PinPoint(ODesc* d, const Obj* obj2 = nullptr, bool pinpoint_only = false) const;
bool pinpoint_only = false) const;
friend inline void Ref(Obj* o); friend inline void Ref(Obj* o);
friend inline void Unref(Obj* o); friend inline void Unref(Obj* o);
@ -159,7 +162,7 @@ private:
// If non-zero, do not print runtime errors. Useful for // If non-zero, do not print runtime errors. Useful for
// speculative evaluation. // speculative evaluation.
static int suppress_errors; static int suppress_errors;
}; };
// Sometimes useful when dealing with Obj subclasses that have their // Sometimes useful when dealing with Obj subclasses that have their
// own (protected) versions of Error. // own (protected) versions of Error.
@ -194,4 +197,4 @@ inline void Unref(Obj* o)
// A dict_delete_func that knows to Unref() dictionary entries. // A dict_delete_func that knows to Unref() dictionary entries.
extern void obj_delete_func(void* v); extern void obj_delete_func(void* v);
} // namespace zeek } // namespace zeek

View file

@ -2,25 +2,25 @@
#include "zeek/OpaqueVal.h" #include "zeek/OpaqueVal.h"
#include <memory>
#include <broker/data.hh> #include <broker/data.hh>
#include <broker/error.hh> #include <broker/error.hh>
#include <memory>
#include "zeek/CompHash.h" #include "zeek/CompHash.h"
#include "zeek/Desc.h"
#include "zeek/NetVar.h" #include "zeek/NetVar.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/Scope.h" #include "zeek/Scope.h"
#include "zeek/Desc.h"
#include "zeek/Var.h" #include "zeek/Var.h"
#include "zeek/probabilistic/BloomFilter.h" #include "zeek/probabilistic/BloomFilter.h"
#include "zeek/probabilistic/CardinalityCounter.h" #include "zeek/probabilistic/CardinalityCounter.h"
namespace zeek { namespace zeek
{
// Helper to retrieve a broker value out of a broker::vector at a specified // Helper to retrieve a broker value out of a broker::vector at a specified
// index, and casted to the expected destination type. // index, and casted to the expected destination type.
template<typename S, typename V, typename D> template <typename S, typename V, typename D>
inline bool get_vector_idx(const V& v, unsigned int i, D* dst) inline bool get_vector_idx(const V& v, unsigned int i, D* dst)
{ {
if ( i >= v.size() ) if ( i >= v.size() )
@ -40,12 +40,9 @@ OpaqueMgr* OpaqueMgr::mgr()
return &mgr; return &mgr;
} }
OpaqueVal::OpaqueVal(OpaqueTypePtr t) : Val(std::move(t)) OpaqueVal::OpaqueVal(OpaqueTypePtr t) : Val(std::move(t)) { }
{}
OpaqueVal::~OpaqueVal() OpaqueVal::~OpaqueVal() { }
{
}
const std::string& OpaqueMgr::TypeID(const OpaqueVal* v) const const std::string& OpaqueMgr::TypeID(const OpaqueVal* v) const
{ {
@ -53,7 +50,7 @@ const std::string& OpaqueMgr::TypeID(const OpaqueVal* v) const
if ( x == _types.end() ) if ( x == _types.end() )
reporter->InternalError("OpaqueMgr::TypeID: opaque type %s not registered", reporter->InternalError("OpaqueMgr::TypeID: opaque type %s not registered",
v->OpaqueName()); v->OpaqueName());
return x->first; return x->first;
} }
@ -211,9 +208,7 @@ HashVal::HashVal(OpaqueTypePtr t) : OpaqueVal(std::move(t))
valid = false; valid = false;
} }
MD5Val::MD5Val() : HashVal(md5_type) MD5Val::MD5Val() : HashVal(md5_type) { }
{
}
MD5Val::~MD5Val() MD5Val::~MD5Val()
{ {
@ -232,7 +227,7 @@ void HashVal::digest_one(EVP_MD_CTX* h, const Val* v)
{ {
ODesc d(DESC_BINARY); ODesc d(DESC_BINARY);
v->Describe(&d); v->Describe(&d);
detail::hash_update(h, (const u_char *) d.Bytes(), d.Len()); detail::hash_update(h, (const u_char*)d.Bytes(), d.Len());
} }
} }
@ -289,18 +284,16 @@ broker::expected<broker::data> MD5Val::DoSerialize() const
if ( ! IsValid() ) if ( ! IsValid() )
return {broker::vector{false}}; return {broker::vector{false}};
MD5_CTX* md = (MD5_CTX*) EVP_MD_CTX_md_data(ctx); MD5_CTX* md = (MD5_CTX*)EVP_MD_CTX_md_data(ctx);
broker::vector d = { broker::vector d = {true,
true, static_cast<uint64_t>(md->A),
static_cast<uint64_t>(md->A), static_cast<uint64_t>(md->B),
static_cast<uint64_t>(md->B), static_cast<uint64_t>(md->C),
static_cast<uint64_t>(md->C), static_cast<uint64_t>(md->D),
static_cast<uint64_t>(md->D), static_cast<uint64_t>(md->Nl),
static_cast<uint64_t>(md->Nl), static_cast<uint64_t>(md->Nh),
static_cast<uint64_t>(md->Nh), static_cast<uint64_t>(md->num)};
static_cast<uint64_t>(md->num)
};
for ( int i = 0; i < MD5_LBLOCK; ++i ) for ( int i = 0; i < MD5_LBLOCK; ++i )
d.emplace_back(static_cast<uint64_t>(md->data[i])); d.emplace_back(static_cast<uint64_t>(md->data[i]));
@ -325,7 +318,7 @@ bool MD5Val::DoUnserialize(const broker::data& data)
} }
Init(); Init();
MD5_CTX* md = (MD5_CTX*) EVP_MD_CTX_md_data(ctx); MD5_CTX* md = (MD5_CTX*)EVP_MD_CTX_md_data(ctx);
if ( ! get_vector_idx<uint64_t>(*d, 1, &md->A) ) if ( ! get_vector_idx<uint64_t>(*d, 1, &md->A) )
return false; return false;
@ -351,9 +344,7 @@ bool MD5Val::DoUnserialize(const broker::data& data)
return true; return true;
} }
SHA1Val::SHA1Val() : HashVal(sha1_type) SHA1Val::SHA1Val() : HashVal(sha1_type) { }
{
}
SHA1Val::~SHA1Val() SHA1Val::~SHA1Val()
{ {
@ -409,19 +400,17 @@ broker::expected<broker::data> SHA1Val::DoSerialize() const
if ( ! IsValid() ) if ( ! IsValid() )
return {broker::vector{false}}; return {broker::vector{false}};
SHA_CTX* md = (SHA_CTX*) EVP_MD_CTX_md_data(ctx); SHA_CTX* md = (SHA_CTX*)EVP_MD_CTX_md_data(ctx);
broker::vector d = { broker::vector d = {true,
true, static_cast<uint64_t>(md->h0),
static_cast<uint64_t>(md->h0), static_cast<uint64_t>(md->h1),
static_cast<uint64_t>(md->h1), static_cast<uint64_t>(md->h2),
static_cast<uint64_t>(md->h2), static_cast<uint64_t>(md->h3),
static_cast<uint64_t>(md->h3), static_cast<uint64_t>(md->h4),
static_cast<uint64_t>(md->h4), static_cast<uint64_t>(md->Nl),
static_cast<uint64_t>(md->Nl), static_cast<uint64_t>(md->Nh),
static_cast<uint64_t>(md->Nh), static_cast<uint64_t>(md->num)};
static_cast<uint64_t>(md->num)
};
for ( int i = 0; i < SHA_LBLOCK; ++i ) for ( int i = 0; i < SHA_LBLOCK; ++i )
d.emplace_back(static_cast<uint64_t>(md->data[i])); d.emplace_back(static_cast<uint64_t>(md->data[i]));
@ -446,7 +435,7 @@ bool SHA1Val::DoUnserialize(const broker::data& data)
} }
Init(); Init();
SHA_CTX* md = (SHA_CTX*) EVP_MD_CTX_md_data(ctx); SHA_CTX* md = (SHA_CTX*)EVP_MD_CTX_md_data(ctx);
if ( ! get_vector_idx<uint64_t>(*d, 1, &md->h0) ) if ( ! get_vector_idx<uint64_t>(*d, 1, &md->h0) )
return false; return false;
@ -474,9 +463,7 @@ bool SHA1Val::DoUnserialize(const broker::data& data)
return true; return true;
} }
SHA256Val::SHA256Val() : HashVal(sha256_type) SHA256Val::SHA256Val() : HashVal(sha256_type) { }
{
}
SHA256Val::~SHA256Val() SHA256Val::~SHA256Val()
{ {
@ -501,7 +488,7 @@ ValPtr SHA256Val::DoClone(CloneState* state)
bool SHA256Val::DoInit() bool SHA256Val::DoInit()
{ {
assert( ! IsValid() ); assert(! IsValid());
ctx = detail::hash_init(detail::Hash_SHA256); ctx = detail::hash_init(detail::Hash_SHA256);
return true; return true;
} }
@ -532,15 +519,10 @@ broker::expected<broker::data> SHA256Val::DoSerialize() const
if ( ! IsValid() ) if ( ! IsValid() )
return {broker::vector{false}}; return {broker::vector{false}};
SHA256_CTX* md = (SHA256_CTX*) EVP_MD_CTX_md_data(ctx); SHA256_CTX* md = (SHA256_CTX*)EVP_MD_CTX_md_data(ctx);
broker::vector d = { broker::vector d = {true, static_cast<uint64_t>(md->Nl), static_cast<uint64_t>(md->Nh),
true, static_cast<uint64_t>(md->num), static_cast<uint64_t>(md->md_len)};
static_cast<uint64_t>(md->Nl),
static_cast<uint64_t>(md->Nh),
static_cast<uint64_t>(md->num),
static_cast<uint64_t>(md->md_len)
};
for ( int i = 0; i < 8; ++i ) for ( int i = 0; i < 8; ++i )
d.emplace_back(static_cast<uint64_t>(md->h[i])); d.emplace_back(static_cast<uint64_t>(md->h[i]));
@ -568,7 +550,7 @@ bool SHA256Val::DoUnserialize(const broker::data& data)
} }
Init(); Init();
SHA256_CTX* md = (SHA256_CTX*) EVP_MD_CTX_md_data(ctx); SHA256_CTX* md = (SHA256_CTX*)EVP_MD_CTX_md_data(ctx);
if ( ! get_vector_idx<uint64_t>(*d, 1, &md->Nl) ) if ( ! get_vector_idx<uint64_t>(*d, 1, &md->Nl) )
return false; return false;
@ -594,9 +576,7 @@ bool SHA256Val::DoUnserialize(const broker::data& data)
return true; return true;
} }
EntropyVal::EntropyVal() : OpaqueVal(entropy_type) EntropyVal::EntropyVal() : OpaqueVal(entropy_type) { }
{
}
bool EntropyVal::Feed(const void* data, size_t size) bool EntropyVal::Feed(const void* data, size_t size)
{ {
@ -604,8 +584,8 @@ bool EntropyVal::Feed(const void* data, size_t size)
return true; return true;
} }
bool EntropyVal::Get(double *r_ent, double *r_chisq, double *r_mean, bool EntropyVal::Get(double* r_ent, double* r_chisq, double* r_mean, double* r_montepicalc,
double *r_montepicalc, double *r_scc) double* r_scc)
{ {
state.end(r_ent, r_chisq, r_mean, r_montepicalc, r_scc); state.end(r_ent, r_chisq, r_mean, r_montepicalc, r_scc);
return true; return true;
@ -615,30 +595,22 @@ IMPLEMENT_OPAQUE_VALUE(EntropyVal)
broker::expected<broker::data> EntropyVal::DoSerialize() const broker::expected<broker::data> EntropyVal::DoSerialize() const
{ {
broker::vector d = broker::vector d = {
{ static_cast<uint64_t>(state.totalc), static_cast<uint64_t>(state.mp),
static_cast<uint64_t>(state.totalc), static_cast<uint64_t>(state.sccfirst), static_cast<uint64_t>(state.inmont),
static_cast<uint64_t>(state.mp), static_cast<uint64_t>(state.mcount), static_cast<uint64_t>(state.cexp),
static_cast<uint64_t>(state.sccfirst), static_cast<uint64_t>(state.montex), static_cast<uint64_t>(state.montey),
static_cast<uint64_t>(state.inmont), static_cast<uint64_t>(state.montepi), static_cast<uint64_t>(state.sccu0),
static_cast<uint64_t>(state.mcount), static_cast<uint64_t>(state.scclast), static_cast<uint64_t>(state.scct1),
static_cast<uint64_t>(state.cexp), static_cast<uint64_t>(state.scct2), static_cast<uint64_t>(state.scct3),
static_cast<uint64_t>(state.montex), };
static_cast<uint64_t>(state.montey),
static_cast<uint64_t>(state.montepi),
static_cast<uint64_t>(state.sccu0),
static_cast<uint64_t>(state.scclast),
static_cast<uint64_t>(state.scct1),
static_cast<uint64_t>(state.scct2),
static_cast<uint64_t>(state.scct3),
};
d.reserve(256 + 3 + RT_MONTEN + 11); d.reserve(256 + 3 + RT_MONTEN + 11);
for ( int i = 0; i < 256; ++i ) for ( int i = 0; i < 256; ++i )
d.emplace_back(static_cast<uint64_t>(state.ccount[i])); d.emplace_back(static_cast<uint64_t>(state.ccount[i]));
for ( int i = 0; i < RT_MONTEN; ++i ) for ( int i = 0; i < RT_MONTEN; ++i )
d.emplace_back(static_cast<uint64_t>(state.monte[i])); d.emplace_back(static_cast<uint64_t>(state.monte[i]));
return {std::move(d)}; return {std::move(d)};
@ -694,15 +666,13 @@ bool EntropyVal::DoUnserialize(const broker::data& data)
return true; return true;
} }
BloomFilterVal::BloomFilterVal() BloomFilterVal::BloomFilterVal() : OpaqueVal(bloomfilter_type)
: OpaqueVal(bloomfilter_type)
{ {
hash = nullptr; hash = nullptr;
bloom_filter = nullptr; bloom_filter = nullptr;
} }
BloomFilterVal::BloomFilterVal(probabilistic::BloomFilter* bf) BloomFilterVal::BloomFilterVal(probabilistic::BloomFilter* bf) : OpaqueVal(bloomfilter_type)
: OpaqueVal(bloomfilter_type)
{ {
hash = nullptr; hash = nullptr;
bloom_filter = bf; bloom_filter = bf;
@ -762,12 +732,10 @@ std::string BloomFilterVal::InternalState() const
return bloom_filter->InternalState(); return bloom_filter->InternalState();
} }
BloomFilterValPtr BloomFilterVal::Merge(const BloomFilterVal* x, BloomFilterValPtr BloomFilterVal::Merge(const BloomFilterVal* x, const BloomFilterVal* y)
const BloomFilterVal* y)
{ {
if ( x->Type() && // any one 0 is ok here if ( x->Type() && // any one 0 is ok here
y->Type() && y->Type() && ! same_type(x->Type(), y->Type()) )
! same_type(x->Type(), y->Type()) )
{ {
reporter->Error("cannot merge Bloom filters with different types"); reporter->Error("cannot merge Bloom filters with different types");
return nullptr; return nullptr;
@ -875,8 +843,8 @@ CardinalityVal::~CardinalityVal()
ValPtr CardinalityVal::DoClone(CloneState* state) ValPtr CardinalityVal::DoClone(CloneState* state)
{ {
return state->NewClone(this, return state->NewClone(
make_intrusive<CardinalityVal>(new probabilistic::detail::CardinalityCounter(*c))); this, make_intrusive<CardinalityVal>(new probabilistic::detail::CardinalityCounter(*c)));
} }
bool CardinalityVal::Typify(TypePtr arg_type) bool CardinalityVal::Typify(TypePtr arg_type)
@ -948,16 +916,15 @@ bool CardinalityVal::DoUnserialize(const broker::data& data)
return true; return true;
} }
ParaglobVal::ParaglobVal(std::unique_ptr<paraglob::Paraglob> p) ParaglobVal::ParaglobVal(std::unique_ptr<paraglob::Paraglob> p) : OpaqueVal(paraglob_type)
: OpaqueVal(paraglob_type)
{ {
this->internal_paraglob = std::move(p); this->internal_paraglob = std::move(p);
} }
VectorValPtr ParaglobVal::Get(StringVal* &pattern) VectorValPtr ParaglobVal::Get(StringVal*& pattern)
{ {
auto rval = make_intrusive<VectorVal>(id::string_vec); auto rval = make_intrusive<VectorVal>(id::string_vec);
std::string string_pattern (reinterpret_cast<const char*>(pattern->Bytes()), pattern->Len()); std::string string_pattern(reinterpret_cast<const char*>(pattern->Bytes()), pattern->Len());
std::vector<std::string> matches = this->internal_paraglob->get(string_pattern); std::vector<std::string> matches = this->internal_paraglob->get(string_pattern);
for ( size_t i = 0; i < matches.size(); i++ ) for ( size_t i = 0; i < matches.size(); i++ )
@ -977,7 +944,7 @@ broker::expected<broker::data> ParaglobVal::DoSerialize() const
{ {
broker::vector d; broker::vector d;
std::unique_ptr<std::vector<uint8_t>> iv = this->internal_paraglob->serialize(); std::unique_ptr<std::vector<uint8_t>> iv = this->internal_paraglob->serialize();
for (uint8_t a : *(iv.get())) for ( uint8_t a : *(iv.get()) )
d.emplace_back(static_cast<uint64_t>(a)); d.emplace_back(static_cast<uint64_t>(a));
return {std::move(d)}; return {std::move(d)};
} }
@ -988,10 +955,10 @@ bool ParaglobVal::DoUnserialize(const broker::data& data)
if ( ! d ) if ( ! d )
return false; return false;
std::unique_ptr<std::vector<uint8_t>> iv (new std::vector<uint8_t>); std::unique_ptr<std::vector<uint8_t>> iv(new std::vector<uint8_t>);
iv->resize(d->size()); iv->resize(d->size());
for (std::vector<broker::data>::size_type i = 0; i < d->size(); ++i) for ( std::vector<broker::data>::size_type i = 0; i < d->size(); ++i )
{ {
if ( ! get_vector_idx<uint64_t>(*d, i, iv.get()->data() + i) ) if ( ! get_vector_idx<uint64_t>(*d, i, iv.get()->data() + i) )
return false; return false;
@ -1001,12 +968,12 @@ bool ParaglobVal::DoUnserialize(const broker::data& data)
{ {
this->internal_paraglob = std::make_unique<paraglob::Paraglob>(std::move(iv)); this->internal_paraglob = std::make_unique<paraglob::Paraglob>(std::move(iv));
} }
catch (const paraglob::underflow_error& e) catch ( const paraglob::underflow_error& e )
{ {
reporter->Error("Paraglob underflow error -> %s", e.what()); reporter->Error("Paraglob underflow error -> %s", e.what());
return false; return false;
} }
catch (const paraglob::overflow_error& e) catch ( const paraglob::overflow_error& e )
{ {
reporter->Error("Paraglob overflow error -> %s", e.what()); reporter->Error("Paraglob overflow error -> %s", e.what());
return false; return false;
@ -1017,16 +984,17 @@ bool ParaglobVal::DoUnserialize(const broker::data& data)
ValPtr ParaglobVal::DoClone(CloneState* state) ValPtr ParaglobVal::DoClone(CloneState* state)
{ {
try { try
return make_intrusive<ParaglobVal> {
(std::make_unique<paraglob::Paraglob>(this->internal_paraglob->serialize())); return make_intrusive<ParaglobVal>(
std::make_unique<paraglob::Paraglob>(this->internal_paraglob->serialize()));
} }
catch (const paraglob::underflow_error& e) catch ( const paraglob::underflow_error& e )
{ {
reporter->Error("Paraglob underflow error while cloning -> %s", e.what()); reporter->Error("Paraglob underflow error while cloning -> %s", e.what());
return nullptr; return nullptr;
} }
catch (const paraglob::overflow_error& e) catch ( const paraglob::overflow_error& e )
{ {
reporter->Error("Paraglob overflow error while cloning -> %s", e.what()); reporter->Error("Paraglob overflow error while cloning -> %s", e.what());
return nullptr; return nullptr;
@ -1035,8 +1003,7 @@ ValPtr ParaglobVal::DoClone(CloneState* state)
broker::expected<broker::data> TelemetryVal::DoSerialize() const broker::expected<broker::data> TelemetryVal::DoSerialize() const
{ {
return broker::make_error(broker::ec::invalid_data, return broker::make_error(broker::ec::invalid_data, "cannot serialize metric handles");
"cannot serialize metric handles");
} }
bool TelemetryVal::DoUnserialize(const broker::data&) bool TelemetryVal::DoUnserialize(const broker::data&)
@ -1044,52 +1011,38 @@ bool TelemetryVal::DoUnserialize(const broker::data&)
return false; return false;
} }
TelemetryVal::TelemetryVal(telemetry::IntCounter) :OpaqueVal(int_counter_metric_type) TelemetryVal::TelemetryVal(telemetry::IntCounter) : OpaqueVal(int_counter_metric_type) { }
TelemetryVal::TelemetryVal(telemetry::IntCounterFamily) : OpaqueVal(int_counter_metric_family_type)
{ {
} }
TelemetryVal::TelemetryVal(telemetry::IntCounterFamily) :OpaqueVal(int_counter_metric_family_type) TelemetryVal::TelemetryVal(telemetry::DblCounter) : OpaqueVal(dbl_counter_metric_type) { }
TelemetryVal::TelemetryVal(telemetry::DblCounterFamily) : OpaqueVal(dbl_counter_metric_family_type)
{ {
} }
TelemetryVal::TelemetryVal(telemetry::DblCounter) :OpaqueVal(dbl_counter_metric_type) TelemetryVal::TelemetryVal(telemetry::IntGauge) : OpaqueVal(int_gauge_metric_type) { }
TelemetryVal::TelemetryVal(telemetry::IntGaugeFamily) : OpaqueVal(int_gauge_metric_family_type) { }
TelemetryVal::TelemetryVal(telemetry::DblGauge) : OpaqueVal(dbl_gauge_metric_type) { }
TelemetryVal::TelemetryVal(telemetry::DblGaugeFamily) : OpaqueVal(dbl_gauge_metric_family_type) { }
TelemetryVal::TelemetryVal(telemetry::IntHistogram) : OpaqueVal(int_histogram_metric_type) { }
TelemetryVal::TelemetryVal(telemetry::IntHistogramFamily)
: OpaqueVal(int_histogram_metric_family_type)
{ {
} }
TelemetryVal::TelemetryVal(telemetry::DblCounterFamily) :OpaqueVal(dbl_counter_metric_family_type) TelemetryVal::TelemetryVal(telemetry::DblHistogram) : OpaqueVal(dbl_histogram_metric_type) { }
TelemetryVal::TelemetryVal(telemetry::DblHistogramFamily)
: OpaqueVal(dbl_histogram_metric_family_type)
{ {
} }
TelemetryVal::TelemetryVal(telemetry::IntGauge) :OpaqueVal(int_gauge_metric_type)
{
} }
TelemetryVal::TelemetryVal(telemetry::IntGaugeFamily) :OpaqueVal(int_gauge_metric_family_type)
{
}
TelemetryVal::TelemetryVal(telemetry::DblGauge) :OpaqueVal(dbl_gauge_metric_type)
{
}
TelemetryVal::TelemetryVal(telemetry::DblGaugeFamily) :OpaqueVal(dbl_gauge_metric_family_type)
{
}
TelemetryVal::TelemetryVal(telemetry::IntHistogram) :OpaqueVal(int_histogram_metric_type)
{
}
TelemetryVal::TelemetryVal(telemetry::IntHistogramFamily) :OpaqueVal(int_histogram_metric_family_type)
{
}
TelemetryVal::TelemetryVal(telemetry::DblHistogram) :OpaqueVal(dbl_histogram_metric_type)
{
}
TelemetryVal::TelemetryVal(telemetry::DblHistogramFamily) :OpaqueVal(dbl_histogram_metric_family_type)
{
}
}

View file

@ -2,9 +2,9 @@
#pragma once #pragma once
#include <sys/types.h> // for u_char
#include <broker/expected.hh> #include <broker/expected.hh>
#include <paraglob/paraglob.h> #include <paraglob/paraglob.h>
#include <sys/types.h> // for u_char
#include "zeek/IntrusivePtr.h" #include "zeek/IntrusivePtr.h"
#include "zeek/RandTest.h" #include "zeek/RandTest.h"
@ -14,12 +14,22 @@
#include "zeek/telemetry/Gauge.h" #include "zeek/telemetry/Gauge.h"
#include "zeek/telemetry/Histogram.h" #include "zeek/telemetry/Histogram.h"
namespace broker { class data; } namespace broker
{
class data;
}
namespace zeek { namespace zeek
{
namespace probabilistic { class BloomFilter; } namespace probabilistic
namespace probabilistic::detail { class CardinalityCounter; } {
class BloomFilter;
}
namespace probabilistic::detail
{
class CardinalityCounter;
}
class OpaqueVal; class OpaqueVal;
using OpaqueValPtr = IntrusivePtr<OpaqueVal>; using OpaqueValPtr = IntrusivePtr<OpaqueVal>;
@ -28,12 +38,13 @@ class BloomFilterVal;
using BloomFilterValPtr = IntrusivePtr<BloomFilterVal>; using BloomFilterValPtr = IntrusivePtr<BloomFilterVal>;
/** /**
* Singleton that registers all available all available types of opaque * Singleton that registers all available all available types of opaque
* values. This faciliates their serialization into Broker values. * values. This faciliates their serialization into Broker values.
*/ */
class OpaqueMgr { class OpaqueMgr
{
public: public:
using Factory = OpaqueValPtr (); using Factory = OpaqueValPtr();
/** /**
* Return's a unique ID for the type of an opaque value. * Return's a unique ID for the type of an opaque value.
@ -66,27 +77,26 @@ public:
* Internal helper class to register an OpaqueVal-derived classes * Internal helper class to register an OpaqueVal-derived classes
* with the manager. * with the manager.
*/ */
template<class T> template <class T> class Register
class Register { {
public: public:
Register(const char* id) Register(const char* id) { OpaqueMgr::mgr()->_types.emplace(id, &T::OpaqueInstantiate); }
{ OpaqueMgr::mgr()->_types.emplace(id, &T::OpaqueInstantiate); } };
};
private: private:
std::unordered_map<std::string, Factory*> _types; std::unordered_map<std::string, Factory*> _types;
}; };
/** Macro to insert into an OpaqueVal-derived class's declaration. */ /** Macro to insert into an OpaqueVal-derived class's declaration. */
#define DECLARE_OPAQUE_VALUE(T) \ #define DECLARE_OPAQUE_VALUE(T) \
friend class zeek::OpaqueMgr::Register<T>; \ friend class zeek::OpaqueMgr::Register<T>; \
friend zeek::IntrusivePtr<T> zeek::make_intrusive<T>(); \ friend zeek::IntrusivePtr<T> zeek::make_intrusive<T>(); \
broker::expected<broker::data> DoSerialize() const override; \ broker::expected<broker::data> DoSerialize() const override; \
bool DoUnserialize(const broker::data& data) override; \ bool DoUnserialize(const broker::data& data) override; \
const char* OpaqueName() const override { return #T; } \ const char* OpaqueName() const override { return #T; } \
static zeek::OpaqueValPtr OpaqueInstantiate() { return zeek::make_intrusive<T>(); } static zeek::OpaqueValPtr OpaqueInstantiate() { return zeek::make_intrusive<T>(); }
#define __OPAQUE_MERGE(a, b) a ## b #define __OPAQUE_MERGE(a, b) a##b
#define __OPAQUE_ID(x) __OPAQUE_MERGE(_opaque, x) #define __OPAQUE_ID(x) __OPAQUE_MERGE(_opaque, x)
/** Macro to insert into an OpaqueVal-derived class's implementation file. */ /** Macro to insert into an OpaqueVal-derived class's implementation file. */
@ -97,7 +107,8 @@ private:
* completely internally, with no further script-level operators provided * completely internally, with no further script-level operators provided
* (other than bif functions). See OpaqueVal.h for derived classes. * (other than bif functions). See OpaqueVal.h for derived classes.
*/ */
class OpaqueVal : public Val { class OpaqueVal : public Val
{
public: public:
explicit OpaqueVal(OpaqueTypePtr t); explicit OpaqueVal(OpaqueTypePtr t);
~OpaqueVal() override; ~OpaqueVal() override;
@ -164,9 +175,10 @@ protected:
* during unserialization. Returns the type at reference count +1. * during unserialization. Returns the type at reference count +1.
*/ */
static TypePtr UnserializeType(const broker::data& data); static TypePtr UnserializeType(const broker::data& data);
}; };
class HashVal : public OpaqueVal { class HashVal : public OpaqueVal
{
public: public:
template <class T> template <class T>
static void digest_all(detail::HashAlgorithm alg, const T& vlist, u_char* result) static void digest_all(detail::HashAlgorithm alg, const T& vlist, u_char* result)
@ -197,17 +209,18 @@ protected:
private: private:
// This flag exists because Get() can only be called once. // This flag exists because Get() can only be called once.
bool valid; bool valid;
}; };
class MD5Val : public HashVal { class MD5Val : public HashVal
{
public: public:
template <class T> template <class T> static void digest(const T& vlist, u_char result[MD5_DIGEST_LENGTH])
static void digest(const T& vlist, u_char result[MD5_DIGEST_LENGTH]) {
{ digest_all(detail::Hash_MD5, vlist, result); } digest_all(detail::Hash_MD5, vlist, result);
}
template <class T> template <class T>
static void hmac(const T& vlist, static void hmac(const T& vlist, u_char key[MD5_DIGEST_LENGTH],
u_char key[MD5_DIGEST_LENGTH],
u_char result[MD5_DIGEST_LENGTH]) u_char result[MD5_DIGEST_LENGTH])
{ {
digest(vlist, result); digest(vlist, result);
@ -233,13 +246,15 @@ protected:
DECLARE_OPAQUE_VALUE(MD5Val) DECLARE_OPAQUE_VALUE(MD5Val)
private: private:
EVP_MD_CTX* ctx; EVP_MD_CTX* ctx;
}; };
class SHA1Val : public HashVal { class SHA1Val : public HashVal
{
public: public:
template <class T> template <class T> static void digest(const T& vlist, u_char result[SHA_DIGEST_LENGTH])
static void digest(const T& vlist, u_char result[SHA_DIGEST_LENGTH]) {
{ digest_all(detail::Hash_SHA1, vlist, result); } digest_all(detail::Hash_SHA1, vlist, result);
}
SHA1Val(); SHA1Val();
~SHA1Val(); ~SHA1Val();
@ -256,13 +271,15 @@ protected:
DECLARE_OPAQUE_VALUE(SHA1Val) DECLARE_OPAQUE_VALUE(SHA1Val)
private: private:
EVP_MD_CTX* ctx; EVP_MD_CTX* ctx;
}; };
class SHA256Val : public HashVal { class SHA256Val : public HashVal
{
public: public:
template <class T> template <class T> static void digest(const T& vlist, u_char result[SHA256_DIGEST_LENGTH])
static void digest(const T& vlist, u_char result[SHA256_DIGEST_LENGTH]) {
{ digest_all(detail::Hash_SHA256, vlist, result); } digest_all(detail::Hash_SHA256, vlist, result);
}
SHA256Val(); SHA256Val();
~SHA256Val(); ~SHA256Val();
@ -279,15 +296,15 @@ protected:
DECLARE_OPAQUE_VALUE(SHA256Val) DECLARE_OPAQUE_VALUE(SHA256Val)
private: private:
EVP_MD_CTX* ctx; EVP_MD_CTX* ctx;
}; };
class EntropyVal : public OpaqueVal { class EntropyVal : public OpaqueVal
{
public: public:
EntropyVal(); EntropyVal();
bool Feed(const void* data, size_t size); bool Feed(const void* data, size_t size);
bool Get(double *r_ent, double *r_chisq, double *r_mean, bool Get(double* r_ent, double* r_chisq, double* r_mean, double* r_montepicalc, double* r_scc);
double *r_montepicalc, double *r_scc);
protected: protected:
friend class Val; friend class Val;
@ -295,17 +312,17 @@ protected:
DECLARE_OPAQUE_VALUE(EntropyVal) DECLARE_OPAQUE_VALUE(EntropyVal)
private: private:
detail::RandTest state; detail::RandTest state;
}; };
class BloomFilterVal : public OpaqueVal { class BloomFilterVal : public OpaqueVal
{
public: public:
explicit BloomFilterVal(probabilistic::BloomFilter* bf); explicit BloomFilterVal(probabilistic::BloomFilter* bf);
~BloomFilterVal() override; ~BloomFilterVal() override;
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
const TypePtr& Type() const const TypePtr& Type() const { return type; }
{ return type; }
bool Typify(TypePtr type); bool Typify(TypePtr type);
@ -315,8 +332,7 @@ public:
bool Empty() const; bool Empty() const;
std::string InternalState() const; std::string InternalState() const;
static BloomFilterValPtr Merge(const BloomFilterVal* x, static BloomFilterValPtr Merge(const BloomFilterVal* x, const BloomFilterVal* y);
const BloomFilterVal* y);
protected: protected:
friend class Val; friend class Val;
@ -331,10 +347,10 @@ private:
TypePtr type; TypePtr type;
detail::CompositeHash* hash; detail::CompositeHash* hash;
probabilistic::BloomFilter* bloom_filter; probabilistic::BloomFilter* bloom_filter;
}; };
class CardinalityVal : public OpaqueVal
class CardinalityVal : public OpaqueVal { {
public: public:
explicit CardinalityVal(probabilistic::detail::CardinalityCounter*); explicit CardinalityVal(probabilistic::detail::CardinalityCounter*);
~CardinalityVal() override; ~CardinalityVal() override;
@ -343,12 +359,11 @@ public:
void Add(const Val* val); void Add(const Val* val);
const TypePtr& Type() const const TypePtr& Type() const { return type; }
{ return type; }
bool Typify(TypePtr type); bool Typify(TypePtr type);
probabilistic::detail::CardinalityCounter* Get() { return c; }; probabilistic::detail::CardinalityCounter* Get() { return c; };
protected: protected:
CardinalityVal(); CardinalityVal();
@ -358,28 +373,30 @@ private:
TypePtr type; TypePtr type;
detail::CompositeHash* hash; detail::CompositeHash* hash;
probabilistic::detail::CardinalityCounter* c; probabilistic::detail::CardinalityCounter* c;
}; };
class ParaglobVal : public OpaqueVal { class ParaglobVal : public OpaqueVal
{
public: public:
explicit ParaglobVal(std::unique_ptr<paraglob::Paraglob> p); explicit ParaglobVal(std::unique_ptr<paraglob::Paraglob> p);
VectorValPtr Get(StringVal* &pattern); VectorValPtr Get(StringVal*& pattern);
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
bool operator==(const ParaglobVal& other) const; bool operator==(const ParaglobVal& other) const;
protected: protected:
ParaglobVal() : OpaqueVal(paraglob_type) {} ParaglobVal() : OpaqueVal(paraglob_type) { }
DECLARE_OPAQUE_VALUE(ParaglobVal) DECLARE_OPAQUE_VALUE(ParaglobVal)
private: private:
std::unique_ptr<paraglob::Paraglob> internal_paraglob; std::unique_ptr<paraglob::Paraglob> internal_paraglob;
}; };
/** /**
* Base class for metric handles. Handle types are not serializable. * Base class for metric handles. Handle types are not serializable.
*/ */
class TelemetryVal : public OpaqueVal { class TelemetryVal : public OpaqueVal
{
protected: protected:
explicit TelemetryVal(telemetry::IntCounter); explicit TelemetryVal(telemetry::IntCounter);
explicit TelemetryVal(telemetry::IntCounterFamily); explicit TelemetryVal(telemetry::IntCounterFamily);
@ -396,34 +413,25 @@ protected:
broker::expected<broker::data> DoSerialize() const override; broker::expected<broker::data> DoSerialize() const override;
bool DoUnserialize(const broker::data& data) override; bool DoUnserialize(const broker::data& data) override;
}; };
template <class Handle> template <class Handle> class TelemetryValImpl : public TelemetryVal
class TelemetryValImpl : public TelemetryVal { {
public: public:
using HandleType = Handle; using HandleType = Handle;
explicit TelemetryValImpl(Handle hdl) : TelemetryVal(hdl), hdl(hdl) { } explicit TelemetryValImpl(Handle hdl) : TelemetryVal(hdl), hdl(hdl) { }
Handle GetHandle() const noexcept Handle GetHandle() const noexcept { return hdl; }
{
return hdl;
}
protected: protected:
ValPtr DoClone(CloneState*) override ValPtr DoClone(CloneState*) override { return make_intrusive<TelemetryValImpl>(hdl); }
{
return make_intrusive<TelemetryValImpl>(hdl);
}
const char* OpaqueName() const override const char* OpaqueName() const override { return Handle::OpaqueName; }
{
return Handle::OpaqueName;
}
private: private:
Handle hdl; Handle hdl;
}; };
using IntCounterMetricVal = TelemetryValImpl<telemetry::IntCounter>; using IntCounterMetricVal = TelemetryValImpl<telemetry::IntCounter>;
using IntCounterMetricFamilyVal = TelemetryValImpl<telemetry::IntCounterFamily>; using IntCounterMetricFamilyVal = TelemetryValImpl<telemetry::IntCounterFamily>;
@ -438,4 +446,4 @@ using IntHistogramMetricFamilyVal = TelemetryValImpl<telemetry::IntHistogramFami
using DblHistogramMetricVal = TelemetryValImpl<telemetry::DblHistogram>; using DblHistogramMetricVal = TelemetryValImpl<telemetry::DblHistogram>;
using DblHistogramMetricFamilyVal = TelemetryValImpl<telemetry::DblHistogramFamily>; using DblHistogramMetricFamilyVal = TelemetryValImpl<telemetry::DblHistogramFamily>;
} // namespace zeek } // namespace zeek

View file

@ -1,12 +1,12 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Options.h" #include "zeek/Options.h"
#include "zeek/script_opt/ScriptOpt.h"
#include <unistd.h> #include <unistd.h>
#include "zeek/script_opt/ScriptOpt.h"
#include "zeek/zeek-config.h"
#ifdef HAVE_GETOPT_H #ifdef HAVE_GETOPT_H
#include <getopt.h> #include <getopt.h>
#endif #endif
@ -19,7 +19,8 @@
#include "zeek/bsd-getopt-long.h" #include "zeek/bsd-getopt-long.h"
#include "zeek/logging/writers/ascii/Ascii.h" #include "zeek/logging/writers/ascii/Ascii.h"
namespace zeek { namespace zeek
{
void Options::filter_supervisor_options() void Options::filter_supervisor_options()
{ {
@ -84,22 +85,30 @@ void usage(const char* prog, int code)
fprintf(stderr, "usage: %s [options] [file ...]\n", prog); fprintf(stderr, "usage: %s [options] [file ...]\n", prog);
fprintf(stderr, "usage: %s --test [doctest-options] -- [options] [file ...]\n", prog); fprintf(stderr, "usage: %s --test [doctest-options] -- [options] [file ...]\n", prog);
fprintf(stderr, " <file> | Zeek script file, or read stdin\n"); fprintf(stderr, " <file> | Zeek script file, or read stdin\n");
fprintf(stderr, " -a|--parse-only | exit immediately after parsing scripts\n"); fprintf(stderr,
fprintf(stderr, " -b|--bare-mode | don't load scripts from the base/ directory\n"); " -a|--parse-only | exit immediately after parsing scripts\n");
fprintf(stderr,
" -b|--bare-mode | don't load scripts from the base/ directory\n");
fprintf(stderr, " -d|--debug-script | activate Zeek script debugging\n"); fprintf(stderr, " -d|--debug-script | activate Zeek script debugging\n");
fprintf(stderr, " -e|--exec <zeek code> | augment loaded scripts by given code\n"); fprintf(stderr, " -e|--exec <zeek code> | augment loaded scripts by given code\n");
fprintf(stderr, " -f|--filter <filter> | tcpdump filter\n"); fprintf(stderr, " -f|--filter <filter> | tcpdump filter\n");
fprintf(stderr, " -h|--help | command line help\n"); fprintf(stderr, " -h|--help | command line help\n");
fprintf(stderr, " -i|--iface <interface> | read from given interface (only one allowed)\n"); fprintf(stderr,
fprintf(stderr, " -p|--prefix <prefix> | add given prefix to Zeek script file resolution\n"); " -i|--iface <interface> | read from given interface (only one allowed)\n");
fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file (only one allowed, pass '-' as the filename to read from stdin)\n"); fprintf(
stderr,
" -p|--prefix <prefix> | add given prefix to Zeek script file resolution\n");
fprintf(stderr, " -r|--readfile <readfile> | read from given tcpdump file (only one "
"allowed, pass '-' as the filename to read from stdin)\n");
fprintf(stderr, " -s|--rulefile <rulefile> | read rules from given file\n"); fprintf(stderr, " -s|--rulefile <rulefile> | read rules from given file\n");
fprintf(stderr, " -t|--tracefile <tracefile> | activate execution tracing\n"); fprintf(stderr, " -t|--tracefile <tracefile> | activate execution tracing\n");
fprintf(stderr, " -u|--usage-issues | find variable usage issues and exit; use -uu for deeper/more expensive analysis\n"); fprintf(stderr, " -u|--usage-issues | find variable usage issues and exit; use "
"-uu for deeper/more expensive analysis\n");
fprintf(stderr, " -v|--version | print version and exit\n"); fprintf(stderr, " -v|--version | print version and exit\n");
fprintf(stderr, " -w|--writefile <writefile> | write to given tcpdump file\n"); fprintf(stderr, " -w|--writefile <writefile> | write to given tcpdump file\n");
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, " -B|--debug <dbgstreams> | Enable debugging output for selected streams ('-B help' for help)\n"); fprintf(stderr, " -B|--debug <dbgstreams> | Enable debugging output for selected "
"streams ('-B help' for help)\n");
#endif #endif
fprintf(stderr, " -C|--no-checksums | ignore checksums\n"); fprintf(stderr, " -C|--no-checksums | ignore checksums\n");
fprintf(stderr, " -D|--deterministic | initialize random seeds to zero\n"); fprintf(stderr, " -D|--deterministic | initialize random seeds to zero\n");
@ -107,35 +116,57 @@ void usage(const char* prog, int code)
fprintf(stderr, " -G|--load-seeds <file> | load seeds from given file\n"); fprintf(stderr, " -G|--load-seeds <file> | load seeds from given file\n");
fprintf(stderr, " -H|--save-seeds <file> | save seeds to given file\n"); fprintf(stderr, " -H|--save-seeds <file> | save seeds to given file\n");
fprintf(stderr, " -I|--print-id <ID name> | print out given ID\n"); fprintf(stderr, " -I|--print-id <ID name> | print out given ID\n");
fprintf(stderr, " -N|--print-plugins | print available plugins and exit (-NN for verbose)\n"); fprintf(stderr, " -N|--print-plugins | print available plugins and exit (-NN "
fprintf(stderr, " -O|--optimize[=<option>] | enable script optimization (use -O help for options)\n"); "for verbose)\n");
fprintf(stderr, " -o|--optimize-only=<func> | enable script optimization only for the given function\n"); fprintf(stderr, " -O|--optimize[=<option>] | enable script optimization (use -O help "
"for options)\n");
fprintf(stderr, " -o|--optimize-only=<func> | enable script optimization only for the "
"given function\n");
fprintf(stderr, " -P|--prime-dns | prime DNS\n"); fprintf(stderr, " -P|--prime-dns | prime DNS\n");
fprintf(stderr, " -Q|--time | print execution time summary to stderr\n"); fprintf(stderr,
" -Q|--time | print execution time summary to stderr\n");
fprintf(stderr, " -S|--debug-rules | enable rule debugging\n"); fprintf(stderr, " -S|--debug-rules | enable rule debugging\n");
fprintf(stderr, " -T|--re-level <level> | set 'RE_level' for rules\n"); fprintf(stderr, " -T|--re-level <level> | set 'RE_level' for rules\n");
fprintf(stderr, " -U|--status-file <file> | Record process status in file\n"); fprintf(stderr, " -U|--status-file <file> | Record process status in file\n");
fprintf(stderr, " -W|--watchdog | activate watchdog timer\n"); fprintf(stderr, " -W|--watchdog | activate watchdog timer\n");
fprintf(stderr, " -X|--zeekygen <cfgfile> | generate documentation based on config file\n"); fprintf(stderr,
" -X|--zeekygen <cfgfile> | generate documentation based on config file\n");
#ifdef USE_PERFTOOLS_DEBUG #ifdef USE_PERFTOOLS_DEBUG
fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n"); fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n");
fprintf(stderr, " -M|--mem-profile | record heap [perftools]\n"); fprintf(stderr, " -M|--mem-profile | record heap [perftools]\n");
#endif #endif
fprintf(stderr, " --pseudo-realtime[=<speedup>] | enable pseudo-realtime for performance evaluation (default 1)\n"); fprintf(stderr, " --pseudo-realtime[=<speedup>] | enable pseudo-realtime for performance "
"evaluation (default 1)\n");
fprintf(stderr, " -j|--jobs | enable supervisor mode\n"); fprintf(stderr, " -j|--jobs | enable supervisor mode\n");
fprintf(stderr, " --test | run unit tests ('--test -h' for help, only when compiling with ENABLE_ZEEK_UNIT_TESTS)\n"); fprintf(stderr, " --test | run unit tests ('--test -h' for help, "
fprintf(stderr, " $ZEEKPATH | file search path (%s)\n", util::zeek_path().c_str()); "only when compiling with ENABLE_ZEEK_UNIT_TESTS)\n");
fprintf(stderr, " $ZEEK_PLUGIN_PATH | plugin search path (%s)\n", util::zeek_plugin_path()); fprintf(stderr, " $ZEEKPATH | file search path (%s)\n",
fprintf(stderr, " $ZEEK_PLUGIN_ACTIVATE | plugins to always activate (%s)\n", util::zeek_plugin_activate()); util::zeek_path().c_str());
fprintf(stderr, " $ZEEK_PREFIXES | prefix list (%s)\n", util::zeek_prefixes().c_str()); fprintf(stderr, " $ZEEK_PLUGIN_PATH | plugin search path (%s)\n",
fprintf(stderr, " $ZEEK_DNS_FAKE | disable DNS lookups (%s)\n", fake_dns() ? "on" : "off"); util::zeek_plugin_path());
fprintf(stderr, " $ZEEK_PLUGIN_ACTIVATE | plugins to always activate (%s)\n",
util::zeek_plugin_activate());
fprintf(stderr, " $ZEEK_PREFIXES | prefix list (%s)\n",
util::zeek_prefixes().c_str());
fprintf(stderr, " $ZEEK_DNS_FAKE | disable DNS lookups (%s)\n",
fake_dns() ? "on" : "off");
fprintf(stderr, " $ZEEK_SEED_FILE | file to load seeds from (not set)\n"); fprintf(stderr, " $ZEEK_SEED_FILE | file to load seeds from (not set)\n");
fprintf(stderr, " $ZEEK_LOG_SUFFIX | ASCII log file extension (.%s)\n", logging::writer::detail::Ascii::LogExt().c_str()); fprintf(stderr, " $ZEEK_LOG_SUFFIX | ASCII log file extension (.%s)\n",
fprintf(stderr, " $ZEEK_PROFILER_FILE | Output file for script execution statistics (not set)\n"); logging::writer::detail::Ascii::LogExt().c_str());
fprintf(stderr, " $ZEEK_DISABLE_ZEEKYGEN | Disable Zeekygen documentation support (%s)\n", getenv("ZEEK_DISABLE_ZEEKYGEN") ? "set" : "not set"); fprintf(stderr, " $ZEEK_PROFILER_FILE | Output file for script execution "
fprintf(stderr, " $ZEEK_DNS_RESOLVER | IPv4/IPv6 address of DNS resolver to use (%s)\n", getenv("ZEEK_DNS_RESOLVER") ? getenv("ZEEK_DNS_RESOLVER") : "not set, will use first IPv4 address from /etc/resolv.conf"); "statistics (not set)\n");
fprintf(stderr, " $ZEEK_DEBUG_LOG_STDERR | Use stderr for debug logs generated via the -B flag"); fprintf(stderr,
" $ZEEK_DISABLE_ZEEKYGEN | Disable Zeekygen documentation support (%s)\n",
getenv("ZEEK_DISABLE_ZEEKYGEN") ? "set" : "not set");
fprintf(stderr,
" $ZEEK_DNS_RESOLVER | IPv4/IPv6 address of DNS resolver to use (%s)\n",
getenv("ZEEK_DNS_RESOLVER")
? getenv("ZEEK_DNS_RESOLVER")
: "not set, will use first IPv4 address from /etc/resolv.conf");
fprintf(
stderr,
" $ZEEK_DEBUG_LOG_STDERR | Use stderr for debug logs generated via the -B flag");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@ -152,7 +183,8 @@ static void print_analysis_help()
fprintf(stderr, " dump-uds dump use-defs to stdout; implies xform\n"); fprintf(stderr, " dump-uds dump use-defs to stdout; implies xform\n");
fprintf(stderr, " dump-xform dump transformed scripts to stdout; implies xform\n"); fprintf(stderr, " dump-xform dump transformed scripts to stdout; implies xform\n");
fprintf(stderr, " dump-ZAM dump generated ZAM code; implies gen-ZAM-code\n"); fprintf(stderr, " dump-ZAM dump generated ZAM code; implies gen-ZAM-code\n");
fprintf(stderr, " gen-ZAM-code generate ZAM code (without turning on additional optimizations)\n"); fprintf(stderr,
" gen-ZAM-code generate ZAM code (without turning on additional optimizations)\n");
fprintf(stderr, " inline inline function calls\n"); fprintf(stderr, " inline inline function calls\n");
fprintf(stderr, " no-ZAM-opt omit low-level ZAM optimization\n"); fprintf(stderr, " no-ZAM-opt omit low-level ZAM optimization\n");
fprintf(stderr, " optimize-all optimize all scripts, even inlined ones\n"); fprintf(stderr, " optimize-all optimize all scripts, even inlined ones\n");
@ -229,8 +261,7 @@ static void set_analysis_option(const char* opt, Options& opts)
else else
{ {
fprintf(stderr,"zeek: unrecognized -O/--optimize option: %s\n\n", fprintf(stderr, "zeek: unrecognized -O/--optimize option: %s\n\n", opt);
opt);
print_analysis_help(); print_analysis_help();
exit(1); exit(1);
} }
@ -251,17 +282,17 @@ Options parse_cmdline(int argc, char** argv)
if ( argc > 1 && strcmp(argv[1], "--test") == 0 ) if ( argc > 1 && strcmp(argv[1], "--test") == 0 )
{ {
#ifdef DOCTEST_CONFIG_DISABLE #ifdef DOCTEST_CONFIG_DISABLE
fprintf(stderr, "ERROR: C++ unit tests are disabled for this build.\n" fprintf(stderr, "ERROR: C++ unit tests are disabled for this build.\n"
" Please re-compile with ENABLE_ZEEK_UNIT_TESTS " " Please re-compile with ENABLE_ZEEK_UNIT_TESTS "
"to run the C++ unit tests.\n"); "to run the C++ unit tests.\n");
usage(argv[0], 1); usage(argv[0], 1);
#endif #endif
auto is_separator = [](const char* cstr) auto is_separator = [](const char* cstr)
{ {
return strcmp(cstr, "--") == 0; return strcmp(cstr, "--") == 0;
}; };
auto first = argv; auto first = argv;
auto last = argv + argc; auto last = argv + argc;
auto separator = std::find_if(first, last, is_separator); auto separator = std::find_if(first, last, is_separator);
@ -285,9 +316,10 @@ Options parse_cmdline(int argc, char** argv)
if ( argc > 1 ) if ( argc > 1 )
{ {
auto endsWith = [](const std::string& str, const std::string& suffix) auto endsWith = [](const std::string& str, const std::string& suffix)
{ {
return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix); return str.size() >= suffix.size() &&
}; 0 == str.compare(str.size() - suffix.size(), suffix.size(), suffix);
};
auto i = 0; auto i = 0;
for ( ; i < argc && ! endsWith(argv[i], "--"); ++i ) for ( ; i < argc && ! endsWith(argv[i], "--"); ++i )
@ -327,53 +359,53 @@ Options parse_cmdline(int argc, char** argv)
} }
constexpr struct option long_opts[] = { constexpr struct option long_opts[] = {
{"parse-only", no_argument, nullptr, 'a'}, {"parse-only", no_argument, nullptr, 'a'},
{"bare-mode", no_argument, nullptr, 'b'}, {"bare-mode", no_argument, nullptr, 'b'},
{"debug-script", no_argument, nullptr, 'd'}, {"debug-script", no_argument, nullptr, 'd'},
{"exec", required_argument, nullptr, 'e'}, {"exec", required_argument, nullptr, 'e'},
{"filter", required_argument, nullptr, 'f'}, {"filter", required_argument, nullptr, 'f'},
{"help", no_argument, nullptr, 'h'}, {"help", no_argument, nullptr, 'h'},
{"iface", required_argument, nullptr, 'i'}, {"iface", required_argument, nullptr, 'i'},
{"zeekygen", required_argument, nullptr, 'X'}, {"zeekygen", required_argument, nullptr, 'X'},
{"prefix", required_argument, nullptr, 'p'}, {"prefix", required_argument, nullptr, 'p'},
{"readfile", required_argument, nullptr, 'r'}, {"readfile", required_argument, nullptr, 'r'},
{"rulefile", required_argument, nullptr, 's'}, {"rulefile", required_argument, nullptr, 's'},
{"tracefile", required_argument, nullptr, 't'}, {"tracefile", required_argument, nullptr, 't'},
{"writefile", required_argument, nullptr, 'w'}, {"writefile", required_argument, nullptr, 'w'},
{"usage-issues", no_argument, nullptr, 'u'}, {"usage-issues", no_argument, nullptr, 'u'},
{"version", no_argument, nullptr, 'v'}, {"version", no_argument, nullptr, 'v'},
{"no-checksums", no_argument, nullptr, 'C'}, {"no-checksums", no_argument, nullptr, 'C'},
{"force-dns", no_argument, nullptr, 'F'}, {"force-dns", no_argument, nullptr, 'F'},
{"deterministic", no_argument, nullptr, 'D'}, {"deterministic", no_argument, nullptr, 'D'},
{"load-seeds", required_argument, nullptr, 'G'}, {"load-seeds", required_argument, nullptr, 'G'},
{"save-seeds", required_argument, nullptr, 'H'}, {"save-seeds", required_argument, nullptr, 'H'},
{"print-plugins", no_argument, nullptr, 'N'}, {"print-plugins", no_argument, nullptr, 'N'},
{"optimize", required_argument, nullptr, 'O'}, {"optimize", required_argument, nullptr, 'O'},
{"optimize-only", required_argument, nullptr, 'o'}, {"optimize-only", required_argument, nullptr, 'o'},
{"prime-dns", no_argument, nullptr, 'P'}, {"prime-dns", no_argument, nullptr, 'P'},
{"time", no_argument, nullptr, 'Q'}, {"time", no_argument, nullptr, 'Q'},
{"debug-rules", no_argument, nullptr, 'S'}, {"debug-rules", no_argument, nullptr, 'S'},
{"re-level", required_argument, nullptr, 'T'}, {"re-level", required_argument, nullptr, 'T'},
{"watchdog", no_argument, nullptr, 'W'}, {"watchdog", no_argument, nullptr, 'W'},
{"print-id", required_argument, nullptr, 'I'}, {"print-id", required_argument, nullptr, 'I'},
{"status-file", required_argument, nullptr, 'U'}, {"status-file", required_argument, nullptr, 'U'},
{"debug", required_argument, nullptr, 'B'}, {"debug", required_argument, nullptr, 'B'},
#ifdef USE_PERFTOOLS_DEBUG #ifdef USE_PERFTOOLS_DEBUG
{"mem-leaks", no_argument, nullptr, 'm'}, {"mem-leaks", no_argument, nullptr, 'm'},
{"mem-profile", no_argument, nullptr, 'M'}, {"mem-profile", no_argument, nullptr, 'M'},
#endif #endif
{"pseudo-realtime", optional_argument, nullptr, 'E'}, {"pseudo-realtime", optional_argument, nullptr, 'E'},
{"jobs", optional_argument, nullptr, 'j'}, {"jobs", optional_argument, nullptr, 'j'},
{"test", no_argument, nullptr, '#'}, {"test", no_argument, nullptr, '#'},
{nullptr, 0, nullptr, 0}, {nullptr, 0, nullptr, 0},
}; };
char opts[256]; char opts[256];
util::safe_strncpy(opts, "B:e:f:G:H:I:i:j::n:O:o:p:r:s:T:t:U:w:X:CDFMNPQSWabdhmuv", util::safe_strncpy(opts, "B:e:f:G:H:I:i:j::n:O:o:p:r:s:T:t:U:w:X:CDFMNPQSWabdhmuv",
sizeof(opts)); sizeof(opts));
int op; int op;
int long_optsind; int long_optsind;
@ -385,178 +417,180 @@ Options parse_cmdline(int argc, char** argv)
for ( size_t i = 0; i < zeek_args.size(); ++i ) for ( size_t i = 0; i < zeek_args.size(); ++i )
zargs[i] = zeek_args[i].data(); zargs[i] = zeek_args[i].data();
while ( (op = getopt_long(zeek_args.size(), zargs.get(), opts, long_opts, &long_optsind)) != EOF ) while ( (op = getopt_long(zeek_args.size(), zargs.get(), opts, long_opts, &long_optsind)) !=
switch ( op ) { EOF )
case 'a': switch ( op )
rval.parse_only = true; {
break; case 'a':
case 'b': rval.parse_only = true;
rval.bare_mode = true; break;
break; case 'b':
case 'd': rval.bare_mode = true;
rval.debug_scripts = true; break;
break; case 'd':
case 'e': rval.debug_scripts = true;
rval.script_code_to_exec = optarg; break;
break; case 'e':
case 'f': rval.script_code_to_exec = optarg;
rval.pcap_filter = optarg; break;
break; case 'f':
case 'h': rval.pcap_filter = optarg;
rval.print_usage = true; break;
break; case 'h':
case 'i': rval.print_usage = true;
if ( rval.interface ) break;
{ case 'i':
fprintf(stderr, "ERROR: Only a single interface option (-i) is allowed.\n"); if ( rval.interface )
exit(1); {
} fprintf(stderr, "ERROR: Only a single interface option (-i) is allowed.\n");
if ( rval.pcap_file )
{
fprintf(stderr, "ERROR: Using -i is not allow when reading a pcap file.\n");
exit(1);
}
rval.interface = optarg;
break;
case 'j':
rval.supervisor_mode = true;
if ( optarg )
{
// TODO: for supervised offline pcap reading, the argument is
// expected to be number of workers like "-j 4" or possibly a
// list of worker/proxy/logger counts like "-j 4,2,1"
}
break;
case 'p':
rval.script_prefixes.emplace_back(optarg);
break;
case 'r':
if ( rval.pcap_file )
{
fprintf(stderr, "ERROR: Only a single readfile option (-r) is allowed.\n");
exit(1);
}
if ( rval.interface )
{
fprintf(stderr, "Using -r is not allowed when reading a live interface.\n");
exit(1);
}
rval.pcap_file = optarg;
break;
case 's':
rval.signature_files.emplace_back(optarg);
break;
case 't':
rval.debug_script_tracing_file = optarg;
break;
case 'u':
++rval.analysis_options.usage_issues;
break;
case 'v':
rval.print_version = true;
break;
case 'w':
rval.pcap_output_file = optarg;
break;
case 'B':
#ifdef DEBUG
rval.debug_log_streams = optarg;
#else
if ( util::streq(optarg, "help") )
{
fprintf(stderr,"debug streams unavailable\n");
exit(1); exit(1);
} }
#endif
break;
case 'C': if ( rval.pcap_file )
rval.ignore_checksums = true; {
break; fprintf(stderr, "ERROR: Using -i is not allow when reading a pcap file.\n");
case 'D': exit(1);
rval.deterministic_mode = true; }
break;
case 'E': rval.interface = optarg;
rval.pseudo_realtime = 1.0; break;
if ( optarg ) case 'j':
rval.pseudo_realtime = atof(optarg); rval.supervisor_mode = true;
break; if ( optarg )
case 'F': {
if ( rval.dns_mode != detail::DNS_DEFAULT ) // TODO: for supervised offline pcap reading, the argument is
usage(zargs[0], 1); // expected to be number of workers like "-j 4" or possibly a
rval.dns_mode = detail::DNS_FORCE; // list of worker/proxy/logger counts like "-j 4,2,1"
break; }
case 'G': break;
rval.random_seed_input_file = optarg; case 'p':
break; rval.script_prefixes.emplace_back(optarg);
case 'H': break;
rval.random_seed_output_file = optarg; case 'r':
break; if ( rval.pcap_file )
case 'I': {
rval.identifier_to_print = optarg; fprintf(stderr, "ERROR: Only a single readfile option (-r) is allowed.\n");
break; exit(1);
case 'N': }
++rval.print_plugins;
break; if ( rval.interface )
case 'O': {
set_analysis_option(optarg, rval); fprintf(stderr, "Using -r is not allowed when reading a live interface.\n");
break; exit(1);
case 'o': }
rval.analysis_options.only_func = optarg;
break; rval.pcap_file = optarg;
case 'P': break;
if ( rval.dns_mode != detail::DNS_DEFAULT ) case 's':
usage(zargs[0], 1); rval.signature_files.emplace_back(optarg);
rval.dns_mode = detail::DNS_PRIME; break;
break; case 't':
case 'Q': rval.debug_script_tracing_file = optarg;
rval.print_execution_time = true; break;
break; case 'u':
case 'S': ++rval.analysis_options.usage_issues;
rval.print_signature_debug_info = true; break;
break; case 'v':
case 'T': rval.print_version = true;
rval.signature_re_level = atoi(optarg); break;
break; case 'w':
case 'U': rval.pcap_output_file = optarg;
rval.process_status_file = optarg; break;
break;
case 'W': case 'B':
rval.use_watchdog = true; #ifdef DEBUG
break; rval.debug_log_streams = optarg;
case 'X': #else
rval.zeekygen_config_file = optarg; if ( util::streq(optarg, "help") )
break; {
fprintf(stderr, "debug streams unavailable\n");
exit(1);
}
#endif
break;
case 'C':
rval.ignore_checksums = true;
break;
case 'D':
rval.deterministic_mode = true;
break;
case 'E':
rval.pseudo_realtime = 1.0;
if ( optarg )
rval.pseudo_realtime = atof(optarg);
break;
case 'F':
if ( rval.dns_mode != detail::DNS_DEFAULT )
usage(zargs[0], 1);
rval.dns_mode = detail::DNS_FORCE;
break;
case 'G':
rval.random_seed_input_file = optarg;
break;
case 'H':
rval.random_seed_output_file = optarg;
break;
case 'I':
rval.identifier_to_print = optarg;
break;
case 'N':
++rval.print_plugins;
break;
case 'O':
set_analysis_option(optarg, rval);
break;
case 'o':
rval.analysis_options.only_func = optarg;
break;
case 'P':
if ( rval.dns_mode != detail::DNS_DEFAULT )
usage(zargs[0], 1);
rval.dns_mode = detail::DNS_PRIME;
break;
case 'Q':
rval.print_execution_time = true;
break;
case 'S':
rval.print_signature_debug_info = true;
break;
case 'T':
rval.signature_re_level = atoi(optarg);
break;
case 'U':
rval.process_status_file = optarg;
break;
case 'W':
rval.use_watchdog = true;
break;
case 'X':
rval.zeekygen_config_file = optarg;
break;
#ifdef USE_PERFTOOLS_DEBUG #ifdef USE_PERFTOOLS_DEBUG
case 'm': case 'm':
rval.perftools_check_leaks = 1; rval.perftools_check_leaks = 1;
break; break;
case 'M': case 'M':
rval.perftools_profile = 1; rval.perftools_profile = 1;
break; break;
#endif #endif
case '#': case '#':
fprintf(stderr, "ERROR: --test only allowed as first argument.\n"); fprintf(stderr, "ERROR: --test only allowed as first argument.\n");
usage(zargs[0], 1); usage(zargs[0], 1);
break; break;
case 0: case 0:
// This happens for long options that don't have // This happens for long options that don't have
// a short-option equivalent. // a short-option equivalent.
break; break;
case '?': case '?':
default: default:
usage(zargs[0], 1); usage(zargs[0], 1);
break; break;
} }
// Process remaining arguments. X=Y arguments indicate script // Process remaining arguments. X=Y arguments indicate script
// variable/parameter assignments. X::Y arguments indicate plugins to // variable/parameter assignments. X::Y arguments indicate plugins to
@ -572,7 +606,7 @@ Options parse_cmdline(int argc, char** argv)
} }
auto canonify_script_path = [](std::string* path) auto canonify_script_path = [](std::string* path)
{ {
if ( path->empty() ) if ( path->empty() )
return; return;
@ -605,13 +639,12 @@ Options parse_cmdline(int argc, char** argv)
if ( ! getcwd(cwd, sizeof(cwd)) ) if ( ! getcwd(cwd, sizeof(cwd)) )
{ {
fprintf(stderr, "failed to get current directory: %s\n", fprintf(stderr, "failed to get current directory: %s\n", strerror(errno));
strerror(errno));
exit(1); exit(1);
} }
*path = std::string(cwd) + "/" + *path; *path = std::string(cwd) + "/" + *path;
}; };
if ( rval.supervisor_mode ) if ( rval.supervisor_mode )
{ {
@ -625,4 +658,4 @@ Options parse_cmdline(int argc, char** argv)
return rval; return rval;
} }
} // namespace zeek } // namespace zeek

View file

@ -9,13 +9,15 @@
#include "zeek/DNS_Mgr.h" #include "zeek/DNS_Mgr.h"
#include "zeek/script_opt/ScriptOpt.h" #include "zeek/script_opt/ScriptOpt.h"
namespace zeek { namespace zeek
{
/** /**
* Options that define general Zeek processing behavior, usually determined * Options that define general Zeek processing behavior, usually determined
* from command-line arguments. * from command-line arguments.
*/ */
struct Options { struct Options
{
/** /**
* Unset options that aren't meant to be used by the supervisor, but may * Unset options that aren't meant to be used by the supervisor, but may
* make sense for supervised nodes to inherit (as opposed to flagging * make sense for supervised nodes to inherit (as opposed to flagging
@ -40,7 +42,7 @@ struct Options {
std::optional<std::string> identifier_to_print; std::optional<std::string> identifier_to_print;
std::optional<std::string> script_code_to_exec; std::optional<std::string> script_code_to_exec;
std::vector<std::string> script_prefixes = { "" }; // "" = "no prefix" std::vector<std::string> script_prefixes = {""}; // "" = "no prefix"
int signature_re_level = 4; int signature_re_level = 4;
bool ignore_checksums = false; bool ignore_checksums = false;
@ -79,7 +81,7 @@ struct Options {
// For script optimization: // For script optimization:
detail::AnalyOpt analysis_options; detail::AnalyOpt analysis_options;
}; };
/** /**
* Parse Zeek command-line arguments. * Parse Zeek command-line arguments.
@ -101,4 +103,4 @@ void usage(const char* prog, int code = 1);
*/ */
bool fake_dns(); bool fake_dns();
} // namespace zeek } // namespace zeek

View file

@ -1,12 +1,13 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/Overflow.h" #include "zeek/Overflow.h"
#include "zeek/Val.h" #include "zeek/Val.h"
namespace zeek::detail { namespace zeek::detail
{
bool would_overflow(const zeek::Type* from_type, const zeek::Type* to_type, bool would_overflow(const zeek::Type* from_type, const zeek::Type* to_type, const Val* val)
const Val* val)
{ {
if ( ! to_type || ! from_type ) if ( ! to_type || ! from_type )
return true; return true;
@ -36,4 +37,4 @@ bool would_overflow(const zeek::Type* from_type, const zeek::Type* to_type,
return false; return false;
} }
} }

View file

@ -4,7 +4,8 @@
#include "zeek/Type.h" #include "zeek/Type.h"
namespace zeek::detail { namespace zeek::detail
{
inline bool double_to_count_would_overflow(double v) inline bool double_to_count_would_overflow(double v)
{ {
@ -18,8 +19,7 @@ inline bool int_to_count_would_overflow(bro_int_t v)
inline bool double_to_int_would_overflow(double v) inline bool double_to_int_would_overflow(double v)
{ {
return v < static_cast<double>(INT64_MIN) || return v < static_cast<double>(INT64_MIN) || v > static_cast<double>(INT64_MAX);
v > static_cast<double>(INT64_MAX);
} }
inline bool count_to_int_would_overflow(bro_uint_t v) inline bool count_to_int_would_overflow(bro_uint_t v)
@ -27,7 +27,6 @@ inline bool count_to_int_would_overflow(bro_uint_t v)
return v > INT64_MAX; return v > INT64_MAX;
} }
extern bool would_overflow(const zeek::Type* from_type, extern bool would_overflow(const zeek::Type* from_type, const zeek::Type* to_type, const Val* val);
const zeek::Type* to_type, const Val* val);
} }

View file

@ -1,7 +1,9 @@
#include "zeek/PacketFilter.h" #include "zeek/PacketFilter.h"
#include "zeek/IP.h" #include "zeek/IP.h"
namespace zeek::detail { namespace zeek::detail
{
void PacketFilter::DeleteFilter(void* data) void PacketFilter::DeleteFilter(void* data)
{ {
@ -82,40 +84,39 @@ bool PacketFilter::RemoveDst(Val* dst)
bool PacketFilter::Match(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen) bool PacketFilter::Match(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen)
{ {
Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(), 128); Filter* f = (Filter*)src_filter.Lookup(ip->SrcAddr(), 128);
if ( f ) if ( f )
return MatchFilter(*f, *ip, len, caplen); return MatchFilter(*f, *ip, len, caplen);
f = (Filter*) dst_filter.Lookup(ip->DstAddr(), 128); f = (Filter*)dst_filter.Lookup(ip->DstAddr(), 128);
if ( f ) if ( f )
return MatchFilter(*f, *ip, len, caplen); return MatchFilter(*f, *ip, len, caplen);
return default_match; return default_match;
} }
bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip, bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip, int len, int caplen)
int len, int caplen)
{ {
if ( ip.NextProto() == IPPROTO_TCP && f.tcp_flags ) if ( ip.NextProto() == IPPROTO_TCP && f.tcp_flags )
{ {
// Caution! The packet sanity checks have not been performed yet // Caution! The packet sanity checks have not been performed yet
int ip_hdr_len = ip.HdrLen(); int ip_hdr_len = ip.HdrLen();
len -= ip_hdr_len; // remove IP header len -= ip_hdr_len; // remove IP header
caplen -= ip_hdr_len; caplen -= ip_hdr_len;
if ( (unsigned int) len < sizeof(struct tcphdr) || if ( (unsigned int)len < sizeof(struct tcphdr) ||
(unsigned int) caplen < sizeof(struct tcphdr) ) (unsigned int)caplen < sizeof(struct tcphdr) )
// Packet too short, will be dropped anyway. // Packet too short, will be dropped anyway.
return false; return false;
const struct tcphdr* tp = (const struct tcphdr*) ip.Payload(); const struct tcphdr* tp = (const struct tcphdr*)ip.Payload();
if ( tp->th_flags & f.tcp_flags ) if ( tp->th_flags & f.tcp_flags )
// At least one of the flags is set, so don't drop // At least one of the flags is set, so don't drop
return false; return false;
} }
return util::detail::random_number() < f.probability; return util::detail::random_number() < f.probability;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -7,17 +7,20 @@
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
#include "zeek/PrefixTable.h" #include "zeek/PrefixTable.h"
namespace zeek { namespace zeek
{
class IP_Hdr; class IP_Hdr;
class Val; class Val;
namespace detail { namespace detail
{
class PacketFilter { class PacketFilter
{
public: public:
explicit PacketFilter(bool arg_default); explicit PacketFilter(bool arg_default);
~PacketFilter() {} ~PacketFilter() { }
// Drops all packets from a particular source (which may be given // Drops all packets from a particular source (which may be given
// as an AddrVal or a SubnetVal) which hasn't any of TCP flags set // as an AddrVal or a SubnetVal) which hasn't any of TCP flags set
@ -38,10 +41,11 @@ public:
bool Match(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen); bool Match(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen);
private: private:
struct Filter { struct Filter
{
uint32_t tcp_flags; uint32_t tcp_flags;
double probability; double probability;
}; };
static void DeleteFilter(void* data); static void DeleteFilter(void* data);
@ -50,7 +54,7 @@ private:
bool default_match; bool default_match;
PrefixTable src_filter; PrefixTable src_filter;
PrefixTable dst_filter; PrefixTable dst_filter;
}; };
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -2,14 +2,15 @@
#include "zeek/Pipe.h" #include "zeek/Pipe.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio> #include <cstdio>
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
namespace zeek::detail { namespace zeek::detail
{
static void pipe_fail(int eno) static void pipe_fail(int eno)
{ {
@ -88,8 +89,7 @@ static int dup_or_fail(int fd, int flags, int status_flags)
return rval; return rval;
} }
Pipe::Pipe(int flags0, int flags1, int status_flags0, int status_flags1, Pipe::Pipe(int flags0, int flags1, int status_flags0, int status_flags1, int* arg_fds)
int* arg_fds)
{ {
if ( arg_fds ) if ( arg_fds )
{ {
@ -155,8 +155,8 @@ Pipe& Pipe::operator=(const Pipe& other)
PipePair::PipePair(int flags, int status_flags, int* fds) PipePair::PipePair(int flags, int status_flags, int* fds)
: pipes{Pipe(flags, flags, status_flags, status_flags, fds ? fds + 0 : nullptr), : pipes{Pipe(flags, flags, status_flags, status_flags, fds ? fds + 0 : nullptr),
Pipe(flags, flags, status_flags, status_flags, fds ? fds + 2 : nullptr)} Pipe(flags, flags, status_flags, status_flags, fds ? fds + 2 : nullptr)}
{ {
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,11 +2,12 @@
#pragma once #pragma once
namespace zeek::detail { namespace zeek::detail
{
class Pipe { class Pipe
{
public: public:
/** /**
* Create a pair of file descriptors via pipe(), or aborts if it cannot. * Create a pair of file descriptors via pipe(), or aborts if it cannot.
* @param flags0 file descriptor flags to set on read end of pipe. * @param flags0 file descriptor flags to set on read end of pipe.
@ -17,12 +18,12 @@ public:
* than create ones from a new pipe. Should point to memory containing * than create ones from a new pipe. Should point to memory containing
* two consecutive file descriptors, the "read" one and then the "write" one. * two consecutive file descriptors, the "read" one and then the "write" one.
*/ */
explicit Pipe(int flags0 = 0, int flags1 = 0, int status_flags0 = 0, explicit Pipe(int flags0 = 0, int flags1 = 0, int status_flags0 = 0, int status_flags1 = 0,
int status_flags1 = 0, int* fds = nullptr); int* fds = nullptr);
/** /**
* Close the pair of file descriptors owned by the object. * Close the pair of file descriptors owned by the object.
*/ */
~Pipe(); ~Pipe();
/** /**
@ -39,14 +40,12 @@ public:
/** /**
* @return the file descriptor associated with the read-end of the pipe. * @return the file descriptor associated with the read-end of the pipe.
*/ */
int ReadFD() const int ReadFD() const { return fds[0]; }
{ return fds[0]; }
/** /**
* @return the file descriptor associated with the write-end of the pipe. * @return the file descriptor associated with the write-end of the pipe.
*/ */
int WriteFD() const int WriteFD() const { return fds[1]; }
{ return fds[1]; }
/** /**
* Sets the given file descriptor flags for both the read and write end * Sets the given file descriptor flags for both the read and write end
@ -64,14 +63,14 @@ private:
int fds[2]; int fds[2];
int flags[2]; int flags[2];
int status_flags[2]; int status_flags[2];
}; };
/** /**
* A pair of pipes that can be used for bi-directinoal IPC. * A pair of pipes that can be used for bi-directinoal IPC.
*/ */
class PipePair { class PipePair
{
public: public:
/** /**
* Create a pair of pipes * Create a pair of pipes
* @param flags file descriptor flags to set on pipes * @param flags file descriptor flags to set on pipes
@ -87,53 +86,45 @@ public:
/** /**
* @return the pipe used for receiving input * @return the pipe used for receiving input
*/ */
Pipe& In() Pipe& In() { return pipes[swapped]; }
{ return pipes[swapped]; }
/** /**
* @return the pipe used for sending output * @return the pipe used for sending output
*/ */
Pipe& Out() Pipe& Out() { return pipes[! swapped]; }
{ return pipes[!swapped]; }
/** /**
* @return the pipe used for receiving input * @return the pipe used for receiving input
*/ */
const Pipe& In() const const Pipe& In() const { return pipes[swapped]; }
{ return pipes[swapped]; }
/** /**
* @return the pipe used for sending output * @return the pipe used for sending output
*/ */
const Pipe& Out() const const Pipe& Out() const { return pipes[! swapped]; }
{ return pipes[!swapped]; }
/** /**
* @return a file descriptor that may used for receiving messages by * @return a file descriptor that may used for receiving messages by
* polling/reading it. * polling/reading it.
*/ */
int InFD() const int InFD() const { return In().ReadFD(); }
{ return In().ReadFD(); }
/** /**
* @return a file descriptor that may be used for sending messages by * @return a file descriptor that may be used for sending messages by
* writing to it. * writing to it.
*/ */
int OutFD() const int OutFD() const { return Out().WriteFD(); }
{ return Out().WriteFD(); }
/** /**
* Swaps the meaning of the pipes in the pair. E.g. call this after * Swaps the meaning of the pipes in the pair. E.g. call this after
* fork()'ing so that the child process uses the right pipe for * fork()'ing so that the child process uses the right pipe for
* reading/writing. * reading/writing.
*/ */
void Swap() void Swap() { swapped = ! swapped; }
{ swapped = ! swapped; }
private: private:
Pipe pipes[2]; Pipe pipes[2];
bool swapped = false; bool swapped = false;
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,35 +1,44 @@
#include "zeek/zeek-config.h"
#include "zeek/PolicyFile.h" #include "zeek/PolicyFile.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h> #include <assert.h>
#include <stdio.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#include "zeek/Debug.h" #include "zeek/Debug.h"
#include "zeek/util.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/util.h"
#include "zeek/zeek-config.h"
using namespace std; using namespace std;
struct PolicyFile { struct PolicyFile
PolicyFile () { filedata = nullptr; lmtime = 0; } {
~PolicyFile () { delete [] filedata; filedata = nullptr; } PolicyFile()
{
filedata = nullptr;
lmtime = 0;
}
~PolicyFile()
{
delete[] filedata;
filedata = nullptr;
}
time_t lmtime; time_t lmtime;
char* filedata; char* filedata;
vector<const char*> lines; vector<const char*> lines;
}; };
typedef map<string, PolicyFile*> PolicyFileMap; typedef map<string, PolicyFile*> PolicyFileMap;
static PolicyFileMap policy_files; static PolicyFileMap policy_files;
namespace zeek::detail { namespace zeek::detail
{
int how_many_lines_in(const char* policy_filename) int how_many_lines_in(const char* policy_filename)
{ {
@ -97,9 +106,9 @@ bool LoadPolicyFileText(const char* policy_filename)
// ### This code is not necessarily Unicode safe! // ### This code is not necessarily Unicode safe!
// (probably fine with UTF-8) // (probably fine with UTF-8)
pf->filedata = new char[size+1]; pf->filedata = new char[size + 1];
if ( fread(pf->filedata, size, 1, f) != 1 ) if ( fread(pf->filedata, size, 1, f) != 1 )
reporter->InternalError("Failed to fread() file data"); reporter->InternalError("Failed to fread() file data");
pf->filedata[size] = 0; pf->filedata[size] = 0;
fclose(f); fclose(f);
@ -122,8 +131,8 @@ bool LoadPolicyFileText(const char* policy_filename)
} }
// REMEMBER: line number arguments are indexed from 0. // REMEMBER: line number arguments are indexed from 0.
bool PrintLines(const char* policy_filename, unsigned int start_line, bool PrintLines(const char* policy_filename, unsigned int start_line, unsigned int how_many_lines,
unsigned int how_many_lines, bool show_numbers) bool show_numbers)
{ {
if ( ! policy_filename ) if ( ! policy_filename )
return true; return true;
@ -157,8 +166,8 @@ bool PrintLines(const char* policy_filename, unsigned int start_line,
if ( start_line > pf->lines.size() ) if ( start_line > pf->lines.size() )
{ {
debug_msg("Line number %d out of range; %s has %d lines\n", debug_msg("Line number %d out of range; %s has %d lines\n", start_line, policy_filename,
start_line, policy_filename, int(pf->lines.size())); int(pf->lines.size()));
return false; return false;
} }
@ -177,4 +186,4 @@ bool PrintLines(const char* policy_filename, unsigned int start_line,
return true; return true;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -14,14 +14,15 @@
// policy_filename arguments should be absolute or relative paths; // policy_filename arguments should be absolute or relative paths;
// no expansion is done. // no expansion is done.
namespace zeek::detail { namespace zeek::detail
{
int how_many_lines_in(const char* policy_filename); int how_many_lines_in(const char* policy_filename);
bool LoadPolicyFileText(const char* policy_filename); bool LoadPolicyFileText(const char* policy_filename);
// start_line is 1-based (the intuitive way) // start_line is 1-based (the intuitive way)
bool PrintLines(const char* policy_filename, unsigned int start_line, bool PrintLines(const char* policy_filename, unsigned int start_line, unsigned int how_many_lines,
unsigned int how_many_lines, bool show_numbers); bool show_numbers);
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,12 +1,14 @@
#include "zeek/PrefixTable.h" #include "zeek/PrefixTable.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/Val.h" #include "zeek/Val.h"
namespace zeek::detail { namespace zeek::detail
{
prefix_t* PrefixTable::MakePrefix(const IPAddr& addr, int width) prefix_t* PrefixTable::MakePrefix(const IPAddr& addr, int width)
{ {
prefix_t* prefix = (prefix_t*) util::safe_malloc(sizeof(prefix_t)); prefix_t* prefix = (prefix_t*)util::safe_malloc(sizeof(prefix_t));
addr.CopyIPv6(&prefix->add.sin6); addr.CopyIPv6(&prefix->add.sin6);
prefix->family = AF_INET6; prefix->family = AF_INET6;
@ -18,8 +20,9 @@ prefix_t* PrefixTable::MakePrefix(const IPAddr& addr, int width)
IPPrefix PrefixTable::PrefixToIPPrefix(prefix_t* prefix) IPPrefix PrefixTable::PrefixToIPPrefix(prefix_t* prefix)
{ {
return IPPrefix(IPAddr(IPv6, reinterpret_cast<const uint32_t*>(&prefix->add.sin6), return IPPrefix(
IPAddr::Network), prefix->bitlen, true); IPAddr(IPv6, reinterpret_cast<const uint32_t*>(&prefix->add.sin6), IPAddr::Network),
prefix->bitlen, true);
} }
void* PrefixTable::Insert(const IPAddr& addr, int width, void* data) void* PrefixTable::Insert(const IPAddr& addr, int width, void* data)
@ -46,29 +49,28 @@ void* PrefixTable::Insert(const IPAddr& addr, int width, void* data)
void* PrefixTable::Insert(const Val* value, void* data) void* PrefixTable::Insert(const Val* value, void* data)
{ {
// [elem] -> elem // [elem] -> elem
if ( value->GetType()->Tag() == TYPE_LIST && if ( value->GetType()->Tag() == TYPE_LIST && value->AsListVal()->Length() == 1 )
value->AsListVal()->Length() == 1 )
value = value->AsListVal()->Idx(0).get(); value = value->AsListVal()->Idx(0).get();
switch ( value->GetType()->Tag() ) { switch ( value->GetType()->Tag() )
case TYPE_ADDR: {
return Insert(value->AsAddr(), 128, data); case TYPE_ADDR:
break; return Insert(value->AsAddr(), 128, data);
break;
case TYPE_SUBNET: case TYPE_SUBNET:
return Insert(value->AsSubNet().Prefix(), return Insert(value->AsSubNet().Prefix(), value->AsSubNet().LengthIPv6(), data);
value->AsSubNet().LengthIPv6(), data); break;
break;
default: default:
reporter->InternalWarning("Wrong index type for PrefixTable"); reporter->InternalWarning("Wrong index type for PrefixTable");
return nullptr; return nullptr;
} }
} }
std::list<std::tuple<IPPrefix,void*>> PrefixTable::FindAll(const IPAddr& addr, int width) const std::list<std::tuple<IPPrefix, void*>> PrefixTable::FindAll(const IPAddr& addr, int width) const
{ {
std::list<std::tuple<IPPrefix,void*>> out; std::list<std::tuple<IPPrefix, void*>> out;
prefix_t* prefix = MakePrefix(addr, width); prefix_t* prefix = MakePrefix(addr, width);
int elems = 0; int elems = 0;
@ -84,7 +86,7 @@ std::list<std::tuple<IPPrefix,void*>> PrefixTable::FindAll(const IPAddr& addr, i
return out; return out;
} }
std::list<std::tuple<IPPrefix,void*>> PrefixTable::FindAll(const SubNetVal* value) const std::list<std::tuple<IPPrefix, void*>> PrefixTable::FindAll(const SubNetVal* value) const
{ {
return FindAll(value->AsSubNet().Prefix(), value->AsSubNet().LengthIPv6()); return FindAll(value->AsSubNet().Prefix(), value->AsSubNet().LengthIPv6());
} }
@ -93,8 +95,7 @@ void* PrefixTable::Lookup(const IPAddr& addr, int width, bool exact) const
{ {
prefix_t* prefix = MakePrefix(addr, width); prefix_t* prefix = MakePrefix(addr, width);
patricia_node_t* node = patricia_node_t* node =
exact ? patricia_search_exact(tree, prefix) : exact ? patricia_search_exact(tree, prefix) : patricia_search_best(tree, prefix);
patricia_search_best(tree, prefix);
int elems = 0; int elems = 0;
patricia_node_t** list = nullptr; patricia_node_t** list = nullptr;
@ -106,25 +107,24 @@ void* PrefixTable::Lookup(const IPAddr& addr, int width, bool exact) const
void* PrefixTable::Lookup(const Val* value, bool exact) const void* PrefixTable::Lookup(const Val* value, bool exact) const
{ {
// [elem] -> elem // [elem] -> elem
if ( value->GetType()->Tag() == TYPE_LIST && if ( value->GetType()->Tag() == TYPE_LIST && value->AsListVal()->Length() == 1 )
value->AsListVal()->Length() == 1 )
value = value->AsListVal()->Idx(0).get(); value = value->AsListVal()->Idx(0).get();
switch ( value->GetType()->Tag() ) { switch ( value->GetType()->Tag() )
case TYPE_ADDR: {
return Lookup(value->AsAddr(), 128, exact); case TYPE_ADDR:
break; return Lookup(value->AsAddr(), 128, exact);
break;
case TYPE_SUBNET: case TYPE_SUBNET:
return Lookup(value->AsSubNet().Prefix(), return Lookup(value->AsSubNet().Prefix(), value->AsSubNet().LengthIPv6(), exact);
value->AsSubNet().LengthIPv6(), exact); break;
break;
default: default:
reporter->InternalWarning("Wrong index type %d for PrefixTable", reporter->InternalWarning("Wrong index type %d for PrefixTable",
value->GetType()->Tag()); value->GetType()->Tag());
return nullptr; return nullptr;
} }
} }
void* PrefixTable::Remove(const IPAddr& addr, int width) void* PrefixTable::Remove(const IPAddr& addr, int width)
@ -145,24 +145,23 @@ void* PrefixTable::Remove(const IPAddr& addr, int width)
void* PrefixTable::Remove(const Val* value) void* PrefixTable::Remove(const Val* value)
{ {
// [elem] -> elem // [elem] -> elem
if ( value->GetType()->Tag() == TYPE_LIST && if ( value->GetType()->Tag() == TYPE_LIST && value->AsListVal()->Length() == 1 )
value->AsListVal()->Length() == 1 )
value = value->AsListVal()->Idx(0).get(); value = value->AsListVal()->Idx(0).get();
switch ( value->GetType()->Tag() ) { switch ( value->GetType()->Tag() )
case TYPE_ADDR: {
return Remove(value->AsAddr(), 128); case TYPE_ADDR:
break; return Remove(value->AsAddr(), 128);
break;
case TYPE_SUBNET: case TYPE_SUBNET:
return Remove(value->AsSubNet().Prefix(), return Remove(value->AsSubNet().Prefix(), value->AsSubNet().LengthIPv6());
value->AsSubNet().LengthIPv6()); break;
break;
default: default:
reporter->InternalWarning("Wrong index type for PrefixTable"); reporter->InternalWarning("Wrong index type for PrefixTable");
return nullptr; return nullptr;
} }
} }
PrefixTable::iterator PrefixTable::InitIterator() PrefixTable::iterator PrefixTable::InitIterator()
@ -184,7 +183,7 @@ void* PrefixTable::GetNext(iterator* i)
if ( i->Xrn->l ) if ( i->Xrn->l )
{ {
if (i->Xrn->r) if ( i->Xrn->r )
*i->Xsp++ = i->Xrn->r; *i->Xsp++ = i->Xrn->r;
i->Xrn = i->Xrn->l; i->Xrn = i->Xrn->l;
@ -193,17 +192,17 @@ void* PrefixTable::GetNext(iterator* i)
else if ( i->Xrn->r ) else if ( i->Xrn->r )
i->Xrn = i->Xrn->r; i->Xrn = i->Xrn->r;
else if (i->Xsp != i->Xstack) else if ( i->Xsp != i->Xstack )
i->Xrn = *(--i->Xsp); i->Xrn = *(--i->Xsp);
else else
i->Xrn = (patricia_node_t*) nullptr; i->Xrn = (patricia_node_t*)nullptr;
if ( i->Xnode->prefix ) if ( i->Xnode->prefix )
return (void*) i->Xnode->data; return (void*)i->Xnode->data;
} }
// Not reached. // Not reached.
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,33 +1,42 @@
#pragma once #pragma once
extern "C" { extern "C"
#include "zeek/patricia.h" {
} #include "zeek/patricia.h"
}
#include <tuple>
#include <list> #include <list>
#include <tuple>
#include "zeek/IPAddr.h" #include "zeek/IPAddr.h"
namespace zeek { namespace zeek
{
class Val; class Val;
class SubNetVal; class SubNetVal;
namespace detail { namespace detail
{
class PrefixTable { class PrefixTable
{
private: private:
struct iterator { struct iterator
patricia_node_t* Xstack[PATRICIA_MAXBITS+1]; {
patricia_node_t* Xstack[PATRICIA_MAXBITS + 1];
patricia_node_t** Xsp; patricia_node_t** Xsp;
patricia_node_t* Xrn; patricia_node_t* Xrn;
patricia_node_t* Xnode; patricia_node_t* Xnode;
}; };
public: public:
PrefixTable() { tree = New_Patricia(128); delete_function = nullptr; } PrefixTable()
~PrefixTable() { Destroy_Patricia(tree, delete_function); } {
tree = New_Patricia(128);
delete_function = nullptr;
}
~PrefixTable() { Destroy_Patricia(tree, delete_function); }
// Addr in network byte order. If data is zero, acts like a set. // Addr in network byte order. If data is zero, acts like a set.
// Returns ptr to old data if already existing. // Returns ptr to old data if already existing.
@ -51,10 +60,10 @@ public:
void* Remove(const IPAddr& addr, int width); void* Remove(const IPAddr& addr, int width);
void* Remove(const Val* value); void* Remove(const Val* value);
void Clear() { Clear_Patricia(tree, delete_function); } void Clear() { Clear_Patricia(tree, delete_function); }
// Sets a function to call for each node when table is cleared/destroyed. // Sets a function to call for each node when table is cleared/destroyed.
void SetDeleteFunction(data_fn_t del_fn) { delete_function = del_fn; } void SetDeleteFunction(data_fn_t del_fn) { delete_function = del_fn; }
iterator InitIterator(); iterator InitIterator();
void* GetNext(iterator* i); void* GetNext(iterator* i);
@ -65,7 +74,7 @@ private:
patricia_tree_t* tree; patricia_tree_t* tree;
data_fn_t delete_function; data_fn_t delete_function;
}; };
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,6 +1,5 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/PriorityQueue.h" #include "zeek/PriorityQueue.h"
#include <stdio.h> #include <stdio.h>
@ -8,8 +7,10 @@
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/util.h" #include "zeek/util.h"
#include "zeek/zeek-config.h"
namespace zeek::detail { namespace zeek::detail
{
PriorityQueue::PriorityQueue(int initial_size) : max_heap_size(initial_size) PriorityQueue::PriorityQueue(int initial_size) : max_heap_size(initial_size)
{ {
@ -21,7 +22,7 @@ PriorityQueue::~PriorityQueue()
for ( int i = 0; i < heap_size; ++i ) for ( int i = 0; i < heap_size; ++i )
delete heap[i]; delete heap[i];
delete [] heap; delete[] heap;
} }
PQ_Element* PriorityQueue::Remove() PQ_Element* PriorityQueue::Remove()
@ -35,15 +36,14 @@ PQ_Element* PriorityQueue::Remove()
SetElement(0, heap[heap_size]); SetElement(0, heap[heap_size]);
BubbleDown(0); BubbleDown(0);
top->SetOffset(-1); // = not in heap top->SetOffset(-1); // = not in heap
return top; return top;
} }
PQ_Element* PriorityQueue::Remove(PQ_Element* e) PQ_Element* PriorityQueue::Remove(PQ_Element* e)
{ {
if ( e->Offset() < 0 || e->Offset() >= heap_size || if ( e->Offset() < 0 || e->Offset() >= heap_size || heap[e->Offset()] != e )
heap[e->Offset()] != e ) return nullptr; // not in heap
return nullptr; // not in heap
e->MinimizeTime(); e->MinimizeTime();
BubbleUp(e->Offset()); BubbleUp(e->Offset());
@ -79,7 +79,7 @@ bool PriorityQueue::Resize(int new_size)
for ( int i = 0; i < max_heap_size; ++i ) for ( int i = 0; i < max_heap_size; ++i )
tmp[i] = heap[i]; tmp[i] = heap[i];
delete [] heap; delete[] heap;
heap = tmp; heap = tmp;
max_heap_size = new_size; max_heap_size = new_size;
@ -108,7 +108,7 @@ void PriorityQueue::BubbleDown(int bin)
int r = RightChild(bin); int r = RightChild(bin);
if ( l >= heap_size ) if ( l >= heap_size )
return; // No children. return; // No children.
if ( r >= heap_size ) if ( r >= heap_size )
{ // Just a left child. { // Just a left child.
@ -138,4 +138,4 @@ void PriorityQueue::BubbleDown(int bin)
} }
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -2,34 +2,37 @@
#pragma once #pragma once
#include "zeek/zeek-config.h"
#include <math.h> #include <math.h>
#include <stdint.h> #include <stdint.h>
namespace zeek::detail { #include "zeek/zeek-config.h"
namespace zeek::detail
{
class PriorityQueue; class PriorityQueue;
class PQ_Element { class PQ_Element
{
public: public:
explicit PQ_Element(double t) : time(t) {} explicit PQ_Element(double t) : time(t) { }
virtual ~PQ_Element() = default; virtual ~PQ_Element() = default;
double Time() const { return time; } double Time() const { return time; }
int Offset() const { return offset; } int Offset() const { return offset; }
void SetOffset(int off) { offset = off; } void SetOffset(int off) { offset = off; }
void MinimizeTime() { time = -HUGE_VAL; } void MinimizeTime() { time = -HUGE_VAL; }
protected: protected:
PQ_Element() = default; PQ_Element() = default;
double time = 0.0; double time = 0.0;
int offset = -1; int offset = -1;
}; };
class PriorityQueue { class PriorityQueue
{
public: public:
explicit PriorityQueue(int initial_size = 16); explicit PriorityQueue(int initial_size = 16);
~PriorityQueue(); ~PriorityQueue();
@ -55,8 +58,8 @@ public:
// memory to add the element), true on success. // memory to add the element), true on success.
bool Add(PQ_Element* e); bool Add(PQ_Element* e);
int Size() const { return heap_size; } int Size() const { return heap_size; }
int PeakSize() const { return peak_heap_size; } int PeakSize() const { return peak_heap_size; }
uint64_t CumulativeNum() const { return cumulative_num; } uint64_t CumulativeNum() const { return cumulative_num; }
protected: protected:
@ -65,20 +68,11 @@ protected:
void BubbleUp(int bin); void BubbleUp(int bin);
void BubbleDown(int bin); void BubbleDown(int bin);
int Parent(int bin) const int Parent(int bin) const { return bin >> 1; }
{
return bin >> 1;
}
int LeftChild(int bin) const int LeftChild(int bin) const { return bin << 1; }
{
return bin << 1;
}
int RightChild(int bin) const int RightChild(int bin) const { return LeftChild(bin) + 1; }
{
return LeftChild(bin) + 1;
}
void SetElement(int bin, PQ_Element* e) void SetElement(int bin, PQ_Element* e)
{ {
@ -98,6 +92,6 @@ protected:
int peak_heap_size = 0; int peak_heap_size = 0;
int max_heap_size = 0; int max_heap_size = 0;
uint64_t cumulative_num = 0; uint64_t cumulative_num = 0;
}; };
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -23,10 +23,13 @@
// Entries must be either a pointer to the data or nonzero data with // Entries must be either a pointer to the data or nonzero data with
// sizeof(data) <= sizeof(void*). // sizeof(data) <= sizeof(void*).
namespace zeek { namespace zeek
{
template<typename T> template <typename T>
class [[deprecated("Remove in v5.1. This class is deprecated (and is likely broken, see #1528). Use std::vector<T>.")]] Queue { class [[deprecated("Remove in v5.1. This class is deprecated (and is likely broken, see #1528). "
"Use std::vector<T>.")]] Queue
{
public: public:
explicit Queue(int size = 0) explicit Queue(int size = 0)
{ {
@ -42,7 +45,7 @@ public:
} }
else else
{ {
if ( (entries = new T[chunk_size+1]) ) if ( (entries = new T[chunk_size + 1]) )
max_entries = chunk_size; max_entries = chunk_size;
else else
{ {
@ -52,11 +55,11 @@ public:
} }
} }
~Queue() { delete[] entries; } ~Queue() { delete[] entries; }
int length() const { return num_entries; } int length() const { return num_entries; }
int capacity() const { return max_entries; } int capacity() const { return max_entries; }
int resize(int new_size = 0) // 0 => size to fit current number of entries int resize(int new_size = 0) // 0 => size to fit current number of entries
{ {
if ( new_size < num_entries ) if ( new_size < num_entries )
new_size = num_entries; // do not lose any entries new_size = num_entries; // do not lose any entries
@ -66,22 +69,19 @@ public:
// Note, allocate extra space, so that we can always // Note, allocate extra space, so that we can always
// use the [max_entries] element. // use the [max_entries] element.
// ### Yin, why not use realloc()? // ### Yin, why not use realloc()?
T* new_entries = new T[new_size+1]; T* new_entries = new T[new_size + 1];
if ( new_entries ) if ( new_entries )
{ {
if ( head <= tail ) if ( head <= tail )
memcpy( new_entries, entries + head, memcpy(new_entries, entries + head, sizeof(T) * num_entries);
sizeof(T) * num_entries );
else else
{ {
int len = num_entries - tail; int len = num_entries - tail;
memcpy( new_entries, entries + head, memcpy(new_entries, entries + head, sizeof(T) * len);
sizeof(T) * len ); memcpy(new_entries + len, entries, sizeof(T) * tail);
memcpy( new_entries + len, entries,
sizeof(T) * tail );
} }
delete [] entries; delete[] entries;
entries = new_entries; entries = new_entries;
max_entries = new_size; max_entries = new_size;
head = 0; head = 0;
@ -96,19 +96,19 @@ public:
} }
// remove all entries without delete[] entry // remove all entries without delete[] entry
void clear() { head = tail = num_entries = 0; } void clear() { head = tail = num_entries = 0; }
// helper functions for iterating over queue // helper functions for iterating over queue
T& front() { return entries[head]; } T& front() { return entries[head]; }
T& back() { return entries[tail]; } T& back() { return entries[tail]; }
const T& front() const { return entries[head]; } const T& front() const { return entries[head]; }
const T& back() const { return entries[tail]; } const T& back() const { return entries[tail]; }
void push_front(const T& a) // add in front of queue void push_front(const T& a) // add in front of queue
{ {
if ( num_entries == max_entries ) if ( num_entries == max_entries )
{ {
resize(max_entries+chunk_size); // make more room resize(max_entries + chunk_size); // make more room
chunk_size *= 2; chunk_size *= 2;
} }
@ -122,11 +122,11 @@ public:
} }
} }
void push_back(const T& a) // add at end of queue void push_back(const T& a) // add at end of queue
{ {
if ( num_entries == max_entries ) if ( num_entries == max_entries )
{ {
resize(max_entries+chunk_size); // make more room resize(max_entries + chunk_size); // make more room
chunk_size *= 2; chunk_size *= 2;
} }
@ -159,7 +159,7 @@ public:
} }
// return nth *PHYSICAL* entry of queue (do not remove) // return nth *PHYSICAL* entry of queue (do not remove)
T& operator[](int i) const { return entries[i]; } T& operator[](int i) const { return entries[i]; }
// Type traits needed for some of the std algorithms to work // Type traits needed for some of the std algorithms to work
using value_type = T; using value_type = T;
@ -187,17 +187,16 @@ public:
const_reverse_iterator crend() const { return rend(); } const_reverse_iterator crend() const { return rend(); }
protected: protected:
T* entries; T* entries;
int chunk_size; // increase size by this amount when necessary int chunk_size; // increase size by this amount when necessary
int max_entries; // entry's index range: 0 .. max_entries int max_entries; // entry's index range: 0 .. max_entries
int num_entries; int num_entries;
int head; // beginning of the queue in the ring int head; // beginning of the queue in the ring
int tail; // just beyond the end of the queue in the ring int tail; // just beyond the end of the queue in the ring
}; };
template <typename T>
using PQueue [[deprecated("Remove in v5.1. This class is deprecated (and is likely broken, see "
"#1528). Use std::vector<T*>.")]] = Queue<T*>;
template<typename T> } // namespace zeek
using PQueue [[deprecated("Remove in v5.1. This class is deprecated (and is likely broken, see #1528). Use std::vector<T*>.")]] = Queue<T*>;
} // namespace zeek

View file

@ -1,16 +1,16 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/RE.h" #include "zeek/RE.h"
#include <stdlib.h> #include <stdlib.h>
#include <utility> #include <utility>
#include "zeek/DFA.h"
#include "zeek/CCL.h" #include "zeek/CCL.h"
#include "zeek/DFA.h"
#include "zeek/EquivClass.h" #include "zeek/EquivClass.h"
#include "zeek/Reporter.h" #include "zeek/Reporter.h"
#include "zeek/ZeekString.h" #include "zeek/ZeekString.h"
#include "zeek/zeek-config.h"
zeek::detail::CCL* zeek::detail::curr_ccl = nullptr; zeek::detail::CCL* zeek::detail::curr_ccl = nullptr;
zeek::detail::Specific_RE_Matcher* zeek::detail::rem = nullptr; zeek::detail::Specific_RE_Matcher* zeek::detail::rem = nullptr;
@ -21,11 +21,13 @@ extern int RE_parse(void);
extern void RE_set_input(const char* str); extern void RE_set_input(const char* str);
extern void RE_done_with_scan(); extern void RE_done_with_scan();
namespace zeek { namespace zeek
namespace detail { {
namespace detail
{
Specific_RE_Matcher::Specific_RE_Matcher(match_type arg_mt, int arg_multiline) Specific_RE_Matcher::Specific_RE_Matcher(match_type arg_mt, int arg_multiline)
: equiv_class(NUM_SYM) : equiv_class(NUM_SYM)
{ {
mt = arg_mt; mt = arg_mt;
multiline = arg_multiline; multiline = arg_multiline;
@ -42,7 +44,7 @@ Specific_RE_Matcher::~Specific_RE_Matcher()
delete ccl_list[i]; delete ccl_list[i];
Unref(dfa); Unref(dfa);
delete [] pattern_text; delete[] pattern_text;
delete accepted; delete accepted;
} }
@ -84,8 +86,7 @@ void Specific_RE_Matcher::AddExactPat(const char* new_pat)
AddPat(new_pat, "^?(%s)$?", "(%s)|(^?(%s)$?)"); AddPat(new_pat, "^?(%s)$?", "(%s)|(^?(%s)$?)");
} }
void Specific_RE_Matcher::AddPat(const char* new_pat, void Specific_RE_Matcher::AddPat(const char* new_pat, const char* orig_fmt, const char* app_fmt)
const char* orig_fmt, const char* app_fmt)
{ {
int n = strlen(new_pat); int n = strlen(new_pat);
@ -101,7 +102,7 @@ void Specific_RE_Matcher::AddPat(const char* new_pat,
else else
sprintf(s, orig_fmt, new_pat); sprintf(s, orig_fmt, new_pat);
delete [] pattern_text; delete[] pattern_text;
pattern_text = s; pattern_text = s;
} }
@ -114,7 +115,7 @@ void Specific_RE_Matcher::MakeCaseInsensitive()
snprintf(s, n + 5, fmt, pattern_text); snprintf(s, n + 5, fmt, pattern_text);
delete [] pattern_text; delete[] pattern_text;
pattern_text = s; pattern_text = s;
} }
@ -186,7 +187,7 @@ bool Specific_RE_Matcher::CompileSet(const string_list& set, const int_list& idx
nfa = new NFA_Machine(new NFA_State(SYM_BOL, rem->EC())); nfa = new NFA_Machine(new NFA_State(SYM_BOL, rem->EC()));
nfa->MakeOptional(); nfa->MakeOptional();
if ( set_nfa ) if ( set_nfa )
nfa->AppendMachine( set_nfa ); nfa->AppendMachine(set_nfa);
EC()->BuildECs(); EC()->BuildECs();
ConvertCCLs(); ConvertCCLs();
@ -262,7 +263,6 @@ bool Specific_RE_Matcher::MatchAll(const u_char* bv, int n)
return d && d->Accept() != nullptr; return d && d->Accept() != nullptr;
} }
int Specific_RE_Matcher::Match(const u_char* bv, int n) int Specific_RE_Matcher::Match(const u_char* bv, int n)
{ {
if ( ! dfa ) if ( ! dfa )
@ -272,7 +272,8 @@ int Specific_RE_Matcher::Match(const u_char* bv, int n)
DFA_State* d = dfa->StartState(); DFA_State* d = dfa->StartState();
d = d->Xtion(ecs[SYM_BOL], dfa); d = d->Xtion(ecs[SYM_BOL], dfa);
if ( ! d ) return 0; if ( ! d )
return 0;
for ( int i = 0; i < n; ++i ) for ( int i = 0; i < n; ++i )
{ {
@ -289,20 +290,18 @@ int Specific_RE_Matcher::Match(const u_char* bv, int n)
{ {
d = d->Xtion(ecs[SYM_EOL], dfa); d = d->Xtion(ecs[SYM_EOL], dfa);
if ( d && d->Accept() ) if ( d && d->Accept() )
return n > 0 ? n : 1; // we can't return 0 here for match... return n > 0 ? n : 1; // we can't return 0 here for match...
} }
return 0; return 0;
} }
void Specific_RE_Matcher::Dump(FILE* f) void Specific_RE_Matcher::Dump(FILE* f)
{ {
dfa->Dump(f); dfa->Dump(f);
} }
inline void RE_Match_State::AddMatches(const AcceptingSet& as, inline void RE_Match_State::AddMatches(const AcceptingSet& as, MatchPos position)
MatchPos position)
{ {
typedef std::pair<AcceptIdx, MatchPos> am_idx; typedef std::pair<AcceptIdx, MatchPos> am_idx;
@ -310,8 +309,7 @@ inline void RE_Match_State::AddMatches(const AcceptingSet& as,
accepted_matches.insert(am_idx(*it, position)); accepted_matches.insert(am_idx(*it, position));
} }
bool RE_Match_State::Match(const u_char* bv, int n, bool RE_Match_State::Match(const u_char* bv, int n, bool bol, bool eol, bool clear)
bool bol, bool eol, bool clear)
{ {
if ( current_pos == -1 ) if ( current_pos == -1 )
{ {
@ -352,7 +350,7 @@ bool RE_Match_State::Match(const u_char* bv, int n,
else else
ec = ecs[*(bv++)]; ec = ecs[*(bv++)];
DFA_State* next_state = current_state->Xtion(ec,dfa); DFA_State* next_state = current_state->Xtion(ec, dfa);
if ( ! next_state ) if ( ! next_state )
{ {
@ -425,7 +423,8 @@ unsigned int Specific_RE_Matcher::MemoryAllocation() const
size += util::pad_size(sizeof(CCL*) * ccl_dict.size()); size += util::pad_size(sizeof(CCL*) * ccl_dict.size());
for ( const auto& entry : ccl_dict ) for ( const auto& entry : ccl_dict )
{ {
size += padded_sizeof(std::string) + util::pad_size(sizeof(std::string::value_type) * entry.first.size()); size += padded_sizeof(std::string) +
util::pad_size(sizeof(std::string::value_type) * entry.first.size());
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
size += entry.second->MemoryAllocation(); size += entry.second->MemoryAllocation();
@ -434,36 +433,36 @@ unsigned int Specific_RE_Matcher::MemoryAllocation() const
for ( const auto& entry : defs ) for ( const auto& entry : defs )
{ {
size += padded_sizeof(std::string) + util::pad_size(sizeof(std::string::value_type) * entry.first.size()); size += padded_sizeof(std::string) +
size += padded_sizeof(std::string) + util::pad_size(sizeof(std::string::value_type) * entry.second.size()); util::pad_size(sizeof(std::string::value_type) * entry.first.size());
size += padded_sizeof(std::string) +
util::pad_size(sizeof(std::string::value_type) * entry.second.size());
} }
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return size + padded_sizeof(*this) return size + padded_sizeof(*this) +
+ (pattern_text ? util::pad_size(strlen(pattern_text) + 1) : 0) (pattern_text ? util::pad_size(strlen(pattern_text) + 1) : 0) +
+ ccl_list.MemoryAllocation() - padded_sizeof(ccl_list) ccl_list.MemoryAllocation() - padded_sizeof(ccl_list) + equiv_class.Size() -
+ equiv_class.Size() - padded_sizeof(EquivClass) padded_sizeof(EquivClass) +
+ (dfa ? dfa->MemoryAllocation() : 0) // this is ref counted; consider the bytes here? (dfa ? dfa->MemoryAllocation() : 0) // this is ref counted; consider the bytes here?
+ padded_sizeof(*any_ccl) + padded_sizeof(*any_ccl) + padded_sizeof(*accepted) // NOLINT(bugprone-sizeof-container)
+ padded_sizeof(*accepted) // NOLINT(bugprone-sizeof-container) + accepted->size() * padded_sizeof(AcceptingSet::key_type);
+ accepted->size() * padded_sizeof(AcceptingSet::key_type);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} }
static RE_Matcher* matcher_merge(const RE_Matcher* re1, const RE_Matcher* re2, static RE_Matcher* matcher_merge(const RE_Matcher* re1, const RE_Matcher* re2, const char* merge_op)
const char* merge_op)
{ {
const char* text1 = re1->PatternText(); const char* text1 = re1->PatternText();
const char* text2 = re2->PatternText(); const char* text2 = re2->PatternText();
int n = strlen(text1) + strlen(text2) + strlen(merge_op) + 32 /* slop */ ; int n = strlen(text1) + strlen(text2) + strlen(merge_op) + 32 /* slop */;
char* merge_text = new char[n]; char* merge_text = new char[n];
snprintf(merge_text, n, "(%s)%s(%s)", text1, merge_op, text2); snprintf(merge_text, n, "(%s)%s(%s)", text1, merge_op, text2);
RE_Matcher* merge = new RE_Matcher(merge_text); RE_Matcher* merge = new RE_Matcher(merge_text);
delete [] merge_text; delete[] merge_text;
merge->Compile(); merge->Compile();
@ -480,7 +479,7 @@ RE_Matcher* RE_Matcher_disjunction(const RE_Matcher* re1, const RE_Matcher* re2)
return matcher_merge(re1, re2, "|"); return matcher_merge(re1, re2, "|");
} }
} // namespace detail } // namespace detail
RE_Matcher::RE_Matcher() RE_Matcher::RE_Matcher()
{ {
@ -529,4 +528,4 @@ bool RE_Matcher::Compile(bool lazy)
return re_anywhere->Compile(lazy) && re_exact->Compile(lazy); return re_anywhere->Compile(lazy) && re_exact->Compile(lazy);
} }
} // namespace zeek } // namespace zeek

View file

@ -2,27 +2,29 @@
#pragma once #pragma once
#include <sys/types.h> // for u_char
#include <ctype.h> #include <ctype.h>
#include <set> #include <sys/types.h> // for u_char
#include <map> #include <map>
#include <set>
#include <string> #include <string>
#include "zeek/List.h"
#include "zeek/CCL.h" #include "zeek/CCL.h"
#include "zeek/EquivClass.h" #include "zeek/EquivClass.h"
#include "zeek/List.h"
typedef int (*cce_func)(int); typedef int (*cce_func)(int);
// This method is automatically generated by flex and shouldn't be namespaced // This method is automatically generated by flex and shouldn't be namespaced
extern int re_lex(void); extern int re_lex(void);
namespace zeek { namespace zeek
{
class String; class String;
class RE_Matcher; class RE_Matcher;
namespace detail { namespace detail
{
class NFA_Machine; class NFA_Machine;
class DFA_Machine; class DFA_Machine;
@ -45,21 +47,26 @@ using MatchPos = uint64_t;
using AcceptingMatchSet = std::map<AcceptIdx, MatchPos>; using AcceptingMatchSet = std::map<AcceptIdx, MatchPos>;
using string_list = name_list; using string_list = name_list;
enum match_type { MATCH_ANYWHERE, MATCH_EXACTLY }; enum match_type
{
MATCH_ANYWHERE,
MATCH_EXACTLY
};
// A "specific" RE matcher will match one type of pattern: either // A "specific" RE matcher will match one type of pattern: either
// MATCH_ANYWHERE or MATCH_EXACTLY. // MATCH_ANYWHERE or MATCH_EXACTLY.
class Specific_RE_Matcher { class Specific_RE_Matcher
{
public: public:
explicit Specific_RE_Matcher(match_type mt, int multiline=0); explicit Specific_RE_Matcher(match_type mt, int multiline = 0);
~Specific_RE_Matcher(); ~Specific_RE_Matcher();
void AddPat(const char* pat); void AddPat(const char* pat);
void MakeCaseInsensitive(); void MakeCaseInsensitive();
void SetPat(const char* pat) { pattern_text = util::copy_string(pat); } void SetPat(const char* pat) { pattern_text = util::copy_string(pat); }
bool Compile(bool lazy = false); bool Compile(bool lazy = false);
@ -82,7 +89,7 @@ public:
return nullptr; return nullptr;
} }
CCL* LookupCCL(int index) { return ccl_list[index]; } CCL* LookupCCL(int index) { return ccl_list[index]; }
CCL* AnyCCL(); CCL* AnyCCL();
void ConvertCCLs(); void ConvertCCLs();
@ -107,16 +114,17 @@ public:
int LongestMatch(const String* s); int LongestMatch(const String* s);
int LongestMatch(const u_char* bv, int n); int LongestMatch(const u_char* bv, int n);
EquivClass* EC() { return &equiv_class; } EquivClass* EC() { return &equiv_class; }
const char* PatternText() const { return pattern_text; } const char* PatternText() const { return pattern_text; }
DFA_Machine* DFA() const { return dfa; } DFA_Machine* DFA() const { return dfa; }
void Dump(FILE* f); void Dump(FILE* f);
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const; "GHI-572.")]] unsigned int
MemoryAllocation() const;
protected: protected:
void AddAnywherePat(const char* pat); void AddAnywherePat(const char* pat);
@ -142,9 +150,10 @@ protected:
DFA_Machine* dfa; DFA_Machine* dfa;
CCL* any_ccl; CCL* any_ccl;
AcceptingSet* accepted; AcceptingSet* accepted;
}; };
class RE_Match_State { class RE_Match_State
{
public: public:
explicit RE_Match_State(Specific_RE_Matcher* matcher) explicit RE_Match_State(Specific_RE_Matcher* matcher)
{ {
@ -154,11 +163,10 @@ public:
current_state = nullptr; current_state = nullptr;
} }
const AcceptingMatchSet& AcceptedMatches() const const AcceptingMatchSet& AcceptedMatches() const { return accepted_matches; }
{ return accepted_matches; }
// Returns the number of bytes feeded into the matcher so far // Returns the number of bytes feeded into the matcher so far
int Length() { return current_pos; } int Length() { return current_pos; }
// Returns true if this inputs leads to at least one new match. // Returns true if this inputs leads to at least one new match.
// If clear is true, starts matching over. // If clear is true, starts matching over.
@ -180,14 +188,15 @@ protected:
AcceptingMatchSet accepted_matches; AcceptingMatchSet accepted_matches;
DFA_State* current_state; DFA_State* current_state;
int current_pos; int current_pos;
}; };
extern RE_Matcher* RE_Matcher_conjunction(const RE_Matcher* re1, const RE_Matcher* re2); extern RE_Matcher* RE_Matcher_conjunction(const RE_Matcher* re1, const RE_Matcher* re2);
extern RE_Matcher* RE_Matcher_disjunction(const RE_Matcher* re1, const RE_Matcher* re2); extern RE_Matcher* RE_Matcher_disjunction(const RE_Matcher* re1, const RE_Matcher* re2);
} // namespace detail } // namespace detail
class RE_Matcher final { class RE_Matcher final
{
public: public:
RE_Matcher(); RE_Matcher();
explicit RE_Matcher(const char* pat); explicit RE_Matcher(const char* pat);
@ -198,49 +207,42 @@ public:
// Makes the matcher as specified to date case-insensitive. // Makes the matcher as specified to date case-insensitive.
void MakeCaseInsensitive(); void MakeCaseInsensitive();
bool IsCaseInsensitive() const { return is_case_insensitive; } bool IsCaseInsensitive() const { return is_case_insensitive; }
bool Compile(bool lazy = false); bool Compile(bool lazy = false);
// Returns true if s exactly matches the pattern, false otherwise. // Returns true if s exactly matches the pattern, false otherwise.
bool MatchExactly(const char* s) bool MatchExactly(const char* s) { return re_exact->MatchAll(s); }
{ return re_exact->MatchAll(s); } bool MatchExactly(const String* s) { return re_exact->MatchAll(s); }
bool MatchExactly(const String* s)
{ return re_exact->MatchAll(s); }
// Returns the position in s just beyond where the first match // Returns the position in s just beyond where the first match
// occurs, or 0 if there is no such position in s. Note that // occurs, or 0 if there is no such position in s. Note that
// if the pattern matches empty strings, matching continues // if the pattern matches empty strings, matching continues
// in an attempt to match at least one character. // in an attempt to match at least one character.
int MatchAnywhere(const char* s) int MatchAnywhere(const char* s) { return re_anywhere->Match(s); }
{ return re_anywhere->Match(s); } int MatchAnywhere(const String* s) { return re_anywhere->Match(s); }
int MatchAnywhere(const String* s)
{ return re_anywhere->Match(s); }
// Note: it matches the *longest* prefix and returns the // Note: it matches the *longest* prefix and returns the
// length of matched prefix. It returns -1 on mismatch. // length of matched prefix. It returns -1 on mismatch.
int MatchPrefix(const char* s) int MatchPrefix(const char* s) { return re_exact->LongestMatch(s); }
{ return re_exact->LongestMatch(s); } int MatchPrefix(const String* s) { return re_exact->LongestMatch(s); }
int MatchPrefix(const String* s) int MatchPrefix(const u_char* s, int n) { return re_exact->LongestMatch(s, n); }
{ return re_exact->LongestMatch(s); }
int MatchPrefix(const u_char* s, int n)
{ return re_exact->LongestMatch(s, n); }
const char* PatternText() const { return re_exact->PatternText(); } const char* PatternText() const { return re_exact->PatternText(); }
const char* AnywherePatternText() const { return re_anywhere->PatternText(); } const char* AnywherePatternText() const { return re_anywhere->PatternText(); }
// Original text used to construct this matcher. Empty unless // Original text used to construct this matcher. Empty unless
// the main ("explicit") constructor was used. // the main ("explicit") constructor was used.
const char* OrigText() const { return orig_text.c_str(); } const char* OrigText() const { return orig_text.c_str(); }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] [[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
unsigned int MemoryAllocation() const "GHI-572.")]] unsigned int
MemoryAllocation() const
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return padded_sizeof(*this) return padded_sizeof(*this) + (re_anywhere ? re_anywhere->MemoryAllocation() : 0) +
+ (re_anywhere ? re_anywhere->MemoryAllocation() : 0) (re_exact ? re_exact->MemoryAllocation() : 0);
+ (re_exact ? re_exact->MemoryAllocation() : 0);
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
} }
@ -251,6 +253,6 @@ protected:
detail::Specific_RE_Matcher* re_exact; detail::Specific_RE_Matcher* re_exact;
bool is_case_insensitive = false; bool is_case_insensitive = false;
}; };
} // namespace zeek } // namespace zeek

View file

@ -1,15 +1,15 @@
/* /*
Apply various randomness tests to a stream of bytes Apply various randomness tests to a stream of bytes
by John Walker -- September 1996 by John Walker -- September 1996
http://www.fourmilab.ch/random http://www.fourmilab.ch/random
This software is in the public domain. Permission to use, copy, modify, This software is in the public domain. Permission to use, copy, modify,
and distribute this software and its documentation for any purpose and and distribute this software and its documentation for any purpose and
without fee is hereby granted, without any conditions or restrictions. without fee is hereby granted, without any conditions or restrictions.
This software is provided as is without express or implied warranty. This software is provided as is without express or implied warranty.
Modified for Bro by Seth Hall - July 2010 Modified for Bro by Seth Hall - July 2010
*/ */
#include "zeek/RandTest.h" #include "zeek/RandTest.h"
@ -20,14 +20,15 @@ constexpr double log2of10 = 3.32192809488736234787;
/* RT_LOG2 -- Calculate log to the base 2 */ /* RT_LOG2 -- Calculate log to the base 2 */
static double rt_log2(double x) static double rt_log2(double x)
{ {
return log2of10 * log10(x); return log2of10 * log10(x);
} }
// RT_INCIRC = pow(pow(256.0, (double) (RT_MONTEN / 2)) - 1, 2.0); // RT_INCIRC = pow(pow(256.0, (double) (RT_MONTEN / 2)) - 1, 2.0);
constexpr double RT_INCIRC = 281474943156225.0; constexpr double RT_INCIRC = 281474943156225.0;
namespace zeek::detail { namespace zeek::detail
{
RandTest::RandTest() RandTest::RandTest()
{ {
@ -37,45 +38,45 @@ RandTest::RandTest()
inmont = mcount = 0; inmont = mcount = 0;
cexp = montex = montey = montepi = sccu0 = scclast = scct1 = scct2 = scct3 = 0.0; cexp = montex = montey = montepi = sccu0 = scclast = scct1 = scct2 = scct3 = 0.0;
for (int i = 0; i < 256; i++) for ( int i = 0; i < 256; i++ )
{ {
ccount[i] = 0; ccount[i] = 0;
} }
} }
void RandTest::add(const void *buf, int bufl) void RandTest::add(const void* buf, int bufl)
{ {
const unsigned char *bp = static_cast<const unsigned char*>(buf); const unsigned char* bp = static_cast<const unsigned char*>(buf);
int oc; int oc;
while (bufl-- > 0) while ( bufl-- > 0 )
{ {
oc = *bp++; oc = *bp++;
ccount[oc]++; /* Update counter for this bin */ ccount[oc]++; /* Update counter for this bin */
totalc++; totalc++;
/* Update inside / outside circle counts for Monte Carlo /* Update inside / outside circle counts for Monte Carlo
computation of PI */ computation of PI */
monte[mp++] = oc; /* Save character for Monte Carlo */ monte[mp++] = oc; /* Save character for Monte Carlo */
if (mp >= RT_MONTEN) /* Calculate every RT_MONTEN character */ if ( mp >= RT_MONTEN ) /* Calculate every RT_MONTEN character */
{ {
mp = 0; mp = 0;
mcount++; mcount++;
montex = 0; montex = 0;
montey = 0; montey = 0;
for (int mj=0; mj < RT_MONTEN/2; mj++) for ( int mj = 0; mj < RT_MONTEN / 2; mj++ )
{ {
montex = (montex * 256.0) + monte[mj]; montex = (montex * 256.0) + monte[mj];
montey = (montey * 256.0) + monte[(RT_MONTEN / 2) + mj]; montey = (montey * 256.0) + monte[(RT_MONTEN / 2) + mj];
} }
if (montex*montex + montey*montey <= RT_INCIRC) if ( montex * montex + montey * montey <= RT_INCIRC )
{ {
inmont++; inmont++;
} }
} }
/* Update calculation of serial correlation coefficient */ /* Update calculation of serial correlation coefficient */
if (sccfirst) if ( sccfirst )
{ {
sccfirst = 0; sccfirst = 0;
scclast = 0; scclast = 0;
@ -93,42 +94,45 @@ void RandTest::add(const void *buf, int bufl)
} }
} }
void RandTest::end(double* r_ent, double* r_chisq, void RandTest::end(double* r_ent, double* r_chisq, double* r_mean, double* r_montepicalc,
double* r_mean, double* r_montepicalc, double* r_scc) double* r_scc)
{ {
int i; int i;
double ent, chisq, scc, datasum; double ent, chisq, scc, datasum;
ent = 0.0; chisq = 0.0; scc = 0.0; datasum = 0.0; ent = 0.0;
double prob[256]; /* Probabilities per bin for entropy */ chisq = 0.0;
scc = 0.0;
datasum = 0.0;
double prob[256]; /* Probabilities per bin for entropy */
/* Complete calculation of serial correlation coefficient */ /* Complete calculation of serial correlation coefficient */
scct1 = scct1 + scclast * sccu0; scct1 = scct1 + scclast * sccu0;
scct2 = scct2 * scct2; scct2 = scct2 * scct2;
scc = totalc * scct3 - scct2; scc = totalc * scct3 - scct2;
if (scc == 0.0) if ( scc == 0.0 )
scc = -100000; scc = -100000;
else else
scc = (totalc * scct1 - scct2) / scc; scc = (totalc * scct1 - scct2) / scc;
/* Scan bins and calculate probability for each bin and /* Scan bins and calculate probability for each bin and
Chi-Square distribution. The probability will be reused Chi-Square distribution. The probability will be reused
in the entropy calculation below. While we're at it, in the entropy calculation below. While we're at it,
we sum of all the data which will be used to compute the we sum of all the data which will be used to compute the
mean. */ mean. */
cexp = totalc / 256.0; /* Expected count per bin */ cexp = totalc / 256.0; /* Expected count per bin */
for (i = 0; i < 256; i++) for ( i = 0; i < 256; i++ )
{ {
double a = ccount[i] - cexp; double a = ccount[i] - cexp;
prob[i] = ((double) ccount[i]) / totalc; prob[i] = ((double)ccount[i]) / totalc;
chisq += (a * a) / cexp; chisq += (a * a) / cexp;
datasum += ((double) i) * ccount[i]; datasum += ((double)i) * ccount[i];
} }
/* Calculate entropy */ /* Calculate entropy */
for (i = 0; i < 256; i++) for ( i = 0; i < 256; i++ )
{ {
if (prob[i] > 0.0) if ( prob[i] > 0.0 )
{ {
ent += prob[i] * rt_log2(1 / prob[i]); ent += prob[i] * rt_log2(1 / prob[i]);
} }
@ -136,7 +140,7 @@ void RandTest::end(double* r_ent, double* r_chisq,
/* Calculate Monte Carlo value for PI from percentage of hits /* Calculate Monte Carlo value for PI from percentage of hits
within the circle */ within the circle */
montepi = mcount == 0 ? 0 : 4.0 * (((double) inmont) / mcount); montepi = mcount == 0 ? 0 : 4.0 * (((double)inmont) / mcount);
/* Return results through arguments */ /* Return results through arguments */
*r_ent = ent; *r_ent = ent;
@ -146,4 +150,4 @@ void RandTest::end(double* r_ent, double* r_chisq,
*r_scc = scc; *r_scc = scc;
} }
} // namespace zeek::detail } // namespace zeek::detail

View file

@ -1,38 +1,41 @@
#pragma once #pragma once
#include "zeek/zeek-config.h"
#include <stdint.h> #include <stdint.h>
#define RT_MONTEN 6 /* Bytes used as Monte Carlo #include "zeek/zeek-config.h"
co-ordinates. This should be no more
bits than the mantissa of your "double"
floating point type. */
namespace zeek { #define RT_MONTEN \
6 /* Bytes used as Monte Carlo \
co-ordinates. This should be no more \
bits than the mantissa of your "double" \
floating point type. */
namespace zeek
{
class EntropyVal; class EntropyVal;
namespace detail { namespace detail
{
class RandTest { class RandTest
{
public: public:
RandTest(); RandTest();
void add(const void* buf, int bufl); void add(const void* buf, int bufl);
void end(double* r_ent, double* r_chisq, double* r_mean, void end(double* r_ent, double* r_chisq, double* r_mean, double* r_montepicalc, double* r_scc);
double* r_montepicalc, double* r_scc);
private: private:
friend class zeek::EntropyVal; friend class zeek::EntropyVal;
int64_t ccount[256]; /* Bins to count occurrences of values */ int64_t ccount[256]; /* Bins to count occurrences of values */
int64_t totalc; /* Total bytes counted */ int64_t totalc; /* Total bytes counted */
int mp; int mp;
int sccfirst; int sccfirst;
unsigned int monte[RT_MONTEN]; unsigned int monte[RT_MONTEN];
int64_t inmont, mcount; int64_t inmont, mcount;
double cexp, montex, montey, montepi, double cexp, montex, montey, montepi, sccu0, scclast, scct1, scct2, scct3;
sccu0, scclast, scct1, scct2, scct3; };
};
} // namespace detail } // namespace detail
} // namespace zeek } // namespace zeek

View file

@ -1,15 +1,16 @@
// See the file "COPYING" in the main distribution directory for copyright. // See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Reassem.h" #include "zeek/Reassem.h"
#include <algorithm> #include <algorithm>
#include "zeek/Desc.h" #include "zeek/Desc.h"
#include "zeek/zeek-config.h"
using std::min; using std::min;
namespace zeek { namespace zeek
{
uint64_t Reassembler::total_size = 0; uint64_t Reassembler::total_size = 0;
uint64_t Reassembler::sizes[REASSEM_NUM]; uint64_t Reassembler::sizes[REASSEM_NUM];
@ -100,9 +101,8 @@ DataBlockMap::const_iterator DataBlockList::FirstBlockAtOrBefore(uint64_t seq) c
return std::prev(it); return std::prev(it);
} }
DataBlockMap::const_iterator DataBlockMap::const_iterator DataBlockList::Insert(uint64_t seq, uint64_t upper, const u_char* data,
DataBlockList::Insert(uint64_t seq, uint64_t upper, const u_char* data, DataBlockMap::const_iterator hint)
DataBlockMap::const_iterator hint)
{ {
auto size = upper - seq; auto size = upper - seq;
auto rval = block_map.emplace_hint(hint, seq, DataBlock(data, size, seq)); auto rval = block_map.emplace_hint(hint, seq, DataBlock(data, size, seq));
@ -114,9 +114,8 @@ DataBlockList::Insert(uint64_t seq, uint64_t upper, const u_char* data,
return rval; return rval;
} }
DataBlockMap::const_iterator DataBlockMap::const_iterator DataBlockList::Insert(uint64_t seq, uint64_t upper, const u_char* data,
DataBlockList::Insert(uint64_t seq, uint64_t upper, const u_char* data, DataBlockMap::const_iterator* hint)
DataBlockMap::const_iterator* hint)
{ {
// Empty list. // Empty list.
if ( block_map.empty() ) if ( block_map.empty() )
@ -191,8 +190,7 @@ DataBlockList::Insert(uint64_t seq, uint64_t upper, const u_char* data,
return rval; return rval;
} }
uint64_t DataBlockList::Trim(uint64_t seq, uint64_t max_old, uint64_t DataBlockList::Trim(uint64_t seq, uint64_t max_old, DataBlockList* old_list)
DataBlockList* old_list)
{ {
uint64_t num_missing = 0; uint64_t num_missing = 0;
@ -267,14 +265,12 @@ uint64_t DataBlockList::Trim(uint64_t seq, uint64_t max_old,
} }
Reassembler::Reassembler(uint64_t init_seq, ReassemblerType reassem_type) Reassembler::Reassembler(uint64_t init_seq, ReassemblerType reassem_type)
: block_list(this), old_block_list(this), : block_list(this), old_block_list(this), last_reassem_seq(init_seq), trim_seq(init_seq),
last_reassem_seq(init_seq), trim_seq(init_seq),
max_old_blocks(0), rtype(reassem_type) max_old_blocks(0), rtype(reassem_type)
{ {
} }
void Reassembler::CheckOverlap(const DataBlockList& list, void Reassembler::CheckOverlap(const DataBlockList& list, uint64_t seq, uint64_t len,
uint64_t seq, uint64_t len,
const u_char* data) const u_char* data)
{ {
if ( list.Empty() ) if ( list.Empty() )
@ -347,7 +343,8 @@ void Reassembler::NewBlock(double t, uint64_t seq, uint64_t len, const u_char* d
len -= amount_old; len -= amount_old;
} }
auto it = block_list.Insert(seq, upper_seq, data);; auto it = block_list.Insert(seq, upper_seq, data);
;
BlockInserted(it); BlockInserted(it);
} }
@ -387,4 +384,4 @@ uint64_t Reassembler::MemoryAllocation(ReassemblerType rtype)
return Reassembler::sizes[rtype]; return Reassembler::sizes[rtype];
} }
} // namespace zeek } // namespace zeek

Some files were not shown because too many files have changed in this diff Show more