cleanup(userspace/engine): drop filtr_evttype_resolver

Its logic was ported into libsinsp in:
3d8550e70e

Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
This commit is contained in:
Jason Dellaluce
2023-02-17 11:13:12 +00:00
committed by poiana
parent e54eda16f7
commit 34ea7a8245
4 changed files with 0 additions and 712 deletions

View File

@@ -1,231 +0,0 @@
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <gtest/gtest.h>
#include <engine/filter_evttype_resolver.h>
#include <sinsp.h>
#include <filter/parser.h>
#define ASSERT_FILTER_EQ(a, b) { ASSERT_EQ(get_filter_set(a), get_filter_set(b)); }
std::set<uint16_t> get_filter_set(const string &fltstr)
{
set<uint16_t> actual;
auto f = libsinsp::filter::parser(fltstr).parse();
filter_evttype_resolver().evttypes(f.get(), actual);
return actual;
}
std::set<uint16_t> get_set_difference(std::set<uint16_t> exclude_set = {})
{
std::set<uint16_t> set_difference = {};
for(uint32_t i = PPME_GENERIC_E; i < PPM_EVENT_MAX; i++)
{
/* Skip events that are unused. */
if(sinsp::is_unused_event(i))
{
continue;
}
if(exclude_set.find(i) == exclude_set.end())
{
set_difference.insert(i);
}
}
return set_difference;
}
TEST(EvtTypeResolver, check_openat)
{
std::set<uint16_t> openat_only{
PPME_SYSCALL_OPENAT_E, PPME_SYSCALL_OPENAT_X,
PPME_SYSCALL_OPENAT_2_E, PPME_SYSCALL_OPENAT_2_X};
std::set<uint16_t> not_openat = get_set_difference(openat_only);
/* `openat_only` */
ASSERT_EQ(get_filter_set("evt.type=openat"), openat_only);
ASSERT_EQ(get_filter_set("evt.type = openat"), openat_only);
ASSERT_EQ(get_filter_set("not evt.type != openat"), openat_only);
ASSERT_EQ(get_filter_set("not not evt.type = openat"), openat_only);
ASSERT_EQ(get_filter_set("not not not not evt.type = openat"), openat_only);
ASSERT_EQ(get_filter_set("evt.type in (openat)"), openat_only);
ASSERT_EQ(get_filter_set("not (not evt.type=openat)"), openat_only);
ASSERT_EQ(get_filter_set("evt.type=openat and proc.name=nginx"), openat_only);
ASSERT_EQ(get_filter_set("evt.type=openat and not proc.name=nginx"), openat_only);
ASSERT_EQ(get_filter_set("evt.type=openat and (proc.name=nginx)"), openat_only);
ASSERT_EQ(get_filter_set("evt.type=openat and not (evt.type=close and proc.name=nginx)"), openat_only);
/* `not_openat` */
ASSERT_EQ(get_filter_set("evt.type!=openat"), not_openat);
ASSERT_EQ(get_filter_set("not not not evt.type = openat"), not_openat);
ASSERT_EQ(get_filter_set("not evt.type=openat"), not_openat);
ASSERT_EQ(get_filter_set("evt.type=close or evt.type!=openat"), not_openat);
}
TEST(EvtTypeResolver, check_openat_or_close)
{
std::set<uint16_t> openat_close_only{
PPME_SYSCALL_OPENAT_E, PPME_SYSCALL_OPENAT_X,
PPME_SYSCALL_OPENAT_2_E, PPME_SYSCALL_OPENAT_2_X,
PPME_SYSCALL_CLOSE_E, PPME_SYSCALL_CLOSE_X};
std::set<uint16_t> not_openat_close = get_set_difference(openat_close_only);
/* `openat_close_only` */
ASSERT_EQ(get_filter_set("evt.type in (openat, close)"), openat_close_only);
ASSERT_EQ(get_filter_set("evt.type=openat or evt.type=close"), openat_close_only);
ASSERT_EQ(get_filter_set("evt.type=openat or (evt.type=close and proc.name=nginx)"), openat_close_only);
ASSERT_EQ(get_filter_set("evt.type=close or (evt.type=openat and proc.name=nginx)"), openat_close_only);
/* not `not_openat_close` */
ASSERT_EQ(get_filter_set("not evt.type in (openat, close)"), not_openat_close);
ASSERT_EQ(get_filter_set("not not not evt.type in (openat, close)"), not_openat_close);
ASSERT_EQ(get_filter_set("evt.type!=openat and evt.type!=close"), not_openat_close);
}
TEST(EvtTypeResolver, check_all_events)
{
/* Computed as a difference of the empty set */
std::set<uint16_t> all_events = get_set_difference();
ASSERT_EQ(get_filter_set("evt.type!=openat or evt.type!=close"), all_events);
ASSERT_EQ(get_filter_set("proc.name=nginx"), all_events);
ASSERT_EQ(get_filter_set("evt.type=openat or proc.name=nginx"), all_events);
ASSERT_EQ(get_filter_set("evt.type=openat or (proc.name=nginx)"), all_events);
ASSERT_EQ(get_filter_set("(evt.type=openat) or proc.name=nginx"), all_events);
ASSERT_EQ(get_filter_set("evt.type=close or not (evt.type=openat and proc.name=nginx)"), all_events);
ASSERT_EQ(get_filter_set("evt.type=openat or not (evt.type=close and proc.name=nginx)"), all_events);
}
TEST(EvtTypeResolver, check_no_events)
{
std::set<uint16_t> no_events = {};
ASSERT_EQ(get_filter_set("evt.type=close and evt.type=openat"), no_events);
ASSERT_EQ(get_filter_set("evt.type=openat and (evt.type=close and proc.name=nginx)"), no_events);
ASSERT_EQ(get_filter_set("evt.type=openat and (evt.type=close)"), no_events);
}
TEST(EvtTypeResolver, check_properties)
{
std::set<uint16_t> no_events = {};
// see: https://github.com/falcosecurity/libs/pull/854#issuecomment-1411151732
ASSERT_FILTER_EQ(
"evt.type in (connect, execve, accept, mmap, container) and not (proc.name=cat and evt.type=mmap)",
"evt.type in (accept, connect, container, execve, mmap)");
ASSERT_EQ(get_filter_set("(evt.type=mmap and not evt.type=mmap)"), no_events);
// defining algebraic base sets
std::string zerof = "(evt.type in ())"; ///< "zero"-set: no evt type should matches the filter
std::string onef = "(evt.type exists)"; ///< "one"-set: all evt types should match the filter
std::string neutral1 = "(proc.name=cat)"; ///< "neutral"-sets: evt types are not checked in the filter
std::string neutral2 = "(not proc.name=cat)";
ASSERT_FILTER_EQ(onef, neutral1);
ASSERT_FILTER_EQ(onef, neutral2);
// algebraic set properties
// 1' = 0
ASSERT_FILTER_EQ("not " + onef, zerof);
// 0' = 1
ASSERT_FILTER_EQ("not " + zerof, onef);
// (A')' = A
ASSERT_FILTER_EQ("evt.type=mmap", "not (not evt.type=mmap)");
// A * A' = 0
ASSERT_EQ(get_filter_set(zerof), no_events);
// A + A' = 1
ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", onef);
ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", neutral1);
ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", neutral2);
// 0 * 1 = 0
ASSERT_FILTER_EQ(zerof + " and " + onef, zerof);
ASSERT_FILTER_EQ(zerof + " and " + neutral1, zerof);
ASSERT_FILTER_EQ(zerof + " and " + neutral2, zerof);
// 0 + 1 = 1
ASSERT_FILTER_EQ(zerof + " or " + onef, onef);
ASSERT_FILTER_EQ(zerof + " or " + neutral1, onef);
ASSERT_FILTER_EQ(zerof + " or " + neutral2, onef);
// A * 0 = 0
ASSERT_FILTER_EQ("evt.type=mmap and " + zerof, zerof);
// A * 1 = A
ASSERT_FILTER_EQ("evt.type=mmap and " + onef, "evt.type=mmap");
ASSERT_FILTER_EQ("evt.type=mmap and " + neutral1, "evt.type=mmap");
ASSERT_FILTER_EQ("evt.type=mmap and " + neutral2, "evt.type=mmap");
// A + 0 = A
ASSERT_FILTER_EQ("evt.type=mmap or " + zerof, "evt.type=mmap");
// A + 1 = 1
ASSERT_FILTER_EQ("evt.type=mmap or " + onef, onef);
ASSERT_FILTER_EQ("evt.type=mmap or " + neutral1, onef);
ASSERT_FILTER_EQ("evt.type=mmap or " + neutral2, onef);
// A + A = A
ASSERT_FILTER_EQ("evt.type=mmap or evt.type=mmap", "evt.type=mmap");
// A * A = A
ASSERT_FILTER_EQ("evt.type=mmap and evt.type=mmap", "evt.type=mmap");
// de morgan's laws
ASSERT_FILTER_EQ(
"not (proc.name=cat or evt.type=mmap)",
"not proc.name=cat and not evt.type=mmap");
ASSERT_FILTER_EQ(
"not (proc.name=cat or fd.type=file)",
"not proc.name=cat and not fd.type=file");
ASSERT_FILTER_EQ(
"not (evt.type=execve or evt.type=mmap)",
"not evt.type=execve and not evt.type=mmap");
ASSERT_FILTER_EQ(
"not (evt.type=mmap or evt.type=mmap)",
"not evt.type=mmap and not evt.type=mmap");
ASSERT_FILTER_EQ(
"not (proc.name=cat and evt.type=mmap)",
"not proc.name=cat or not evt.type=mmap");
ASSERT_FILTER_EQ(
"not (proc.name=cat and fd.type=file)",
"not proc.name=cat or not fd.type=file");
ASSERT_FILTER_EQ(
"not (evt.type=execve and evt.type=mmap)",
"not evt.type=execve or not evt.type=mmap");
ASSERT_FILTER_EQ(
"not (evt.type=mmap and evt.type=mmap)",
"not evt.type=mmap or not evt.type=mmap");
// negation isomorphism
ASSERT_FILTER_EQ("not evt.type=mmap", "evt.type!=mmap");
ASSERT_FILTER_EQ("not proc.name=cat", "proc.name!=cat");
// commutative property (and)
ASSERT_FILTER_EQ("evt.type=execve and evt.type=mmap", "evt.type=mmap and evt.type=execve");
ASSERT_FILTER_EQ("not (evt.type=execve and evt.type=mmap)", "not (evt.type=mmap and evt.type=execve)");
ASSERT_FILTER_EQ("not evt.type=execve and not evt.type=mmap", "not evt.type=mmap and not evt.type=execve");
ASSERT_FILTER_EQ("proc.name=cat and evt.type=mmap", "evt.type=mmap and proc.name=cat");
ASSERT_FILTER_EQ("not (proc.name=cat and evt.type=mmap)", "not (evt.type=mmap and proc.name=cat)");
ASSERT_FILTER_EQ("not proc.name=cat and not evt.type=mmap", "not evt.type=mmap and not proc.name=cat");
ASSERT_FILTER_EQ("proc.name=cat and fd.type=file", "fd.type=file and proc.name=cat");
ASSERT_FILTER_EQ("not (proc.name=cat and fd.type=file)", "not (fd.type=file and proc.name=cat)");
ASSERT_FILTER_EQ("not proc.name=cat and not fd.type=file", "not fd.type=file and not proc.name=cat");
// commutative property (or)
ASSERT_FILTER_EQ("evt.type=execve or evt.type=mmap", "evt.type=mmap or evt.type=execve");
ASSERT_FILTER_EQ("not (evt.type=execve or evt.type=mmap)", "not (evt.type=mmap or evt.type=execve)");
ASSERT_FILTER_EQ("not evt.type=execve or not evt.type=mmap", "not evt.type=mmap or not evt.type=execve");
ASSERT_FILTER_EQ("proc.name=cat or evt.type=mmap", "evt.type=mmap or proc.name=cat");
ASSERT_FILTER_EQ("not (proc.name=cat or evt.type=mmap)", "not (evt.type=mmap or proc.name=cat)");
ASSERT_FILTER_EQ("not proc.name=cat or not evt.type=mmap", "not evt.type=mmap or not proc.name=cat");
ASSERT_FILTER_EQ("proc.name=cat or fd.type=file", "fd.type=file or proc.name=cat");
ASSERT_FILTER_EQ("not (proc.name=cat or fd.type=file)", "not (fd.type=file or proc.name=cat)");
ASSERT_FILTER_EQ("not proc.name=cat or not fd.type=file", "not fd.type=file or not proc.name=cat");
}

