+104
+-- changed configure --with-libpcre-* to --with-pcre-* for consistency
+-- same for pcap (again!)
+-- added stream_size and stream_reassemble ips options
+
103
-- added modules to ips options
-- removed ips option sameip which was obsoleted by 116:152
# with foo
#--------------------------------------------------------------------------
-AC_ARG_WITH(libpcap_includes,
+AC_ARG_WITH(pcap_includes,
[ --with-pcap-includes=DIR libpcap include directory],
[with_libpcap_includes="$withval"],[with_libpcap_includes="no"])
CPPFLAGS="${CPPFLAGS} -I${with_libpcap_includes}"
fi
-AC_ARG_WITH(libpcap_libraries,
+AC_ARG_WITH(pcap_libraries,
[ --with-pcap-libraries=DIR libpcap library directory],
[with_libpcap_libraries="$withval"],[with_libpcap_libraries="no"])
fi
fi
-AC_ARG_WITH(libpcre_includes,
+AC_ARG_WITH(pcre_includes,
[ --with-pcre-includes=DIR libpcre include directory],
[with_libpcre_includes="$withval"],[with_libpcre_includes="no"])
CPPFLAGS="${CPPFLAGS} `pcre-config --cflags`"
fi
-AC_ARG_WITH(libpcre_libraries,
+AC_ARG_WITH(pcre_libraries,
[ --with-pcre-libraries=DIR libpcre library directory],
[with_libpcre_libraries="$withval"],[with_libpcre_libraries="no"])
extern const BaseApi* nin_stream_tcp;
extern const BaseApi* nin_stream_udp;
+extern const BaseApi* ips_stream_reassemble;
+extern const BaseApi* ips_stream_size;
+
#ifdef STATIC_INSPECTORS
extern const BaseApi* nin_arp_spoof;
extern const BaseApi* nin_port_scan_global;
nin_stream_icmp,
nin_stream_tcp,
nin_stream_udp,
+
+ ips_stream_reassemble,
+ ips_stream_size,
+
#ifdef STATIC_INSPECTORS
nin_arp_spoof,
nin_port_scan_global,
tcp_module.h
tcp_session.cc
tcp_session.h
+ ips_stream_reassemble.cc
+ ips_stream_size.cc
)
tcp_module.cc \
tcp_module.h \
tcp_session.cc \
-tcp_session.h
+tcp_session.h \
+ips_stream_reassemble.cc \
+ips_stream_size.cc
AM_CXXFLAGS = @AM_CXXFLAGS@
--- /dev/null
+/****************************************************************************
+ * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation. You may not use, modify or
+ * distribute this program under any other version of the GNU General
+ * Public License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ****************************************************************************/
+
+// ips_stream_reassemble.cc author Russ Combs <rucombs@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tcp_session.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+#include "framework/parameter.h"
+#include "detection/detect.h"
+#include "hash/sfhashfcn.h"
+#include "time/profiler.h"
+
+//-------------------------------------------------------------------------
+// stream_reassemble
+//-------------------------------------------------------------------------
+
+#define IPS_REASS "stream_reassemble"
+
+static THREAD_LOCAL ProfileStats streamReassembleRuleOptionPerfStats;
+
+struct StreamReassembleRuleOptionData
+{
+ char enable;
+ char alert;
+ char direction;
+ char fastpath;
+};
+
+class ReassembleOption : public IpsOption
+{
+public:
+ ReassembleOption(const StreamReassembleRuleOptionData& c) :
+ IpsOption(IPS_REASS)
+ { srod = c; };
+
+ uint32_t hash() const;
+ bool operator==(const IpsOption&) const;
+
+ int eval(Cursor&, Packet*);
+
+private:
+ StreamReassembleRuleOptionData srod;
+};
+
+//-------------------------------------------------------------------------
+// stream_reassemble option
+//-------------------------------------------------------------------------
+
+uint32_t ReassembleOption::hash() const
+{
+ uint32_t a,b,c;
+
+ a = srod.enable;
+ b = srod.direction;
+ c = srod.alert;
+
+ mix(a,b,c);
+
+ a = srod.fastpath;
+
+ mix_str(a,b,c,get_name());
+ final(a,b,c);
+
+ return c;
+}
+
+bool ReassembleOption::operator==(const IpsOption& ips) const
+{
+ if ( strcmp(get_name(), ips.get_name()) )
+ return false;
+
+ const ReassembleOption& rhs = (ReassembleOption&)ips;
+
+ if ( (srod.enable == rhs.srod.enable) &&
+ (srod.direction == rhs.srod.direction) &&
+ (srod.alert == rhs.srod.alert) )
+ return true;
+
+ return false;
+}
+
+int ReassembleOption::eval(Cursor&, Packet* pkt)
+{
+ if (!pkt->flow || !pkt->tcph)
+ return 0;
+
+ PROFILE_VARS;
+ PREPROC_PROFILE_START(streamReassembleRuleOptionPerfStats);
+
+ Flow *lwssn = (Flow*)pkt->flow;
+ TcpSession* tcpssn = (TcpSession*)lwssn->session;
+
+ if ( !srod.enable ) /* Turn it off */
+ {
+ if ( srod.direction & SSN_DIR_SERVER )
+ tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
+
+ if ( srod.direction & SSN_DIR_CLIENT )
+ tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
+ }
+ else
+ {
+ // FIXIT PAF need to instantiate atom splitter?
+ // FIXIT PAF need to check for ips / on-data
+ if ( srod.direction & SSN_DIR_SERVER )
+ tcpssn->server.flush_policy = STREAM_FLPOLICY_ON_ACK;
+
+ if ( srod.direction & SSN_DIR_CLIENT )
+ tcpssn->client.flush_policy = STREAM_FLPOLICY_ON_ACK;
+ }
+
+ if (srod.fastpath)
+ {
+ /* Turn off inspection */
+ lwssn->s5_state.ignore_direction |= srod.direction;
+ DisableInspection(pkt);
+
+ /* TBD: Set TF_FORCE_FLUSH ? */
+ }
+
+ PREPROC_PROFILE_END(streamReassembleRuleOptionPerfStats);
+
+ if (srod.alert)
+ return DETECTION_OPTION_MATCH;
+
+ return DETECTION_OPTION_NO_ALERT;
+}
+
+//-------------------------------------------------------------------------
+// stream_reassemble module
+//-------------------------------------------------------------------------
+
+static const Parameter reassemble_params[] =
+{
+ { "*action", Parameter::PT_ENUM, "disable|enable", nullptr,
+ "stop or start stream reassembly" },
+
+ { "*direction", Parameter::PT_ENUM, "client|server|both", nullptr,
+ "action applies to the given direction(s)" },
+
+ { "noalert", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "don't alert when rule matches" },
+
+ { "fastpath", Parameter::PT_IMPLIED, nullptr, nullptr,
+ "optionally whitelist the remainder of the session" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+class ReassembleModule : public Module
+{
+public:
+ ReassembleModule() : Module(IPS_REASS, reassemble_params) { };
+
+ bool begin(const char*, int, SnortConfig*);
+ bool set(const char*, Value&, SnortConfig*);
+
+ ProfileStats* get_profile() const
+ { return &streamReassembleRuleOptionPerfStats; };
+
+ StreamReassembleRuleOptionData srod;
+};
+
+bool ReassembleModule::begin(const char*, int, SnortConfig*)
+{
+ srod.enable = 0;
+ srod.direction = 0;
+ srod.alert = 1;
+ srod.fastpath = 0;
+ return true;
+}
+
+bool ReassembleModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("*action") )
+ srod.enable = v.get_long();
+
+ else if ( v.is("*direction") )
+ srod.enable = v.get_long() + 1;
+
+ else if ( v.is("noalert") )
+ srod.alert = 0;
+
+ else if ( v.is("fastpath") )
+ srod.fastpath = 0;
+
+ else
+ return false;
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// stream_reassemble api methods
+//-------------------------------------------------------------------------
+
+static Module* reassemble_mod_ctor()
+{
+ return new ReassembleModule;
+}
+
+static void mod_dtor(Module* m)
+{
+ delete m;
+}
+
+static IpsOption* reassemble_ctor(Module* p, OptTreeNode*)
+{
+ ReassembleModule* m = (ReassembleModule*)p;
+ return new ReassembleOption(m->srod);
+}
+
+static void opt_dtor(IpsOption* p)
+{
+ delete p;
+}
+
+static const IpsApi reassemble_api =
+{
+ {
+ PT_IPS_OPTION,
+ IPS_REASS,
+ IPSAPI_PLUGIN_V0,
+ 0,
+ reassemble_mod_ctor,
+ mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 1, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ reassemble_ctor,
+ opt_dtor,
+ nullptr
+};
+
+const BaseApi* ips_stream_reassemble = &reassemble_api.base;
+
--- /dev/null
+/****************************************************************************
+ * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation. You may not use, modify or
+ * distribute this program under any other version of the GNU General
+ * Public License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ ****************************************************************************/
+
+// ips_stream_size.cc author Russ Combs <rucombs@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tcp_session.h"
+#include "framework/ips_option.h"
+#include "framework/module.h"
+#include "framework/parameter.h"
+#include "detection/detect.h"
+#include "hash/sfhashfcn.h"
+#include "time/profiler.h"
+
+enum SsodOp
+{
+ SSOD_EQ = 1,
+ SSOD_NE,
+ SSOD_LT,
+ SSOD_GT,
+ SSOD_LE,
+ SSOD_GE,
+ SSOD_MAX
+};
+
+struct StreamSizeOptionData
+{
+ SsodOp opcode;
+ uint32_t size;
+ char direction;
+
+ bool compare(uint32_t, uint32_t);
+};
+
+bool StreamSizeOptionData::compare(uint32_t size1, uint32_t size2)
+{
+ switch (opcode)
+ {
+ case SSOD_EQ:
+ return (size1 == size2);
+
+ case SSOD_NE:
+ return (size1 != size2);
+
+ case SSOD_LT:
+ return (size1 < size2);
+
+ case SSOD_GT:
+ return (size1 > size2);
+
+ case SSOD_LE:
+ return (size1 <= size2);
+
+ case SSOD_GE:
+ return (size1 >= size2);
+
+ default:
+ break;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------
+// stream_size
+//-------------------------------------------------------------------------
+
+#define IPS_SIZE "stream_size"
+
+static THREAD_LOCAL ProfileStats streamSizePerfStats;
+
+class SizeOption : public IpsOption
+{
+public:
+ SizeOption(const StreamSizeOptionData& c) :
+ IpsOption(IPS_SIZE)
+ { ssod = c; };
+
+ uint32_t hash() const;
+ bool operator==(const IpsOption&) const;
+
+ int eval(Cursor&, Packet*);
+
+private:
+ StreamSizeOptionData ssod;
+};
+
+//-------------------------------------------------------------------------
+// stream_size option
+//-------------------------------------------------------------------------
+
+uint32_t SizeOption::hash() const
+{
+ uint32_t a,b,c;
+
+ a = ssod.direction;
+ b = ssod.opcode;
+ c = ssod.size;
+
+ mix(a,b,c);
+ mix_str(a,b,c,get_name());
+ final(a,b,c);
+
+ return c;
+}
+
+bool SizeOption::operator==(const IpsOption& ips) const
+{
+ if ( strcmp(get_name(), ips.get_name()) )
+ return false;
+
+ const SizeOption& rhs = (SizeOption&)ips;
+
+ if ( (ssod.direction == rhs.ssod.direction) &&
+ (ssod.opcode == rhs.ssod.opcode) &&
+ (ssod.size == rhs.ssod.size) )
+ return true;
+
+ return false;
+}
+
+int SizeOption::eval(Cursor&, Packet* pkt)
+{
+ if (!pkt->flow || !pkt->tcph)
+ return DETECTION_OPTION_NO_MATCH;
+
+ PROFILE_VARS;
+ PREPROC_PROFILE_START(streamSizePerfStats);
+
+ Flow *lwssn = (Flow*)pkt->flow;
+ TcpSession *tcpssn = (TcpSession*)lwssn->session;
+
+ uint32_t client_size;
+ uint32_t server_size;
+
+ if (tcpssn->client.l_nxt_seq > tcpssn->client.isn)
+ {
+ /* the normal case... */
+ client_size = tcpssn->client.l_nxt_seq - tcpssn->client.isn;
+ }
+ else
+ {
+ /* the seq num wrapping case... */
+ client_size = tcpssn->client.isn - tcpssn->client.l_nxt_seq;
+ }
+ if (tcpssn->server.l_nxt_seq > tcpssn->server.isn)
+ {
+ /* the normal case... */
+ server_size = tcpssn->server.l_nxt_seq - tcpssn->server.isn;
+ }
+ else
+ {
+ /* the seq num wrapping case... */
+ server_size = tcpssn->server.isn - tcpssn->server.l_nxt_seq;
+ }
+
+ int result;
+
+ switch (ssod.direction)
+ {
+ case SSN_DIR_CLIENT:
+ if ( ssod.compare(client_size, ssod.size) )
+ result = DETECTION_OPTION_MATCH;
+ break;
+
+ case SSN_DIR_SERVER:
+ if ( ssod.compare(server_size, ssod.size) )
+ result = DETECTION_OPTION_MATCH;
+ break;
+
+ case SSN_DIR_NONE: /* overloaded. really, its an 'either' */
+ if ( ssod.compare(client_size, ssod.size) ||
+ ssod.compare(server_size, ssod.size) )
+ {
+ result = DETECTION_OPTION_MATCH;
+ }
+ break;
+
+ case SSN_DIR_BOTH:
+ if ( ssod.compare(client_size, ssod.size) &&
+ ssod.compare(server_size, ssod.size) )
+ {
+ result = DETECTION_OPTION_MATCH;
+ }
+ break;
+
+ default:
+ result = DETECTION_OPTION_NO_MATCH;
+ break;
+ }
+ PREPROC_PROFILE_END(streamSizePerfStats);
+ return result;
+}
+
+//-------------------------------------------------------------------------
+// stream_size module
+//-------------------------------------------------------------------------
+
+static const Parameter size_params[] =
+{
+ { "*direction", Parameter::PT_ENUM, "either|client|server|both", nullptr,
+ "compare applies to the given direction(s)" },
+
+ { "*operator", Parameter::PT_ENUM, "= | != | < | > | <= | >=", nullptr,
+ "how to compare" },
+
+ { "*size", Parameter::PT_INT, nullptr, nullptr,
+ "size for comparison" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+class SizeModule : public Module
+{
+public:
+ SizeModule() : Module(IPS_SIZE, size_params) { };
+
+ bool begin(const char*, int, SnortConfig*);
+ bool set(const char*, Value&, SnortConfig*);
+
+ ProfileStats* get_profile() const
+ { return &streamSizePerfStats; };
+
+ StreamSizeOptionData ssod;
+};
+
+bool SizeModule::begin(const char*, int, SnortConfig*)
+{
+ ssod.direction = 0;
+ ssod.opcode = SSOD_EQ;
+ ssod.size = 0;
+ return true;
+}
+
+bool SizeModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("*direction") )
+ ssod.direction = v.get_long();
+
+ else if ( v.is("*operator") )
+ ssod.opcode = (SsodOp)(v.get_long() + 1);
+
+ else if ( v.is("*size") )
+ ssod.size = 0;
+
+ else
+ return false;
+
+ return true;
+}
+
+//-------------------------------------------------------------------------
+// stream_size api methods
+//-------------------------------------------------------------------------
+
+static Module* size_mod_ctor()
+{
+ return new SizeModule;
+}
+
+static void mod_dtor(Module* m)
+{
+ delete m;
+}
+
+static IpsOption* size_ctor(Module* p, OptTreeNode*)
+{
+ SizeModule* m = (SizeModule*)p;
+ return new SizeOption(m->ssod);
+}
+
+static void opt_dtor(IpsOption* p)
+{
+ delete p;
+}
+
+static const IpsApi size_api =
+{
+ {
+ PT_IPS_OPTION,
+ IPS_SIZE,
+ IPSAPI_PLUGIN_V0,
+ 0,
+ size_mod_ctor,
+ mod_dtor
+ },
+ OPT_TYPE_DETECTION,
+ 1, PROTO_BIT__TCP,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ size_ctor,
+ opt_dtor,
+ nullptr
+};
+
+const BaseApi* ips_stream_size = &size_api.base;
+
THREAD_LOCAL ProfileStats s5TcpFlushPerfStats;
THREAD_LOCAL ProfileStats s5TcpBuildPacketPerfStats;
THREAD_LOCAL ProfileStats s5TcpProcessRebuiltPerfStats;
-THREAD_LOCAL ProfileStats streamSizePerfStats;
-THREAD_LOCAL ProfileStats streamReassembleRuleOptionPerfStats;
struct TcpStats
{
sf_base->stream5_mem_in_use = tcp_memcap->used();
}
-#if 0
-static void Stream5TcpRegisterRuleOptions(SnortConfig*)
-{
- // FIXIT implement preproc rule option as any other rule option
- /* Register the 'stream_size' rule option */
- RegisterPreprocessorRuleOption(sc, "stream_size", &s5TcpStreamSizeInit,
- &s5TcpStreamSizeEval, &s5TcpStreamSizeCleanup,
- NULL, NULL, NULL, NULL);
-
- RegisterPreprocessorRuleOption(sc, "stream_reassemble", &s5TcpStreamReassembleRuleOptionInit,
- &s5TcpStreamReassembleRuleOptionEval, &s5TcpStreamReassembleRuleOptionCleanup,
- NULL, NULL, NULL, NULL);
-#ifdef PERF_PROFILING
- RegisterProfile(
- "stream_size", &streamSizePerfStats, 4, &preprocRuleOptionPerfStats,
- tcp_get_profile);
- RegisterProfile(
- "reassemble", &streamReassembleRuleOptionPerfStats, 4,
- &preprocRuleOptionPerfStats, tcp_get_profile);
-#endif
-}
-#endif
-
//-------------------------------------------------------------------------
// policy translation
//-------------------------------------------------------------------------
return 0;
}
-#define SSOD_LESS_THAN 1
-#define SSOD_GREATER_THAN 2
-#define SSOD_EQUALS 3
-#define SSOD_LESS_THAN_OR_EQUALS 4
-#define SSOD_GREATER_THAN_OR_EQUALS 5
-#define SSOD_NOT_EQUALS 6
-
-#define SSOD_MATCH 1
-#define SSOD_NOMATCH 0
-typedef struct _StreamSizeOptionData
-{
- char opcode;
- uint32_t size;
- char direction;
-} StreamSizeOptionData;
-
-int s5TcpStreamSizeInit(
- SnortConfig*, char *name, char *parameters, void **dataPtr)
-{
- char **toks;
- int num_toks;
- char *endp;
- StreamSizeOptionData *ssod;
- toks = mSplit(parameters, ",", 4, &num_toks, 0);
-
- if (num_toks != 3)
- {
- ParseError("Invalid parameters for %s option", name);
- }
-
- ssod = (StreamSizeOptionData*)SnortAlloc(sizeof(*ssod));
-
- if (!ssod)
- {
- ParseError("Failed to allocate data for %s option",
- name);
- }
-
- /* Parse the direction.
- * Can be: client, server, both, either
- */
- if (!strcasecmp(toks[0], "client"))
- {
- ssod->direction = SSN_DIR_CLIENT;
- }
- else if (!strcasecmp(toks[0], "server"))
- {
- ssod->direction = SSN_DIR_SERVER;
- }
- else if (!strcasecmp(toks[0], "both"))
- {
- ssod->direction = SSN_DIR_BOTH;
- }
- else if (!strcasecmp(toks[0], "either"))
- {
- ssod->direction = SSN_DIR_NONE;
- }
- else
- {
- ParseError("Invalid direction: %s for option %s",
- toks[0], name);
- }
-
- /* Parse the opcode.
- * Can be: =, <, > , !=, <=, >=
- */
- if (!strcasecmp(toks[1], "="))
- {
- ssod->opcode = SSOD_EQUALS;
- }
- else if (!strcasecmp(toks[1], "<"))
- {
- ssod->opcode = SSOD_LESS_THAN;
- }
- else if (!strcasecmp(toks[1], ">"))
- {
- ssod->opcode = SSOD_GREATER_THAN;
- }
- else if (!strcasecmp(toks[1], "!="))
- {
- ssod->opcode = SSOD_NOT_EQUALS;
- }
- else if (!strcasecmp(toks[1], "<="))
- {
- ssod->opcode = SSOD_LESS_THAN_OR_EQUALS;
- }
- else if (!strcasecmp(toks[1], ">="))
- {
- ssod->opcode = SSOD_GREATER_THAN_OR_EQUALS;
- }
- else
- {
- ParseError("Invalid opcode: %s for option %s",
- toks[1], name);
- }
-
- ssod->size = SnortStrtoul(toks[2], &endp, 0);
- if ((endp == toks[2]) || (errno == ERANGE))
- {
- ParseError("Invalid size: %s for option %s",
- toks[2], name);
- }
-
- *dataPtr = ssod;
- mSplitFree(&toks, num_toks);
-
- return 1;
-}
-
-static inline int s5TcpStreamSizeCompare(uint32_t size1, uint32_t size2, char opcode)
-{
- int retval = 0;
- switch (opcode)
- {
- case SSOD_EQUALS:
- if (size1 == size2)
- retval = 1;
- break;
- case SSOD_LESS_THAN:
- if (size1 < size2)
- retval = 1;
- break;
- case SSOD_GREATER_THAN:
- if (size1 > size2)
- retval = 1;
- break;
- case SSOD_NOT_EQUALS:
- if (size1 != size2)
- retval = 1;
- break;
- case SSOD_LESS_THAN_OR_EQUALS:
- if (size1 <= size2)
- retval = 1;
- break;
- case SSOD_GREATER_THAN_OR_EQUALS:
- if (size1 >= size2)
- retval = 1;
- break;
- default:
- break;
- }
- return retval;
-}
-
-int s5TcpStreamSizeEval(Packet* pkt, const uint8_t**, void *dataPtr)
-{
- Flow *lwssn = NULL;
- TcpSession *tcpssn = NULL;
- StreamSizeOptionData *ssod = (StreamSizeOptionData *)dataPtr;
- uint32_t client_size;
- uint32_t server_size;
- PROFILE_VARS;
-
- if (!pkt || !pkt->flow || !ssod || !pkt->tcph)
- return DETECTION_OPTION_NO_MATCH;
-
- lwssn = (Flow*)pkt->flow;
-
- PREPROC_PROFILE_START(streamSizePerfStats);
-
- tcpssn = (TcpSession *)lwssn->session;
-
- if (tcpssn->client.l_nxt_seq > tcpssn->client.isn)
- {
- /* the normal case... */
- client_size = tcpssn->client.l_nxt_seq - tcpssn->client.isn;
- }
- else
- {
- /* the seq num wrapping case... */
- client_size = tcpssn->client.isn - tcpssn->client.l_nxt_seq;
- }
- if (tcpssn->server.l_nxt_seq > tcpssn->server.isn)
- {
- /* the normal case... */
- server_size = tcpssn->server.l_nxt_seq - tcpssn->server.isn;
- }
- else
- {
- /* the seq num wrapping case... */
- server_size = tcpssn->server.isn - tcpssn->server.l_nxt_seq;
- }
-
- switch (ssod->direction)
- {
- case SSN_DIR_CLIENT:
- if (s5TcpStreamSizeCompare(client_size, ssod->size, ssod->opcode)
- == SSOD_MATCH)
- {
- PREPROC_PROFILE_END(streamSizePerfStats);
- return DETECTION_OPTION_MATCH;
- }
- break;
- case SSN_DIR_SERVER:
- if (s5TcpStreamSizeCompare(server_size, ssod->size, ssod->opcode)
- == SSOD_MATCH)
- {
- PREPROC_PROFILE_END(streamSizePerfStats);
- return DETECTION_OPTION_MATCH;
- }
- break;
- case SSN_DIR_NONE: /* overloaded. really, its an 'either' */
- if ((s5TcpStreamSizeCompare(client_size, ssod->size, ssod->opcode)
- == SSOD_MATCH) ||
- (s5TcpStreamSizeCompare(server_size, ssod->size, ssod->opcode)
- == SSOD_MATCH))
- {
- PREPROC_PROFILE_END(streamSizePerfStats);
- return DETECTION_OPTION_MATCH;
- }
- break;
- case SSN_DIR_BOTH:
- if ((s5TcpStreamSizeCompare(client_size, ssod->size, ssod->opcode)
- == SSOD_MATCH) &&
- (s5TcpStreamSizeCompare(server_size, ssod->size, ssod->opcode)
- == SSOD_MATCH))
- {
- PREPROC_PROFILE_END(streamSizePerfStats);
- return DETECTION_OPTION_MATCH;
- }
- break;
- default:
- break;
- }
- PREPROC_PROFILE_END(streamSizePerfStats);
- return DETECTION_OPTION_NO_MATCH;
-}
-
-void s5TcpStreamSizeCleanup(void *dataPtr)
-{
- StreamSizeOptionData *ssod = (StreamSizeOptionData*)dataPtr;
- if (ssod)
- {
- free(ssod);
- }
-}
-
-typedef struct _StreamReassembleRuleOptionData
-{
- char enable;
- char alert;
- char direction;
- char fastpath;
-} StreamReassembleRuleOptionData;
-
-int s5TcpStreamReassembleRuleOptionInit(
- SnortConfig*, char *name, char *parameters, void **dataPtr)
-{
- char **toks;
- int num_toks;
- StreamReassembleRuleOptionData *srod = NULL;
- toks = mSplit(parameters, ",", 4, &num_toks, 0);
-
- if (num_toks < 2)
- {
- ParseError("Invalid parameters for %s option", name);
- }
-
- srod = (StreamReassembleRuleOptionData*)SnortAlloc(sizeof(*srod));
-
- if (!srod)
- {
- ParseError("Failed to allocate data for %s option", name);
- }
-
- /* Parse the action.
- * Can be: enable or disable
- */
- if (!strcasecmp(toks[0], "enable"))
- {
- srod->enable = 1;
- }
- else if (!strcasecmp(toks[0], "disable"))
- {
- srod->enable = 0;
- }
- else
- {
- ParseError("Invalid action: %s for option %s. Valid "
- "parameters are 'enable' or 'disable'", toks[0], name);
- }
-
- /* Parse the direction.
- * Can be: client, server, both
- */
- /* Need to these around, so they match the ones specified via the stream_tcp ports
- * option, ie, stream_tcp: ports client enables reassembly on client-sourced traffic. */
- if (!strcasecmp(toks[1], "client"))
- {
- srod->direction = SSN_DIR_SERVER;
- }
- else if (!strcasecmp(toks[1], "server"))
- {
- srod->direction = SSN_DIR_CLIENT;
- }
- else if (!strcasecmp(toks[1], "both"))
- {
- srod->direction = SSN_DIR_BOTH;
- }
- else
- {
- ParseError("Invalid direction: %s for option %s", toks[1], name);
- }
-
- /* Parse the optional parameters:
- * noalert flag, fastpath flag
- */
- srod->alert = 1;
- if (num_toks > 2)
- {
- int i = 2;
- for (; i< num_toks; i++)
- {
- if (!strcasecmp(toks[i], "noalert"))
- {
- srod->alert = 0;
- }
- else if (!strcasecmp(toks[i], "fastpath"))
- {
- srod->fastpath = 1;
- if (srod->enable)
- {
- ParseError("Using 'fastpath' with 'enable' is "
- "not valid for %s", name);
- }
- }
- else
- {
- ParseError("Invalid optional parameter: %s for option %s",
- toks[i], name);
- }
- }
- }
-
- *dataPtr = srod;
- mSplitFree(&toks, num_toks);
-
- return 1;
-}
-
-int s5TcpStreamReassembleRuleOptionEval(
- Packet* pkt, const uint8_t**, void *dataPtr)
-{
- Flow *lwssn = NULL;
- StreamReassembleRuleOptionData *srod = (StreamReassembleRuleOptionData *)dataPtr;
- PROFILE_VARS;
-
- if (!pkt || !pkt->flow || !srod || !pkt->tcph)
- return 0;
-
- PREPROC_PROFILE_START(streamReassembleRuleOptionPerfStats);
- lwssn = (Flow*)pkt->flow;
- TcpSession* tcpssn = (TcpSession*)lwssn->session;
-
- if (!srod->enable) /* Turn it off */
- {
- if ( srod->direction & SSN_DIR_SERVER )
- tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
-
- if ( srod->direction & SSN_DIR_CLIENT )
- tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
- }
- else
- {
- // FIXIT PAF need to instantiate atom splitter?
- // FIXIT PAF need to check for ips / on-data
- if ( srod->direction & SSN_DIR_SERVER )
- tcpssn->server.flush_policy = STREAM_FLPOLICY_ON_ACK;
-
- if ( srod->direction & SSN_DIR_CLIENT )
- tcpssn->client.flush_policy = STREAM_FLPOLICY_ON_ACK;
- }
-
- if (srod->fastpath)
- {
- /* Turn off inspection */
- lwssn->s5_state.ignore_direction |= srod->direction;
- DisableInspection(pkt);
-
- /* TBD: Set TF_FORCE_FLUSH ? */
- }
-
- if (srod->alert)
- {
- PREPROC_PROFILE_END(streamReassembleRuleOptionPerfStats);
- return DETECTION_OPTION_MATCH;
- }
-
- PREPROC_PROFILE_END(streamReassembleRuleOptionPerfStats);
- return DETECTION_OPTION_NO_ALERT;
-}
-
-void s5TcpStreamReassembleRuleOptionCleanup(void *dataPtr)
-{
- StreamReassembleRuleOptionData *srod = (StreamReassembleRuleOptionData*)dataPtr;
- if (srod)
- {
- free(srod);
- }
-}
-
void s5TcpSetSynSessionStatus(
StreamTcpConfig* tcp_config, uint16_t status)
{
void tcp_init()
{
-#if 0
- // FIXIT add inspector rule options
- Stream5TcpRegisterRuleOptions(sc);
-#endif
}
void tcp_reset()
mpsePerfStats = &node->stats;
}
-void RegisterOtnProfile(const char *keyword, get_profile_func get)
-{
- RegisterProfile(keyword, "rule tree eval", get);
-}
-
void RegisterProfile(Module* m)
{
ProfileStats* ps = m->get_profile();
const char* keyword, const char* parent,
get_profile_func, class Module* owner = nullptr);
-void RegisterOtnProfile(const char* keyword, get_profile_func);
void RegisterProfile(class Module*);
void ShowPreprocProfiles(void);