Commit 67639803 authored by Alija Sabic's avatar Alija Sabic
Browse files

Add Eclipse workspace (for container default startup)

parent 24124929
!SESSION 2017-11-26 23:04:56.626 -----------------------------------------------
eclipse.buildId=4.7.0.I20170612-0950
java.version=1.8.0_151
java.vendor=Oracle Corporation
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US
Framework arguments: -product org.eclipse.epp.package.cpp.product
Command-line arguments: -os linux -ws gtk -arch x86_64 -product org.eclipse.epp.package.cpp.product
!ENTRY org.eclipse.cdt.core 1 0 2017-11-26 23:07:08.596
!MESSAGE Indexed 'snort++' (920 sources, 1,195 headers) in 50.8 sec: 122,406 declarations; 400,376 references; 21 unresolved inclusions; 38 syntax errors; 3,871 unresolved names (0.74%)
!SESSION 2017-11-26 23:21:26.364 -----------------------------------------------
eclipse.buildId=4.7.0.I20170612-0950
java.version=1.8.0_151
java.vendor=Oracle Corporation
BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=en_US
Framework arguments: -product org.eclipse.epp.package.cpp.product
Command-line arguments: -os linux -ws gtk -arch x86_64 -product org.eclipse.epp.package.cpp.product
!ENTRY org.eclipse.core.resources 2 10035 2017-11-26 23:21:36.922
!MESSAGE The workspace exited with unsaved changes in the previous session; refreshing workspace to recover changes.
//--------------------------------------------------------------------------
// Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License Version 2 as published
// by the Free Software Foundation. You may not use, modify or distribute
// this program under any other version of the GNU General Public License.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
// main.cc author Russ Combs <rucombs@cisco.com>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "main.h"
#include <thread>
#include <mutex>
#include "control/idle_processing.h"
#include "framework/module.h"
#include "helpers/process.h"
#include "helpers/ring.h"
#include "log/messages.h"
#include "lua/lua.h"
#include "main/analyzer.h"
#include "main/analyzer_command.h"
#include "main/request.h"
#include "main/shell.h"
#include "main/snort.h"
#include "main/snort_config.h"
#include "main/snort_debug.h"
#include "main/snort_module.h"
#include "main/swapper.h"
#include "main/thread_config.h"
#include "managers/inspector_manager.h"
#include "managers/module_manager.h"
#include "managers/plugin_manager.h"
#include "memory/memory_cap.h"
#include "packet_io/sfdaq.h"
#include "packet_io/trough.h"
#include "target_based/sftarget_reader.h"
#include "time/periodic.h"
#include "utils/util.h"
#include "utils/safec.h"
#ifdef UNIT_TEST
#include "catch/unit_test_main.h"
#endif
#ifdef PIGLET
#include "piglet/piglet.h"
#endif
#ifdef SHELL
#include "main/control_mgmt.h"
#endif
//-------------------------------------------------------------------------
static bool exit_requested = false;
static int main_exit_code = 0;
static bool paused = false;
static std::queue<AnalyzerCommand*> orphan_commands;
static std::mutex poke_mutex;
static Ring<unsigned>* pig_poke = nullptr;
const struct timespec main_sleep = { 0, 1000000 }; // 0.001 sec
static const char* prompt = "o\")~ ";
const char* get_prompt()
{ return prompt; }
static bool use_shell(SnortConfig* sc)
{
#ifdef SHELL
return ( sc->run_flags & RUN_FLAG__SHELL );
#else
UNUSED(sc);
return false;
#endif
}
// FIXIT-L X Replace main_poke()/main_read() usage with command objects
void main_poke(unsigned id)
{
std::lock_guard<std::mutex> lock(poke_mutex);
pig_poke->put(id);
}
static int main_read()
{
std::lock_guard<std::mutex> lock(poke_mutex);
return pig_poke->get(-1);
}
static Request request;
static Request* current_request = &request;
#ifdef SHELL
static int current_fd = -1;
#endif
//-------------------------------------------------------------------------
// pig foo
//-------------------------------------------------------------------------
class Pig
{
public:
Analyzer* analyzer;
bool awaiting_privilege_change = false;
Pig() { analyzer = nullptr; athread = nullptr; idx = (unsigned)-1; }
void set_index(unsigned index) { idx = index; }
void prep(const char* source);
void start();
void stop();
bool queue_command(AnalyzerCommand*);
void reap_commands();
private:
void reap_command(AnalyzerCommand* ac);
std::thread* athread;
unsigned idx;
};
void Pig::prep(const char* source)
{
analyzer = new Analyzer(idx, source);
}
void Pig::start()
{
static uint16_t run_num = 0;
assert(!athread);
LogMessage("++ [%u] %s\n", idx, analyzer->get_source());
Swapper* ps = new Swapper(snort_conf, SFAT_GetConfig());
athread = new std::thread(std::ref(*analyzer), ps, ++run_num);
}
void Pig::stop()
{
assert(analyzer);
assert(athread);
athread->join();
delete athread;
athread = nullptr;
LogMessage("-- [%u] %s\n", idx, analyzer->get_source());
// Reap all analyzer commands, completed or not.
// FIXIT-L X Add concept of finalizing commands differently based on whether they were
// completed or not when we have commands that care about that.
while (!analyzer->completed_work_queue.empty())
{
reap_command(analyzer->completed_work_queue.front());
analyzer->completed_work_queue.pop();
}
while (!analyzer->pending_work_queue.empty())
{
reap_command(analyzer->pending_work_queue.front());
analyzer->pending_work_queue.pop();
}
delete analyzer;
analyzer = nullptr;
}
bool Pig::queue_command(AnalyzerCommand* ac)
{
if (!analyzer || !athread)
return false;
#ifdef DEBUG_MSGS
unsigned ac_ref_count = ac->get();
DebugFormat(DEBUG_ANALYZER, "[%u] Queuing command %s for execution (refcount %u)\n",
idx, ac->stringify(), ac_ref_count);
#else
ac->get();
#endif
analyzer->execute(ac);
return true;
}
void Pig::reap_command(AnalyzerCommand* ac)
{
unsigned ac_ref_count = ac->put();
if (ac_ref_count == 0)
{
DebugFormat(DEBUG_ANALYZER, "[%u] Destroying completed command %s\n",
idx, ac->stringify());
delete ac;
}
#ifdef DEBUG_MSGS
else
DebugFormat(DEBUG_ANALYZER, "[%u] Reaped ongoing command %s (refcount %u)\n",
idx, ac->stringify(), ac_ref_count);
#endif
}
void Pig::reap_commands()
{
if (!analyzer)
return;
size_t commands_to_reap;
do
{
AnalyzerCommand* ac = nullptr;
analyzer->completed_work_queue_mutex.lock();
commands_to_reap = analyzer->completed_work_queue.size();
if (commands_to_reap)
{
ac = analyzer->completed_work_queue.front();
analyzer->completed_work_queue.pop();
}
analyzer->completed_work_queue_mutex.unlock();
if (ac)
reap_command(ac);
} while (commands_to_reap > 1);
}
static Pig* pigs = nullptr;
static unsigned max_pigs = 0;
static Pig* get_lazy_pig(unsigned max)
{
for ( unsigned i = 0; i < max; ++i )
if ( !pigs[i].analyzer )
return pigs + i;
assert(false);
return nullptr;
}
//-------------------------------------------------------------------------
// main commands
//-------------------------------------------------------------------------
static void broadcast(AnalyzerCommand* ac)
{
unsigned dispatched = 0;
DebugFormat(DEBUG_ANALYZER, "Broadcasting %s command\n", ac->stringify());
for (unsigned idx = 0; idx < max_pigs; ++idx)
{
if (pigs[idx].queue_command(ac))
dispatched++;
}
if (!dispatched)
orphan_commands.push(ac);
}
static AnalyzerCommand* get_command(AnalyzerCommand* ac, bool from_shell)
{
#ifndef SHELL
UNUSED(from_shell);
#else
if ( from_shell )
return ( new ACShellCmd(current_fd, ac) );
else
#endif
return ac;
}
int main_dump_stats(lua_State* L)
{
bool from_shell = ( L != nullptr );
current_request->respond("== dumping stats\n", from_shell);
broadcast(get_command(new ACGetStats(), from_shell));
return 0;
}
int main_rotate_stats(lua_State* L)
{
bool from_shell = ( L != nullptr );
current_request->respond("== rotating stats\n", from_shell);
broadcast(get_command(new ACRotate(), from_shell));
return 0;
}
int main_reload_config(lua_State* L)
{
if ( Swapper::get_reload_in_progress() )
{
current_request->respond("== reload pending; retry\n");
return 0;
}
const char* fname = nullptr;
if ( L )
{
Lua::ManageStack(L, 1);
fname = luaL_checkstring(L, 1);
}
current_request->respond(".. reloading configuration\n");
SnortConfig* old = snort_conf;
SnortConfig* sc = Snort::get_reload_config(fname);
if ( !sc )
{
current_request->respond("== reload failed\n");
return 0;
}
snort_conf = sc;
proc_stats.conf_reloads++;
bool from_shell = ( L != nullptr );
current_request->respond(".. swapping configuration\n", from_shell);
broadcast(get_command(new ACSwap(new Swapper(old, sc)), from_shell));
return 0;
}
int main_reload_daq(lua_State* L)
{
bool from_shell = ( L != nullptr );
current_request->respond(".. reloading daq module\n", from_shell);
broadcast(get_command(new ACDAQSwap(), from_shell));
proc_stats.daq_reloads++;
return 0;
}
int main_reload_hosts(lua_State* L)
{
if ( Swapper::get_reload_in_progress() )
{
current_request->respond("== reload pending; retry\n");
return 0;
}
Lua::ManageStack(L, 1);
const char* fname = luaL_checkstring(L, 1);
if ( fname and *fname )
current_request->respond(".. reloading hosts table\n");
else
{
current_request->respond("== filename required\n");
return 0;
}
Shell sh = Shell(fname);
sh.configure(snort_conf);
tTargetBasedConfig* old = SFAT_GetConfig();
tTargetBasedConfig* tc = SFAT_Swap();
if ( !tc )
{
current_request->respond("== reload failed\n");
return 0;
}
bool from_shell = ( L != nullptr );
current_request->respond(".. swapping hosts table\n", from_shell);
broadcast(get_command(new ACSwap(new Swapper(old, tc)), from_shell));
return 0;
}
int main_process(lua_State* L)
{
const char* f = lua_tostring(L, 1);
if ( !f )
{
current_request->respond("== pcap filename required\n");
return 0;
}
current_request->respond("== queuing pcap\n");
Trough::add_source(Trough::SOURCE_LIST, f);
return 0;
}
int main_pause(lua_State* L)
{
bool from_shell = ( L != nullptr );
current_request->respond("== pausing\n", from_shell);
broadcast(get_command(new ACPause(), from_shell));
paused = true;
return 0;
}
int main_resume(lua_State* L)
{
bool from_shell = ( L != nullptr );
current_request->respond("== resuming\n", from_shell);
broadcast(get_command(new ACResume(), from_shell));
paused = false;
return 0;
}
#ifdef SHELL
int main_detach(lua_State*)
{
current_request->respond("== detaching\n");
return 0;
}
int main_dump_plugins(lua_State*)
{
ModuleManager::dump_modules();
PluginManager::dump_plugins();
return 0;
}
#endif
int main_quit(lua_State* L)
{
bool from_shell = ( L != nullptr );
current_request->respond("== stopping\n", from_shell);
broadcast(get_command(new ACStop(), from_shell));
exit_requested = true;
return 0;
}
int main_help(lua_State*)
{
const Command* cmd = get_snort_module()->get_commands();
while ( cmd->name )
{
std::string info = cmd->name;
info += cmd->get_arg_list();
info += ": ";
info += cmd->help;
info += "\n";
current_request->respond(info.c_str());
++cmd;
}
return 0;
}
//-------------------------------------------------------------------------
// housekeeping foo
//-------------------------------------------------------------------------
static int signal_check()
{
PigSignal s = get_pending_signal();
if ( s == PIG_SIG_NONE or s >= PIG_SIG_MAX )
return 0;
LogMessage("** caught %s signal\n", get_signal_name(s));
switch ( s )
{
case PIG_SIG_QUIT:
case PIG_SIG_TERM:
main_quit();
break;
case PIG_SIG_INT:
if ( paused )
main_resume(nullptr);
else
main_quit();
break;
case PIG_SIG_RELOAD_CONFIG:
main_reload_config();
break;
case PIG_SIG_RELOAD_HOSTS:
main_reload_hosts();
break;
case PIG_SIG_DUMP_STATS:
main_dump_stats();
break;
case PIG_SIG_ROTATE_STATS:
main_rotate_stats();
break;
default:
break;
}
proc_stats.signals++;
return 1;
}
static void reap_commands()
{
for (unsigned idx = 0; idx < max_pigs; ++idx)
pigs[idx].reap_commands();
while (!orphan_commands.empty())
{
AnalyzerCommand* ac = orphan_commands.front();
orphan_commands.pop();
DebugFormat(DEBUG_ANALYZER, "Destroying orphan command %s\n", ac->stringify());
delete ac;
}
}
// FIXIT-L return true if something was done to avoid sleeping
static bool house_keeping()
{
signal_check();
reap_commands();
IdleProcessing::execute();
Periodic::check();
InspectorManager::empty_trash();
return false;
}
static void service_check()
{
#ifdef SHELL
if ( ControlMgmt::service_users(current_fd, current_request) )
return;
#endif
if ( house_keeping() )
return;
nanosleep(&main_sleep, NULL);
}
//-------------------------------------------------------------------------
// main foo
//-------------------------------------------------------------------------
static bool just_validate()