00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 //
00004 // This program is free software; you can redistribute it and/or modify it
00005 // under the terms of the GNU General Public License Version 2 as published
00006 // by the Free Software Foundation. You may not use, modify or distribute
00007 // this program under any other version of the GNU General Public License.
00008 //
00009 // This program is distributed in the hope that it will be useful, but
00010 // WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program; if not, write to the Free Software Foundation, Inc.,
00016 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 //--------------------------------------------------------------------------
00018 // main.cc author Russ Combs <rucombs@cisco.com>
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include "main.h"
00025
00026 #include <thread>
00027
00028 #include "control/idle_processing.h"
00029 #include "framework/module.h"
00030 #include "helpers/process.h"
00031 #include "helpers/ring.h"
00032 #include "log/messages.h"
00033 #include "lua/lua.h"
00034 #include "main/analyzer.h"
00035 #include "main/analyzer_command.h"
00036 #include "main/request.h"
00037 #include "main/shell.h"
00038 #include "main/snort.h"
00039 #include "main/snort_config.h"
00040 #include "main/snort_debug.h"
00041 #include "main/snort_module.h"
00042 #include "main/swapper.h"
00043 #include "main/thread_config.h"
00044 #include "managers/inspector_manager.h"
00045 #include "managers/module_manager.h"
00046 #include "managers/plugin_manager.h"
00047 #include "packet_io/sfdaq.h"
00048 #include "packet_io/trough.h"
00049 #include "target_based/sftarget_reader.h"
00050 #include "time/periodic.h"
00051 #include "utils/util.h"
00052 #include "utils/safec.h"
00053
00054 #ifdef UNIT_TEST
00055 #include "catch/unit_test_main.h"
00056 #endif
00057
00058 #ifdef PIGLET
00059 #include "piglet/piglet.h"
00060 #endif
00061
00062 #ifdef SHELL
00063 #include "main/control_mgmt.h"
00064 #endif
00065
00066
00067 //#include "mysql_connection.h"
00068
00069 //#include <cppconn/driver.h>
00070 //#include <cppconn/exception.h>
00071 //#include <cppconn/resultset.h>
00072 //#include <cppconn/statement.h>
00073
00074 //using namespace std;
00075
00076
00077
00078
00079
00080 //-------------------------------------------------------------------------
00081
00082 static bool exit_requested = false;
00083 static int main_exit_code = 0;
00084 static bool paused = false;
00085 static std::queue<AnalyzerCommand*> orphan_commands;
00086
00087 static std::mutex poke_mutex;
00088 static Ring<unsigned>* pig_poke = nullptr;
00089
00090 const struct timespec main_sleep = { 0, 1000000 }; // 0.001 sec
00091
00092 static const char* prompt = "o\")~ ";
00093
00094 const char* get_prompt()
00095 { return prompt; }
00096
00097 static bool use_shell(SnortConfig* sc)
00098 {
00099 #ifdef SHELL
00100 return ( sc->run_flags & RUN_FLAG__SHELL );
00101 #else
00102 UNUSED(sc);
00103 return false;
00104 #endif
00105 }
00106
00107 // FIXIT-L X Replace main_poke()/main_read() usage with command objects
00108 void main_poke(unsigned id)
00109 {
00110 std::lock_guard<std::mutex> lock(poke_mutex);
00111 pig_poke->put(id);
00112 }
00113
00114 static int main_read()
00115 {
00116 std::lock_guard<std::mutex> lock(poke_mutex);
00117 return pig_poke->get(-1);
00118 }
00119
00120 static Request request;
00121 static Request* current_request = &request;
00122 #ifdef SHELL
00123 static int current_fd = -1;
00124 #endif
00125
00126 //-------------------------------------------------------------------------
00127 // pig foo
00128 //-------------------------------------------------------------------------
00129
00130 class Pig
00131 {
00132 public:
00133 Analyzer* analyzer;
00134 bool awaiting_privilege_change = false;
00135
00136 Pig() { analyzer = nullptr; athread = nullptr; idx = (unsigned)-1; }
00137
00138 void set_index(unsigned index) { idx = index; }
00139
00140 void prep(const char* source);
00141 void start();
00142 void stop();
00143
00144 bool queue_command(AnalyzerCommand*);
00145 void reap_commands();
00146
00147 private:
00148 void reap_command(AnalyzerCommand* ac);
00149
00150 std::thread* athread;
00151 unsigned idx;
00152 };
00153
00154 void Pig::prep(const char* source)
00155 {
00156 analyzer = new Analyzer(idx, source);
00157 }
00158
00159 void Pig::start()
00160 {
00161 static uint16_t run_num = 0;
00162 assert(!athread);
00163 LogMessage("++ [%u] %s\n", idx, analyzer->get_source());
00164
00165 Swapper* ps = new Swapper(snort_conf, SFAT_GetConfig());
00166 athread = new std::thread(std::ref(*analyzer), ps, ++run_num);
00167 }
00168
00169 void Pig::stop()
00170 {
00171 assert(analyzer);
00172 assert(athread);
00173
00174 athread->join();
00175 delete athread;
00176 athread = nullptr;
00177
00178 LogMessage("-- [%u] %s\n", idx, analyzer->get_source());
00179
00180 // Reap all analyzer commands, completed or not.
00181 // FIXIT-L X Add concept of finalizing commands differently based on whether they were
00182 // completed or not when we have commands that care about that.
00183 while (!analyzer->completed_work_queue.empty())
00184 {
00185 reap_command(analyzer->completed_work_queue.front());
00186 analyzer->completed_work_queue.pop();
00187 }
00188 while (!analyzer->pending_work_queue.empty())
00189 {
00190 reap_command(analyzer->pending_work_queue.front());
00191 analyzer->pending_work_queue.pop();
00192 }
00193 delete analyzer;
00194 analyzer = nullptr;
00195 }
00196
00197 bool Pig::queue_command(AnalyzerCommand* ac)
00198 {
00199 if (!analyzer || !athread)
00200 return false;
00201
00202 #ifdef DEBUG_MSGS
00203 unsigned ac_ref_count = ac->get();
00204 DebugFormat(DEBUG_ANALYZER, "[%u] Queuing command %s for execution (refcount %u)\n",
00205 idx, ac->stringify(), ac_ref_count);
00206 #else
00207 ac->get();
00208 #endif
00209 analyzer->execute(ac);
00210 return true;
00211 }
00212
00213 void Pig::reap_command(AnalyzerCommand* ac)
00214 {
00215 unsigned ac_ref_count = ac->put();
00216 if (ac_ref_count == 0)
00217 {
00218 DebugFormat(DEBUG_ANALYZER, "[%u] Destroying completed command %s\n",
00219 idx, ac->stringify());
00220 delete ac;
00221 }
00222 #ifdef DEBUG_MSGS
00223 else
00224 DebugFormat(DEBUG_ANALYZER, "[%u] Reaped ongoing command %s (refcount %u)\n",
00225 idx, ac->stringify(), ac_ref_count);
00226 #endif
00227 }
00228
00229 void Pig::reap_commands()
00230 {
00231 if (!analyzer)
00232 return;
00233 size_t commands_to_reap;
00234 do
00235 {
00236 AnalyzerCommand* ac = nullptr;
00237 analyzer->completed_work_queue_mutex.lock();
00238 commands_to_reap = analyzer->completed_work_queue.size();
00239 if (commands_to_reap)
00240 {
00241 ac = analyzer->completed_work_queue.front();
00242 analyzer->completed_work_queue.pop();
00243 }
00244 analyzer->completed_work_queue_mutex.unlock();
00245 if (ac)
00246 reap_command(ac);
00247 } while (commands_to_reap > 1);
00248 }
00249
00250 static Pig* pigs = nullptr;
00251 static unsigned max_pigs = 0;
00252
00253 static Pig* get_lazy_pig(unsigned max)
00254 {
00255 for ( unsigned i = 0; i < max; ++i )
00256 if ( !pigs[i].analyzer )
00257 return pigs + i;
00258
00259 assert(false);
00260 return nullptr;
00261 }
00262
00263 //-------------------------------------------------------------------------
00264 // main commands
00265 //-------------------------------------------------------------------------
00266
00267 static void broadcast(AnalyzerCommand* ac)
00268 {
00269 unsigned dispatched = 0;
00270
00271 DebugFormat(DEBUG_ANALYZER, "Broadcasting %s command\n", ac->stringify());
00272
00273 for (unsigned idx = 0; idx < max_pigs; ++idx)
00274 {
00275 if (pigs[idx].queue_command(ac))
00276 dispatched++;
00277 }
00278
00279 if (!dispatched)
00280 orphan_commands.push(ac);
00281 }
00282
00283 static AnalyzerCommand* get_command(AnalyzerCommand* ac, bool from_shell)
00284 {
00285 #ifndef SHELL
00286 UNUSED(from_shell);
00287 #else
00288 if ( from_shell )
00289 return ( new ACShellCmd(current_fd, ac) );
00290 else
00291 #endif
00292 return ac;
00293 }
00294
00295 int main_dump_stats(lua_State* L)
00296 {
00297 bool from_shell = ( L != nullptr );
00298 current_request->respond("== dumping stats\n", from_shell);
00299 broadcast(get_command(new ACGetStats(), from_shell));
00300 return 0;
00301 }
00302
00303 int main_rotate_stats(lua_State* L)
00304 {
00305 bool from_shell = ( L != nullptr );
00306 current_request->respond("== rotating stats\n", from_shell);
00307 broadcast(get_command(new ACRotate(), from_shell));
00308 return 0;
00309 }
00310
00311 int main_reload_config(lua_State* L)
00312 {
00313 if ( Swapper::get_reload_in_progress() )
00314 {
00315 current_request->respond("== reload pending; retry\n");
00316 return 0;
00317 }
00318 const char* fname = nullptr;
00319
00320 if ( L )
00321 {
00322 Lua::ManageStack(L, 1);
00323 fname = luaL_checkstring(L, 1);
00324 }
00325
00326 current_request->respond(".. reloading configuration\n");
00327 SnortConfig* old = snort_conf;
00328 SnortConfig* sc = Snort::get_reload_config(fname);
00329
00330 if ( !sc )
00331 {
00332 current_request->respond("== reload failed\n");
00333 return 0;
00334 }
00335 snort_conf = sc;
00336 proc_stats.conf_reloads++;
00337
00338 bool from_shell = ( L != nullptr );
00339 current_request->respond(".. swapping configuration\n", from_shell);
00340 broadcast(get_command(new ACSwap(new Swapper(old, sc)), from_shell));
00341
00342 return 0;
00343 }
00344
00345 int main_reload_policy(lua_State* L)
00346 {
00347 if ( Swapper::get_reload_in_progress() )
00348 {
00349 current_request->respond("== reload pending; retry\n");
00350 return 0;
00351 }
00352 const char* fname = nullptr;
00353
00354 if ( L )
00355 {
00356 Lua::ManageStack(L, 1);
00357 fname = luaL_checkstring(L, 1);
00358 }
00359
00360 if ( fname and *fname )
00361 current_request->respond(".. reloading policy\n");
00362 else
00363 {
00364 current_request->respond("== filename required\n");
00365 return 0;
00366 }
00367
00368 SnortConfig* old = snort_conf;
00369 SnortConfig* sc = Snort::get_updated_policy(old, fname, nullptr);
00370
00371 if ( !sc )
00372 {
00373 current_request->respond("== reload failed\n");
00374 return 0;
00375 }
00376 snort_conf = sc;
00377 proc_stats.policy_reloads++;
00378
00379 bool from_shell = ( L != nullptr );
00380 current_request->respond(".. swapping policy\n", from_shell);
00381 broadcast(get_command(new ACSwap(new Swapper(old, sc)), from_shell));
00382
00383 return 0;
00384 }
00385
00386 int main_reload_daq(lua_State* L)
00387 {
00388 bool from_shell = ( L != nullptr );
00389 current_request->respond(".. reloading daq module\n", from_shell);
00390 broadcast(get_command(new ACDAQSwap(), from_shell));
00391 proc_stats.daq_reloads++;
00392
00393 return 0;
00394 }
00395
00396 int main_reload_hosts(lua_State* L)
00397 {
00398 if ( Swapper::get_reload_in_progress() )
00399 {
00400 current_request->respond("== reload pending; retry\n");
00401 return 0;
00402 }
00403 Lua::ManageStack(L, 1);
00404 const char* fname = luaL_checkstring(L, 1);
00405
00406 if ( fname and *fname )
00407 current_request->respond(".. reloading hosts table\n");
00408 else
00409 {
00410 current_request->respond("== filename required\n");
00411 return 0;
00412 }
00413
00414 Shell sh = Shell(fname);
00415 sh.configure(snort_conf);
00416
00417 tTargetBasedConfig* old = SFAT_GetConfig();
00418 tTargetBasedConfig* tc = SFAT_Swap();
00419
00420 if ( !tc )
00421 {
00422 current_request->respond("== reload failed\n");
00423 return 0;
00424 }
00425
00426 bool from_shell = ( L != nullptr );
00427 current_request->respond(".. swapping hosts table\n", from_shell);
00428 broadcast(get_command(new ACSwap(new Swapper(old, tc)), from_shell));
00429
00430 return 0;
00431 }
00432
00433 int main_delete_inspector(lua_State* L)
00434 {
00435 if ( Swapper::get_reload_in_progress() )
00436 {
00437 current_request->respond("== delete pending; retry\n");
00438 return 0;
00439 }
00440 const char* iname = nullptr;
00441
00442 if ( L )
00443 {
00444 Lua::ManageStack(L, 1);
00445 iname = luaL_checkstring(L, 1);
00446 }
00447
00448 if ( iname and *iname )
00449 current_request->respond(".. deleting inspector\n");
00450 else
00451 {
00452 current_request->respond("== inspector name required\n");
00453 return 0;
00454 }
00455
00456 SnortConfig* old = snort_conf;
00457 SnortConfig* sc = Snort::get_updated_policy(old, nullptr, iname);
00458
00459 if ( !sc )
00460 {
00461 current_request->respond("== reload failed\n");
00462 return 0;
00463 }
00464 snort_conf = sc;
00465 proc_stats.inspector_deletions++;
00466
00467 bool from_shell = ( L != nullptr );
00468 current_request->respond(".. deleted inspector\n", from_shell);
00469 broadcast(get_command(new ACSwap(new Swapper(old, sc)), from_shell));
00470
00471 return 0;
00472 }
00473
00474 int main_process(lua_State* L)
00475 {
00476 const char* f = lua_tostring(L, 1);
00477 if ( !f )
00478 {
00479 current_request->respond("== pcap filename required\n");
00480 return 0;
00481 }
00482 current_request->respond("== queuing pcap\n");
00483 Trough::add_source(Trough::SOURCE_LIST, f);
00484 return 0;
00485 }
00486
00487 int main_pause(lua_State* L)
00488 {
00489 bool from_shell = ( L != nullptr );
00490 current_request->respond("== pausing\n", from_shell);
00491 broadcast(get_command(new ACPause(), from_shell));
00492 paused = true;
00493 return 0;
00494 }
00495
00496 int main_resume(lua_State* L)
00497 {
00498 bool from_shell = ( L != nullptr );
00499 current_request->respond("== resuming\n", from_shell);
00500 broadcast(get_command(new ACResume(), from_shell));
00501 paused = false;
00502 return 0;
00503 }
00504
00505 #ifdef SHELL
00506 int main_detach(lua_State*)
00507 {
00508 current_request->respond("== detaching\n");
00509 return 0;
00510 }
00511
00512 int main_dump_plugins(lua_State*)
00513 {
00514 ModuleManager::dump_modules();
00515 PluginManager::dump_plugins();
00516 return 0;
00517 }
00518 #endif
00519
00520 int main_quit(lua_State* L)
00521 {
00522 bool from_shell = ( L != nullptr );
00523 current_request->respond("== stopping\n", from_shell);
00524 broadcast(get_command(new ACStop(), from_shell));
00525 exit_requested = true;
00526 return 0;
00527 }
00528
00529 int main_help(lua_State*)
00530 {
00531 const Command* cmd = get_snort_module()->get_commands();
00532
00533 while ( cmd->name )
00534 {
00535 std::string info = cmd->name;
00536 info += cmd->get_arg_list();
00537 info += ": ";
00538 info += cmd->help;
00539 info += "\n";
00540 current_request->respond(info.c_str());
00541 ++cmd;
00542 }
00543 return 0;
00544 }
00545
00546 //-------------------------------------------------------------------------
00547 // housekeeping foo
00548 //-------------------------------------------------------------------------
00549
00550 static int signal_check()
00551 {
00552 PigSignal s = get_pending_signal();
00553
00554 if ( s == PIG_SIG_NONE or s >= PIG_SIG_MAX )
00555 return 0;
00556
00557 LogMessage("** caught %s signal\n", get_signal_name(s));
00558
00559 switch ( s )
00560 {
00561 case PIG_SIG_QUIT:
00562 case PIG_SIG_TERM:
00563 main_quit();
00564 break;
00565
00566 case PIG_SIG_INT:
00567 if ( paused )
00568 main_resume(nullptr);
00569 else
00570 main_quit();
00571 break;
00572
00573 case PIG_SIG_RELOAD_CONFIG:
00574 main_reload_config();
00575 break;
00576
00577 case PIG_SIG_RELOAD_HOSTS:
00578 main_reload_hosts();
00579 break;
00580
00581 case PIG_SIG_DUMP_STATS:
00582 main_dump_stats();
00583 break;
00584
00585 case PIG_SIG_ROTATE_STATS:
00586 main_rotate_stats();
00587 break;
00588 default:
00589 break;
00590 }
00591 proc_stats.signals++;
00592 return 1;
00593 }
00594
00595 static void reap_commands()
00596 {
00597 for (unsigned idx = 0; idx < max_pigs; ++idx)
00598 pigs[idx].reap_commands();
00599
00600 while (!orphan_commands.empty())
00601 {
00602 AnalyzerCommand* ac = orphan_commands.front();
00603 orphan_commands.pop();
00604 DebugFormat(DEBUG_ANALYZER, "Destroying orphan command %s\n", ac->stringify());
00605 delete ac;
00606 }
00607 }
00608
00609 // FIXIT-L return true if something was done to avoid sleeping
00610 static bool house_keeping()
00611 {
00612 signal_check();
00613
00614 reap_commands();
00615
00616 IdleProcessing::execute();
00617
00618 Periodic::check();
00619
00620 InspectorManager::empty_trash();
00621
00622 return false;
00623 }
00624
00625 static void service_check()
00626 {
00627 #ifdef SHELL
00628 if ( ControlMgmt::service_users(current_fd, current_request) )
00629 return;
00630 #endif
00631
00632 if ( house_keeping() )
00633 return;
00634
00635 nanosleep(&main_sleep, nullptr);
00636 }
00637
00638 //-------------------------------------------------------------------------
00639 // main foo
00640 //-------------------------------------------------------------------------
00641
00642 static bool just_validate()
00643 {
00644 if ( SnortConfig::test_mode() )
00645 return true;
00646
00647 if ( use_shell(snort_conf) )
00648 return false;
00649
00650 /* FIXIT-L X This should really check if the DAQ module was unset as it could be explicitly
00651 set to the default value */
00652 if ( !strcmp(SFDAQ::get_type(), SFDAQ::default_type()) )
00653 {
00654 if ( SnortConfig::read_mode() && !Trough::get_queue_size() )
00655 return true;
00656
00657 if ( !SnortConfig::read_mode() && !SFDAQ::get_input_spec(snort_conf, 0) )
00658 return true;
00659 }
00660
00661 return false;
00662 }
00663
00664 static bool set_mode()
00665 {
00666 #ifdef PIGLET
00667 if ( Piglet::piglet_mode() )
00668 {
00669 // FIXIT-L the early return means that piglet and catch tests cannot
00670 // be run in the same process
00671 main_exit_code = Piglet::main();
00672 return false;
00673 }
00674 #endif
00675 #ifdef UNIT_TEST
00676 // FIXIT-M X we should move this out of set_mode and not do Snort bring up/teardown at all
00677 if ( catch_enabled() )
00678 {
00679 main_exit_code = catch_test();
00680 return false;
00681 }
00682 #endif
00683
00684 unsigned warnings = get_parse_warnings();
00685
00686 if ( unsigned k = get_parse_errors() )
00687 FatalError("see prior %u errors (%u warnings)\n", k, warnings);
00688
00689 if ( SnortConfig::conf_error_out() )
00690 {
00691 if ( warnings )
00692 FatalError("see prior %u warnings\n", warnings);
00693 }
00694
00695 if ( just_validate() )
00696 {
00697 LogMessage("\nSnort successfully validated the configuration (with %u warnings).\n",
00698 warnings);
00699
00700 // force test mode to exit w/o stats
00701 snort_conf->run_flags |= RUN_FLAG__TEST;
00702 return false;
00703 }
00704
00705 if ( snort_conf->run_flags & RUN_FLAG__PAUSE )
00706 {
00707 LogMessage("Paused; resume to start packet processing\n");
00708 paused = true;
00709 }
00710 else
00711 LogMessage("Commencing packet processing\n");
00712
00713 #ifdef SHELL
00714 if ( use_shell(snort_conf) )
00715 {
00716 LogMessage("Entering command shell\n");
00717 ControlMgmt::add_control(STDOUT_FILENO, true);
00718 }
00719 #endif
00720
00721 return true;
00722 }
00723
00724 static void handle(Pig& pig, unsigned& swine, unsigned& pending_privileges)
00725 {
00726 switch (pig.analyzer->get_state())
00727 {
00728 case Analyzer::State::NEW:
00729 pig.start();
00730 break;
00731
00732 case Analyzer::State::INITIALIZED:
00733 if (pig.analyzer->requires_privileged_start() && pending_privileges &&
00734 !Snort::has_dropped_privileges())
00735 {
00736 if (!pig.awaiting_privilege_change)
00737 {
00738 pig.awaiting_privilege_change = true;
00739 pending_privileges--;
00740 }
00741 if (pending_privileges)
00742 break;
00743 // FIXIT-L Make this call and the one below exit more gracefully upon error
00744 if (!Snort::drop_privileges())
00745 FatalError("Failed to drop privileges!\n");
00746
00747 Snort::do_pidfile();
00748 broadcast(new ACStart());
00749 }
00750 else
00751 {
00752 Snort::do_pidfile();
00753 pig.queue_command(new ACStart());
00754 }
00755 break;
00756
00757 case Analyzer::State::STARTED:
00758 if (!pig.analyzer->requires_privileged_start() && pending_privileges &&
00759 !Snort::has_dropped_privileges())
00760 {
00761 if (!pig.awaiting_privilege_change)
00762 {
00763 pig.awaiting_privilege_change = true;
00764 pending_privileges--;
00765 }
00766 if (pending_privileges)
00767 break;
00768
00769 if (!Snort::drop_privileges())
00770 FatalError("Failed to drop privileges!\n");
00771
00772 Snort::do_pidfile();
00773 broadcast(new ACRun(paused));
00774 }
00775 else
00776 {
00777 Snort::do_pidfile();
00778 pig.queue_command(new ACRun(paused));
00779 }
00780 break;
00781
00782 case Analyzer::State::STOPPED:
00783 pig.stop();
00784 --swine;
00785 break;
00786
00787 default:
00788 break;
00789 }
00790 }
00791
00792 static void main_loop()
00793 {
00794 unsigned swine = 0, pending_privileges = 0;
00795
00796 if (SnortConfig::change_privileges())
00797 pending_privileges = max_pigs;
00798
00799 // Preemptively prep all pigs in live traffic mode
00800 if (!SnortConfig::read_mode())
00801 {
00802 for (swine = 0; swine < max_pigs; swine++)
00803 pigs[swine].prep(SFDAQ::get_input_spec(snort_conf, swine));
00804 }
00805
00806 // Iterate over the drove, spawn them as allowed, and handle their deaths.
00807 // FIXIT-L X - If an exit has been requested, we might want to have some mechanism
00808 // for forcing inconsiderate pigs to die in timely fashion.
00809 while ( swine or paused or (Trough::has_next() and !exit_requested) )
00810 {
00811 const char* src;
00812 int idx = main_read();
00813
00814 if ( idx >= 0 )
00815 {
00816 Pig& pig = pigs[idx];
00817
00818 if ( pig.analyzer )
00819 handle(pig, swine, pending_privileges);
00820
00821 else if ( pending_privileges )
00822 pending_privileges--;
00823
00824 if ( !swine and exit_requested )
00825 break;
00826
00827 continue;
00828 }
00829 if ( !exit_requested and (swine < max_pigs) and (src = Trough::get_next()) )
00830 {
00831 Pig* pig = get_lazy_pig(max_pigs);
00832 pig->prep(src);
00833 ++swine;
00834 continue;
00835 }
00836 service_check();
00837 }
00838 }
00839
00840 static void snort_main()
00841 {
00842 #ifdef SHELL
00843 ControlMgmt::socket_init();
00844 #endif
00845
00846 max_pigs = ThreadConfig::get_instance_max();
00847 assert(max_pigs > 0);
00848
00849 pig_poke = new Ring<unsigned>(max_pigs+2);
00850 pigs = new Pig[max_pigs];
00851
00852 for (unsigned idx = 0; idx < max_pigs; idx++)
00853 {
00854 Pig& pig = pigs[idx];
00855 pig.set_index(idx);
00856 }
00857
00858 main_loop();
00859
00860 delete pig_poke;
00861 delete[] pigs;
00862 pigs = nullptr;
00863
00864 #ifdef SHELL
00865 ControlMgmt::socket_term();
00866 #endif
00867 }
00868
00869 int main(int argc, char* argv[])
00870 {
00871 set_mem_constraint_handler_s(log_safec_error);
00872 set_str_constraint_handler_s(log_safec_error);
00873
00874 const char* s = getenv("SNORT_PROMPT");
00875
00876 if ( s )
00877 prompt = s;
00878
00879
00880 Snort::setup(argc, argv);
00881
00882 if ( set_mode() )
00883 snort_main();
00884
00885 Snort::cleanup();
00886
00887 return main_exit_code;
00888 }
00889
END OF CODE