Merge remote-tracking branch 'origin/topic/timw/386-clang-format'

* origin/topic/timw/386-clang-format:
  Minor fixes for build problems after reformatting
  Reformat the world
  Fixes for includes ahead of reformatting
  GH-386: Add clang-format config and scripts
This commit is contained in:
Tim Wojtulewicz 2021-09-16 15:36:52 -07:00
commit 9068b71750
723 changed files with 35332 additions and 35168 deletions

98
.clang-format Normal file
View file

@ -0,0 +1,98 @@
# Clang-format configuration for Zeek. This configuration requires
# at least clang-format 12.0.1 to format correctly.
#
# The easiest way to run this from the command-line is using the
# python script in auxil/run-clang-format:
#
# python3 auxil/run-clang-format/run-clang-format.py --clang-format-executable /path/to/clang-format -r src -i
Language: Cpp
Standard: c++17
BreakBeforeBraces: Whitesmiths
# BraceWrapping:
# AfterCaseLabel: true
# AfterClass: false
# AfterControlStatement: Always
# AfterEnum: false
# AfterFunction: true
# AfterNamespace: false
# AfterStruct: false
# AfterUnion: false
# AfterExternBlock: false
# BeforeCatch: true
# BeforeElse: true
# BeforeWhile: false
# IndentBraces: true
# SplitEmptyFunction: false
# SplitEmptyRecord: false
# SplitEmptyNamespace: false
AccessModifierOffset: -4
AlignAfterOpenBracket: true
AlignTrailingComments: false
AllowShortBlocksOnASingleLine: Empty
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
BinPackArguments: true
BinPackParameters: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: false
FixNamespaceComments: false
IndentCaseLabels: true
IndentCaseBlocks: true
IndentExternBlock: NoIndent
IndentPPDirectives: None
IndentWidth: 4
NamespaceIndentation: None
PointerAlignment: Left
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInConditionalStatement: true
SpacesInContainerLiterals: false
SpacesInParentheses: false
TabWidth: 4
UseTab: AlignWithSpaces
IncludeBlocks: Regroup
# Include categories go like this:
# 0: reserved, since this automatically is the primary header for any .cc file
# 1: zeek-config.h
# 2: any c-style header
# 3: any c++-style header
# 4: any header that starts with "zeek/"
# 5: everything else, which should catch any of the auto-generated code from the
# build directory as well
#
# Sections 0-1 and 2-3 get group together in their respective blocks
IncludeCategories:
- Regex: '^"zeek-config\.h"'
Priority: 0
SortPriority: 1
- Regex: '^<[[:print:]]+\.(h|hh)>'
Priority: 2
SortPriority: 2
- Regex: '^<[[:print:]]+>'
Priority: 2
SortPriority: 3
- Regex: '^"zeek/'
Priority: 4
- Regex: '.*'
Priority: 5

17
.clang-format-ignore Normal file
View file

@ -0,0 +1,17 @@
# Ignore everything 3rdparty
src/3rdparty/*
# These are files that are technically sourced from other places but aren't in 3rdparty
# and shouldn't be reformatted.
src/ConvertUTF.*
src/bro_inet_ntop.*
src/bsd-getopt-long.*
src/in_cksum.*
src/nb_dns.*
src/modp_numtoa.*
src/patricia.*
src/strsep.c
src/setsignal.c
# These files are generated code
src/DebugCmdInfoConstants.*

3
.gitmodules vendored
View file

@ -49,3 +49,6 @@
[submodule "auxil/zeek-client"]
path = auxil/zeek-client
url = https://github.com/zeek/zeek-client
[submodule "auxil/run-clang-format"]
path = auxil/run-clang-format
url = https://github.com/Sarcasm/run-clang-format

View file

@ -1,3 +1,12 @@
4.2.0-dev.174 | 2021-09-16 15:36:52 -0700
* Minor fixes for build problems after reformatting (Tim Wojtulewicz, Corelight)
* Reformat the world (Tim Wojtulewicz, Corelight)
* Fixes for includes ahead of reformatting (Tim Wojtulewicz, Corelight)
* GH-386: Add clang-format config and scripts (Tim Wojtulewicz, Corelight)
4.2.0-dev.169 | 2021-09-16 11:15:14 +0200

8
NEWS
View file

@ -9,6 +9,14 @@ Zeek 4.2.0
New Functionality
-----------------
- Zeek now supports formatting the C++ code using clang-format. It requires at
least clang-format 12.0.1 due to some additions that were made in that version
to better support the Whitesmiths style. Zeek also includes a set of python
scripts to more easily reformat in the auxil/run-clang-format directory. An
example command to reformat the code:
`python3 auxil/run-clang-format/run-clang-format.py --clang-format-executable `which clang-format-12` -r src -i`
Changed Functionality
---------------------

View file

@ -1 +1 @@
4.2.0-dev.169
4.2.0-dev.174

@ -0,0 +1 @@
Subproject commit 39081c9c42768ab5e8321127a7494ad1647c6a2f

65
ci/run-clang-format.sh Executable file
View file

@ -0,0 +1,65 @@
#! /bin/sh
#
# Copyright (c) 2020 by the Zeek Project. See LICENSE for details.
base=$(git rev-parse --show-toplevel)
fix=0
pre_commit_hook=0
# Directories to run on by default. When changing, adapt .pre-commit-config.yam
# as well.
files="src"
error() {
test "${pre_commit_hook}" = 0 && echo "$@" >&2 && exit 1
exit 0
}
if [ $# != 0 ]; then
case "$1" in
--fixit)
shift
fix=1
;;
--pre-commit-hook)
shift
fix=1
pre_commit_hook=1
;;
-*)
echo "usage: $(basename $0) [--fixit | --pre-commit-hook] [<files>]"
exit 1
esac
fi
test $# != 0 && files="$@"
if [ -z "${CLANG_FORMAT}" ]; then
CLANG_FORMAT=$(which clang-format 2>/dev/null)
fi
if [ -z "${CLANG_FORMAT}" -o ! -x "${CLANG_FORMAT}" ]; then
error "Cannot find clang-format. If not in PATH, set CLANG_FORMAT."
fi
if ! (cd / && ${CLANG_FORMAT} -dump-config | grep -q SpacesInConditionalStatement); then
error "${CLANG_FORMAT} does not support SpacesInConditionalStatement. Install custom version and put it into PATH, or point CLANG_FORMAT to it."
fi
if [ ! -e .clang-format ]; then
error "Must execute in top-level directory."
fi
cmd="${base}/auxil/run-clang-format/run-clang-format.py -r --clang-format-executable ${CLANG_FORMAT} --exclude '*/3rdparty/*' ${files}"
tmp=/tmp/$(basename $0).$$.tmp
trap "rm -f ${tmp}" EXIT
eval "${cmd}" >"${tmp}"
if [ "${fix}" = 1 ]; then
test -s "${tmp}" && cat "${tmp}" | git apply -p0
true
else
cat "${tmp}"
fi

View file

@ -1,36 +1,36 @@
#include "zeek/Anon.h"
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include "zeek/util.h"
#include "zeek/net_util.h"
#include "zeek/Val.h"
#include "zeek/Event.h"
#include "zeek/ID.h"
#include "zeek/IPAddr.h"
#include "zeek/NetVar.h"
#include "zeek/Reporter.h"
#include "zeek/Scope.h"
#include "zeek/ID.h"
#include "zeek/IPAddr.h"
#include "zeek/Event.h"
#include "zeek/Val.h"
#include "zeek/net_util.h"
#include "zeek/util.h"
namespace zeek::detail {
namespace zeek::detail
{
AnonymizeIPAddr* ip_anonymizer[NUM_ADDR_ANONYMIZATION_METHODS] = {nullptr};
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.
static int bi_ffs(uint32_t value)
{
int add = 0;
static uint8_t bvals[] = {
0, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1
};
static uint8_t bvals[] = {0, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1};
if ( (value & 0xFFFF0000) == 0 )
{
@ -57,7 +57,7 @@ static int bi_ffs(uint32_t value)
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)
{
@ -82,16 +82,17 @@ bool AnonymizeIPAddr::PreservePrefix(ipaddr32_t /* input */, int /* num_bits */)
bool AnonymizeIPAddr::PreserveNet(ipaddr32_t input)
{
switch ( addr_to_class(ntohl(input)) ) {
case 'A':
return PreservePrefix(input, 8);
case 'B':
return PreservePrefix(input, 16);
case 'C':
return PreservePrefix(input, 24);
default:
return false;
}
switch ( addr_to_class(ntohl(input)) )
{
case 'A':
return PreservePrefix(input, 8);
case 'B':
return PreservePrefix(input, 16);
case 'C':
return PreservePrefix(input, 24);
default:
return false;
}
}
ipaddr32_t AnonymizeIPAddr_Seq::anonymize(ipaddr32_t /* input */)
@ -113,7 +114,6 @@ ipaddr32_t AnonymizeIPAddr_RandomMD5::anonymize(ipaddr32_t input)
return output;
}
// This code is from "On the Design and Performance of Prefix-Preserving
// 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 .
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})).
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}))).
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}.
output ^= bit_mask;
@ -148,7 +148,7 @@ ipaddr32_t AnonymizeIPAddr_PrefixMD5::anonymize(ipaddr32_t input)
AnonymizeIPAddr_A50::~AnonymizeIPAddr_A50()
{
for ( auto& b : blocks )
delete [] b;
delete[] b;
}
void AnonymizeIPAddr_A50::init()
@ -167,9 +167,7 @@ void AnonymizeIPAddr_A50::init()
bool AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits)
{
DEBUG_MSG("%s/%d\n",
IPAddr(IPv4, &input, IPAddr::Network).AsString().c_str(),
num_bits);
DEBUG_MSG("%s/%d\n", IPAddr(IPv4, &input, IPAddr::Network).AsString().c_str(), num_bits);
if ( ! before_anonymization )
{
@ -225,7 +223,7 @@ AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node_block()
blocks.push_back(block);
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;
next_free_node = &block[1];
@ -247,7 +245,7 @@ inline AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node()
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;
next_free_node = n;
@ -261,8 +259,7 @@ ipaddr32_t AnonymizeIPAddr_A50::make_output(ipaddr32_t old_output, int swivel) c
else
{
// Bits up to swivel are unchanged; bit swivel is flipped.
ipaddr32_t known_part =
((old_output >> (32 - swivel)) ^ 1) << (32 - swivel);
ipaddr32_t known_part = ((old_output >> (32 - swivel)) ^ 1) << (32 - swivel);
// Remainder of bits are random.
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]->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->child[0] = down[0]; // point to children
n->child[0] = down[0]; // point to children
n->child[1] = down[1];
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
// differ.
int swivel =
bi_ffs(n->child[0]->input ^ n->child[1]->input);
int swivel = bi_ffs(n->child[0]->input ^ n->child[1]->input);
if ( bi_ffs(a ^ n->input) < swivel )
// Input differs earlier.
@ -394,22 +390,23 @@ ipaddr32_t anonymize_ip(ipaddr32_t ip, enum ip_addr_anonymization_class_t cl)
int method = -1;
switch ( cl ) {
case ORIG_ADDR: // client address
preserve_addr = anon_preserve_orig_addr.get();
method = orig_addr_anonymization;
break;
switch ( cl )
{
case ORIG_ADDR: // client address
preserve_addr = anon_preserve_orig_addr.get();
method = orig_addr_anonymization;
break;
case RESP_ADDR: // server address
preserve_addr = anon_preserve_resp_addr.get();
method = resp_addr_anonymization;
break;
case RESP_ADDR: // server address
preserve_addr = anon_preserve_resp_addr.get();
method = resp_addr_anonymization;
break;
default:
preserve_addr = anon_preserve_other_addr.get();
method = other_addr_anonymization;
break;
}
default:
preserve_addr = anon_preserve_other_addr.get();
method = other_addr_anonymization;
break;
}
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)
{
if ( anonymization_mapping )
event_mgr.Enqueue(anonymization_mapping,
make_intrusive<AddrVal>(input),
make_intrusive<AddrVal>(output)
);
event_mgr.Enqueue(anonymization_mapping, make_intrusive<AddrVal>(input),
make_intrusive<AddrVal>(output));
}
#endif
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -10,36 +10,40 @@
#pragma once
#include <vector>
#include <map>
#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 ...
enum ip_addr_anonymization_class_t {
ORIG_ADDR, // client address
RESP_ADDR, // server address
enum ip_addr_anonymization_class_t
{
ORIG_ADDR, // client address
RESP_ADDR, // server address
OTHER_ADDR,
NUM_ADDR_ANONYMIZATION_CLASSES,
};
};
enum ip_addr_anonymization_method_t {
enum ip_addr_anonymization_method_t
{
KEEP_ORIG_ADDR,
SEQUENTIALLY_NUMBERED,
RANDOM_MD5,
PREFIX_PRESERVING_A50,
PREFIX_PRESERVING_MD5,
NUM_ADDR_ANONYMIZATION_METHODS,
};
};
typedef uint32_t ipaddr32_t;
// NOTE: all addresses in parameters of *public* functions are in
// network order.
class AnonymizeIPAddr {
class AnonymizeIPAddr
{
public:
virtual ~AnonymizeIPAddr() = default;
@ -53,47 +57,53 @@ public:
protected:
std::map<ipaddr32_t, ipaddr32_t> mapping;
};
};
class AnonymizeIPAddr_Seq : public AnonymizeIPAddr {
class AnonymizeIPAddr_Seq : public AnonymizeIPAddr
{
public:
AnonymizeIPAddr_Seq() { seq = 1; }
AnonymizeIPAddr_Seq() { seq = 1; }
ipaddr32_t anonymize(ipaddr32_t addr) override;
protected:
ipaddr32_t seq;
};
};
class AnonymizeIPAddr_RandomMD5 : public AnonymizeIPAddr {
class AnonymizeIPAddr_RandomMD5 : public AnonymizeIPAddr
{
public:
ipaddr32_t anonymize(ipaddr32_t addr) override;
};
};
class AnonymizeIPAddr_PrefixMD5 : public AnonymizeIPAddr {
class AnonymizeIPAddr_PrefixMD5 : public AnonymizeIPAddr
{
public:
ipaddr32_t anonymize(ipaddr32_t addr) override;
protected:
struct anon_prefix {
struct anon_prefix
{
int len;
ipaddr32_t prefix;
} prefix;
};
} prefix;
};
class AnonymizeIPAddr_A50 : public AnonymizeIPAddr {
class AnonymizeIPAddr_A50 : public AnonymizeIPAddr
{
public:
AnonymizeIPAddr_A50() { init(); }
AnonymizeIPAddr_A50() { init(); }
~AnonymizeIPAddr_A50() override;
ipaddr32_t anonymize(ipaddr32_t addr) override;
bool PreservePrefix(ipaddr32_t input, int num_bits) override;
protected:
struct Node {
struct Node
{
ipaddr32_t input;
ipaddr32_t output;
Node* child[2];
};
};
int method;
int before_anonymization;
@ -118,7 +128,7 @@ protected:
ipaddr32_t make_output(ipaddr32_t, int) const;
Node* make_peer(ipaddr32_t, Node*);
Node* find_node(ipaddr32_t);
};
};
// The global IP anonymizers.
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
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.
#include "zeek/zeek-config.h"
#include "zeek/Attr.h"
#include "zeek/Expr.h"
#include "zeek/Desc.h"
#include "zeek/Val.h"
#include "zeek/Expr.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/Val.h"
#include "zeek/input/Manager.h"
#include "zeek/threading/SerialTypes.h"
#include "zeek/zeek-config.h"
namespace zeek::detail {
namespace zeek::detail
{
const char* attr_name(AttrTag t)
{
static const char* attr_names[int(NUM_ATTRS)] = {
"&optional", "&default", "&redef",
"&add_func", "&delete_func", "&expire_func",
"&read_expire", "&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",
"&optional",
"&default",
"&redef",
"&add_func",
"&delete_func",
"&expire_func",
"&read_expire",
"&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)];
}
Attr::Attr(AttrTag t, ExprPtr e)
: expr(std::move(e))
Attr::Attr(AttrTag t, ExprPtr e) : expr(std::move(e))
{
tag = t;
SetLocationInfo(&start_location, &end_location);
}
Attr::Attr(AttrTag t)
: Attr(t, nullptr)
{
}
Attr::Attr(AttrTag t) : Attr(t, nullptr) { }
void Attr::SetAttrExpr(ExprPtr e)
{ expr = std::move(e); }
{
expr = std::move(e);
}
std::string Attr::DeprecationMessage() const
{
@ -71,7 +85,7 @@ void Attr::Describe(ODesc* d) const
void Attr::DescribeReST(ODesc* d, bool shorten) const
{
auto add_long_expr_string = [](ODesc* d, const std::string& s, bool shorten)
{
{
constexpr auto max_expr_chars = 32;
constexpr auto shortened_expr = "*...*";
@ -93,7 +107,7 @@ void Attr::DescribeReST(ODesc* d, bool shorten) const
d->Add(s);
d->Add("``");
}
};
};
d->Add(":zeek:attr:`");
AddTag(d);
@ -152,12 +166,11 @@ void Attr::AddTag(ODesc* d) const
}
Attributes::Attributes(TypePtr t, bool arg_in_record, bool is_global)
: Attributes(std::vector<AttrPtr>{}, std::move(t),
arg_in_record, is_global)
{}
: Attributes(std::vector<AttrPtr>{}, std::move(t), arg_in_record, is_global)
{
}
Attributes::Attributes(std::vector<AttrPtr> a,
TypePtr t, bool arg_in_record, bool is_global)
Attributes::Attributes(std::vector<AttrPtr> a, TypePtr t, bool arg_in_record, bool is_global)
: type(std::move(t))
{
attrs.reserve(a.size());
@ -177,22 +190,22 @@ Attributes::Attributes(std::vector<AttrPtr> a,
void Attributes::AddAttr(AttrPtr attr, bool is_redef)
{
auto acceptable_duplicate_attr = [](const AttrPtr& attr, const AttrPtr& existing) -> bool
{
{
AttrTag new_tag = attr->Tag();
if ( new_tag == ATTR_DEPRECATED )
{
if ( ! attr->DeprecationMessage().empty() ||
( existing && ! existing->DeprecationMessage().empty() ) )
(existing && ! existing->DeprecationMessage().empty()) )
return false;
return true;
}
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_ERROR_HANDLER;
};
new_tag == ATTR_BROKER_STORE_ALLOW_COMPLEX || new_tag == ATTR_RAW_OUTPUT ||
new_tag == ATTR_ERROR_HANDLER;
};
// A `redef` is allowed to overwrite an existing attribute instead of
// 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
// those attributes only have meaning for a redefinable value.
if ( (attr->Tag() == ATTR_ADD_FUNC || attr->Tag() == ATTR_DEL_FUNC) &&
! Find(ATTR_REDEF) )
if ( (attr->Tag() == ATTR_ADD_FUNC || attr->Tag() == ATTR_DEL_FUNC) && ! Find(ATTR_REDEF) )
{
auto a = make_intrusive<Attr>(ATTR_REDEF);
attrs.emplace_back(std::move(a));
}
// For DEFAULT, add an implicit OPTIONAL if it's not a global.
if ( ! global_var && attr->Tag() == ATTR_DEFAULT &&
! Find(ATTR_OPTIONAL) )
if ( ! global_var && attr->Tag() == ATTR_DEFAULT && ! Find(ATTR_OPTIONAL) )
{
auto a = make_intrusive<Attr>(ATTR_OPTIONAL);
attrs.emplace_back(std::move(a));
@ -290,425 +301,420 @@ void Attributes::DescribeReST(ODesc* d, bool shorten) const
void Attributes::CheckAttr(Attr* a)
{
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:
switch ( a->Tag() )
{
bool is_add = a->Tag() == ATTR_ADD_FUNC;
const auto& at = a->GetExpr()->GetType();
if ( at->Tag() != TYPE_FUNC )
{
a->GetExpr()->Error(
is_add ?
"&add_func must be a function" :
"&delete_func must be a function");
case ATTR_DEPRECATED:
case ATTR_REDEF:
case ATTR_IS_ASSIGNED:
case ATTR_IS_USED:
break;
}
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");
case ATTR_OPTIONAL:
if ( global_var )
Error("&optional is not valid for global variables");
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 )
case ATTR_ADD_FUNC:
case ATTR_DEL_FUNC:
{
a->SetAttrExpr(std::move(e));
// Ok.
break;
}
bool is_add = a->Tag() == ATTR_ADD_FUNC;
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 )
const auto& at = a->GetExpr()->GetType();
if ( at->Tag() != TYPE_FUNC )
{
FuncType* f = atype->AsFuncType();
if ( ! f->CheckArgs(tt->GetIndexTypes()) ||
! same_type(f->Yield(), ytype) )
Error("&default function type clash");
a->GetExpr()->Error(is_add ? "&add_func must be a function"
: "&delete_func must be a function");
break;
}
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.
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 )
else
{
a->SetAttrExpr(std::move(e));
// Ok.
break;
// &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 ( 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;
}
else
{
// &default applies to record field.
if ( same_type(atype, type) )
// Ok.
break;
if ( (atype->Tag() == TYPE_TABLE && atype->AsTableType()->IsUnspecifiedTable()) )
case ATTR_EXPIRE_READ:
{
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;
}
}
// 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
//### not easy to test this w/o knowing the ID.
if ( ! global_var )
Error("expiration not supported for local variables");
#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;
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]) )
case ATTR_EXPIRE_FUNC:
{
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;
}
}
if ( ! type->IsSet() )
if ( ! same_type(args[2+t_indexes.size()], the_table->Yield()) )
case ATTR_ON_CHANGE:
{
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;
}
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
@ -744,4 +750,4 @@ bool Attributes::operator==(const Attributes& other) const
return true;
}
}
}

View file

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

View file

@ -1,21 +1,23 @@
#include "zeek/zeek-config.h"
#include "zeek/Base64.h"
#include <math.h>
#include "zeek/Base64.h"
#include "zeek/ZeekString.h"
#include "zeek/Reporter.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];
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)
{
int blen;
char *buf;
char* buf;
if ( ! pbuf )
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;
}
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;
bit32 += (i++ < len ? data[i-1] : 0) << 8;
bit32 += i++ < len ? data[i-1] : 0;
uint32_t bit32 = data[i++] << 16;
bit32 += (i++ < len ? data[i - 1] : 0) << 8;
bit32 += i++ < len ? data[i - 1] : 0;
buf[j++] = alphabet[(bit32 >> 18) & 0x3f];
buf[j++] = alphabet[(bit32 >> 12) & 0x3f];
buf[j++] = (i == (len+2)) ? '=' : alphabet[(bit32 >> 6) & 0x3f];
buf[j++] = (i >= (len+1)) ? '=' : alphabet[bit32 & 0x3f];
buf[j++] = alphabet[(bit32 >> 18) & 0x3f];
buf[j++] = alphabet[(bit32 >> 12) & 0x3f];
buf[j++] = (i == (len + 2)) ? '=' : alphabet[(bit32 >> 6) & 0x3f];
buf[j++] = (i >= (len + 1)) ? '=' : alphabet[bit32 & 0x3f];
}
}
int* Base64Converter::InitBase64Table(const std::string& alphabet)
{
assert(alphabet.size() == 64);
@ -111,7 +112,7 @@ Base64Converter::Base64Converter(Connection* arg_conn, const std::string& arg_al
Base64Converter::~Base64Converter()
{
if ( base64_table != default_base64_table )
delete [] base64_table;
delete[] base64_table;
}
int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
@ -160,11 +161,8 @@ int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
if ( buf + num_octets > *pbuf + blen )
break;
uint32_t bit32 =
((base64_group[0] & 0x3f) << 18) |
((base64_group[1] & 0x3f) << 12) |
((base64_group[2] & 0x3f) << 6) |
((base64_group[3] & 0x3f));
uint32_t bit32 = ((base64_group[0] & 0x3f) << 18) | ((base64_group[1] & 0x3f) << 12) |
((base64_group[2] & 0x3f) << 6) | ((base64_group[3] & 0x3f));
if ( --num_octets >= 0 )
*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);
if ( --num_octets >= 0 )
*buf++ = char((bit32) & 0xff);
*buf++ = char((bit32)&0xff);
if ( base64_padding > 0 )
base64_after_padding = 1;
@ -188,13 +186,14 @@ int Base64Converter::Decode(int len, const char* data, int* pblen, char** pbuf)
if ( data[dlen] == '=' )
++base64_padding;
int k = base64_table[(unsigned char) data[dlen]];
int k = base64_table[(unsigned char)data[dlen]];
if ( k >= 0 )
base64_group[base64_group_next++] = k;
else
{
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;
@ -212,7 +211,7 @@ int Base64Converter::Done(int* pblen, char** pbuf)
{
if ( base64_group_next < 4 )
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);
return -1;
}
@ -224,29 +223,28 @@ int Base64Converter::Done(int* pblen, char** pbuf)
}
void Base64Converter::IllegalEncoding(const char* msg)
{
// strncpy(error_msg, msg, sizeof(error_msg));
if ( conn )
conn->Weird("base64_illegal_encoding", msg);
else
reporter->Error("%s", msg);
}
{
// strncpy(error_msg, msg, sizeof(error_msg));
if ( conn )
conn->Weird("base64_illegal_encoding", msg);
else
reporter->Error("%s", msg);
}
String* decode_base64(const String* s, const String* a, Connection* conn)
{
if ( a && a->Len() != 0 && a->Len() != 64 )
{
reporter->Error("base64 decoding alphabet is not 64 characters: %s",
a->CheckString());
reporter->Error("base64 decoding alphabet is not 64 characters: %s", a->CheckString());
return nullptr;
}
int buf_len = int((s->Len() + 3) / 4) * 3 + 1;
int rlen2, rlen = buf_len;
char* rbuf2, *rbuf = new char[rlen];
char *rbuf2, *rbuf = new char[rlen];
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() )
goto err;
@ -259,10 +257,10 @@ String* decode_base64(const String* s, const String* a, Connection* conn)
rlen += rlen2;
rbuf[rlen] = '\0';
return new String(true, (u_char*) rbuf, rlen);
return new String(true, (u_char*)rbuf, rlen);
err:
delete [] rbuf;
delete[] rbuf;
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 )
{
reporter->Error("base64 alphabet is not 64 characters: %s",
a->CheckString());
reporter->Error("base64 alphabet is not 64 characters: %s", a->CheckString());
return nullptr;
}
char* outbuf = nullptr;
int outlen = 0;
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);
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -1,17 +1,21 @@
#pragma once
#include "zeek/zeek-config.h"
#include <string>
namespace zeek {
#include "zeek/zeek-config.h"
namespace zeek
{
class String;
class Connection;
namespace detail {
namespace detail
{
// Maybe we should have a base class for generic decoders?
class Base64Converter {
class Base64Converter
{
public:
// <conn> is used for error reporting. If it is set to zero (as,
// e.g., done by the built-in functions decode_base64() and
@ -38,9 +42,9 @@ public:
bool HasData() const { return base64_group_next != 0; }
// 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);
protected:
@ -57,13 +61,12 @@ protected:
int base64_padding;
int base64_after_padding;
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;
};
};
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);
} // namespace detail
} // namespace zeek
} // namespace detail
} // namespace zeek

View file

@ -1,11 +1,12 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/BifReturnVal.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
#include "zeek/zeek-config.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/zeek-config.h"
namespace zeek {
namespace zeek
{
class Val;
using ValPtr = IntrusivePtr<Val>;
namespace detail {
namespace detail
{
/**
* 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
* potentially be deprecated).
*/
class BifReturnVal {
class BifReturnVal
{
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;
ValPtr rval;
};
};
} // namespace detail
} // namespace zeek
} // namespace detail
} // namespace zeek

View file

@ -1,14 +1,15 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/CCL.h"
#include <algorithm>
#include "zeek/RE.h"
#include "zeek/DFA.h"
#include "zeek/RE.h"
#include "zeek/zeek-config.h"
namespace zeek::detail {
namespace zeek::detail
{
CCL::CCL()
{
@ -48,7 +49,8 @@ void CCL::Sort()
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 <vector>
namespace zeek::detail {
namespace zeek::detail
{
using int_list = std::vector<std::intptr_t>;
class CCL {
class CCL
{
public:
CCL();
~CCL();
void Add(int sym);
void Negate();
bool IsNegated() { return negated != 0; }
int Index() { return index; }
bool IsNegated() { return negated != 0; }
int Index() { return index; }
void Sort();
int_list* Syms() { return syms; }
int_list* Syms() { return 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.")]]
unsigned int MemoryAllocation() const;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] unsigned int
MemoryAllocation() const;
protected:
int_list* syms;
int negated;
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 "zeek/Type.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/Type.h"
namespace zeek {
namespace zeek
{
class ListVal;
using ListValPtr = zeek::IntrusivePtr<ListVal>;
} // namespace zeek
} // namespace zeek
namespace zeek::detail {
namespace zeek::detail
{
class HashKey;
class CompositeHash {
class CompositeHash
{
public:
explicit CompositeHash(TypeListPtr composite_type);
~CompositeHash();
@ -30,24 +33,26 @@ public:
// Given a hash key, recover the values used to create it.
ListValPtr RecoverVals(const HashKey& k) const;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]]
unsigned int MemoryAllocation() const { return padded_sizeof(*this) + util::pad_size(size); }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] unsigned int
MemoryAllocation() const
{
return padded_sizeof(*this) + util::pad_size(size);
}
protected:
std::unique_ptr<HashKey> ComputeSingletonHash(const Val* v, bool type_check) const;
// Computes the piece of the hash for Val*, returning the new kp.
// Used as a helper for ComputeHash in the non-singleton case.
char* SingleValHash(bool type_check, char* kp, Type* bt, Val* v,
bool optional) const;
char* SingleValHash(bool type_check, char* kp, Type* bt, Val* v, bool optional) const;
// Recovers just one Val of possibly many; called from RecoverVals.
// Upon return, pval will point to the recovered Val of type t.
// Returns and updated kp for the next Val. Calls reporter->InternalError()
// upon errors, so there is no return value for invalid input.
const char* RecoverOneVal(
const HashKey& k, const char* kp, const char* const k_end,
Type* t, ValPtr* pval, bool optional) const;
const char* RecoverOneVal(const HashKey& k, const char* kp, const char* const k_end, Type* t,
ValPtr* pval, bool optional) const;
// Rounds the given pointer up to the nearest multiple of the
// given size, if not already a multiple.
@ -61,44 +66,36 @@ protected:
// of the given size.
int SizeAlign(int offset, unsigned int size) const;
template<class T>
T* AlignAndPadType(char* ptr) const
template <class T> T* AlignAndPadType(char* ptr) const
{
return reinterpret_cast<T*>(AlignAndPad(ptr, sizeof(T)));
}
template<class T>
const T* AlignType(const char* ptr) const
template <class T> const T* AlignType(const char* ptr) const
{
return reinterpret_cast<const T*>(Align(ptr, sizeof(T)));
}
template<class T>
int SizeAlignType(int offset) const
{
return SizeAlign(offset, sizeof(T));
}
template <class T> int SizeAlignType(int offset) const { return SizeAlign(offset, sizeof(T)); }
// Compute the size of the composite key. If v is non-nil then
// the value is computed for the particular list of values.
// Returns 0 if the key has an indeterminant size (if v not given),
// or if v doesn't match the index type (if given).
int ComputeKeySize(const Val* v, bool type_check,
bool calc_static_size) const;
int ComputeKeySize(const Val* v, bool type_check, bool calc_static_size) const;
int SingleTypeKeySize(Type*, const Val*,
bool type_check, int sz, bool optional,
int SingleTypeKeySize(Type*, const Val*, bool type_check, int sz, bool optional,
bool calc_static_size) const;
TypeListPtr type;
char* key; // space for composite key
char* key; // space for composite key
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.
bool is_complex_type;
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.
#include "zeek/zeek-config.h"
#include "zeek/Conn.h"
#include <ctype.h>
#include <binpac.h>
#include <ctype.h>
#include "zeek/Desc.h"
#include "zeek/RunState.h"
#include "zeek/NetVar.h"
#include "zeek/Event.h"
#include "zeek/session/Manager.h"
#include "zeek/NetVar.h"
#include "zeek/Reporter.h"
#include "zeek/RunState.h"
#include "zeek/Timer.h"
#include "zeek/iosource/IOSource.h"
#include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/TunnelEncapsulation.h"
#include "zeek/analyzer/Analyzer.h"
#include "zeek/analyzer/Manager.h"
#include "zeek/analyzer/protocol/pia/PIA.h"
#include "zeek/iosource/IOSource.h"
#include "zeek/packet_analysis/protocol/ip/SessionAdapter.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::current_connections = 0;
Connection::Connection(const detail::ConnKey& k, double t,
const ConnTuple* id, uint32_t flow, const Packet* pkt)
Connection::Connection(const detail::ConnKey& k, double t, const ConnTuple* id, uint32_t flow,
const Packet* pkt)
: Session(t, connection_timeout, connection_status_update,
detail::connection_status_update_interval),
detail::connection_status_update_interval),
key(k)
{
orig_addr = id->src_addr;
@ -96,8 +96,7 @@ void Connection::CheckEncapsulation(const std::shared_ptr<EncapsulationStack>& a
if ( *encapsulation != *arg_encap )
{
if ( tunnel_changed )
EnqueueEvent(tunnel_changed, nullptr, GetVal(),
arg_encap->ToVal());
EnqueueEvent(tunnel_changed, nullptr, GetVal(), arg_encap->ToVal());
encapsulation = std::make_shared<EncapsulationStack>(*arg_encap);
}
@ -144,12 +143,10 @@ void Connection::Done()
}
}
void Connection::NextPacket(double t, bool is_orig,
const IP_Hdr* ip, int len, int caplen,
const u_char*& data,
int& record_packet, int& record_content,
void Connection::NextPacket(double t, bool is_orig, const IP_Hdr* ip, int len, int caplen,
const u_char*& data, int& record_packet, int& record_content,
// arguments for reproducing packets
const Packet *pkt)
const Packet* pkt)
{
run_state::current_timestamp = t;
run_state::current_pkt = pkt;
@ -177,8 +174,7 @@ bool Connection::IsReuse(double t, const u_char* pkt)
return adapter && adapter->IsReuse(t, pkt);
}
bool Connection::ScaledHistoryEntry(char code, uint32_t& counter,
uint32_t& scaling_threshold,
bool Connection::ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold,
uint32_t scaling_base)
{
if ( ++counter == scaling_threshold )
@ -202,8 +198,7 @@ bool Connection::ScaledHistoryEntry(char code, uint32_t& counter,
return false;
}
void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig,
uint32_t threshold)
void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, uint32_t threshold)
{
if ( ! e )
return;
@ -213,11 +208,7 @@ void Connection::HistoryThresholdEvent(EventHandlerPtr e, bool is_orig,
// and at this stage it's not a *multiple* instance.
return;
EnqueueEvent(e, nullptr,
GetVal(),
val_mgr->Bool(is_orig),
val_mgr->Count(threshold)
);
EnqueueEvent(e, nullptr, GetVal(), val_mgr->Bool(is_orig), val_mgr->Count(threshold));
}
const RecordValPtr& Connection::GetVal()
@ -257,8 +248,8 @@ const RecordValPtr& Connection::GetVal()
conn_val->Assign(1, std::move(orig_endp));
conn_val->Assign(2, std::move(resp_endp));
// 3 and 4 are set below.
conn_val->Assign(5, make_intrusive<TableVal>(id::string_set)); // service
conn_val->Assign(6, val_mgr->EmptyString()); // history
conn_val->Assign(5, make_intrusive<TableVal>(id::string_set)); // service
conn_val->Assign(6, val_mgr->EmptyString()); // history
if ( ! uid )
uid.Set(zeek::detail::bits_per_uid);
@ -273,13 +264,12 @@ const RecordValPtr& Connection::GetVal()
if ( inner_vlan != 0 )
conn_val->Assign(10, inner_vlan);
}
if ( adapter )
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->Assign(6, history);
@ -318,16 +308,15 @@ static inline bool is_version_sep(const char* s, const char* end)
{
return
// 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
(s < end - 2 && ispunct(s[0]) &&
tolower(s[1]) == 'v' && isdigit(s[2])) ||
(s < end - 2 && ispunct(s[0]) && tolower(s[1]) == 'v' && isdigit(s[2])) ||
// foo 1.2.3
isspace(s[0]);
isspace(s[0]);
}
void Connection::Match(detail::Rule::PatternType type, const u_char* data, int len,
bool is_orig, bool bol, bool eol, bool clear_state)
void Connection::Match(detail::Rule::PatternType type, const u_char* data, int len, bool is_orig,
bool bol, bool eol, bool clear_state)
{
if ( primary_PIA )
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 ignored "-Wdeprecated-declarations"
return session::Session::MemoryAllocation() + padded_sizeof(*this)
+ (timers.MemoryAllocation() - padded_sizeof(timers))
+ (conn_val ? conn_val->MemoryAllocation() : 0)
+ (adapter ? adapter->MemoryAllocation(): 0)
return session::Session::MemoryAllocation() + padded_sizeof(*this) +
(timers.MemoryAllocation() - padded_sizeof(timers)) +
(conn_val ? conn_val->MemoryAllocation() : 0) +
(adapter ? adapter->MemoryAllocation() : 0)
// primary_PIA is already contained in the analyzer tree.
;
#pragma GCC diagnostic pop
@ -404,7 +393,8 @@ void Connection::Describe(ODesc* d) const
{
session::Session::Describe(d);
switch ( proto ) {
switch ( proto )
{
case TRANSPORT_TCP:
d->Add("TCP");
break;
@ -419,14 +409,12 @@ void Connection::Describe(ODesc* d) const
case TRANSPORT_UNKNOWN:
d->Add("unknown");
reporter->InternalWarning(
"unknown transport in Connction::Describe()");
reporter->InternalWarning("unknown transport in Connction::Describe()");
break;
default:
reporter->InternalError(
"unhandled transport type in Connection::Describe");
reporter->InternalError("unhandled transport type in Connection::Describe");
}
d->SP();
@ -455,8 +443,7 @@ void Connection::IDString(ODesc* d) const
d->Add(ntohs(resp_port));
}
void Connection::SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa,
analyzer::pia::PIA* pia)
void Connection::SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia)
{
adapter = aa;
primary_PIA = pia;
@ -477,12 +464,8 @@ void Connection::CheckFlowLabel(bool is_orig, uint32_t flow_label)
if ( connection_flow_label_changed &&
(is_orig ? saw_first_orig_packet : saw_first_resp_packet) )
{
EnqueueEvent(connection_flow_label_changed, nullptr,
GetVal(),
val_mgr->Bool(is_orig),
val_mgr->Count(my_flow_label),
val_mgr->Count(flow_label)
);
EnqueueEvent(connection_flow_label_changed, nullptr, GetVal(), val_mgr->Bool(is_orig),
val_mgr->Count(my_flow_label), val_mgr->Count(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;
}
bool Connection::PermitWeird(const char* name, uint64_t threshold, uint64_t rate,
double duration)
bool Connection::PermitWeird(const char* name, uint64_t threshold, uint64_t rate, double duration)
{
return detail::PermitWeird(weird_state, name, threshold, rate, duration);
}
} // namespace zeek
} // namespace zeek

View file

@ -3,26 +3,25 @@
#pragma once
#include <sys/types.h>
#include <string>
#include <tuple>
#include <type_traits>
#include "zeek/Dict.h"
#include "zeek/Timer.h"
#include "zeek/Rule.h"
#include "zeek/IPAddr.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/Rule.h"
#include "zeek/Timer.h"
#include "zeek/UID.h"
#include "zeek/WeirdState.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/Tag.h"
#include "zeek/iosource/Packet.h"
#include "zeek/session/Session.h"
namespace zeek {
namespace zeek
{
class Connection;
class EncapsulationStack;
@ -32,47 +31,59 @@ class RecordVal;
using ValPtr = IntrusivePtr<Val>;
using RecordValPtr = IntrusivePtr<RecordVal>;
namespace session { class Manager; }
namespace detail {
namespace session
{
class Manager;
}
namespace detail
{
class Specific_RE_Matcher;
class RuleEndpointState;
class RuleHdrTest;
} // namespace detail
} // namespace detail
namespace analyzer { class Analyzer; }
namespace packet_analysis::IP { class SessionAdapter; }
namespace analyzer
{
class Analyzer;
}
namespace packet_analysis::IP
{
class SessionAdapter;
}
enum ConnEventToFlag {
enum ConnEventToFlag
{
NUL_IN_LINE,
SINGULAR_CR,
SINGULAR_LF,
NUM_EVENTS_TO_FLAG,
};
};
struct ConnTuple {
struct ConnTuple
{
IPAddr src_addr;
IPAddr dst_addr;
uint32_t src_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;
};
};
using ConnID [[deprecated("Remove in v5.1. Use zeek::ConnTuple.")]] = ConnTuple;
static inline int addr_port_canon_lt(const IPAddr& addr1, uint32_t p1,
const IPAddr& addr2, uint32_t p2)
static inline int addr_port_canon_lt(const IPAddr& addr1, uint32_t p1, const IPAddr& addr2,
uint32_t p2)
{
return addr1 < addr2 || (addr1 == addr2 && p1 < p2);
}
class Connection final : public session::Session {
class Connection final : public session::Session
{
public:
Connection(const detail::ConnKey& k, double t, const ConnTuple* id,
uint32_t flow, const Packet* pkt);
Connection(const detail::ConnKey& k, double t, const ConnTuple* id, uint32_t flow,
const Packet* pkt);
~Connection() override;
/**
@ -101,34 +112,32 @@ public:
// If record_content is true, then its entire contents should
// be recorded, otherwise just up through the transport header.
// Both are assumed set to true when called.
void NextPacket(double t, bool is_orig,
const IP_Hdr* ip, int len, int caplen,
const u_char*& data,
int& record_packet, int& record_content,
void NextPacket(double t, bool is_orig, const IP_Hdr* ip, int len, int caplen,
const u_char*& data, int& record_packet, int& record_content,
// arguments for reproducing packets
const Packet *pkt);
const Packet* pkt);
// Keys are only considered valid for a connection when a
// connection is in the session map. If it is removed, the key
// 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
{
return session::detail::Key{
&key, sizeof(key), session::detail::Key::CONNECTION_KEY_TYPE, copy};
return session::detail::Key{&key, sizeof(key), session::detail::Key::CONNECTION_KEY_TYPE,
copy};
}
const IPAddr& OrigAddr() const { return orig_addr; }
const IPAddr& RespAddr() const { return resp_addr; }
const IPAddr& OrigAddr() const { return orig_addr; }
const IPAddr& RespAddr() const { return resp_addr; }
uint32_t OrigPort() const { return orig_port; }
uint32_t RespPort() const { return resp_port; }
uint32_t OrigPort() const { return orig_port; }
uint32_t RespPort() const { return resp_port; }
void FlipRoles();
analyzer::Analyzer* FindAnalyzer(analyzer::ID id);
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 analyzer::Tag& tag); // find first in tree.
analyzer::Analyzer* FindAnalyzer(const char* name); // find first in tree.
TransportProto ConnTransport() const { return proto; }
std::string TransportIdentifier() const override
@ -158,8 +167,8 @@ public:
*/
void AppendAddl(const char* str);
void Match(detail::Rule::PatternType type, const u_char* data, int len,
bool is_orig, bool bol, bool eol, bool clear_state);
void Match(detail::Rule::PatternType type, const u_char* data, int len, bool is_orig, bool bol,
bool eol, bool clear_state);
/**
* Generates connection removal event(s).
@ -167,7 +176,7 @@ public:
void RemovalEvent() override;
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)
{
@ -187,15 +196,15 @@ public:
// Statistics.
// Just a lower bound.
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]]
unsigned int MemoryAllocation() const override;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]]
unsigned int MemoryAllocationVal() const override;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] unsigned int
MemoryAllocation() 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()
{ return total_connections; }
static uint64_t CurrentConnections()
{ return current_connections; }
static uint64_t TotalConnections() { return total_connections; }
static uint64_t CurrentConnections() { return current_connections; }
// Returns true if the history was already seen, false otherwise.
bool CheckHistory(uint32_t mask, char code)
@ -214,59 +223,54 @@ public:
// code if it has crossed the next scaling threshold. Scaling
// is done in terms of powers of the third argument.
// Returns true if the threshold was crossed, false otherwise.
bool ScaledHistoryEntry(char code, uint32_t& counter,
uint32_t& scaling_threshold,
bool ScaledHistoryEntry(char code, uint32_t& counter, uint32_t& scaling_threshold,
uint32_t scaling_base = 10);
void HistoryThresholdEvent(EventHandlerPtr e, bool is_orig,
uint32_t threshold);
void HistoryThresholdEvent(EventHandlerPtr e, bool is_orig, 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.
void SetSessionAdapter(packet_analysis::IP::SessionAdapter* aa, analyzer::pia::PIA* pia);
packet_analysis::IP::SessionAdapter* GetSessionAdapter() { return adapter; }
analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; }
packet_analysis::IP::SessionAdapter* GetSessionAdapter() { return adapter; }
analyzer::pia::PIA* GetPrimaryPIA() { return primary_PIA; }
// 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; }
std::shared_ptr<EncapsulationStack> GetEncapsulation() const
{ return encapsulation; }
std::shared_ptr<EncapsulationStack> GetEncapsulation() const { return encapsulation; }
void CheckFlowLabel(bool is_orig, uint32_t flow_label);
uint32_t GetOrigFlowLabel() { return orig_flow_label; }
uint32_t GetRespFlowLabel() { return resp_flow_label; }
bool PermitWeird(const char* name, uint64_t threshold, uint64_t rate,
double duration);
bool PermitWeird(const char* name, uint64_t threshold, uint64_t rate, double duration);
private:
friend class session::detail::Timer;
IPAddr orig_addr;
IPAddr resp_addr;
uint32_t orig_port, resp_port; // in network order
uint32_t orig_port, resp_port; // in network order
TransportProto proto;
uint32_t orig_flow_label, resp_flow_label; // most recent IPv6 flow labels
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 resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available
int suppress_event; // suppress certain events to once per conn.
uint32_t orig_flow_label, resp_flow_label; // most recent IPv6 flow labels
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 resp_l2_addr[Packet::L2_ADDR_LEN]; // Link-layer responder address, if available
int suppress_event; // suppress certain events to once per conn.
RecordValPtr conn_val;
std::shared_ptr<EncapsulationStack> encapsulation; // tunnels
detail::ConnKey key;
unsigned int weird:1;
unsigned int finished:1;
unsigned int saw_first_orig_packet:1, saw_first_resp_packet:1;
unsigned int weird : 1;
unsigned int finished : 1;
unsigned int saw_first_orig_packet : 1, saw_first_resp_packet : 1;
uint32_t hist_seen;
std::string history;
@ -274,12 +278,12 @@ private:
packet_analysis::IP::SessionAdapter* adapter;
analyzer::pia::PIA* primary_PIA;
UID uid; // Globally unique connection ID.
UID uid; // Globally unique connection ID.
detail::WeirdStateMap weird_state;
// Count number of connections.
static uint64_t total_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.
#include "zeek/DFA.h"
#include "zeek/Desc.h"
#include "zeek/EquivClass.h"
#include "zeek/Hash.h"
#include "zeek/zeek-config.h"
#include "zeek/DFA.h"
#include "zeek/EquivClass.h"
#include "zeek/Desc.h"
#include "zeek/Hash.h"
namespace zeek::detail {
namespace zeek::detail
{
unsigned int DFA_State::transition_counter = 0;
DFA_State::DFA_State(int arg_state_num, const EquivClass* ec,
NFA_state_list* arg_nfa_states,
AcceptingSet* arg_accept)
DFA_State::DFA_State(int arg_state_num, const EquivClass* ec, NFA_state_list* arg_nfa_states,
AcceptingSet* arg_accept)
{
state_num = arg_state_num;
num_sym = ec->NumClasses();
@ -31,7 +31,7 @@ DFA_State::DFA_State(int arg_state_num, const EquivClass* ec,
DFA_State::~DFA_State()
{
delete [] xtions;
delete[] xtions;
delete nfa_states;
delete accept;
delete meta_ec;
@ -98,7 +98,7 @@ DFA_State* DFA_State::ComputeXtion(int sym, DFA_Machine* machine)
else
{
delete ns;
next_d = nullptr; // Jam
next_d = nullptr; // Jam
}
AddXtion(equiv_sym, next_d);
@ -163,7 +163,7 @@ NFA_state_list* DFA_State::SymFollowSet(int ec_sym, const EquivClass* ec)
break;
}
}
}
}
else if ( n->TransSym() == SYM_EPSILON )
{ // do nothing
@ -241,15 +241,14 @@ void DFA_State::Dump(FILE* f, DFA_Machine* m)
if ( i == sym + 1 )
sprintf(xbuf, "'%c'", r);
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 )
fprintf(f, "%stransition on %s to <uncomputed>",
++num_trans == 1 ? "\t" : "\n\t", xbuf);
fprintf(f, "%stransition on %s to <uncomputed>", ++num_trans == 1 ? "\t" : "\n\t",
xbuf);
else
fprintf(f, "%stransition on %s to state %d",
++num_trans == 1 ? "\t" : "\n\t", xbuf,
s->StateNum());
fprintf(f, "%stransition on %s to state %d", ++num_trans == 1 ? "\t" : "\n\t", xbuf,
s->StateNum());
sym = i - 1;
}
@ -283,11 +282,10 @@ void DFA_State::Stats(unsigned int* computed, unsigned int* uncomputed)
unsigned int DFA_State::Size()
{
return sizeof(*this)
+ util::pad_size(sizeof(DFA_State*) * num_sym)
+ (accept ? util::pad_size(sizeof(int) * accept->size()) : 0)
+ (nfa_states ? util::pad_size(sizeof(NFA_State*) * nfa_states->length()) : 0)
+ (meta_ec ? meta_ec->Size() : 0);
return sizeof(*this) + util::pad_size(sizeof(DFA_State*) * num_sym) +
(accept ? util::pad_size(sizeof(int) * accept->size()) : 0) +
(nfa_states ? util::pad_size(sizeof(NFA_State*) * nfa_states->length()) : 0) +
(meta_ec ? meta_ec->Size() : 0);
}
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);
id /= 10;
}
while ( id > 0 );
} while ( id > 0 );
*p++ = '&';
}
}
@ -428,15 +425,12 @@ unsigned int DFA_Machine::MemoryAllocation() const
// FIXME: Count *ec?
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return padded_sizeof(*this)
+ s.mem
+ padded_sizeof(*start_state)
+ nfa->MemoryAllocation();
return padded_sizeof(*this) + s.mem + padded_sizeof(*start_state) + nfa->MemoryAllocation();
#pragma GCC diagnostic pop
}
bool DFA_Machine::StateSetToDFA_State(NFA_state_list* state_set,
DFA_State*& d, const EquivClass* ec)
bool DFA_Machine::StateSetToDFA_State(NFA_state_list* state_set, DFA_State*& d,
const EquivClass* ec)
{
DigestStr digest;
d = dfa_state_cache->Lookup(*state_set, &digest);
@ -475,4 +469,4 @@ int DFA_Machine::Rep(int sym)
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.
#pragma once
#include <assert.h>
@ -9,10 +8,11 @@
#include <string>
#include "zeek/NFA.h"
#include "zeek/RE.h" // for typedef AcceptingSet
#include "zeek/Obj.h"
#include "zeek/RE.h" // for typedef AcceptingSet
namespace zeek::detail {
namespace zeek::detail
{
class DFA_State;
class DFA_Machine;
@ -20,32 +20,33 @@ class DFA_Machine;
// Transitions to the uncomputed state indicate that we haven't yet
// computed the state to go to.
#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:
DFA_State(int state_num, const EquivClass* ec,
NFA_state_list* nfa_states, AcceptingSet* accept);
DFA_State(int state_num, const EquivClass* ec, NFA_state_list* nfa_states,
AcceptingSet* accept);
~DFA_State() override;
int StateNum() const { return state_num; }
int NFAStateNum() const { return nfa_states->length(); }
int StateNum() const { return state_num; }
int NFAStateNum() const { return nfa_states->length(); }
void AddXtion(int sym, DFA_State* next_state);
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);
// ec_sym is an equivalence class, not a character.
NFA_state_list* SymFollowSet(int ec_sym, const EquivClass* ec);
void SetMark(DFA_State* m) { mark = m; }
DFA_State* Mark() const { return mark; }
void SetMark(DFA_State* m) { mark = m; }
DFA_State* Mark() const { return mark; }
void ClearMarks();
// 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 Dump(FILE* f, DFA_Machine* m);
@ -65,15 +66,16 @@ protected:
AcceptingSet* accept;
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;
static unsigned int transition_counter; // see Xtion()
};
static unsigned int transition_counter; // see Xtion()
};
using DigestStr = std::basic_string<u_char>;
class DFA_State_Cache {
class DFA_State_Cache
{
public:
DFA_State_Cache();
~DFA_State_Cache();
@ -84,9 +86,10 @@ public:
// Takes ownership of state; digest is the one returned by Lookup().
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
unsigned int nfa_states;
unsigned int dfa_states;
@ -95,54 +98,55 @@ public:
unsigned int mem;
unsigned int hits;
unsigned int misses;
};
};
void GetStats(Stats* s);
private:
int hits; // Statistics
int hits; // Statistics
int misses;
// Hash indexed by NFA states (MD5s of them, actually).
std::map<DigestStr, DFA_State*> states;
};
};
class DFA_Machine : public Obj {
class DFA_Machine : public Obj
{
public:
DFA_Machine(NFA_Machine* n, EquivClass* ec);
~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);
void Describe(ODesc* d) const override;
void Dump(FILE* f);
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]]
unsigned int MemoryAllocation() const;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] unsigned int
MemoryAllocation() const;
protected:
friend class DFA_State; // for DFA_State::ComputeXtion
friend class DFA_State; // for DFA_State::ComputeXtion
friend class DFA_State_Cache;
int state_count;
// The state list has to be sorted according to IDs.
bool StateSetToDFA_State(NFA_state_list* state_set, DFA_State*& d,
const EquivClass* ec);
const EquivClass* EC() const { return ec; }
bool StateSetToDFA_State(NFA_state_list* state_set, DFA_State*& d, const EquivClass* 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_Cache* dfa_state_cache;
NFA_Machine* nfa;
};
};
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];
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -1,88 +1,87 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/DNS_Mgr.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "zeek/zeek-config.h"
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#include <sys/time.h>
#include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <netinet/in.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <stdlib.h>
#include <algorithm>
#include "zeek/ZeekString.h"
#include "zeek/Expr.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/Val.h"
#include "zeek/NetVar.h"
#include "zeek/ID.h"
#include "zeek/Reporter.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/ZeekString.h"
#include "zeek/iosource/Manager.h"
#include "zeek/Hash.h"
extern "C" {
extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
extern "C"
{
extern int select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
#include <netdb.h>
#include "zeek/nb_dns.h"
}
}
using namespace std;
namespace zeek::detail {
namespace zeek::detail
{
class DNS_Mgr_Request {
class DNS_Mgr_Request
{
public:
DNS_Mgr_Request(const char* h, int af, bool is_txt)
: host(util::copy_string(h)), fam(af), qtype(is_txt ? 16 : 0), addr(),
request_pending()
{ }
: host(util::copy_string(h)), fam(af), qtype(is_txt ? 16 : 0), addr(), request_pending()
{
}
DNS_Mgr_Request(const IPAddr& a)
: host(), fam(), qtype(), addr(a), request_pending()
{ }
DNS_Mgr_Request(const IPAddr& a) : 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.
const char* ReqHost() const { return host; }
const IPAddr& ReqAddr() const { return addr; }
bool ReqIsTxt() const { return qtype == 16; }
const char* ReqHost() const { return host; }
const IPAddr& ReqAddr() const { return addr; }
bool ReqIsTxt() const { return qtype == 16; }
int MakeRequest(nb_dns_info* nb_dns);
int RequestPending() const { return request_pending; }
void RequestDone() { request_pending = 0; }
int RequestPending() const { return request_pending; }
void RequestDone() { request_pending = 0; }
protected:
char* host; // if non-nil, this is a host request
int fam; // address family query type for host requests
int qtype; // Query type
char* host; // if non-nil, this is a host request
int fam; // address family query type for host requests
int qtype; // Query type
IPAddr addr;
int request_pending;
};
};
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];
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
{
const uint32_t* bytes;
int len = addr.GetBytes(&bytes);
return nb_dns_addr_request2(nb_dns, (char*) bytes,
len == 1 ? AF_INET : AF_INET6, (void*) this, err) >= 0;
return nb_dns_addr_request2(nb_dns, (char*)bytes, len == 1 ? AF_INET : AF_INET6,
(void*)this, err) >= 0;
}
}
class DNS_Mapping {
class DNS_Mapping
{
public:
DNS_Mapping(const char* host, struct hostent* h, uint32_t ttl);
DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32_t ttl);
DNS_Mapping(FILE* f);
bool NoMapping() const { return no_mapping; }
bool InitFailed() const { return init_failed; }
bool NoMapping() const { return no_mapping; }
bool InitFailed() const { return init_failed; }
~DNS_Mapping();
// Returns nil if this was an address request.
const char* ReqHost() const { return req_host; }
IPAddr ReqAddr() const { return req_addr; }
string ReqStr() const
{
return req_host ? req_host : req_addr.AsString();
}
const char* ReqHost() const { return req_host; }
IPAddr ReqAddr() const { return req_addr; }
string ReqStr() const { return req_host ? req_host : req_addr.AsString(); }
ListValPtr Addrs();
TableValPtr AddrsSet(); // addresses returned as a set
TableValPtr AddrsSet(); // addresses returned as a set
StringValPtr Host();
double CreationTime() const { return creation_time; }
double CreationTime() const { return creation_time; }
void Save(FILE* f) const;
bool Failed() const { return failed; }
bool Valid() const { return ! failed; }
bool Failed() const { return failed; }
bool Valid() const { return ! failed; }
bool Expired() const
{
if ( req_host && num_addrs == 0)
if ( req_host && num_addrs == 0 )
return false; // nothing to expire
return util::current_time() > (creation_time + req_ttl);
@ -163,14 +160,14 @@ protected:
double creation_time;
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 failed;
};
};
void DNS_Mgr_mapping_delete_func(void* v)
{
delete (DNS_Mapping*) v;
delete (DNS_Mapping*)v;
}
static TableValPtr empty_addr_set()
@ -217,13 +214,12 @@ DNS_Mapping::DNS_Mapping(FILE* f)
return;
}
char req_buf[512+1], name_buf[512+1];
char req_buf[512 + 1], name_buf[512 + 1];
int is_req_host;
int failed_local;
if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %" PRIu32, &creation_time,
&is_req_host, req_buf, &failed_local, name_buf, &map_type, &num_addrs,
&req_ttl) != 8 )
if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %" PRIu32, &creation_time, &is_req_host, req_buf,
&failed_local, name_buf, &map_type, &num_addrs, &req_ttl) != 8 )
return;
failed = static_cast<bool>(failed_local);
@ -264,16 +260,16 @@ DNS_Mapping::DNS_Mapping(FILE* f)
DNS_Mapping::~DNS_Mapping()
{
delete [] req_host;
delete[] req_host;
if ( names )
{
for ( int i = 0; i < num_names; ++i )
delete [] names[i];
delete [] names;
delete[] names[i];
delete[] names;
}
delete [] addrs;
delete[] addrs;
}
ListValPtr DNS_Mapping::Addrs()
@ -292,7 +288,8 @@ ListValPtr DNS_Mapping::Addrs()
return addrs_val;
}
TableValPtr DNS_Mapping::AddrsSet() {
TableValPtr DNS_Mapping::AddrsSet()
{
auto l = Addrs();
if ( ! l )
@ -327,7 +324,7 @@ void DNS_Mapping::Init(struct hostent* h)
}
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[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];
for ( int i = 0; i < num_addrs; ++i )
if ( h->h_addrtype == AF_INET )
addrs[i] = IPAddr(IPv4, (uint32_t*)h->h_addr_list[i],
IPAddr::Network);
addrs[i] = IPAddr(IPv4, (uint32_t*)h->h_addr_list[i], IPAddr::Network);
else if ( h->h_addrtype == AF_INET6 )
addrs[i] = IPAddr(IPv6, (uint32_t*)h->h_addr_list[i],
IPAddr::Network);
addrs[i] = IPAddr(IPv6, (uint32_t*)h->h_addr_list[i], IPAddr::Network);
}
else
addrs = nullptr;
@ -365,16 +360,14 @@ void DNS_Mapping::Clear()
void DNS_Mapping::Save(FILE* f) const
{
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(),
failed, (names && names[0]) ? names[0] : "*",
map_type, num_addrs, req_ttl);
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(), failed,
(names && names[0]) ? names[0] : "*", map_type, num_addrs, req_ttl);
for ( int i = 0; i < num_addrs; ++i )
fprintf(f, "%s\n", addrs[i].AsString().c_str());
}
DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode)
{
did_init = false;
@ -395,8 +388,8 @@ DNS_Mgr::~DNS_Mgr()
if ( nb_dns )
nb_dns_finish(nb_dns);
delete [] cache_name;
delete [] dir;
delete[] cache_name;
delete[] dir;
}
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 char tmp[128];
snprintf(tmp, sizeof(tmp), "fake_addr_lookup_result_%s",
addr.AsString().c_str());
snprintf(tmp, sizeof(tmp), "fake_addr_lookup_result_%s", addr.AsString().c_str());
return tmp;
}
@ -520,26 +512,27 @@ TableValPtr DNS_Mgr::LookupHost(const char* name)
}
// Not found, or priming.
switch ( mode ) {
case DNS_PRIME:
requests.push_back(new DNS_Mgr_Request(name, AF_INET, false));
requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false));
return empty_addr_set();
switch ( mode )
{
case DNS_PRIME:
requests.push_back(new DNS_Mgr_Request(name, AF_INET, false));
requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false));
return empty_addr_set();
case DNS_FORCE:
reporter->FatalError("can't find DNS entry for %s in cache", name);
return nullptr;
case DNS_FORCE:
reporter->FatalError("can't find DNS entry for %s in cache", name);
return nullptr;
case DNS_DEFAULT:
requests.push_back(new DNS_Mgr_Request(name, AF_INET, false));
requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false));
Resolve();
return LookupHost(name);
case DNS_DEFAULT:
requests.push_back(new DNS_Mgr_Request(name, AF_INET, false));
requests.push_back(new DNS_Mgr_Request(name, AF_INET6, false));
Resolve();
return LookupHost(name);
default:
reporter->InternalError("bad mode in DNS_Mgr::LookupHost");
return nullptr;
}
default:
reporter->InternalError("bad mode in DNS_Mgr::LookupHost");
return nullptr;
}
}
ValPtr DNS_Mgr::LookupAddr(const IPAddr& addr)
@ -565,30 +558,28 @@ ValPtr DNS_Mgr::LookupAddr(const IPAddr& addr)
}
// Not found, or priming.
switch ( mode ) {
case DNS_PRIME:
requests.push_back(new DNS_Mgr_Request(addr));
return make_intrusive<StringVal>("<none>");
switch ( mode )
{
case DNS_PRIME:
requests.push_back(new DNS_Mgr_Request(addr));
return make_intrusive<StringVal>("<none>");
case DNS_FORCE:
reporter->FatalError("can't find DNS entry for %s in cache",
addr.AsString().c_str());
return nullptr;
case DNS_FORCE:
reporter->FatalError("can't find DNS entry for %s in cache", addr.AsString().c_str());
return nullptr;
case DNS_DEFAULT:
requests.push_back(new DNS_Mgr_Request(addr));
Resolve();
return LookupAddr(addr);
case DNS_DEFAULT:
requests.push_back(new DNS_Mgr_Request(addr));
Resolve();
return LookupAddr(addr);
default:
reporter->InternalError("bad mode in DNS_Mgr::LookupAddr");
return nullptr;
}
default:
reporter->InternalError("bad mode in DNS_Mgr::LookupAddr");
return nullptr;
}
}
void DNS_Mgr::Verify()
{
}
void DNS_Mgr::Verify() { }
#define MAX_PENDING_REQUESTS 20
@ -628,8 +619,7 @@ void DNS_Mgr::Resolve()
}
first_req = last_req + 1;
num_pending = min(requests.length() - first_req,
MAX_PENDING_REQUESTS);
num_pending = min(requests.length() - first_req, MAX_PENDING_REQUESTS);
last_req = first_req + num_pending - 1;
for ( i = first_req; i <= last_req; ++i )
@ -642,12 +632,10 @@ void DNS_Mgr::Resolve()
struct nb_dns_result r;
status = nb_dns_activity(nb_dns, &r, err);
if ( status < 0 )
reporter->Warning(
"NB-DNS error in DNS_Mgr::WaitForReplies (%s)",
err);
reporter->Warning("NB-DNS error in DNS_Mgr::WaitForReplies (%s)", err);
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() )
{
AddResult(dr, &r);
@ -697,8 +685,7 @@ void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* dm)
event_mgr.Enqueue(e, BuildMappingVal(dm));
}
void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* dm,
ListValPtr l1, ListValPtr l2)
void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* dm, ListValPtr l1, ListValPtr l2)
{
if ( ! e )
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());
if ( it == host_mappings.end() )
{
host_mappings[dr->ReqHost()].first =
new_dm->Type() == AF_INET ? new_dm : nullptr;
host_mappings[dr->ReqHost()].first = new_dm->Type() == AF_INET ? new_dm : nullptr;
host_mappings[dr->ReqHost()].second =
new_dm->Type() == AF_INET ? nullptr : new_dm;
host_mappings[dr->ReqHost()].second = new_dm->Type() == AF_INET ? nullptr : new_dm;
}
else
{
@ -1029,15 +1014,13 @@ const char* DNS_Mgr::LookupTextInCache(const string& name)
return d->names ? d->names[0] : "<\?\?\?>";
}
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback,
TableValPtr result)
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback, TableValPtr result)
{
callback->Resolved(result.get());
delete callback;
}
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback,
const char* result)
static void resolve_lookup_cb(DNS_Mgr::LookupCallback* callback, const char* result)
{
callback->Resolved(result);
delete callback;
@ -1184,15 +1167,16 @@ void DNS_Mgr::IssueAsyncRequests()
if ( req->IsAddrReq() )
success = DoRequest(nb_dns, new DNS_Mgr_Request(req->host));
else if ( req->is_txt )
success = 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(), AF_INET, req->is_txt));
else
{
// If only one request type succeeds, don't consider it a failure.
success = 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(),
AF_INET6, req->is_txt)) || success;
success =
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(), AF_INET6, req->is_txt)) ||
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
// eventually times out.
}
}
void DNS_Mgr::CheckAsyncTextRequest(const char* host, bool timeout)
@ -1378,11 +1361,10 @@ void DNS_Mgr::Process()
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;
if ( dr->ReqHost() &&
host_mappings.find(dr->ReqHost()) == host_mappings.end() )
if ( dr->ReqHost() && host_mappings.find(dr->ReqHost()) == host_mappings.end() )
// Don't timeout when this is the first result in an expected pair
// (one result each for A and AAAA queries).
do_host_timeout = false;
@ -1427,7 +1409,7 @@ int DNS_Mgr::AnswerAvailable(int timeout)
t.tv_sec = timeout;
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 )
{
@ -1463,4 +1445,4 @@ void DNS_Mgr::Terminate()
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
@ -7,13 +7,14 @@
#include <queue>
#include <utility>
#include "zeek/List.h"
#include "zeek/EventHandler.h"
#include "zeek/iosource/IOSource.h"
#include "zeek/IPAddr.h"
#include "zeek/List.h"
#include "zeek/iosource/IOSource.h"
#include "zeek/util.h"
namespace zeek {
namespace zeek
{
class EventHandler;
class RecordType;
@ -26,30 +27,33 @@ using ValPtr = IntrusivePtr<Val>;
using ListValPtr = IntrusivePtr<ListVal>;
using TableValPtr = IntrusivePtr<TableVal>;
} // namespace zeek
} // namespace zeek
// Defined in nb_dns.h
struct nb_dns_info;
struct nb_dns_result;
namespace zeek::detail {
namespace zeek::detail
{
class DNS_Mgr_Request;
using DNS_mgr_request_list = PList<DNS_Mgr_Request>;
class DNS_Mapping;
enum DNS_MgrMode {
DNS_PRIME, // used to prime the cache
DNS_FORCE, // internal error if cache miss
DNS_DEFAULT, // lookup names as they're requested
DNS_FAKE, // don't look up names, just return dummy results
};
enum DNS_MgrMode
{
DNS_PRIME, // used to prime the cache
DNS_FORCE, // internal error if cache miss
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.
#define DNS_TIMEOUT 5
class DNS_Mgr final : public iosource::IOSource {
class DNS_Mgr final : public iosource::IOSource
{
public:
explicit DNS_Mgr(DNS_MgrMode mode);
~DNS_Mgr() override;
@ -64,7 +68,7 @@ public:
ValPtr LookupAddr(const IPAddr& addr);
// 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 Resolve();
@ -75,29 +79,31 @@ public:
const char* LookupTextInCache(const std::string& name);
// Support for async lookups.
class LookupCallback {
class LookupCallback
{
public:
LookupCallback() { }
virtual ~LookupCallback() { }
LookupCallback() { }
virtual ~LookupCallback() { }
virtual void Resolved(const char* name) { };
virtual void Resolved(TableVal* addrs) { };
virtual void Resolved(const char* name){};
virtual void Resolved(TableVal* addrs){};
virtual void Timeout() = 0;
};
};
void AsyncLookupAddr(const IPAddr& host, LookupCallback* callback);
void AsyncLookupName(const std::string& name, LookupCallback* callback);
void AsyncLookupNameText(const std::string& name, LookupCallback* callback);
struct Stats {
unsigned long requests; // These count only async requests.
struct Stats
{
unsigned long requests; // These count only async requests.
unsigned long successful;
unsigned long failed;
unsigned long pending;
unsigned long cached_hosts;
unsigned long cached_addresses;
unsigned long cached_texts;
};
};
void GetStats(Stats* stats);
@ -108,8 +114,7 @@ protected:
friend class DNS_Mgr_Request;
void Event(EventHandlerPtr e, DNS_Mapping* dm);
void Event(EventHandlerPtr e, DNS_Mapping* dm,
ListValPtr l1, ListValPtr l2);
void Event(EventHandlerPtr e, DNS_Mapping* dm, ListValPtr l1, ListValPtr l2);
void Event(EventHandlerPtr e, DNS_Mapping* old_dm, DNS_Mapping* new_dm);
ValPtr BuildMappingVal(DNS_Mapping* dm);
@ -119,7 +124,7 @@ protected:
ListValPtr AddrListDelta(ListVal* al1, ListVal* al2);
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<std::string, DNS_Mapping*> TextMap;
void LoadCache(FILE* f);
@ -143,7 +148,7 @@ protected:
// IOSource interface.
void Process() override;
void InitSource() override;
const char* Tag() override { return "DNS_Mgr"; }
const char* Tag() override { return "DNS_Mgr"; }
double GetNextTimeout() override;
DNS_MgrMode mode;
@ -156,7 +161,7 @@ protected:
nb_dns_info* nb_dns;
char* cache_name;
char* dir; // directory in which cache_name resides
char* dir; // directory in which cache_name resides
bool did_init;
int asyncs_pending;
@ -165,7 +170,8 @@ protected:
typedef std::list<LookupCallback*> CallbackList;
struct AsyncRequest {
struct AsyncRequest
{
double time;
IPAddr host;
std::string name;
@ -175,12 +181,11 @@ protected:
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)
{
for ( CallbackList::iterator i = callbacks.begin();
i != callbacks.end(); ++i )
for ( CallbackList::iterator i = callbacks.begin(); i != callbacks.end(); ++i )
{
(*i)->Resolved(name);
delete *i;
@ -191,8 +196,7 @@ protected:
void Resolved(TableVal* addrs)
{
for ( CallbackList::iterator i = callbacks.begin();
i != callbacks.end(); ++i )
for ( CallbackList::iterator i = callbacks.begin(); i != callbacks.end(); ++i )
{
(*i)->Resolved(addrs);
delete *i;
@ -203,8 +207,7 @@ protected:
void Timeout()
{
for ( CallbackList::iterator i = callbacks.begin();
i != callbacks.end(); ++i )
for ( CallbackList::iterator i = callbacks.begin(); i != callbacks.end(); ++i )
{
(*i)->Timeout();
delete *i;
@ -212,8 +215,7 @@ protected:
callbacks.clear();
processed = true;
}
};
};
typedef std::map<IPAddr, AsyncRequest*> AsyncRequestAddrMap;
AsyncRequestAddrMap asyncs_addrs;
@ -227,21 +229,20 @@ protected:
typedef std::list<AsyncRequest*> QueuedList;
QueuedList asyncs_queued;
struct AsyncRequestCompare {
bool operator()(const AsyncRequest* a, const AsyncRequest* b)
{
return a->time > b->time;
}
};
struct AsyncRequestCompare
{
bool operator()(const AsyncRequest* a, const AsyncRequest* b) { 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;
unsigned long num_requests;
unsigned long successful;
unsigned long failed;
};
};
extern DNS_Mgr* dns_mgr;
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -1,37 +1,39 @@
// Implementation of breakpoints.
#include "zeek/zeek-config.h"
#include "zeek/DbgBreakpoint.h"
#include <assert.h>
#include "zeek/Desc.h"
#include "zeek/ID.h"
#include "zeek/Debug.h"
#include "zeek/Scope.h"
#include "zeek/Desc.h"
#include "zeek/Frame.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/Timer.h"
#include "zeek/Reporter.h"
#include "zeek/Val.h"
#include "zeek/module_util.h"
#include "zeek/zeek-config.h"
namespace zeek::detail {
namespace zeek::detail
{
// BreakpointTimer used for time-based breakpoints
class BreakpointTimer final : public Timer {
class BreakpointTimer final : public Timer
{
public:
BreakpointTimer(DbgBreakpoint* arg_bp, double arg_t)
: Timer(arg_t, TIMER_BREAKPOINT)
{ bp = arg_bp; }
BreakpointTimer(DbgBreakpoint* arg_bp, double arg_t) : Timer(arg_t, TIMER_BREAKPOINT)
{
bp = arg_bp;
}
void Dispatch(double t, bool is_expire) override;
protected:
DbgBreakpoint* bp;
};
};
void BreakpointTimer::Dispatch(double t, bool is_expire)
{
@ -41,7 +43,6 @@ void BreakpointTimer::Dispatch(double t, bool is_expire)
bp->ShouldBreak(t);
}
DbgBreakpoint::DbgBreakpoint()
{
kind = BP_STMT;
@ -61,7 +62,7 @@ DbgBreakpoint::DbgBreakpoint()
DbgBreakpoint::~DbgBreakpoint()
{
SetEnable(false); // clean up any active state
SetEnable(false); // clean up any active state
RemoveFromGlobalMap();
}
@ -119,7 +120,6 @@ void DbgBreakpoint::RemoveFromStmt()
at_stmt->DecrBPCount();
}
bool DbgBreakpoint::SetLocation(ParseLocationRec plr, std::string_view loc_str)
{
if ( plr.type == PLR_UNKNOWN )
@ -141,8 +141,7 @@ bool DbgBreakpoint::SetLocation(ParseLocationRec plr, std::string_view loc_str)
}
at_stmt = plr.stmt;
snprintf(description, sizeof(description), "%s:%d",
source_filename, source_line);
snprintf(description, sizeof(description), "%s:%d", source_filename, source_line);
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);
kind = BP_FUNC;
function_name = make_full_var_name(current_module.c_str(),
loc_s.c_str());
function_name = make_full_var_name(current_module.c_str(), loc_s.c_str());
at_stmt = plr.stmt;
const Location* loc = at_stmt->GetLocationInfo();
snprintf(description, sizeof(description), "%s at %s:%d",
function_name.c_str(), loc->filename, loc->last_line);
snprintf(description, sizeof(description), "%s at %s:%d", function_name.c_str(),
loc->filename, loc->last_line);
debug_msg("Breakpoint %d set at %s\n", GetID(), Description());
}
@ -178,8 +176,7 @@ bool DbgBreakpoint::SetLocation(Stmt* stmt)
AddToGlobalMap();
const Location* loc = stmt->GetLocationInfo();
snprintf(description, sizeof(description), "%s:%d",
loc->filename, loc->last_line);
snprintf(description, sizeof(description), "%s:%d", loc->filename, loc->last_line);
debug_msg("Breakpoint %d set at %s\n", GetID(), Description());
@ -204,19 +201,20 @@ bool DbgBreakpoint::Reset()
{
ParseLocationRec plr;
switch ( kind ) {
case BP_TIME:
debug_msg("Time-based breakpoints not yet supported.\n");
break;
switch ( kind )
{
case BP_TIME:
debug_msg("Time-based breakpoints not yet supported.\n");
break;
case BP_FUNC:
case BP_STMT:
case BP_LINE:
plr.type = PLR_FUNCTION;
//### How to deal with wildcards?
//### perhaps save user choices?--tough...
break;
}
case BP_FUNC:
case BP_STMT:
case BP_LINE:
plr.type = PLR_FUNCTION;
//### How to deal with wildcards?
//### perhaps save user choices?--tough...
break;
}
reporter->InternalError("DbgBreakpoint::Reset function incomplete.");
@ -252,14 +250,13 @@ BreakCode DbgBreakpoint::HasHit()
if ( ! yes )
{
debug_msg("Breakpoint condition '%s' invalid, removing condition.\n",
condition.c_str());
condition.c_str());
SetCondition("");
PrintHitMsg();
return BC_HIT;
}
if ( ! IsIntegral(yes->GetType()->Tag()) &&
! IsBool(yes->GetType()->Tag()) )
if ( ! IsIntegral(yes->GetType()->Tag()) && ! IsBool(yes->GetType()->Tag()) )
{
PrintHitMsg();
debug_msg("Breakpoint condition should return an integral type");
@ -295,24 +292,25 @@ BreakCode DbgBreakpoint::ShouldBreak(Stmt* s)
if ( ! IsEnabled() )
return BC_NO_HIT;
switch ( kind ) {
case BP_STMT:
case BP_FUNC:
if ( at_stmt != s )
return BC_NO_HIT;
break;
switch ( kind )
{
case BP_STMT:
case BP_FUNC:
if ( at_stmt != s )
return BC_NO_HIT;
break;
case BP_LINE:
assert(s->GetLocationInfo()->first_line <= source_line &&
s->GetLocationInfo()->last_line >= source_line);
break;
case BP_LINE:
assert(s->GetLocationInfo()->first_line <= source_line &&
s->GetLocationInfo()->last_line >= source_line);
break;
case BP_TIME:
assert(false);
case BP_TIME:
assert(false);
default:
reporter->InternalError("Invalid breakpoint type in DbgBreakpoint::ShouldBreak");
}
default:
reporter->InternalError("Invalid breakpoint type in DbgBreakpoint::ShouldBreak");
}
// If we got here, that means that the breakpoint could hit,
// except potentially if it has a special condition or a repeat count.
@ -324,7 +322,6 @@ BreakCode DbgBreakpoint::ShouldBreak(Stmt* s)
return code;
}
BreakCode DbgBreakpoint::ShouldBreak(double t)
{
if ( kind != BP_TIME )
@ -345,32 +342,32 @@ BreakCode DbgBreakpoint::ShouldBreak(double t)
void DbgBreakpoint::PrintHitMsg()
{
switch ( kind ) {
case BP_STMT:
case BP_FUNC:
case BP_LINE:
switch ( kind )
{
ODesc d;
Frame* f = g_frame_stack.back();
const ScriptFunc* func = f->GetFunction();
case BP_STMT:
case BP_FUNC:
case BP_LINE:
{
ODesc d;
Frame* f = g_frame_stack.back();
const ScriptFunc* func = f->GetFunction();
if ( func )
func->DescribeDebug (&d, f->GetFuncArgs());
if ( func )
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",
GetID(), d.Description(),
loc->filename, loc->first_line);
debug_msg("Breakpoint %d, %s at %s:%d\n", GetID(), d.Description(), 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
#include <string>
#include "zeek/util.h"
namespace zeek::detail {
namespace zeek::detail
{
class Stmt;
class ParseLocationRec;
enum BreakCode { BC_NO_HIT, BC_HIT, BC_HIT_AND_DELETE };
class DbgBreakpoint {
enum Kind { BP_STMT = 0, BP_FUNC, BP_LINE, BP_TIME };
enum BreakCode
{
BC_NO_HIT,
BC_HIT,
BC_HIT_AND_DELETE
};
class DbgBreakpoint
{
enum Kind
{
BP_STMT = 0,
BP_FUNC,
BP_LINE,
BP_TIME
};
public:
DbgBreakpoint();
~DbgBreakpoint();
int GetID() const { return BPID; }
void SetID(int newID) { BPID = newID; }
int GetID() const { return BPID; }
void SetID(int newID) { BPID = newID; }
// True if breakpoint could be set; false otherwise
bool SetLocation(ParseLocationRec plr, std::string_view loc_str);
bool SetLocation(Stmt* stmt);
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.
bool IsTemporary() const { return temporary; }
void SetTemporary(bool is_temporary) { temporary = is_temporary; }
bool IsTemporary() const { return temporary; }
void SetTemporary(bool is_temporary) { temporary = is_temporary; }
// Feed it a Stmt* or a time and see if this breakpoint should
// hit. bcHitAndDelete means that it has hit, and should now be
@ -41,17 +55,17 @@ public:
BreakCode ShouldBreak(Stmt* s);
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);
int GetRepeatCount() const { return repeat_count; }
int GetRepeatCount() const { return repeat_count; }
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);
// e.g. "FooBar() at foo.c:23"
const char * Description() const { return description; }
const char* Description() const { return description; }
protected:
void AddToGlobalMap();
@ -60,27 +74,27 @@ protected:
void AddToStmt();
void RemoveFromStmt();
BreakCode HasHit(); // a breakpoint hit, update state, return proper code.
void PrintHitMsg(); // display reason when the breakpoint hits
BreakCode HasHit(); // a breakpoint hit, update state, return proper code.
void PrintHitMsg(); // display reason when the breakpoint hits
Kind kind;
int32_t BPID;
char description[512];
std::string function_name; // location
std::string function_name; // location
const char* source_filename;
int32_t source_line;
bool enabled; // ### comment this and next
bool enabled; // ### comment this and next
bool temporary;
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.
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 repeat_count; // if positive, break after this many hits
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
namespace zeek::detail {
namespace zeek::detail
{
class Expr;
// Automatic displays: display these at each stoppage.
class DbgDisplay {
class DbgDisplay
{
public:
DbgDisplay(Expr* expr_to_display);
bool IsEnabled() { return enabled; }
bool IsEnabled() { return enabled; }
bool SetEnable(bool do_enable)
{
bool old_value = enabled;
@ -19,11 +21,11 @@ public:
return old_value;
}
const Expr* Expression() const { return expression; }
const Expr* Expression() const { return expression; }
protected:
bool enabled;
Expr* expression;
};
} // namespace zeek::detail
} // namespace zeek::detail

View file

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

View file

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

View file

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

View file

@ -1,42 +1,41 @@
// Debugging support for Bro policy files.
#include "zeek/zeek-config.h"
#include "zeek/Debug.h"
#include <stdio.h>
#include <stdarg.h>
#include <signal.h>
#include <ctype.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string>
#include "zeek/zeek-config.h"
#ifdef HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#include <readline/readline.h>
#endif
#include "zeek/util.h"
#include "zeek/DebugCmds.h"
#include "zeek/DbgBreakpoint.h"
#include "zeek/ID.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/DebugCmds.h"
#include "zeek/Desc.h"
#include "zeek/Expr.h"
#include "zeek/Stmt.h"
#include "zeek/Frame.h"
#include "zeek/Func.h"
#include "zeek/ID.h"
#include "zeek/IntrusivePtr.h"
#include "zeek/Scope.h"
#include "zeek/PolicyFile.h"
#include "zeek/Desc.h"
#include "zeek/Reporter.h"
#include "zeek/Scope.h"
#include "zeek/Stmt.h"
#include "zeek/Val.h"
#include "zeek/module_util.h"
#include "zeek/input.h"
#include "zeek/module_util.h"
#include "zeek/util.h"
extern "C" {
extern "C"
{
#include "zeek/setsignal.h"
}
}
using namespace std;
@ -63,11 +62,12 @@ struct yy_buffer_state;
typedef struct yy_buffer_state* YY_BUFFER_STATE;
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 const char* filename;
namespace zeek::detail {
namespace zeek::detail
{
DebuggerState::DebuggerState()
{
@ -88,15 +88,13 @@ DebuggerState::~DebuggerState()
bool StmtLocMapping::StartsAfter(const StmtLocMapping* m2)
{
if ( ! m2 )
if ( ! m2 )
reporter->InternalError("Assertion failed: m2 != 0");
return loc.first_line > m2->loc.first_line ||
(loc.first_line == m2->loc.first_line &&
loc.first_column > m2->loc.first_column);
(loc.first_line == m2->loc.first_line && loc.first_column > m2->loc.first_column);
}
// Generic debug message output.
int debug_msg(const char* fmt, ...)
{
@ -110,7 +108,6 @@ int debug_msg(const char* fmt, ...)
return retval;
}
// Trace message output
FILE* TraceState::SetTraceFile(const char* trace_filename)
@ -195,7 +192,6 @@ int TraceState::LogTrace(const char* fmt, ...)
return retval;
}
// Helper functions.
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();
}
static void parse_function_name(vector<ParseLocationRec>& result,
ParseLocationRec& plr, const string& s)
static void parse_function_name(vector<ParseLocationRec>& result, ParseLocationRec& plr,
const string& s)
{ // function name
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;
}
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 )
body = bodies[0].stmts.get();
@ -263,13 +259,13 @@ static void parse_function_name(vector<ParseLocationRec>& result,
while ( true )
{
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 )
{
Stmt* first;
Location 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");
@ -298,7 +294,7 @@ static void parse_function_name(vector<ParseLocationRec>& result,
}
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();
break;
@ -394,7 +390,7 @@ vector<ParseLocationRec> parse_location_string(const string& s)
auto iter = g_dbgfilemaps.find(loc_filename);
if ( iter == g_dbgfilemaps.end() )
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()) )
{
@ -411,8 +407,7 @@ vector<ParseLocationRec> parse_location_string(const string& s)
if ( entry->Loc().first_line > plr.line )
break;
if ( plr.line >= entry->Loc().first_line &&
plr.line <= entry->Loc().last_line )
if ( plr.line >= entry->Loc().first_line && plr.line <= entry->Loc().last_line )
{
hit = entry;
break;
@ -428,7 +423,6 @@ vector<ParseLocationRec> parse_location_string(const string& s)
return result;
}
// Interactive debugging console.
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)
{
if ( ! g_policy_debug )
return 0; // probably shouldn't have been called
return 0; // probably shouldn't have been called
init_global_dbg_constants();
@ -469,7 +463,7 @@ int dbg_init_debugger(const char* cmdfile)
// ### Implement this
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
init_readline();
#endif
@ -486,7 +480,6 @@ int dbg_shutdown_debugger()
return 1;
}
// 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
// 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';
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;
int start = i;
@ -512,7 +505,7 @@ void tokenize(const char* cstr, string& operation, vector<string>& arguments)
{
if ( str[i] == '\\' )
{
if ( i < (signed int) str.length() )
if ( i < (signed int)str.length() )
++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.
int dbg_execute_command(const char* cmd)
{
@ -563,8 +555,7 @@ int dbg_execute_command(const char* cmd)
if ( ! entry )
return 0;
const DebugCmdInfo* info =
(const DebugCmdInfo*) entry->data;
const DebugCmdInfo* info = (const DebugCmdInfo*)entry->data;
if ( info && info->Repeatable() )
{
@ -585,7 +576,7 @@ int dbg_execute_command(const char* cmd)
vector<string> arguments;
tokenize(localcmd, opstring, arguments);
delete [] localcmd;
delete[] localcmd;
// Make sure we know this op name.
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 )
if ( matching_cmds[i] )
{
cmd_code = (DebugCmd) i;
cmd_code = (DebugCmd)i;
break;
}
@ -628,9 +619,9 @@ int dbg_execute_command(const char* cmd)
* http://tiswww.case.edu/php/chet/readline/history.html
* 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();
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
@ -643,11 +634,11 @@ int dbg_execute_command(const char* cmd)
return retcode;
const DebugCmdInfo* info = get_debug_cmd_info(cmd_code);
if ( ! info )
if ( ! info )
reporter->InternalError("Assertion failed: info");
if ( ! info )
return -2; // ### yuck, why -2?
return -2; // ### yuck, why -2?
return info->ResumeExecution();
}
@ -655,85 +646,86 @@ int dbg_execute_command(const char* cmd)
// Call the appropriate function for the command.
static int dbg_dispatch_cmd(DebugCmd cmd_code, const vector<string>& args)
{
switch ( cmd_code ) {
case dcHelp:
dbg_cmd_help(cmd_code, args);
break;
switch ( cmd_code )
{
case dcHelp:
dbg_cmd_help(cmd_code, args);
break;
case dcQuit:
debug_msg("Program Terminating\n");
exit(0);
case dcQuit:
debug_msg("Program Terminating\n");
exit(0);
case dcNext:
g_frame_stack.back()->BreakBeforeNextStmt(true);
step_or_next_pending = true;
last_frame = g_frame_stack.back();
break;
case dcNext:
g_frame_stack.back()->BreakBeforeNextStmt(true);
step_or_next_pending = true;
last_frame = g_frame_stack.back();
break;
case dcStep:
g_debugger_state.BreakBeforeNextStmt(true);
step_or_next_pending = true;
last_frame = g_frame_stack.back();
break;
case dcStep:
g_debugger_state.BreakBeforeNextStmt(true);
step_or_next_pending = true;
last_frame = g_frame_stack.back();
break;
case dcContinue:
g_debugger_state.BreakBeforeNextStmt(false);
debug_msg("Continuing.\n");
break;
case dcContinue:
g_debugger_state.BreakBeforeNextStmt(false);
debug_msg("Continuing.\n");
break;
case dcFinish:
g_frame_stack.back()->BreakOnReturn(true);
g_debugger_state.BreakBeforeNextStmt(false);
break;
case dcFinish:
g_frame_stack.back()->BreakOnReturn(true);
g_debugger_state.BreakBeforeNextStmt(false);
break;
case dcBreak:
dbg_cmd_break(cmd_code, args);
break;
case dcBreak:
dbg_cmd_break(cmd_code, args);
break;
case dcBreakCondition:
dbg_cmd_break_condition(cmd_code, args);
break;
case dcBreakCondition:
dbg_cmd_break_condition(cmd_code, args);
break;
case dcDeleteBreak:
case dcClearBreak:
case dcDisableBreak:
case dcEnableBreak:
case dcIgnoreBreak:
dbg_cmd_break_set_state(cmd_code, args);
break;
case dcDeleteBreak:
case dcClearBreak:
case dcDisableBreak:
case dcEnableBreak:
case dcIgnoreBreak:
dbg_cmd_break_set_state(cmd_code, args);
break;
case dcPrint:
dbg_cmd_print(cmd_code, args);
break;
case dcPrint:
dbg_cmd_print(cmd_code, args);
break;
case dcBacktrace:
return dbg_cmd_backtrace(cmd_code, args);
case dcBacktrace:
return dbg_cmd_backtrace(cmd_code, args);
case dcFrame:
case dcUp:
case dcDown:
return dbg_cmd_frame(cmd_code, args);
case dcFrame:
case dcUp:
case dcDown:
return dbg_cmd_frame(cmd_code, args);
case dcInfo:
return dbg_cmd_info(cmd_code, args);
case dcInfo:
return dbg_cmd_info(cmd_code, args);
case dcList:
return dbg_cmd_list(cmd_code, args);
case dcList:
return dbg_cmd_list(cmd_code, args);
case dcDisplay:
case dcUndisplay:
debug_msg("Command not yet implemented.\n");
break;
case dcDisplay:
case dcUndisplay:
debug_msg("Command not yet implemented.\n");
break;
case dcTrace:
return dbg_cmd_trace(cmd_code, args);
case dcTrace:
return dbg_cmd_trace(cmd_code, args);
default:
debug_msg("INTERNAL ERROR: "
"Got an unknown debugger command in DbgDispatchCmd: %d\n",
cmd_code);
return 0;
}
default:
debug_msg("INTERNAL ERROR: "
"Got an unknown debugger command in DbgDispatchCmd: %d\n",
cmd_code);
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;
char* buf = new char[buf_size];
snprintf(buf, buf_size, "In %s at %s:%d",
d.Description(), loc.filename, loc.last_line);
snprintf(buf, buf_size, "In %s at %s:%d", d.Description(), loc.filename, loc.last_line);
string retval(buf);
delete [] buf;
delete[] buf;
return retval;
}
@ -807,29 +798,27 @@ int dbg_handle_debug_input()
if ( ! step_or_next_pending || g_frame_stack.back() != last_frame )
{
string context =
get_context_description(stmt, g_frame_stack.back());
string context = get_context_description(stmt, g_frame_stack.back());
debug_msg("%s\n", context.c_str());
}
step_or_next_pending = false;
PrintLines(loc.filename, loc.first_line,
loc.last_line - loc.first_line + 1, true);
PrintLines(loc.filename, loc.first_line, loc.last_line - loc.first_line + 1, true);
g_debugger_state.last_loc = loc;
do
{
// readline returns a pointer to a buffer it allocates; it's
// freed at the bottom.
// readline returns a pointer to a buffer it allocates; it's
// freed at the bottom.
#ifdef HAVE_READLINE
input_line = readline(get_prompt());
#else
printf ("%s", get_prompt());
printf("%s", get_prompt());
// readline uses malloc, and we want to be consistent
// with it.
input_line = (char*) util::safe_malloc(1024);
input_line = (char*)util::safe_malloc(1024);
input_line[1023] = 0;
// ### Maybe it's not always stdin.
input_line = fgets(input_line, 1023, stdin);
@ -843,13 +832,12 @@ int dbg_handle_debug_input()
if ( input_line )
{
free(input_line); // this was malloc'ed
free(input_line); // this was malloc'ed
input_line = nullptr;
}
else
exit(0);
}
while ( status == 0 );
} while ( status == 0 );
// Clear out some state. ### Is there a better place?
g_debugger_state.curr_frame_idx = 0;
@ -861,12 +849,10 @@ int dbg_handle_debug_input()
return 0;
}
// Return true to continue execution, false to abort.
bool pre_execute_stmt(Stmt* stmt, Frame* f)
{
if ( ! g_policy_debug ||
stmt->Tag() == STMT_LIST || stmt->Tag() == STMT_NULL )
if ( ! g_policy_debug || stmt->Tag() == STMT_LIST || stmt->Tag() == STMT_NULL )
return true;
if ( g_trace_state.DoTrace() )
@ -888,8 +874,7 @@ bool pre_execute_stmt(Stmt* stmt, Frame* f)
bool should_break = false;
if ( g_debugger_state.BreakBeforeNextStmt() ||
f->BreakBeforeNextStmt() )
if ( g_debugger_state.BreakBeforeNextStmt() || f->BreakBeforeNextStmt() )
{
if ( g_debugger_state.BreakBeforeNextStmt() )
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 )
{
int break_code = i->second->ShouldBreak(stmt);
if ( break_code == 2 ) // ### 2?
if ( break_code == 2 ) // ### 2?
{
i->second->SetEnable(false);
delete i->second;
@ -960,14 +945,14 @@ ValPtr dbg_eval_expr(const char* expr)
// Push the current frame's associated scope.
// Note: g_debugger_state.curr_frame_idx is the user-visible number,
// while the array index goes in the opposite direction
int frame_idx =
(g_frame_stack.size() - 1) - g_debugger_state.curr_frame_idx;
int frame_idx = (g_frame_stack.size() - 1) - g_debugger_state.curr_frame_idx;
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()");
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()");
Frame* frame = g_frame_stack[frame_idx];
if ( ! (frame) )
if ( ! (frame) )
reporter->InternalError("Assertion failed: frame");
const ScriptFunc* func = frame->GetFunction();
@ -1009,11 +994,11 @@ ValPtr dbg_eval_expr(const char* expr)
delete g_curr_debug_expr;
g_curr_debug_expr = nullptr;
delete [] g_curr_debug_error;
delete[] g_curr_debug_error;
g_curr_debug_error = nullptr;
in_debug = false;
return result;
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -2,16 +2,17 @@
#pragma once
#include <vector>
#include <deque>
#include <map>
#include <string>
#include <deque>
#include <vector>
#include "zeek/Obj.h"
#include "zeek/StmtEnums.h"
#include "zeek/util.h"
namespace zeek {
namespace zeek
{
class Val;
template <class T> class IntrusivePtr;
@ -19,7 +20,8 @@ using ValPtr = zeek::IntrusivePtr<Val>;
extern std::string current_module;
namespace detail {
namespace detail
{
class Frame;
class Stmt;
@ -28,14 +30,20 @@ class DbgWatch;
class DbgDisplay;
// This needs to be defined before we do the includes that come after it.
enum ParseLocationRecType { PLR_UNKNOWN, PLR_FILE_AND_LINE, PLR_FUNCTION };
class ParseLocationRec {
enum ParseLocationRecType
{
PLR_UNKNOWN,
PLR_FILE_AND_LINE,
PLR_FUNCTION
};
class ParseLocationRec
{
public:
ParseLocationRecType type;
int32_t line;
Stmt* stmt;
const char* filename;
};
};
class StmtLocMapping;
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 BPMapType = std::multimap<const Stmt*, DbgBreakpoint*>;
class TraceState {
class TraceState
{
public:
TraceState() { dbgtrace = false; trace_file = stderr; }
TraceState()
{
dbgtrace = false;
trace_file = stderr;
}
// Returns previous filename.
FILE* SetTraceFile(const char* trace_filename);
bool DoTrace() const { return dbgtrace; }
bool DoTrace() const { return dbgtrace; }
void TraceOn();
void TraceOff();
int LogTrace(const char* fmt, ...) __attribute__((format(printf, 2, 3)));;
int LogTrace(const char* fmt, ...) __attribute__((format(printf, 2, 3)));
;
protected:
bool dbgtrace; // print an execution trace
bool dbgtrace; // print an execution trace
FILE* trace_file;
};
};
extern TraceState g_trace_state;
class DebuggerState {
class DebuggerState
{
public:
DebuggerState();
~DebuggerState();
int NextBPID() { return next_bp_id++; }
int NextWatchID() { return next_watch_id++; }
int NextDisplayID() { return next_display_id++; }
int NextBPID() { return next_bp_id++; }
int NextWatchID() { return next_watch_id++; }
int NextDisplayID() { return next_display_id++; }
bool BreakBeforeNextStmt() { return break_before_next_stmt; }
void BreakBeforeNextStmt(bool dobrk) { break_before_next_stmt = dobrk; }
@ -78,7 +93,6 @@ public:
bool BreakFromSignal() { return break_from_signal; }
void BreakFromSignal(bool dobrk) { break_from_signal = dobrk; }
// Temporary state: vanishes when execution resumes.
//### 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.
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<DbgDisplay*> displays;
BPMapType breakpoint_map; // maps Stmt -> Breakpoints on it
BPMapType breakpoint_map; // maps Stmt -> Breakpoints on it
protected:
bool break_before_next_stmt; // trap into debugger (used for "step")
bool break_from_signal; // was break caused by a signal?
bool break_before_next_stmt; // trap into debugger (used for "step")
bool break_from_signal; // was break caused by a signal?
int next_bp_id, next_watch_id, next_display_id;
private:
Frame* dbg_locals; // unused
};
};
// Source line -> statement mapping.
// (obj -> source line mapping available in object itself)
class StmtLocMapping {
class StmtLocMapping
{
public:
StmtLocMapping() { }
StmtLocMapping(const Location* l, Stmt* s) { loc = *l; stmt = s; }
StmtLocMapping() { }
StmtLocMapping(const Location* l, Stmt* s)
{
loc = *l;
stmt = s;
}
bool StartsAfter(const StmtLocMapping* m2);
const Location& Loc() const { return loc; }
Stmt* Statement() const { return stmt; }
const Location& Loc() const { return loc; }
Stmt* Statement() const { return stmt; }
protected:
Location loc;
Stmt* stmt;
};
};
extern bool g_policy_debug; // enable debugging facility
extern bool g_policy_debug; // enable debugging facility
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
// Debugging hooks.
// Return true to continue execution, false to abort.
@ -158,7 +176,7 @@ int dbg_init_debugger(const char* cmdfile = nullptr);
int dbg_shutdown_debugger();
// 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
// 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".
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
// 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 zeek
} // namespace detail
} // namespace zeek

View file

@ -1,32 +1,32 @@
// Support routines to help deal with Bro debugging commands and
// implementation of most commands.
#include "zeek/zeek-config.h"
#include "zeek/DebugCmds.h"
#include <sys/types.h>
#include <assert.h>
#include <regex.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/ID.h"
#include "zeek/Debug.h"
#include "zeek/DebugCmdInfoConstants.cc"
#include "zeek/Desc.h"
#include "zeek/Frame.h"
#include "zeek/Func.h"
#include "zeek/Stmt.h"
#include "zeek/Scope.h"
#include "zeek/Reporter.h"
#include "zeek/ID.h"
#include "zeek/PolicyFile.h"
#include "zeek/Reporter.h"
#include "zeek/Scope.h"
#include "zeek/Stmt.h"
#include "zeek/Val.h"
#include "zeek/util.h"
#include "zeek/zeek-config.h"
using namespace std;
namespace zeek::detail {
namespace zeek::detail
{
DebugCmdInfoQueue g_DebugCmdInfos;
@ -55,7 +55,7 @@ static void lookup_global_symbols_regex(const string& orig_regex, vector<ID*>& m
regex.push_back('$');
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());
return;
@ -69,7 +69,7 @@ static void lookup_global_symbols_regex(const string& orig_regex, vector<ID*>& m
{
ID* nextid = sym.second.get();
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);
}
}
@ -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");
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("[n] None of the above\n");
@ -112,7 +112,7 @@ static void choose_global_symbols_regex(const string& regex, vector<ID*>& choice
return;
}
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];
choices.clear();
@ -122,13 +122,11 @@ static void choose_global_symbols_regex(const string& regex, vector<ID*>& choice
}
}
//
// DebugCmdInfo implementation
//
DebugCmdInfo::DebugCmdInfo(const DebugCmdInfo& info)
: cmd(info.cmd), helpstring(nullptr)
DebugCmdInfo::DebugCmdInfo(const DebugCmdInfo& info) : cmd(info.cmd), helpstring(nullptr)
{
num_names = info.num_names;
names = info.names;
@ -136,11 +134,10 @@ DebugCmdInfo::DebugCmdInfo(const DebugCmdInfo& info)
repeatable = info.repeatable;
}
DebugCmdInfo::DebugCmdInfo(DebugCmd arg_cmd, const char* const* arg_names,
int arg_num_names, bool arg_resume_execution,
const char* const arg_helpstring,
bool arg_repeatable)
: cmd(arg_cmd), helpstring(arg_helpstring)
DebugCmdInfo::DebugCmdInfo(DebugCmd arg_cmd, const char* const* arg_names, int arg_num_names,
bool arg_resume_execution, const char* const arg_helpstring,
bool arg_repeatable)
: cmd(arg_cmd), helpstring(arg_helpstring)
{
num_names = arg_num_names;
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]);
}
const DebugCmdInfo* get_debug_cmd_info(DebugCmd cmd)
{
if ( (int) cmd < g_DebugCmdInfos.size() )
return g_DebugCmdInfos[(int) cmd];
if ( (int)cmd < g_DebugCmdInfos.size() )
return g_DebugCmdInfos[(int)cmd];
else
return nullptr;
}
@ -198,13 +194,11 @@ int find_all_matching_cmds(const string& prefix, const char* array_of_matches[])
// ------------------------------------------------------------
// Implementation of some debugger commands
// Start, end bounds of which frame numbers to print
static int dbg_backtrace_internal(int start, int end)
{
if ( start < 0 || end < 0 ||
(unsigned) start >= g_frame_stack.size() ||
(unsigned) end >= g_frame_stack.size() )
if ( start < 0 || end < 0 || (unsigned)start >= g_frame_stack.size() ||
(unsigned)end >= g_frame_stack.size() )
reporter->InternalError("Invalid stack frame index in DbgBacktraceInternal\n");
if ( start < end )
@ -220,14 +214,12 @@ static int dbg_backtrace_internal(int start, int end)
const Stmt* stmt = f ? f->GetNextStmt() : nullptr;
string context = get_context_description(stmt, f);
debug_msg("#%d %s\n",
int(g_frame_stack.size() - 1 - i), context.c_str());
debug_msg("#%d %s\n", int(g_frame_stack.size() - 1 - i), context.c_str());
};
return 1;
}
// Returns 0 for illegal arguments, or 1 on success.
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 )
{
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);
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);
}
// Returns 0 if invalid args, else 1.
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;
}
if ( idx < 0 ||
(unsigned int) idx >= g_frame_stack.size() )
if ( idx < 0 || (unsigned int)idx >= g_frame_stack.size() )
{
debug_msg("No frame %d", idx);
return 0;
@ -319,8 +309,7 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args)
else if ( cmd == dcUp )
{
if ( (unsigned int)(g_debugger_state.curr_frame_idx + 1) ==
g_frame_stack.size() )
if ( (unsigned int)(g_debugger_state.curr_frame_idx + 1) == g_frame_stack.size() )
{
debug_msg("Outermost frame already selected\n");
return 0;
@ -329,8 +318,7 @@ int dbg_cmd_frame(DebugCmd cmd, const vector<string>& args)
++g_debugger_state.curr_frame_idx;
}
int user_frame_number =
g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
int user_frame_number = g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
// Set the current location to the new frame being looked at
// for 'list', 'break', etc.
@ -352,14 +340,13 @@ int dbg_cmd_help(DebugCmd cmd, const vector<string>& args)
debug_msg("Help summary: \n\n");
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());
}
return -1;
}
int dbg_cmd_break(DebugCmd cmd, const vector<string>& args)
{
assert(cmd == dcBreak);
@ -370,9 +357,7 @@ int dbg_cmd_break(DebugCmd cmd, const vector<string>& args)
if ( args.empty() || args[0] == "if" )
{ // break on next stmt
int user_frame_number =
g_frame_stack.size() - 1 -
g_debugger_state.curr_frame_idx;
int user_frame_number = g_frame_stack.size() - 1 - g_debugger_state.curr_frame_idx;
Stmt* stmt = g_frame_stack[user_frame_number]->GetNextStmt();
if ( ! stmt )
@ -407,13 +392,10 @@ int dbg_cmd_break(DebugCmd cmd, const vector<string>& args)
else
locstrings.push_back(args[0].c_str());
for ( unsigned int strindex = 0; strindex < locstrings.size();
++strindex )
for ( unsigned int strindex = 0; strindex < locstrings.size(); ++strindex )
{
debug_msg("Setting breakpoint on %s:\n",
locstrings[strindex].c_str());
vector<ParseLocationRec> plrs =
parse_location_string(locstrings[strindex]);
debug_msg("Setting breakpoint on %s:\n", locstrings[strindex].c_str());
vector<ParseLocationRec> plrs = parse_location_string(locstrings[strindex]);
for ( const auto& plr : plrs )
{
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.
int dbg_cmd_break_set_state(DebugCmd cmd, const vector<string>& args)
{
assert(cmd == dcDeleteBreak || cmd == dcClearBreak ||
cmd == dcDisableBreak || cmd == dcEnableBreak ||
cmd == dcIgnoreBreak);
assert(cmd == dcDeleteBreak || cmd == dcClearBreak || cmd == dcDisableBreak ||
cmd == dcEnableBreak || 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() )
{
debug_msg ("No breakpoints currently set.\n");
debug_msg("No breakpoints currently set.\n");
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 )
{
BPIDMapType::iterator result =
g_debugger_state.breakpoints.find(bp_change);
BPIDMapType::iterator result = g_debugger_state.breakpoints.find(bp_change);
if ( result != g_debugger_state.breakpoints.end() )
{
switch ( cmd ) {
case dcDisableBreak:
g_debugger_state.breakpoints[bp_change]->SetEnable(false);
debug_msg("Breakpoint %d disabled\n", bp_change);
break;
switch ( cmd )
{
case dcDisableBreak:
g_debugger_state.breakpoints[bp_change]->SetEnable(false);
debug_msg("Breakpoint %d disabled\n", bp_change);
break;
case dcEnableBreak:
g_debugger_state.breakpoints[bp_change]->SetEnable(true);
debug_msg("Breakpoint %d enabled\n", bp_change);
break;
case dcEnableBreak:
g_debugger_state.breakpoints[bp_change]->SetEnable(true);
debug_msg("Breakpoint %d enabled\n", bp_change);
break;
case dcDeleteBreak:
delete g_debugger_state.breakpoints[bp_change];
g_debugger_state.breakpoints.erase(bp_change);
debug_msg("Breakpoint %d deleted\n", bp_change);
break;
case dcDeleteBreak:
delete g_debugger_state.breakpoints[bp_change];
g_debugger_state.breakpoints.erase(bp_change);
debug_msg("Breakpoint %d deleted\n", bp_change);
break;
default:
reporter->InternalError("Invalid command in DbgCmdBreakSetState\n");
}
default:
reporter->InternalError("Invalid command in DbgCmdBreakSetState\n");
}
}
else
@ -582,7 +563,6 @@ int dbg_cmd_print(DebugCmd cmd, const vector<string>& args)
return 1;
}
// Get the debugger's state.
// Allowed arguments are: break (breakpoints), watch, display, source.
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;
for ( iter = g_debugger_state.breakpoints.begin();
iter != g_debugger_state.breakpoints.end();
++iter )
iter != g_debugger_state.breakpoints.end(); ++iter )
{
DbgBreakpoint* bp = (*iter).second;
debug_msg("%-4d%-15s%-5s%-4s%s\n",
bp->GetID(),
"breakpoint",
bp->IsTemporary() ? "del" : "keep",
bp->IsEnabled() ? "y" : "n",
bp->Description());
debug_msg("%-4d%-15s%-5s%-4s%s\n", bp->GetID(), "breakpoint",
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;
}
if ( (int) pre_offset +
(int) g_debugger_state.last_loc.first_line -
(int) CENTER_IDX < 0 )
if ( (int)pre_offset + (int)g_debugger_state.last_loc.first_line - (int)CENTER_IDX < 0 )
pre_offset = CENTER_IDX - g_debugger_state.last_loc.first_line;
g_debugger_state.last_loc.first_line += pre_offset;
int last_line_in_file =
how_many_lines_in(g_debugger_state.last_loc.filename);
int last_line_in_file = how_many_lines_in(g_debugger_state.last_loc.filename);
if ( 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,
g_debugger_state.last_loc.first_line - CENTER_IDX,
10, true);
g_debugger_state.last_loc.first_line - CENTER_IDX, 10, 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() )
{
debug_msg("Execution tracing is %s.\n",
g_trace_state.DoTrace() ? "on" : "off" );
debug_msg("Execution tracing is %s.\n", g_trace_state.DoTrace() ? "on" : "off");
return 1;
}
@ -725,4 +696,4 @@ int dbg_cmd_trace(DebugCmd cmd, const vector<string>& args)
return 0;
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

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

View file

@ -11,29 +11,17 @@
zeek::detail::DebugLogger 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.
DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = {
{ "serial", 0, false },
{ "rules", 0, false },
{ "string", 0, false },
{ "notifiers", 0, false },
{ "main-loop", 0, false },
{ "dpd", 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 }
};
{"serial", 0, false}, {"rules", 0, false}, {"string", 0, false},
{"notifiers", 0, false}, {"main-loop", 0, false}, {"dpd", 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()
{
@ -81,10 +69,11 @@ void DebugLogger::ShowStreamsHelp()
fprintf(stderr, "Available streams:\n");
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, " 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, "Pseudo streams\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);
next:
next:
tok = strtok(0, ",");
}
delete [] tmp;
delete[] tmp;
}
void DebugLogger::Log(DebugStream stream, const char* fmt, ...)
@ -160,8 +149,8 @@ void DebugLogger::Log(DebugStream stream, const char* fmt, ...)
if ( ! g->enabled )
return;
fprintf(file, "%17.06f/%17.06f [%s] ",
run_state::network_time, util::current_time(true), g->prefix);
fprintf(file, "%17.06f/%17.06f [%s] ", run_state::network_time, util::current_time(true),
g->prefix);
for ( int i = g->indent; i > 0; --i )
fputs(" ", file);
@ -183,8 +172,8 @@ void DebugLogger::Log(const plugin::Plugin& plugin, const char* fmt, ...)
if ( enabled_streams.find(tok) == enabled_streams.end() )
return;
fprintf(file, "%17.06f/%17.06f [plugin %s] ",
run_state::network_time, util::current_time(true), plugin.Name().c_str());
fprintf(file, "%17.06f/%17.06f [plugin %s] ", run_state::network_time, util::current_time(true),
plugin.Name().c_str());
va_list ap;
va_start(ap, fmt);
@ -195,6 +184,6 @@ void DebugLogger::Log(const plugin::Plugin& plugin, const char* fmt, ...)
fflush(file);
}
} // namespace zeek::detail
} // namespace zeek::detail
#endif

View file

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

View file

@ -1,22 +1,23 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Desc.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "zeek/File.h"
#include "zeek/Reporter.h"
#include "zeek/ConvertUTF.h"
#include "zeek/File.h"
#include "zeek/IPAddr.h"
#include "zeek/Reporter.h"
#include "zeek/zeek-config.h"
#define DEFAULT_SIZE 128
#define SLOP 10
namespace zeek {
namespace zeek
{
ODesc::ODesc(DescType t, File* arg_f)
{
@ -28,7 +29,7 @@ ODesc::ODesc(DescType t, File* arg_f)
{
size = DEFAULT_SIZE;
base = util::safe_malloc(size);
((char*) base)[0] = '\0';
((char*)base)[0] = '\0';
offset = 0;
}
else
@ -64,7 +65,7 @@ void ODesc::EnableEscaping()
escape = true;
}
void ODesc::EnableUTF8 ()
void ODesc::EnableUTF8()
{
utf8 = true;
}
@ -93,12 +94,11 @@ void ODesc::Add(const char* s, int do_indent)
{
unsigned int n = strlen(s);
if ( do_indent && IsReadable() && offset > 0 &&
((const char*) base)[offset - 1] == '\n' )
if ( do_indent && IsReadable() && offset > 0 && ((const char*)base)[offset - 1] == '\n' )
Indent();
if ( IsBinary() )
AddBytes(s, n+1);
AddBytes(s, n + 1);
else
AddBytes(s, n);
}
@ -169,13 +169,12 @@ void ODesc::Add(double d, bool no_exp)
Add(tmp);
auto approx_equal = [](double a, double b, double tolerance = 1e-6) -> bool
{
{
auto v = a - b;
return v < 0 ? -v < tolerance : v < tolerance;
};
};
if ( approx_equal(d, nearbyint(d), 1e-9) &&
isfinite(d) && ! strchr(tmp, 'e') )
if ( approx_equal(d, nearbyint(d), 1e-9) && isfinite(d) && ! strchr(tmp, 'e') )
// disambiguate from integer
Add(".0");
}
@ -210,7 +209,7 @@ void ODesc::AddBytes(const String* s)
{
const char* str = s->Render(String::EXPANDED_STRING);
Add(str);
delete [] str;
delete[] str;
}
}
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)
{
if ( ! escape )
{
AddBytesRaw(bytes, n);
return;
}
{
AddBytesRaw(bytes, n);
return;
}
const char* s = (const char*) bytes;
const char* e = (const char*) bytes + n;
const char* s = (const char*)bytes;
const char* e = (const char*)bytes + n;
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 )
{
@ -343,7 +342,7 @@ void ODesc::AddBytesRaw(const void* bytes, unsigned int n)
{
static bool write_failed = false;
if ( ! f->Write((const char*) bytes, n) )
if ( ! f->Write((const char*)bytes, n) )
{
if ( ! write_failed )
// 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
// simply using &base[offset] generates complaints about
// using a void* for pointer arithemtic.
memcpy((void*) &((char*) base)[offset], bytes, n);
memcpy((void*)&((char*)base)[offset], bytes, 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);
size = DEFAULT_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;
}
std::string obj_desc(const Obj* o)
{
static ODesc d;
@ -428,4 +426,4 @@ std::string obj_desc(const Obj* o)
return std::string(d.Description());
}
} // namespace zeek
} // namespace zeek

View file

@ -3,95 +3,97 @@
#pragma once
#include <sys/types.h> // for u_char
#include <set>
#include <utility>
#include <string>
#include <utility>
#include "zeek/ZeekString.h" // for byte_vec
#include "zeek/util.h" // for bro_int_t
namespace zeek {
namespace zeek
{
class IPAddr;
class IPPrefix;
class File;
class Type;
enum DescType {
enum DescType
{
DESC_READABLE,
DESC_PORTABLE,
DESC_BINARY,
};
};
enum DescStyle {
enum DescStyle
{
STANDARD_STYLE,
RAW_STYLE,
};
};
class ODesc {
class ODesc
{
public:
explicit ODesc(DescType t=DESC_READABLE, File* f=nullptr);
explicit ODesc(DescType t = DESC_READABLE, File* f = nullptr);
~ODesc();
bool IsReadable() const { return type == DESC_READABLE; }
bool IsPortable() const { return type == DESC_PORTABLE; }
bool IsBinary() const { return type == DESC_BINARY; }
bool IsReadable() const { return type == DESC_READABLE; }
bool IsPortable() const { return type == DESC_PORTABLE; }
bool IsBinary() const { return type == DESC_BINARY; }
bool IsShort() const { return is_short; }
void SetShort() { is_short = true; }
void SetShort(bool s) { is_short = s; }
bool IsShort() const { return is_short; }
void SetShort() { is_short = true; }
void SetShort(bool s) { is_short = s; }
// Whether we want to have quotes around strings.
bool WantQuotes() const { return want_quotes; }
void SetQuotes(bool q) { want_quotes = q; }
bool WantQuotes() const { return want_quotes; }
void SetQuotes(bool q) { want_quotes = q; }
// Whether to ensure deterministic output (for example, when
// describing TableVal's).
bool WantDeterminism() const { return want_determinism; }
void SetDeterminism(bool d) { want_determinism = d; }
bool WantDeterminism() const { return want_determinism; }
void SetDeterminism(bool d) { want_determinism = d; }
// Whether we want to print statistics like access time and execution
// count where available.
bool IncludeStats() const { return include_stats; }
void SetIncludeStats(bool s) { include_stats = s; }
bool IncludeStats() const { return include_stats; }
void SetIncludeStats(bool s) { include_stats = s; }
DescStyle Style() const { return style; }
void SetStyle(DescStyle s) { style = s; }
DescStyle Style() const { return style; }
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 EnableUTF8();
void AddEscapeSequence(const char* s) { escape_sequences.insert(s); }
void AddEscapeSequence(const char* s, size_t n)
{ escape_sequences.insert(std::string(s, n)); }
void AddEscapeSequence(const std::string & s)
{ escape_sequences.insert(s); }
void AddEscapeSequence(const char* s, size_t n) { escape_sequences.insert(std::string(s, n)); }
void AddEscapeSequence(const std::string& s) { escape_sequences.insert(s); }
void RemoveEscapeSequence(const char* s) { escape_sequences.erase(s); }
void RemoveEscapeSequence(const char* s, size_t n)
{ escape_sequences.erase(std::string(s, n)); }
void RemoveEscapeSequence(const std::string & s)
{ escape_sequences.erase(s); }
{
escape_sequences.erase(std::string(s, n));
}
void RemoveEscapeSequence(const std::string& s) { escape_sequences.erase(s); }
void PushIndent();
void PopIndent();
void PopIndentNoNL();
int GetIndentLevel() const { return indent_level; }
int GetIndentLevel() const { return indent_level; }
void ClearIndentLevel() { indent_level = 0; }
int IndentSpaces() const { return indent_with_spaces; }
void SetIndentSpaces(int i) { indent_with_spaces = i; }
int IndentSpaces() const { return indent_with_spaces; }
void SetIndentSpaces(int i) { indent_with_spaces = i; }
void Add(const char* s, int do_indent=1);
void AddN(const char* s, int len) { AddBytes(s, len); }
void Add(const std::string& s) { AddBytes(s.data(), s.size()); }
void Add(const char* s, int do_indent = 1);
void AddN(const char* s, int len) { AddBytes(s, len); }
void Add(const std::string& s) { AddBytes(s.data(), s.size()); }
void Add(int i);
void Add(uint32_t u);
void Add(int64_t i);
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 IPPrefix& prefix);
@ -101,13 +103,22 @@ public:
void AddBytes(const String* s);
void Add(const char* s1, const char* s2)
{ Add(s1); Add(s2); }
{
Add(s1);
Add(s2);
}
void AddSP(const char* s1, const char* s2)
{ Add(s1); AddSP(s2); }
{
Add(s1);
AddSP(s2);
}
void AddSP(const char* s )
{ Add(s); SP(); }
void AddSP(const char* s)
{
Add(s);
SP();
}
void AddCount(bro_int_t n)
{
@ -118,23 +129,25 @@ public:
}
}
void SP() {
if ( ! IsBinary() )
Add(" ", 0);
}
void NL() {
if ( ! IsBinary() && ! is_short )
Add("\n", 0);
}
void SP()
{
if ( ! IsBinary() )
Add(" ", 0);
}
void NL()
{
if ( ! IsBinary() && ! is_short )
Add("\n", 0);
}
// Bypasses the escaping enabled via EnableEscaping().
void AddRaw(const char* s, int len) { AddBytesRaw(s, len); }
void AddRaw(const std::string &s) { AddBytesRaw(s.data(), s.size()); }
void AddRaw(const char* s, int len) { AddBytesRaw(s, len); }
void AddRaw(const std::string& s) { AddBytesRaw(s.data(), s.size()); }
// 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()
{
const void* t = base;
@ -147,7 +160,7 @@ public:
return byte_vec(t);
}
int Len() const { return offset; }
int Len() const { return offset; }
void Clear();
@ -191,12 +204,12 @@ protected:
DescType type;
DescStyle style;
void* base; // beginning of buffer
unsigned int offset; // where we are in the buffer
unsigned int size; // size of buffer in bytes
void* base; // beginning of buffer
unsigned int offset; // where we are in the buffer
unsigned int size; // size of buffer in bytes
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 want_quotes;
bool want_determinism;
@ -209,10 +222,10 @@ protected:
using escape_set = std::set<std::string>;
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;
};
};
// Returns a string representation of an object's description. Used for
// debugging and error messages. takes a bare pointer rather than an
@ -221,4 +234,4 @@ protected:
class Obj;
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
#include <cstdint>
#include <vector>
#include <memory>
#include <vector>
#include "zeek/Hash.h"
// Type for function to be called when deleting elements.
typedef void (*dict_delete_func)(void*);
namespace zeek {
namespace zeek
{
class IterCookie;
class Dictionary;
enum DictOrder { ORDERED, UNORDERED };
enum DictOrder
{
ORDERED,
UNORDERED
};
// A dict_delete_func that just calls delete.
extern void generic_delete_func(void*);
namespace detail {
namespace detail
{
class DictEntry;
// Default number of hash buckets in dictionary. The dictionary will increase the size
// 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
// or for debugging purposes.
@ -54,9 +60,9 @@ constexpr uint16_t TOO_FAR_TO_REACH = 0xFFFF;
/**
* An entry stored in the dictionary.
*/
class DictEntry {
class DictEntry
{
public:
#ifdef DEBUG
int bucket = 0;
#endif
@ -72,10 +78,10 @@ public:
uint32_t hash = 0;
void* value = nullptr;
union {
char key_here[8]; //hold key len<=8. when over 8, it's a pointer to real keys.
union {
char key_here[8]; // hold key len<=8. when over 8, it's a pointer to real keys.
char* key;
};
};
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)
@ -88,7 +94,7 @@ public:
{
memcpy(key_here, arg_key, key_size);
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
{
@ -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()
{
distance = TOO_FAR_TO_REACH;
@ -115,13 +121,13 @@ public:
value = nullptr;
key_size = 0;
bucket = 0;
#endif//DEBUG
#endif // DEBUG
}
void Clear()
{
if( key_size > 8 )
delete [] key;
if ( key_size > 8 )
delete[] key;
SetEmpty();
}
@ -131,27 +137,21 @@ public:
return std::make_unique<detail::HashKey>(GetKey(), key_size, hash);
}
template <typename T>
T GetValue() const { return static_cast<T>(value); }
template <typename T> T GetValue() const { return static_cast<T>(value); }
bool Equal(const char* arg_key, int arg_key_size, hash_t arg_hash) const
{//only 40-bit hash comparison.
return ( 0 == ((hash ^ arg_hash) & HASH_MASK) )
&& key_size == arg_key_size && 0 == memcmp(GetKey(), arg_key, key_size);
{ // only 40-bit hash comparison.
return (0 == ((hash ^ arg_hash) & HASH_MASK)) && key_size == arg_key_size &&
0 == memcmp(GetKey(), arg_key, key_size);
}
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);
}
};
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); }
};
} // namespace detail
} // namespace detail
class DictIterator {
class DictIterator
{
public:
using value_type = detail::DictEntry;
using reference = detail::DictEntry&;
@ -171,13 +171,17 @@ public:
pointer operator->() { return curr; }
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 !(*this == that); }
bool operator==(const DictIterator& that) const { return curr == that.curr; }
bool operator!=(const DictIterator& that) const { return ! (*this == that); }
private:
friend class Dictionary;
DictIterator(const Dictionary* d, detail::DictEntry* begin, detail::DictEntry* end);
@ -185,9 +189,10 @@ private:
Dictionary* dict = nullptr;
detail::DictEntry* curr = nullptr;
detail::DictEntry* end = nullptr;
};
};
class RobustDictIterator {
class RobustDictIterator
{
public:
using value_type = detail::DictEntry;
using reference = detail::DictEntry&;
@ -195,20 +200,25 @@ public:
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
RobustDictIterator() : curr(nullptr) {}
RobustDictIterator() : curr(nullptr) { }
RobustDictIterator(Dictionary* d);
RobustDictIterator(const RobustDictIterator& other);
RobustDictIterator(RobustDictIterator&& other);
~RobustDictIterator();
~RobustDictIterator();
reference operator*() { return curr; }
pointer operator->() { return &curr; }
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 !(*this == that); }
bool operator==(const RobustDictIterator& that) const { return curr == that.curr; }
bool operator!=(const RobustDictIterator& that) const { return ! (*this == that); }
private:
friend class Dictionary;
@ -225,7 +235,7 @@ private:
detail::DictEntry curr;
Dictionary* dict = nullptr;
int next = -1;
};
};
/**
* 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
* entries is the absolute limit. Only Connections use that many entries, and that is rare.
*/
class Dictionary {
class Dictionary
{
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();
// Member functions for looking up a key, inserting/changing its
// contents, and deleting it. These come in two flavors: one
// which takes a zeek::detail::HashKey, and the other which takes a raw key,
// 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 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 the removal may have invalidated any existing iterators.
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
// that it's a heap pointer that now belongs to the Dictionary to
// manage as needed.
// If iterators_invalidated is supplied, its value is set to true
// 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
// 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 the removal may have invalidated any existing iterators.
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.
int Length() const
{ return num_entries; }
int Length() const { return num_entries; }
// Largest it's ever been.
int MaxLength() const
{ return max_entries; }
int MaxLength() const { return max_entries; }
// Total number of entries ever.
uint64_t NumCumulativeInserts() const
{ return cum_entries; }
uint64_t NumCumulativeInserts() const { return cum_entries; }
// 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;
// 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,
// which should be delete'd when no longer needed.
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]]
IterCookie* InitForIteration() const;
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]]
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 iteration.")]]
void StopIteration(IterCookie* cookie) const;
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
"iteration.")]] IterCookie*
InitForIteration() const;
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
"iteration.")]] 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 "
"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
// 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
// removed. (We don't get this for free, so only use it if
// necessary.)
[[deprecated("Remove in v5.1. Use begin_robust() and the standard-library-compatible version of iteration.")]]
void MakeRobustCookie(IterCookie* cookie);
[[deprecated("Remove in v5.1. Use begin_robust() and the standard-library-compatible version "
"of iteration.")]] void
MakeRobustCookie(IterCookie* cookie);
// Remove all entries.
void Clear();
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]]
size_t MemoryAllocation() const;
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] size_t
MemoryAllocation() const;
/// The capacity of the table, Buckets + Overflow Size.
int Capacity(bool expected = false) const;
//Debugging
// Debugging
#ifdef DEBUG
void AssertValid() const;
#endif//DEBUG
void Dump(int level=0) const;
#endif // DEBUG
void Dump(int level = 0) const;
void DistanceStats(int& max_distance, int* distances = 0, int num_distances = 0) const;
void DumpKeys() const;
@ -362,12 +382,12 @@ public:
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
iterator begin() { return { this, table, table + Capacity() }; }
iterator end() { return { this, table + Capacity(), table + Capacity() }; }
const_iterator begin() const { return { this, table, table + Capacity() }; }
const_iterator end() const { return { this, table + Capacity(), table + Capacity() }; }
const_iterator cbegin() { return { this, table, table + Capacity() }; }
const_iterator cend() { return { this, table + Capacity(), table + Capacity() }; }
iterator begin() { return {this, table, table + Capacity()}; }
iterator end() { return {this, table + Capacity(), table + Capacity()}; }
const_iterator begin() const { return {this, table, table + Capacity()}; }
const_iterator end() const { return {this, table + Capacity(), table + Capacity()}; }
const_iterator cbegin() { return {this, table, table + Capacity()}; }
const_iterator cend() { return {this, table + Capacity(), table + Capacity()}; }
RobustDictIterator begin_robust() { return MakeRobustIterator(); }
RobustDictIterator end_robust() { return RobustDictIterator(); }
@ -380,7 +400,7 @@ private:
/// Buckets of the table, not including overflow size.
int Buckets(bool expected = false) const;
//bucket math
// bucket math
int Log2(int num) const;
int ThresholdEntries() const;
@ -419,47 +439,55 @@ private:
void Init();
// Iteration
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]]
IterCookie* InitForIterationNonConst();
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of iteration.")]]
void* 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);
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
"iteration.")]] IterCookie*
InitForIterationNonConst();
[[deprecated("Remove in v5.1. Use begin() and the standard-library-compatible version of "
"iteration.")]] void*
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 LookupIndex(const void* key, int key_size, detail::hash_t hash, int* insert_position = nullptr,
int* insert_distance = nullptr);
int LookupIndex(const void* key, int key_size, detail::hash_t hash,
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* insert_position = nullptr, int* insert_distance = nullptr);
int* insert_position = nullptr, int* insert_distance = nullptr);
/// Insert entry, Adjust cookies when necessary.
void InsertRelocateAndAdjust(detail::DictEntry& entry, int insert_position);
/// 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.
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration and the version that takes a RobustDictIterator.")]]
void AdjustOnInsert(IterCookie* c, const detail::DictEntry& entry, int insert_position, int last_affected_position);
void AdjustOnInsert(RobustDictIterator* c, const detail::DictEntry& entry,
int insert_position, int last_affected_position);
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration and the "
"version that takes a RobustDictIterator.")]] void
AdjustOnInsert(IterCookie* c, const detail::DictEntry& entry, int insert_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);
///Remove & Relocate
/// Remove & Relocate
detail::DictEntry RemoveAndRelocate(int position, int* last_affected_position = nullptr);
///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.")]]
void AdjustOnRemove(IterCookie* c, const detail::DictEntry& entry, int position, int last_affected_position);
void AdjustOnRemove(RobustDictIterator* c, const detail::DictEntry& entry,
int position, int last_affected_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.")]] void
AdjustOnRemove(IterCookie* c, const detail::DictEntry& entry, int 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();
// Remap an item in position to a new position. Returns true if the relocation was
@ -471,16 +499,18 @@ private:
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();
detail::DictEntry GetNextRobustIteration(RobustDictIterator* iter);
void IncrIters() { ++num_iterators; }
void DecrIters() { --num_iterators; }
void IncrIters() { ++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
// 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.
std::vector<detail::DictEntry>* order = nullptr;
};
};
/*
* Template specialization of Dictionary that stores pointers for values.
*/
template<typename T>
class PDict : public Dictionary {
template <typename T> class PDict : public Dictionary
{
public:
explicit PDict(DictOrder ordering = UNORDERED, int initial_size = 0) :
Dictionary(ordering, initial_size) {}
explicit PDict(DictOrder ordering = UNORDERED, int initial_size = 0)
: Dictionary(ordering, initial_size)
{
}
T* Lookup(const char* key) const
{
detail::HashKey h(key);
return (T*) Dictionary::Lookup(&h);
return (T*)Dictionary::Lookup(&h);
}
T* Lookup(const detail::HashKey* key) const
{ return (T*) Dictionary::Lookup(key); }
T* Lookup(const detail::HashKey* key) const { return (T*)Dictionary::Lookup(key); }
T* Insert(const char* key, T* val, bool* iterators_invalidated = nullptr)
{
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)
{ return (T*) Dictionary::Insert(key, (void*) val, iterators_invalidated); }
T* NthEntry(int n) const
{ return (T*) Dictionary::NthEntry(n); }
{
return (T*)Dictionary::Insert(key, (void*)val, iterators_invalidated);
}
T* NthEntry(int n) const { return (T*)Dictionary::NthEntry(n); }
T* NthEntry(int n, const char*& key) const
{
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.")]]
T* NextEntry(IterCookie*& cookie) const
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration.")]] T*
NextEntry(IterCookie*& cookie) const
{
detail::HashKey* h;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return (T*) Dictionary::NextEntry(h, cookie, false);
return (T*)Dictionary::NextEntry(h, cookie, false);
#pragma GCC diagnostic pop
}
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration.")]]
T* NextEntry(detail::HashKey*& h, IterCookie*& cookie) const
[[deprecated("Remove in v5.1. Use the standard-library-compatible version of iteration.")]] T*
NextEntry(detail::HashKey*& h, IterCookie*& cookie) const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return (T*) Dictionary::NextEntry(h, cookie, true);
return (T*)Dictionary::NextEntry(h, cookie, true);
#pragma GCC diagnostic pop
}
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)
{ 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.
#include "zeek/zeek-config.h"
#include "zeek/Discard.h"
#include <algorithm>
#include "zeek/ZeekString.h"
#include "zeek/RunState.h"
#include "zeek/Func.h"
#include "zeek/Var.h"
#include "zeek/Val.h"
#include "zeek/IP.h"
#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()
{
@ -26,9 +26,7 @@ Discarder::Discarder()
discarder_maxlen = static_cast<int>(id::find_val("discarder_maxlen")->AsCount());
}
Discarder::~Discarder()
{
}
Discarder::~Discarder() { }
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();
if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
proto != IPPROTO_ICMP )
if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && proto != IPPROTO_ICMP )
// This is not a protocol we understand.
return false;
@ -69,14 +66,13 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
return false;
int ip_hdr_len = ip->HdrLen();
len -= ip_hdr_len; // remove IP header
len -= ip_hdr_len; // remove IP header
caplen -= ip_hdr_len;
bool is_tcp = (proto == IPPROTO_TCP);
bool is_udp = (proto == IPPROTO_UDP);
int min_hdr_len = is_tcp ?
sizeof(struct tcphdr) :
(is_udp ? sizeof(struct udphdr) : sizeof(struct icmp));
int min_hdr_len =
is_tcp ? sizeof(struct tcphdr) : (is_udp ? sizeof(struct udphdr) : sizeof(struct icmp));
if ( len < min_hdr_len || caplen < min_hdr_len )
// 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 )
{
const struct tcphdr* tp = (const struct tcphdr*) data;
const struct tcphdr* tp = (const struct tcphdr*)data;
int th_len = tp->th_off * 4;
zeek::Args args{
@ -114,8 +110,8 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
{
if ( check_udp )
{
const struct udphdr* up = (const struct udphdr*) data;
int uh_len = sizeof (struct udphdr);
const struct udphdr* up = (const struct udphdr*)data;
int uh_len = sizeof(struct udphdr);
zeek::Args args{
ip->ToPktHdrVal(),
@ -138,7 +134,7 @@ bool Discarder::NextPacket(const std::unique_ptr<IP_Hdr>& ip, int len, int caple
{
if ( check_icmp )
{
const struct icmp* ih = (const struct icmp*) data;
const struct icmp* ih = (const struct icmp*)data;
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));
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

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

View file

@ -1,12 +1,13 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/EquivClass.h"
#include "zeek/CCL.h"
#include "zeek/util.h"
#include "zeek/zeek-config.h"
namespace zeek::detail {
namespace zeek::detail
{
EquivClass::EquivClass(int arg_size)
{
@ -38,11 +39,11 @@ EquivClass::EquivClass(int arg_size)
EquivClass::~EquivClass()
{
delete [] fwd;
delete [] bck;
delete [] equiv_class;
delete [] rep;
delete [] ccl_flags;
delete[] fwd;
delete[] bck;
delete[] equiv_class;
delete[] rep;
delete[] ccl_flags;
}
void EquivClass::ConvertCCL(CCL* ccl)
@ -163,7 +164,6 @@ void EquivClass::CCL_Use(CCL* ccl)
}
}
void EquivClass::UniqueChar(int sym)
{
// 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);
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));
}
@ -192,4 +192,4 @@ int EquivClass::Size() const
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>
namespace zeek::detail {
namespace zeek::detail
{
class CCL;
class EquivClass {
class EquivClass
{
public:
explicit EquivClass(int size);
~EquivClass();
@ -22,26 +24,26 @@ public:
void ConvertCCL(CCL* ccl);
bool IsRep(int sym) const { return rep[sym] == sym; }
int EquivRep(int sym) const { return rep[sym]; }
int SymEquivClass(int sym) const { return equiv_class[sym]; }
int* EquivClasses() const { return equiv_class; }
bool IsRep(int sym) const { return rep[sym] == sym; }
int EquivRep(int sym) const { return rep[sym]; }
int SymEquivClass(int sym) const { return equiv_class[sym]; }
int* EquivClasses() const { return equiv_class; }
int NumSyms() const { return size; }
int NumClasses() const { return num_ecs; }
int NumSyms() const { return size; }
int NumClasses() const { return num_ecs; }
void Dump(FILE* f);
int Size() const;
protected:
int size; // size of character set
int num_ecs; // size of equivalence classes
int* fwd; // forward list of different classes
int* bck; // backward list
int* equiv_class; // symbol's equivalence class
int* rep; // representative for symbol's equivalence class
int size; // size of character set
int num_ecs; // size of equivalence classes
int* fwd; // forward list of different classes
int* bck; // backward list
int* equiv_class; // symbol's equivalence class
int* rep; // representative for symbol's equivalence class
int* ccl_flags;
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.
#include "zeek/zeek-config.h"
#include "zeek/Event.h"
#include "zeek/Desc.h"
#include "zeek/Func.h"
#include "zeek/NetVar.h"
#include "zeek/RunState.h"
#include "zeek/Trigger.h"
#include "zeek/Val.h"
#include "zeek/plugin/Manager.h"
#include "zeek/iosource/Manager.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& mgr = zeek::event_mgr;
namespace zeek {
namespace zeek
{
Event::Event(EventHandlerPtr arg_handler, zeek::Args arg_args,
util::detail::SourceID arg_src, analyzer::ID arg_aid,
Obj* arg_obj)
: handler(arg_handler),
args(std::move(arg_args)),
src(arg_src),
aid(arg_aid),
obj(arg_obj),
Event::Event(EventHandlerPtr arg_handler, zeek::Args arg_args, util::detail::SourceID arg_src,
analyzer::ID 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)
{
if ( obj )
@ -94,8 +90,7 @@ EventMgr::~EventMgr()
Unref(src_val);
}
void EventMgr::Enqueue(const EventHandlerPtr& h, Args vl,
util::detail::SourceID src,
void EventMgr::Enqueue(const EventHandlerPtr& h, Args vl, util::detail::SourceID src,
analyzer::ID aid, Obj* 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");
}
} // namespace zeek
} // namespace zeek

View file

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

View file

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

View file

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

View file

@ -1,9 +1,3 @@
#include "zeek/Val.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"

View file

@ -1,3 +1,10 @@
#pragma once
#include "zeek/Conn.h"
#include "zeek/Event.h"
#include "zeek/File.h"
#include "zeek/NetVar.h"
#include "zeek/Val.h"
#include "zeek/analyzer/Analyzer.h"
#include "event.bif.func_h"

View file

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

View file

@ -2,22 +2,24 @@
#pragma once
#include "zeek/zeek-config.h"
#include <map>
#include <memory>
#include <string>
#include <string_view>
#include <vector>
namespace zeek {
#include "zeek/zeek-config.h"
namespace zeek
{
class EventHandler;
class EventHandlerPtr;
class RE_Matcher;
// The registry keeps track of all events that we provide or handle.
class EventRegistry {
class EventRegistry
{
public:
EventRegistry();
~EventRegistry() noexcept;
@ -53,8 +55,8 @@ public:
private:
std::map<std::string, std::unique_ptr<EventHandler>, std::less<>> handlers;
};
};
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.
#include "zeek/zeek-config.h"
#include "zeek/File.h"
#include <sys/types.h>
#include "zeek/zeek-config.h"
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#include <sys/time.h>
#include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#include <errno.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <algorithm>
#include "zeek/Attr.h"
#include "zeek/Type.h"
#include "zeek/Desc.h"
#include "zeek/Event.h"
#include "zeek/Expr.h"
#include "zeek/NetVar.h"
#include "zeek/RunState.h"
#include "zeek/Event.h"
#include "zeek/Reporter.h"
#include "zeek/Desc.h"
#include "zeek/RunState.h"
#include "zeek/Type.h"
#include "zeek/Var.h"
namespace zeek {
namespace zeek
{
std::list<std::pair<std::string, File*>> File::open_files;
@ -159,8 +160,8 @@ File::~File()
Close();
Unref(attrs);
delete [] name;
delete [] access;
delete[] name;
delete[] access;
#ifdef USE_PERFTOOLS_DEBUG
heap_checker->UnIgnoreObject(this);
@ -231,7 +232,7 @@ bool File::Close()
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 )
{
@ -294,7 +295,7 @@ RecordVal* File::Rotate()
Unlink();
fclose(f);
fclose(f);
f = nullptr;
Open(newf);
@ -350,11 +351,11 @@ double File::Size()
FilePtr File::Get(const char* name)
{
for ( const auto &el : open_files )
for ( const auto& el : open_files )
if ( el.first == name )
return {NewRef{}, el.second};
return make_intrusive<File>(name, "w");
}
} // namespace zeek
} // namespace zeek

View file

@ -3,7 +3,6 @@
#pragma once
#include <fcntl.h>
#include <list>
#include <string>
#include <utility>
@ -15,16 +14,18 @@
#include "zeek/Val.h"
#include "zeek/util.h"
namespace zeek {
namespace zeek
{
namespace detail {
namespace detail
{
class PrintStmt;
class Attributes;
extern void do_print_stmt(const std::vector<ValPtr>& vals);
} // namespace detail;
} // namespace detail;
class RecordVal;
class Type;
@ -33,7 +34,8 @@ using TypePtr = IntrusivePtr<Type>;
class File;
using FilePtr = IntrusivePtr<File>;
class File final : public Obj {
class File final : public Obj
{
public:
explicit File(FILE* arg_f);
File(FILE* arg_f, const char* filename, const char* access);
@ -45,19 +47,18 @@ public:
// Returns false if an error occured.
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
{ return t; }
const TypePtr& GetType() const { return t; }
// Whether the file is open in a general sense; it might
// not be open as a Unix file due to our management of
// 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
// 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.
static FilePtr Get(const char* name);
void EnableRawOutput() { raw_output = true; }
bool IsRawOutput() const { return raw_output; }
void EnableRawOutput() { raw_output = true; }
bool IsRawOutput() const { return raw_output; }
protected:
friend void detail::do_print_stmt(const std::vector<ValPtr>& vals);
File() { Init(); }
File() { Init(); }
void Init();
/**
@ -114,7 +114,7 @@ protected:
char* access;
detail::Attributes* attrs;
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 raw_output;
@ -122,6 +122,6 @@ protected:
private:
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 <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include "zeek/Reporter.h"
namespace zeek::detail {
Flare::Flare()
: pipe(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK)
namespace zeek::detail
{
}
Flare::Flare() : pipe(FD_CLOEXEC, FD_CLOEXEC, O_NONBLOCK, O_NONBLOCK) { }
[[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;
for ( ; ; )
for ( ;; )
{
int n = write(pipe.WriteFD(), &tmp, 1);
@ -66,7 +64,7 @@ int Flare::Extinguish(bool signal_safe)
int rval = 0;
char tmp[256];
for ( ; ; )
for ( ;; )
{
int n = read(pipe.ReadFD(), &tmp, sizeof(tmp));
@ -91,4 +89,4 @@ int Flare::Extinguish(bool signal_safe)
return rval;
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -4,11 +4,12 @@
#include "zeek/Pipe.h"
namespace zeek::detail {
namespace zeek::detail
{
class Flare {
class Flare
{
public:
/**
* 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.
@ -21,7 +22,7 @@ public:
* @return a file descriptor that will become ready if the flare has been
* 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.
@ -41,6 +42,6 @@ public:
private:
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.
#include "zeek/zeek-config.h"
#include "zeek/Frag.h"
#include "zeek/Hash.h"
#include "zeek/IP.h"
#include "zeek/NetVar.h"
#include "zeek/session/Manager.h"
#include "zeek/Reporter.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 MAX_ACCEPTABLE_FRAG_SIZE = 64000;
namespace zeek::detail {
namespace zeek::detail
{
FragTimer::~FragTimer()
{
@ -29,9 +30,8 @@ void FragTimer::Dispatch(double t, bool /* is_expire */)
reporter->InternalWarning("fragment timer dispatched w/o reassembler");
}
FragReassembler::FragReassembler(session::Manager* arg_s,
const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt,
const FragReassemblerKey& k, double t)
FragReassembler::FragReassembler(session::Manager* arg_s, const std::unique_ptr<IP_Hdr>& ip,
const u_char* pkt, const FragReassemblerKey& k, double t)
: Reassembler(0, REASSEM_FRAG)
{
s = arg_s;
@ -41,9 +41,9 @@ FragReassembler::FragReassembler(session::Manager* arg_s,
if ( ip4 )
{
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.
memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len);
memcpy((void*)proto_hdr, (const void*)ip4, proto_hdr_len);
}
else
{
@ -53,7 +53,7 @@ FragReassembler::FragReassembler(session::Manager* arg_s,
}
reassembled_pkt = nullptr;
frag_size = 0; // flag meaning "not known"
frag_size = 0; // flag meaning "not known"
next_proto = ip->NextProto();
if ( frag_timeout != 0.0 )
@ -70,11 +70,10 @@ FragReassembler::FragReassembler(session::Manager* arg_s,
FragReassembler::~FragReassembler()
{
DeleteTimer();
delete [] proto_hdr;
delete[] proto_hdr;
}
void FragReassembler::AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip,
const u_char* pkt)
void FragReassembler::AddFragment(double t, const std::unique_ptr<IP_Hdr>& ip, const u_char* pkt)
{
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 ||
ip4->ip_hl != ((const struct ip*)proto_hdr)->ip_hl )
// || ip4->ip_tos != proto_hdr->ip_tos
// don't check TOS, there's at least one stack that actually
// uses different values, and it's hard to see an associated
// attack.
s->Weird("fragment_protocol_inconsistency", ip.get());
// || ip4->ip_tos != proto_hdr->ip_tos
// don't check TOS, there's at least one stack that actually
// uses different values, and it's hard to see an associated
// attack.
s->Weird("fragment_protocol_inconsistency", ip.get());
}
else
{
if ( ip->NextProto() != next_proto ||
ip->HdrLen() - 8 != proto_hdr_len )
if ( ip->NextProto() != next_proto || ip->HdrLen() - 8 != proto_hdr_len )
s->Weird("fragment_protocol_inconsistency", ip.get());
// 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)
{
if ( memcmp((const void*) b1, (const void*) b2, n) )
if ( memcmp((const void*)b1, (const void*)b2, n) )
Weird("fragment_inconsistency");
else
Weird("fragment_overlap");
@ -254,7 +252,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
// for a more recent one.
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;
@ -280,7 +278,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
reporter->InternalWarning("bad fragment reassembly");
DeleteTimer();
Expire(run_state::network_time);
delete [] pkt_start;
delete[] pkt_start;
return;
}
@ -293,7 +291,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
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);
reassembled_pkt = std::make_unique<IP_Hdr>(reassem4, true, true);
DeleteTimer();
@ -301,7 +299,7 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
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);
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);
@ -310,9 +308,8 @@ void FragReassembler::BlockInserted(DataBlockMap::const_iterator /* it */)
else
{
reporter->InternalWarning("bad IP version in fragment reassembly: %d",
version);
delete [] pkt_start;
reporter->InternalWarning("bad IP version in fragment reassembly: %d", version);
delete[] pkt_start;
}
}
@ -320,7 +317,7 @@ void FragReassembler::Expire(double t)
{
block_list.Clear();
expire_timer->ClearReassembler();
expire_timer = nullptr; // timer manager will delete it
expire_timer = nullptr; // timer manager will delete it
fragment_mgr->Remove(this);
}
@ -331,7 +328,7 @@ void FragReassembler::DeleteTimer()
{
expire_timer->ClearReassembler();
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));
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

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

View file

@ -4,16 +4,17 @@
#include <broker/error.hh>
#include "zeek/broker/Data.h"
#include "zeek/Func.h"
#include "zeek/Desc.h"
#include "zeek/Func.h"
#include "zeek/ID.h"
#include "zeek/Trigger.h"
#include "zeek/Val.h"
#include "zeek/ID.h"
#include "zeek/broker/Data.h"
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)
{
@ -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
// after this frame does.
captures = function ? function->GetCapturesFrame() : nullptr;
captures_offset_map =
function ? function->GetCapturesOffsetMap() : nullptr;
captures_offset_map = function ? function->GetCapturesOffsetMap() : nullptr;
current_offset = 0;
}
@ -178,10 +178,10 @@ void Frame::Describe(ODesc* d) const
d->Add(size);
for ( int i = 0; i < size; ++i )
{
d->Add(frame[i].val != nullptr);
d->SP();
}
{
d->Add(frame[i].val != nullptr);
d->SP();
}
}
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 )
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);
}
@ -334,7 +335,8 @@ broker::expected<broker::data> Frame::SerializeClosureFrame(const IDPList& selec
if ( them.length() )
{
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"));
@ -380,7 +382,7 @@ broker::expected<broker::data> Frame::SerializeClosureFrame(const IDPList& selec
if ( ! expected )
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;
}
@ -404,8 +406,7 @@ broker::expected<broker::data> Frame::SerializeCopyFrame()
return broker::ec::invalid_data;
TypeTag tag = val->GetType()->Tag();
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.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,
const std::optional<FuncType::CaptureList>& captures)
const std::optional<FuncType::CaptureList>& captures)
{
if ( data.size() == 0 )
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);
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);
if ( ! val )
@ -470,7 +471,6 @@ std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data,
return std::make_pair(true, std::move(rf));
}
// Code to support deprecated semantics:
IDPList outer_ids;
@ -572,7 +572,7 @@ std::pair<bool, FramePtr> Frame::Unserialize(const broker::vector& data,
return std::make_pair(false, nullptr);
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);
if ( ! val )
@ -590,10 +590,10 @@ void Frame::AddKnownOffsets(const IDPList& ids)
offset_map = std::make_unique<OffsetMap>();
std::transform(ids.begin(), ids.end(), std::inserter(*offset_map, offset_map->end()),
[] (const ID* id) -> std::pair<std::string, int>
{
return std::make_pair(std::string(id->Name()), id->Offset());
});
[](const ID* id) -> std::pair<std::string, int>
{
return std::make_pair(std::string(id->Name()), id->Offset());
});
}
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
{
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)
@ -661,20 +664,21 @@ broker::expected<broker::data> Frame::SerializeIDList(const IDPList& in)
return {std::move(rval)};
}
broker::expected<broker::data>
Frame::SerializeOffsetMap(const OffsetMap& in)
broker::expected<broker::data> Frame::SerializeOffsetMap(const OffsetMap& in)
{
broker::vector rval;
std::for_each(in.begin(), in.end(),
[&rval] (const std::pair<std::string, int>& e)
{ rval.emplace_back(e.first); rval.emplace_back(e.second);});
[&rval](const std::pair<std::string, int>& e)
{
rval.emplace_back(e.first);
rval.emplace_back(e.second);
});
return {std::move(rval)};
}
std::pair<bool, IDPList>
Frame::UnserializeIDList(const broker::vector& data)
std::pair<bool, IDPList> Frame::UnserializeIDList(const broker::vector& data)
{
IDPList rval;
if ( data.size() % 2 != 0 )
@ -725,14 +729,14 @@ Frame::UnserializeOffsetMap(const broker::vector& data)
if ( ! key )
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 )
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));
}
}
}

View file

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

View file

@ -1,60 +1,59 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Func.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "zeek/zeek-config.h"
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#include <sys/time.h>
#include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#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 <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/Debug.h"
#include "zeek/Desc.h"
#include "zeek/Event.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/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/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/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
// break what symbols are available when, which keeps the build from breaking.
// clang-format off
#include "zeek.bif.func_h"
#include "stats.bif.func_h"
#include "reporter.bif.func_h"
@ -72,17 +71,20 @@
#include "supervisor.bif.func_def"
#include "packet_analysis.bif.func_def"
#include "CPP-load.bif.func_def"
// 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;
bool did_builtin_init = false;
std::vector<void (*)()> bif_initializers;
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()
{
@ -145,8 +147,8 @@ Func::Func(Kind arg_kind) : kind(arg_kind)
Func::~Func() = default;
void Func::AddBody(detail::StmtPtr /* new_body */,
const std::vector<detail::IDPtr>& /* new_inits */,
size_t /* new_frame_size */, int /* priority */)
const std::vector<detail::IDPtr>& /* new_inits */, size_t /* new_frame_size */,
int /* priority */)
{
Internal("Func::AddBody called");
}
@ -238,8 +240,7 @@ void Func::CopyStateInto(Func* other) const
other->unique_id = unique_id;
}
void Func::CheckPluginResult(bool handled, const ValPtr& hook_result,
FunctionFlavor flavor) const
void Func::CheckPluginResult(bool handled, const ValPtr& hook_result, FunctionFlavor flavor) const
{
// Helper function factoring out this code from ScriptFunc:Call() for
// better readability.
@ -247,54 +248,57 @@ void Func::CheckPluginResult(bool handled, const ValPtr& hook_result,
if ( ! handled )
{
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
// into ::Call method).
return;
}
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:
switch ( flavor )
{
const auto& yt = GetType()->Yield();
if ( (! yt) || yt->Tag() == TYPE_VOID )
{
case FUNC_FLAVOR_EVENT:
if ( hook_result )
reporter->InternalError("plugin returned non-void result for void method %s",
this->Name());
}
reporter->InternalError("plugin returned non-void result for event %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;
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,
const std::vector<IDPtr>& aggr_inits,
ScriptFunc::ScriptFunc(const IDPtr& arg_id, StmtPtr arg_body, const std::vector<IDPtr>& aggr_inits,
size_t arg_frame_size, int priority)
: Func(SCRIPT_FUNC)
{
@ -312,8 +316,8 @@ ScriptFunc::ScriptFunc(const IDPtr& arg_id, StmtPtr arg_body,
}
}
ScriptFunc::ScriptFunc(std::string _name, FuncTypePtr ft,
std::vector<StmtPtr> bs, std::vector<int> priorities)
ScriptFunc::ScriptFunc(std::string _name, FuncTypePtr ft, std::vector<StmtPtr> bs,
std::vector<int> priorities)
{
name = std::move(_name);
frame_size = ft->ParamList()->GetTypes().size();
@ -351,7 +355,10 @@ ScriptFunc::~ScriptFunc()
bool ScriptFunc::IsPure() const
{
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
@ -364,9 +371,8 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
if ( sample_logger )
sample_logger->FunctionSeen(this);
auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION,
HookCallFunction(this, parent, args),
empty_hook_result);
auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(
HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result);
CheckPluginResult(handled, hook_result, Flavor());
@ -392,7 +398,7 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
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;
call_stack.emplace_back(CallInfo{call_expr, this, *args});
@ -401,8 +407,8 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
ODesc d;
DescribeDebug(&d, args);
g_trace_state.LogTrace("%s called: %s\n",
GetType()->FlavorString().c_str(), d.Description());
g_trace_state.LogTrace("%s called: %s\n", GetType()->FlavorString().c_str(),
d.Description());
}
StmtFlowType flow = FLOW_NEXT;
@ -479,11 +485,10 @@ ValPtr ScriptFunc::Invoke(zeek::Args* args, Frame* parent) const
// Warn if the function returns something, but we returned from
// the function without an explicit return, or without a value.
else if ( GetType()->Yield() && GetType()->Yield()->Tag() != TYPE_VOID &&
(flow != FLOW_RETURN /* we fell off the end */ ||
! result /* explicit return with no result */) &&
! f->HasDelayed() )
reporter->Warning("non-void function returning without a value: %s",
Name());
(flow != FLOW_RETURN /* we fell off the end */ ||
! result /* explicit return with no result */) &&
! f->HasDelayed() )
reporter->Warning("non-void function returning without a value: %s", Name());
if ( result && g_trace_state.DoTrace() )
{
@ -548,8 +553,7 @@ void ScriptFunc::SetCaptures(Frame* f)
}
}
void ScriptFunc::AddBody(StmtPtr new_body,
const std::vector<IDPtr>& new_inits,
void ScriptFunc::AddBody(StmtPtr new_body, const std::vector<IDPtr>& new_inits,
size_t new_frame_size, int priority)
{
if ( new_frame_size > frame_size )
@ -630,8 +634,7 @@ bool ScriptFunc::HasCopySemantics() const
void ScriptFunc::SetClosureFrame(Frame* f)
{
if ( closure )
reporter->InternalError("Tried to override closure for ScriptFunc %s.",
Name());
reporter->InternalError("Tried to override closure for ScriptFunc %s.", Name());
// Have to use weak references initially because otherwise Ref'ing the
// original frame creates a circular reference: the function holds a
@ -670,14 +673,13 @@ bool ScriptFunc::DeserializeCaptures(const broker::vector& data)
{
auto result = Frame::Unserialize(data, GetType()->GetCaptures());
ASSERT(result.first);
ASSERT(result.first);
SetCaptures(result.second.release());
return true;
}
FuncPtr ScriptFunc::DoClone()
{
// ScriptFunc could hold a closure. In this case a clone of it must
@ -722,9 +724,7 @@ void ScriptFunc::Describe(ODesc* d) const
}
}
StmtPtr ScriptFunc::AddInits(
StmtPtr body,
const std::vector<IDPtr>& inits)
StmtPtr ScriptFunc::AddInits(StmtPtr body, const std::vector<IDPtr>& inits)
{
if ( inits.empty() )
return body;
@ -736,9 +736,8 @@ StmtPtr ScriptFunc::AddInits(
return stmt_series;
}
BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
bool arg_is_pure)
: Func(BUILTIN_FUNC)
BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, bool arg_is_pure)
: Func(BUILTIN_FUNC)
{
func = arg_func;
name = make_full_var_name(GLOBAL_MODULE_NAME, arg_name);
@ -755,9 +754,7 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
id->SetConst();
}
BuiltinFunc::~BuiltinFunc()
{
}
BuiltinFunc::~BuiltinFunc() { }
bool BuiltinFunc::IsPure() const
{
@ -774,9 +771,8 @@ ValPtr BuiltinFunc::Invoke(Args* args, Frame* parent) const
if ( sample_logger )
sample_logger->FunctionSeen(this);
auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(HOOK_CALL_FUNCTION,
HookCallFunction(this, parent, args),
empty_hook_result);
auto [handled, hook_result] = PLUGIN_HOOK_WITH_RESULT(
HOOK_CALL_FUNCTION, HookCallFunction(this, parent, args), empty_hook_result);
CheckPluginResult(handled, hook_result, FUNC_FLAVOR_FUNCTION);
@ -815,7 +811,7 @@ void BuiltinFunc::Describe(ODesc* d) const
bool check_built_in_call(BuiltinFunc* f, CallExpr* call)
{
if ( f->TheFunc() != BifFunc::fmt_bif)
if ( f->TheFunc() != BifFunc::fmt_bif )
return true;
const ExprPList& args = call->Args()->Exprs();
@ -858,7 +854,8 @@ bool check_built_in_call(BuiltinFunc* f, CallExpr* call)
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;
}
}
@ -920,7 +917,7 @@ function_ingredients::function_ingredients(ScopePtr scope, StmtPtr body)
static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind)
{
auto emit = [=](const CallExpr* ce)
{
{
if ( ce )
{
if ( unwind )
@ -929,8 +926,7 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind)
{
ODesc d;
arg->Describe(&d);
reporter->ExprRuntimeError(ce, "%s (%s), during call:", msg,
d.Description());
reporter->ExprRuntimeError(ce, "%s (%s), during call:", msg, d.Description());
}
else
reporter->ExprRuntimeError(ce, "%s", msg);
@ -955,8 +951,7 @@ static void emit_builtin_error_common(const char* msg, Obj* arg, bool unwind)
reporter->Error("%s", msg);
}
}
};
};
if ( call_stack.empty() )
{
@ -976,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
{ return name.size() > 2 && name[0] == '_' && name[1] == '_'; };
{
return name.size() > 2 && name[0] == '_' && name[1] == '_';
};
std::string last_func = last_call.func->Name();
auto pos = last_func.find_first_of("::");
@ -1051,21 +1048,20 @@ void init_primary_bifs()
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 "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();
did_builtin_init = true;
}
} // namespace detail
} // namespace detail
void emit_builtin_error(const char* msg)
{
@ -1082,4 +1078,4 @@ void emit_builtin_error(const char* msg, Obj* arg)
zeek::detail::emit_builtin_error_common(msg, arg, false);
}
} // namespace zeek
} // namespace zeek

View file

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

View file

@ -1,45 +1,56 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/Hash.h"
#include <highwayhash/sip_hash.h>
#include <highwayhash/highwayhash_target.h>
#include <highwayhash/instruction_sets.h>
#include <highwayhash/sip_hash.h>
#include "zeek/digest.h"
#include "zeek/Reporter.h"
#include "zeek/ZeekString.h"
#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"
namespace zeek::detail {
namespace zeek::detail
{
alignas(32) uint64_t KeyedHash::shared_highwayhash_key[4];
alignas(32) uint64_t KeyedHash::cluster_highwayhash_key[4];
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.
static_assert(std::is_same<hash64_t, highwayhash::HHResult64>::value, "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");
// 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.
static_assert(std::is_same<hash64_t, highwayhash::HHResult64>::value,
"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)
{
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_highwayhash_key), highwayhash::HHKey>::value, "Highwayhash HHKey is not uint64_t[4]");
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_highwayhash_key), highwayhash::HHKey>::value,
"Highwayhash HHKey is not uint64_t[4]");
if ( seeds_initialized )
return;
// 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.
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
// yes, we use the same buffer twice to initialize two different keys. This should not really be 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.
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
// yes, we use the same buffer twice to initialize two different keys. This should not really be
// 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);
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);
seeds_initialized = true;
@ -47,39 +58,45 @@ void KeyedHash::InitializeSeeds(const std::array<uint32_t, SEED_INIT_SIZE>& seed
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)
{
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)
{
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)
{
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 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;
}
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)
{
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()
@ -92,7 +109,7 @@ void init_hash_function()
HashKey::HashKey(bro_int_t i)
{
key_u.i = i;
key = (void*) &key_u;
key = (void*)&key_u;
size = sizeof(i);
hash = HashBytes(key, size);
}
@ -100,7 +117,7 @@ HashKey::HashKey(bro_int_t i)
HashKey::HashKey(bro_uint_t u)
{
key_u.i = bro_int_t(u);
key = (void*) &key_u;
key = (void*)&key_u;
size = sizeof(u);
hash = HashBytes(key, size);
}
@ -108,7 +125,7 @@ HashKey::HashKey(bro_uint_t u)
HashKey::HashKey(uint32_t u)
{
key_u.u32 = u;
key = (void*) &key_u;
key = (void*)&key_u;
size = sizeof(u);
hash = HashBytes(key, size);
}
@ -116,19 +133,19 @@ HashKey::HashKey(uint32_t u)
HashKey::HashKey(const uint32_t u[], int n)
{
size = n * sizeof(u[0]);
key = (void*) u;
key = (void*)u;
hash = HashBytes(key, size);
}
HashKey::HashKey(double d)
{
union {
union {
double d;
int i[2];
} u;
} u;
key_u.d = u.d = d;
key = (void*) &key_u;
key = (void*)&key_u;
size = sizeof(d);
hash = HashBytes(key, size);
}
@ -136,22 +153,22 @@ HashKey::HashKey(double d)
HashKey::HashKey(const void* p)
{
key_u.p = p;
key = (void*) &key_u;
key = (void*)&key_u;
size = sizeof(p);
hash = HashBytes(key, size);
}
HashKey::HashKey(const char* s)
{
size = strlen(s); // note - skip final \0
key = (void*) s;
size = strlen(s); // note - skip final \0
key = (void*)s;
hash = HashBytes(key, size);
}
HashKey::HashKey(const String* s)
{
size = s->Len();
key = (void*) s->Bytes();
key = (void*)s->Bytes();
hash = HashBytes(key, size);
}
@ -162,7 +179,7 @@ HashKey::HashKey(int copy_key, void* arg_key, int arg_size)
if ( copy_key )
{
key = (void*) new char[size];
key = (void*)new char[size];
memcpy(key, arg_key, size);
}
else
@ -179,8 +196,7 @@ HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash)
is_our_dynamic = true;
}
HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash,
bool /* dont_copy */)
HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash, bool /* dont_copy */)
{
size = arg_size;
hash = arg_hash;
@ -208,7 +224,7 @@ void* HashKey::TakeKey()
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);
return k_copy;
}
@ -218,4 +234,4 @@ hash_t HashKey::HashBytes(const void* bytes, int 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.
* 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,
* e.g. for lookups in hash-tables; the Hashes are also used for connection ID generation.
* The HashKey class is the actual class that is used to generate Hash keys that are used
* 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
* a seed file is used. There are a few functions that create hashes that are static over runs
* and use an installation-wide seed value; these are specifically called out.
* This means that the hashes created by most functions in this file will be different each run,
* unless a seed file is used. There are a few functions that create hashes that are static over
* runs and use an installation-wide seed value; these are specifically called out.
*/
#pragma once
@ -26,26 +27,33 @@
// to allow bro_md5_hmac access to the hmac seed
#include "zeek/ZeekArgs.h"
namespace zeek { class String; }
namespace zeek::detail {
namespace zeek
{
class String;
}
namespace zeek::detail
{
class Frame;
class BifReturnVal;
}
}
namespace zeek::BifFunc {
extern zeek::detail::BifReturnVal md5_hmac_bif(zeek::detail::Frame* frame, const zeek::Args*);
}
namespace zeek::BifFunc
{
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 hash64_t;
typedef uint64_t hash128_t[2];
typedef uint64_t hash256_t[4];
class KeyedHash {
class KeyedHash
{
public:
/**
* Generate a 64 bit digest hash.
@ -193,19 +201,23 @@ public:
private:
// actually HHKey. This key changes each start (unless a seed is specified)
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];
// 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];
// This key changes each start (unless a seed is specified)
inline static uint8_t shared_hmac_md5_key[16];
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*);
};
};
typedef enum {
typedef enum
{
HASH_KEY_INT,
HASH_KEY_DOUBLE,
HASH_KEY_STRING
@ -213,7 +225,8 @@ typedef enum {
constexpr int NUM_HASH_KEYS = HASH_KEY_STRING + 1;
class HashKey {
class HashKey
{
public:
explicit HashKey(bro_int_t i);
explicit HashKey(bro_uint_t u);
@ -226,7 +239,7 @@ public:
~HashKey()
{
if ( is_our_dynamic )
delete [] (char *) key;
delete[](char*) key;
}
// Create a HashKey given all of its components. "key" is assumed
@ -257,30 +270,35 @@ public:
// we give them a copy of it.
void* TakeKey();
const void* Key() const { return key; }
int Size() const { return size; }
hash_t Hash() const { return hash; }
const void* Key() const { return key; }
int Size() const { return size; }
hash_t Hash() const { return hash; }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]]
unsigned int MemoryAllocation() const { return padded_sizeof(*this) + util::pad_size(size); }
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See "
"GHI-572.")]] unsigned int
MemoryAllocation() const
{
return padded_sizeof(*this) + util::pad_size(size);
}
static hash_t HashBytes(const void* bytes, int size);
protected:
void* CopyKey(const void* key, int size) const;
union {
union {
bro_int_t i;
uint32_t u32;
double d;
const void* p;
} key_u;
} key_u;
void* key;
hash_t hash;
int size;
bool is_our_dynamic = false;
};
};
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.
#include "zeek/zeek-config.h"
#include "zeek/ID.h"
#include "zeek/Attr.h"
#include "zeek/Desc.h"
#include "zeek/Expr.h"
#include "zeek/Dict.h"
#include "zeek/EventRegistry.h"
#include "zeek/Expr.h"
#include "zeek/File.h"
#include "zeek/Func.h"
#include "zeek/Scope.h"
#include "zeek/Type.h"
#include "zeek/File.h"
#include "zeek/Traverse.h"
#include "zeek/Type.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/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::endpoint;
@ -46,8 +47,7 @@ const TypePtr& id::find_type(std::string_view name)
auto id = zeek::detail::global_scope()->Find(name);
if ( ! id )
reporter->InternalError("Failed to find type named: %s",
std::string(name).data());
reporter->InternalError("Failed to find type named: %s", std::string(name).data());
return id->GetType();
}
@ -57,8 +57,7 @@ const ValPtr& id::find_val(std::string_view name)
auto id = zeek::detail::global_scope()->Find(name);
if ( ! id )
reporter->InternalError("Failed to find variable named: %s",
std::string(name).data());
reporter->InternalError("Failed to find variable named: %s", std::string(name).data());
return id->GetVal();
}
@ -68,12 +67,11 @@ const ValPtr& id::find_const(std::string_view name)
auto id = zeek::detail::global_scope()->Find(name);
if ( ! id )
reporter->InternalError("Failed to find variable named: %s",
std::string(name).data());
reporter->InternalError("Failed to find variable named: %s", std::string(name).data());
if ( ! id->IsConst() )
reporter->InternalError("Variable is not 'const', but expected to be: %s",
std::string(name).data());
std::string(name).data());
return id->GetVal();
}
@ -87,7 +85,7 @@ FuncPtr id::find_func(std::string_view name)
if ( ! IsFunc(v->GetType()->Tag()) )
reporter->InternalError("Expected variable '%s' to be a function",
std::string(name).data());
std::string(name).data());
return v.get()->As<FuncVal*>()->AsFuncPtr();
}
@ -107,7 +105,8 @@ void id::detail::init_types()
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)
{
@ -129,7 +128,7 @@ ID::ID(const char* arg_name, IDScope arg_scope, bool arg_is_export)
ID::~ID()
{
delete [] name;
delete[] name;
delete opt_info;
}
@ -157,8 +156,7 @@ void ID::SetVal(ValPtr v)
UpdateValID();
#endif
if ( type && val &&
type->Tag() == TYPE_FUNC &&
if ( type && val && type->Tag() == TYPE_FUNC &&
type->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT )
{
EventHandler* handler = event_registry->Lookup(name);
@ -186,9 +184,8 @@ void ID::SetVal(ValPtr v, InitClass c)
return;
}
if ( type->Tag() != TYPE_TABLE &&
(type->Tag() != TYPE_PATTERN || c == INIT_REMOVE) &&
(type->Tag() != TYPE_VECTOR || c == INIT_REMOVE) )
if ( type->Tag() != TYPE_TABLE && (type->Tag() != TYPE_PATTERN || c == INIT_REMOVE) &&
(type->Tag() != TYPE_VECTOR || c == INIT_REMOVE) )
{
if ( c == INIT_EXTRA )
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 )
{
Error(zeek::util::fmt("%s initializer applied to ID without value",
c == INIT_EXTRA ? "+=" : "-="), this);
c == INIT_EXTRA ? "+=" : "-="),
this);
return;
}
@ -373,8 +371,7 @@ TraversalCode ID::Traverse(TraversalCallback* cb) const
}
// FIXME: Perhaps we should be checking at other than global scope.
else if ( val && IsFunc(val->GetType()->Tag()) &&
cb->current_scope == detail::global_scope() )
else if ( val && IsFunc(val->GetType()->Tag()) && cb->current_scope == detail::global_scope() )
{
tc = val->AsFunc()->Traverse(cb);
HANDLE_TC_STMT_PRE(tc);
@ -448,26 +445,27 @@ void ID::DescribeReSTShort(ODesc* d) const
{
TypeTag t = type->Tag();
switch ( t ) {
case TYPE_TABLE:
d->Add(type->IsSet() ? "set" : type_name(t));
break;
switch ( t )
{
case TYPE_TABLE:
d->Add(type->IsSet() ? "set" : type_name(t));
break;
case TYPE_FUNC:
d->Add(type->AsFuncType()->FlavorString().c_str());
break;
case TYPE_FUNC:
d->Add(type->AsFuncType()->FlavorString().c_str());
break;
case TYPE_ENUM:
if ( is_type )
case TYPE_ENUM:
if ( is_type )
d->Add(type_name(t));
else
d->Add(zeekygen_mgr->GetEnumTypeName(Name()).c_str());
break;
default:
d->Add(type_name(t));
else
d->Add(zeekygen_mgr->GetEnumTypeName(Name()).c_str());
break;
default:
d->Add(type_name(t));
break;
}
break;
}
}
d->Add("`");
@ -529,8 +527,7 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const
{
auto ft = type->AsFuncType();
if ( ft->Flavor() == FUNC_FLAVOR_EVENT ||
ft->Flavor() == FUNC_FLAVOR_HOOK )
if ( ft->Flavor() == FUNC_FLAVOR_EVENT || ft->Flavor() == FUNC_FLAVOR_HOOK )
{
const auto& protos = ft->Prototypes();
@ -568,42 +565,40 @@ void ID::DescribeReST(ODesc* d, bool roles_only) const
d->NL();
}
if ( val && type &&
type->Tag() != TYPE_FUNC &&
type->InternalType() != TYPE_INTERNAL_VOID &&
if ( val && type && type->Tag() != TYPE_FUNC && type->InternalType() != TYPE_INTERNAL_VOID &&
// Values within Version module are likely to include a
// constantly-changing version number and be a frequent
// source of error/desynchronization, so don't include them.
ModuleName() != "Version" )
ModuleName() != "Version" )
{
d->Add(":Default:");
auto ii = zeekygen_mgr->GetIdentifierInfo(Name());
auto redefs = ii->GetRedefs();
const auto& iv = ! redefs.empty() && ii->InitialVal() ? ii->InitialVal()
: val;
const auto& iv = ! redefs.empty() && ii->InitialVal() ? ii->InitialVal() : val;
if ( type->InternalType() == TYPE_INTERNAL_OTHER )
{
switch ( type->Tag() ) {
case TYPE_TABLE:
if ( iv->AsTable()->Length() == 0 )
{
d->Add(" ``{}``");
d->NL();
break;
}
// Fall-through.
switch ( type->Tag() )
{
case TYPE_TABLE:
if ( iv->AsTable()->Length() == 0 )
{
d->Add(" ``{}``");
d->NL();
break;
}
// Fall-through.
default:
d->NL();
d->PushIndent();
d->Add("::");
d->NL();
d->PushIndent();
iv->DescribeReST(d);
d->PopIndent();
d->PopIndent();
}
default:
d->NL();
d->PushIndent();
d->Add("::");
d->NL();
d->PushIndent();
iv->DescribeReST(d);
d->PopIndent();
d->PopIndent();
}
}
else
@ -675,12 +670,11 @@ std::vector<Func*> ID::GetOptionHandlers() const
return v;
}
void IDOptInfo::AddInitExpr(ExprPtr 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 <vector>
#include "zeek/Obj.h"
#include "zeek/Attr.h"
#include "zeek/Notifier.h"
#include "zeek/Obj.h"
#include "zeek/TraverseTypes.h"
namespace zeek {
namespace zeek
{
class Func;
class Val;
@ -29,23 +30,36 @@ using EnumTypePtr = IntrusivePtr<EnumType>;
using ValPtr = IntrusivePtr<Val>;
using FuncPtr = IntrusivePtr<Func>;
}
}
namespace zeek::detail {
namespace zeek::detail
{
class Attributes;
class Expr;
using ExprPtr = IntrusivePtr<Expr>;
enum InitClass { INIT_NONE, INIT_FULL, INIT_EXTRA, INIT_REMOVE, };
enum IDScope { SCOPE_FUNCTION, SCOPE_MODULE, SCOPE_GLOBAL };
enum InitClass
{
INIT_NONE,
INIT_FULL,
INIT_EXTRA,
INIT_REMOVE,
};
enum IDScope
{
SCOPE_FUNCTION,
SCOPE_MODULE,
SCOPE_GLOBAL
};
class ID;
using IDPtr = IntrusivePtr<ID>;
class IDOptInfo;
class ID final : public Obj, public notifier::detail::Modifiable {
class ID final : public Obj, public notifier::detail::Modifiable
{
public:
static inline const IDPtr nil;
@ -53,53 +67,48 @@ public:
~ID() override;
const char* Name() const { return name; }
const char* Name() const { return name; }
int Scope() const { return scope; }
bool IsGlobal() const { return scope != SCOPE_FUNCTION; }
int Scope() const { return scope; }
bool IsGlobal() const { return scope != SCOPE_FUNCTION; }
bool IsExport() const { return is_export; }
void SetExport() { is_export = true; }
bool IsExport() const { return is_export; }
void SetExport() { is_export = true; }
std::string ModuleName() const;
void SetType(TypePtr t);
const TypePtr& GetType() const
{ return type; }
const TypePtr& GetType() const { return type; }
template <class T>
IntrusivePtr<T> GetType() const
{ return cast_intrusive<T>(type); }
template <class T> IntrusivePtr<T> GetType() const { return cast_intrusive<T>(type); }
bool IsType() const
{ return is_type; }
bool IsType() const { return is_type; }
void MakeType() { is_type = true; }
void MakeType() { is_type = true; }
void SetVal(ValPtr v);
void SetVal(ValPtr v, InitClass c);
void SetVal(ExprPtr ev, InitClass c);
bool HasVal() const { return val != nullptr; }
bool HasVal() const { return val != nullptr; }
const ValPtr& GetVal() const
{ return val; }
const ValPtr& GetVal() const { return val; }
void ClearVal();
void SetConst() { is_const = true; }
bool IsConst() const { return is_const; }
void SetConst() { is_const = true; }
bool IsConst() const { return is_const; }
void SetOption();
bool IsOption() const { return is_option; }
bool IsOption() const { return is_option; }
void SetEnumConst() { is_enum_const = true; }
bool IsEnumConst() const { return is_enum_const; }
void SetEnumConst() { is_enum_const = true; }
bool IsEnumConst() const { return is_enum_const; }
void SetOffset(int arg_offset) { offset = arg_offset; }
int Offset() const { return offset; }
void SetOffset(int arg_offset) { offset = arg_offset; }
int Offset() const { return offset; }
bool IsRedefinable() const;
@ -108,8 +117,7 @@ public:
void RemoveAttr(AttrTag a);
void UpdateValAttrs();
const AttributesPtr& GetAttrs() const
{ return attrs; }
const AttributesPtr& GetAttrs() const { return attrs; }
const AttrPtr& GetAttr(AttrTag t) const;
@ -128,20 +136,17 @@ public:
void DescribeReST(ODesc* d, bool roles_only = false) const;
void DescribeReSTShort(ODesc* d) const;
bool DoInferReturnType() const
{ return infer_return_type; }
void SetInferReturnType(bool infer)
{ infer_return_type = infer; }
bool DoInferReturnType() const { return infer_return_type; }
void SetInferReturnType(bool infer) { infer_return_type = infer; }
virtual TraversalCode Traverse(TraversalCallback* cb) const;
bool HasOptionHandlers() const
{ return !option_handlers.empty(); }
bool HasOptionHandlers() const { return ! option_handlers.empty(); }
void AddOptionHandler(FuncPtr callback, int priority);
std::vector<Func*> GetOptionHandlers() const;
IDOptInfo* GetOptInfo() const { return opt_info; }
IDOptInfo* GetOptInfo() const { return opt_info; }
protected:
void EvalFunc(ExprPtr ef, ExprPtr ev);
@ -168,12 +173,12 @@ protected:
// via the associated pointer, to allow it to be modified in
// contexts where the ID is itself "const".
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;
@ -197,9 +202,10 @@ const TypePtr& find_type(std::string_view name);
* @param name The identifier name to lookup
* @return The type of the identifier.
*/
template<class T>
IntrusivePtr<T> find_type(std::string_view name)
{ return cast_intrusive<T>(find_type(name)); }
template <class T> IntrusivePtr<T> find_type(std::string_view name)
{
return cast_intrusive<T>(find_type(name));
}
/**
* 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
* @return The current value of the identifier.
*/
template<class T>
IntrusivePtr<T> find_val(std::string_view name)
{ return cast_intrusive<T>(find_val(name)); }
template <class T> IntrusivePtr<T> find_val(std::string_view name)
{
return cast_intrusive<T>(find_val(name));
}
/**
* 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
* @return The current value of the identifier.
*/
template<class T>
IntrusivePtr<T> find_const(std::string_view name)
{ return cast_intrusive<T>(find_const(name)); }
template <class T> IntrusivePtr<T> find_const(std::string_view name)
{
return cast_intrusive<T>(find_const(name));
}
/**
* 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 index_vec;
namespace detail {
namespace detail
{
void init_types();
} // namespace detail
} // namespace zeek::id
} // namespace detail
} // namespace zeek::id

824
src/IP.cc
View file

@ -2,18 +2,19 @@
#include "zeek/IP.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
#include <netinet/in.h>
#include <sys/types.h>
#include "zeek/IPAddr.h"
#include "zeek/Reporter.h"
#include "zeek/Type.h"
#include "zeek/Val.h"
#include "zeek/Var.h"
#include "zeek/ZeekString.h"
#include "zeek/Reporter.h"
namespace zeek {
namespace zeek
{
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 )
{
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);
rv->Assign(0, opt->ip6o_type);
@ -54,251 +55,265 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
{
RecordValPtr rv;
switch ( type ) {
case IPPROTO_IPV6:
switch ( type )
{
static auto ip6_hdr_type = id::find_type<RecordType>("ip6_hdr");
rv = make_intrusive<RecordVal>(ip6_hdr_type);
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
rv->Assign(0, (ntohl(ip6->ip6_flow) & 0x0ff00000)>>20);
rv->Assign(1, ntohl(ip6->ip6_flow) & 0x000fffff);
rv->Assign(2, ntohs(ip6->ip6_plen));
rv->Assign(3, ip6->ip6_nxt);
rv->Assign(4, ip6->ip6_hlim);
rv->Assign(5, make_intrusive<AddrVal>(IPAddr(ip6->ip6_src)));
rv->Assign(6, make_intrusive<AddrVal>(IPAddr(ip6->ip6_dst)));
if ( ! chain )
chain = make_intrusive<VectorVal>(
id::find_type<VectorType>("ip6_ext_hdr_chain"));
rv->Assign(7, std::move(chain));
}
break;
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));
}
case IPPROTO_IPV6:
{
static auto ip6_hdr_type = id::find_type<RecordType>("ip6_hdr");
rv = make_intrusive<RecordVal>(ip6_hdr_type);
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
rv->Assign(0, (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20);
rv->Assign(1, ntohl(ip6->ip6_flow) & 0x000fffff);
rv->Assign(2, ntohs(ip6->ip6_plen));
rv->Assign(3, ip6->ip6_nxt);
rv->Assign(4, ip6->ip6_hlim);
rv->Assign(5, make_intrusive<AddrVal>(IPAddr(ip6->ip6_src)));
rv->Assign(6, make_intrusive<AddrVal>(IPAddr(ip6->ip6_dst)));
if ( ! chain )
chain =
make_intrusive<VectorVal>(id::find_type<VectorType>("ip6_ext_hdr_chain"));
rv->Assign(7, std::move(chain));
}
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));
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 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));
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 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));
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 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));
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 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 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]));
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));
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 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));
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;
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;
}
default:
reporter->Weird("unknown_mobility_type", util::fmt("%d", mob->ip6mob_type));
break;
}
rv->Assign(5, std::move(msg));
}
break;
default:
break;
}
return rv;
}
RecordValPtr IPv6_Hdr::ToVal() const
{ return ToVal(nullptr); }
{
return ToVal(nullptr);
}
IPAddr IP_Hdr::IPHeaderSrcAddr() const
{
@ -366,104 +381,106 @@ RecordValPtr IP_Hdr::ToPktHdrVal(RecordValPtr pkt_hdr, int sindex) const
const u_char* data = Payload();
int proto = NextProto();
switch ( proto ) {
case IPPROTO_TCP:
switch ( proto )
{
const struct tcphdr* tp = (const struct tcphdr*) data;
auto tcp_hdr = make_intrusive<RecordVal>(tcp_hdr_type);
case IPPROTO_TCP:
{
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 data_len = PayloadLen() - tcp_hdr_len;
int tcp_hdr_len = tp->th_off * 4;
int data_len = PayloadLen() - tcp_hdr_len;
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(2, ntohl(tp->th_seq));
tcp_hdr->Assign(3, ntohl(tp->th_ack));
tcp_hdr->Assign(4, tcp_hdr_len);
tcp_hdr->Assign(5, data_len);
tcp_hdr->Assign(6, tp->th_x2);
tcp_hdr->Assign(7, tp->th_flags);
tcp_hdr->Assign(8, ntohs(tp->th_win));
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(2, ntohl(tp->th_seq));
tcp_hdr->Assign(3, ntohl(tp->th_ack));
tcp_hdr->Assign(4, tcp_hdr_len);
tcp_hdr->Assign(5, data_len);
tcp_hdr->Assign(6, tp->th_x2);
tcp_hdr->Assign(7, tp->th_flags);
tcp_hdr->Assign(8, ntohs(tp->th_win));
pkt_hdr->Assign(sindex + 2, std::move(tcp_hdr));
break;
pkt_hdr->Assign(sindex + 2, std::move(tcp_hdr));
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;
}
static inline bool isIPv6ExtHeader(uint8_t type)
{
switch (type) {
case IPPROTO_HOPOPTS:
case IPPROTO_ROUTING:
case IPPROTO_DSTOPTS:
case IPPROTO_FRAGMENT:
case IPPROTO_AH:
case IPPROTO_ESP:
case IPPROTO_MOBILITY:
return true;
default:
return false;
}
switch ( type )
{
case IPPROTO_HOPOPTS:
case IPPROTO_ROUTING:
case IPPROTO_DSTOPTS:
case IPPROTO_FRAGMENT:
case IPPROTO_AH:
case IPPROTO_ESP:
case IPPROTO_MOBILITY:
return true;
default:
return false;
}
}
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 finalDst;
}
void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len,
bool set_next, uint16_t next)
void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len, bool set_next, uint16_t next)
{
length = 0;
uint8_t current_type, next_type;
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) )
{
@ -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.
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.
if ( current_type == IPPROTO_DSTOPTS )
ProcessDstOpts((const struct ip6_dest*) hdrs, cur_len);
ProcessDstOpts((const struct ip6_dest*)hdrs, cur_len);
hdrs += cur_len;
length += cur_len;
total_len -= cur_len;
} while ( current_type != IPPROTO_FRAGMENT &&
current_type != IPPROTO_ESP &&
current_type != IPPROTO_MOBILITY &&
isIPv6ExtHeader(next_type) );
} while ( current_type != IPPROTO_FRAGMENT && current_type != IPPROTO_ESP &&
current_type != IPPROTO_MOBILITY && isIPv6ExtHeader(next_type) );
}
bool IPv6_Hdr_Chain::IsFragment() const
@ -525,7 +540,7 @@ bool IPv6_Hdr_Chain::IsFragment() const
return false;
}
return chain[chain.size()-1]->Type() == IPPROTO_FRAGMENT;
return chain[chain.size() - 1]->Type() == IPPROTO_FRAGMENT;
}
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.
const in6_addr* addr = (const in6_addr*)(((const u_char*)r) + len - 16);
switch ( r->ip6r_type ) {
case 0: // Defined by RFC 2460, deprecated by RFC 5095
switch ( r->ip6r_type )
{
if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 )
{
if ( r->ip6r_len % 2 == 0 )
finalDst = new IPAddr(*addr);
else
reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len");
}
case 0: // Defined by RFC 2460, deprecated by RFC 5095
{
if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 )
{
if ( r->ip6r_len % 2 == 0 )
finalDst = new IPAddr(*addr);
else
reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len");
}
// Always raise a weird since this type is deprecated.
reporter->Weird(SrcAddr(), DstAddr(), "routing0_hdr");
// Always raise a weird since this type is deprecated.
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)
@ -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
assert(len >= 2);
const u_char* data = (const u_char*) d;
const u_char* data = (const u_char*)d;
len -= 2 * sizeof(uint8_t);
data += 2* sizeof(uint8_t);
data += 2 * sizeof(uint8_t);
while ( len > 0 )
{
const struct ip6_opt* opt = (const struct ip6_opt*) data;
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:
const struct ip6_opt* opt = (const struct ip6_opt*)data;
switch ( opt->ip6o_type )
{
// Double-check that the len can hold the whole option structure.
// Otherwise we get a buffer-overflow when we check the option_len.
// Also check that it holds everything for the option itself.
if ( len < sizeof(struct ip6_opt) ||
len < sizeof(struct ip6_opt) + opt->ip6o_len )
{
reporter->Weird(SrcAddr(), DstAddr(), "bad_ipv6_dest_opt_len");
len = 0;
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;
}
if ( opt->ip6o_type == 201 ) // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
{
if ( opt->ip6o_len == sizeof(struct in6_addr) )
default:
{
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");
}
// Double-check that the len can hold the whole option structure.
// Otherwise we get a buffer-overflow when we check the option_len.
// Also check that it holds everything for the option itself.
if ( len < sizeof(struct ip6_opt) ||
len < sizeof(struct ip6_opt) + opt->ip6o_len )
{
reporter->Weird(SrcAddr(), DstAddr(), "bad_ipv6_dest_opt_len");
len = 0;
break;
}
data += sizeof(struct ip6_opt) + opt->ip6o_len;
len -= sizeof(struct ip6_opt) + opt->ip6o_len;
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 )
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
{
@ -677,32 +696,33 @@ VectorValPtr IPv6_Hdr_Chain::ToVal() const
uint8_t type = chain[i]->Type();
ext_hdr->Assign(0, type);
switch (type) {
case IPPROTO_HOPOPTS:
ext_hdr->Assign(1, std::move(v));
break;
case IPPROTO_DSTOPTS:
ext_hdr->Assign(2, std::move(v));
break;
case IPPROTO_ROUTING:
ext_hdr->Assign(3, std::move(v));
break;
case IPPROTO_FRAGMENT:
ext_hdr->Assign(4, std::move(v));
break;
case IPPROTO_AH:
ext_hdr->Assign(5, std::move(v));
break;
case IPPROTO_ESP:
ext_hdr->Assign(6, std::move(v));
break;
case IPPROTO_MOBILITY:
ext_hdr->Assign(7, std::move(v));
break;
default:
reporter->InternalWarning("IPv6_Hdr_Chain bad header %d", type);
continue;
}
switch ( type )
{
case IPPROTO_HOPOPTS:
ext_hdr->Assign(1, std::move(v));
break;
case IPPROTO_DSTOPTS:
ext_hdr->Assign(2, std::move(v));
break;
case IPPROTO_ROUTING:
ext_hdr->Assign(3, std::move(v));
break;
case IPPROTO_FRAGMENT:
ext_hdr->Assign(4, std::move(v));
break;
case IPPROTO_AH:
ext_hdr->Assign(5, std::move(v));
break;
case IPPROTO_ESP:
ext_hdr->Assign(6, std::move(v));
break;
case IPPROTO_MOBILITY:
ext_hdr->Assign(7, std::move(v));
break;
default:
reporter->InternalWarning("IPv6_Hdr_Chain bad header %d", type);
continue;
}
rval->Assign(rval->Size(), std::move(ext_hdr));
}
@ -717,7 +737,7 @@ IP_Hdr* IP_Hdr::Copy() const
if ( ip4 )
{
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());
@ -756,4 +776,4 @@ IPv6_Hdr_Chain* IPv6_Hdr_Chain::Copy(const ip6_hdr* new_hdr) const
return rval;
}
} // namespace zeek
} // namespace zeek

223
src/IP.h
View file

@ -2,12 +2,12 @@
#pragma once
#include "zeek/zeek-config.h"
#include <sys/types.h> // for u_char
#include <netinet/in.h>
#include <netinet/ip.h>
#include "zeek/zeek-config.h"
#ifdef HAVE_NETINET_IP6_H
#include <netinet/ip6.h>
#endif
@ -16,7 +16,8 @@
#include "zeek/IntrusivePtr.h"
namespace zeek {
namespace zeek
{
class IPAddr;
class RecordVal;
@ -24,54 +25,60 @@ class VectorVal;
using RecordValPtr = IntrusivePtr<RecordVal>;
using VectorValPtr = IntrusivePtr<VectorVal>;
namespace detail { class FragReassembler; }
namespace detail
{
class FragReassembler;
}
#ifndef IPPROTO_MOBILITY
#define IPPROTO_MOBILITY 135
#endif
struct ip6_mobility {
struct ip6_mobility
{
uint8_t ip6mob_payload;
uint8_t ip6mob_len;
uint8_t ip6mob_type;
uint8_t ip6mob_rsv;
uint16_t ip6mob_chksum;
};
};
/**
* Base class for IPv6 header/extensions.
*/
class IPv6_Hdr {
class IPv6_Hdr
{
public:
/**
* 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.
*/
void ChangeNext(uint8_t next_type)
{
switch ( type ) {
case IPPROTO_IPV6:
((ip6_hdr*)data)->ip6_nxt = next_type;
break;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_FRAGMENT:
case IPPROTO_AH:
case IPPROTO_MOBILITY:
((ip6_ext*)data)->ip6e_nxt = next_type;
break;
case IPPROTO_ESP:
default:
break;
}
switch ( type )
{
case IPPROTO_IPV6:
((ip6_hdr*)data)->ip6_nxt = next_type;
break;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_FRAGMENT:
case IPPROTO_AH:
case IPPROTO_MOBILITY:
((ip6_ext*)data)->ip6e_nxt = next_type;
break;
case IPPROTO_ESP:
default:
break;
}
}
~IPv6_Hdr() {}
~IPv6_Hdr() { }
/**
* Returns the assigned IPv6 extension header type number of the header
@ -79,20 +86,21 @@ public:
*/
uint8_t NextHdr() const
{
switch ( type ) {
case IPPROTO_IPV6:
return ((ip6_hdr*)data)->ip6_nxt;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_FRAGMENT:
case IPPROTO_AH:
case IPPROTO_MOBILITY:
return ((ip6_ext*)data)->ip6e_nxt;
case IPPROTO_ESP:
default:
return IPPROTO_NONE;
}
switch ( type )
{
case IPPROTO_IPV6:
return ((ip6_hdr*)data)->ip6_nxt;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_FRAGMENT:
case IPPROTO_AH:
case IPPROTO_MOBILITY:
return ((ip6_ext*)data)->ip6e_nxt;
case IPPROTO_ESP:
default:
return IPPROTO_NONE;
}
}
/**
@ -100,23 +108,24 @@ public:
*/
uint16_t Length() const
{
switch ( type ) {
case IPPROTO_IPV6:
return 40;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_MOBILITY:
return 8 + 8 * ((ip6_ext*)data)->ip6e_len;
case IPPROTO_FRAGMENT:
return 8;
case IPPROTO_AH:
return 8 + 4 * ((ip6_ext*)data)->ip6e_len;
case IPPROTO_ESP:
return 8; //encrypted payload begins after 8 bytes
default:
return 0;
}
switch ( type )
{
case IPPROTO_IPV6:
return 40;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_MOBILITY:
return 8 + 8 * ((ip6_ext*)data)->ip6e_len;
case IPPROTO_FRAGMENT:
return 8;
case IPPROTO_AH:
return 8 + 4 * ((ip6_ext*)data)->ip6e_len;
case IPPROTO_ESP:
return 8; // encrypted payload begins after 8 bytes
default:
return 0;
}
}
/**
@ -138,15 +147,15 @@ public:
protected:
uint8_t type;
const u_char* data;
};
};
class IPv6_Hdr_Chain {
class IPv6_Hdr_Chain
{
public:
/**
* Initializes the header chain from an IPv6 header structure.
*/
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, int len)
{ Init(ip6, len, false); }
IPv6_Hdr_Chain(const struct ip6_hdr* ip6, int len) { Init(ip6, len, false); }
~IPv6_Hdr_Chain();
@ -180,29 +189,28 @@ public:
* Returns pointer to fragment header structure if the chain contains one.
*/
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
* relative to the start of the Fragmentable Part of the original packet.
*/
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.
*/
uint32_t ID() const
{ return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; }
uint32_t ID() const { return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; }
/**
* If the header chain is a fragment, returns the M (more fragments) flag.
*/
int MF() const
{ return IsFragment() ?
(ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
int MF() const { return IsFragment() ? (ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; }
/**
* 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.
*/
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
* length, possibly setting the first next protocol pointer field that
* points to a fragment header.
*/
void Init(const struct ip6_hdr* ip6, int total_len, bool set_next,
uint16_t next = 0);
void Init(const struct ip6_hdr* ip6, int total_len, bool set_next, uint16_t next = 0);
/**
* Process a routing header and allocate/remember the final destination
@ -275,13 +284,14 @@ protected:
* non-zero segments left.
*/
IPAddr* finalDst = nullptr;
};
};
/**
* A class that wraps either an IPv4 or IPv6 packet and abstracts methods
* for inquiring about common features between the two.
*/
class IP_Hdr {
class IP_Hdr
{
public:
/**
* 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 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)
{
}
@ -307,10 +317,10 @@ public:
* @param c an already-constructed header chain to take ownership of.
* @param reassembled whether this header is for a reassembled packet.
*/
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len,
const IPv6_Hdr_Chain* c = nullptr, bool reassembled=false)
: ip6(arg_ip6), ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len)),
del(arg_del), reassembled(reassembled)
IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len, const IPv6_Hdr_Chain* c = nullptr,
bool reassembled = false)
: ip6(arg_ip6), ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len)), del(arg_del),
reassembled(reassembled)
{
}
@ -330,20 +340,20 @@ public:
if ( del )
{
delete [] (struct ip*) ip4;
delete [] (struct ip6_hdr*) ip6;
delete[](struct ip*) ip4;
delete[](struct ip6_hdr*) ip6;
}
}
/**
* 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.
*/
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.
@ -377,9 +387,9 @@ public:
const u_char* Payload() const
{
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 )
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;
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).
*/
uint16_t HdrLen() const
{ return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); }
uint16_t HdrLen() const { return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); }
/**
* 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();
if ( i > 0 )
return (*ip6_hdrs)[i-1]->Type();
return (*ip6_hdrs)[i - 1]->Type();
return IPPROTO_NONE;
}
@ -452,7 +461,7 @@ public:
size_t i = ip6_hdrs->Size();
if ( i > 0 )
return (*ip6_hdrs)[i-1]->NextHdr();
return (*ip6_hdrs)[i - 1]->NextHdr();
return IPPROTO_NONE;
}
@ -460,54 +469,50 @@ public:
/**
* Returns the IPv4 Time to Live or IPv6 Hop Limit field.
*/
unsigned char TTL() const
{ return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
unsigned char TTL() const { return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; }
/**
* Returns whether the IP header indicates this packet is a fragment.
*/
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
* packet in bytes.
*/
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.
*/
uint32_t ID() const
{ return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); }
uint32_t ID() const { return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); }
/**
* Returns whether a fragment packet's "More Fragments" field is set.
*/
int MF() const
{ return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); }
int MF() const { return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); }
/**
* Returns whether a fragment packet's "Don't Fragment" field is set.
* Note that IPv6 has no such field.
*/
int DF() const
{ return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; }
int DF() const { 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.
*/
uint32_t FlowLabel() const
{ return ip4 ? 0 : (ntohl(ip6->ip6_flow) & 0x000fffff); }
uint32_t FlowLabel() const { return ip4 ? 0 : (ntohl(ip6->ip6_flow) & 0x000fffff); }
/**
* Returns number of IP headers in packet (includes IPv6 extension headers).
*/
size_t NumHeaders() const
{ return ip4 ? 1 : ip6_hdrs->Size(); }
size_t NumHeaders() const { return ip4 ? 1 : ip6_hdrs->Size(); }
/**
* Returns an ip_hdr or ip6_hdr_chain RecordVal.
@ -534,6 +539,6 @@ private:
const IPv6_Hdr_Chain* ip6_hdrs = nullptr;
bool del = 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.
#include "zeek/IPAddr.h"
#include <cstdlib>
#include <string>
#include <vector>
#include "zeek/IPAddr.h"
#include "zeek/Reporter.h"
#include "zeek/ZeekString.h"
#include "zeek/Conn.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/bro_inet_ntop.h"
namespace zeek {
namespace zeek
{
const IPAddr IPAddr::v4_unspecified = IPAddr(in4_addr{});
const IPAddr IPAddr::v6_unspecified = IPAddr();
namespace detail {
namespace detail
{
ConnKey::ConnKey(const IPAddr& src, const IPAddr& dst, uint16_t src_port,
uint16_t dst_port, TransportProto t, bool one_way)
ConnKey::ConnKey(const IPAddr& src, const IPAddr& dst, uint16_t src_port, uint16_t dst_port,
TransportProto t, bool one_way)
: 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>
// followed by the other.
if ( one_way ||
addr_port_canon_lt(src, src_port, dst, dst_port)
)
if ( one_way || addr_port_canon_lt(src, src_port, dst, dst_port) )
{
ip1 = src.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(id.src_addr, id.dst_addr, id.src_port, id.dst_port,
id.proto, id.is_one_way)
: ConnKey(id.src_addr, id.dst_addr, id.src_port, id.dst_port, id.proto, id.is_one_way)
{
}
@ -64,7 +64,7 @@ ConnKey& ConnKey::operator=(const ConnKey& rhs)
return *this;
}
} // namespace detail
} // namespace detail
IPAddr::IPAddr(const String& s)
{
@ -81,7 +81,7 @@ static inline uint32_t bit_mask32(int bottom_bits)
if ( bottom_bits >= 32 )
return 0xffffffff;
return (((uint32_t) 1) << bottom_bits) - 1;
return (((uint32_t)1) << bottom_bits) - 1;
}
void IPAddr::Mask(int top_bits_to_keep)
@ -92,12 +92,11 @@ void IPAddr::Mask(int top_bits_to_keep)
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);
if ( res.quot < 4 )
mask_bits[res.quot] =
htonl(mask_bits[res.quot] & ~bit_mask32(32 - res.rem));
mask_bits[res.quot] = htonl(mask_bits[res.quot] & ~bit_mask32(32 - res.rem));
for ( unsigned int i = res.quot + 1; i < 4; ++i )
mask_bits[i] = 0;
@ -116,7 +115,7 @@ void IPAddr::ReverseMask(int top_bits_to_chop)
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);
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.
int a[4];
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 )
return false;
@ -200,15 +199,14 @@ std::string IPAddr::AsHexString() const
if ( GetFamily() == IPv4 )
{
uint32_t* p = (uint32_t*) &in6.s6_addr[12];
snprintf(buf, sizeof(buf), "%08x", (uint32_t) ntohl(*p));
uint32_t* p = (uint32_t*)&in6.s6_addr[12];
snprintf(buf, sizeof(buf), "%08x", (uint32_t)ntohl(*p));
}
else
{
uint32_t* p = (uint32_t*) in6.s6_addr;
snprintf(buf, sizeof(buf), "%08x%08x%08x%08x",
(uint32_t) ntohl(p[0]), (uint32_t) ntohl(p[1]),
(uint32_t) ntohl(p[2]), (uint32_t) ntohl(p[3]));
uint32_t* p = (uint32_t*)in6.s6_addr;
snprintf(buf, sizeof(buf), "%08x%08x%08x%08x", (uint32_t)ntohl(p[0]), (uint32_t)ntohl(p[1]),
(uint32_t)ntohl(p[2]), (uint32_t)ntohl(p[3]));
}
return buf;
@ -219,7 +217,7 @@ std::string IPAddr::PtrName() const
if ( GetFamily() == IPv4 )
{
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 a3 = (a >> 24) & 0xff;
uint32_t a2 = (a >> 16) & 0xff;
@ -232,15 +230,15 @@ std::string IPAddr::PtrName() const
{
static const char hex_digit[] = "0123456789abcdef";
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 )
{
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, 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)
: prefix(in4), length(96 + length)
IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length) : prefix(in4), length(96 + length)
{
if ( length > 32 )
{
@ -260,8 +257,7 @@ IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length)
prefix.Mask(this->length);
}
IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length)
: prefix(in6), length(length)
IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length) : prefix(in6), length(length)
{
if ( length > 128 )
{
@ -289,8 +285,7 @@ bool IPAddr::CheckPrefixLength(uint8_t length, bool len_is_v6_relative) const
return true;
}
IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length, bool len_is_v6_relative)
: prefix(addr)
IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length, bool len_is_v6_relative) : prefix(addr)
{
if ( prefix.CheckPrefixLength(length, len_is_v6_relative) )
{
@ -318,15 +313,16 @@ std::string IPPrefix::AsString() const
else
modp_uitoa10(length, l);
return prefix.AsString() +"/" + l;
return prefix.AsString() + "/" + l;
}
std::unique_ptr<detail::HashKey> IPPrefix::MakeHashKey() const
{
struct {
struct
{
in6_addr ip;
uint32_t len;
} key;
} key;
key.ip = prefix.in6;
key.len = Length();
@ -359,4 +355,4 @@ bool IPPrefix::ConvertString(const char* text, IPPrefix* result)
return true;
}
} // namespace zeek
} // namespace zeek

View file

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

View file

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

View file

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

View file

@ -2,23 +2,28 @@
#pragma once
#include <functional>
#include <type_traits>
#include <utility>
#include <functional>
namespace zeek {
namespace zeek
{
/**
* A tag class for the #IntrusivePtr constructor which means: adopt
* the reference from the caller.
*/
struct AdoptRef {};
struct AdoptRef
{
};
/**
* A tag class for the #IntrusivePtr constructor which means: create a
* new reference to the object.
*/
struct NewRef {};
struct NewRef
{
};
/**
* 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
* increase robustness of the code (in particular w.r.t. exceptions).
*/
template <class T>
class IntrusivePtr {
template <class T> class IntrusivePtr
{
public:
// -- member types
@ -74,10 +79,7 @@ public:
*
* @param raw_ptr Pointer to the shared object.
*/
constexpr IntrusivePtr(AdoptRef, pointer raw_ptr) noexcept
: ptr_(raw_ptr)
{
}
constexpr IntrusivePtr(AdoptRef, pointer raw_ptr) noexcept : ptr_(raw_ptr) { }
/**
* 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.
*/
IntrusivePtr(NewRef, pointer raw_ptr) noexcept
: ptr_(raw_ptr)
IntrusivePtr(NewRef, pointer raw_ptr) noexcept : ptr_(raw_ptr)
{
if ( ptr_ )
Ref(ptr_);
@ -99,10 +100,7 @@ public:
// nop
}
IntrusivePtr(const IntrusivePtr& other) noexcept
: IntrusivePtr(NewRef{}, other.get())
{
}
IntrusivePtr(const IntrusivePtr& other) noexcept : IntrusivePtr(NewRef{}, other.get()) { }
template <class U, class = std::enable_if_t<std::is_convertible_v<U*, T*>>>
IntrusivePtr(IntrusivePtr<U> other) noexcept : ptr_(other.release())
@ -116,10 +114,7 @@ public:
Unref(ptr_);
}
void swap(IntrusivePtr& other) noexcept
{
std::swap(ptr_, other.ptr_);
}
void swap(IntrusivePtr& other) noexcept { std::swap(ptr_, other.ptr_); }
friend void swap(IntrusivePtr& a, IntrusivePtr& b) noexcept
{
@ -132,10 +127,7 @@ public:
* intrusive pointer to @c nullptr.
* @returns the raw pointer without modifying the reference count.
*/
pointer release() noexcept
{
return std::exchange(ptr_, nullptr);
}
pointer release() noexcept { return std::exchange(ptr_, nullptr); }
IntrusivePtr& operator=(const IntrusivePtr& other) noexcept
{
@ -160,34 +152,19 @@ public:
return *this;
}
pointer get() const noexcept
{
return ptr_;
}
pointer get() const noexcept { return ptr_; }
pointer operator->() const noexcept
{
return ptr_;
}
pointer operator->() const noexcept { return ptr_; }
reference operator*() const noexcept
{
return *ptr_;
}
reference operator*() const noexcept { return *ptr_; }
bool operator!() const noexcept
{
return !ptr_;
}
bool operator!() const noexcept { return ! ptr_; }
explicit operator bool() const noexcept
{
return ptr_ != nullptr;
}
explicit operator bool() const noexcept { return ptr_ != nullptr; }
private:
pointer ptr_ = nullptr;
};
};
/**
* 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.
* @relates IntrusivePtr
*/
template <class T, class... Ts>
IntrusivePtr<T> make_intrusive(Ts&&... args)
template <class T, class... Ts> IntrusivePtr<T> make_intrusive(Ts&&... args)
{
// Assumes that objects start with a reference count of 1!
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.
* @return The pointer, as cast to type @c T.
*/
template <class T, class U>
IntrusivePtr<T> cast_intrusive(IntrusivePtr<U> p) noexcept
template <class T, class U> IntrusivePtr<T> cast_intrusive(IntrusivePtr<U> p) noexcept
{
return {AdoptRef{}, static_cast<T*>(p.release())};
}
@ -221,68 +196,68 @@ IntrusivePtr<T> cast_intrusive(IntrusivePtr<U> p) noexcept
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator==(const zeek::IntrusivePtr<T>& x, std::nullptr_t) {
return !x;
}
template <class T> bool operator==(const zeek::IntrusivePtr<T>& x, std::nullptr_t)
{
return ! x;
}
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator==(std::nullptr_t, const zeek::IntrusivePtr<T>& x) {
return !x;
}
template <class T> bool operator==(std::nullptr_t, const zeek::IntrusivePtr<T>& x)
{
return ! x;
}
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator!=(const zeek::IntrusivePtr<T>& x, std::nullptr_t) {
return static_cast<bool>(x);
}
template <class T> bool operator!=(const zeek::IntrusivePtr<T>& x, std::nullptr_t)
{
return static_cast<bool>(x);
}
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator!=(std::nullptr_t, const zeek::IntrusivePtr<T>& x) {
return static_cast<bool>(x);
}
template <class T> bool operator!=(std::nullptr_t, const zeek::IntrusivePtr<T>& x)
{
return static_cast<bool>(x);
}
// -- comparison to raw pointer ------------------------------------------------
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator==(const zeek::IntrusivePtr<T>& x, const T* y) {
return x.get() == y;
}
template <class T> bool operator==(const zeek::IntrusivePtr<T>& x, const T* y)
{
return x.get() == y;
}
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator==(const T* x, const zeek::IntrusivePtr<T>& y) {
return x == y.get();
}
template <class T> bool operator==(const T* x, const zeek::IntrusivePtr<T>& y)
{
return x == y.get();
}
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator!=(const zeek::IntrusivePtr<T>& x, const T* y) {
return x.get() != y;
}
template <class T> bool operator!=(const zeek::IntrusivePtr<T>& x, const T* y)
{
return x.get() != y;
}
/**
* @relates IntrusivePtr
*/
template <class T>
bool operator!=(const T* x, const zeek::IntrusivePtr<T>& y) {
return x != y.get();
}
template <class T> bool operator!=(const T* x, const zeek::IntrusivePtr<T>& y)
{
return x != y.get();
}
// -- comparison to intrusive pointer ------------------------------------------
@ -294,7 +269,7 @@ bool operator!=(const T* x, const zeek::IntrusivePtr<T>& y) {
*/
template <class T, class U>
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();
}
@ -304,19 +279,23 @@ auto operator==(const zeek::IntrusivePtr<T>& x, const zeek::IntrusivePtr<U>& y)
*/
template <class T, class U>
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();
}
} // namespace zeek
} // namespace zeek
// -- hashing ------------------------------------------------
namespace std {
template <class T> struct hash<zeek::IntrusivePtr<T>> {
namespace std
{
template <class T> struct hash<zeek::IntrusivePtr<T>>
{
// 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
{ return std::hash<T*>{}(v.get()); }
};
}
{
return std::hash<T*>{}(v.get());
}
};
}

