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
00019 #ifdef HAVE_CONFIG_H
00020 #include "config.h"
00021 #endif
00022
00023 #include "flow/flow_control.h"
00024 #include "flow/prune_stats.h"
00025 #include "managers/inspector_manager.h"
00026 #include "profiler/profiler_defs.h"
00027 #include "protocols/packet.h"
00028 #include "stream/flush_bucket.h"
00029
00030 #include "stream_ha.h"
00031 #include "stream_module.h"
00032
00033 //-------------------------------------------------------------------------
00034 // stats
00035 //-------------------------------------------------------------------------
00036
00037 THREAD_LOCAL ProfileStats s5PerfStats;
00038 THREAD_LOCAL FlowControl* flow_con = nullptr;
00039
00040 static BaseStats g_stats;
00041 THREAD_LOCAL BaseStats stream_base_stats;
00042
00043 #define PROTO_PEGS(proto_str) \
00044 { CountType::SUM, proto_str "_flows", "total " proto_str " sessions" }, \
00045 { CountType::SUM, proto_str "_total_prunes", "total " proto_str " sessions pruned" }, \
00046 { CountType::SUM, proto_str "_idle_prunes", proto_str " sessions pruned due to timeout" }, \
00047 { CountType::SUM, proto_str "_excess_prunes", proto_str " sessions pruned due to excess" }, \
00048 { CountType::SUM, proto_str "_uni_prunes", proto_str " uni sessions pruned" }, \
00049 { CountType::SUM, proto_str "_preemptive_prunes", proto_str " sessions pruned during preemptive pruning" }, \
00050 { CountType::SUM, proto_str "_memcap_prunes", proto_str " sessions pruned due to memcap" }, \
00051 { CountType::SUM, proto_str "_ha_prunes", proto_str " sessions pruned by high availability sync" }
00052
00053 #define SET_PROTO_COUNTS(proto, pkttype) \
00054 stream_base_stats.proto ## _flows = flow_con->get_flows(PktType::pkttype); \
00055 stream_base_stats.proto ## _total_prunes = flow_con->get_total_prunes(PktType::pkttype), \
00056 stream_base_stats.proto ## _timeout_prunes = \
00057 flow_con->get_prunes(PktType::pkttype, PruneReason::IDLE), \
00058 stream_base_stats.proto ## _excess_prunes = \
00059 flow_con->get_prunes(PktType::pkttype, PruneReason::EXCESS), \
00060 stream_base_stats.proto ## _uni_prunes = \
00061 flow_con->get_prunes(PktType::pkttype, PruneReason::UNI), \
00062 stream_base_stats.proto ## _preemptive_prunes = \
00063 flow_con->get_prunes(PktType::pkttype, PruneReason::PREEMPTIVE), \
00064 stream_base_stats.proto ## _memcap_prunes = \
00065 flow_con->get_prunes(PktType::pkttype, PruneReason::MEMCAP), \
00066 stream_base_stats.proto ## _ha_prunes = \
00067 flow_con->get_prunes(PktType::pkttype, PruneReason::HA)
00068
00069 // FIXIT-L dependency on stats define in another file
00070 const PegInfo base_pegs[] =
00071 {
00072 PROTO_PEGS("ip"),
00073 PROTO_PEGS("icmp"),
00074 PROTO_PEGS("tcp"),
00075 PROTO_PEGS("udp"),
00076 PROTO_PEGS("user"),
00077 PROTO_PEGS("file"),
00078 { CountType::END, nullptr, nullptr }
00079 };
00080
00081 // FIXIT-L dependency on stats define in another file
00082 void base_sum()
00083 {
00084 if ( !flow_con )
00085 return;
00086
00087 SET_PROTO_COUNTS(ip, IP);
00088 SET_PROTO_COUNTS(icmp, ICMP);
00089 SET_PROTO_COUNTS(tcp, TCP);
00090 SET_PROTO_COUNTS(udp, UDP);
00091 SET_PROTO_COUNTS(user, PDU);
00092 SET_PROTO_COUNTS(file, FILE);
00093
00094 sum_stats((PegCount*)&g_stats, (PegCount*)&stream_base_stats,
00095 array_size(base_pegs)-1);
00096 }
00097
00098 void base_stats()
00099 {
00100 show_stats((PegCount*)&g_stats, base_pegs, array_size(base_pegs)-1, MOD_NAME);
00101 }
00102
00103 void base_reset()
00104 {
00105 if ( flow_con )
00106 flow_con->clear_counts();
00107
00108 memset(&stream_base_stats, 0, sizeof(stream_base_stats));
00109 }
00110
00111 //-------------------------------------------------------------------------
00112 // runtime support
00113 //-------------------------------------------------------------------------
00114
00115 static inline bool is_eligible(Packet* p)
00116 {
00117 // FIXIT-M extra check? bad checksums should be removed in detect.c snort_inspect()
00118 if ( p->ptrs.decode_flags & DECODE_ERR_CKSUM_IP )
00119 return false;
00120
00121 if ( p->packet_flags & PKT_REBUILT_STREAM )
00122 return false;
00123
00124 if ( !p->ptrs.ip_api.is_valid() )
00125 return false;
00126
00127 return true;
00128 }
00129
00130 //-------------------------------------------------------------------------
00131 // inspector stuff
00132 //-------------------------------------------------------------------------
00133
00134 class StreamBase : public Inspector
00135 {
00136 public:
00137 StreamBase(const StreamModuleConfig*);
00138
00139 void show(SnortConfig*) override;
00140
00141 void tinit() override;
00142 void tterm() override;
00143
00144 void eval(Packet*) override;
00145
00146 public:
00147 StreamModuleConfig config;
00148 };
00149
00150 StreamBase::StreamBase(const StreamModuleConfig* c)
00151 { config = *c; }
00152
00153 void StreamBase::tinit()
00154 {
00155 assert(!flow_con);
00156 flow_con = new FlowControl;
00157 InspectSsnFunc f;
00158
00159 StreamHAManager::tinit();
00160
00161 if ( config.ip_cfg.max_sessions )
00162 {
00163 if ( (f = InspectorManager::get_session((uint16_t)PktType::IP)) )
00164 flow_con->init_ip(config.ip_cfg, f);
00165 }
00166 if ( config.icmp_cfg.max_sessions )
00167 {
00168 if ( (f = InspectorManager::get_session((uint16_t)PktType::ICMP)) )
00169 flow_con->init_icmp(config.icmp_cfg, f);
00170 }
00171 if ( config.tcp_cfg.max_sessions )
00172 {
00173 if ( (f = InspectorManager::get_session((uint16_t)PktType::TCP)) )
00174 flow_con->init_tcp(config.tcp_cfg, f);
00175 }
00176 if ( config.udp_cfg.max_sessions )
00177 {
00178 if ( (f = InspectorManager::get_session((uint16_t)PktType::UDP)) )
00179 flow_con->init_udp(config.udp_cfg, f);
00180 }
00181 if ( config.user_cfg.max_sessions )
00182 {
00183 if ( (f = InspectorManager::get_session((uint16_t)PktType::PDU)) )
00184 flow_con->init_user(config.user_cfg, f);
00185 }
00186 if ( config.file_cfg.max_sessions )
00187 {
00188 if ( (f = InspectorManager::get_session((uint16_t)PktType::FILE)) )
00189 flow_con->init_file(config.file_cfg, f);
00190 }
00191 uint32_t max = config.tcp_cfg.max_sessions + config.udp_cfg.max_sessions
00192 + config.user_cfg.max_sessions;
00193
00194 if ( max > 0 )
00195 flow_con->init_exp(max);
00196
00197 FlushBucket::set(config.footprint);
00198 }
00199
00200 void StreamBase::tterm()
00201 {
00202 StreamHAManager::tterm();
00203 FlushBucket::clear();
00204 }
00205
00206 void StreamBase::show(SnortConfig*)
00207 {
00208 // FIXIT-L SSN print
00209 //StreamPrintGlobalConfig(&config);
00210 }
00211
00212 void StreamBase::eval(Packet* p)
00213 {
00214 Profile profile(s5PerfStats);
00215
00216
00217 //printf("StreamBase - %d\n", p->get_id());
00218
00219
00220 if ( !is_eligible(p) )
00221 return;
00222
00223 switch ( p->type() )
00224 {
00225 case PktType::IP:
00226 if ( p->has_ip() and
00227 ((p->ptrs.decode_flags & DECODE_FRAG) or !config.ip_frags_only) )
00228 flow_con->process_ip(p);
00229 break;
00230
00231 case PktType::ICMP:
00232 if ( p->ptrs.icmph )
00233 flow_con->process_icmp(p);
00234 break;
00235
00236 case PktType::TCP:
00237 if ( p->ptrs.tcph )
00238 flow_con->process_tcp(p);
00239 break;
00240
00241 case PktType::UDP:
00242 if ( p->ptrs.decode_flags & DECODE_FRAG )
00243 flow_con->process_ip(p);
00244
00245 if ( p->ptrs.udph )
00246 flow_con->process_udp(p);
00247 break;
00248
00249 case PktType::PDU:
00250 flow_con->process_user(p);
00251 break;
00252
00253 case PktType::FILE:
00254 flow_con->process_file(p);
00255 break;
00256
00257 default:
00258 break;
00259 }
00260 }
00261
00262 #if 0
00263 // FIXIT-L add method to get exp cache?
00264 LogMessage(" Expected Flows\n");
00265 LogMessage(" Expected: %lu\n", exp_cache->get_expects());
00266 LogMessage(" Realized: %lu\n", exp_cache->get_realized());
00267 LogMessage(" Pruned: %lu\n", exp_cache->get_prunes());
00268 LogMessage(" Overflows: %lu\n", exp_cache->get_overflows());
00269 #endif
00270
00271 //-------------------------------------------------------------------------
00272 // api stuff
00273 //-------------------------------------------------------------------------
00274
00275 static Module* mod_ctor()
00276 { return new StreamModule; }
00277
00278 static void mod_dtor(Module* m)
00279 { delete m; }
00280
00281 static Inspector* base_ctor(Module* m)
00282 {
00283 StreamModule* mod = (StreamModule*)m;
00284 return new StreamBase(mod->get_data());
00285 }
00286
00287 static void base_dtor(Inspector* p)
00288 {
00289 delete p;
00290 }
00291
00292 static void base_tterm()
00293 {
00294 delete flow_con;
00295 flow_con = nullptr;
00296 }
00297
00298 static const InspectApi base_api =
00299 {
00300 {
00301 PT_INSPECTOR,
00302 sizeof(InspectApi),
00303 INSAPI_VERSION,
00304 0,
00305 API_RESERVED,
00306 API_OPTIONS,
00307 MOD_NAME,
00308 MOD_HELP,
00309 mod_ctor,
00310 mod_dtor
00311 },
00312 IT_STREAM,
00313 (unsigned)PktType::ANY_SSN,
00314 nullptr, // buffers
00315 nullptr, // service
00316 nullptr, // init
00317 nullptr, // term
00318 nullptr, // tinit
00319 base_tterm,
00320 base_ctor,
00321 base_dtor,
00322 nullptr, // ssn
00323 nullptr // reset
00324 };
00325
00326 const BaseApi* nin_stream_base = &base_api.base;
00327
END OF CODE