1 //-------------------------------------------------------------------------- 2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved. 3 // 4 // This program is free software; you can redistribute it and/or modify it 5 // under the terms of the GNU General Public License Version 2 as published 6 // by the Free Software Foundation. You may not use, modify or distribute 7 // this program under any other version of the GNU General Public License. 8 // 9 // This program is distributed in the hope that it will be useful, but 10 // WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License along 15 // with this program; if not, write to the Free Software Foundation, Inc., 16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 //-------------------------------------------------------------------------- 18 // analyzer.h author Michael Altizer <mialtize@cisco.com> 19 20 #ifndef ANALYZER_H 21 #define ANALYZER_H 22 23 // Analyzer provides the packet acquisition and processing loop. Since it 24 // runs in a different thread, it also provides a command facility so that 25 // to control the thread and swap configuration. 26 27 #include <daq_common.h> 28 29 #include <atomic> 30 #include <list> 31 #include <mutex> 32 #include <queue> 33 #include <string> 34 35 #include "thread.h" 36 37 class ContextSwitcher; 38 class OopsHandler; 39 class RetryQueue; 40 class Swapper; 41 42 namespace snort 43 { 44 class AnalyzerCommand; 45 class ReloadResourceTuner; 46 class SFDAQInstance; 47 struct Packet; 48 struct SnortConfig; 49 struct ProfileStats; 50 } 51 52 typedef bool (* MainHook_f)(snort::Packet*); 53 54 class UncompletedAnalyzerCommand 55 { 56 public: UncompletedAnalyzerCommand(snort::AnalyzerCommand * ac,void * acs)57 UncompletedAnalyzerCommand(snort::AnalyzerCommand* ac, void* acs) : command(ac), state(acs) 58 { } 59 60 snort::AnalyzerCommand* command; 61 void* state; 62 }; 63 64 class Analyzer 65 { 66 public: 67 enum class State { 68 NEW, 69 INITIALIZED, 70 STARTED, 71 RUNNING, 72 PAUSED, 73 STOPPED, 74 NUM_STATES 75 }; 76 77 static Analyzer* get_local_analyzer(); 78 static ContextSwitcher* get_switcher(); 79 static void set_main_hook(MainHook_f); 80 81 Analyzer(snort::SFDAQInstance*, unsigned id, const char* source, uint64_t msg_cnt = 0); 82 ~Analyzer(); 83 84 void operator()(Swapper*, uint16_t run_num); 85 get_state()86 State get_state() { return state; } 87 const char* get_state_string(); get_source()88 const char* get_source() { return source.c_str(); } 89 set_pause_after_cnt(uint64_t msg_cnt)90 void set_pause_after_cnt(uint64_t msg_cnt) { pause_after_cnt = msg_cnt; } set_skip_cnt(uint64_t msg_cnt)91 void set_skip_cnt(uint64_t msg_cnt) { skip_cnt = msg_cnt; } 92 93 void execute(snort::AnalyzerCommand*); 94 95 void post_process_packet(snort::Packet*); 96 bool process_rebuilt_packet(snort::Packet*, const DAQ_PktHdr_t*, const uint8_t* pkt, uint32_t pktlen); 97 bool inspect_rebuilt(snort::Packet*); 98 void finalize_daq_message(DAQ_Msg_h, DAQ_Verdict); 99 void add_to_retry_queue(DAQ_Msg_h); 100 101 // Functions called by analyzer commands 102 void start(); 103 void run(bool paused = false); 104 void stop(); 105 void pause(); 106 void resume(uint64_t msg_cnt); 107 void reload_daq(); 108 void reinit(const snort::SnortConfig*); 109 void stop_removed(const snort::SnortConfig*); 110 void rotate(); get_daq_instance()111 snort::SFDAQInstance* get_daq_instance() { return daq_instance; } 112 is_idling()113 bool is_idling() const 114 { return idling; } 115 116 private: 117 void analyze(); 118 bool handle_command(); 119 void handle_commands(); 120 void handle_uncompleted_commands(); 121 DAQ_RecvStatus process_messages(); 122 void process_daq_msg(DAQ_Msg_h, bool retry); 123 void process_daq_pkt_msg(DAQ_Msg_h, bool retry); 124 void post_process_daq_pkt_msg(snort::Packet*); 125 void process_retry_queue(); 126 void set_state(State); 127 void idle(); 128 bool init_privileged(); 129 void init_unprivileged(); 130 void term(); 131 void show_source(); 132 void add_command_to_uncompleted_queue(snort::AnalyzerCommand*, void*); 133 void add_command_to_completed_queue(snort::AnalyzerCommand*); 134 135 public: 136 std::queue<snort::AnalyzerCommand*> completed_work_queue; 137 std::mutex completed_work_queue_mutex; 138 std::queue<snort::AnalyzerCommand*> pending_work_queue; 139 140 private: 141 std::atomic<State> state; 142 unsigned id; 143 bool exit_requested = false; 144 bool idling = false; 145 uint64_t exit_after_cnt; 146 uint64_t pause_after_cnt = 0; 147 uint64_t skip_cnt = 0; 148 std::string source; 149 snort::SFDAQInstance* daq_instance; 150 RetryQueue* retry_queue = nullptr; 151 OopsHandler* oops_handler = nullptr; 152 ContextSwitcher* switcher = nullptr; 153 std::mutex pending_work_queue_mutex; 154 std::list<UncompletedAnalyzerCommand*> uncompleted_work_queue; 155 }; 156 157 extern THREAD_LOCAL snort::ProfileStats daqPerfStats; 158 159 #endif 160 161