View file

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

View file

@ -20,24 +20,29 @@
// sizeof(data) <= sizeof(void*).
#include <stdarg.h>
#include <cassert>
#include <initializer_list>
#include <iterator>
#include <utility>
#include <cassert>
#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>
class List {
template <typename T, ListOrder Order = ListOrder::ORDERED> class List
{
public:
constexpr static int DEFAULT_LIST_SIZE = 10;
constexpr static int LIST_GROWTH_FACTOR = 2;
~List() { free(entries); }
~List() { free(entries); }
explicit List(int size = 0)
{
num_entries = 0;
@ -51,7 +56,7 @@ public:
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)
@ -60,7 +65,7 @@ public:
num_entries = b.num_entries;
if ( max_entries )
entries = (T*) util::safe_malloc(max_entries * sizeof(T));
entries = (T*)util::safe_malloc(max_entries * sizeof(T));
else
entries = nullptr;
@ -81,11 +86,11 @@ public:
List(const T* arr, int 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));
}
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)
{
@ -98,7 +103,7 @@ public:
num_entries = b.num_entries;
if ( max_entries )
entries = (T *) util::safe_malloc(max_entries * sizeof(T));
entries = (T*)util::safe_malloc(max_entries * sizeof(T));
else
entries = nullptr;
@ -124,12 +129,9 @@ public:
}
// Return nth ent of list (do not remove).
T& operator[](int i) const
{
return entries[i];
}
T& operator[](int i) const { return entries[i]; }
void clear() // remove all entries
void clear() // remove all entries
{
free(entries);
entries = nullptr;
@ -139,16 +141,16 @@ public:
bool empty() const noexcept { return num_entries == 0; }
size_t size() const noexcept { return num_entries; }
int length() const { return num_entries; }
int max() const { return max_entries; }
int resize(int new_size = 0) // 0 => size to fit current number of entries
int length() const { return num_entries; }
int max() const { return max_entries; }
int resize(int new_size = 0) // 0 => size to fit current number of 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 )
{
entries = (T*) util::safe_realloc((void*) entries, sizeof(T) * new_size);
entries = (T*)util::safe_realloc((void*)entries, sizeof(T) * new_size);
if ( entries )
max_entries = new_size;
else
@ -158,9 +160,12 @@ public:
return max_entries;
}
[[deprecated("Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]]
int MemoryAllocation() const
{ return padded_sizeof(*this) + util::pad_size(max_entries * sizeof(T)); }
[[deprecated(
"Remove in v5.1. MemoryAllocation() is deprecated and will be removed. See GHI-572.")]] int
MemoryAllocation() const
{
return padded_sizeof(*this) + util::pad_size(max_entries * sizeof(T));
}
void push_front(const T& a)
{
@ -168,7 +173,7 @@ public:
resize(max_entries ? max_entries * LIST_GROWTH_FACTOR : DEFAULT_LIST_SIZE);
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;
entries[0] = a;
@ -182,20 +187,20 @@ public:
entries[num_entries++] = a;
}
void pop_front() { remove_nth(0); }
void pop_back() { remove_nth(num_entries-1); }
void pop_front() { remove_nth(0); }
void pop_back() { remove_nth(num_entries - 1); }
T& front() { return entries[0]; }
T& back() { return entries[num_entries-1]; }
T& front() { return entries[0]; }
T& back() { return entries[num_entries - 1]; }
// The append method is maintained for historical/compatibility reasons.
// (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);
}
bool remove(const T& a) // delete entry from list
bool remove(const T& a) // delete entry from list
{
int pos = member_pos(a);
if ( pos != -1 )
@ -207,9 +212,9 @@ public:
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];
@ -221,7 +226,7 @@ public:
--num_entries;
for ( ; n < num_entries; ++n )
entries[n] = entries[n+1];
entries[n] = entries[n + 1];
}
else
{
@ -249,7 +254,7 @@ public:
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 )
return T{};
@ -298,7 +303,6 @@ public:
const_reverse_iterator crend() const { return rend(); }
protected:
// This could essentially be an std::vector if we wanted. Some
// reasons to maybe not refactor to use std::vector ?
//
@ -328,17 +332,15 @@ protected:
int num_entries;
};
// Specialization of the List class to store pointers of a type.
template<typename T, ListOrder Order = ListOrder::ORDERED>
using PList = List<T*, Order>;
template <typename T, ListOrder Order = ListOrder::ORDERED> using PList = List<T*, Order>;
// Popular type of list: list of strings.
using name_list = PList<char>;
} // namespace zeek
} // namespace zeek
// Macro to visit each list element in turn.
#define loop_over_list(list, iterator) \
int iterator; \
#define loop_over_list(list, iterator) \
int 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.
#include "zeek/zeek-config.h"
#include "zeek/NFA.h"
#include <algorithm>
@ -8,8 +7,10 @@
#include "zeek/Desc.h"
#include "zeek/EquivClass.h"
#include "zeek/IntSet.h"
#include "zeek/zeek-config.h"
namespace zeek::detail {
namespace zeek::detail
{
static int nfa_state_id = 0;
@ -159,9 +160,8 @@ unsigned int NFA_State::TotalMemoryAllocation() const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
return padded_sizeof(*this)
+ xtions.MemoryAllocation() - padded_sizeof(xtions)
+ (epsclosure ? epsclosure->MemoryAllocation() : 0);
return padded_sizeof(*this) + xtions.MemoryAllocation() - padded_sizeof(xtions) +
(epsclosure ? epsclosure->MemoryAllocation() : 0);
#pragma GCC diagnostic pop
}
@ -219,7 +219,7 @@ void NFA_Machine::LinkCopies(int n)
for ( i = 0; i < n; ++i )
AppendMachine(copies[i]);
delete [] copies;
delete[] copies;
}
NFA_Machine* NFA_Machine::DuplicateMachine()
@ -243,7 +243,7 @@ void NFA_Machine::AppendMachine(NFA_Machine* m)
final_state->AddXtion(m->FirstState());
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);
}
@ -332,7 +332,6 @@ NFA_Machine* make_alternate(NFA_Machine* m1, NFA_Machine* m2)
return new NFA_Machine(first, last);
}
NFA_state_list* epsilon_closure(NFA_state_list* states)
{
// 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;
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

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

View file

@ -1,12 +1,12 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "zeek/zeek-config.h"
#include "zeek/NetVar.h"
#include "zeek/Var.h"
#include "zeek/EventHandler.h"
#include "zeek/Val.h"
#include "zeek/ID.h"
#include "zeek/Val.h"
#include "zeek/Var.h"
#include "zeek/zeek-config.h"
zeek::RecordType* conn_id;
zeek::RecordType* endpoint;
@ -105,7 +105,8 @@ zeek::StringVal* cmd_line_bpf_filter;
zeek::StringVal* global_hash_seed;
namespace zeek::detail {
namespace zeek::detail
{
int watchdog_interval;
@ -192,7 +193,8 @@ int record_all_packets;
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,
// 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()
{
#include "const.bif.netvar_init"
#include "packet_analysis.bif.netvar_init"
#include "reporter.bif.netvar_init"
#include "supervisor.bif.netvar_init"
#include "packet_analysis.bif.netvar_init"
}
static void init_bif_types()
@ -216,14 +218,15 @@ static void init_bif_types()
}
#include "const.bif.netvar_def"
#include "types.bif.netvar_def"
#include "event.bif.netvar_def"
#include "packet_analysis.bif.netvar_def"
#include "reporter.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.
namespace zeek::detail {
namespace zeek::detail
{
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_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_excessive_data_without_further_acks = id::find_val("tcp_excessive_data_without_further_acks")->AsCount();
tcp_max_above_hole_without_any_acks =
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();
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_interarrival_thresh = id::find_val("tcp_storm_interarrival_thresh")->AsInterval();
tcp_content_deliver_all_orig =
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_orig = 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());
udp_content_deliver_all_orig =
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_orig = 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_delivery_ports_use_resp =
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();
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -2,11 +2,12 @@
#pragma once
#include "zeek/Val.h"
#include "zeek/EventRegistry.h"
#include "zeek/Stats.h"
#include "zeek/Val.h"
namespace zeek::detail {
namespace zeek::detail
{
extern int watchdog_interval;
@ -101,11 +102,11 @@ extern void init_event_handlers();
extern void init_net_var();
extern void init_builtin_types();
} // namespace zeek::detail
} // namespace zeek::detail
#include "const.bif.netvar_h"
#include "types.bif.netvar_h"
#include "event.bif.netvar_h"
#include "packet_analysis.bif.netvar_h"
#include "reporter.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.
#include "zeek/Notifier.h"
#include <set>
#include "zeek/Notifier.h"
#include "zeek/DebugLogger.h"
zeek::notifier::detail::Registry zeek::notifier::detail::registry;
namespace zeek::notifier::detail {
namespace zeek::notifier::detail
{
Receiver::Receiver()
{
@ -86,4 +88,4 @@ Modifiable::~Modifiable()
registry.Unregister(this);
}
} // namespace zeek::notifier::detail
} // namespace zeek::notifier::detail

View file

@ -7,15 +7,17 @@
#pragma once
#include <unordered_map>
#include <cstdint>
#include <unordered_map>
namespace zeek::notifier::detail {
namespace zeek::notifier::detail
{
class Modifiable;
/** Interface class for receivers of notifications. */
class Receiver {
class Receiver
{
public:
Receiver();
virtual ~Receiver();
@ -32,10 +34,11 @@ public:
* no further modifications can possibly occur.
*/
virtual void Terminate() { }
};
};
/** Singleton class tracking all notification requests globally. */
class Registry {
class Registry
{
public:
~Registry();
@ -86,7 +89,7 @@ private:
typedef std::unordered_multimap<Modifiable*, Receiver*> ModifiableMap;
ModifiableMap registrations;
};
};
/**
* 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
* modified.
*/
class Modifiable {
class Modifiable
{
public:
/**
* Calling this method signals to all registered receivers that the
@ -116,6 +120,6 @@ protected:
// Number of currently registered receivers.
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.
#include "zeek/zeek-config.h"
#include "zeek/Obj.h"
#include <stdlib.h>
#include "zeek/Desc.h"
#include "zeek/Func.h"
#include "zeek/File.h"
#include "zeek/Func.h"
#include "zeek/plugin/Manager.h"
#include "zeek/zeek-config.h"
namespace zeek {
namespace detail {
namespace zeek
{
namespace detail
{
Location start_location("<start 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
{
if ( filename == l.filename ||
(filename && l.filename && util::streq(filename, l.filename)) )
if ( filename == l.filename || (filename && l.filename && util::streq(filename, l.filename)) )
return first_line == l.first_line && last_line == l.last_line;
else
return false;
}
} // namespace detail
} // namespace detail
int Obj::suppress_errors = 0;
@ -63,7 +64,8 @@ Obj::~Obj()
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;
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();
}
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 )
return;
@ -146,8 +149,7 @@ bool Obj::SetLocationInfo(const detail::Location* start, const detail::Location*
delete location;
location = new detail::Location(start->filename,
start->first_line, end->last_line,
location = new detail::Location(start->filename, start->first_line, end->last_line,
start->first_column, end->last_column);
return true;
@ -162,8 +164,8 @@ void Obj::UpdateLocationEndInfo(const detail::Location& end)
location->last_column = end.last_column;
}
void Obj::DoMsg(ODesc* d, const char s1[], const Obj* obj2,
bool pinpoint_only, const detail::Location* expr_location) const
void Obj::DoMsg(ODesc* d, const char s1[], const Obj* obj2, bool pinpoint_only,
const detail::Location* expr_location) const
{
d->SetShort();
@ -172,7 +174,7 @@ void Obj::DoMsg(ODesc* d, const char s1[], const Obj* obj2,
const detail::Location* loc2 = nullptr;
if ( obj2 && obj2->GetLocationInfo() != &detail::no_location &&
*obj2->GetLocationInfo() != *GetLocationInfo() )
*obj2->GetLocationInfo() != *GetLocationInfo() )
loc2 = obj2->GetLocationInfo();
else if ( expr_location )
loc2 = expr_location;
@ -209,7 +211,7 @@ void bad_ref(int type)
void obj_delete_func(void* v)
{
Unref((Obj*) v);
Unref((Obj*)v);
}
} // namespace zeek
} // namespace zeek

View file

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

View file

@ -2,25 +2,25 @@
#include "zeek/OpaqueVal.h"
#include <memory>
#include <broker/data.hh>
#include <broker/error.hh>
#include <memory>
#include "zeek/CompHash.h"
#include "zeek/Desc.h"
#include "zeek/NetVar.h"
#include "zeek/Reporter.h"
#include "zeek/Scope.h"
#include "zeek/Desc.h"
#include "zeek/Var.h"
#include "zeek/probabilistic/BloomFilter.h"
#include "zeek/probabilistic/CardinalityCounter.h"
namespace zeek {
namespace zeek
{
// Helper to retrieve a broker value out of a broker::vector at a specified
// 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)
{
if ( i >= v.size() )
@ -40,12 +40,9 @@ OpaqueMgr* OpaqueMgr::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
{
@ -53,7 +50,7 @@ const std::string& OpaqueMgr::TypeID(const OpaqueVal* v) const
if ( x == _types.end() )
reporter->InternalError("OpaqueMgr::TypeID: opaque type %s not registered",
v->OpaqueName());
v->OpaqueName());
return x->first;
}
@ -211,9 +208,7 @@ HashVal::HashVal(OpaqueTypePtr t) : OpaqueVal(std::move(t))
valid = false;
}
MD5Val::MD5Val() : HashVal(md5_type)
{
}
MD5Val::MD5Val() : HashVal(md5_type) { }
MD5Val::~MD5Val()
{
@ -232,7 +227,7 @@ void HashVal::digest_one(EVP_MD_CTX* h, const Val* v)
{
ODesc d(DESC_BINARY);
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() )
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 = {
true,
static_cast<uint64_t>(md->A),
static_cast<uint64_t>(md->B),
static_cast<uint64_t>(md->C),
static_cast<uint64_t>(md->D),
static_cast<uint64_t>(md->Nl),
static_cast<uint64_t>(md->Nh),
static_cast<uint64_t>(md->num)
};
broker::vector d = {true,
static_cast<uint64_t>(md->A),
static_cast<uint64_t>(md->B),
static_cast<uint64_t>(md->C),
static_cast<uint64_t>(md->D),
static_cast<uint64_t>(md->Nl),
static_cast<uint64_t>(md->Nh),
static_cast<uint64_t>(md->num)};
for ( int i = 0; i < MD5_LBLOCK; ++i )
d.emplace_back(static_cast<uint64_t>(md->data[i]));
@ -325,7 +318,7 @@ bool MD5Val::DoUnserialize(const broker::data& data)
}
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) )
return false;
@ -351,9 +344,7 @@ bool MD5Val::DoUnserialize(const broker::data& data)
return true;
}
SHA1Val::SHA1Val() : HashVal(sha1_type)
{
}
SHA1Val::SHA1Val() : HashVal(sha1_type) { }
SHA1Val::~SHA1Val()
{
@ -409,19 +400,17 @@ broker::expected<broker::data> SHA1Val::DoSerialize() const
if ( ! IsValid() )
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 = {
true,
static_cast<uint64_t>(md->h0),
static_cast<uint64_t>(md->h1),
static_cast<uint64_t>(md->h2),
static_cast<uint64_t>(md->h3),
static_cast<uint64_t>(md->h4),
static_cast<uint64_t>(md->Nl),
static_cast<uint64_t>(md->Nh),
static_cast<uint64_t>(md->num)
};
broker::vector d = {true,
static_cast<uint64_t>(md->h0),
static_cast<uint64_t>(md->h1),
static_cast<uint64_t>(md->h2),
static_cast<uint64_t>(md->h3),
static_cast<uint64_t>(md->h4),
static_cast<uint64_t>(md->Nl),
static_cast<uint64_t>(md->Nh),
static_cast<uint64_t>(md->num)};
for ( int i = 0; i < SHA_LBLOCK; ++i )
d.emplace_back(static_cast<uint64_t>(md->data[i]));
@ -446,7 +435,7 @@ bool SHA1Val::DoUnserialize(const broker::data& data)
}
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) )
return false;
@ -474,9 +463,7 @@ bool SHA1Val::DoUnserialize(const broker::data& data)
return true;
}
SHA256Val::SHA256Val() : HashVal(sha256_type)
{
}
SHA256Val::SHA256Val() : HashVal(sha256_type) { }
SHA256Val::~SHA256Val()
{
@ -501,7 +488,7 @@ ValPtr SHA256Val::DoClone(CloneState* state)
bool SHA256Val::DoInit()
{
assert( ! IsValid() );
assert(! IsValid());
ctx = detail::hash_init(detail::Hash_SHA256);
return true;
}
@ -532,15 +519,10 @@ broker::expected<broker::data> SHA256Val::DoSerialize() const
if ( ! IsValid() )
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 = {
true,
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)
};
broker::vector d = {true, 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 )
d.emplace_back(static_cast<uint64_t>(md->h[i]));
@ -568,7 +550,7 @@ bool SHA256Val::DoUnserialize(const broker::data& data)
}
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) )
return false;
@ -594,9 +576,7 @@ bool SHA256Val::DoUnserialize(const broker::data& data)
return true;
}
EntropyVal::EntropyVal() : OpaqueVal(entropy_type)
{
}
EntropyVal::EntropyVal() : OpaqueVal(entropy_type) { }
bool EntropyVal::Feed(const void* data, size_t size)
{
@ -604,8 +584,8 @@ bool EntropyVal::Feed(const void* data, size_t size)
return true;
}
bool EntropyVal::Get(double *r_ent, double *r_chisq, double *r_mean,
double *r_montepicalc, double *r_scc)
bool EntropyVal::Get(double* r_ent, double* r_chisq, double* r_mean, double* r_montepicalc,
double* r_scc)
{
state.end(r_ent, r_chisq, r_mean, r_montepicalc, r_scc);
return true;
@ -615,30 +595,22 @@ IMPLEMENT_OPAQUE_VALUE(EntropyVal)
broker::expected<broker::data> EntropyVal::DoSerialize() const
{
broker::vector d =
{
static_cast<uint64_t>(state.totalc),
static_cast<uint64_t>(state.mp),
static_cast<uint64_t>(state.sccfirst),
static_cast<uint64_t>(state.inmont),
static_cast<uint64_t>(state.mcount),
static_cast<uint64_t>(state.cexp),
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),
};
broker::vector d = {
static_cast<uint64_t>(state.totalc), static_cast<uint64_t>(state.mp),
static_cast<uint64_t>(state.sccfirst), static_cast<uint64_t>(state.inmont),
static_cast<uint64_t>(state.mcount), static_cast<uint64_t>(state.cexp),
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);
for ( int i = 0; i < 256; ++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]));
return {std::move(d)};
@ -694,15 +666,13 @@ bool EntropyVal::DoUnserialize(const broker::data& data)
return true;
}
BloomFilterVal::BloomFilterVal()
: OpaqueVal(bloomfilter_type)
BloomFilterVal::BloomFilterVal() : OpaqueVal(bloomfilter_type)
{
hash = nullptr;
bloom_filter = nullptr;
}
BloomFilterVal::BloomFilterVal(probabilistic::BloomFilter* bf)
: OpaqueVal(bloomfilter_type)
BloomFilterVal::BloomFilterVal(probabilistic::BloomFilter* bf) : OpaqueVal(bloomfilter_type)
{
hash = nullptr;
bloom_filter = bf;
@ -762,12 +732,10 @@ std::string BloomFilterVal::InternalState() const
return bloom_filter->InternalState();
}
BloomFilterValPtr BloomFilterVal::Merge(const BloomFilterVal* x,
const BloomFilterVal* y)
BloomFilterValPtr BloomFilterVal::Merge(const BloomFilterVal* x, const BloomFilterVal* y)
{
if ( x->Type() && // any one 0 is ok here
y->Type() &&
! same_type(x->Type(), y->Type()) )
y->Type() && ! same_type(x->Type(), y->Type()) )
{
reporter->Error("cannot merge Bloom filters with different types");
return nullptr;
@ -875,8 +843,8 @@ CardinalityVal::~CardinalityVal()
ValPtr CardinalityVal::DoClone(CloneState* state)
{
return state->NewClone(this,
make_intrusive<CardinalityVal>(new probabilistic::detail::CardinalityCounter(*c)));
return state->NewClone(
this, make_intrusive<CardinalityVal>(new probabilistic::detail::CardinalityCounter(*c)));
}
bool CardinalityVal::Typify(TypePtr arg_type)
@ -948,16 +916,15 @@ bool CardinalityVal::DoUnserialize(const broker::data& data)
return true;
}
ParaglobVal::ParaglobVal(std::unique_ptr<paraglob::Paraglob> p)
: OpaqueVal(paraglob_type)
ParaglobVal::ParaglobVal(std::unique_ptr<paraglob::Paraglob> p) : OpaqueVal(paraglob_type)
{
this->internal_paraglob = std::move(p);
}
VectorValPtr ParaglobVal::Get(StringVal* &pattern)
VectorValPtr ParaglobVal::Get(StringVal*& pattern)
{
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);
for ( size_t i = 0; i < matches.size(); i++ )
@ -977,7 +944,7 @@ broker::expected<broker::data> ParaglobVal::DoSerialize() const
{
broker::vector d;
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));
return {std::move(d)};
}
@ -988,10 +955,10 @@ bool ParaglobVal::DoUnserialize(const broker::data& data)
if ( ! d )
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());
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) )
return false;
@ -1001,12 +968,12 @@ bool ParaglobVal::DoUnserialize(const broker::data& data)
{
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());
return false;
}
catch (const paraglob::overflow_error& e)
catch ( const paraglob::overflow_error& e )
{
reporter->Error("Paraglob overflow error -> %s", e.what());
return false;
@ -1017,16 +984,17 @@ bool ParaglobVal::DoUnserialize(const broker::data& data)
ValPtr ParaglobVal::DoClone(CloneState* state)
{
try {
return make_intrusive<ParaglobVal>
(std::make_unique<paraglob::Paraglob>(this->internal_paraglob->serialize()));
try
{
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());
return nullptr;
}
catch (const paraglob::overflow_error& e)
catch ( const paraglob::overflow_error& e )
{
reporter->Error("Paraglob overflow error while cloning -> %s", e.what());
return nullptr;
@ -1035,8 +1003,7 @@ ValPtr ParaglobVal::DoClone(CloneState* state)
broker::expected<broker::data> TelemetryVal::DoSerialize() const
{
return broker::make_error(broker::ec::invalid_data,
"cannot serialize metric handles");
return broker::make_error(broker::ec::invalid_data, "cannot serialize metric handles");
}
bool TelemetryVal::DoUnserialize(const broker::data&)
@ -1044,52 +1011,38 @@ bool TelemetryVal::DoUnserialize(const broker::data&)
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
#include <sys/types.h> // for u_char
#include <broker/expected.hh>
#include <paraglob/paraglob.h>
#include <sys/types.h> // for u_char
#include "zeek/IntrusivePtr.h"
#include "zeek/RandTest.h"
@ -14,12 +14,22 @@
#include "zeek/telemetry/Gauge.h"
#include "zeek/telemetry/Histogram.h"
namespace broker { class data; }
namespace broker
{
class data;
}
namespace zeek {
namespace zeek
{
namespace probabilistic { class BloomFilter; }
namespace probabilistic::detail { class CardinalityCounter; }
namespace probabilistic
{
class BloomFilter;
}
namespace probabilistic::detail
{
class CardinalityCounter;
}
class OpaqueVal;
using OpaqueValPtr = IntrusivePtr<OpaqueVal>;
@ -28,12 +38,13 @@ class BloomFilterVal;
using BloomFilterValPtr = IntrusivePtr<BloomFilterVal>;
/**
* Singleton that registers all available all available types of opaque
* values. This faciliates their serialization into Broker values.
*/
class OpaqueMgr {
* Singleton that registers all available all available types of opaque
* values. This faciliates their serialization into Broker values.
*/
class OpaqueMgr
{
public:
using Factory = OpaqueValPtr ();
using Factory = OpaqueValPtr();
/**
* 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
* with the manager.
*/
template<class T>
class Register {
template <class T> class Register
{
public:
Register(const char* id)
{ OpaqueMgr::mgr()->_types.emplace(id, &T::OpaqueInstantiate); }
};
Register(const char* id) { OpaqueMgr::mgr()->_types.emplace(id, &T::OpaqueInstantiate); }
};
private:
std::unordered_map<std::string, Factory*> _types;
};
};
/** Macro to insert into an OpaqueVal-derived class's declaration. */
#define DECLARE_OPAQUE_VALUE(T) \
friend class zeek::OpaqueMgr::Register<T>; \
friend zeek::IntrusivePtr<T> zeek::make_intrusive<T>(); \
broker::expected<broker::data> DoSerialize() const override; \
bool DoUnserialize(const broker::data& data) override; \
const char* OpaqueName() const override { return #T; } \
static zeek::OpaqueValPtr OpaqueInstantiate() { return zeek::make_intrusive<T>(); }
#define DECLARE_OPAQUE_VALUE(T) \
friend class zeek::OpaqueMgr::Register<T>; \
friend zeek::IntrusivePtr<T> zeek::make_intrusive<T>(); \
broker::expected<broker::data> DoSerialize() const override; \
bool DoUnserialize(const broker::data& data) override; \
const char* OpaqueName() const override { return #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)
/** 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
* (other than bif functions). See OpaqueVal.h for derived classes.
*/
class OpaqueVal : public Val {
class OpaqueVal : public Val
{
public:
explicit OpaqueVal(OpaqueTypePtr t);
~OpaqueVal() override;
@ -164,9 +175,10 @@ protected:
* during unserialization. Returns the type at reference count +1.
*/
static TypePtr UnserializeType(const broker::data& data);
};
};
class HashVal : public OpaqueVal {
class HashVal : public OpaqueVal
{
public:
template <class T>
static void digest_all(detail::HashAlgorithm alg, const T& vlist, u_char* result)
@ -197,17 +209,18 @@ protected:
private:
// This flag exists because Get() can only be called once.
bool valid;
};
};
class MD5Val : public HashVal {
class MD5Val : public HashVal
{
public:
template <class T>
static void digest(const T& vlist, u_char result[MD5_DIGEST_LENGTH])
{ digest_all(detail::Hash_MD5, vlist, result); }
template <class T> static void digest(const T& vlist, u_char result[MD5_DIGEST_LENGTH])
{
digest_all(detail::Hash_MD5, vlist, result);
}
template <class T>
static void hmac(const T& vlist,
u_char key[MD5_DIGEST_LENGTH],
static void hmac(const T& vlist, u_char key[MD5_DIGEST_LENGTH],
u_char result[MD5_DIGEST_LENGTH])
{
digest(vlist, result);
@ -233,13 +246,15 @@ protected:
DECLARE_OPAQUE_VALUE(MD5Val)
private:
EVP_MD_CTX* ctx;
};
};
class SHA1Val : public HashVal {
class SHA1Val : public HashVal
{
public:
template <class T>
static void digest(const T& vlist, u_char result[SHA_DIGEST_LENGTH])
{ digest_all(detail::Hash_SHA1, vlist, result); }
template <class T> static void digest(const T& vlist, u_char result[SHA_DIGEST_LENGTH])
{
digest_all(detail::Hash_SHA1, vlist, result);
}
SHA1Val();
~SHA1Val();
@ -256,13 +271,15 @@ protected:
DECLARE_OPAQUE_VALUE(SHA1Val)
private:
EVP_MD_CTX* ctx;
};
};
class SHA256Val : public HashVal {
class SHA256Val : public HashVal
{
public:
template <class T>
static void digest(const T& vlist, u_char result[SHA256_DIGEST_LENGTH])
{ digest_all(detail::Hash_SHA256, vlist, result); }
template <class T> static void digest(const T& vlist, u_char result[SHA256_DIGEST_LENGTH])
{
digest_all(detail::Hash_SHA256, vlist, result);
}
SHA256Val();
~SHA256Val();
@ -279,15 +296,15 @@ protected:
DECLARE_OPAQUE_VALUE(SHA256Val)
private:
EVP_MD_CTX* ctx;
};
};
class EntropyVal : public OpaqueVal {
class EntropyVal : public OpaqueVal
{
public:
EntropyVal();
bool Feed(const void* data, size_t size);
bool Get(double *r_ent, double *r_chisq, double *r_mean,
double *r_montepicalc, double *r_scc);
bool Get(double* r_ent, double* r_chisq, double* r_mean, double* r_montepicalc, double* r_scc);
protected:
friend class Val;
@ -295,17 +312,17 @@ protected:
DECLARE_OPAQUE_VALUE(EntropyVal)
private:
detail::RandTest state;
};
};
class BloomFilterVal : public OpaqueVal {
class BloomFilterVal : public OpaqueVal
{
public:
explicit BloomFilterVal(probabilistic::BloomFilter* bf);
~BloomFilterVal() override;
ValPtr DoClone(CloneState* state) override;
const TypePtr& Type() const
{ return type; }
const TypePtr& Type() const { return type; }
bool Typify(TypePtr type);
@ -315,8 +332,7 @@ public:
bool Empty() const;
std::string InternalState() const;
static BloomFilterValPtr Merge(const BloomFilterVal* x,
const BloomFilterVal* y);
static BloomFilterValPtr Merge(const BloomFilterVal* x, const BloomFilterVal* y);
protected:
friend class Val;
@ -331,10 +347,10 @@ private:
TypePtr type;
detail::CompositeHash* hash;
probabilistic::BloomFilter* bloom_filter;
};
};
class CardinalityVal : public OpaqueVal {
class CardinalityVal : public OpaqueVal
{
public:
explicit CardinalityVal(probabilistic::detail::CardinalityCounter*);
~CardinalityVal() override;
@ -343,12 +359,11 @@ public:
void Add(const Val* val);
const TypePtr& Type() const
{ return type; }
const TypePtr& Type() const { return type; }
bool Typify(TypePtr type);
probabilistic::detail::CardinalityCounter* Get() { return c; };
probabilistic::detail::CardinalityCounter* Get() { return c; };
protected:
CardinalityVal();
@ -358,28 +373,30 @@ private:
TypePtr type;
detail::CompositeHash* hash;
probabilistic::detail::CardinalityCounter* c;
};
};
class ParaglobVal : public OpaqueVal {
class ParaglobVal : public OpaqueVal
{
public:
explicit ParaglobVal(std::unique_ptr<paraglob::Paraglob> p);
VectorValPtr Get(StringVal* &pattern);
VectorValPtr Get(StringVal*& pattern);
ValPtr DoClone(CloneState* state) override;
bool operator==(const ParaglobVal& other) const;
protected:
ParaglobVal() : OpaqueVal(paraglob_type) {}
ParaglobVal() : OpaqueVal(paraglob_type) { }
DECLARE_OPAQUE_VALUE(ParaglobVal)
private:
std::unique_ptr<paraglob::Paraglob> internal_paraglob;
};
};
/**
* Base class for metric handles. Handle types are not serializable.
*/
class TelemetryVal : public OpaqueVal {
class TelemetryVal : public OpaqueVal
{
protected:
explicit TelemetryVal(telemetry::IntCounter);
explicit TelemetryVal(telemetry::IntCounterFamily);
@ -396,34 +413,25 @@ protected:
broker::expected<broker::data> DoSerialize() const override;
bool DoUnserialize(const broker::data& data) override;
};
};
template <class Handle>
class TelemetryValImpl : public TelemetryVal {
template <class Handle> class TelemetryValImpl : public TelemetryVal
{
public:
using HandleType = Handle;
explicit TelemetryValImpl(Handle hdl) : TelemetryVal(hdl), hdl(hdl) { }
Handle GetHandle() const noexcept
{
return hdl;
}
Handle GetHandle() const noexcept { return hdl; }
protected:
ValPtr DoClone(CloneState*) override
{
return make_intrusive<TelemetryValImpl>(hdl);
}
ValPtr DoClone(CloneState*) override { return make_intrusive<TelemetryValImpl>(hdl); }
const char* OpaqueName() const override
{
return Handle::OpaqueName;
}
const char* OpaqueName() const override { return Handle::OpaqueName; }
private:
Handle hdl;
};
};
using IntCounterMetricVal = TelemetryValImpl<telemetry::IntCounter>;
using IntCounterMetricFamilyVal = TelemetryValImpl<telemetry::IntCounterFamily>;
@ -438,4 +446,4 @@ using IntHistogramMetricFamilyVal = TelemetryValImpl<telemetry::IntHistogramFami
using DblHistogramMetricVal = TelemetryValImpl<telemetry::DblHistogram>;
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.
#include "zeek/zeek-config.h"
#include "zeek/Options.h"
#include "zeek/script_opt/ScriptOpt.h"
#include <unistd.h>
#include "zeek/script_opt/ScriptOpt.h"
#include "zeek/zeek-config.h"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
@ -19,7 +19,8 @@
#include "zeek/bsd-getopt-long.h"
#include "zeek/logging/writers/ascii/Ascii.h"
namespace zeek {
namespace zeek
{
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 --test [doctest-options] -- [options] [file ...]\n", prog);
fprintf(stderr, " <file> | Zeek script file, or read stdin\n");
fprintf(stderr, " -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,
" -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, " -e|--exec <zeek code> | augment loaded scripts by given code\n");
fprintf(stderr, " -f|--filter <filter> | tcpdump filter\n");
fprintf(stderr, " -h|--help | command line help\n");
fprintf(stderr, " -i|--iface <interface> | read from given interface (only one allowed)\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,
" -i|--iface <interface> | read from given interface (only one allowed)\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, " -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, " -w|--writefile <writefile> | write to given tcpdump file\n");
#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
fprintf(stderr, " -C|--no-checksums | ignore checksums\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, " -H|--save-seeds <file> | save seeds to given file\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, " -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, " -N|--print-plugins | print available plugins and exit (-NN "
"for verbose)\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, " -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, " -T|--re-level <level> | set 'RE_level' for rules\n");
fprintf(stderr, " -U|--status-file <file> | Record process status in file\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
fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n");
fprintf(stderr, " -M|--mem-profile | record heap [perftools]\n");
#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, " --test | run unit tests ('--test -h' for help, only when compiling with ENABLE_ZEEK_UNIT_TESTS)\n");
fprintf(stderr, " $ZEEKPATH | file search path (%s)\n", util::zeek_path().c_str());
fprintf(stderr, " $ZEEK_PLUGIN_PATH | plugin search path (%s)\n", 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, " --test | run unit tests ('--test -h' for help, "
"only when compiling with ENABLE_ZEEK_UNIT_TESTS)\n");
fprintf(stderr, " $ZEEKPATH | file search path (%s)\n",
util::zeek_path().c_str());
fprintf(stderr, " $ZEEK_PLUGIN_PATH | plugin search path (%s)\n",
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_LOG_SUFFIX | ASCII log file extension (.%s)\n", logging::writer::detail::Ascii::LogExt().c_str());
fprintf(stderr, " $ZEEK_PROFILER_FILE | Output file for script execution statistics (not set)\n");
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, " $ZEEK_LOG_SUFFIX | ASCII log file extension (.%s)\n",
logging::writer::detail::Ascii::LogExt().c_str());
fprintf(stderr, " $ZEEK_PROFILER_FILE | Output file for script execution "
"statistics (not set)\n");
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");
@ -152,7 +183,8 @@ static void print_analysis_help()
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-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, " no-ZAM-opt omit low-level ZAM optimization\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
{
fprintf(stderr,"zeek: unrecognized -O/--optimize option: %s\n\n",
opt);
fprintf(stderr, "zeek: unrecognized -O/--optimize option: %s\n\n", opt);
print_analysis_help();
exit(1);
}
@ -251,17 +282,17 @@ Options parse_cmdline(int argc, char** argv)
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"
" 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);
#endif
#endif
auto is_separator = [](const char* cstr)
{
{
return strcmp(cstr, "--") == 0;
};
};
auto first = argv;
auto last = argv + argc;
auto separator = std::find_if(first, last, is_separator);
@ -285,9 +316,10 @@ Options parse_cmdline(int argc, char** argv)
if ( argc > 1 )
{
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;
for ( ; i < argc && ! endsWith(argv[i], "--"); ++i )
@ -327,53 +359,53 @@ Options parse_cmdline(int argc, char** argv)
}
constexpr struct option long_opts[] = {
{"parse-only", no_argument, nullptr, 'a'},
{"bare-mode", no_argument, nullptr, 'b'},
{"debug-script", no_argument, nullptr, 'd'},
{"exec", required_argument, nullptr, 'e'},
{"filter", required_argument, nullptr, 'f'},
{"help", no_argument, nullptr, 'h'},
{"iface", required_argument, nullptr, 'i'},
{"zeekygen", required_argument, nullptr, 'X'},
{"prefix", required_argument, nullptr, 'p'},
{"readfile", required_argument, nullptr, 'r'},
{"rulefile", required_argument, nullptr, 's'},
{"tracefile", required_argument, nullptr, 't'},
{"writefile", required_argument, nullptr, 'w'},
{"usage-issues", no_argument, nullptr, 'u'},
{"version", no_argument, nullptr, 'v'},
{"no-checksums", no_argument, nullptr, 'C'},
{"force-dns", no_argument, nullptr, 'F'},
{"deterministic", no_argument, nullptr, 'D'},
{"load-seeds", required_argument, nullptr, 'G'},
{"save-seeds", required_argument, nullptr, 'H'},
{"print-plugins", no_argument, nullptr, 'N'},
{"optimize", required_argument, nullptr, 'O'},
{"optimize-only", required_argument, nullptr, 'o'},
{"prime-dns", no_argument, nullptr, 'P'},
{"time", no_argument, nullptr, 'Q'},
{"debug-rules", no_argument, nullptr, 'S'},
{"re-level", required_argument, nullptr, 'T'},
{"watchdog", no_argument, nullptr, 'W'},
{"print-id", required_argument, nullptr, 'I'},
{"status-file", required_argument, nullptr, 'U'},
{"debug", required_argument, nullptr, 'B'},
{"parse-only", no_argument, nullptr, 'a'},
{"bare-mode", no_argument, nullptr, 'b'},
{"debug-script", no_argument, nullptr, 'd'},
{"exec", required_argument, nullptr, 'e'},
{"filter", required_argument, nullptr, 'f'},
{"help", no_argument, nullptr, 'h'},
{"iface", required_argument, nullptr, 'i'},
{"zeekygen", required_argument, nullptr, 'X'},
{"prefix", required_argument, nullptr, 'p'},
{"readfile", required_argument, nullptr, 'r'},
{"rulefile", required_argument, nullptr, 's'},
{"tracefile", required_argument, nullptr, 't'},
{"writefile", required_argument, nullptr, 'w'},
{"usage-issues", no_argument, nullptr, 'u'},
{"version", no_argument, nullptr, 'v'},
{"no-checksums", no_argument, nullptr, 'C'},
{"force-dns", no_argument, nullptr, 'F'},
{"deterministic", no_argument, nullptr, 'D'},
{"load-seeds", required_argument, nullptr, 'G'},
{"save-seeds", required_argument, nullptr, 'H'},
{"print-plugins", no_argument, nullptr, 'N'},
{"optimize", required_argument, nullptr, 'O'},
{"optimize-only", required_argument, nullptr, 'o'},
{"prime-dns", no_argument, nullptr, 'P'},
{"time", no_argument, nullptr, 'Q'},
{"debug-rules", no_argument, nullptr, 'S'},
{"re-level", required_argument, nullptr, 'T'},
{"watchdog", no_argument, nullptr, 'W'},
{"print-id", required_argument, nullptr, 'I'},
{"status-file", required_argument, nullptr, 'U'},
{"debug", required_argument, nullptr, 'B'},
#ifdef USE_PERFTOOLS_DEBUG
{"mem-leaks", no_argument, nullptr, 'm'},
{"mem-profile", no_argument, nullptr, 'M'},
#ifdef USE_PERFTOOLS_DEBUG
{"mem-leaks", no_argument, nullptr, 'm'},
{"mem-profile", no_argument, nullptr, 'M'},
#endif
{"pseudo-realtime", optional_argument, nullptr, 'E'},
{"jobs", optional_argument, nullptr, 'j'},
{"test", no_argument, nullptr, '#'},
{"pseudo-realtime", optional_argument, nullptr, 'E'},
{"jobs", optional_argument, nullptr, 'j'},
{"test", no_argument, nullptr, '#'},
{nullptr, 0, nullptr, 0},
{nullptr, 0, nullptr, 0},
};
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",
sizeof(opts));
sizeof(opts));
int op;
int long_optsind;
@ -385,178 +417,180 @@ Options parse_cmdline(int argc, char** argv)
for ( size_t i = 0; i < zeek_args.size(); ++i )
zargs[i] = zeek_args[i].data();
while ( (op = getopt_long(zeek_args.size(), zargs.get(), opts, long_opts, &long_optsind)) != EOF )
switch ( op ) {
case 'a':
rval.parse_only = true;
break;
case 'b':
rval.bare_mode = true;
break;
case 'd':
rval.debug_scripts = true;
break;
case 'e':
rval.script_code_to_exec = optarg;
break;
case 'f':
rval.pcap_filter = optarg;
break;
case 'h':
rval.print_usage = true;
break;
case 'i':
if ( rval.interface )
{
fprintf(stderr, "ERROR: Only a single interface option (-i) is allowed.\n");
exit(1);
}
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");
while ( (op = getopt_long(zeek_args.size(), zargs.get(), opts, long_opts, &long_optsind)) !=
EOF )
switch ( op )
{
case 'a':
rval.parse_only = true;
break;
case 'b':
rval.bare_mode = true;
break;
case 'd':
rval.debug_scripts = true;
break;
case 'e':
rval.script_code_to_exec = optarg;
break;
case 'f':
rval.pcap_filter = optarg;
break;
case 'h':
rval.print_usage = true;
break;
case 'i':
if ( rval.interface )
{
fprintf(stderr, "ERROR: Only a single interface option (-i) is allowed.\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;
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);
}
#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
case 'm':
rval.perftools_check_leaks = 1;
break;
case 'M':
rval.perftools_profile = 1;
break;
case 'm':
rval.perftools_check_leaks = 1;
break;
case 'M':
rval.perftools_profile = 1;
break;
#endif
case '#':
fprintf(stderr, "ERROR: --test only allowed as first argument.\n");
usage(zargs[0], 1);
break;
case '#':
fprintf(stderr, "ERROR: --test only allowed as first argument.\n");
usage(zargs[0], 1);
break;
case 0:
// This happens for long options that don't have
// a short-option equivalent.
break;
case 0:
// This happens for long options that don't have
// a short-option equivalent.
break;
case '?':
default:
usage(zargs[0], 1);
break;
}
case '?':
default:
usage(zargs[0], 1);
break;
}
// Process remaining arguments. X=Y arguments indicate script
// 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)
{
{
if ( path->empty() )
return;
@ -605,13 +639,12 @@ Options parse_cmdline(int argc, char** argv)
if ( ! getcwd(cwd, sizeof(cwd)) )
{
fprintf(stderr, "failed to get current directory: %s\n",
strerror(errno));
fprintf(stderr, "failed to get current directory: %s\n", strerror(errno));
exit(1);
}
*path = std::string(cwd) + "/" + *path;
};
};
if ( rval.supervisor_mode )
{
@ -625,4 +658,4 @@ Options parse_cmdline(int argc, char** argv)
return rval;
}
} // namespace zeek
} // namespace zeek

View file

@ -9,13 +9,15 @@
#include "zeek/DNS_Mgr.h"
#include "zeek/script_opt/ScriptOpt.h"
namespace zeek {
namespace zeek
{
/**
* Options that define general Zeek processing behavior, usually determined
* from command-line arguments.
*/
struct Options {
struct Options
{
/**
* 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
@ -40,7 +42,7 @@ struct Options {
std::optional<std::string> identifier_to_print;
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;
bool ignore_checksums = false;
@ -79,7 +81,7 @@ struct Options {
// For script optimization:
detail::AnalyOpt analysis_options;
};
};
/**
* Parse Zeek command-line arguments.
@ -101,4 +103,4 @@ void usage(const char* prog, int code = 1);
*/
bool fake_dns();
} // namespace zeek
} // namespace zeek

View file

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

View file

@ -4,7 +4,8 @@
#include "zeek/Type.h"
namespace zeek::detail {
namespace zeek::detail
{
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)
{
return v < static_cast<double>(INT64_MIN) ||
v > static_cast<double>(INT64_MAX);
return v < static_cast<double>(INT64_MIN) || v > static_cast<double>(INT64_MAX);
}
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;
}
extern bool would_overflow(const zeek::Type* from_type,
const zeek::Type* to_type, const Val* val);
extern bool would_overflow(const zeek::Type* from_type, const zeek::Type* to_type, const Val* val);
}
}

View file

@ -1,7 +1,9 @@
#include "zeek/PacketFilter.h"
#include "zeek/IP.h"
namespace zeek::detail {
namespace zeek::detail
{
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)
{
Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(), 128);
Filter* f = (Filter*)src_filter.Lookup(ip->SrcAddr(), 128);
if ( f )
return MatchFilter(*f, *ip, len, caplen);
f = (Filter*) dst_filter.Lookup(ip->DstAddr(), 128);
f = (Filter*)dst_filter.Lookup(ip->DstAddr(), 128);
if ( f )
return MatchFilter(*f, *ip, len, caplen);
return default_match;
}
bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip,
int len, int caplen)
bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip, int len, int caplen)
{
if ( ip.NextProto() == IPPROTO_TCP && f.tcp_flags )
{
// Caution! The packet sanity checks have not been performed yet
int ip_hdr_len = ip.HdrLen();
len -= ip_hdr_len; // remove IP header
len -= ip_hdr_len; // remove IP header
caplen -= ip_hdr_len;
if ( (unsigned int) len < sizeof(struct tcphdr) ||
(unsigned int) caplen < sizeof(struct tcphdr) )
if ( (unsigned int)len < sizeof(struct tcphdr) ||
(unsigned int)caplen < sizeof(struct tcphdr) )
// Packet too short, will be dropped anyway.
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 )
// 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 util::detail::random_number() < f.probability;
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

@ -7,17 +7,20 @@
#include "zeek/IPAddr.h"
#include "zeek/PrefixTable.h"
namespace zeek {
namespace zeek
{
class IP_Hdr;
class Val;
namespace detail {
namespace detail
{
class PacketFilter {
class PacketFilter
{
public:
explicit PacketFilter(bool arg_default);
~PacketFilter() {}
~PacketFilter() { }
// 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
@ -38,10 +41,11 @@ public:
bool Match(const std::unique_ptr<IP_Hdr>& ip, int len, int caplen);
private:
struct Filter {
struct Filter
{
uint32_t tcp_flags;
double probability;
};
};
static void DeleteFilter(void* data);
@ -50,7 +54,7 @@ private:
bool default_match;
PrefixTable src_filter;
PrefixTable dst_filter;
};
};
} // namespace detail
} // namespace zeek
} // namespace detail
} // namespace zeek

View file

@ -2,14 +2,15 @@
#include "zeek/Pipe.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include "zeek/Reporter.h"
namespace zeek::detail {
namespace zeek::detail
{
static void pipe_fail(int eno)
{
@ -88,8 +89,7 @@ static int dup_or_fail(int fd, int flags, int status_flags)
return rval;
}
Pipe::Pipe(int flags0, int flags1, int status_flags0, int status_flags1,
int* arg_fds)
Pipe::Pipe(int flags0, int flags1, int status_flags0, int status_flags1, int* arg_fds)
{
if ( arg_fds )
{
@ -155,8 +155,8 @@ Pipe& Pipe::operator=(const Pipe& other)
PipePair::PipePair(int flags, int status_flags, int* fds)
: 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
namespace zeek::detail {
namespace zeek::detail
{
class Pipe {
class Pipe
{
public:
/**
* 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.
@ -17,12 +18,12 @@ public:
* than create ones from a new pipe. Should point to memory containing
* two consecutive file descriptors, the "read" one and then the "write" one.
*/
explicit Pipe(int flags0 = 0, int flags1 = 0, int status_flags0 = 0,
int status_flags1 = 0, int* fds = nullptr);
explicit Pipe(int flags0 = 0, int flags1 = 0, int status_flags0 = 0, int status_flags1 = 0,
int* fds = nullptr);
/**
* Close the pair of file descriptors owned by the object.
*/
* Close the pair of file descriptors owned by the object.
*/
~Pipe();
/**
@ -39,14 +40,12 @@ public:
/**
* @return the file descriptor associated with the read-end of the pipe.
*/
int ReadFD() const
{ return fds[0]; }
int ReadFD() const { return fds[0]; }
/**
* @return the file descriptor associated with the write-end of the pipe.
*/
int WriteFD() const
{ return fds[1]; }
int WriteFD() const { return fds[1]; }
/**
* Sets the given file descriptor flags for both the read and write end
@ -64,14 +63,14 @@ private:
int fds[2];
int flags[2];
int status_flags[2];
};
};
/**
* A pair of pipes that can be used for bi-directinoal IPC.
*/
class PipePair {
class PipePair
{
public:
/**
* Create a pair of pipes
* @param flags file descriptor flags to set on pipes
@ -87,53 +86,45 @@ public:
/**
* @return the pipe used for receiving input
*/
Pipe& In()
{ return pipes[swapped]; }
Pipe& In() { return pipes[swapped]; }
/**
* @return the pipe used for sending output
*/
Pipe& Out()
{ return pipes[!swapped]; }
Pipe& Out() { return pipes[! swapped]; }
/**
* @return the pipe used for receiving input
*/
const Pipe& In() const
{ return pipes[swapped]; }
const Pipe& In() const { return pipes[swapped]; }
/**
* @return the pipe used for sending output
*/
const Pipe& Out() const
{ return pipes[!swapped]; }
const Pipe& Out() const { return pipes[! swapped]; }
/**
* @return a file descriptor that may used for receiving messages by
* polling/reading it.
*/
int InFD() const
{ return In().ReadFD(); }
int InFD() const { return In().ReadFD(); }
/**
* @return a file descriptor that may be used for sending messages by
* writing to it.
*/
int OutFD() const
{ return Out().WriteFD(); }
int OutFD() const { return Out().WriteFD(); }
/**
* 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
* reading/writing.
*/
void Swap()
{ swapped = ! swapped; }
void Swap() { swapped = ! swapped; }
private:
Pipe pipes[2];
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 <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <map>
#include <string>
#include <vector>
#include <map>
#include "zeek/Debug.h"
#include "zeek/util.h"
#include "zeek/Reporter.h"
#include "zeek/util.h"
#include "zeek/zeek-config.h"
using namespace std;
struct PolicyFile {
PolicyFile () { filedata = nullptr; lmtime = 0; }
~PolicyFile () { delete [] filedata; filedata = nullptr; }
struct PolicyFile
{
PolicyFile()
{
filedata = nullptr;
lmtime = 0;
}
~PolicyFile()
{
delete[] filedata;
filedata = nullptr;
}
time_t lmtime;
char* filedata;
vector<const char*> lines;
};
};
typedef map<string, PolicyFile*> PolicyFileMap;
static PolicyFileMap policy_files;
namespace zeek::detail {
namespace zeek::detail
{
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!
// (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 )
reporter->InternalError("Failed to fread() file data");
reporter->InternalError("Failed to fread() file data");
pf->filedata[size] = 0;
fclose(f);
@ -122,8 +131,8 @@ bool LoadPolicyFileText(const char* policy_filename)
}
// REMEMBER: line number arguments are indexed from 0.
bool PrintLines(const char* policy_filename, unsigned int start_line,
unsigned int how_many_lines, bool show_numbers)
bool PrintLines(const char* policy_filename, unsigned int start_line, unsigned int how_many_lines,
bool show_numbers)
{
if ( ! policy_filename )
return true;
@ -157,8 +166,8 @@ bool PrintLines(const char* policy_filename, unsigned int start_line,
if ( start_line > pf->lines.size() )
{
debug_msg("Line number %d out of range; %s has %d lines\n",
start_line, policy_filename, int(pf->lines.size()));
debug_msg("Line number %d out of range; %s has %d lines\n", start_line, policy_filename,
int(pf->lines.size()));
return false;
}
@ -177,4 +186,4 @@ bool PrintLines(const char* policy_filename, unsigned int start_line,
return true;
}
} // namespace zeek::detail
} // namespace zeek::detail

View file

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

View file

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

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