00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 // Copyright (C) 2013-2013 Sourcefire, Inc.
00004 //
00005 // This program is free software; you can redistribute it and/or modify it
00006 // under the terms of the GNU General Public License Version 2 as published
00007 // by the Free Software Foundation. You may not use, modify or distribute
00008 // this program under any other version of the GNU General Public License.
00009 //
00010 // This program is distributed in the hope that it will be useful, but
00011 // WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program; if not, write to the Free Software Foundation, Inc.,
00017 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 //--------------------------------------------------------------------------
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include "snort.h"
00025
00026 #include <sys/stat.h>
00027 #include <syslog.h>
00028
00029 #include "actions/ips_actions.h"
00030 #include "codecs/codec_api.h"
00031 #include "connectors/connectors.h"
00032 #include "decompress/file_decomp.h"
00033 #include "detection/context_switcher.h"
00034 #include "detection/detect.h"
00035 #include "detection/detection_engine.h"
00036 #include "detection/detection_util.h"
00037 #include "detection/fp_config.h"
00038 #include "detection/fp_detect.h"
00039 #include "detection/ips_context.h"
00040 #include "detection/tag.h"
00041 #include "file_api/file_service.h"
00042 #include "filters/detection_filter.h"
00043 #include "filters/rate_filter.h"
00044 #include "filters/sfthreshold.h"
00045 #include "flow/ha.h"
00046 #include "framework/endianness.h"
00047 #include "framework/mpse.h"
00048 #include "helpers/base64_encoder.h"
00049 #include "helpers/process.h"
00050 #include "host_tracker/host_cache.h"
00051 #include "ips_options/ips_flowbits.h"
00052 #include "ips_options/ips_options.h"
00053 #include "latency/packet_latency.h"
00054 #include "latency/rule_latency.h"
00055 #include "log/log.h"
00056 #include "log/messages.h"
00057 #include "log/packet_tracer.h"
00058 #include "loggers/loggers.h"
00059 #include "main.h"
00060 #include "main/shell.h"
00061 #include "main/thread_config.h"
00062 #include "managers/action_manager.h"
00063 #include "managers/codec_manager.h"
00064 #include "managers/inspector_manager.h"
00065 #include "managers/ips_manager.h"
00066 #include "managers/event_manager.h"
00067 #include "managers/module_manager.h"
00068 #include "managers/mpse_manager.h"
00069 #include "managers/plugin_manager.h"
00070 #include "managers/script_manager.h"
00071 #include "memory/memory_cap.h"
00072 #include "network_inspectors/network_inspectors.h"
00073 #include "packet_io/active.h"
00074 #include "packet_io/sfdaq.h"
00075 #include "packet_io/trough.h"
00076 #include "parser/cmd_line.h"
00077 #include "parser/parser.h"
00078 #include "perf_monitor/perf_monitor.h"
00079 #include "profiler/profiler.h"
00080 #include "search_engines/search_engines.h"
00081 #include "service_inspectors/service_inspectors.h"
00082 #include "side_channel/side_channel.h"
00083 #include "stream/stream.h"
00084 #include "stream/stream_inspectors.h"
00085 #include "target_based/sftarget_reader.h"
00086 #include "time/packet_time.h"
00087 #include "time/periodic.h"
00088 #include "utils/kmap.h"
00089 #include "utils/util.h"
00090 #include "utils/util_utf.h"
00091 #include "utils/util_jsnorm.h"
00092 #include "main/snort_debug.h"
00093
00094 #ifdef PIGLET
00095 #include "piglet/piglet.h"
00096 #include "piglet/piglet_manager.h"
00097 #include "piglet_plugins/piglet_plugins.h"
00098 #endif
00099
00100 #ifdef SHELL
00101 #include "control_mgmt.h"
00102 #endif
00103
00104 #include "build.h"
00105 #include "snort_config.h"
00106 #include "thread_config.h"
00107
00108 using namespace std;
00109
00110 //-------------------------------------------------------------------------
00111
00112 static SnortConfig* snort_cmd_line_conf = nullptr;
00113 static pid_t snort_main_thread_pid = 0;
00114
00115 // non-local for easy access from core
00116 static THREAD_LOCAL DAQ_PktHdr_t s_pkth;
00117 static THREAD_LOCAL uint8_t s_data[65536];
00118 static THREAD_LOCAL Packet* s_packet = nullptr;
00119 static THREAD_LOCAL ContextSwitcher* s_switcher = nullptr;
00120
00121 ContextSwitcher* Snort::get_switcher()
00122 { return s_switcher; }
00123
00124 //-------------------------------------------------------------------------
00125 // perf stats
00126 // FIXIT-M move these to appropriate modules
00127 //-------------------------------------------------------------------------
00128
00129 static THREAD_LOCAL ProfileStats totalPerfStats;
00130 static THREAD_LOCAL ProfileStats metaPerfStats;
00131
00132 static ProfileStats* get_profile(const char* key)
00133 {
00134 if ( !strcmp(key, "detect") )
00135 return &detectPerfStats;
00136
00137 if ( !strcmp(key, "mpse") )
00138 return &mpsePerfStats;
00139
00140 if ( !strcmp(key, "rebuilt_packet") )
00141 return &rebuiltPacketPerfStats;
00142
00143 if ( !strcmp(key, "rule_eval") )
00144 return &rulePerfStats;
00145
00146 if ( !strcmp(key, "rtn_eval") )
00147 return &ruleRTNEvalPerfStats;
00148
00149 if ( !strcmp(key, "rule_tree_eval") )
00150 return &ruleOTNEvalPerfStats;
00151
00152 if ( !strcmp(key, "nfp_rule_tree_eval") )
00153 return &ruleNFPEvalPerfStats;
00154
00155 if ( !strcmp(key, "decode") )
00156 return &decodePerfStats;
00157
00158 if ( !strcmp(key, "eventq") )
00159 return &eventqPerfStats;
00160
00161 if ( !strcmp(key, "total") )
00162 return &totalPerfStats;
00163
00164 if ( !strcmp(key, "daq_meta") )
00165 return &metaPerfStats;
00166
00167 return nullptr;
00168 }
00169
00170 static void register_profiles()
00171 {
00172 Profiler::register_module("detect", nullptr, get_profile);
00173 Profiler::register_module("mpse", "detect", get_profile);
00174 Profiler::register_module("rebuilt_packet", "detect", get_profile);
00175 Profiler::register_module("rule_eval", "detect", get_profile);
00176 Profiler::register_module("rtn_eval", "rule_eval", get_profile);
00177 Profiler::register_module("rule_tree_eval", "rule_eval", get_profile);
00178 Profiler::register_module("nfp_rule_tree_eval", "rule_eval", get_profile);
00179 Profiler::register_module("decode", nullptr, get_profile);
00180 Profiler::register_module("eventq", nullptr, get_profile);
00181 Profiler::register_module("total", nullptr, get_profile);
00182 Profiler::register_module("daq_meta", nullptr, get_profile);
00183 }
00184
00185 //-------------------------------------------------------------------------
00186 // helpers
00187 //-------------------------------------------------------------------------
00188
00189 static void pass_pkts(Packet*) { }
00190 static MainHook_f main_hook = pass_pkts;
00191
00192 static void set_policy(Packet* p) // FIXIT-M delete this?
00193 {
00194 set_default_policy();
00195 p->user_inspection_policy_id = get_inspection_policy()->user_policy_id;
00196 p->user_ips_policy_id = get_ips_policy()->user_policy_id;
00197 p->user_network_policy_id = get_network_policy()->user_policy_id;
00198 }
00199
00200 static void show_source(const char* pcap)
00201 {
00202 if ( !SnortConfig::pcap_show() )
00203 return;
00204
00205 if ( !strcmp(pcap, "-") )
00206 pcap = "stdin";
00207
00208 static bool first = true;
00209 if ( first )
00210 first = false;
00211 else
00212 fprintf(stdout, "%s", "\n");
00213
00214 fprintf(stdout, "Reading network traffic from \"%s\" with snaplen = %u\n",
00215 pcap, SFDAQ::get_snap_len());
00216 }
00217
00218 //-------------------------------------------------------------------------
00219 // initialization
00220 //-------------------------------------------------------------------------
00221
00222 void Snort::init(int argc, char** argv)
00223 {
00224 init_signals();
00225 ThreadConfig::init();
00226
00227 #if defined(NOCOREFILE)
00228 SetNoCores();
00229 #else
00230 StoreSnortInfoStrings();
00231 #endif
00232
00233 InitProtoNames();
00234 SFAT_Init();
00235
00236 load_actions();
00237 load_codecs();
00238 load_connectors();
00239 load_ips_options();
00240 load_loggers();
00241 #ifdef PIGLET
00242 load_piglets();
00243 #endif
00244 load_search_engines();
00245 load_stream_inspectors();
00246 load_network_inspectors();
00247 load_service_inspectors();
00248
00249 /* chew up the command line */
00250 snort_cmd_line_conf = parse_cmd_line(argc, argv);
00251 snort_conf = snort_cmd_line_conf;
00252
00253 LogMessage("--------------------------------------------------\n");
00254 LogMessage("%s Snort++ %s-%s\n", get_prompt(), VERSION, BUILD);
00255 LogMessage("--------------------------------------------------\n");
00256
00257 #ifdef PIGLET
00258 Piglet::Manager::init();
00259 #endif
00260
00261 SideChannelManager::pre_config_init();
00262 HighAvailabilityManager::pre_config_init();
00263
00264 ModuleManager::init();
00265 ScriptManager::load_scripts(snort_cmd_line_conf->script_paths);
00266 PluginManager::load_plugins(snort_cmd_line_conf->plugin_path);
00267
00268 if ( snort_conf->logging_flags & LOGGING_FLAG__SHOW_PLUGINS )
00269 {
00270 ModuleManager::dump_modules();
00271 PluginManager::dump_plugins();
00272 }
00273
00274 FileService::init();
00275 register_profiles();
00276
00277 parser_init();
00278 SnortConfig* sc = ParseSnortConf(snort_cmd_line_conf);
00279
00280 /* Merge the command line and config file confs to take care of
00281 * command line overriding config file.
00282 * Set the global snort_conf that will be used during run time */
00283 sc->merge(snort_cmd_line_conf);
00284 snort_conf = sc;
00285
00286 #ifdef PIGLET
00287 if ( !Piglet::piglet_mode() )
00288 #endif
00289 CodecManager::instantiate();
00290
00291 #ifdef PIGLET
00292 if ( !Piglet::piglet_mode() )
00293 #endif
00294 if ( !snort_conf->output.empty() )
00295 EventManager::instantiate(snort_conf->output.c_str(), snort_conf);
00296
00297 if (SnortConfig::alert_before_pass())
00298 {
00299 OrderRuleLists(snort_conf, "drop sdrop reject alert pass log");
00300 }
00301
00302 snort_conf->setup();
00303
00304 FileService::post_init();
00305
00306 // Must be after CodecManager::instantiate()
00307 if ( !InspectorManager::configure(snort_conf) )
00308 ParseError("can't initialize inspectors");
00309 else if ( SnortConfig::log_verbose() )
00310 InspectorManager::print_config(snort_conf);
00311
00312 ModuleManager::reset_stats(snort_conf);
00313
00314 if (snort_conf->file_mask != 0)
00315 umask(snort_conf->file_mask);
00316 else
00317 umask(077); /* set default to be sane */
00318
00319 /* Need to do this after dynamic detection stuff is initialized, too */
00320 IpsManager::global_init(snort_conf);
00321
00322 snort_conf->post_setup();
00323
00324 MpseManager::activate_search_engine(
00325 snort_conf->fast_pattern_config->get_search_api(), snort_conf);
00326
00327 SFAT_Start();
00328
00329 #ifdef PIGLET
00330 if ( !Piglet::piglet_mode() )
00331 #endif
00332 /* Finish up the pcap list and put in the queues */
00333 Trough::setup();
00334
00335 // FIXIT-L refactor stuff done here and in snort_config.cc::VerifyReload()
00336 if ( snort_conf->bpf_filter.empty() && !snort_conf->bpf_file.empty() )
00337 snort_conf->bpf_filter = read_infile("bpf_file", snort_conf->bpf_file.c_str());
00338
00339 if ( !snort_conf->bpf_filter.empty() )
00340 LogMessage("Snort BPF option: %s\n", snort_conf->bpf_filter.c_str());
00341
00342 parser_term(snort_conf);
00343 }
00344
00345 // this function should only include initialization that must be done as a
00346 // non-root user such as creating log files. other initialization stuff should
00347 // be in the main initialization function since, depending on platform and
00348 // configuration, this may be running in a background thread while passing
00349 // packets in a fail open mode in the main thread. we don't want big delays
00350 // here to cause excess latency or dropped packets in that thread which may
00351 // be the case if all threads are pinned to a single cpu/core.
00352 //
00353 // clarification: once snort opens/starts the DAQ, packets are queued for snort
00354 // and must be disposed of quickly or the queue will overflow and packets will
00355 // be dropped so the fail open thread does the remaining initialization while
00356 // the main thread passes packets. prior to opening and starting the DAQ,
00357 // packet passing is done by the driver/hardware. the goal then is to put as
00358 // much initialization stuff in Snort::init() as possible and to restrict this
00359 // function to those things that depend on DAQ startup or non-root user/group.
00360
00361 bool Snort::drop_privileges()
00362 {
00363 /* Enter the chroot jail if necessary. */
00364 if (!snort_conf->chroot_dir.empty() &&
00365 !EnterChroot(snort_conf->chroot_dir, snort_conf->log_dir))
00366 return false;
00367
00368 /* Drop privileges if requested. */
00369 if (SnortConfig::get_uid() != -1 || SnortConfig::get_gid() != -1)
00370 {
00371 if (!SFDAQ::unprivileged())
00372 {
00373 ParseError("Cannot drop privileges - %s DAQ does not support unprivileged operation.\n",
00374 SFDAQ::get_type());
00375 return false;
00376 }
00377 if (!SetUidGid(SnortConfig::get_uid(), SnortConfig::get_gid()))
00378 return false;
00379 }
00380
00381 initializing = false;
00382 privileges_dropped = true;
00383
00384 return true;
00385 }
00386
00387 void Snort::do_pidfile()
00388 {
00389 static bool pid_file_created = false;
00390
00391 if (SnortConfig::create_pid_file() && !pid_file_created)
00392 {
00393 CreatePidFile(snort_main_thread_pid);
00394 pid_file_created = true;
00395 }
00396 }
00397
00398 //-------------------------------------------------------------------------
00399 // termination
00400 //-------------------------------------------------------------------------
00401
00402 void Snort::term()
00403 {
00404 /* This function can be called more than once. For example,
00405 * once from the SIGINT signal handler, and once recursively
00406 * as a result of calling pcap_close() below. We only need
00407 * to perform the cleanup once, however. So the static
00408 * variable already_exiting will act as a flag to prevent
00409 * double-freeing any memory. Not guaranteed to be
00410 * thread-safe, but it will prevent the simple cases.
00411 */
00412 static bool already_exiting = false;
00413 if ( already_exiting )
00414 return;
00415
00416 already_exiting = true;
00417 initializing = false; // just in case we cut out early
00418
00419 term_signals();
00420 IpsManager::global_term(snort_conf);
00421 SFAT_Cleanup();
00422 host_cache.clear();
00423
00424 #ifdef PIGLET
00425 if ( !Piglet::piglet_mode() )
00426 #endif
00427 Trough::cleanup();
00428
00429 ClosePidFile();
00430
00431 /* remove pid file */
00432 if ( !snort_conf->pid_filename.empty() )
00433 {
00434 int ret = unlink(snort_conf->pid_filename.c_str());
00435
00436 if (ret != 0)
00437 {
00438 ErrorMessage("Could not remove pid file %s: %s\n",
00439 snort_conf->pid_filename.c_str(), get_error(errno));
00440 }
00441 }
00442
00443 //MpseManager::print_search_engine_stats();
00444
00445 FileService::close();
00446
00447 sfthreshold_free(); // FIXDAQ etc.
00448 RateFilter_Cleanup();
00449
00450 Periodic::unregister_all();
00451
00452 /* free allocated memory */
00453 if (snort_conf == snort_cmd_line_conf)
00454 {
00455 delete snort_cmd_line_conf;
00456 snort_cmd_line_conf = nullptr;
00457 snort_conf = nullptr;
00458 }
00459 else
00460 {
00461 delete snort_cmd_line_conf;
00462 snort_cmd_line_conf = nullptr;
00463
00464 delete snort_conf;
00465 snort_conf = nullptr;
00466 }
00467 CleanupProtoNames();
00468 SideChannelManager::term();
00469 ModuleManager::term();
00470 PluginManager::release_plugins();
00471 ScriptManager::release_scripts();
00472 }
00473
00474 void Snort::clean_exit(int)
00475 {
00476 SnortConfig tmp;
00477
00478 // Have to trick LogMessage to log correctly after snort_conf is freed
00479 if ( snort_conf )
00480 {
00481 tmp.logging_flags |=
00482 (snort_conf->logging_flags & LOGGING_FLAG__QUIET);
00483
00484 tmp.run_flags |= (snort_conf->run_flags & RUN_FLAG__DAEMON);
00485
00486 tmp.logging_flags |=
00487 (snort_conf->logging_flags & LOGGING_FLAG__SYSLOG);
00488 }
00489
00490 term();
00491 snort_conf = &tmp;
00492
00493 LogMessage("%s Snort exiting\n", get_prompt());
00494 closelog();
00495 }
00496
00497 //-------------------------------------------------------------------------
00498 // public methods
00499 //-------------------------------------------------------------------------
00500
00501 bool Snort::initializing = true;
00502 bool Snort::reloading = false;
00503 bool Snort::privileges_dropped = false;
00504
00505 bool Snort::is_starting()
00506 { return initializing; }
00507
00508 bool Snort::is_reloading()
00509 { return reloading; }
00510
00511 bool Snort::has_dropped_privileges()
00512 { return privileges_dropped; }
00513
00514 void Snort::set_main_hook(MainHook_f f)
00515 { main_hook = f; }
00516
00517 Packet* Snort::get_packet()
00518 { return s_packet; }
00519
00520 void Snort::setup(int argc, char* argv[])
00521 {
00522 set_main_thread();
00523
00524 // must be done before any other files are opened because we
00525 // will try to grab file descriptor 3 (if --enable-stdlog)
00526 OpenLogger();
00527
00528 init(argc, argv);
00529
00530 LogMessage("%s\n", LOG_DIV);
00531 SFDAQ::init(snort_conf);
00532
00533 if ( SnortConfig::daemon_mode() )
00534 daemonize();
00535
00536 // this must follow daemonization
00537 snort_main_thread_pid = gettid();
00538
00539 /* Change groups */
00540 InitGroups(SnortConfig::get_uid(), SnortConfig::get_gid());
00541
00542 set_quick_exit(false);
00543
00544 // FIXIT-L eliminate keep_*() required for dynamic-only linkage
00545 keep_base64_encoder();
00546 keep_decomp_lib();
00547 keep_jsnorm_lib();
00548 keep_kmap_lib();
00549 keep_utf_lib();
00550
00551 memory::MemoryCap::calculate(ThreadConfig::get_instance_max());
00552 memory::MemoryCap::print();
00553
00554 TimeStart();
00555 }
00556
00557 void Snort::cleanup()
00558 {
00559 TimeStop();
00560
00561 SFDAQ::term();
00562
00563 if ( !SnortConfig::test_mode() ) // FIXIT-M ideally the check is in one place
00564 PrintStatistics();
00565
00566 CloseLogger();
00567 ThreadConfig::term();
00568 clean_exit(0);
00569 }
00570
00571 // FIXIT-M refactor this so startup and reload call the same core function to
00572 // instantiate things that can be reloaded
00573 SnortConfig* Snort::get_reload_config(const char* fname)
00574 {
00575 reloading = true;
00576 ModuleManager::reset_errors();
00577 trim_heap();
00578
00579 parser_init();
00580 SnortConfig* sc = ParseSnortConf(snort_cmd_line_conf, fname);
00581 sc->merge(snort_cmd_line_conf);
00582
00583 if ( ModuleManager::get_errors() || !sc->verify() )
00584 {
00585 parser_term(sc);
00586 delete sc;
00587 reloading = false;
00588 return nullptr;
00589 }
00590
00591 sc->setup();
00592
00593 #ifdef SHELL
00594 ControlMgmt::reconfigure_controls();
00595 #endif
00596
00597 if ( !InspectorManager::configure(sc) )
00598 {
00599 parser_term(sc);
00600 delete sc;
00601 reloading = false;
00602 return nullptr;
00603 }
00604
00605 FlowbitResetCounts(); // FIXIT-L updates global hash, put in sc
00606
00607 if ((sc->file_mask != 0) && (sc->file_mask != snort_conf->file_mask))
00608 umask(sc->file_mask);
00609
00610 // FIXIT-L is this still needed?
00611 /* Transfer any user defined rule type outputs to the new rule list */
00612 {
00613 RuleListNode* cur = snort_conf->rule_lists;
00614
00615 for (; cur != nullptr; cur = cur->next)
00616 {
00617 RuleListNode* rnew = sc->rule_lists;
00618
00619 for (; rnew != nullptr; rnew = rnew->next)
00620 {
00621 if (strcasecmp(cur->name, rnew->name) == 0)
00622 {
00623 EventManager::copy_outputs(
00624 rnew->RuleList->AlertList, cur->RuleList->AlertList);
00625
00626 EventManager::copy_outputs(
00627 rnew->RuleList->LogList, cur->RuleList->LogList);
00628 break;
00629 }
00630 }
00631 }
00632 }
00633
00634 sc->post_setup();
00635
00636 if ( sc->fast_pattern_config->get_search_api() !=
00637 snort_conf->fast_pattern_config->get_search_api() )
00638 {
00639 MpseManager::activate_search_engine(sc->fast_pattern_config->get_search_api(), sc);
00640 }
00641
00642 reloading = false;
00643 parser_term(sc);
00644
00645 return sc;
00646 }
00647
00648 SnortConfig* Snort::get_updated_policy(SnortConfig* other_conf, const char* fname, const char* iname)
00649 {
00650 reloading = true;
00651
00652 SnortConfig* sc = new SnortConfig(other_conf);
00653
00654 if ( fname )
00655 {
00656 Shell sh = Shell(fname);
00657 sh.configure(sc);
00658
00659 if ( ModuleManager::get_errors() || !sc->verify() )
00660 {
00661 sc->cloned = true;
00662 InspectorManager::update_policy(other_conf);
00663 delete sc;
00664 set_default_policy(other_conf);
00665 reloading = false;
00666 return nullptr;
00667 }
00668 }
00669
00670 if ( iname )
00671 {
00672 if ( !InspectorManager::delete_inspector(sc, iname) )
00673 {
00674 sc->cloned = true;
00675 InspectorManager::update_policy(other_conf);
00676 delete sc;
00677 set_default_policy(other_conf);
00678 reloading = false;
00679 return nullptr;
00680 }
00681 }
00682
00683 if ( !InspectorManager::configure(sc, true) )
00684 {
00685 sc->cloned = true;
00686 InspectorManager::update_policy(other_conf);
00687 delete sc;
00688 set_default_policy(other_conf);
00689 reloading = false;
00690 return nullptr;
00691 }
00692
00693 other_conf->cloned = true;
00694
00695 InspectorManager::update_policy(sc);
00696 reloading = false;
00697 return sc;
00698 }
00699
00700 void Snort::capture_packet()
00701 {
00702 if ( snort_main_thread_pid == gettid() )
00703 {
00704 // FIXIT-L main thread crashed. Do anything?
00705 }
00706 else
00707 {
00708 // Copy the crashed threads data. C++11 specs ensure the
00709 // thread that segfaulted will still be running.
00710 if ( s_packet && s_packet->pkth )
00711 {
00712 s_pkth = *(s_packet->pkth);
00713
00714 if ( s_packet->pkt )
00715 {
00716 memcpy(s_data, s_packet->pkt, 0xFFFF & s_packet->pkth->caplen);
00717 s_packet->pkt = s_data;
00718 }
00719 }
00720 }
00721 }
00722
00723 void Snort::thread_idle()
00724 {
00725 Stream::timeout_flows(time(nullptr));
00726 perf_monitor_idle_process();
00727 aux_counts.idle++;
00728 HighAvailabilityManager::process_receive();
00729 }
00730
00731 void Snort::thread_rotate()
00732 {
00733 SetRotatePerfFileFlag();
00734 }
00735
00736 /*
00737 * Perform all packet thread initialization actions that need to be taken with escalated privileges
00738 * prior to starting the DAQ module.
00739 */
00740 bool Snort::thread_init_privileged(const char* intf)
00741 {
00742 show_source(intf);
00743
00744 snort_conf->thread_config->implement_thread_affinity(STHREAD_TYPE_PACKET, get_instance_id());
00745
00746 // FIXIT-M the start-up sequence is a little off due to dropping privs
00747 SFDAQInstance *daq_instance = new SFDAQInstance(intf);
00748 SFDAQ::set_local_instance(daq_instance);
00749 if (!daq_instance->configure(snort_conf))
00750 {
00751 SFDAQ::set_local_instance(nullptr);
00752 delete daq_instance;
00753 return false;
00754 }
00755
00756 return true;
00757 }
00758
00759 /*
00760 * Perform all packet thread initialization actions that can be taken with dropped privileges
00761 * and/or must be called after the DAQ module has been started.
00762 */
00763 void Snort::thread_init_unprivileged()
00764 {
00765 // using dummy values until further integration
00766 const unsigned max_contexts = 20;
00767
00768 s_switcher = new ContextSwitcher(max_contexts);
00769
00770 for ( unsigned i = 0; i < max_contexts; ++i )
00771 s_switcher->push(new IpsContext);
00772
00773 CodecManager::thread_init(snort_conf);
00774
00775 // this depends on instantiated daq capabilities
00776 // so it is done here instead of init()
00777 Active::init(snort_conf);
00778
00779 InitTag();
00780 EventTrace_Init();
00781 detection_filter_init(snort_conf->detection_filter_config);
00782 DetectionEngine::thread_init();
00783
00784 EventManager::open_outputs();
00785 IpsManager::setup_options();
00786 ActionManager::thread_init(snort_conf);
00787 FileService::thread_init();
00788 SideChannelManager::thread_init();
00789 HighAvailabilityManager::thread_init(); // must be before InspectorManager::thread_init();
00790 InspectorManager::thread_init(snort_conf);
00791 PacketTracer::thread_init();
00792 if (SnortConfig::packet_trace_enabled())
00793 PacketTracer::enable_user_trace();
00794
00795 // in case there are HA messages waiting, process them first
00796 HighAvailabilityManager::process_receive();
00797 }
00798
00799 void Snort::thread_term()
00800 {
00801 HighAvailabilityManager::thread_term_beginning();
00802
00803 if ( !snort_conf->dirty_pig )
00804 Stream::purge_flows();
00805
00806 DetectionEngine::idle();
00807 InspectorManager::thread_stop(snort_conf);
00808 ModuleManager::accumulate(snort_conf);
00809 InspectorManager::thread_term(snort_conf);
00810 ActionManager::thread_term(snort_conf);
00811
00812 IpsManager::clear_options();
00813 EventManager::close_outputs();
00814 CodecManager::thread_term();
00815 HighAvailabilityManager::thread_term();
00816 SideChannelManager::thread_term();
00817
00818 s_packet = nullptr;
00819
00820 SFDAQInstance *daq_instance = SFDAQ::get_local_instance();
00821 if ( daq_instance->was_started() )
00822 daq_instance->stop();
00823 SFDAQ::set_local_instance(nullptr);
00824 delete daq_instance;
00825
00826 PacketLatency::tterm();
00827 RuleLatency::tterm();
00828
00829 Profiler::consolidate_stats();
00830
00831 DetectionEngine::thread_term();
00832 detection_filter_term();
00833 EventTrace_Term();
00834 CleanupTag();
00835 FileService::thread_term();
00836 PacketTracer::thread_term();
00837
00838 Active::term();
00839 delete s_switcher;
00840 }
00841
00842 void Snort::inspect(Packet* p)
00843 {
00844 // Need to include this b/c call is outside the detect tree
00845 Profile detect_profile(detectPerfStats);
00846 Profile rebuilt_profile(rebuiltPacketPerfStats);
00847
00848 DetectionEngine de;
00849 main_hook(p);
00850
00851 //upload_pseudo_packet(p);
00852
00853 }
00854
00855 DAQ_Verdict Snort::process_packet(
00856 Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, bool is_frag)
00857 {
00858 aux_counts.rx_bytes += pkthdr->caplen;
00859
00860 PacketManager::decode(p, pkthdr, pkt);
00861 assert(p->pkth && p->pkt);
00862
00863 PacketTracer::add_header_info(p);
00864
00865 if (is_frag)
00866 {
00867 p->packet_flags |= (PKT_PSEUDO | PKT_REBUILT_FRAG);
00868 p->pseudo_type = PSEUDO_PKT_IP;
00869 }
00870
00871 set_policy(p); // FIXIT-M should not need this here
00872
00873 //printf("process_packet - %d\n", p->get_id());
00874
00875 if ( !(p->packet_flags & PKT_IGNORE) )
00876 {
00877 //printf("process_packet - %d\n", p->get_id());
00878 clear_file_data();
00879 main_hook(p);
00880
00881 //upload_DAQ_packet(p);
00882
00883 } else {
00884 printf("process_packet - packet ignored - %d\n", p->get_id());
00885 }
00886
00887 // process flow verdicts here
00888 if ( Active::packet_retry_requested() )
00889 {
00890 return DAQ_VERDICT_RETRY;
00891 }
00892 else if ( Active::session_was_blocked() )
00893 {
00894 if ( !Active::can_block() )
00895 return DAQ_VERDICT_PASS;
00896
00897 if ( Active::get_tunnel_bypass() )
00898 {
00899 aux_counts.internal_blacklist++;
00900 return DAQ_VERDICT_PASS;
00901 }
00902
00903 if ( SnortConfig::inline_mode() || Active::packet_force_dropped() )
00904 return DAQ_VERDICT_BLACKLIST;
00905 else
00906 return DAQ_VERDICT_IGNORE;
00907 }
00908
00909 return DAQ_VERDICT_PASS;
00910 }
00911
00912 // process (wire-only) packet verdicts here
00913 static DAQ_Verdict update_verdict(DAQ_Verdict verdict, int& inject)
00914 {
00915 // FIXIT-M X PKT_RESIZED is a superset of PKT_MODIFIED, so this conditional is broken
00916 if ( Active::packet_was_dropped() and Active::can_block() )
00917 {
00918 if ( verdict == DAQ_VERDICT_PASS )
00919 verdict = DAQ_VERDICT_BLOCK;
00920 }
00921 else if ( s_packet->packet_flags & PKT_MODIFIED )
00922 {
00923 // this packet was normalized and/or has replacements
00924 PacketManager::encode_update(s_packet);
00925 verdict = DAQ_VERDICT_REPLACE;
00926 }
00927 else if ( s_packet->packet_flags & PKT_RESIZED )
00928 {
00929 // we never increase, only trim, but
00930 // daq doesn't support resizing wire packet
00931 if ( !SFDAQ::inject(s_packet->pkth, 0, s_packet->pkt, s_packet->pkth->pktlen) )
00932 {
00933 inject = 1;
00934 verdict = DAQ_VERDICT_BLOCK;
00935 }
00936 }
00937 else if ( (s_packet->packet_flags & PKT_IGNORE) ||
00938 (s_packet->flow && s_packet->flow->get_ignore_direction( ) == SSN_DIR_BOTH) )
00939 {
00940 if ( !Active::get_tunnel_bypass() )
00941 {
00942 verdict = DAQ_VERDICT_WHITELIST;
00943 }
00944 else
00945 {
00946 verdict = DAQ_VERDICT_PASS;
00947 aux_counts.internal_whitelist++;
00948 }
00949 }
00950 else if ( s_packet->ptrs.decode_flags & DECODE_PKT_TRUST )
00951 {
00952 if (s_packet->flow)
00953 s_packet->flow->set_ignore_direction(SSN_DIR_BOTH);
00954 verdict = DAQ_VERDICT_WHITELIST;
00955 }
00956 else
00957 {
00958 verdict = DAQ_VERDICT_PASS;
00959 }
00960 return verdict;
00961 }
00962
00963 DAQ_Verdict Snort::packet_callback(
00964 void*, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt)
00965 {
00966 if (pkthdr->flags & DAQ_PKT_FLAG_TRACE_ENABLED)
00967 PacketTracer::enable_daq_trace();
00968 else
00969 PacketTracer::disable_daq_trace();
00970
00971
00972 set_default_policy();
00973 Profile profile(totalPerfStats);
00974
00975 pc.total_from_daq++;
00976 packet_time_update(&pkthdr->ts);
00977
00978 if ( snort_conf->pkt_skip && pc.total_from_daq <= snort_conf->pkt_skip )
00979 return DAQ_VERDICT_PASS;
00980
00981 s_switcher->start();
00982 s_packet = s_switcher->get_context()->packet;
00983 DetectionEngine::reset();
00984
00985 sfthreshold_reset();
00986 ActionManager::reset_queue();
00987
00988
00989 //printf("packet_callback - %d\n", s_packet->get_id());
00990
00991 DAQ_Verdict verdict = process_packet(s_packet, pkthdr, pkt);
00992 ActionManager::execute(s_packet);
00993
00994 int inject = 0;
00995 verdict = update_verdict(verdict, inject);
00996
00997 PacketTracer::log("NAP id %u, IPS id %u, Verdict %s\n",
00998 get_network_policy()->policy_id, get_ips_policy()->policy_id,
00999 SFDAQ::verdict_to_string(verdict));
01000
01001 PacketTracer::dump(pkthdr, verdict);
01002
01003 HighAvailabilityManager::process_update(s_packet->flow, pkthdr);
01004
01005 Active::reset();
01006 Stream::timeout_flows(pkthdr->ts.tv_sec);
01007 HighAvailabilityManager::process_receive();
01008
01009 s_packet->pkth = nullptr; // no longer avail upon sig segv
01010
01011 if ( snort_conf->pkt_cnt && pc.total_from_daq >= snort_conf->pkt_cnt )
01012 SFDAQ::break_loop(-1);
01013
01014 else if ( break_time() )
01015 SFDAQ::break_loop(0);
01016
01017 s_switcher->stop();
01018
01019 return verdict;
01020 }
01021
END OF CODE