?? spp_stream5.c
字號:
/* $Id$ *//**************************************************************************** * * Copyright (C) 2005-2007 Sourcefire, Inc. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************//** * @file spp_stream5.c * @author Martin Roesch <roesch@sourcefire.com> * Steven Sturges <ssturges@sourcefire.com> * @date 19 Apr 2005 * * @brief You can never have too many stream reassemblers... *//* * Copyright (C) 2004-2005 Sourcefire, Inc. *//* I N C L U D E S ************************************************/#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#ifndef WIN32#include <sys/time.h> /* struct timeval */#endif#include <sys/types.h> /* u_int*_t */#include "snort.h"#include "bounds.h"#include "util.h"#include "debug.h"#include "plugbase.h"#include "spp_stream5.h"#include "stream_api.h"#include "stream5_common.h"#include "snort_stream5_session.h"#include "snort_stream5_tcp.h"#include "snort_stream5_udp.h"#include "snort_stream5_icmp.h"#include "checksum.h"#include "mstring.h"#include "parser/IpAddrSet.h"#include "decode.h"#include "detect.h"#include "generators.h"#include "event_queue.h"#include "stream_ignore.h"#include "stream_api.h"#include "perf.h"#include "ipv6_port.h"#ifdef TARGET_BASED#include "sftarget_protocol_reference.h"#include "sftarget_hostentry.h"#endif#include "profiler.h"#ifdef PERF_PROFILINGPreprocStats s5PerfStats;extern PreprocStats s5TcpPerfStats;extern PreprocStats s5UdpPerfStats;extern PreprocStats s5IcmpPerfStats;#endifextern OptTreeNode *otn_tmp;/* M A C R O S **************************************************//* default limits */#define S5_DEFAULT_PRUNE_QUANTA 30 /* seconds to timeout a session */#define S5_DEFAULT_MEMCAP 8388608 /* 8MB */#define S5_RIDICULOUS_HI_MEMCAP 1024*1024*1024 /* 1GB */#define S5_RIDICULOUS_LOW_MEMCAP 32768 /* 32k*/#define S5_DEFAULT_MIN_TTL 1 /* default for min TTL */#define S5_DEFAULT_TTL_LIMIT 5 /* default for TTL Limit */#define S5_RIDICULOUS_MAX_SESSIONS 1024*1028 /* 1 million sessions */#define S5_DEFAULT_MAX_TCP_SESSIONS 262144 /* 256k TCP sessions by default */#define S5_DEFAULT_MAX_UDP_SESSIONS 131072 /* 128k UDP sessions by default */#define S5_DEFAULT_MAX_ICMP_SESSIONS 65536 /* 64k ICMP sessions by default *//* G L O B A L S **************************************************/Stream5GlobalConfig s5_global_config;static char s5_global_config_complete = 0;static char s5_process_registered = 0;u_int32_t firstPacketTime = 0;Stream5Stats s5stats;MemPool s5FlowMempool;/* Define this locally when Flow preprocessor has actually been removed */#ifdef FLOWPP_IS_EIGHTYSIXEDunsigned int giFlowbitSize = 64;#elseextern unsigned int giFlowbitSize;//#include "flow.h"#endif/* P R O T O T Y P E S ********************************************/static void Stream5GlobalInit(char *);static void Stream5ParseGlobalArgs(char *);static void Stream5PolicyInitTcp(char *);static void Stream5PolicyInitUdp(char *);static void Stream5PolicyInitIcmp(char *);static void Stream5Restart(int, void *);static void Stream5CleanExit(int, void *);static void Stream5VerifyConfig(void);static void Stream5PrintGlobalConfig();static void Stream5PrintStats(int);static void Stream5Process(Packet *p, void *context);static INLINE int IsEligible(Packet *p);/* S T R E A M A P I **********************************************/static int Stream5MidStreamDropAlert() { return s5_global_config.flags & STREAM5_CONFIG_MIDSTREAM_DROP_NOALERT; }static void Stream5UpdateDirection( void * ssnptr, char dir, ip_p ip, u_int16_t port);static u_int32_t Stream5GetPacketDirection( Packet *p);static void Stream5StopInspection( void * ssnptr, Packet *p, char dir, int32_t bytes, int response);static int Stream5IgnoreChannel( ip_p srcIP, u_int16_t srcPort, ip_p dstIP, u_int16_t dstPort, char protocol, char direction, char flags);static void Stream5ResumeInspection( void *ssnptr, char dir);static void Stream5DropTraffic( void *ssnptr, char dir);static void Stream5DropPacket( Packet *p);static void Stream5SetApplicationData( void *ssnptr, u_int32_t protocol, void *data, StreamAppDataFree free_func);static void *Stream5GetApplicationData( void *ssnptr, u_int32_t protocol);static u_int32_t Stream5SetSessionFlags( void *ssnptr, u_int32_t flags);static u_int32_t Stream5GetSessionFlags(void *ssnptr);static int Stream5AlertFlushStream(Packet *p);static int Stream5ResponseFlushStream(Packet *p);static int Stream5AddSessionAlert(void *ssnptr, Packet *p, u_int32_t gid, u_int32_t sid);static int Stream5CheckSessionAlert(void *ssnptr, Packet *p, u_int32_t gid, u_int32_t sid);static char Stream5SetReassembly(void *ssnptr, u_int8_t flush_policy, char dir, char flags);static char Stream5GetReassemblyDirection(void *ssnptr);static char Stream5GetReassemblyFlushPolicy(void *ssnptr, char dir);static char Stream5IsStreamSequenced(void *ssnptr, char dir);static int Stream5GetRebuiltPackets( Packet *p, PacketIterator callback, void *userdata);static StreamFlowData *Stream5GetFlowData(Packet *p);#ifdef TARGET_BASEDstatic int16_t Stream5GetApplicationProtocolId(void *ssnptr);static int16_t Stream5SetApplicationProtocolId(void *ssnptr, int16_t id);#endifStreamAPI s5api = { STREAM_API_VERSION5, Stream5MidStreamDropAlert, Stream5UpdateDirection, Stream5GetPacketDirection, Stream5StopInspection, Stream5IgnoreChannel, Stream5ResumeInspection, Stream5DropTraffic, Stream5DropPacket, Stream5SetApplicationData, Stream5GetApplicationData, Stream5SetSessionFlags, Stream5GetSessionFlags, Stream5AlertFlushStream, Stream5ResponseFlushStream, Stream5GetRebuiltPackets, Stream5AddSessionAlert, Stream5CheckSessionAlert, Stream5GetFlowData, Stream5SetReassembly, Stream5GetReassemblyDirection, Stream5GetReassemblyFlushPolicy, Stream5IsStreamSequenced#ifdef TARGET_BASED , Stream5GetApplicationProtocolId, Stream5SetApplicationProtocolId#endif /* More to follow */};void SetupStream5(){ RegisterPreprocessor("stream5_global", Stream5GlobalInit); RegisterPreprocessor("stream5_tcp", Stream5PolicyInitTcp); RegisterPreprocessor("stream5_udp", Stream5PolicyInitUdp); RegisterPreprocessor("stream5_icmp", Stream5PolicyInitIcmp); DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Preprocessor stream5 is setup\n"););}void Stream5GlobalInit(char *args){ if (s5_global_config_complete) { FatalError("%s(%d) ==> Cannot duplicate Stream5 global " "configuration\n", file_name, file_line); } if (stream_api == NULL) stream_api = &s5api; else FatalError("Cannot use both Stream4 & Stream5 simultaneously\n"); s5_global_config.track_tcp_sessions = S5_TRACK_YES; s5_global_config.max_tcp_sessions = S5_DEFAULT_MAX_TCP_SESSIONS; s5_global_config.track_udp_sessions = S5_TRACK_YES; s5_global_config.max_udp_sessions = S5_DEFAULT_MAX_UDP_SESSIONS; s5_global_config.track_icmp_sessions = S5_TRACK_NO; s5_global_config.max_icmp_sessions = S5_DEFAULT_MAX_ICMP_SESSIONS; s5_global_config.memcap = S5_DEFAULT_MEMCAP; s5_global_config.mem_in_use = 0; Stream5ParseGlobalArgs(args);#ifdef PERF_PROFILING RegisterPreprocessorProfile("s5", &s5PerfStats, 0, &totalPerfStats); RegisterPreprocessorProfile("s5tcp", &s5TcpPerfStats, 1, &s5PerfStats); RegisterPreprocessorProfile("s5udp", &s5UdpPerfStats, 1, &s5PerfStats); RegisterPreprocessorProfile("s5icmp", &s5IcmpPerfStats, 1, &s5PerfStats);#endif Stream5InitTcp(); Stream5InitUdp(); Stream5InitIcmp(); snort_runtime.capabilities.stateful_inspection = 1; Stream5PrintGlobalConfig(); AddFuncToPreprocCleanExitList(Stream5CleanExit, NULL, PRIORITY_FIRST, PP_STREAM5); AddFuncToPreprocRestartList(Stream5Restart, NULL, PRIORITY_FIRST, PP_STREAM5); AddFuncToConfigCheckList(Stream5VerifyConfig); RegisterPreprocStats("stream5", Stream5PrintStats); s5_global_config_complete = 1; pv.stateful = 1; return;}static void Stream5ParseGlobalArgs(char *args){ char **toks; int num_toks; int i; char *index; char **stoks; int s_toks; char *endPtr = NULL;#define MAX_TCP 0x01#define MAX_UDP 0x02#define MAX_ICMP 0x04 char max_set = 0; if(args != NULL && strlen(args) != 0) { toks = mSplit(args, ",", 12, &num_toks, 0); i = 0; while(i < num_toks) { index = toks[i]; while(isspace((int)*index)) index++; stoks = mSplit(index, " ", 4, &s_toks, 0); if (s_toks == 0) { FatalError("%s(%d) => Missing parameter in Stream5 Global config.\n", file_name, file_line); } if(!strcasecmp(stoks[0], "memcap")) { if (stoks[1]) { s5_global_config.memcap = strtoul(stoks[1], &endPtr, 10); } if (!stoks[1] || (endPtr == &stoks[1][0])) { FatalError("%s(%d) => Invalid memcap in config file. Requires integer parameter.\n", file_name, file_line); } if ((s5_global_config.memcap > S5_RIDICULOUS_HI_MEMCAP) || (s5_global_config.memcap < S5_RIDICULOUS_LOW_MEMCAP)) { FatalError("%s(%d) => 'memcap %s' invalid: value must be " "between %d and %d bytes\n", file_name, file_line, stoks[1], S5_RIDICULOUS_LOW_MEMCAP, S5_RIDICULOUS_HI_MEMCAP); } } else if(!strcasecmp(stoks[0], "max_tcp")) { if (stoks[1]) { s5_global_config.max_tcp_sessions = strtoul(stoks[1], &endPtr, 10); if (s5_global_config.track_tcp_sessions == S5_TRACK_NO) { if (s5_global_config.max_tcp_sessions != 0) { FatalError("%s(%d) => max_tcp conflict: not " "tracking TCP sessions\n", file_name, file_line); } } else { if ((s5_global_config.max_tcp_sessions > S5_RIDICULOUS_MAX_SESSIONS) || (s5_global_config.max_tcp_sessions == 0)) { FatalError("%s(%d) => 'max_tcp %d' invalid: value must be " "between 1 and %d sessions\n", file_name, file_line, s5_global_config.max_tcp_sessions, S5_RIDICULOUS_MAX_SESSIONS); } } } if (!stoks[1] || (endPtr == &stoks[1][0])) { FatalError("%s(%d) => Invalid max_tcp in config file. Requires integer parameter.\n", file_name, file_line); } max_set |= MAX_TCP; } else if(!strcasecmp(stoks[0], "track_tcp")) { if (stoks[1]) { if(!strcasecmp(stoks[1], "no")) s5_global_config.track_tcp_sessions = S5_TRACK_NO; else s5_global_config.track_tcp_sessions = S5_TRACK_YES; } else { FatalError("%s(%d) => 'track_udp' missing option\n", file_name, file_line); } if ((max_set & MAX_TCP) && (s5_global_config.track_tcp_sessions == S5_TRACK_NO)) { FatalError("%s(%d) => max_tcp/track_tcp conflict: not " "tracking TCP sessions\n", file_name, file_line); } } else if(!strcasecmp(stoks[0], "max_udp")) { if (stoks[1]) { s5_global_config.max_udp_sessions = strtoul(stoks[1], &endPtr, 10); if (s5_global_config.track_udp_sessions == S5_TRACK_NO) { if (s5_global_config.max_udp_sessions != 0) { FatalError("%s(%d) => max_udp conflict: not " "tracking UDP sessions\n", file_name, file_line); } } else { if ((s5_global_config.max_udp_sessions > S5_RIDICULOUS_MAX_SESSIONS) || (s5_global_config.max_udp_sessions == 0)) { FatalError("%s(%d) => 'max_udp %d' invalid: value must be " "between 1 and %d sessions\n", file_name, file_line, s5_global_config.max_udp_sessions, S5_RIDICULOUS_MAX_SESSIONS); } } } if (!stoks[1] || (endPtr == &stoks[1][0])) { FatalError("%s(%d) => Invalid max_udp in config file. Requires integer parameter.\n", file_name, file_line); } max_set |= MAX_UDP; } else if(!strcasecmp(stoks[0], "track_udp")) { if (stoks[1]) { if(!strcasecmp(stoks[1], "no")) s5_global_config.track_udp_sessions = S5_TRACK_NO; else s5_global_config.track_udp_sessions = S5_TRACK_YES; } else { FatalError("%s(%d) => 'track_udp' missing option\n", file_name, file_line); } if ((max_set & MAX_UDP) && (s5_global_config.track_udp_sessions == S5_TRACK_NO)) { FatalError("%s(%d) => max_udp/track_udp conflict: not " "tracking UDP sessions\n", file_name, file_line); } } else if(!strcasecmp(stoks[0], "max_icmp")) { if (stoks[1]) { s5_global_config.max_icmp_sessions = strtoul(stoks[1], &endPtr, 10); if (s5_global_config.track_icmp_sessions == S5_TRACK_NO) { if (s5_global_config.max_icmp_sessions != 0) { FatalError("%s(%d) => max_icmp conflict: not " "tracking ICMP sessions\n", file_name, file_line); } } else { if ((s5_global_config.max_icmp_sessions > S5_RIDICULOUS_MAX_SESSIONS) || (s5_global_config.max_icmp_sessions == 0)) { FatalError("%s(%d) => 'max_icmp %d' invalid: value must be " "between 1 and %d sessions\n",
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -