Support for log filter policy hooks

This adds a "policy" hook into the logging framework's streams and
filters to replace the existing log filter predicates. The hook
signature is as follows:

    hook(rec: any, id: Log::ID, filter: Log::Filter);

The logging manager invokes hooks on each log record. Hooks can veto
log records via a break, and modify them if necessary. Log filters
inherit the stream-level hook, but can override or remove the hook as
needed.

The distribution's existing log streams now come with pre-defined
hooks that users can add handlers to. Their name is standardized as
"log_policy" by convention, with additional suffixes when a module
provides multiple streams. The following adds a handler to the Conn
module's default log policy hook:

    hook Conn::log_policy(rec: Conn::Info, id: Log::ID, filter: Log::Filter)
            {
            if ( some_veto_reason(rec) )
                break;
            }

By default, this handler will get invoked for any log filter
associated with the Conn::LOG stream.

The existing predicates are deprecated for removal in 4.1 but continue
to work.
This commit is contained in:
Christian Kreibich 2020-09-21 16:09:36 -07:00
parent c8545c85d8
commit 1bd658da8f
61 changed files with 289 additions and 85 deletions

View file

@ -5,6 +5,8 @@ module PE;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Current timestamp.
ts: time &log;
@ -58,7 +60,7 @@ const pe_mime_types = { "application/x-dosexec" };
event zeek_init() &priority=5
{
Files::register_for_mime_types(Files::ANALYZER_PE, pe_mime_types);
Log::create_stream(LOG, [$columns=Info, $ev=log_pe, $path="pe"]);
Log::create_stream(LOG, [$columns=Info, $ev=log_pe, $path="pe", $policy=log_policy]);
}
hook set_file(f: fa_file) &priority=5

View file

