Refactor misc. Supervisor code

E.g. mostly to start taking advantage of C++17 things like
std::optional.  Also IntrusivePtr.
This commit is contained in:
Jon Siwek 2019-11-05 19:29:43 -08:00
parent c43ffc14fe
commit 8aa77436f9
5 changed files with 116 additions and 121 deletions

View file

@ -148,7 +148,8 @@ void net_update_time(double new_network_time)
void net_init(const std::vector<std::string>& interfaces, void net_init(const std::vector<std::string>& interfaces,
const std::vector<std::string>& pcap_input_files, const std::vector<std::string>& pcap_input_files,
const std::string& pcap_output_file, bool do_watchdog) const std::optional<std::string>& pcap_output_file,
bool do_watchdog)
{ {
if ( ! pcap_input_files.empty() ) if ( ! pcap_input_files.empty() )
{ {
@ -189,9 +190,9 @@ void net_init(const std::vector<std::string>& interfaces,
// a timer. // a timer.
reading_traces = reading_live = 0; reading_traces = reading_live = 0;
if ( ! pcap_output_file.empty() ) if ( pcap_output_file )
{ {
const char* writefile = pcap_output_file.data(); const char* writefile = pcap_output_file->data();
pkt_dumper = iosource_mgr->OpenPktDumper(writefile, false); pkt_dumper = iosource_mgr->OpenPktDumper(writefile, false);
assert(pkt_dumper); assert(pkt_dumper);

View file

@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <optional>
#include "net_util.h" #include "net_util.h"
#include "util.h" #include "util.h"
@ -15,7 +16,8 @@
extern void net_init(const std::vector<std::string>& interfaces, extern void net_init(const std::vector<std::string>& interfaces,
const std::vector<std::string>& pcap_input_files, const std::vector<std::string>& pcap_input_files,
const std::string& pcap_output_file, bool do_watchdog); const std::optional<std::string>& pcap_output_file,
bool do_watchdog);
extern void net_run(); extern void net_run();
extern void net_get_final_stats(); extern void net_get_final_stats();
extern void net_finish(int drain_events); extern void net_finish(int drain_events);

View file

@ -20,39 +20,41 @@ extern "C" {
#include "setsignal.h" #include "setsignal.h"
} }
using namespace zeek;
namespace { namespace {
struct Stem { struct Stem {
Stem(std::unique_ptr<bro::PipePair> p); Stem(std::unique_ptr<bro::PipePair> p);
~Stem(); ~Stem();
zeek::Supervisor::Node* Run(); Supervisor::Node* Run();
zeek::Supervisor::Node* Poll(); Supervisor::Node* Poll();
zeek::Supervisor::Node* Revive(); Supervisor::Node* Revive();
void Reap(); void Reap();
bool Spawn(zeek::Supervisor::Node* node); bool Spawn(Supervisor::Node* node);
int AliveNodeCount() const; int AliveNodeCount() const;
void KillNodes(int signal) const; void KillNodes(int signal) const;
void KillNode(const zeek::Supervisor::Node& node, int signal) const; void KillNode(const Supervisor::Node& node, int signal) const;
void Destroy(zeek::Supervisor::Node* node) const; void Destroy(Supervisor::Node* node) const;
bool Wait(zeek::Supervisor::Node* node, int options) const; bool Wait(Supervisor::Node* node, int options) const;
void Shutdown(int exit_code); void Shutdown(int exit_code);
void ReportStatus(const zeek::Supervisor::Node& node) const; void ReportStatus(const Supervisor::Node& node) const;
std::unique_ptr<bro::Flare> signal_flare; std::unique_ptr<bro::Flare> signal_flare;
std::unique_ptr<bro::PipePair> pipe; std::unique_ptr<bro::PipePair> pipe;
std::map<std::string, zeek::Supervisor::Node> nodes; std::map<std::string, Supervisor::Node> nodes;
std::string msg_buffer; std::string msg_buffer;
bool shutting_down = false; bool shutting_down = false;
}; };
@ -80,7 +82,7 @@ static RETSIGTYPE supervisor_sig_handler(int signo)
{ {
// TODO: signal safety // TODO: signal safety
DBG_LOG(DBG_SUPERVISOR, "received signal: %d", signo); DBG_LOG(DBG_SUPERVISOR, "received signal: %d", signo);
zeek::supervisor->ObserveChildSignal(); supervisor->ObserveChildSignal();
return RETSIGVAL; return RETSIGVAL;
} }
@ -104,13 +106,13 @@ static std::vector<std::string> extract_messages(std::string* buffer)
return rval; return rval;
} }
static std::string make_create_message(const zeek::Supervisor::Node& node) static std::string make_create_message(const Supervisor::Node& node)
{ {
auto json_str = node.ToJSON(); auto json_str = node.ToJSON();
return fmt("create %s %s", node.name.data(), json_str.data()); return fmt("create %s %s", node.name.data(), json_str.data());
} }
zeek::Supervisor::Supervisor(zeek::Supervisor::Config cfg, Supervisor::Supervisor(Supervisor::Config cfg,
std::unique_ptr<bro::PipePair> pipe, std::unique_ptr<bro::PipePair> pipe,
pid_t arg_stem_pid) pid_t arg_stem_pid)
: config(std::move(cfg)), stem_pid(arg_stem_pid), stem_pipe(std::move(pipe)) : config(std::move(cfg)), stem_pid(arg_stem_pid), stem_pipe(std::move(pipe))
@ -121,7 +123,7 @@ zeek::Supervisor::Supervisor(zeek::Supervisor::Config cfg,
SetIdle(true); SetIdle(true);
} }
zeek::Supervisor::~Supervisor() Supervisor::~Supervisor()
{ {
setsignal(SIGCHLD, SIG_DFL); setsignal(SIGCHLD, SIG_DFL);
@ -156,12 +158,12 @@ zeek::Supervisor::~Supervisor()
} }
} }
void zeek::Supervisor::ObserveChildSignal() void Supervisor::ObserveChildSignal()
{ {
signal_flare.Fire(); signal_flare.Fire();
} }
void zeek::Supervisor::ReapStem() void Supervisor::ReapStem()
{ {
if ( ! stem_pid ) if ( ! stem_pid )
return; return;
@ -199,7 +201,7 @@ void zeek::Supervisor::ReapStem()
" of stem process for unknown reason"); " of stem process for unknown reason");
} }
void zeek::Supervisor::HandleChildSignal() void Supervisor::HandleChildSignal()
{ {
bool had_child_signal = signal_flare.Extinguish(); bool had_child_signal = signal_flare.Extinguish();
@ -270,19 +272,19 @@ void zeek::Supervisor::HandleChildSignal()
} }
} }
void zeek::Supervisor::GetFds(iosource::FD_Set* read, iosource::FD_Set* write, void Supervisor::GetFds(iosource::FD_Set* read, iosource::FD_Set* write,
iosource::FD_Set* except) iosource::FD_Set* except)
{ {
read->Insert(signal_flare.FD()); read->Insert(signal_flare.FD());
read->Insert(stem_pipe->InFD()); read->Insert(stem_pipe->InFD());
} }
double zeek::Supervisor::NextTimestamp(double* local_network_time) double Supervisor::NextTimestamp(double* local_network_time)
{ {
return timer_mgr->Time(); return timer_mgr->Time();
} }
void zeek::Supervisor::Process() void Supervisor::Process()
{ {
HandleChildSignal(); HandleChildSignal();
@ -357,7 +359,7 @@ void Stem::Reap()
} }
} }
bool Stem::Wait(zeek::Supervisor::Node* node, int options) const bool Stem::Wait(Supervisor::Node* node, int options) const
{ {
int status; int status;
auto res = waitpid(node->pid, &status, options); auto res = waitpid(node->pid, &status, options);
@ -394,7 +396,7 @@ bool Stem::Wait(zeek::Supervisor::Node* node, int options) const
return true; return true;
} }
void Stem::KillNode(const zeek::Supervisor::Node& node, int signal) const void Stem::KillNode(const Supervisor::Node& node, int signal) const
{ {
auto kill_res = kill(node.pid, signal); auto kill_res = kill(node.pid, signal);
@ -403,7 +405,7 @@ void Stem::KillNode(const zeek::Supervisor::Node& node, int signal) const
node.name.data(), strerror(errno)); node.name.data(), strerror(errno));
} }
void Stem::Destroy(zeek::Supervisor::Node* node) const void Stem::Destroy(Supervisor::Node* node) const
{ {
constexpr auto max_term_attempts = 13; constexpr auto max_term_attempts = 13;
constexpr auto kill_delay = 2; constexpr auto kill_delay = 2;
@ -424,7 +426,7 @@ void Stem::Destroy(zeek::Supervisor::Node* node) const
} }
} }
zeek::Supervisor::Node* Stem::Revive() Supervisor::Node* Stem::Revive()
{ {
constexpr auto attempts_before_delay_increase = 3; constexpr auto attempts_before_delay_increase = 3;
constexpr auto delay_increase_factor = 2; constexpr auto delay_increase_factor = 2;
@ -459,7 +461,7 @@ zeek::Supervisor::Node* Stem::Revive()
node.revival_delay *= delay_increase_factor; node.revival_delay *= delay_increase_factor;
if ( Spawn(&node) ) if ( Spawn(&node) )
return new zeek::Supervisor::Node(node); return new Supervisor::Node(node);
ReportStatus(node); ReportStatus(node);
} }
@ -467,7 +469,7 @@ zeek::Supervisor::Node* Stem::Revive()
return {}; return {};
} }
bool Stem::Spawn(zeek::Supervisor::Node* node) bool Stem::Spawn(Supervisor::Node* node)
{ {
auto node_pid = fork(); auto node_pid = fork();
@ -552,13 +554,13 @@ void Stem::Shutdown(int exit_code)
} }
} }
void Stem::ReportStatus(const zeek::Supervisor::Node& node) const void Stem::ReportStatus(const Supervisor::Node& node) const
{ {
std::string msg = fmt("status %s %d", node.name.data(), node.pid); std::string msg = fmt("status %s %d", node.name.data(), node.pid);
safe_write(pipe->OutFD(), msg.data(), msg.size() + 1); safe_write(pipe->OutFD(), msg.data(), msg.size() + 1);
} }
zeek::Supervisor::Node* Stem::Run() Supervisor::Node* Stem::Run()
{ {
for ( ; ; ) for ( ; ; )
{ {
@ -571,7 +573,7 @@ zeek::Supervisor::Node* Stem::Run()
return {}; return {};
} }
zeek::Supervisor::Node* Stem::Poll() Supervisor::Node* Stem::Poll()
{ {
pollfd fds[2] = { { pipe->InFD(), POLLIN, 0 }, pollfd fds[2] = { { pipe->InFD(), POLLIN, 0 },
{ signal_flare->FD(), POLLIN, 0} }; { signal_flare->FD(), POLLIN, 0} };
@ -650,10 +652,10 @@ zeek::Supervisor::Node* Stem::Poll()
{ {
const auto& node_json = msg_tokens[2]; const auto& node_json = msg_tokens[2];
assert(nodes.find(node_name) == nodes.end()); assert(nodes.find(node_name) == nodes.end());
auto node = zeek::Supervisor::Node::FromJSON(node_json); auto node = Supervisor::Node::FromJSON(node_json);
if ( Spawn(&node) ) if ( Spawn(&node) )
return new zeek::Supervisor::Node(node); return new Supervisor::Node(node);
// TODO: get stem printfs going through standard Zeek debug.log // TODO: get stem printfs going through standard Zeek debug.log
printf("Stem created node: %s (%d)\n", node.name.data(), node.pid); printf("Stem created node: %s (%d)\n", node.name.data(), node.pid);
@ -678,7 +680,7 @@ zeek::Supervisor::Node* Stem::Poll()
Destroy(&node); Destroy(&node);
if ( Spawn(&node) ) if ( Spawn(&node) )
return new zeek::Supervisor::Node(node); return new Supervisor::Node(node);
ReportStatus(node); ReportStatus(node);
} }
@ -689,7 +691,7 @@ zeek::Supervisor::Node* Stem::Poll()
return {}; return {};
} }
zeek::Supervisor::Node* zeek::Supervisor::RunStem(std::unique_ptr<bro::PipePair> pipe) Supervisor::Node* Supervisor::RunStem(std::unique_ptr<bro::PipePair> pipe)
{ {
Stem s(std::move(pipe)); Stem s(std::move(pipe));
return s.Run(); return s.Run();
@ -709,9 +711,9 @@ static BifEnum::Supervisor::ClusterRole role_str_to_enum(const std::string& r)
return BifEnum::Supervisor::NONE; return BifEnum::Supervisor::NONE;
} }
zeek::Supervisor::Node zeek::Supervisor::Node::FromRecord(const RecordVal* node) Supervisor::Node Supervisor::Node::FromRecord(const RecordVal* node)
{ {
zeek::Supervisor::Node rval; Supervisor::Node rval;
rval.name = node->Lookup("name")->AsString()->CheckString(); rval.name = node->Lookup("name")->AsString()->CheckString();
auto iface_val = node->Lookup("interface"); auto iface_val = node->Lookup("interface");
@ -726,12 +728,11 @@ zeek::Supervisor::Node zeek::Supervisor::Node::FromRecord(const RecordVal* node)
while ( (v = cluster_table->NextEntry(k, c)) ) while ( (v = cluster_table->NextEntry(k, c)) )
{ {
auto key = cluster_table_val->RecoverIndex(k); IntrusivePtr<ListVal> key{cluster_table_val->RecoverIndex(k), false};
auto name = key->Index(0)->AsStringVal()->ToStdString(); auto name = key->Index(0)->AsStringVal()->ToStdString();
Unref(key);
auto rv = v->Value()->AsRecordVal(); auto rv = v->Value()->AsRecordVal();
zeek::Supervisor::ClusterEndpoint ep; Supervisor::ClusterEndpoint ep;
ep.role = static_cast<BifEnum::Supervisor::ClusterRole>(rv->Lookup("role")->AsEnum()); ep.role = static_cast<BifEnum::Supervisor::ClusterRole>(rv->Lookup("role")->AsEnum());
ep.host = rv->Lookup("host")->AsAddr().AsString(); ep.host = rv->Lookup("host")->AsAddr().AsString();
ep.port = rv->Lookup("p")->AsPortVal()->Port(); ep.port = rv->Lookup("p")->AsPortVal()->Port();
@ -747,9 +748,9 @@ zeek::Supervisor::Node zeek::Supervisor::Node::FromRecord(const RecordVal* node)
return rval; return rval;
} }
zeek::Supervisor::Node zeek::Supervisor::Node::FromJSON(const std::string& json) Supervisor::Node Supervisor::Node::FromJSON(const std::string& json)
{ {
zeek::Supervisor::Node rval; Supervisor::Node rval;
auto j = nlohmann::json::parse(json); auto j = nlohmann::json::parse(json);
rval.name = j["name"]; rval.name = j["name"];
@ -784,27 +785,23 @@ zeek::Supervisor::Node zeek::Supervisor::Node::FromJSON(const std::string& json)
return rval; return rval;
} }
std::string zeek::Supervisor::Node::ToJSON() const std::string Supervisor::Node::ToJSON() const
{ {
auto re = new RE_Matcher("^_"); auto re = std::make_unique<RE_Matcher>("^_");
auto node_val = ToRecord(); auto node_val = ToRecord();
auto json_val = node_val->ToJSON(false, re); IntrusivePtr<StringVal> json_val{node_val->ToJSON(false, re.get()), false};
auto rval = json_val->ToStdString(); auto rval = json_val->ToStdString();
delete re;
Unref(node_val);
Unref(json_val);
return rval; return rval;
} }
RecordVal* zeek::Supervisor::Node::ToRecord() const IntrusivePtr<RecordVal> Supervisor::Node::ToRecord() const
{ {
auto rt = BifType::Record::Supervisor::Node; auto rt = BifType::Record::Supervisor::Node;
auto rval = new RecordVal(rt); auto rval = make_intrusive<RecordVal>(rt);
rval->Assign(rt->FieldOffset("name"), new StringVal(name)); rval->Assign(rt->FieldOffset("name"), new StringVal(name));
if ( ! interface.empty() ) if ( interface )
rval->Assign(rt->FieldOffset("interface"), rval->Assign(rt->FieldOffset("interface"), new StringVal(*interface));
new StringVal(interface));
auto tt = BifType::Record::Supervisor::Node->FieldType("cluster"); auto tt = BifType::Record::Supervisor::Node->FieldType("cluster");
auto cluster_val = new TableVal(tt->AsTableType()); auto cluster_val = new TableVal(tt->AsTableType());
@ -814,19 +811,18 @@ RecordVal* zeek::Supervisor::Node::ToRecord() const
{ {
auto& name = e.first; auto& name = e.first;
auto& ep = e.second; auto& ep = e.second;
auto key = new StringVal(name); auto key = make_intrusive<StringVal>(name);
auto ept = BifType::Record::Supervisor::ClusterEndpoint; auto ept = BifType::Record::Supervisor::ClusterEndpoint;
auto val = new RecordVal(ept); auto val = make_intrusive<RecordVal>(ept);
val->Assign(ept->FieldOffset("role"), BifType::Enum::Supervisor::ClusterRole->GetVal(ep.role)); val->Assign(ept->FieldOffset("role"), BifType::Enum::Supervisor::ClusterRole->GetVal(ep.role));
val->Assign(ept->FieldOffset("host"), new AddrVal(ep.host)); val->Assign(ept->FieldOffset("host"), new AddrVal(ep.host));
val->Assign(ept->FieldOffset("p"), val_mgr->GetPort(ep.port, TRANSPORT_TCP)); val->Assign(ept->FieldOffset("p"), val_mgr->GetPort(ep.port, TRANSPORT_TCP));
if ( ! ep.interface.empty() ) if ( ep.interface )
val->Assign(ept->FieldOffset("interface"), new StringVal(ep.interface)); val->Assign(ept->FieldOffset("interface"), new StringVal(*ep.interface));
cluster_val->Assign(key, val); cluster_val->Assign(key.get(), val.detach());
Unref(key);
} }
if ( pid ) if ( pid )
@ -853,14 +849,14 @@ static Val* supervisor_role_to_cluster_node_type(BifEnum::Supervisor::ClusterRol
} }
} }
void zeek::Supervisor::Node::InitCluster() void Supervisor::Node::InitCluster()
{ {
auto cluster_node_type = global_scope()->Lookup("Cluster::Node")->AsType()->AsRecordType(); auto cluster_node_type = global_scope()->Lookup("Cluster::Node")->AsType()->AsRecordType();
auto cluster_nodes_id = global_scope()->Lookup("Cluster::nodes"); auto cluster_nodes_id = global_scope()->Lookup("Cluster::nodes");
auto cluster_manager_is_logger_id = global_scope()->Lookup("Cluster::manager_is_logger"); auto cluster_manager_is_logger_id = global_scope()->Lookup("Cluster::manager_is_logger");
auto cluster_nodes = cluster_nodes_id->ID_Val()->AsTableVal(); auto cluster_nodes = cluster_nodes_id->ID_Val()->AsTableVal();
auto has_logger = false; auto has_logger = false;
std::string manager_name; std::optional<std::string> manager_name;
for ( const auto& e : supervised_node->cluster ) for ( const auto& e : supervised_node->cluster )
{ {
@ -874,30 +870,29 @@ void zeek::Supervisor::Node::InitCluster()
{ {
const auto& node_name = e.first; const auto& node_name = e.first;
const auto& ep = e.second; const auto& ep = e.second;
auto key = new StringVal(node_name); auto key = make_intrusive<StringVal>(node_name);
auto val = new RecordVal(cluster_node_type); auto val = make_intrusive<RecordVal>(cluster_node_type);
auto node_type = supervisor_role_to_cluster_node_type(ep.role); auto node_type = supervisor_role_to_cluster_node_type(ep.role);
val->Assign(cluster_node_type->FieldOffset("node_type"), node_type); val->Assign(cluster_node_type->FieldOffset("node_type"), node_type);
val->Assign(cluster_node_type->FieldOffset("ip"), new AddrVal(ep.host)); val->Assign(cluster_node_type->FieldOffset("ip"), new AddrVal(ep.host));
val->Assign(cluster_node_type->FieldOffset("p"), val_mgr->GetPort(ep.port, TRANSPORT_TCP)); val->Assign(cluster_node_type->FieldOffset("p"), val_mgr->GetPort(ep.port, TRANSPORT_TCP));
if ( ! ep.interface.empty() ) if ( ep.interface )
val->Assign(cluster_node_type->FieldOffset("interface"), val->Assign(cluster_node_type->FieldOffset("interface"),
new StringVal(ep.interface)); new StringVal(*ep.interface));
if ( ! manager_name.empty() && ep.role != BifEnum::Supervisor::MANAGER ) if ( manager_name && ep.role != BifEnum::Supervisor::MANAGER )
val->Assign(cluster_node_type->FieldOffset("manager"), val->Assign(cluster_node_type->FieldOffset("manager"),
new StringVal(manager_name)); new StringVal(*manager_name));
cluster_nodes->Assign(key, val); cluster_nodes->Assign(key.get(), val.detach());
Unref(key);
} }
cluster_manager_is_logger_id->SetVal(val_mgr->GetBool(! has_logger)); cluster_manager_is_logger_id->SetVal(val_mgr->GetBool(! has_logger));
} }
RecordVal* zeek::Supervisor::Status(const std::string& node_name) RecordVal* Supervisor::Status(const std::string& node_name)
{ {
// TODO: handle node classes // TODO: handle node classes
auto rval = new RecordVal(BifType::Record::Supervisor::Status); auto rval = new RecordVal(BifType::Record::Supervisor::Status);
@ -908,22 +903,21 @@ RecordVal* zeek::Supervisor::Status(const std::string& node_name)
for ( const auto& n : nodes ) for ( const auto& n : nodes )
{ {
const auto& node = n.second; const auto& node = n.second;
auto key = new StringVal(node.name); auto key = make_intrusive<StringVal>(node.name);
auto val = node.ToRecord(); auto val = node.ToRecord();
node_table_val->Assign(key, val); node_table_val->Assign(key.get(), val.detach());
Unref(key);
} }
return rval; return rval;
} }
std::string zeek::Supervisor::Create(const RecordVal* node_val) std::string Supervisor::Create(const RecordVal* node_val)
{ {
auto node = zeek::Supervisor::Node::FromRecord(node_val); auto node = Supervisor::Node::FromRecord(node_val);
return Create(node); return Create(node);
} }
std::string zeek::Supervisor::Create(const zeek::Supervisor::Node& node) std::string Supervisor::Create(const Supervisor::Node& node)
{ {
if ( node.name.find(' ') != std::string::npos ) if ( node.name.find(' ') != std::string::npos )
return fmt("node names must not contain spaces: '%s'", return fmt("node names must not contain spaces: '%s'",
@ -938,7 +932,7 @@ std::string zeek::Supervisor::Create(const zeek::Supervisor::Node& node)
return ""; return "";
} }
bool zeek::Supervisor::Destroy(const std::string& node_name) bool Supervisor::Destroy(const std::string& node_name)
{ {
// TODO: handle node classes // TODO: handle node classes
@ -950,7 +944,7 @@ bool zeek::Supervisor::Destroy(const std::string& node_name)
return true; return true;
} }
bool zeek::Supervisor::Restart(const std::string& node_name) bool Supervisor::Restart(const std::string& node_name)
{ {
// TODO: handle node classes // TODO: handle node classes

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <sys/types.h> #include <sys/types.h>
#include <optional>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <vector> #include <vector>
@ -13,6 +14,7 @@
#include "Pipe.h" #include "Pipe.h"
#include "Flare.h" #include "Flare.h"
#include "NetVar.h" #include "NetVar.h"
#include "IntrusivePtr.h"
namespace zeek { namespace zeek {
@ -29,7 +31,7 @@ public:
BifEnum::Supervisor::ClusterRole role; BifEnum::Supervisor::ClusterRole role;
std::string host; std::string host;
int port; int port;
std::string interface; std::optional<std::string> interface;
}; };
struct Node { struct Node {
@ -39,10 +41,10 @@ public:
static void InitCluster(); static void InitCluster();
std::string ToJSON() const; std::string ToJSON() const;
RecordVal* ToRecord() const; IntrusivePtr<RecordVal> ToRecord() const;
std::string name; std::string name;
std::string interface; std::optional<std::string> interface;
std::map<std::string, ClusterEndpoint> cluster; std::map<std::string, ClusterEndpoint> cluster;
pid_t pid = 0; pid_t pid = 0;

View file

@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <list> #include <list>
#include <optional>
#ifdef HAVE_GETOPT_H #ifdef HAVE_GETOPT_H
#include <getopt.h> #include <getopt.h>
#endif #endif
@ -219,11 +220,11 @@ struct zeek_options {
bool print_signature_debug_info = false; bool print_signature_debug_info = false;
int print_plugins = 0; int print_plugins = 0;
std::string debug_log_streams; std::optional<std::string> debug_log_streams;
std::string debug_script_tracing_file; std::optional<std::string> debug_script_tracing_file;
std::string identifier_to_print; std::optional<std::string> identifier_to_print;
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 supervised_workers = 0; int supervised_workers = 0;
@ -239,16 +240,16 @@ struct zeek_options {
bool perftools_check_leaks = false; bool perftools_check_leaks = false;
bool perftools_profile = false; bool perftools_profile = false;
std::string pcap_filter; std::optional<std::string> pcap_filter;
std::vector<std::string> interfaces; std::vector<std::string> interfaces;
std::vector<std::string> pcap_files; std::vector<std::string> pcap_files;
std::vector<std::string> signature_files; std::vector<std::string> signature_files;
std::string pcap_output_file; std::optional<std::string> pcap_output_file;
std::string random_seed_input_file; std::optional<std::string> random_seed_input_file;
std::string random_seed_output_file; std::optional<std::string> random_seed_output_file;
std::string process_status_file; std::optional<std::string> process_status_file;
std::string zeekygen_config_file; std::optional<std::string> zeekygen_config_file;
std::string libidmef_dtd_file = "idmef-message.dtd"; std::string libidmef_dtd_file = "idmef-message.dtd";
std::set<std::string> plugins_to_load; std::set<std::string> plugins_to_load;
@ -329,11 +330,6 @@ static zeek_options parse_cmdline(int argc, char** argv)
rval.debug_scripts = true; rval.debug_scripts = true;
break; break;
case 'e': case 'e':
if ( optarg[0] == 0 )
// Cheating a bit, but allows checking for an empty string
// to determine whether -e was used or not.
rval.script_code_to_exec = " ";
else
rval.script_code_to_exec = optarg; rval.script_code_to_exec = optarg;
break; break;
case 'f': case 'f':
@ -681,7 +677,7 @@ static std::vector<std::string> get_script_signature_files()
return rval; return rval;
} }
static std::string get_exe_path(std::string invocation) static std::string get_exe_path(const std::string& invocation)
{ {
if ( invocation.empty() ) if ( invocation.empty() )
return ""; return "";
@ -792,8 +788,8 @@ int main(int argc, char** argv)
options = {}; options = {};
const auto& node_name = zeek::supervised_node->name; const auto& node_name = zeek::supervised_node->name;
if ( ! zeek::supervised_node->interface.empty() ) if ( zeek::supervised_node->interface )
options.interfaces.emplace_back(zeek::supervised_node->interface); options.interfaces.emplace_back(*zeek::supervised_node->interface);
if ( ! zeek::supervised_node->cluster.empty() ) if ( ! zeek::supervised_node->cluster.empty() )
{ {
@ -838,17 +834,17 @@ int main(int argc, char** argv)
fprintf(stderr, "Zeek script debugging ON.\n"); fprintf(stderr, "Zeek script debugging ON.\n");
} }
if ( ! options.script_code_to_exec.empty() ) if ( options.script_code_to_exec )
command_line_policy = options.script_code_to_exec.data(); command_line_policy = options.script_code_to_exec->data();
if ( ! options.debug_script_tracing_file.empty() ) if ( options.debug_script_tracing_file )
{ {
g_trace_state.SetTraceFile(options.debug_script_tracing_file.data()); g_trace_state.SetTraceFile(options.debug_script_tracing_file->data());
g_trace_state.TraceOn(); g_trace_state.TraceOn();
} }
if ( ! options.process_status_file.empty() ) if ( options.process_status_file )
proc_status_file = options.process_status_file.data(); proc_status_file = options.process_status_file->data();
atexit(atexit_handler); atexit(atexit_handler);
set_processing_status("INITIALIZING", "main"); set_processing_status("INITIALIZING", "main");
@ -862,9 +858,9 @@ int main(int argc, char** argv)
plugin_mgr = new plugin::Manager(); plugin_mgr = new plugin::Manager();
#ifdef DEBUG #ifdef DEBUG
if ( ! options.debug_log_streams.empty() ) if ( options.debug_log_streams )
{ {
debug_logger.EnableStreams(options.debug_log_streams.data()); debug_logger.EnableStreams(options.debug_log_streams->data());
const char* debug_log_name = nullptr; const char* debug_log_name = nullptr;
if ( ! getenv("ZEEK_DEBUG_LOG_STDERR") ) if ( ! getenv("ZEEK_DEBUG_LOG_STDERR") )
@ -896,11 +892,11 @@ int main(int argc, char** argv)
const char* seed_load_file = zeekenv("ZEEK_SEED_FILE"); const char* seed_load_file = zeekenv("ZEEK_SEED_FILE");
if ( ! options.random_seed_input_file.empty() ) if ( options.random_seed_input_file )
seed_load_file = options.random_seed_input_file.data(); seed_load_file = options.random_seed_input_file->data();
init_random_seed((seed_load_file && *seed_load_file ? seed_load_file : 0), init_random_seed((seed_load_file && *seed_load_file ? seed_load_file : 0),
options.random_seed_output_file.empty() ? 0 : options.random_seed_output_file.data()); options.random_seed_output_file ? options.random_seed_output_file->data() : 0);
// DEBUG_MSG("HMAC key: %s\n", md5_digest_print(shared_hmac_md5_key)); // DEBUG_MSG("HMAC key: %s\n", md5_digest_print(shared_hmac_md5_key));
init_hash_function(); init_hash_function();
@ -929,8 +925,8 @@ int main(int argc, char** argv)
timer_mgr = new PQ_TimerMgr("<GLOBAL>"); timer_mgr = new PQ_TimerMgr("<GLOBAL>");
// timer_mgr = new CQ_TimerMgr(); // timer_mgr = new CQ_TimerMgr();
zeekygen_mgr = new zeekygen::Manager(options.zeekygen_config_file, auto zeekygen_cfg = options.zeekygen_config_file.value_or("");
bro_argv[0]); zeekygen_mgr = new zeekygen::Manager(zeekygen_cfg, bro_argv[0]);
add_essential_input_file("base/init-bare.zeek"); add_essential_input_file("base/init-bare.zeek");
add_essential_input_file("base/init-frameworks-and-bifs.zeek"); add_essential_input_file("base/init-frameworks-and-bifs.zeek");
@ -944,7 +940,7 @@ int main(int argc, char** argv)
options.script_options_to_set.empty() && options.script_options_to_set.empty() &&
options.pcap_files.size() == 0 && options.pcap_files.size() == 0 &&
options.interfaces.size() == 0 && options.interfaces.size() == 0 &&
options.identifier_to_print.empty() && ! options.identifier_to_print &&
! command_line_policy && ! options.print_plugins && ! command_line_policy && ! options.print_plugins &&
! use_supervisor() && ! zeek::supervised_node ) ! use_supervisor() && ! zeek::supervised_node )
add_input_file("-"); add_input_file("-");
@ -1077,14 +1073,14 @@ int main(int argc, char** argv)
reporter->InitOptions(); reporter->InitOptions();
zeekygen_mgr->GenerateDocs(); zeekygen_mgr->GenerateDocs();
if ( ! options.pcap_filter.empty() ) if ( options.pcap_filter )
{ {
ID* id = global_scope()->Lookup("cmd_line_bpf_filter"); ID* id = global_scope()->Lookup("cmd_line_bpf_filter");
if ( ! id ) if ( ! id )
reporter->InternalError("global cmd_line_bpf_filter not defined"); reporter->InternalError("global cmd_line_bpf_filter not defined");
id->SetVal(new StringVal(options.pcap_filter)); id->SetVal(new StringVal(*options.pcap_filter));
} }
auto all_signature_files = options.signature_files; auto all_signature_files = options.signature_files;
@ -1164,11 +1160,11 @@ int main(int argc, char** argv)
} }
// Print the ID. // Print the ID.
if ( ! options.identifier_to_print.empty() ) if ( options.identifier_to_print )
{ {
ID* id = global_scope()->Lookup(options.identifier_to_print); ID* id = global_scope()->Lookup(*options.identifier_to_print);
if ( ! id ) if ( ! id )
reporter->FatalError("No such ID: %s\n", options.identifier_to_print.data()); reporter->FatalError("No such ID: %s\n", options.identifier_to_print->data());
ODesc desc; ODesc desc;
desc.SetQuotes(true); desc.SetQuotes(true);