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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +1,10 @@
#pragma once #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" #include "event.bif.func_h"

View file

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

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

142
src/ID.cc
View file

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

119
src/ID.h
View file

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

824
src/IP.cc
View file

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

223
src/IP.h
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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