@ -1,3 +1,4 @@
@load base/frameworks/files
@load base/files/hash
@ -6,6 +7,8 @@ module X509;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## How often do you have to encounter a certificate before
## caching it. Set to 0 to disable caching of certificates.
option caching_required_encounters : count = 10;
@ -91,7 +94,7 @@ redef record Files::Info += {
event zeek_init() &priority=5
{
Log::create_stream(X509::LOG, [$columns=Info, $ev=log_x509, $path="x509"]);
Log::create_stream(X509::LOG, [$columns=Info, $ev=log_x509, $path="x509", $policy=log_policy]);
# We use MIME types internally to distinguish between user and CA certificates.
# The first certificate in a connection always gets tagged as user-cert, all

View file

@ -6,6 +6,9 @@ export {
## The Broker logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The type of a Broker activity being logged.
type Type: enum {
## An informational status update.
@ -32,7 +35,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(Broker::LOG, [$columns=Info, $path="broker"]);
Log::create_stream(Broker::LOG, [$columns=Info, $path="broker", $policy=log_policy]);
}
function log_status(ev: string, endpoint: EndpointInfo, msg: string)

View file

@ -115,6 +115,9 @@ export {
## The cluster logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains the column fields of the cluster log.
type Info: record {
## The time at which a cluster message was generated.
@ -374,7 +377,7 @@ event zeek_init() &priority=5
terminate();
}
Log::create_stream(Cluster::LOG, [$columns=Info, $path="cluster"]);
Log::create_stream(Cluster::LOG, [$columns=Info, $path="cluster", $policy=log_policy]);
}
function create_store(name: string, persistent: bool &default=F): Cluster::StoreInfo

View file

@ -10,6 +10,9 @@ export {
## The config logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## Represents the data in config.log.
type Info: record {
## Timestamp at which the configuration change occured.
@ -152,7 +155,7 @@ function config_option_changed(ID: string, new_value: any, location: string): an
event zeek_init() &priority=10
{
Log::create_stream(LOG, [$columns=Info, $ev=log_config, $path="config"]);
Log::create_stream(LOG, [$columns=Info, $ev=log_config, $path="config", $policy=log_policy]);
# Limit logging to the manager - everyone else just feeds off it.
@if ( !Cluster::is_enabled() || Cluster::local_node_type() == Cluster::MANAGER )

View file

@ -7,6 +7,9 @@ export {
## Add the DPD logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type defining the columns to log in the DPD logging stream.
type Info: record {
## Timestamp for when protocol analysis failed.
@ -47,7 +50,7 @@ redef record connection += {
event zeek_init() &priority=5
{
Log::create_stream(DPD::LOG, [$columns=Info, $path="dpd"]);
Log::create_stream(DPD::LOG, [$columns=Info, $path="dpd", $policy=log_policy]);
}
event protocol_confirmation(c: connection, atype: Analyzer::Tag, aid: count) &priority=10

View file

@ -14,6 +14,9 @@ export {
LOG
};
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## A structure which parameterizes a type of file analysis.
type AnalyzerArgs: record {
## An event which will be generated for all new file contents,
@ -318,7 +321,7 @@ global analyzer_add_callbacks: table[Files::Tag] of function(f: fa_file, args: A
event zeek_init() &priority=5
{
Log::create_stream(Files::LOG, [$columns=Info, $ev=log_files, $path="files"]);
Log::create_stream(Files::LOG, [$columns=Info, $ev=log_files, $path="files", $policy=log_policy]);
}
function set_info(f: fa_file)

View file

@ -10,6 +10,8 @@ module Intel;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Enum type to represent various types of intelligence data.
type Type: enum {
## An IP address.
@ -225,7 +227,7 @@ global min_data_store: MinDataStore &redef;
event zeek_init() &priority=5
{
Log::create_stream(LOG, [$columns=Info, $ev=log_intel, $path="intel"]);
Log::create_stream(LOG, [$columns=Info, $ev=log_intel, $path="intel", $policy=log_policy]);
}
# Function that abstracts expiration of different types.

View file

@ -43,21 +43,6 @@ export {
## Individual writers can use a different value.
const unset_field = "-" &redef;
## Type defining the content of a logging stream.
type Stream: record {
## A record type defining the log's columns.
columns: any;
## Event that will be raised once for each log entry.
## The event receives a single same parameter, an instance of
## type ``columns``.
ev: any &optional;
## A path that will be inherited by any filters added to the
## stream which do not already specify their own path.
path: string &optional;
};
## Builds the default path values for log filters if not otherwise
## specified by a filter. The default implementation uses *id*
## to derive a name. Upon adding a filter to a stream, if neither
@ -232,7 +217,8 @@ export {
## fields set to the values to be logged.
##
## Returns: True if the entry is to be recorded.
pred: function(rec: any): bool &optional;
pred: function(rec: any): bool &optional
&deprecated="Remove in 4.1. PolicyHooks will replace the $pred function.";
## Output path for recording entries matching this
## filter.
@ -322,6 +308,60 @@ export {
config: table[string] of string &default=table();
};
## A hook type to implement filtering policy. Hook handlers can
## veto the logging of a record or alter it prior to logging.
## You can pass arbitrary state into the hook via the
## filter argument and its config member.
##
## rec: An instance of the stream's ``columns`` type with its
## fields set to the values to be logged.
##
## id: The ID associated with the logging stream the filter
## belongs to.
##
## filter: The :zeek:type:`Log::Filter` instance that controls
## the fate of the given log record.
type PolicyHook: hook(rec: any, id: ID, filter: Filter);
# To allow Filters to have a policy hook that refers to
# Filters, the Filter type must exist. So redef now to add the
# hook to the record.
redef record Filter += {
## Policy hooks can adjust log entry values and veto
## the writing of a log entry for the record passed
## into it. Any hook that breaks from its body signals
## that Zeek won't log the entry passed into it.
##
## When no policy hook is defined, the filter inherits
## the hook from the stream it's associated with.
policy: PolicyHook &optional;
};
## Type defining the content of a logging stream.
type Stream: record {
## A record type defining the log's columns.
columns: any;
## Event that will be raised once for each log entry.
## The event receives a single same parameter, an instance of
## type ``columns``.
ev: any &optional;
## A path that will be inherited by any filters added to the
## stream which do not already specify their own path.
path: string &optional;
## Policy hooks can adjust log records and veto their
## writing. Any hook handler that breaks from its body
## signals that Zeek won't log the entry passed into
## it. You can pass arbitrary state into the hook via
## the filter instance and its config table.
##
## New Filters created for this stream will inherit
## this policy hook, unless they provide their own.
policy: PolicyHook &optional;
};
## Sentinel value for indicating that a filter was not found when looked up.
const no_filter: Filter = [$name="<not found>"];

View file

@ -7,6 +7,8 @@ module NetControl;
export {
redef enum Log::ID += { DROP_LOG };
global log_policy_drop: Log::PolicyHook;
## Stops all packets involving an IP address from being forwarded.
##
## a: The address to be dropped.
@ -57,7 +59,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(NetControl::DROP_LOG, [$columns=DropInfo, $ev=log_netcontrol_drop, $path="netcontrol_drop"]);
Log::create_stream(NetControl::DROP_LOG, [$columns=DropInfo, $ev=log_netcontrol_drop, $path="netcontrol_drop", $policy=log_policy_drop]);
}
function drop_connection(c: conn_id, t: interval, location: string &default="") : string

View file

@ -19,6 +19,9 @@ export {
## The framework's logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
# ###
# ### Generic functions and events.
# ###
@ -366,7 +369,7 @@ global rule_entities: table[Entity, RuleType] of Rule;
event zeek_init() &priority=5
{
Log::create_stream(NetControl::LOG, [$columns=Info, $ev=log_netcontrol, $path="netcontrol"]);
Log::create_stream(NetControl::LOG, [$columns=Info, $ev=log_netcontrol, $path="netcontrol", $policy=log_policy]);
}
function entity_to_info(info: Info, e: Entity)

View file

@ -7,6 +7,8 @@ module NetControl;
export {
redef enum Log::ID += { SHUNT };
global log_policy_shunt: Log::PolicyHook;
## Stops forwarding a uni-directional flow's packets to Zeek.
##
## f: The flow to shunt.
@ -38,7 +40,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(NetControl::SHUNT, [$columns=ShuntInfo, $ev=log_netcontrol_shunt, $path="netcontrol_shunt"]);
Log::create_stream(NetControl::SHUNT, [$columns=ShuntInfo, $ev=log_netcontrol_shunt, $path="netcontrol_shunt", $policy=log_policy_shunt]);
}
function shunt_flow(f: flow_id, t: interval, location: string &default="") : string

View file

@ -16,6 +16,10 @@ export {
ALARM_LOG,
};
## Default logging policy hooks for the streams.
global log_policy: Log::PolicyHook;
global log_policy_alarm: Log::PolicyHook;
## Scripts creating new notices need to redef this enum to add their
## own specific notice types which would then get used when they call
## the :zeek:id:`NOTICE` function. The convention is to give a general
@ -388,9 +392,9 @@ function log_mailing_postprocessor(info: Log::RotationInfo): bool
event zeek_init() &priority=5
{
Log::create_stream(Notice::LOG, [$columns=Info, $ev=log_notice, $path="notice"]);
Log::create_stream(Notice::LOG, [$columns=Info, $ev=log_notice, $path="notice", $policy=log_policy]);
Log::create_stream(Notice::ALARM_LOG, [$columns=Notice::Info, $path="notice_alarm"]);
Log::create_stream(Notice::ALARM_LOG, [$columns=Notice::Info, $path="notice_alarm", $policy=log_policy_alarm]);
# If Zeek is configured for mailing notices, set up mailing for alarms.
# Make sure that this alarm log is also output as text so that it can
# be packaged up and emailed later.

View file

@ -17,6 +17,9 @@ export {
## The weird logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
redef enum Notice::Type += {
## Generic unusual but notice-worthy weird activity.
Activity,
@ -298,7 +301,7 @@ const notice_actions = {
event zeek_init() &priority=5
{
Log::create_stream(Weird::LOG, [$columns=Info, $ev=log_weird, $path="weird"]);
Log::create_stream(Weird::LOG, [$columns=Info, $ev=log_weird, $path="weird", $policy=log_policy]);
}
function flow_id_string(src: addr, dst: addr): string

View file

@ -13,6 +13,8 @@ export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Log controller constructor.
##
## dpid: OpenFlow switch datapath id.
@ -48,7 +50,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(OpenFlow::LOG, [$columns=Info, $ev=log_openflow, $path="openflow"]);
Log::create_stream(OpenFlow::LOG, [$columns=Info, $ev=log_openflow, $path="openflow", $policy=log_policy]);
}
function log_flow_mod(state: ControllerState, match: ofp_match, flow_mod: OpenFlow::ofp_flow_mod): bool

View file

@ -14,6 +14,9 @@ export {
## Add the packet filter logging stream.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## Add notice types related to packet filter errors.
redef enum Notice::Type += {
## This notice is generated if a packet filter cannot be compiled.
@ -159,7 +162,7 @@ event filter_change_tracking()
event zeek_init() &priority=5
{
Log::create_stream(PacketFilter::LOG, [$columns=Info, $path="packet_filter"]);
Log::create_stream(PacketFilter::LOG, [$columns=Info, $path="packet_filter", $policy=log_policy]);
# Preverify the capture and restrict filters to give more granular failure messages.
for ( id, cf in capture_filters )

View file

@ -17,6 +17,9 @@ export {
## The reporter logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains the column fields of the reporter log.
type Info: record {
## The network time at which the reporter event was generated.
@ -37,7 +40,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(Reporter::LOG, [$columns=Info, $path="reporter"]);
Log::create_stream(Reporter::LOG, [$columns=Info, $path="reporter", $policy=log_policy]);
}
event reporter_info(t: time, msg: string, location: string) &priority=-5

View file

@ -35,6 +35,9 @@ export {
## The signature logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## These are the default actions you can apply to signature matches.
## All of them write the signature record to the logging stream unless
## declared otherwise.
@ -142,7 +145,7 @@ global did_sig_log: set[string] &read_expire = 1 hr;
event zeek_init() &priority=5
{
Log::create_stream(Signatures::LOG, [$columns=Info, $ev=log_signature, $path="signatures"]);
Log::create_stream(Signatures::LOG, [$columns=Info, $ev=log_signature, $path="signatures", $policy=log_policy]);
}
# Returns true if the given signature has already been triggered for the given

View file

@ -14,6 +14,9 @@ export {
## The software logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## Scripts detecting new types of software need to redef this enum to add
## their own specific software types which would then be used when they
## create :zeek:type:`Software::Info` records.
@ -123,7 +126,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(Software::LOG, [$columns=Info, $ev=log_software, $path="software"]);
Log::create_stream(Software::LOG, [$columns=Info, $ev=log_software, $path="software", $policy=log_policy]);
}
type Description: record {

View file

@ -13,6 +13,9 @@ export {
## The tunnel logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## Types of interesting activity that can occur with a tunnel.
type Action: enum {
## A new tunnel (encapsulating "connection") has been seen.
@ -94,7 +97,7 @@ redef likely_server_ports += { ayiya_ports, teredo_ports, gtpv1_ports, vxlan_por
event zeek_init() &priority=5
{
Log::create_stream(Tunnel::LOG, [$columns=Info, $path="tunnel"]);
Log::create_stream(Tunnel::LOG, [$columns=Info, $path="tunnel", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_AYIYA, ayiya_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_TEREDO, teredo_ports);

View file

@ -13,6 +13,9 @@ export {
## The connection logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains column fields of the connection log.
type Info: record {
## This is the time of the first packet.
@ -158,7 +161,7 @@ redef record connection += {
event zeek_init() &priority=5
{
Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn, $path="conn"]);
Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn, $path="conn", $policy=log_policy]);
}
function conn_state(c: connection, trans: transport_proto): string

View file

@ -7,6 +7,8 @@ module DCE_RPC;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts : time &log;
@ -65,7 +67,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(DCE_RPC::LOG, [$columns=Info, $path="dce_rpc"]);
Log::create_stream(DCE_RPC::LOG, [$columns=Info, $path="dce_rpc", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DCE_RPC, ports);
}

View file

@ -12,6 +12,8 @@ module DHCP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the column fields of the DHCP log.
type Info: record {
## The earliest time at which a DHCP message over the
@ -122,7 +124,7 @@ redef likely_server_ports += { 67/udp };
event zeek_init() &priority=5
{
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp, $path="dhcp"]);
Log::create_stream(DHCP::LOG, [$columns=Info, $ev=log_dhcp, $path="dhcp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DHCP, ports);
}

View file

@ -8,6 +8,8 @@ module DNP3;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Time of the request.
ts: time &log;
@ -40,7 +42,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3, $path="dnp3"]);
Log::create_stream(DNP3::LOG, [$columns=Info, $ev=log_dnp3, $path="dnp3", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DNP3_TCP, ports);
}

View file

@ -11,6 +11,9 @@ export {
## The DNS logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains the column fields of the DNS log.
type Info: record {
## The earliest time at which a DNS protocol message over the
@ -160,7 +163,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns, $path="dns"]);
Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns, $path="dns", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_DNS, ports);
}

View file

@ -18,6 +18,9 @@ export {
## The FTP protocol logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## List of commands that should have their command/response pairs logged.
option logged_commands = {
"APPE", "DELE", "RETR", "STOR", "STOU", "ACCT", "PORT", "PASV", "EPRT",
@ -61,7 +64,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp, $path="ftp"]);
Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp, $path="ftp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_FTP, ports);
}

View file

@ -12,6 +12,8 @@ module HTTP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Indicate a type of attack or compromise in the record to be logged.
type Tags: enum {
## Placeholder.
@ -145,7 +147,7 @@ redef likely_server_ports += { ports };
# Initialize the HTTP logging stream and ports.
event zeek_init() &priority=5
{
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http, $path="http"]);
Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http, $path="http", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_HTTP, ports);
}

View file

@ -8,6 +8,8 @@ export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp when the command was seen.
ts: time &log;
@ -43,7 +45,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log, $path="irc"]);
Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log, $path="irc", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_IRC, ports);
}

View file

@ -9,6 +9,8 @@ module KRB;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -81,7 +83,7 @@ event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_KRB, udp_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_KRB_TCP, tcp_ports);
Log::create_stream(KRB::LOG, [$columns=Info, $ev=log_krb, $path="kerberos"]);
Log::create_stream(KRB::LOG, [$columns=Info, $ev=log_krb, $path="kerberos", $policy=log_policy]);
}
function set_session(c: connection): bool

View file

@ -7,6 +7,8 @@ module Modbus;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Time of the request.
ts: time &log;
@ -34,7 +36,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus, $path="modbus"]);
Log::create_stream(Modbus::LOG, [$columns=Info, $ev=log_modbus, $path="modbus", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MODBUS, ports);
}

View file

@ -8,6 +8,8 @@ module MySQL;
export {
redef enum Log::ID += { mysql::LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -43,7 +45,7 @@ const ports = { 1434/tcp, 3306/tcp };
event zeek_init() &priority=5
{
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql, $path="mysql"]);
Log::create_stream(mysql::LOG, [$columns=Info, $ev=log_mysql, $path="mysql", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MYSQL, ports);
}

View file

@ -6,6 +6,8 @@ module NTLM;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts : time &log;
@ -48,7 +50,7 @@ redef record connection += {
event zeek_init() &priority=5
{
Log::create_stream(NTLM::LOG, [$columns=Info, $path="ntlm"]);
Log::create_stream(NTLM::LOG, [$columns=Info, $path="ntlm", $policy=log_policy]);
}
function set_session(c: connection)

View file

@ -3,6 +3,8 @@ module NTP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -59,7 +61,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_NTP, ports);
Log::create_stream(NTP::LOG, [$columns = Info, $ev = log_ntp, $path="ntp"]);
Log::create_stream(NTP::LOG, [$columns = Info, $ev = log_ntp, $path="ntp", $policy=log_policy]);
}
event ntp_message(c: connection, is_orig: bool, msg: NTP::Message) &priority=5

View file

@ -9,6 +9,8 @@ module RADIUS;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts : time &log;
@ -63,7 +65,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius, $path="radius"]);
Log::create_stream(RADIUS::LOG, [$columns=Info, $ev=log_radius, $path="radius", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_RADIUS, ports);
}

View file

@ -8,6 +8,8 @@ module RDP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp for when the event happened.
ts: time &log;
@ -95,7 +97,7 @@ redef likely_server_ports += { rdp_ports, rdpeudp_ports };
event zeek_init() &priority=5
{
Log::create_stream(RDP::LOG, [$columns=RDP::Info, $ev=log_rdp, $path="rdp"]);
Log::create_stream(RDP::LOG, [$columns=RDP::Info, $ev=log_rdp, $path="rdp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_RDP, rdp_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_RDPEUDP, rdpeudp_ports);
}

View file

@ -5,6 +5,8 @@ module RFB;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the RFB log.
type Info: record {
## Timestamp for when the event happened.
@ -83,7 +85,7 @@ redef record connection += {
event zeek_init() &priority=5
{
Log::create_stream(RFB::LOG, [$columns=Info, $ev=log_rfb, $path="rfb"]);
Log::create_stream(RFB::LOG, [$columns=Info, $ev=log_rfb, $path="rfb", $policy=log_policy]);
}
function write_log(c:connection)

View file

@ -11,6 +11,8 @@ module SIP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the SIP log.
type Info: record {
## Timestamp for when the request happened.
@ -104,7 +106,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SIP::LOG, [$columns=Info, $ev=log_sip, $path="sip"]);
Log::create_stream(SIP::LOG, [$columns=Info, $ev=log_sip, $path="sip", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SIP, ports);
}

View file

@ -11,6 +11,9 @@ export {
FILES_LOG
};
global log_policy_files: Log::PolicyHook;
global log_policy_mapping: Log::PolicyHook;
## Abstracted actions for SMB file actions.
type Action: enum {
FILE_READ,
@ -179,8 +182,8 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SMB::FILES_LOG, [$columns=SMB::FileInfo, $path="smb_files"]);
Log::create_stream(SMB::MAPPING_LOG, [$columns=SMB::TreeInfo, $path="smb_mapping"]);
Log::create_stream(SMB::FILES_LOG, [$columns=SMB::FileInfo, $path="smb_files", $policy=log_policy_files]);
Log::create_stream(SMB::MAPPING_LOG, [$columns=SMB::TreeInfo, $path="smb_mapping", $policy=log_policy_mapping]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SMB, ports);
}

View file

@ -8,6 +8,8 @@ module SMTP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Time when the message was first seen.
ts: time &log;
@ -98,7 +100,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp, $path="smtp"]);
Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp, $path="smtp", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SMTP, ports);
}

View file

@ -7,6 +7,8 @@ module SNMP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Information tracked per SNMP session.
type Info: record {
## Timestamp of first packet belonging to the SNMP session.
@ -71,7 +73,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_SNMP, ports);
Log::create_stream(SNMP::LOG, [$columns=SNMP::Info, $ev=log_snmp, $path="snmp"]);
Log::create_stream(SNMP::LOG, [$columns=SNMP::Info, $ev=log_snmp, $path="snmp", $policy=log_policy]);
}
function init_state(c: connection, h: SNMP::Header): Info

View file

@ -7,6 +7,8 @@ module SOCKS;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## Whether passwords are captured or not.
option default_capture_password = F;
@ -53,7 +55,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks, $path="socks"]);
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks, $path="socks", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SOCKS, ports);
}

View file

@ -9,6 +9,9 @@ export {
## The SSH protocol logging stream identifier.
redef enum Log::ID += { LOG };
## A default logging policy hook for the stream.
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the SSH log.
type Info: record {
## Time when the SSH connection began.
@ -143,7 +146,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Analyzer::register_for_ports(Analyzer::ANALYZER_SSH, ports);
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh, $path="ssh"]);
Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh, $path="ssh", $policy=log_policy]);
}
function set_session(c: connection)

View file

@ -10,6 +10,8 @@ module SSL;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the SSL log.
type Info: record {
## Time when the SSL connection was first detected.
@ -147,7 +149,7 @@ redef likely_server_ports += { ssl_ports, dtls_ports };
event zeek_init() &priority=5
{
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl"]);
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ssl_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_DTLS, dtls_ports);
}

View file

@ -8,6 +8,8 @@ module Syslog;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the syslog log.
type Info: record {
## Timestamp when the syslog message was seen.
@ -36,7 +38,7 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(Syslog::LOG, [$columns=Info, $path="syslog"]);
Log::create_stream(Syslog::LOG, [$columns=Info, $path="syslog", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SYSLOG, ports);
}

View file

@ -7,6 +7,8 @@ module Unified2;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## File to watch for Unified2 files.
const watch_file = "" &redef;
@ -195,7 +197,7 @@ event Input::end_of_data(name: string, source: string)
event zeek_init() &priority=5
{
Log::create_stream(Unified2::LOG, [$columns=Info, $ev=log_unified2, $path="unified2"]);
Log::create_stream(Unified2::LOG, [$columns=Info, $ev=log_unified2, $path="unified2", $policy=log_policy]);
if ( sid_msg == "" )
{

View file

@ -8,6 +8,8 @@ module OCSP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the OCSP log.
type Info: record {
## Time when the OCSP reply was encountered.
@ -41,7 +43,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(LOG, [$columns=Info, $ev=log_ocsp, $path="ocsp"]);
Log::create_stream(LOG, [$columns=Info, $ev=log_ocsp, $path="ocsp", $policy=log_policy]);
Files::register_for_mime_type(Files::ANALYZER_OCSP_REPLY, "application/ocsp-response");
}

View file

@ -9,6 +9,8 @@ export {
redef enum Log::ID += { CATCH_RELEASE };
global log_policy_catch_release: Log::PolicyHook;
## This record is used for storing information about current blocks that are
## part of catch and release.
type BlockInfo: record {
@ -164,7 +166,7 @@ global catch_release_recently_notified: set[addr] &create_expire=30secs;
event zeek_init() &priority=5
{
Log::create_stream(NetControl::CATCH_RELEASE, [$columns=CatchReleaseInfo, $ev=log_netcontrol_catch_release, $path="netcontrol_catch_release"]);
Log::create_stream(NetControl::CATCH_RELEASE, [$columns=CatchReleaseInfo, $ev=log_netcontrol_catch_release, $path="netcontrol_catch_release", $policy=log_policy_catch_release]);
}
function get_watch_interval(current_interval: count): interval

View file

@ -9,6 +9,8 @@ module Barnyard2;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Timestamp of the alert.
ts: time &log;
@ -26,7 +28,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(Barnyard2::LOG, [$columns=Info, $path="barnyard2"]);
Log::create_stream(Barnyard2::LOG, [$columns=Info, $path="barnyard2", $policy=log_policy]);
}

View file

@ -14,6 +14,8 @@ module CaptureLoss;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
redef enum Notice::Type += {
## Report if the detected capture loss exceeds the percentage
## threshold.
@ -76,7 +78,7 @@ event CaptureLoss::take_measurement(last_ts: time, last_acks: count, last_gaps:
event zeek_init() &priority=5
{
Log::create_stream(LOG, [$columns=Info, $path="capture_loss"]);
Log::create_stream(LOG, [$columns=Info, $path="capture_loss", $policy=log_policy]);
# We only schedule the event if we are capturing packets.
if ( reading_live_traffic() || reading_traces() )

View file

@ -14,6 +14,8 @@ module Traceroute;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
redef enum Notice::Type += {
## Indicates that a host was seen running traceroutes. For more
## detail about specific traceroutes that we run, refer to the
@ -55,7 +57,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(Traceroute::LOG, [$columns=Info, $ev=log_traceroute, $path="traceroute"]);
Log::create_stream(Traceroute::LOG, [$columns=Info, $ev=log_traceroute, $path="traceroute", $policy=log_policy]);
local r1: SumStats::Reducer = [$stream="traceroute.time_exceeded", $apply=set(SumStats::UNIQUE)];
local r2: SumStats::Reducer = [$stream="traceroute.low_ttl_packet", $apply=set(SumStats::SUM)];

View file

@ -6,6 +6,8 @@ module LoadedScripts;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
type Info: record {
## Name of the script loaded potentially with spaces included
## before the file name to indicate load depth. The convention
@ -29,7 +31,7 @@ function get_indent(level: count): string
event zeek_init() &priority=5
{
Log::create_stream(LoadedScripts::LOG, [$columns=Info, $path="loaded_scripts"]);
Log::create_stream(LoadedScripts::LOG, [$columns=Info, $path="loaded_scripts", $policy=log_policy]);
}
event zeek_script_loaded(path: string, level: count)

View file

@ -7,6 +7,8 @@ module Stats;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## How often stats are reported.
option report_interval = 5min;
@ -84,7 +86,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(Stats::LOG, [$columns=Info, $ev=log_stats, $path="stats"]);
Log::create_stream(Stats::LOG, [$columns=Info, $ev=log_stats, $path="stats", $policy=log_policy]);
}
event check_stats(then: time, last_ns: NetStats, last_cs: ConnStats, last_ps: ProcStats, last_es: EventStats, last_rs: ReassemblerStats, last_ts: TimerStats, last_fs: FileAnalysisStats, last_ds: DNSStats)

View file

@ -8,6 +8,8 @@ module WeirdStats;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## How often stats are reported.
const weird_stat_interval = 15min &redef;
@ -55,7 +57,7 @@ event zeek_init() &priority=5
{
Log::create_stream(WeirdStats::LOG,
[$columns = Info, $ev = log_weird_stats,
$path="weird_stats"]);
$path="weird_stats", $policy=log_policy]);
local r1 = SumStats::Reducer($stream = "weirds.encountered",
$apply = set(SumStats::SUM));
SumStats::create([$name = "weirds.statistics",

View file

@ -12,6 +12,9 @@ export {
## The known-hosts logging stream identifier.
redef enum Log::ID += { HOSTS_LOG };
## A default logging policy hook for the stream.
global log_policy_hosts: Log::PolicyHook;
## The record type which contains the column fields of the known-hosts log.
type HostsInfo: record {
## The timestamp at which the host was detected.
@ -147,7 +150,7 @@ event Known::host_found(info: HostsInfo)
event zeek_init() &priority=5
{
Log::create_stream(Known::HOSTS_LOG, [$columns=HostsInfo, $ev=log_known_hosts, $path="known_hosts"]);
Log::create_stream(Known::HOSTS_LOG, [$columns=HostsInfo, $ev=log_known_hosts, $path="known_hosts", $policy=log_policy_hosts]);
}
event connection_established(c: connection) &priority=5

View file

@ -15,6 +15,9 @@ export {
## The known-services logging stream identifier.
redef enum Log::ID += { SERVICES_LOG };
## A default logging policy hook for the stream.
global log_policy_services: Log::PolicyHook;
## The record type which contains the column fields of the known-services
## log.
type ServicesInfo: record {
@ -308,6 +311,7 @@ event zeek_init() &priority=5
{
Log::create_stream(Known::SERVICES_LOG, [$columns=ServicesInfo,
$ev=log_known_services,
$path="known_services"]);
$path="known_services",
$policy=log_policy_services]);
}

View file

@ -11,6 +11,8 @@ module Known;
export {
redef enum Log::ID += { MODBUS_LOG };
global log_policy_modbus: Log::PolicyHook;
type ModbusDeviceType: enum {
MODBUS_MASTER,
MODBUS_SLAVE,
@ -35,7 +37,7 @@ export {
event zeek_init() &priority=5
{
Log::create_stream(Known::MODBUS_LOG, [$columns=ModbusInfo, $ev=log_known_modbus, $path="known_modbus"]);
Log::create_stream(Known::MODBUS_LOG, [$columns=ModbusInfo, $ev=log_known_modbus, $path="known_modbus", $policy=log_policy_modbus]);
}
event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool)

View file

@ -11,6 +11,8 @@ module Modbus;
export {
redef enum Log::ID += { Modbus::REGISTER_CHANGE_LOG };
global log_policy_register_change: Log::PolicyHook;
## The hosts that should have memory mapping enabled.
option track_memmap: Host = ALL_HOSTS;
@ -54,7 +56,7 @@ redef record Modbus::Info += {
event zeek_init() &priority=5
{
Log::create_stream(Modbus::REGISTER_CHANGE_LOG, [$columns=MemmapInfo, $path="modbus_register_change"]);
Log::create_stream(Modbus::REGISTER_CHANGE_LOG, [$columns=MemmapInfo, $path="modbus_register_change", $policy=log_policy_register_change]);
}
event modbus_read_holding_registers_request(c: connection, headers: ModbusHeaders, start_address: count, quantity: count)

View file

@ -12,6 +12,10 @@ export {
PUBLISH_LOG,
};
global log_policy_connect: Log::PolicyHook;
global log_policy_subscribe: Log::PolicyHook;
global log_policy_publish: Log::PolicyHook;
type MQTT::SubUnsub: enum {
MQTT::SUBSCRIBE,
MQTT::UNSUBSCRIBE,
@ -146,9 +150,9 @@ redef likely_server_ports += { ports };
event zeek_init() &priority=5
{
Log::create_stream(MQTT::CONNECT_LOG, [$columns=ConnectInfo, $ev=log_mqtt, $path="mqtt_connect"]);
Log::create_stream(MQTT::SUBSCRIBE_LOG, [$columns=SubscribeInfo, $path="mqtt_subscribe"]);
Log::create_stream(MQTT::PUBLISH_LOG, [$columns=PublishInfo, $path="mqtt_publish"]);
Log::create_stream(MQTT::CONNECT_LOG, [$columns=ConnectInfo, $ev=log_mqtt, $path="mqtt_connect", $policy=log_policy_connect]);
Log::create_stream(MQTT::SUBSCRIBE_LOG, [$columns=SubscribeInfo, $path="mqtt_subscribe", $policy=log_policy_subscribe]);
Log::create_stream(MQTT::PUBLISH_LOG, [$columns=PublishInfo, $path="mqtt_publish", $policy=log_policy_publish]);
Analyzer::register_for_ports(Analyzer::ANALYZER_MQTT, ports);
}

View file

@ -10,6 +10,8 @@ export {
CMD_LOG,
};
global log_policy: Log::PolicyHook;
## The server response statuses which are *not* logged.
option ignored_command_statuses: set[string] = {
"MORE_PROCESSING_REQUIRED",
@ -27,7 +29,7 @@ const deferred_logging_cmds: set[string] = {
event zeek_init() &priority=5
{
Log::create_stream(SMB::CMD_LOG, [$columns=SMB::CmdInfo, $path="smb_cmd"]);
Log::create_stream(SMB::CMD_LOG, [$columns=SMB::CmdInfo, $path="smb_cmd", $policy=log_policy]);
}
event smb1_message(c: connection, hdr: SMB1::Header, is_orig: bool) &priority=-5

View file

@ -11,6 +11,8 @@ module Known;
export {
redef enum Log::ID += { CERTS_LOG };
global log_policy_certs: Log::PolicyHook;
type CertsInfo: record {
## The timestamp when the certificate was detected.
ts: time &log;
@ -195,5 +197,5 @@ event ssl_established(c: connection) &priority=3
event zeek_init() &priority=5
{
Log::create_stream(Known::CERTS_LOG, [$columns=CertsInfo, $ev=log_known_certs, $path="known_certs"]);
Log::create_stream(Known::CERTS_LOG, [$columns=CertsInfo, $ev=log_known_certs, $path="known_certs", $policy=log_policy_certs]);
}

View file

@ -35,6 +35,7 @@ struct Manager::Filter {
Val* fval;
string name;
EnumVal* id;
Func* policy;
Func* pred;
Func* path_func;
string path;
@ -81,6 +82,7 @@ struct Manager::Stream {
string name;
RecordType* columns;
EventHandlerPtr event;
Func* policy;
list<Filter*> filters;
typedef pair<int, string> WriterPathPair;
@ -272,6 +274,9 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval)
const auto& event_val = sval->GetField("ev");
Func* event = event_val ? event_val->AsFunc() : nullptr;
const auto& policy_val = sval->GetField("policy");
Func* policy = policy_val ? policy_val->AsFunc() : nullptr;
if ( event )
{
// Make sure the event is prototyped as expected.
@ -316,6 +321,7 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval)
streams[idx]->enabled = true;
streams[idx]->name = id->GetType()->AsEnumType()->Lookup(idx);
streams[idx]->event = event ? event_registry->Lookup(event->Name()) : nullptr;
streams[idx]->policy = policy;
streams[idx]->columns = columns->Ref()->AsRecordType();
streams[idx]->enable_remote = id::find_val("Log::enable_remote_logging")->AsBool();
@ -550,6 +556,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval)
// Create a new Filter instance.
auto name = fval->GetFieldOrDefault("name");
auto policy = fval->GetFieldOrDefault("policy");
auto pred = fval->GetFieldOrDefault("pred");
auto path_func = fval->GetFieldOrDefault("path_func");
auto log_local = fval->GetFieldOrDefault("log_local");
@ -566,6 +573,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval)
filter->fval = fval->Ref();
filter->name = name->AsString()->CheckString();
filter->id = id->Ref()->AsEnumVal();
filter->policy = policy ? policy->AsFunc() : stream->policy;
filter->pred = pred ? pred->AsFunc() : nullptr;
filter->path_func = path_func ? path_func->AsFunc() : nullptr;
filter->writer = writer->Ref()->AsEnumVal();
@ -648,6 +656,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval)
DBG_LOG(DBG_LOGGING, " writer : %s", desc.Description());
DBG_LOG(DBG_LOGGING, " path : %s", filter->path.c_str());
DBG_LOG(DBG_LOGGING, " path_func : %s", (filter->path_func ? "set" : "not set"));
DBG_LOG(DBG_LOGGING, " policy : %s", (filter->policy ? "set" : "not set"));
DBG_LOG(DBG_LOGGING, " pred : %s", (filter->pred ? "set" : "not set"));
for ( int i = 0; i < filter->num_fields; i++ )
@ -721,17 +730,29 @@ bool Manager::Write(EnumVal* id, RecordVal* columns_arg)
Filter* filter = *i;
string path = filter->path;
// Policy hooks may veto the logging or alter the log
// record if really necessary. Potential optimization:
// don't invoke the hook at all when it has no
// handlers/bodies. Doing this skips sampling and
// plugin hooks, though, so for now we do invoke.
if ( filter->policy )
{
auto v = filter->policy->Invoke(columns,
IntrusivePtr{NewRef{}, id},
IntrusivePtr{NewRef{}, filter->fval});
if ( v && ! v->AsBool() )
continue;
}
// $pred is deprecated and will get removed in 4.1.
// This block can go when that time comes.
if ( filter->pred )
{
// See whether the predicates indicates that we want
// See whether the predicate indicates that we want
// to log this record.
int result = 1;
auto v = filter->pred->Invoke(columns);
if ( v )
result = v->AsBool();
if ( ! result )
if ( v && ! v->AsBool() )
continue;
}