View File

@@ -19,7 +19,6 @@ set(FALCO_ENGINE_SOURCE_FILES
evttype_index_ruleset.cpp
formats.cpp
filter_macro_resolver.cpp
filter_evttype_resolver.cpp
filter_warning_resolver.cpp
stats_manager.cpp
rule_loader.cpp

View File

@@ -1,253 +0,0 @@
/*
Copyright (C) 2022 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "filter_evttype_resolver.h"
#include <sinsp.h>
/**
* Given a rule filtering condition (in AST form), the following logic is
* responsible of returning the set of event types for which the
* filtering condition can be evaluated to true.
*
* This implementation is based on the boolean algebraic properties of sets
* and works as follows depending on the type of nodes:
* - the evt types of "and" nodes are the intersection set of the evt types of
* their children nodes.
* - the evt types of "or" nodes are the union set of the evt types of
* their children nodes.
* - the evt types of leaf nodes (e.g. "evt.type=open" or "proc.name=cat")
* depend on the type of check:
* * checks based on evt types (e.g. =xxx, != xxx, in (xxx)) give a clear
* definition of the matched event types. The "evt.type exists" check
* matches every evt type.
* * checks non-related to evt types are neutral and match all evt types
* (e.g. proc.name=cat).
*
* The tricky part is handling negation (e.g. "not evt.type=open").
* Given a set of event types, its negation is the difference between the
* "set of all events" and the set (e.g. all types but not the ones in the set).
* Reasonably, negation should not affect checks unrelated to evt types (e.g.
* "proc.name=cat" is equivalent to "not proc.name=cat" for evt type matching).
* The knowledge of whether a set of event types should be negated or not
* can't be handled nor propagated in "and" and "or" nodes. Since rules'
* conditions are boolean expression, the solution is to use De Morgan's Laws
* to push the negation evaluations down to the leaf nodes as follows:
* - "not (A and B)" is evaluated as "not A or not B"
* - "not (A or B)" is evaluated as "not A and not B"
* By happening only on leaf nodes, the set of matching event types can safely
* be constructed and negated depending on the different cases.
*/
using namespace libsinsp::filter;
extern sinsp_evttables g_infotables;
static bool is_evttype_operator(const std::string& op)
{
return op == "==" || op == "=" || op == "!=" || op == "in";
}
size_t falco_event_types::get_ppm_event_max()
{
return PPM_EVENT_MAX;
}
void filter_evttype_resolver::visitor::inversion(falco_event_types& types)
{
// we don't invert "neutral" checks
if (m_last_node_has_evttypes)
{
types = m_all_events.diff(types);
}
}
void filter_evttype_resolver::visitor::try_inversion(falco_event_types& types)
{
if (m_inside_negation)
{
inversion(types);
}
}
void filter_evttype_resolver::visitor::evttypes(const std::string& evtname, falco_event_types& out)
{
for(uint16_t i = PPME_GENERIC_E; i < PPM_EVENT_MAX; i++)
{
// Skip unused events
if(sinsp::is_unused_event(i))
{
continue;
}
// Fetch event names associated with event id
const auto evtnames = m_inspector.get_events_names({i});
for (const auto& name : evtnames)
{
// Skip events not matching the requested evtname
if(evtname.empty() || name == evtname)
{
out.insert(i);
}
}
}
}
void filter_evttype_resolver::evttypes(
ast::expr* filter,
std::set<uint16_t>& out) const
{
visitor v;
filter->accept(&v);
v.m_last_node_evttypes.for_each([&out](uint16_t val){out.insert(val); return true;});
}
void filter_evttype_resolver::evttypes(
std::shared_ptr<ast::expr> filter,
std::set<uint16_t>& out) const
{
evttypes(filter.get(), out);
}
void filter_evttype_resolver::visitor::conjunction(
const std::vector<std::unique_ptr<ast::expr>>& children)
{
falco_event_types types = m_all_events;
m_last_node_evttypes.clear();
for (auto &c : children)
{
c->accept(this);
types = types.intersect(m_last_node_evttypes);
}
m_last_node_evttypes = types;
}
void filter_evttype_resolver::visitor::disjunction(
const std::vector<std::unique_ptr<ast::expr>>& children)
{
falco_event_types types;
m_last_node_evttypes.clear();
for (auto &c : children)
{
c->accept(this);
types.merge(m_last_node_evttypes);
}
m_last_node_evttypes = types;
}
void filter_evttype_resolver::visitor::visit(ast::and_expr* e)
{
if (m_inside_negation)
{
disjunction(e->children);
}
else
{
conjunction(e->children);
}
}
void filter_evttype_resolver::visitor::visit(ast::or_expr* e)
{
if (m_inside_negation)
{
conjunction(e->children);
}
else
{
disjunction(e->children);
}
}
void filter_evttype_resolver::visitor::visit(ast::not_expr* e)
{
m_last_node_evttypes.clear();
auto inside_negation = m_inside_negation;
m_inside_negation = !m_inside_negation;
e->child->accept(this);
m_inside_negation = inside_negation;
}
void filter_evttype_resolver::visitor::visit(ast::binary_check_expr* e)
{
m_last_node_evttypes.clear();
m_last_node_has_evttypes = false;
if (e->field == "evt.type" && is_evttype_operator(e->op))
{
// note: we expect m_inside_negation and m_last_node_has_evttypes
// to be handled and altered by the child node
m_expect_value = true;
e->value->accept(this);
m_expect_value = false;
if (e->op == "!=")
{
// note: since we push the "negation" down to the tree leaves
// (following de morgan's laws logic), the child node may have
// already inverted the set of matched event type. As such,
// inverting here again is safe for supporting both the
// single-negation and double-negation cases.
inversion(m_last_node_evttypes);
}
return;
}
m_last_node_evttypes = m_all_events;
try_inversion(m_last_node_evttypes);
}
void filter_evttype_resolver::visitor::visit(ast::unary_check_expr* e)
{
m_last_node_evttypes.clear();
m_last_node_has_evttypes = e->field == "evt.type" && e->op == "exists";
m_last_node_evttypes = m_all_events;
try_inversion(m_last_node_evttypes);
}
void filter_evttype_resolver::visitor::visit(ast::value_expr* e)
{
m_last_node_evttypes.clear();
m_last_node_has_evttypes = m_expect_value;
if (m_expect_value)
{
evttypes(e->value, m_last_node_evttypes);
}
else
{
// this case only happens if a macro has not yet been substituted
// with an actual condition. Should not happen, but we handle it
// for consistency.
m_last_node_evttypes = m_all_events;
}
try_inversion(m_last_node_evttypes);
}
void filter_evttype_resolver::visitor::visit(ast::list_expr* e)
{
m_last_node_evttypes.clear();
m_last_node_has_evttypes = false;
if (m_expect_value)
{
m_last_node_has_evttypes = true;
for (auto &v : e->values)
{
evttypes(v, m_last_node_evttypes);
}
try_inversion(m_last_node_evttypes);
return;
}
m_last_node_evttypes = m_all_events;
try_inversion(m_last_node_evttypes);
}

View File

@@ -1,227 +0,0 @@
/*
Copyright (C) 2022 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <filter/parser.h>
#include <string>
#include <set>
#include <memory>
#include <functional>
#include <stdexcept>
#include <sinsp.h>
class falco_event_types
{
private:
using vec_t = std::vector<uint8_t>;
vec_t m_types{};
static inline void check_range(uint16_t e)
{
static const auto enum_max = get_ppm_event_max();
if(e > enum_max)
{
throw std::range_error("invalid event type");
}
}
public:
falco_event_types(falco_event_types&&) = default;
falco_event_types(const falco_event_types&) = default;
falco_event_types& operator=(falco_event_types&&) = default;
falco_event_types& operator=(const falco_event_types&) = default;
static size_t get_ppm_event_max();
inline falco_event_types():
m_types(get_ppm_event_max() + 1, 0)
{
}
inline void insert(uint16_t e)
{
check_range(e);
m_types[e] = 1;
}
void merge(const falco_event_types& other)
{
for(size_t i = 0; i <= get_ppm_event_max(); ++i)
{
m_types[i] |= other.m_types[i];
}
}
void merge(const std::set<uint16_t>& other)
{
for(const auto& e : other)
{
insert(e);
}
}
inline bool contains(uint16_t e) const
{
check_range(e);
return m_types[e] != 0;
}
void clear()
{
for(auto& v : m_types)
{
v = 0;
}
}
bool equals(const falco_event_types& other) const
{
return m_types == other.m_types;
}
falco_event_types diff(const falco_event_types& other) const
{
falco_event_types ret;
for(size_t i = 0; i <= get_ppm_event_max(); ++i)
{
if(m_types[i] == 1 && other.m_types[i] == 0)
{
ret.m_types[i] = 1;
}
}
return ret;
}
falco_event_types intersect(const falco_event_types& other) const
{
falco_event_types ret;
for(size_t i = 0; i <= get_ppm_event_max(); ++i)
{
if(m_types[i] == 1 && other.m_types[i] == 1)
{
ret.m_types[i] = 1;
}
}
return ret;
}
void for_each(std::function<bool(uint16_t)> consumer) const
{
for(uint16_t i = 0; i < m_types.size(); ++i)
{
if(m_types[i] != 0)
{
if(!consumer(i))
{
return;
}
}
}
}
};
inline bool operator==(const falco_event_types& lhs, const falco_event_types& rhs)
{
return lhs.equals(rhs);
}
inline bool operator!=(const falco_event_types& lhs, const falco_event_types& rhs)
{
return !(lhs == rhs);
}
/*!
\brief Helper class for finding event types
*/
class filter_evttype_resolver
{
public:
/*!
\brief Collects the evttypes related to the provided event name.
The event types are inserted in the set provided as parameter.
The set is not cleared before inserting the elements.
\param evtname The event name used to search event types. If an empty
string is passed, all the available evttypes are collected
\param out The set to be filled with the evttypes
*/
inline void evttypes(const std::string& evtname, falco_event_types& out) const
{
falco_event_types evt_types;
visitor().evttypes(evtname, evt_types);
evt_types.for_each([&out](uint16_t val)
{out.insert(val); return true; });
}
/*!
\brief Visits a filter AST and collects all the evttypes for which
the filter expression can be evaluated as true. The event types are
inserted in the set provided as parameter. The set is not cleared before
inserting the elements.
\param filter The filter AST to be explored
\param out The set to be filled with the evttypes
*/
void evttypes(
libsinsp::filter::ast::expr* filter,
std::set<uint16_t>& out) const;
/*!
\brief Overloaded version of evttypes() that supports filters wrapped
in shared pointers
*/
void evttypes(
std::shared_ptr<libsinsp::filter::ast::expr> filter,
std::set<uint16_t>& out) const;
private:
struct visitor : public libsinsp::filter::ast::expr_visitor
{
visitor():
m_expect_value(false),
m_inside_negation(false),
m_last_node_has_evttypes(false),
m_last_node_evttypes({}),
m_all_events({}),
m_inspector()
{
evttypes("", m_all_events);
}
visitor(visitor&&) = default;
visitor& operator = (visitor&&) = default;
visitor(const visitor&) = default;
visitor& operator = (const visitor&) = default;
bool m_expect_value;
bool m_inside_negation;
bool m_last_node_has_evttypes;
falco_event_types m_last_node_evttypes;
falco_event_types m_all_events;
sinsp m_inspector;
void visit(libsinsp::filter::ast::and_expr* e) override;
void visit(libsinsp::filter::ast::or_expr* e) override;
void visit(libsinsp::filter::ast::not_expr* e) override;
void visit(libsinsp::filter::ast::value_expr* e) override;
void visit(libsinsp::filter::ast::list_expr* e) override;
void visit(libsinsp::filter::ast::unary_check_expr* e) override;
void visit(libsinsp::filter::ast::binary_check_expr* e) override;
void try_inversion(falco_event_types& types);
void inversion(falco_event_types& types);
void evttypes(const std::string& evtname, falco_event_types& out);
void conjunction(const std::vector<std::unique_ptr<libsinsp::filter::ast::expr>>&);
void disjunction(const std::vector<std::unique_ptr<libsinsp::filter::ast::expr>>&);
};
};