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