"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/preprocessors/spp_session.c" (16 Oct 2020, 155415 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "spp_session.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
2.9.16.1_vs_2.9.17.
1 /* $Id$ */
2 /****************************************************************************
3 *
4 * Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
5 * Copyright (C) 2005-2013 Sourcefire, Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License Version 2 as
9 * published by the Free Software Foundation. You may not use, modify or
10 * distribute this program under any other version of the GNU General
11 * Public License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 *
22 ****************************************************************************/
23
24 /**
25 * @file spp_session.c
26 * @author davis mcpherson <dmcpherson@sourcefire.com>
27 * @date 22 Feb 2013
28 *
29 * @brief sessions? we don't got no sessions...
30 */
31
32 /* I N C L U D E S ************************************************/
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <assert.h>
38 #include <stdio.h>
39
40 #ifndef WIN32
41 #include <sys/time.h> /* struct timeval */
42 #endif
43 #include <sys/types.h> /* u_int*_t */
44
45 #include "snort.h"
46 #include "snort_bounds.h"
47 #include "util.h"
48 #include "snort_debug.h"
49 #include "mempool.h"
50 #include "mstring.h"
51 #include "detect.h"
52 #include "active.h"
53 #include "sp_flowbits.h"
54 #include "packet_time.h"
55
56 #include "session_expect.h"
57 #include "snort_session.h"
58 #include "session_api.h"
59 #include "spp_session.h"
60 #include "reload.h"
61 #include "snort_stream_tcp.h"
62 #include "snort_stream_udp.h"
63 #include "snort_stream_ip.h"
64 #include "snort_stream_icmp.h"
65
66 #include "reg_test.h"
67
68 #ifdef ENABLE_HA
69 #include "stream5_ha.h"
70 #endif
71
72 #ifdef PERF_PROFILING
73 PreprocStats sessionPerfStats;
74 # ifdef ENABLE_HA
75 extern PreprocStats sessionHAPerfStats;
76 # endif
77 #endif
78
79 extern OptTreeNode *otn_tmp;
80
81 /* M A C R O S **************************************************/
82
83 /* G L O B A L S **************************************************/
84 SessionStatistics session_stats;
85 uint32_t firstPacketTime = 0;
86 uint32_t session_mem_in_use = 0;
87
88 SessionConfiguration *session_configuration = NULL;
89 static SessionConfiguration *session_reload_configuration = NULL;
90 static GetHttpXffPrecedenceFunc getHttpXffPrecedenceFunc = NULL;
91
92 static SessionCache *proto_session_caches[ SESSION_PROTO_MAX ];
93
94 static MemPool sessionFlowMempool;
95
96 static PreprocEnableMask appHandlerDispatchMask[ INT16_MAX ];
97
98 static sfaddr_t fixed_addr = {{{{0xFF,0,0,0}}},0}; /* Used in lieu of ICMPv6/ICMP multicast/broadcast address
99 * to generate a matching key in between router solicitation and advertisement to associate them in one session.
100 * In future, we can extend this approach to other types of services (may need support in snort's decode):
101 * - Multicast Listener Query (MLD) types 130-131-132 (typically multicast dest),
102 * - ICMP Node Information Query types 139-140 (unicast or multicast dest),
103 * - Neighbor Solicitation Message Format types 135-136 (unicast or multicast dest),
104 * - Echo Request/Reply types 128-129 ping6 and 8-0 ping (unicast/multicast/broadcast dest), etc.
105 */
106
107 /* P R O T O T Y P E S ********************************************/
108 void initializeSessionPreproc(struct _SnortConfig *, char *);
109 static void parseSessionConfiguration(SessionConfiguration *, char *);
110 static void exitSessionCleanly(int, void *);
111 static void resetSessionState(int, void *);
112 static void resetSessionStatistics(int, void *);
113 static int verifySessionConfig(struct _SnortConfig *);
114 static void printSessionConfiguration(SessionConfiguration *);
115 static void printSessionStatistics(int);
116 static void sessionPacketProcessor(Packet *p, void *context);
117
118 #ifdef SNORT_RELOAD
119 static void reloadSessionConfiguration( struct _SnortConfig *, char *, void ** );
120 static int verifyReloadedSessionConfiguration( struct _SnortConfig *, void * );
121 static void *activateSessionConfiguration( struct _SnortConfig *sc, void *data );
122 static void freeSessionConfiguration( void * );
123 #endif
124
125 /* S E S S I O N A P I **********************************************/
126 #if 0
127 static void PrintSessionKey(SessionKey *);
128 #endif
129
130 #ifdef MPLS
131 static void initMplsHeaders(SessionControlBlock*);
132 static void freeMplsHeaders(SessionControlBlock*);
133 #endif
134
135 static SessionCache* initSessionCache(uint32_t session_type, uint32_t protocol_scb_size, SessionCleanup clean_fcn);
136 static void *getSessionControlBlock(SessionCache*, Packet *, SessionKey *);
137 static void *checkSessionControlBlock(void *, Packet *, SessionKey *);
138 static void updateSessionControlBlockTime(SessionControlBlock *, Packet *);
139 static void populateSessionKey(Packet *p, SessionKey *key);
140 static int initSessionKeyFromPktHeader( sfaddr_t* srcIP, uint16_t srcPort, sfaddr_t* dstIP,
141 uint16_t dstPort, char proto, uint16_t vlan,
142 uint32_t mplsId,
143 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
144 uint16_t address_space_id_src,
145 uint16_t address_space_id_dst,
146 #else
147 uint16_t addressSpaceId,
148 #endif
149 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
150 uint32_t carrierId,
151 #endif
152 SessionKey *key);
153 static void *getSessionControlBlockFromKey(SessionCache*, const SessionKey *);
154 static void *getSessionHandle(const SessionKey *key);
155 static void *createSession(SessionCache*, Packet *, const SessionKey * );
156 static bool isSessionVerified( void * );
157 static void removeSessionFromProtoOneWayList(uint32_t proto, void *scb);
158 static int deleteSession(SessionCache*, void *, char *reason, bool close_sync);
159 static int deleteSessionByKey(void *, char *reason);
160 static void printSessionCache(SessionCache*);
161 static int deleteSessionCache(uint32_t protocol);
162 static int purgeSessionCache(SessionCache*);
163 static int pruneSessionCache(SessionCache*, uint32_t thetime, void *save_me, int memcheck);
164 static void cleanProtocolSessionsPool( uint32_t );
165 static void freeProtocolSessionsPool( uint32_t, void * );
166 static void *allocateProtocolSession( uint32_t );
167 static int getActiveSessionCount(SessionCache*);
168 static uint32_t getSessionPruneCount( uint32_t );
169 static void resetSessionPruneCount( uint32_t );
170 static void checkSessionTimeout( uint32_t, time_t );
171 static void setPacketDirectionFlag(Packet *p, void *scb);
172 static void freeSessionApplicationData(void *scb);
173
174 static int isProtocolTrackingEnabled( IpProto proto );
175 static uint32_t getPacketDirection( Packet *p );
176 static void disableInspection(void *scbptr, Packet *p);
177 static void stopInspection( void * scbptr, Packet *p, char dir, int32_t bytes, int response );
178 struct _ExpectNode;
179 static int ignoreChannel( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort, sfaddr_t* dstIP,
180 uint16_t dstPort, uint8_t protocol, uint32_t preprocId, char direction, char flags,
181 struct _ExpectNode** packetExpectedNode);
182 static int getIgnoreDirection( void *scbptr );
183 static int setIgnoreDirection( void *scbptr, int );
184 static void resumeInspection( void *scbptr, char dir );
185 static void dropTraffic( Packet*, void *scbptr, char dir );
186 static int setApplicationData( void *scbptr, uint32_t protocol, void *data, StreamAppDataFree free_func );
187 static void *getApplicationData( void *scbptr, uint32_t protocol );
188 static StreamSessionKey * getSessionKeyFromPacket( Packet *p );
189 static void * getApplicationDataFromSessionKey( const StreamSessionKey *key, uint32_t protocol);
190 static void *getApplicationDataFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
191 sfaddr_t* dstIP, uint16_t dstPort,
192 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
193 uint16_t address_space_id_src,
194 uint16_t address_space_id_dst,
195 #else
196 uint16_t addressSpaceId,
197 #endif
198 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
199 uint32_t carrierId,
200 #endif
201 char ip_protocol, uint16_t vlan,
202 uint32_t mplsId, uint32_t protocol );
203 static void setSessionExpirationTime(Packet *p, void *scbptr, uint32_t timeout);
204 static int getSessionExpirationTime(Packet *p, void *scbptr);
205 static uint32_t setSessionFlags( void *scbptr, uint32_t flags );
206 static uint32_t getSessionFlags( void *scbptr );
207 static tSfPolicyId getSessionPolicy(void *scbptr, int policy_type);
208 static void setSessionPolicy(void *scbptr, int policy_type, tSfPolicyId id);
209 static StreamFlowData *getFlowData( Packet *p );
210 static void setSessionDeletionDelayed( void *scbptr, bool delay_session_deletion_flag);
211 static bool isSessionDeletionDelayed( void *scbptr );
212 static int setAppProtocolIdExpected( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort, sfaddr_t* dstIP,
213 uint16_t dstPort, uint8_t protocol, int16_t protoId, uint32_t preprocId,
214 void* protoData, void (*protoDataFreeFn)(void*),
215 struct _ExpectNode** packetExpectedNode);
216 #ifdef TARGET_BASED
217 static void registerApplicationHandler( uint32_t preproc_id, int16_t app_id );
218 static int16_t getAppProtocolId( void *scbptr );
219 static int16_t setAppProtocolId( void *scbptr, int16_t id );
220 static sfaddr_t* getSessionIpAddress( void *scbptr, uint32_t direction );
221 static void getSessionPorts( void *scbptr, uint16_t *client_port, uint16_t *server_port );
222 #endif
223
224 static uint16_t getPreprocessorStatusBit( void );
225 static void getMaxSessions(tSfPolicyId policyId, StreamSessionLimits* limits);
226 static void *getSessionHandleFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
227 sfaddr_t* dstIP, uint16_t dstPort,
228 char ip_protocol, uint16_t vlan,
229 uint32_t mplsId,
230 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
231 uint32_t carrierId,
232 #endif
233 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
234 uint16_t address_space_id_src,
235 uint16_t address_space_id_dst
236 #else
237 uint16_t addressSpaceId
238 #endif
239 );
240 static const StreamSessionKey *getKeyFromSession(const void *scbptr);
241
242 #ifdef TARGET_BASED
243 #ifdef ACTIVE_RESPONSE
244 static void initActiveResponse( Packet*, void* scbptr );
245 #endif
246
247 static uint8_t getHopLimit ( void* scbptr, char dir, int outer );
248 #endif
249 static void deleteSessionIfClosed( Packet* );
250 static void disablePreprocForSession( void *scbptr, uint32_t preproc_id );
251 static void enablePreprocForPort( SnortConfig *sc, uint32_t preproc_id, uint32_t proto, uint16_t port );
252 static void enablePreprocAllPorts( SnortConfig *sc, uint32_t preproc_id, uint32_t proto );
253 static void enablePreprocAllPortsAllPolicies( SnortConfig *sc, uint32_t preproc_id, uint32_t proto );
254 static bool isPreprocEnabledForPort( uint32_t preproc_id, uint16_t port );
255 static void registerNapSelector( nap_selector nap_selector_func );
256 static void registerGetHttpXffPrecedence(GetHttpXffPrecedenceFunc fn);
257 static char** getHttpXffPrecedence(void* ssn, uint32_t flags, int* nFields);
258 static void setReputationUpdateCount (void *ssn, uint8_t count);
259
260 SessionAPI session_api_dispatch_table = {
261 /* .version = */ SESSION_API_VERSION1,
262 /* .init_session_cache = */ initSessionCache,
263 /* .get_session = */ getSessionControlBlock,
264 /* .populate_session_key = */ populateSessionKey,
265 /* .get_session_key_by_ip_port = */ initSessionKeyFromPktHeader,
266 /* .get_session_by_key = */ getSessionControlBlockFromKey,
267 /* .get_session_handle = */ getSessionHandle,
268 /* .create_session = */ createSession,
269 /* .is_session_verified = */ isSessionVerified,
270 /* .remove_session_from_oneway_list = */ removeSessionFromProtoOneWayList,
271 /* .delete_session = */ deleteSession,
272 /* .delete_session_by_key = */ deleteSessionByKey,
273 /* .print_session_cache = */ printSessionCache,
274 /* .delete_session_cache = */ deleteSessionCache,
275 /* .purge_session_cache = */ purgeSessionCache,
276 /* .prune_session_cache = */ pruneSessionCache,
277 /* .clean_protocol_session_pool = */ cleanProtocolSessionsPool,
278 /* .free_protocol_session_pool = */ freeProtocolSessionsPool,
279 /* .alloc_protocol_session = */ allocateProtocolSession,
280 /* .get_session_count = */ getActiveSessionCount,
281 /* .get_session_prune_count = */ getSessionPruneCount,
282 /* .reset_session_prune_count = */ resetSessionPruneCount,
283 /* .check_session_timeout = */ checkSessionTimeout,
284 /* .protocol_tracking_enabled = */ isProtocolTrackingEnabled,
285 /* .set_packet_direction_flag = */ setPacketDirectionFlag,
286 /* .free_application_data = */ freeSessionApplicationData,
287 /* .get_packet_direction = */ getPacketDirection,
288 /* .disable_inspection = */ disableInspection,
289 /* .stop_inspection = */ stopInspection,
290 /* .ignore_session = */ ignoreChannel,
291 /* .get_ignore_direction = */ getIgnoreDirection,
292 /* .resume_inspection = */ resumeInspection,
293 /* .drop_traffic = */ dropTraffic,
294 /* .set_application_data = */ setApplicationData,
295 /* .get_application_data = */ getApplicationData,
296 /* .set_expire_timer = */ setSessionExpirationTime,
297 /* .get_expire_timer = */ getSessionExpirationTime,
298 /* .set_session_flags = */ setSessionFlags,
299 /* .get_session_flags = */ getSessionFlags,
300 /* .get_runtime_policy = */ getSessionPolicy,
301 /* .set_runtime_policy = */ setSessionPolicy,
302 /* .get_flow_data = */ getFlowData,
303 /* .set_session_deletion_delayed = */ setSessionDeletionDelayed,
304 /* .is_session_deletion_delayed = */ isSessionDeletionDelayed,
305 #ifdef TARGET_BASED
306 /* .register_service_handler */ registerApplicationHandler,
307 /* .get_application_protocol_id = */ getAppProtocolId,
308 /* .set_application_protocol_id = */ setAppProtocolId,
309 /* .get_session_ip_address = */ getSessionIpAddress,
310 /* .get_session_ports = */ getSessionPorts,
311 #endif
312 /* .get_preprocessor_status_bit = */ getPreprocessorStatusBit,
313 #ifdef TARGET_BASED
314 #ifdef ACTIVE_RESPONSE
315 /* .init_active_response = */ initActiveResponse,
316 #endif
317 /* .get_session_ttl = */ getHopLimit,
318 #endif
319 /* .set_application_protocol_id_expected = */ setAppProtocolIdExpected,
320 #ifdef ENABLE_HA
321 /* .register_ha_funcs = */ RegisterSessionHAFuncs,
322 /* .unregister_ha_funcs = */ UnregisterSessionHAFuncs,
323 /* .set_ha_pending_bit = */ SessionSetHAPendingBit,
324 /* .process_ha = */ SessionProcessHA,
325 #endif
326 /* .get_max_session_limits = */ getMaxSessions,
327 /* .set_ignore_direction = */ setIgnoreDirection,
328 /* .get_session_ptr_from_ip_port = */ getSessionHandleFromIpPort,
329 /* .get_key_from_session_ptr = */ getKeyFromSession,
330 /* .check_session_closed = */ deleteSessionIfClosed,
331 /* .get_session_key = */ getSessionKeyFromPacket,
332 /* .get_application_data_from_key = */ getApplicationDataFromSessionKey,
333 /* .get_application_data_from_ip_port = */ getApplicationDataFromIpPort,
334 /* .disable_preproc_for_session = */ disablePreprocForSession,
335 /* .enable_preproc_for_port = */ enablePreprocForPort,
336 /* .enable_preproc_all_ports = */ enablePreprocAllPorts,
337 /* .enable_preproc_all_ports_all_policies = */ enablePreprocAllPortsAllPolicies,
338 /* .is_preproc_enabled_for_port = */ isPreprocEnabledForPort,
339 /* .register_nap_selector = */ registerNapSelector,
340 /* .register_mandatory_early_session_creator = */ registerMandatoryEarlySessionCreator,
341 /* .get_application_data_from_expected_node = */ getApplicationDataFromExpectedNode,
342 /* .add_application_data_to_expected_node = */ addApplicationDataToExpectedNode,
343 /* .register_get_http_xff_precedence = */ registerGetHttpXffPrecedence,
344 /* .get_http_xff_precedence = */ getHttpXffPrecedence,
345 /* .get_next_expected_node = */ getNextExpectedNode,
346 /* .set_reputation_update_counter = */ setReputationUpdateCount
347 };
348
349
350 void SetupSessionManager(void)
351 {
352 #ifndef SNORT_RELOAD
353 RegisterPreprocessor("stream5_global", initializeSessionPreproc);
354 # ifdef ENABLE_HA
355 RegisterPreprocessor("stream5_ha", StreamHAInit);
356 # endif
357 #else
358 RegisterPreprocessor("stream5_global",
359 initializeSessionPreproc,
360 reloadSessionConfiguration,
361 verifyReloadedSessionConfiguration,
362 activateSessionConfiguration,
363 freeSessionConfiguration);
364
365 # ifdef ENABLE_HA
366 RegisterPreprocessor("stream5_ha",
367 SessionHAInit,
368 SessionHAReload,
369 SessionVerifyHAConfig,
370 SessionHASwapReload,
371 SessionHAConfigFree);
372 #endif
373 #endif
374
375 // init the pointer to session api dispatch table
376 session_api = &session_api_dispatch_table;
377
378 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Preprocessor Session is setup\n"););
379 }
380
381 static void selectRuntimePolicy( Packet *p, bool client_packet )
382 {
383 tSfPolicyId id;
384 int vlanId = ( p->vh ) ? VTH_VLAN( p->vh ) : -1;
385
386 sfaddr_t* srcIp = ( p->iph ) ? GET_SRC_IP( p ) : NULL;
387 sfaddr_t* dstIp = ( p->iph ) ? GET_DST_IP( p ) : NULL;
388
389 //set policy id for this packet
390 id = sfGetApplicablePolicyId( snort_conf->policy_config, vlanId, srcIp, dstIp );
391 setNapRuntimePolicy( id );
392 setIpsRuntimePolicy( id );
393 p->configPolicyId = snort_conf->targeted_policies[ id ]->configPolicyId;
394 p->ips_os_selected = true;
395 }
396
397 SessionConfiguration *getSessionConfiguration( bool reload_config )
398 {
399 if( reload_config )
400 return session_reload_configuration;
401 else
402 return session_configuration;
403 }
404
405 static SessionConfiguration *initSessionConfiguration( void )
406 {
407 SessionConfiguration *sessionConfig =
408 (SessionConfiguration *)SnortAlloc(sizeof(SessionConfiguration));
409
410 sessionConfig->track_tcp_sessions = STREAM_TRACK_YES;
411 sessionConfig->max_tcp_sessions = STREAM_DEFAULT_MAX_TCP_SESSIONS;
412 sessionConfig->tcp_cache_pruning_timeout = STREAM_DEFAULT_TCP_CACHE_PRUNING_TIMEOUT;
413 sessionConfig->tcp_cache_nominal_timeout = STREAM_DEFAULT_TCP_CACHE_NOMINAL_TIMEOUT;
414 sessionConfig->track_udp_sessions = STREAM_TRACK_YES;
415 sessionConfig->max_udp_sessions = STREAM_DEFAULT_MAX_UDP_SESSIONS;
416 sessionConfig->udp_cache_pruning_timeout = STREAM_DEFAULT_UDP_CACHE_PRUNING_TIMEOUT;
417 sessionConfig->udp_cache_nominal_timeout = STREAM_DEFAULT_UDP_CACHE_NOMINAL_TIMEOUT;
418 sessionConfig->track_icmp_sessions = STREAM_TRACK_NO;
419 sessionConfig->max_icmp_sessions = STREAM_DEFAULT_MAX_ICMP_SESSIONS;
420 sessionConfig->track_ip_sessions = STREAM_TRACK_NO;
421 sessionConfig->max_ip_sessions = STREAM_DEFAULT_MAX_IP_SESSIONS;
422 sessionConfig->memcap = STREAM_DEFAULT_MEMCAP;
423 sessionConfig->prune_log_max = STREAM_DEFAULT_PRUNE_LOG_MAX;
424 #ifdef ACTIVE_RESPONSE
425 sessionConfig->max_active_responses = STREAM_DEFAULT_MAX_ACTIVE_RESPONSES;
426 sessionConfig->min_response_seconds = STREAM_DEFAULT_MIN_RESPONSE_SECONDS;
427 #endif
428
429 #ifdef ENABLE_HA
430 sessionConfig->enable_ha = 0;
431 #endif
432
433 return sessionConfig;
434 }
435
436 void initializeMaxExpectedFlows( SessionConfiguration *sessionConfig )
437 {
438 // initialize max expected flows...
439 uint32_t max = sessionConfig->max_tcp_sessions + sessionConfig->max_udp_sessions;
440
441 if( ( max >>= 9 ) == 0 )
442 max = 2;
443
444 StreamExpectInit(max);
445 LogMessage(" Max Expected Streams: %u\n", max);
446 }
447
448 void initializeSessionPreproc(struct _SnortConfig *sc, char *args)
449 {
450 if (session_configuration == NULL)
451 {
452 session_configuration = initSessionConfiguration( );
453
454 #ifdef PERF_PROFILING
455 RegisterPreprocessorProfile("session_manager", &sessionPerfStats, 0, &totalPerfStats, NULL);
456 # ifdef ENABLE_HA
457 RegisterPreprocessorProfile("session_ha", &sessionHAPerfStats, 1, &sessionPerfStats, NULL);
458 # endif
459 #endif
460
461 // register these to run last so other preprocs have chance to release all session
462 // related resources before session exits
463 AddFuncToPreprocCleanExitList(exitSessionCleanly, NULL, PRIORITY_LAST, PP_SESSION);
464 AddFuncToPreprocResetList(resetSessionState, NULL, PRIORITY_LAST, PP_SESSION);
465 AddFuncToPreprocResetStatsList(resetSessionStatistics, NULL, PP_SESSION_PRIORITY, PP_SESSION);
466 AddFuncToConfigCheckList(sc, verifySessionConfig);
467 RegisterPreprocStats("session_manager", printSessionStatistics);
468
469 session_api = &session_api_dispatch_table;
470
471 #ifdef ENABLE_HA
472 AddFuncToPostConfigList(sc, SessionHAPostConfigInit, NULL);
473 #endif
474
475 parseSessionConfiguration(session_configuration, args);
476 if( ( !session_configuration->disabled) &&
477 ( session_configuration->track_tcp_sessions == STREAM_TRACK_NO) &&
478 ( session_configuration->track_udp_sessions == STREAM_TRACK_NO) &&
479 ( session_configuration->track_icmp_sessions == STREAM_TRACK_NO) &&
480 ( session_configuration->track_ip_sessions == STREAM_TRACK_NO))
481 {
482 FatalError("%s(%d) ==> Session enabled, but not configured to track "
483 "TCP, UDP, ICMP, or IP.\n", file_name, file_line);
484 }
485
486 enablePreprocAllPorts( sc, PP_SESSION, PROTO_BIT__ALL );
487 // TBD-EDM - fix reg tests when this is enabled
488 // printSessionConfiguration(session_configuration);
489
490 // register default NAP selector, nap rule engine will overide when it is configured
491 registerNapSelector( &selectRuntimePolicy );
492 memset( appHandlerDispatchMask, 0, sizeof( appHandlerDispatchMask ) );
493 AddFuncToPreprocList(sc, sessionPacketProcessor, PP_SESSION_PRIORITY, PP_SESSION, PROTO_BIT__ALL);
494
495 initializeMaxExpectedFlows( session_configuration );
496 sc->run_flags |= RUN_FLAG__STATEFUL;
497 }
498 else
499 {
500 #if 0
501 // EDM-TBD
502 FatalError("stream5_global must only be configured once.\n");
503 #else
504 WarningMessage("stream5_global must only be configured once. Ignoring this configuration element\n");
505 #endif
506 }
507 }
508
509 static void parseSessionConfiguration( SessionConfiguration *config, char *args )
510 {
511 char **toks;
512 int num_toks;
513 int i;
514 char **stoks;
515 int s_toks;
516 char *endPtr = NULL;
517
518 if (config == NULL)
519 return;
520
521 if ((args == NULL) || (strlen(args) == 0))
522 return;
523
524 toks = mSplit(args, ",", 0, &num_toks, 0);
525 i = 0;
526
527 for (i = 0; i < num_toks; i++)
528 {
529 stoks = mSplit(toks[i], " ", 4, &s_toks, 0);
530
531 if (s_toks == 0)
532 {
533 FatalError("%s(%d) => Missing parameter in Session config.\n",
534 file_name, file_line);
535 }
536 if (s_toks > 2) //Trailing parameters
537 {
538 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
539 file_name, file_line);
540 }
541
542 if(!strcasecmp(stoks[0], "memcap"))
543 {
544 if (stoks[1])
545 {
546 config->memcap = strtoul(stoks[1], &endPtr, 10);
547 }
548
549 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
550 {
551 FatalError("%s(%d) => Invalid memcap in config file. Requires integer parameter.\n",
552 file_name, file_line);
553 }
554
555 if ((config->memcap > STREAM_RIDICULOUS_HI_MEMCAP) ||
556 (config->memcap < STREAM_RIDICULOUS_LOW_MEMCAP))
557 {
558 FatalError("%s(%d) => 'memcap %s' invalid: value must be "
559 "between %d and %d bytes\n",
560 file_name, file_line,
561 stoks[1], STREAM_RIDICULOUS_LOW_MEMCAP,
562 STREAM_RIDICULOUS_HI_MEMCAP);
563 }
564 }
565 else if(!strcasecmp(stoks[0], "max_tcp"))
566 {
567 if (stoks[1])
568 {
569 config->max_tcp_sessions = strtoul(stoks[1], &endPtr, 10);
570 if (config->track_tcp_sessions == STREAM_TRACK_YES)
571 {
572 if ((config->max_tcp_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
573 (config->max_tcp_sessions == 0))
574 {
575 FatalError("%s(%d) => 'max_tcp %d' invalid: value must be "
576 "between 1 and %d sessions\n",
577 file_name, file_line,
578 config->max_tcp_sessions,
579 STREAM_RIDICULOUS_MAX_SESSIONS);
580 }
581 }
582 }
583
584 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
585 {
586 FatalError("%s(%d) => Invalid max_tcp in config file. Requires integer parameter.\n",
587 file_name, file_line);
588 }
589 }
590 else if(!strcasecmp(stoks[0], "tcp_cache_pruning_timeout"))
591 {
592 if (stoks[1])
593 {
594 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
595
596 if (config->track_tcp_sessions == STREAM_TRACK_YES)
597 {
598 if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
599 {
600 FatalError(
601 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
602 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
603 }
604 }
605 config->tcp_cache_pruning_timeout = (uint16_t)timeout;
606 }
607
608 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
609 {
610 FatalError("%s(%d) => Invalid %s in config file. Requires integer parameter.\n",
611 file_name, file_line, stoks[0]);
612 }
613 }
614 else if(!strcasecmp(stoks[0], "tcp_cache_nominal_timeout"))
615 {
616 if (stoks[1])
617 {
618 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
619
620 if (config->track_tcp_sessions == STREAM_TRACK_YES)
621 {
622 if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
623 {
624 FatalError(
625 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
626 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
627 }
628 }
629 config->tcp_cache_nominal_timeout = (uint16_t)timeout;
630 }
631
632 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
633 {
634 FatalError("%s(%d) => Invalid %s in config file. Requires integer parameter.\n",
635 file_name, file_line, stoks[0]);
636 }
637 }
638 else if(!strcasecmp(stoks[0], "track_tcp"))
639 {
640 if (stoks[1])
641 {
642 if(!strcasecmp(stoks[1], "no"))
643 config->track_tcp_sessions = STREAM_TRACK_NO;
644 else if(!strcasecmp(stoks[1], "yes"))
645 config->track_tcp_sessions = STREAM_TRACK_YES;
646 else
647 FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
648 file_name, file_line);
649 }
650 else
651 {
652 FatalError("%s(%d) => 'track_tcp' missing option\n",
653 file_name, file_line);
654 }
655 }
656 else if(!strcasecmp(stoks[0], "max_udp"))
657 {
658 if (stoks[1])
659 {
660 config->max_udp_sessions = strtoul(stoks[1], &endPtr, 10);
661 if (config->track_udp_sessions == STREAM_TRACK_YES)
662 {
663 if ((config->max_udp_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
664 (config->max_udp_sessions == 0))
665 {
666 FatalError("%s(%d) => 'max_udp %d' invalid: value must be "
667 "between 1 and %d sessions\n",
668 file_name, file_line,
669 config->max_udp_sessions,
670 STREAM_RIDICULOUS_MAX_SESSIONS);
671 }
672 }
673 }
674
675 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
676 {
677 FatalError("%s(%d) => Invalid max_udp in config file. Requires integer parameter.\n",
678 file_name, file_line);
679 }
680 }
681 else if(!strcasecmp(stoks[0], "udp_cache_pruning_timeout"))
682 {
683 if (stoks[1])
684 {
685 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
686
687 if (config->track_udp_sessions == STREAM_TRACK_YES)
688 {
689 if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
690 {
691 FatalError(
692 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
693 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
694 }
695 }
696 config->udp_cache_pruning_timeout = (uint16_t)timeout;
697 }
698
699 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
700 {
701 FatalError("%s(%d) => Invalid %s in config file. Requires integer parameter.\n",
702 file_name, file_line, stoks[0]);
703 }
704 }
705 else if(!strcasecmp(stoks[0], "udp_cache_nominal_timeout"))
706 {
707 if (stoks[1])
708 {
709 unsigned long timeout = strtoul(stoks[1], &endPtr, 10);
710
711 if (config->track_udp_sessions == STREAM_TRACK_YES)
712 {
713 if ( !timeout || (timeout > STREAM_MAX_CACHE_TIMEOUT) )
714 {
715 FatalError(
716 "%s(%d) => '%s %lu' invalid: value must be between 1 and %d seconds\n",
717 file_name, file_line, stoks[0], timeout, STREAM_MAX_CACHE_TIMEOUT);
718 }
719 }
720 config->udp_cache_nominal_timeout = (uint16_t)timeout;
721 }
722
723 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
724 {
725 FatalError("%s(%d) => Invalid %s in config file. Requires integer parameter.\n",
726 file_name, file_line, stoks[0]);
727 }
728 }
729 else if(!strcasecmp(stoks[0], "track_udp"))
730 {
731 if (stoks[1])
732 {
733 if(!strcasecmp(stoks[1], "no"))
734 config->track_udp_sessions = STREAM_TRACK_NO;
735 else if(!strcasecmp(stoks[1], "yes"))
736 config->track_udp_sessions = STREAM_TRACK_YES;
737 else
738 FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
739 file_name, file_line);
740 }
741 else
742 {
743 FatalError("%s(%d) => 'track_udp' missing option\n",
744 file_name, file_line);
745 }
746 }
747 else if(!strcasecmp(stoks[0], "max_icmp"))
748 {
749 if (stoks[1])
750 {
751 config->max_icmp_sessions = strtoul(stoks[1], &endPtr, 10);
752
753 if (config->track_icmp_sessions == STREAM_TRACK_YES)
754 {
755 if ((config->max_icmp_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
756 (config->max_icmp_sessions == 0))
757 {
758 FatalError("%s(%d) => 'max_icmp %d' invalid: value must be "
759 "between 1 and %d sessions\n",
760 file_name, file_line,
761 config->max_icmp_sessions,
762 STREAM_RIDICULOUS_MAX_SESSIONS);
763 }
764 }
765 }
766
767 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
768 {
769 FatalError("%s(%d) => Invalid max_icmp in config file. Requires integer parameter.\n",
770 file_name, file_line);
771 }
772 }
773 else if(!strcasecmp(stoks[0], "track_icmp"))
774 {
775 if (stoks[1])
776 {
777 if(!strcasecmp(stoks[1], "no"))
778 config->track_icmp_sessions = STREAM_TRACK_NO;
779 else if(!strcasecmp(stoks[1], "yes"))
780 config->track_icmp_sessions = STREAM_TRACK_YES;
781 else
782 FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
783 file_name, file_line);
784 }
785 else
786 {
787 FatalError("%s(%d) => 'track_icmp' missing option\n",
788 file_name, file_line);
789 }
790 }
791 else if(!strcasecmp(stoks[0], "max_ip"))
792 {
793 if (stoks[1])
794 {
795 config->max_ip_sessions = strtoul(stoks[1], &endPtr, 10);
796
797 if (config->track_ip_sessions == STREAM_TRACK_YES)
798 {
799 if ((config->max_ip_sessions > STREAM_RIDICULOUS_MAX_SESSIONS) ||
800 (config->max_ip_sessions == 0))
801 {
802 FatalError("%s(%d) => 'max_ip %d' invalid: value must be "
803 "between 1 and %d sessions\n",
804 file_name, file_line,
805 config->max_ip_sessions,
806 STREAM_RIDICULOUS_MAX_SESSIONS);
807 }
808 }
809 }
810
811 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
812 {
813 FatalError("%s(%d) => Invalid max_ip in config file. Requires integer parameter.\n",
814 file_name, file_line);
815 }
816 }
817 else if(!strcasecmp(stoks[0], "track_ip"))
818 {
819 if (stoks[1])
820 {
821 if(!strcasecmp(stoks[1], "no"))
822 config->track_ip_sessions = STREAM_TRACK_NO;
823 else if(!strcasecmp(stoks[1], "yes"))
824 config->track_ip_sessions = STREAM_TRACK_YES;
825 else
826 FatalError("%s(%d) => invalid: value must be 'yes' or 'no'\n",
827 file_name, file_line);
828 }
829 else
830 {
831 FatalError("%s(%d) => 'track_ip' missing option\n",
832 file_name, file_line);
833 }
834 }
835 else if(!strcasecmp(stoks[0], "flush_on_alert"))
836 {
837 if (s_toks > 1) //Trailing parameters
838 {
839 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
840 file_name, file_line);
841 }
842 config->flags |= STREAM_CONFIG_FLUSH_ON_ALERT;
843 }
844 else if(!strcasecmp(stoks[0], "show_rebuilt_packets"))
845 {
846 if (s_toks > 1) //Trailing parameters
847 {
848 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
849 file_name, file_line);
850 }
851 config->flags |= STREAM_CONFIG_SHOW_PACKETS;
852 }
853 else if(!strcasecmp(stoks[0], "prune_log_max"))
854 {
855 if (stoks[1])
856 {
857 config->prune_log_max = strtoul(stoks[1], &endPtr, 10);
858 }
859
860 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
861 {
862 FatalError("%s(%d) => Invalid prune_log_max in config file. Requires integer parameter.\n",
863 file_name, file_line);
864 }
865
866 if (((config->prune_log_max > STREAM_MAX_PRUNE_LOG_MAX) ||
867 (config->prune_log_max < STREAM_MIN_PRUNE_LOG_MAX)) &&
868 (config->prune_log_max != 0))
869 {
870 FatalError("%s(%d) => Invalid Prune Log Max."
871 " Must be 0 (disabled) or between %d and %d\n",
872 file_name, file_line,
873 STREAM_MIN_PRUNE_LOG_MAX, STREAM_MAX_PRUNE_LOG_MAX);
874 }
875 }
876 #ifdef TBD
877 else if(!strcasecmp(stoks[0], "no_midstream_drop_alerts"))
878 {
879 /*
880 * FIXTHIS: Do we want to not alert on drops for sessions picked
881 * up midstream ? If we're inline, and get a session midstream,
882 * its because it was picked up during startup. In inline
883 * mode, we should ALWAYS be requiring TCP 3WHS.
884 */
885 if (s_toks > 1) //Trailing parameters
886 {
887 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
888 file_name, file_line);
889 }
890 config->flags |= STREAM_CONFIG_MIDSTREAM_DROP_NOALERT;
891 }
892 #endif
893 #ifdef ACTIVE_RESPONSE
894 else if(!strcasecmp(stoks[0], "max_active_responses"))
895 {
896 if (stoks[1])
897 {
898 config->max_active_responses = (uint8_t)SnortStrtoulRange(stoks[1], &endPtr, 10, 0, STREAM_MAX_ACTIVE_RESPONSES_MAX);
899 }
900 if ((!stoks[1] || (endPtr == &stoks[1][0])) || *endPtr ||
901 (config->max_active_responses > STREAM_MAX_ACTIVE_RESPONSES_MAX))
902 {
903 FatalError("%s(%d) => 'max_active_responses %d' invalid: "
904 "value must be between 0 and %d responses.\n",
905 file_name, file_line, config->max_active_responses,
906 STREAM_MAX_ACTIVE_RESPONSES_MAX);
907 }
908 if ( config->max_active_responses > 0 )
909 {
910 Active_SetEnabled(2);
911 }
912 }
913 else if(!strcasecmp(stoks[0], "min_response_seconds"))
914 {
915 if (stoks[1])
916 {
917 config->min_response_seconds = strtoul(stoks[1], &endPtr, 10);
918 }
919 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
920 {
921 FatalError("%s(%d) => Invalid min_response_seconds in config file. "
922 " Requires integer parameter.\n", file_name, file_line);
923 }
924 else if ( ( config->min_response_seconds > STREAM_MIN_RESPONSE_SECONDS_MAX ) ||
925 ( config->min_response_seconds < 1 ) )
926 {
927 FatalError("%s(%d) => 'min_response_seconds %d' invalid: "
928 "value must be between 1 and %d seconds.\n",
929 file_name, file_line, config->min_response_seconds,
930 STREAM_MIN_RESPONSE_SECONDS_MAX);
931 }
932 }
933 #endif
934 #ifdef ENABLE_HA
935 else if (!strcasecmp(stoks[0], "enable_ha"))
936 {
937 if (s_toks > 1) //Trailing parameters
938 {
939 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
940 file_name, file_line);
941 }
942 config->enable_ha = 1;
943 }
944 #endif /* ENABLE_HA */
945 else if(!strcasecmp(stoks[0], "disabled"))
946 {
947 if (s_toks > 1) //Trailing parameters
948 {
949 FatalError("%s(%d) => Too many parameters for option in Session config.\n",
950 file_name, file_line);
951 }
952 config->disabled = 1;
953 #if 0
954 // TBD-EDM - breaks reg tests, enable after merge and fix tests
955 WarningMessage("%s(%d) Session disable option is set...supported option but nothing useful can come of this.\n",
956 file_name, file_line);
957 #endif
958 }
959 else
960 {
961 FatalError("%s(%d) => Unknown Session global option (%s)\n",
962 file_name, file_line, toks[i]);
963 }
964
965 mSplitFree(&stoks, s_toks);
966 }
967
968 mSplitFree(&toks, num_toks);
969 }
970
971 static void printSessionConfiguration(SessionConfiguration *config)
972 {
973 // TBD-EDM
974 #if 0
975 if (config == NULL)
976 return;
977
978 LogMessage("Session global config:\n");
979 if (config->track_tcp_sessions == STREAM_TRACK_YES)
980 LogMessage(" Max TCP sessions: %u\n", config->max_tcp_sessions);
981 if (config->track_udp_sessions == STREAM_TRACK_YES)
982 LogMessage(" Max UDP sessions: %u\n", config->max_udp_sessions);
983 if (config->track_icmp_sessions == STREAM_TRACK_YES)
984 LogMessage(" Max ICMP sessions: %u\n", config->max_icmp_sessions);
985 if (config->track_ip_sessions == STREAM_TRACK_YES)
986 LogMessage(" Max IP sessions: %u\n", config->max_ip_sessions);
987 if (config->prune_log_max)
988 {
989 LogMessage(" Log info if session memory consumption exceeds %d\n",
990 config->prune_log_max);
991 }
992 #ifdef ACTIVE_RESPONSE
993 LogMessage(" Send up to %d active responses\n", config->max_active_responses);
994
995 if (config->max_active_responses > 1)
996 {
997 LogMessage(" Wait at least %d seconds between responses\n", config->min_response_seconds);
998 }
999 #endif
1000 #ifdef ENABLE_HA
1001 LogMessage(" High Availability: %s\n", config->enable_ha ? "ENABLED" : "DISABLED");
1002 #endif
1003 #endif
1004 }
1005
1006 static void resetSessionState( int signal, void *foo )
1007 {
1008 if ( session_configuration == NULL )
1009 return;
1010
1011 mempool_clean( &sessionFlowMempool );
1012 }
1013
1014 static void resetSessionStatistics( int signal, void *foo )
1015 {
1016 memset( &session_stats, 0, sizeof( session_stats ) );
1017 #ifdef ENABLE_HA
1018 SessionResetHAStats();
1019 #endif
1020 }
1021
1022 static void exitSessionCleanly( int signal, void *foo )
1023 {
1024 #ifdef ENABLE_HA
1025 SessionCleanHA();
1026 #endif
1027
1028 /* free expected session data structures... */
1029 StreamExpectCleanup();
1030
1031 mempool_destroy( &sessionFlowMempool );
1032 freeSessionPlugins( );
1033 SessionFreeConfig( session_configuration );
1034 session_configuration = NULL;
1035 }
1036
1037 static int verifySessionConfig( struct _SnortConfig *sc )
1038 {
1039 int obj_size = 0;
1040 unsigned total_sessions = 0;
1041
1042 if( session_configuration == NULL )
1043 {
1044 FatalError("%s(%d) Session config is NULL.\n", __FILE__, __LINE__);
1045 }
1046
1047 #ifdef ENABLE_HA
1048 if( session_configuration->enable_ha )
1049 {
1050 if( ( SessionVerifyHAConfig( sc, session_configuration->ha_config ) != 0 ) )
1051 {
1052 FatalError( "Session HA misconfigured. Session preprocessor exiting\n" );
1053 }
1054 }
1055 #endif
1056
1057 if(session_configuration->track_tcp_sessions)
1058 total_sessions += session_configuration->max_tcp_sessions;
1059 else
1060 {
1061 session_configuration->memcap = 0;
1062 session_configuration->max_tcp_sessions = 0;
1063 }
1064 if(session_configuration->track_udp_sessions)
1065 total_sessions += session_configuration->max_udp_sessions;
1066 else
1067 session_configuration->max_udp_sessions = 0;
1068 if(session_configuration->track_icmp_sessions)
1069 total_sessions += session_configuration->max_icmp_sessions;
1070 else
1071 session_configuration->max_icmp_sessions = 0;
1072 if(session_configuration->track_ip_sessions)
1073 total_sessions += session_configuration->max_ip_sessions;
1074 else
1075 session_configuration->max_ip_sessions = 0;
1076
1077 if( total_sessions == 0 && !session_configuration->disabled)
1078 {
1079 FatalError( "%s(%d) All protocols configured with 0 as max session count.\n", __FILE__, __LINE__ );
1080 }
1081
1082 /* Initialize the memory pool for Flowbits Data */
1083 /* use giFlowbitSize - 1, since there is already 1 byte in the
1084 * StreamFlowData structure */
1085 obj_size = sizeof( StreamFlowData ) + getFlowbitSizeInBytes( ) - 1;
1086
1087 if( ( obj_size % sizeof( long ) ) != 0 )
1088 {
1089 /* Increase obj_size by sizeof(long) to force sizeof(long) byte
1090 * alignment for each object in the mempool. Without this,
1091 * the mempool data buffer was not aligned. Overlaying the
1092 * StreamFlowData structure caused problems on some Solaris
1093 * platforms. */
1094 obj_size += ( sizeof( long ) - ( obj_size % sizeof( long ) ) );
1095 }
1096
1097 if (total_sessions != 0)
1098 {
1099 if( mempool_init( &sessionFlowMempool, total_sessions, obj_size ) != 0 )
1100 {
1101 FatalError( "%s(%d) Could not initialize flow bits memory pool.\n", __FILE__, __LINE__ );
1102 }
1103 }
1104
1105 session_configuration->max_sessions = total_sessions;
1106 session_configuration->numSnortPolicies = sc->num_policies_allocated;
1107 session_configuration->policy_ref_count = calloc( sc->num_policies_allocated, sizeof( uint32_t ) );
1108 if( !session_configuration->policy_ref_count )
1109 {
1110 FatalError( "%s(%d) Could not allocate policy ref count.\n", __FILE__, __LINE__ );
1111 }
1112
1113 return 0;
1114 }
1115
1116 static void printSessionStatistics( int exiting )
1117 {
1118 #if 0
1119 LogMessage("Session statistics:\n");
1120 LogMessage(" Total sessions: %u\n", session_stats.total_tcp_sessions +
1121 session_stats.total_udp_sessions +
1122 session_stats.total_icmp_sessions +
1123 session_stats.total_ip_sessions);
1124 LogMessage(" TCP sessions: %u\n", session_stats.total_tcp_sessions);
1125 LogMessage(" UDP sessions: %u\n", session_stats.total_udp_sessions);
1126 LogMessage(" ICMP sessions: %u\n", session_stats.total_icmp_sessions);
1127 LogMessage(" IP sessions: %u\n", session_stats.total_ip_sessions);
1128
1129 LogMessage(" Events: %u\n", session_stats.events);
1130 LogMessage(" Internal Events: %u\n", session_stats.internalEvents);
1131 LogMessage(" TCP Port Filter\n");
1132 LogMessage(" Dropped: %u\n", session_stats.tcp_port_filter.filtered);
1133 LogMessage(" Inspected: %u\n", session_stats.tcp_port_filter.inspected);
1134 LogMessage(" Tracked: %u\n", session_stats.tcp_port_filter.session_tracked);
1135 LogMessage(" UDP Port Filter\n");
1136 LogMessage(" Dropped: %u\n", session_stats.udp_port_filter.filtered);
1137 LogMessage(" Inspected: %u\n", session_stats.udp_port_filter.inspected);
1138 LogMessage(" Tracked: %u\n", session_stats.udp_port_filter.session_tracked);
1139 #ifdef ENABLE_HA
1140 SessionPrintHAStats();
1141 #endif
1142 #endif
1143 }
1144
1145 static void initPreprocDispatchList( Packet *p )
1146 {
1147 PreprocEvalFuncNode *ppn;
1148 SnortPolicy *policy = snort_conf->targeted_policies[ getNapRuntimePolicy() ];
1149
1150 // set initial post session preproc enabled for the policy selected for
1151 // this session
1152 ppn = policy->preproc_eval_funcs;
1153 while( ppn != NULL && ppn->priority <= PP_SESSION_PRIORITY )
1154 ppn = ppn->next;
1155
1156 p->cur_pp = ppn;
1157 }
1158
1159 static inline int isPacketEligible( Packet *p )
1160 {
1161 if( ( p->frag_flag ) || ( p->error_flags & PKT_ERR_CKSUM_IP ) )
1162 return 0;
1163
1164 if( p->packet_flags & PKT_REBUILT_STREAM )
1165 return 0;
1166
1167 if( !IPH_IS_VALID( p ) )
1168 return 0;
1169
1170 switch( GET_IPH_PROTO( p ) )
1171 {
1172 case IPPROTO_TCP:
1173 {
1174 if( p->tcph == NULL )
1175 return 0;
1176
1177 if( p->error_flags & PKT_ERR_CKSUM_TCP )
1178 return 0;
1179 }
1180 break;
1181
1182 case IPPROTO_UDP:
1183 {
1184 if( p->udph == NULL )
1185 return 0;
1186
1187 if( p->error_flags & PKT_ERR_CKSUM_UDP )
1188 return 0;
1189 }
1190 break;
1191
1192 case IPPROTO_ICMP:
1193 case IPPROTO_ICMPV6:
1194 {
1195 if( p->icmph == NULL )
1196 return 0;
1197
1198 if( p->error_flags & PKT_ERR_CKSUM_ICMP )
1199 return 0;
1200 }
1201 break;
1202
1203 default:
1204 if( p->iph == NULL )
1205 return 0;
1206 break;
1207 }
1208
1209 return 1;
1210 }
1211
1212 void insertIntoOneWaySessionList( SessionCache *session_cache, SessionControlBlock *scb )
1213 {
1214
1215 if( session_cache->ows_list.head == NULL )
1216 {
1217 // list is empty link head & tail pointers to this scb
1218 session_cache->ows_list.head = scb;
1219 session_cache->ows_list.tail = scb;
1220 scb->ows_next = NULL;
1221 scb->ows_prev = NULL;
1222 }
1223 else
1224 {
1225 // list is not empty, add this node to the end
1226 session_cache->ows_list.tail->ows_next = scb;
1227 scb->ows_prev = session_cache->ows_list.tail;
1228 scb->ows_next = NULL;
1229 session_cache->ows_list.tail = scb;
1230 }
1231
1232 // set scb state to in oneway list and increment count of sessions
1233 // in the oneway list
1234 scb->in_oneway_list = true;
1235 session_cache->ows_list.num_sessions++;
1236 }
1237
1238 void removeFromOneWaySessionList( SessionCache *session_cache, SessionControlBlock *scb )
1239 {
1240 if( scb->ows_prev == NULL )
1241 {
1242 // removing first node
1243 if( scb->ows_next == NULL )
1244 {
1245 // only node in list
1246 session_cache->ows_list.head = NULL;
1247 session_cache->ows_list.tail = NULL;
1248 }
1249 else
1250 {
1251 session_cache->ows_list.head = scb->ows_next;
1252 scb->ows_next->ows_prev = NULL;
1253 }
1254 }
1255 else if ( scb->ows_next == NULL )
1256 {
1257 // removing last node ( list with one node detected above so must be >1 nodes here )
1258 session_cache->ows_list.tail = scb->ows_prev;
1259 scb->ows_prev->ows_next = NULL;
1260 }
1261 else
1262 {
1263 // removing node from middle of list
1264 scb->ows_prev->ows_next = scb->ows_next;
1265 scb->ows_next->ows_prev = scb->ows_prev;
1266 }
1267
1268 scb->ows_next = NULL;
1269 scb->ows_prev = NULL;
1270
1271 // set scb state to not in oneway list and decrement count of sessions
1272 // in the oneway list
1273 scb->in_oneway_list = false;
1274 session_cache->ows_list.num_sessions--;
1275 }
1276
1277 static void decrementPolicySessionRefCount( SessionControlBlock *scb )
1278 {
1279
1280 #ifdef ENABLE_HA
1281 // if in standby no policy bound to this session
1282 if( scb->ha_flags & HA_FLAG_STANDBY )
1283 return;
1284 #endif
1285
1286 if( scb->napPolicyId < scb->session_config->numSnortPolicies )
1287 {
1288 scb->session_config->policy_ref_count[ scb->napPolicyId ]--;
1289
1290 #ifdef SNORT_RELOAD
1291 if( scb->session_config != session_configuration ||
1292 scb->session_config->no_ref_cb )
1293 #else
1294 if( scb->session_config != session_configuration )
1295 #endif
1296 {
1297 uint32_t i;
1298 bool no_refs = true;
1299
1300 for( i = 0; i < scb->session_config->numSnortPolicies; i++ )
1301 if( scb->session_config->policy_ref_count[ i ] > 0 )
1302 {
1303 no_refs = false;
1304 break;
1305 }
1306
1307 if( no_refs )
1308 {
1309 #ifdef SNORT_RELOAD
1310 if( scb->session_config->no_ref_cb )
1311 {
1312 scb->session_config->no_ref_cb(scb->session_config->no_ref_cb_data);
1313 scb->session_config->no_ref_cb = NULL;
1314 scb->session_config->no_ref_cb_data = NULL;
1315 }
1316 #endif
1317 if( scb->session_config != session_configuration )
1318 SessionFreeConfig( scb->session_config );
1319 }
1320 }
1321 }
1322 else
1323 {
1324 WarningMessage("%s(%d) NAP Policy ID is UNBOUND or not valid: %u", file_name, file_line, scb->napPolicyId );
1325 }
1326 }
1327
1328 void initializePacketPolicy( Packet *p, SessionControlBlock *scb )
1329 {
1330 SnortPolicy *policy;
1331
1332 // opensource policy selector will set to true, product does not
1333 p->ips_os_selected = false;
1334
1335 if( scb != NULL )
1336 {
1337 // if config pointer is same as online we are good to go...
1338 if( scb->session_config != session_configuration )
1339 {
1340 // session config has been reloaded, reevaluate packet against NAP rules
1341 decrementPolicySessionRefCount( scb );
1342 scb->initial_pp = NULL;
1343 scb->stream_config_stale = true;
1344 scb->napPolicyId = SF_POLICY_UNBOUND;
1345 scb->ipsPolicyId = SF_POLICY_UNBOUND;
1346 scb->session_config = session_configuration;
1347 }
1348
1349 /* Select the policy for this session...Then initialize list of
1350 * additional preprocs to be dispatched for this session
1351 */
1352 if ( scb->napPolicyId == SF_POLICY_UNBOUND )
1353 {
1354 if( isNapRuntimePolicyDefault())
1355 getSessionPlugins()->select_session_nap( p,
1356 ( getPacketDirection( p ) & PKT_FROM_CLIENT ) ? true : false );
1357 scb->napPolicyId = getNapRuntimePolicy();
1358 session_configuration->policy_ref_count[ scb->napPolicyId ]++;
1359 scb->ipsPolicyId = getIpsRuntimePolicy();
1360
1361 // set the preproc enable mask for pps registered to handle traffic on this port
1362 policy = snort_conf->targeted_policies[ scb->napPolicyId ];
1363 scb->enabled_pps = policy->pp_enabled[ ntohs(scb->server_port) ];
1364 if( scb->port_guess )
1365 scb->enabled_pps |= policy->pp_enabled[ ntohs(scb->client_port) ];
1366 scb->ips_os_selected = p->ips_os_selected;
1367 }
1368 else
1369 {
1370 // set runtime policy from session setting, session already has preproc list
1371 setNapRuntimePolicy( scb->napPolicyId );
1372 setIpsRuntimePolicy( scb->ipsPolicyId );
1373 p->ips_os_selected = scb->ips_os_selected;
1374 }
1375
1376 initPreprocDispatchList( p );
1377 EnablePreprocessors( p, scb->enabled_pps );
1378
1379 // save current ha state for ha processing after packet processing has completed
1380 scb->cached_ha_state = scb->ha_state;
1381 }
1382 else
1383 {
1384 // no session, select policy from packet network parameters
1385 getSessionPlugins()->select_session_nap( p,
1386 ( getPacketDirection( p ) & PKT_FROM_CLIENT ) ? true : false );
1387 initPreprocDispatchList( p );
1388 policy = snort_conf->targeted_policies[ getNapRuntimePolicy() ];
1389 EnablePreprocessors( p, policy->pp_enabled[ p->dp ] | policy->pp_enabled[ p->sp ] );
1390 }
1391 }
1392
1393 static inline SessionControlBlock *findPacketSessionControlBlock(SessionCache *sessionCache, Packet *p, SessionKey *key)
1394 {
1395 SessionControlBlock *scb = NULL;
1396 #if defined(DAQ_CAPA_CST_TIMEOUT)
1397 uint64_t timeout;
1398 #endif
1399
1400 if (!sessionCache)
1401 return NULL;
1402 scb = checkSessionControlBlock(sessionCache, p, key);
1403 if (scb && getSessionExpirationTime(p, scb))
1404 {
1405 // We retrieved a scb which has already expired but not deleted
1406 // Delete the previous scb and recover it from HA data
1407 deleteSessionByKey (scb, "expired and not cleaned") ;
1408 scb = p->ssnptr = NULL;
1409 }
1410 #if defined(DAQ_CAPA_CST_TIMEOUT)
1411 else if (scb && (p->pkth->flags & DAQ_PKT_FLAG_NEW_FLOW))
1412 {
1413 //We retrieved a scb but this is a new flow, which means this is stale scb, Delete it
1414 deleteSessionByKey (scb, "stale and not cleaned") ;
1415 scb = p->ssnptr = NULL;
1416 }
1417 #endif
1418 else
1419 {
1420 // Update the time of last data seen in the SCB
1421 updateSessionControlBlockTime(scb, p);
1422 }
1423
1424 #if defined(ENABLE_HA) && defined(HAVE_DAQ_QUERYFLOW)
1425 if ((!scb || !scb->appDataList) && session_configuration->enable_ha && session_configuration->ha_config->use_daq &&
1426 #ifndef REG_TEST
1427 (p->pkth->flags & DAQ_PKT_FLAG_HA_STATE_AVAIL) &&
1428 #endif
1429 SessionHAQueryDAQState(p->pkth) == 0)
1430 {
1431
1432 scb = getSessionControlBlock(sessionCache, p, key);
1433 #if defined(DAQ_CAPA_CST_TIMEOUT)
1434 if (scb && Daq_Capa_Timeout)
1435 {
1436 GetTimeout(p,&timeout);
1437 sessionCache->timeoutNominal = timeout;
1438 setSessionExpirationTime(p,scb,timeout);
1439 }
1440 #endif
1441 }
1442 #endif
1443
1444 #ifdef HAVE_DAQ_PKT_TRACE
1445 if (pkt_trace_enabled && (p->pkth->flags & DAQ_PKT_FLAG_SIMULATED) && scb)
1446 {
1447 addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
1448 "Session: simulated packet matches existing snort session\n"));
1449 }
1450 #endif
1451
1452 return scb;
1453 }
1454
1455 // Return true if a preprocessor is enabled for a session
1456 static inline bool isPreprocEnabledForSession( SessionControlBlock *scb, uint32_t preproc_id )
1457 {
1458 return ( scb && scb->enabled_pps & (UINT64_C(1) << preproc_id) ) ? true : false;
1459 }
1460
1461 // Turn ON a preprocessor for a session
1462 static inline void enablePreprocForSession( SessionControlBlock *scb, uint32_t preproc_id)
1463 {
1464 if( scb != NULL )
1465 scb->enabled_pps |= ( UINT64_C(1) << preproc_id );
1466 }
1467
1468 #if defined (HAVE_DAQ_QUERYFLOW) && defined (DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID)
1469 int SessionConnMetaQuery(const DAQ_PktHdr_t *pkthdr)
1470 {
1471 DAQ_QueryFlow_t query;
1472 int rval;
1473
1474 query.type = DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID;
1475 query.length = 0;
1476 query.value = 0;
1477
1478 rval = DAQ_QueryFlow(pkthdr, &query);
1479 if (rval == DAQ_SUCCESS ||
1480 rval == DAQ_ERROR_NOTSUP)
1481 return 1;
1482 else
1483 return 0;
1484 }
1485 #endif
1486
1487 static void sessionPacketProcessor(Packet *p, void *context)
1488 {
1489 SessionControlBlock *scb = NULL;
1490 SessionKey key;
1491 uint32_t flags;
1492 #if defined(DAQ_CAPA_CST_TIMEOUT)
1493 uint64_t timeout;
1494 #endif
1495
1496 PROFILE_VARS;
1497
1498 if (!firstPacketTime)
1499 firstPacketTime = p->pkth->ts.tv_sec;
1500
1501 if( !isPacketEligible( p ) )
1502 {
1503 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "Is not eligible!\n"););
1504 initializePacketPolicy( p, p->ssnptr );
1505 return;
1506 }
1507
1508 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"););
1509 DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "In Session!\n"););
1510
1511 PREPROC_PROFILE_START(sessionPerfStats);
1512
1513 if( p->ssnptr == NULL )
1514 {
1515 switch( GET_IPH_PROTO( p ) )
1516 {
1517 case IPPROTO_TCP:
1518 scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_TCP ], p, &key );
1519 #if defined(DAQ_CAPA_CST_TIMEOUT)
1520 /* we will do syn re-evaluation when the we recive SYN for stale scssions
1521 * we will delete session when we recive SYN on session
1522 * which is going to be exired in this time STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED*/
1523 if ( scb != NULL &&
1524 Daq_Capa_Timeout && (p->tcph && p->tcph->th_flags & (TH_SYN)) &&
1525 (scb->expire_time - (((uint64_t)p->pkth->ts.tv_sec ) * TCP_HZ) <= STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED))
1526 {
1527 scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
1528 deleteSession(proto_session_caches[ SESSION_PROTO_TCP ], scb, "stale/timeout",true);
1529 scb = NULL;
1530 }
1531 #endif
1532 if ( ( scb == NULL ) && SessionTrackingEnabled( session_configuration, SESSION_PROTO_TCP ) )
1533 {
1534 #if defined(HAVE_DAQ_QUERYFLOW) && defined (DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID)
1535 /* It is observed for non-IP packets, conn meta check fails. In case of conn meta check failure,
1536 * check if non_ip_pkt is set to allow flow creation.
1537 */
1538 if (SessionConnMetaQuery(p->pkth) || p->non_ip_pkt) {
1539 scb = createSession( proto_session_caches[ SESSION_PROTO_TCP ], p, &key );
1540 } else {
1541 if (pkt_trace_enabled)
1542 addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
1543 "Conn meta is not available. So not creating TCP session\n"));
1544 DisablePacketAnalysis( p );
1545 PREPROC_PROFILE_END(sessionPerfStats);
1546 return;
1547 }
1548 #else
1549 scb = createSession( proto_session_caches[ SESSION_PROTO_TCP ], p, &key );
1550 #endif
1551 #if defined(DAQ_CAPA_CST_TIMEOUT)
1552 if (Daq_Capa_Timeout && scb != NULL)
1553 {
1554
1555 GetTimeout(p,&timeout);
1556 timeout = timeout + STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED;
1557 proto_session_caches[ SESSION_PROTO_TCP ]->timeoutNominal = timeout;
1558 setSessionExpirationTime(p,scb,timeout);
1559 }
1560 #endif
1561 }
1562
1563 if( ( scb != NULL ) && !scb->session_established && ( getSessionPlugins()->set_tcp_dir_ports != NULL ) )
1564 getSessionPlugins()->set_tcp_dir_ports( p, scb );
1565
1566 break;
1567
1568 case IPPROTO_UDP:
1569 scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_UDP ], p, &key );
1570 if( ( scb == NULL ) && SessionTrackingEnabled( session_configuration, SESSION_PROTO_UDP ) )
1571 {
1572 #if defined(HAVE_DAQ_QUERYFLOW) && defined (DAQ_QUERYFLOW_TYPE_IS_CONN_META_VALID)
1573 /* It is observed for non-IP packets, conn meta check fails. In case of conn meta check failure,
1574 * check if non_ip_pkt is set to allow flow creation.
1575 */
1576 if (SessionConnMetaQuery(p->pkth) || p->non_ip_pkt) {
1577 scb = createSession( proto_session_caches[ SESSION_PROTO_UDP ], p, &key );
1578 } else {
1579 if (pkt_trace_enabled)
1580 addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
1581 "Conn meta is not available. So not creating UDP session\n"));
1582 DisablePacketAnalysis( p );
1583 PREPROC_PROFILE_END(sessionPerfStats);
1584 return;
1585 }
1586 #else
1587 scb = createSession( proto_session_caches[ SESSION_PROTO_UDP ], p, &key );
1588 #endif
1589 #if defined(DAQ_CAPA_CST_TIMEOUT)
1590 if (Daq_Capa_Timeout && scb != NULL)
1591 {
1592 GetTimeout(p,&timeout);
1593 proto_session_caches[ SESSION_PROTO_UDP ]->timeoutNominal = timeout;
1594 setSessionExpirationTime(p,scb,timeout);
1595 }
1596 #endif
1597 }
1598
1599 if( scb && !scb->session_established && ( getSessionPlugins()->set_udp_dir_ports != NULL ) )
1600 getSessionPlugins()->set_udp_dir_ports( p, scb );
1601
1602 break;
1603
1604 case IPPROTO_ICMP:
1605 // new flow allocate an scb, if not tracking ICMP, then fall thru and treat packet as
1606 // an IP protocol packet
1607 if ( SessionTrackingEnabled( session_configuration, SESSION_PROTO_ICMP ) )
1608 {
1609 scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_ICMP ], p, &key );
1610 if( scb != NULL )
1611 break;
1612
1613 scb = createSession( proto_session_caches[ SESSION_PROTO_ICMP ], p, &key );
1614 #if defined(DAQ_CAPA_CST_TIMEOUT)
1615 if (Daq_Capa_Timeout && scb != NULL)
1616 {
1617
1618 GetTimeout(p,&timeout);
1619 proto_session_caches[ SESSION_PROTO_ICMP ]->timeoutNominal = timeout;
1620 setSessionExpirationTime(p,scb,timeout);
1621 }
1622 #endif
1623
1624 break;
1625 }
1626 // fall thru, not tracking ICMP, treat as IP packet...
1627
1628 case IPPROTO_IP:
1629 default:
1630 scb = findPacketSessionControlBlock( proto_session_caches[ SESSION_PROTO_IP ], p, &key );
1631 if( ( scb == NULL ) && SessionTrackingEnabled( session_configuration, SESSION_PROTO_IP ) )
1632 {
1633 scb = createSession( proto_session_caches[ SESSION_PROTO_IP ], p, &key );
1634 #if defined(DAQ_CAPA_CST_TIMEOUT)
1635 if (Daq_Capa_Timeout && scb != NULL)
1636 {
1637
1638 GetTimeout(p,&timeout);
1639 proto_session_caches[ SESSION_PROTO_IP ]->timeoutNominal = timeout;
1640 setSessionExpirationTime(p,scb,timeout);
1641 }
1642 #endif
1643 }
1644 break;
1645
1646 }
1647 // assign allocated SCB to the Packet structure
1648 p->ssnptr = scb;
1649 }
1650 else
1651 {
1652 scb = p->ssnptr;
1653 }
1654
1655 initializePacketPolicy( p, scb );
1656
1657 flags = getSessionFlags( scb );
1658
1659 if( ( scb && (getIPRepUpdateCount() != scb->iprep_update_counter ) )
1660 && ( !(isPreprocEnabledForSession(scb,PP_REPUTATION)) && !(flags & (SSNFLAG_DETECTION_DISABLED|SSNFLAG_FORCE_BLOCK)) ) )
1661 {
1662 // If preproc was disabled or flow was whitelisted earlier, re-enable reputation
1663 EnablePreprocessor(p, PP_REPUTATION);
1664 enablePreprocForSession(scb, PP_REPUTATION);
1665 scb->ha_state.session_flags &= ~SSNFLAG_DETECTION_DISABLED;
1666 scb->ha_state.session_flags &= ~SSNFLAG_FORCE_BLOCK;
1667 }
1668 else if( flags & SSNFLAG_FORCE_BLOCK )
1669 {
1670 DisablePacketAnalysis( p );
1671 /* Detect will turn on the perfmonitor preprocessor when this function returns */
1672 scb->enabled_pps = PP_PERFMONITOR;
1673 Active_ForceDropSession();
1674 if (pkt_trace_enabled)
1675 addPktTraceData(VERDICT_REASON_SESSION, snprintf(trace_line, MAX_TRACE_LINE,
1676 "Session: blocked session flag is true, %s\n", getPktTraceActMsg()));
1677 else addPktTraceData(VERDICT_REASON_SESSION, 0);
1678 }
1679 else if( flags & SSNFLAG_DETECTION_DISABLED )
1680 {
1681 DisablePacketAnalysis( p );
1682 /* Detect will turn on the perfmonitor preprocessor when this function returns */
1683 scb->enabled_pps = PP_PERFMONITOR;
1684 }
1685
1686 PREPROC_PROFILE_END(sessionPerfStats);
1687 }
1688
1689 /*************************** API Implementations *******************/
1690 #define SESSION_CACHE_FLAG_PURGING 0x01
1691 #define SESSION_CACHE_FLAG_PRUNING 0x02
1692
1693 #if 0
1694
1695 void PrintSessionKey(SessionKey *skey)
1696 {
1697 LogMessage("SessionKey:\n");
1698 LogMessage(" ip_l = 0x%08X\n", skey->ip_l);
1699 LogMessage(" ip_h = 0x%08X\n", skey->ip_h);
1700 LogMessage(" prt_l = %d\n", skey->port_l);
1701 LogMessage(" prt_h = %d\n", skey->port_h);
1702 LogMessage(" vlan_tag = %d\n", skey->vlan_tag);
1703 #ifdef MPLS
1704 LogMessage(" mpls label = 0x%08X\n", skey->mplsLabel);
1705 #endif
1706 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1707 LogMessage(" addr space id = %d\n", skey->addressSpaceId);
1708 #endif
1709 }
1710 #endif
1711
1712 static int getActiveSessionCount(SessionCache* session_cache)
1713 {
1714 if (session_cache &&session_cache->hashTable)
1715 return session_cache->hashTable->count;
1716 else
1717 return 0;
1718 }
1719
1720 static uint32_t getSessionPruneCount( uint32_t protocol )
1721 {
1722
1723 if( protocol < SESSION_PROTO_MAX )
1724 {
1725 if( proto_session_caches[ protocol ] )
1726 return proto_session_caches[ protocol ]->prunes;
1727 else
1728 return 0;
1729 }
1730 else
1731 {
1732 WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
1733 return 0;
1734 }
1735 }
1736
1737 static void resetSessionPruneCount( uint32_t protocol )
1738 {
1739 if( protocol < SESSION_PROTO_MAX )
1740 {
1741 if( proto_session_caches[protocol] )
1742 proto_session_caches[protocol]->prunes = 0;
1743 }
1744 else
1745 {
1746 WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
1747 }
1748 }
1749
1750 static int initSessionKeyFromPktHeader( sfaddr_t* srcIP,
1751 uint16_t srcPort,
1752 sfaddr_t* dstIP,
1753 uint16_t dstPort,
1754 char proto,
1755 uint16_t vlan,
1756 uint32_t mplsId,
1757 #if !defined(DAQ_CAPA_VRF) || defined(SFLINUX)
1758 uint16_t addressSpaceId,
1759 #else
1760 uint16_t address_space_id_src,
1761 uint16_t address_space_id_dst,
1762 #endif
1763 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
1764 uint32_t carrierId,
1765 #endif
1766 SessionKey *key )
1767
1768 {
1769 uint16_t sport;
1770 uint16_t dport;
1771 sfaddr_t *src;
1772 sfaddr_t *dst;
1773 /* Because the key is going to be used for hash lookups,
1774 * the lower of the values of the IP address field is
1775 * stored in the key->ip_l and the port for that ip is
1776 * stored in key->port_l.
1777 */
1778
1779 if (!key)
1780 return 0;
1781
1782
1783 switch (proto)
1784 {
1785 case IPPROTO_TCP:
1786 case IPPROTO_UDP:
1787 sport = srcPort;
1788 dport = dstPort;
1789 break;
1790 case IPPROTO_ICMP:
1791 if (srcPort == ICMP_ECHOREPLY)
1792 {
1793 dport = ICMP_ECHO; /* Treat ICMP echo reply the same as request */
1794 sport = 0;
1795 }
1796 else if (srcPort == ICMP_ROUTER_ADVERTISE)
1797 {
1798 dport = ICMP_ROUTER_SOLICIT; /* Treat ICMP router advertisement the same as solicitation */
1799 sport = 0;
1800 srcIP = &fixed_addr; /* Matching src address to solicit dest address */
1801 }
1802 else /* otherwise, every ICMP type gets different key */
1803 {
1804 sport = srcPort;
1805 dport = 0;
1806 if (srcPort == ICMP_ROUTER_SOLICIT)
1807 dstIP = &fixed_addr; /* To get unique key, don't use multicast/broadcast addr (RFC 1256) */
1808 }
1809 break;
1810 case IPPROTO_ICMPV6:
1811 if (srcPort == ICMP6_REPLY)
1812 {
1813 dport = ICMP6_ECHO; /* Treat ICMPv6 echo reply the same as request */
1814 sport = 0;
1815 }
1816 else if (srcPort == ICMP6_ADVERTISEMENT)
1817 {
1818 dport = ICMP6_SOLICITATION; /* Treat ICMPv6 router advertisement the same as solicitation */
1819 sport = 0;
1820 srcIP = &fixed_addr; /* Matching src address to solicit dest address */
1821 }
1822 else /* otherwise, every ICMP type gets different key */
1823 {
1824 sport = srcPort;
1825 dport = 0;
1826 if (srcPort == ICMP6_SOLICITATION)
1827 dstIP = &fixed_addr; /* To get unique key, don't use multicast addr (RFC 4861) */
1828 }
1829 break;
1830 default:
1831 sport = dport = 0;
1832 break;
1833 }
1834
1835 src = srcIP;
1836 dst = dstIP;
1837
1838 if (sfip_fast_lt6(src, dst))
1839 {
1840 COPY4(key->ip_l, sfaddr_get_ip6_ptr(src));
1841 key->port_l = sport;
1842 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1843 key->addressSpaceId_l = address_space_id_src;
1844 key->addressSpaceId_h = address_space_id_dst;
1845 #endif
1846 COPY4(key->ip_h, sfaddr_get_ip6_ptr(dst));
1847 key->port_h = dport;
1848 }
1849 else if (sfip_fast_eq6(src, dst))
1850 {
1851 COPY4(key->ip_l, sfaddr_get_ip6_ptr(src));
1852 COPY4(key->ip_h, sfaddr_get_ip6_ptr(dst));
1853 if (sport < dport)
1854 {
1855 key->port_l = sport;
1856 key->port_h = dport;
1857 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1858 key->addressSpaceId_l = address_space_id_src;
1859 key->addressSpaceId_h = address_space_id_dst;
1860 #endif
1861 }
1862 else
1863 {
1864 key->port_l = dport;
1865 key->port_h = sport;
1866 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1867 key->addressSpaceId_l = address_space_id_dst;
1868 key->addressSpaceId_h = address_space_id_src;
1869 #endif
1870 }
1871 }
1872 else
1873 {
1874 COPY4(key->ip_l, sfaddr_get_ip6_ptr(dst));
1875 key->port_l = dport;
1876 COPY4(key->ip_h, sfaddr_get_ip6_ptr(src));
1877 key->port_h = sport;
1878 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1879 key->addressSpaceId_l = address_space_id_dst;
1880 key->addressSpaceId_h = address_space_id_src;
1881 #endif
1882 }
1883 # ifdef MPLS
1884 if (ScMplsOverlappingIp())
1885 {
1886 key->mplsLabel = mplsId;
1887 }
1888 else
1889 {
1890 key->mplsLabel = 0;
1891 }
1892 # else
1893 key->mplsLabel = 0;
1894 # endif
1895
1896 key->protocol = proto;
1897
1898 if (!ScVlanAgnostic())
1899 key->vlan_tag = vlan;
1900 else
1901 key->vlan_tag = 0;
1902
1903 key->pad = 0;
1904 #if !defined(DAQ_CAPA_VRF) || defined(SFLINUX)
1905 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1906 if (!ScAddressSpaceAgnostic())
1907 key->addressSpaceId = addressSpaceId;
1908 else
1909 key->addressSpaceId = 0;
1910 #else
1911 key->addressSpaceId = 0;
1912 #endif
1913 key->addressSpaceIdPad1 = 0;
1914 #endif
1915 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
1916 key->carrierId = carrierId;
1917 #endif
1918 return 1;
1919 }
1920
1921 static int getSessionKey(Packet *p, SessionKey *key)
1922 {
1923 char proto = GET_IPH_PROTO(p);
1924 uint32_t mplsId = 0;
1925 uint16_t vlanId = 0;
1926 uint16_t sport = p->sp;
1927 # ifdef MPLS
1928 if (ScMplsOverlappingIp() && (p->mpls != NULL))
1929 {
1930 mplsId = p->mplsHdr.label;
1931 }
1932 #endif
1933
1934 if (p->vh && !ScVlanAgnostic())
1935 vlanId = (uint16_t)VTH_VLAN(p->vh);
1936 if ((proto == IPPROTO_ICMP) || (proto == IPPROTO_ICMPV6))
1937 {
1938 /* ICMP */
1939 sport = p->icmph->type;
1940 }
1941 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
1942 uint32_t cid = p->pkth->carrier_id;
1943
1944 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1945 uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
1946 uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
1947
1948 return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1949 proto, vlanId, mplsId, sAsId, dAsId, cid, key);
1950 #else
1951 uint16_t addressSpaceId = 0;
1952 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1953 addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
1954 #endif
1955 return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1956 proto, vlanId, mplsId, addressSpaceId, cid, key);
1957 #endif
1958 #else /* No CarrierId support */
1959 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
1960 uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
1961 uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
1962
1963 return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1964 proto, vlanId, mplsId, sAsId, dAsId, key);
1965 #else
1966 uint16_t addressSpaceId = 0;
1967 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
1968 addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
1969 #endif
1970 return initSessionKeyFromPktHeader(GET_SRC_IP(p), sport, GET_DST_IP(p), p->dp,
1971 proto, vlanId, mplsId, addressSpaceId, key);
1972 #endif
1973 #endif
1974 }
1975
1976 static inline void determinePacketDirection( Packet *p, uint16_t p_port, uint16_t scb_port, int is_sport )
1977 {
1978 if ( is_sport )
1979 p->packet_flags |= ( p_port == scb_port ) ? PKT_FROM_CLIENT : PKT_FROM_SERVER;
1980 else
1981 p->packet_flags |= ( p_port == scb_port ) ? PKT_FROM_SERVER : PKT_FROM_CLIENT;
1982 }
1983
1984 static void setPacketDirectionFlag(Packet *p, void *session)
1985 {
1986 SessionControlBlock *scb = ( SessionControlBlock *) session;
1987
1988 if(IS_IP4(p))
1989 {
1990 if (sfip_fast_eq4(&p->ip4h->ip_addrs->ip_src, &scb->client_ip))
1991 {
1992 if (GET_IPH_PROTO(p) == IPPROTO_TCP)
1993 determinePacketDirection(p, p->tcph->th_sport, scb->client_port, true);
1994 else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
1995 determinePacketDirection(p, p->udph->uh_sport, scb->client_port, true);
1996 else
1997 p->packet_flags |= PKT_FROM_CLIENT;
1998 }
1999 else if (sfip_fast_eq4(&p->ip4h->ip_addrs->ip_dst, &scb->client_ip))
2000 {
2001 if (GET_IPH_PROTO(p) == IPPROTO_TCP)
2002 determinePacketDirection(p, p->tcph->th_dport, scb->client_port, false);
2003 else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
2004 determinePacketDirection(p, p->udph->uh_dport, scb->client_port, false);
2005 else
2006 p->packet_flags |= PKT_FROM_SERVER;
2007 }
2008 }
2009 else /* IS_IP6(p) */
2010 {
2011 if (sfip_fast_eq6(&p->ip6h->ip_addrs->ip_src, &scb->client_ip))
2012 {
2013 if (GET_IPH_PROTO(p) == IPPROTO_TCP)
2014 determinePacketDirection(p, p->tcph->th_sport, scb->client_port, true);
2015 else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
2016 determinePacketDirection(p, p->udph->uh_sport, scb->client_port, true);
2017 else
2018 p->packet_flags |= PKT_FROM_CLIENT;
2019 }
2020 else if (sfip_fast_eq6(&p->ip6h->ip_addrs->ip_dst, &scb->client_ip))
2021 {
2022 if (GET_IPH_PROTO(p) == IPPROTO_TCP)
2023 determinePacketDirection(p, p->tcph->th_dport, scb->client_port, false);
2024 else if (GET_IPH_PROTO(p) == IPPROTO_UDP)
2025 determinePacketDirection(p, p->udph->uh_dport, scb->client_port, false);
2026 else
2027 p->packet_flags |= PKT_FROM_SERVER;
2028 }
2029 }
2030 }
2031
2032 static void *getSessionControlBlock( SessionCache* sessionCache, Packet *p, SessionKey *key )
2033 {
2034 SessionControlBlock *scb = NULL;
2035 scb = ( SessionControlBlock *) checkSessionControlBlock ( sessionCache, p, key );
2036 updateSessionControlBlockTime ( scb, p );
2037 return scb;
2038 }
2039
2040 static void *checkSessionControlBlock( void *sessionCache, Packet *p, SessionKey *key )
2041 {
2042 // Retrieve the SCB without updating the last_data_seen time on the SCB
2043 SessionControlBlock *scb = NULL;
2044
2045 if( getSessionKey( p, key ) )
2046 {
2047 scb = getSessionControlBlockFromKey( sessionCache, key );
2048 }
2049 return scb;
2050 }
2051
2052 static void updateSessionControlBlockTime(SessionControlBlock *scb, Packet *p)
2053 {
2054 if( scb != NULL )
2055 {
2056 if( scb->last_data_seen < p->pkth->ts.tv_sec )
2057 scb->last_data_seen = p->pkth->ts.tv_sec;
2058 }
2059 }
2060
2061 static void populateSessionKey( Packet *p, SessionKey *key )
2062 {
2063
2064 if (!key || !p)
2065 return;
2066
2067 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2068 uint32_t cid = p->pkth->carrier_id;
2069
2070 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
2071 uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
2072 uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
2073
2074 initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2075 GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2076 p->mplsHdr.label, sAsId, dAsId, cid, key);
2077 #else
2078 uint16_t addressSpaceId = 0;
2079 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2080 addressSpaceId = DAQ_GetAddressSpaceID( p->pkth );
2081 #endif
2082
2083 initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2084 GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2085 p->mplsHdr.label, addressSpaceId, cid, key);
2086 #endif
2087 #else /* No Carrierid support */
2088 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
2089 uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
2090 uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
2091
2092 initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2093 GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2094 p->mplsHdr.label, sAsId, dAsId, key);
2095 #else
2096 uint16_t addressSpaceId = 0;
2097 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2098 addressSpaceId = DAQ_GetAddressSpaceID( p->pkth );
2099 #endif
2100
2101 initSessionKeyFromPktHeader( GET_SRC_IP( p ), p->sp, GET_DST_IP( p ), p->dp,
2102 GET_IPH_PROTO( p ), p->vh ? VTH_VLAN( p->vh ) : 0,
2103 p->mplsHdr.label, addressSpaceId, key);
2104 #endif
2105 #endif
2106 }
2107
2108 static void *getSessionControlBlockFromKey( SessionCache* session_cache, const SessionKey *key )
2109 {
2110 SessionControlBlock *scb = NULL;
2111 SFXHASH_NODE *hnode;
2112
2113 if( !session_cache )
2114 return NULL;
2115
2116 hnode = sfxhash_find_node( session_cache->hashTable, key );
2117
2118 if( hnode && hnode->data )
2119 {
2120 /* This is a unique hnode, since the sfxhash finds the
2121 * same key before returning this node.
2122 */
2123 scb = ( SessionControlBlock * ) hnode->data;
2124 }
2125
2126 return scb;
2127 }
2128
2129 static void freeSessionApplicationData(void *session)
2130 {
2131 SessionControlBlock *scb = ( SessionControlBlock *) session;
2132
2133 StreamAppData *tmpData, *appData = scb->appDataList;
2134 while( appData )
2135 {
2136 if( appData->freeFunc && appData->dataPointer )
2137 appData->freeFunc( appData->dataPointer );
2138
2139 tmpData = appData->next;
2140 free(appData);
2141 appData = tmpData;
2142 scb->appDataList = appData;
2143 }
2144 }
2145
2146 static int removeSession(SessionCache *session_cache, SessionControlBlock *scb )
2147 {
2148 SFXHASH_NODE *hnode;
2149
2150 decrementPolicySessionRefCount( scb );
2151
2152 mempool_free(&sessionFlowMempool, scb->flowdata);
2153 scb->flowdata = NULL;
2154
2155 hnode = sfxhash_find_node(session_cache->hashTable, scb->key);
2156 if (!hnode)
2157 return SFXHASH_ERR;
2158 if (session_cache->nextTimeoutEvalNode == hnode)
2159 session_cache->nextTimeoutEvalNode = NULL;
2160
2161 return sfxhash_free_node(session_cache->hashTable, hnode);
2162 }
2163
2164 static int deleteSessionByKey(void *session, char *delete_reason)
2165 {
2166 SessionCache *session_cache;
2167 SessionControlBlock *scb = ( SessionControlBlock *) session;
2168
2169 assert( ( NULL != scb ) && ( NULL != scb->key ) );
2170
2171 switch(scb->key->protocol)
2172 {
2173 case IPPROTO_TCP:
2174 session_cache = proto_session_caches[SESSION_PROTO_TCP];
2175 break;
2176 case IPPROTO_UDP:
2177 session_cache = proto_session_caches[SESSION_PROTO_UDP];
2178 break;
2179 case IPPROTO_ICMP:
2180 session_cache = proto_session_caches[SESSION_PROTO_ICMP];
2181 if (session_cache) break;
2182 default:
2183 session_cache = proto_session_caches[SESSION_PROTO_IP];
2184 break;
2185 }
2186
2187 return deleteSession(session_cache, session, delete_reason, false);
2188 }
2189
2190 static int deleteSession(SessionCache* session_cache, void *session, char *delete_reason, bool close_sync)
2191 {
2192 sfaddr_t client_ip;
2193 sfaddr_t server_ip;
2194 uint16_t client_port;
2195 uint16_t server_port;
2196 uint16_t lw_session_state;
2197 uint16_t lw_session_flags;
2198 int16_t app_proto_id;
2199 uint32_t prune_log_max;
2200 uint32_t old_mem_in_use;
2201 int ret;
2202 bool saved_pkt_trace = false;
2203
2204 SessionControlBlock *scb = ( SessionControlBlock *) session;
2205
2206 assert( ( NULL != session_cache ) && ( NULL != scb ) );
2207
2208 if(!close_sync && pkt_trace_enabled)
2209 {
2210 SavePktTrace();
2211 saved_pkt_trace = true;
2212 }
2213
2214 if(!close_sync)
2215 pkt_trace_enabled = pktTracerDebugCheckSsn((void *)scb);
2216
2217 if (pkt_trace_enabled)
2218 addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
2219 "Session: deleting snort session, reason: %s\n",delete_reason ?delete_reason:"unknown"));
2220
2221 /* Save the current mem in use before pruning */
2222 old_mem_in_use = session_mem_in_use;
2223
2224 /* And save some info on that session */
2225 client_port = ntohs(scb->client_port);
2226 server_port = ntohs(scb->server_port);
2227 lw_session_state = scb->session_state;
2228 lw_session_flags = scb->ha_state.session_flags;
2229 #ifdef TARGET_BASED
2230 app_proto_id = scb->ha_state.application_protocol;
2231 #endif
2232
2233 sfip_set_ip(&client_ip, &scb->client_ip);
2234 sfip_set_ip(&server_ip, &scb->server_ip);
2235
2236 #ifdef MPLS
2237 if( scb->clientMplsHeader != NULL && scb->serverMplsHeader != NULL )
2238 freeMplsHeaders(scb);
2239 #endif
2240
2241 #ifdef ENABLE_HA
2242 if ( !(session_cache->flags & SESSION_CACHE_FLAG_PURGING) )
2243 SessionHANotifyDeletion(scb);
2244 #endif
2245
2246 /*
2247 * Call callback to cleanup the protocol (TCP/UDP/ICMP)
2248 * specific session details
2249 */
2250 if ( session_cache->cleanup_fcn )
2251 session_cache->cleanup_fcn(scb);
2252
2253 freeSessionApplicationData(scb);
2254
2255 /* Need to save this off since the global config might be from an
2256 * older session - because of a reload - and that config might
2257 * get freed after removing the session */
2258 prune_log_max = GetSessionPruneLogMax( );
2259
2260 // if sessions is in the one-way list then remove it...
2261 if( scb->in_oneway_list )
2262 removeFromOneWaySessionList( session_cache, scb );
2263
2264 ret = removeSession(session_cache, scb);
2265
2266 /* If we're pruning and we clobbered some large amount, log a
2267 * message about that session. */
2268 if ( prune_log_max
2269 && ((old_mem_in_use - session_mem_in_use ) > prune_log_max) )
2270 {
2271 char *client_ip_str, *server_ip_str;
2272 client_ip_str = SnortStrdup(inet_ntoa(&client_ip));
2273 server_ip_str = SnortStrdup(inet_ntoa(&server_ip));
2274 LogMessage("S5: Pruned session from cache that was "
2275 "using %d bytes (%s). %s %d --> %s %d "
2276 #ifdef TARGET_BASED
2277 "(%d) "
2278 #endif
2279 ": LWstate 0x%x LWFlags 0x%x\n",
2280 old_mem_in_use - session_mem_in_use,
2281 delete_reason?delete_reason:"Unknown",
2282 client_ip_str, client_port,
2283 server_ip_str, server_port,
2284 #ifdef TARGET_BASED
2285 app_proto_id,
2286 #endif
2287 lw_session_state, lw_session_flags);
2288 free(client_ip_str);
2289 free(server_ip_str);
2290 }
2291
2292 if (pkt_trace_enabled)
2293 addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
2294 "Session: deleted snort session using %d bytes; "
2295 #ifdef TARGET_BASED
2296 "protocol id:(%d) "
2297 #endif
2298 ": LWstate 0x%x LWFlags 0x%x\n",
2299 old_mem_in_use - session_mem_in_use,
2300 #ifdef TARGET_BASED
2301 app_proto_id,
2302 #endif
2303 lw_session_state, lw_session_flags));
2304
2305 if(saved_pkt_trace)
2306 {
2307 pkt_trace_enabled = true;
2308 RestorePktTrace();
2309 }
2310 else if(!close_sync)
2311 pkt_trace_enabled = false;
2312
2313 return ret;
2314 }
2315
2316 static int purgeSessionCache(SessionCache* session_cache)
2317 {
2318 int retCount = 0;
2319 SessionControlBlock *idx;
2320 SFXHASH_NODE *hnode;
2321
2322 if (!session_cache)
2323 return 0;
2324
2325 session_cache->flags |= SESSION_CACHE_FLAG_PURGING;
2326
2327 /* Remove all sessions from the hash table. */
2328 hnode = sfxhash_mru_node(session_cache->hashTable);
2329 while (hnode)
2330 {
2331 idx = (SessionControlBlock *)hnode->data;
2332 if (!idx)
2333 {
2334 sfxhash_free_node(session_cache->hashTable, hnode);
2335 }
2336 else
2337 {
2338 idx->ha_state.session_flags |= SSNFLAG_PRUNED;
2339 deleteSession(session_cache, idx, "purge whole cache", false);
2340 }
2341 hnode = sfxhash_mru_node(session_cache->hashTable);
2342 retCount++;
2343 }
2344
2345 session_cache->flags &= ~SESSION_CACHE_FLAG_PURGING;
2346
2347 return retCount;
2348 }
2349
2350 static int deleteSessionCache( uint32_t protocol )
2351 {
2352 int retCount = 0;
2353 SessionCache *session_cache = NULL;
2354
2355 if( protocol < SESSION_PROTO_MAX )
2356 session_cache = proto_session_caches[ protocol ];
2357
2358 if( session_cache )
2359 {
2360 retCount = purgeSessionCache(session_cache);
2361
2362 // release memory allocated for protocol specific session data
2363 mempool_destroy( session_cache->protocol_session_pool );
2364 free( session_cache->protocol_session_pool );
2365
2366 sfxhash_delete( session_cache->hashTable );
2367 free( session_cache );
2368 proto_session_caches[ protocol ] = NULL;
2369 }
2370
2371 return retCount;
2372 }
2373
2374 static inline bool isSessionBlocked (SessionControlBlock* session)
2375 {
2376 SessionControlBlock *scb = ( SessionControlBlock *) session;
2377
2378 return ( scb->ha_state.session_flags & ( SSNFLAG_DROP_CLIENT | SSNFLAG_DROP_SERVER ) ) != 0;
2379 }
2380
2381 static int pruneOneWaySessions( SessionCache *session_cache )
2382 {
2383 unsigned num_pruned = 0;
2384
2385 while( session_cache->ows_list.num_sessions > session_cache->ows_list.prune_threshold )
2386 {
2387 SessionControlBlock *scb = session_cache->ows_list.head;
2388 if( scb != NULL )
2389 {
2390 removeFromOneWaySessionList( session_cache, scb );
2391 deleteSession(session_cache, scb, "oneway", false);
2392 if( ++num_pruned > session_cache->ows_list.prune_max )
2393 break;
2394 }
2395 else
2396 {
2397 WarningMessage("%s(%d) One Way Session Count Non-zero but list head is NULL\n",
2398 file_name, file_line );
2399 break;
2400 }
2401 }
2402
2403 session_cache->prunes += num_pruned;
2404 return num_pruned;
2405 }
2406
2407 static bool prune_more_sessions( SessionCache *session_cache, uint32_t num_pruned,
2408 uint32_t prune_stop_threshold, int memCheck )
2409 {
2410 unsigned int session_count = sfxhash_count(session_cache->hashTable);
2411
2412 if( session_count < 1 )
2413 return false;
2414
2415 if( !memCheck )
2416 return ( ( session_count > prune_stop_threshold ) || ( num_pruned == 0 ) );
2417 else
2418 return session_mem_in_use > GetSessionMemCap();
2419 }
2420
2421 static void moveHashNodeToFront( SessionCache *session_cache )
2422 {
2423 SFXHASH_NODE *lastNode;
2424
2425 lastNode = sfxhash_lru_node(session_cache->hashTable);
2426 if(lastNode)
2427 sfxhash_gmovetofront(session_cache->hashTable, lastNode);
2428 }
2429 static ThrottleInfo error_throttleInfo = {0,60,0};
2430
2431 static int pruneSessionCache( SessionCache* session_cache, uint32_t thetime, void *save_me_session, int memCheck )
2432 {
2433 SessionControlBlock *save_me = ( SessionControlBlock * ) save_me_session;
2434 SessionControlBlock *scb;
2435 uint32_t pruned = 0;
2436
2437 Active_Suspend();
2438
2439 if( thetime != 0 )
2440 {
2441 /* Pruning, look for sessions that have time'd out */
2442 bool got_one;
2443 scb = ( SessionControlBlock * ) sfxhash_lru( session_cache->hashTable );
2444
2445 if( scb == NULL )
2446 {
2447 Active_Resume();
2448 return 0;
2449 }
2450
2451 do
2452 {
2453 got_one = false;
2454 if( scb == save_me )
2455 {
2456 SFXHASH_NODE *lastNode = sfxhash_lru_node( session_cache->hashTable );
2457 sfxhash_gmovetofront( session_cache->hashTable, lastNode );
2458 lastNode = sfxhash_lru_node( session_cache->hashTable );
2459 if( ( lastNode ) && ( lastNode->data != scb ) )
2460 {
2461 scb = ( SessionControlBlock * ) lastNode->data;
2462 got_one = true;
2463 continue;
2464 }
2465 else
2466 {
2467 session_cache->prunes += pruned;
2468 Active_Resume();
2469 return pruned;
2470 }
2471 }
2472
2473 if((scb->last_data_seen + session_cache->timeoutAggressive) < thetime)
2474 {
2475 SessionControlBlock *savscb = scb;
2476
2477 if(sfxhash_count(session_cache->hashTable) > 1)
2478 {
2479 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning stale session\n"););
2480 savscb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
2481 deleteSession(session_cache, savscb, "stale/timeout", false);
2482
2483 scb = (SessionControlBlock *) sfxhash_lru(session_cache->hashTable);
2484 pruned++;
2485 got_one = true;
2486 }
2487 else
2488 {
2489 savscb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
2490 deleteSession(session_cache, savscb, "stale/timeout/last scb", false);
2491 pruned++;
2492 session_cache->prunes += pruned;
2493 Active_Resume();
2494 return pruned;
2495 }
2496 }
2497 else
2498 {
2499 session_cache->prunes += pruned;
2500 Active_Resume();
2501 return pruned;
2502 }
2503
2504 if (pruned > session_cache->cleanup_sessions)
2505 {
2506 /* Don't bother cleaning more than 'n' at a time */
2507 break;
2508 }
2509 } while( ( scb != NULL ) && got_one );
2510
2511 session_cache->prunes += pruned;
2512 Active_Resume();
2513 return pruned;
2514 }
2515 else
2516 {
2517 /* Free up to 'n' sessions at a time until we get under the memcap or free
2518 * enough sessions to be able to create new ones.
2519 */
2520 uint32_t prune_stop_threshold = session_cache->max_sessions - session_cache->cleanup_sessions;
2521 while( prune_more_sessions( session_cache, pruned, prune_stop_threshold, memCheck ) )
2522 {
2523 unsigned int blocks = 0;
2524 DEBUG_WRAP( DebugMessage(DEBUG_STREAM,
2525 "S5: Pruning session cache by %d scbs for %s: %d/%d\n",
2526 session_cache->cleanup_sessions,
2527 memCheck ? "memcap" : "hash limit",
2528 session_mem_in_use,
2529 GetSessionMemCap() ););
2530
2531 scb = (SessionControlBlock *) sfxhash_lru(session_cache->hashTable);
2532
2533 if( scb == NULL )
2534 break;
2535
2536 if( scb == save_me )
2537 {
2538 if(sfxhash_count(session_cache->hashTable) == 1)
2539 break;
2540 moveHashNodeToFront( session_cache );
2541 continue;
2542 }
2543
2544 if( memCheck )
2545 {
2546 if ( isSessionBlocked( scb ) )
2547 {
2548 if( ++blocks >= sfxhash_count( session_cache->hashTable ) )
2549 break;
2550
2551 moveHashNodeToFront( session_cache );
2552 continue;
2553 }
2554 else
2555 {
2556 scb->ha_state.session_flags |= SSNFLAG_PRUNED;
2557 deleteSession( session_cache, scb, "memcap/check", false );
2558 pruned++;
2559 }
2560 }
2561 else
2562 {
2563 scb->ha_state.session_flags |= SSNFLAG_PRUNED;
2564 deleteSession( session_cache, scb, "memcap/stale", false );
2565 pruned++;
2566 }
2567
2568 if ( pruned >= session_cache->cleanup_sessions )
2569 break;
2570 }
2571 }
2572
2573 if( memCheck && pruned )
2574 {
2575 ErrorMessageThrottled(&error_throttleInfo,"S5: Pruned %d sessions from cache for memcap. %d scbs remain. memcap: %d/%d\n",
2576 pruned, sfxhash_count( session_cache->hashTable ),
2577 session_mem_in_use,
2578 GetSessionMemCap() );
2579 DEBUG_WRAP( if( sfxhash_count(session_cache->hashTable) == 1 )
2580 {
2581 DebugMessage(DEBUG_STREAM, "S5: Pruned, one session remains\n");
2582 } );
2583 }
2584 session_cache->prunes += pruned;
2585 Active_Resume();
2586 return pruned;
2587 }
2588
2589 static void freeMplsHeaders(SessionControlBlock *scb)
2590 {
2591 if ( scb->clientMplsHeader->start != NULL )
2592 {
2593 free(scb->clientMplsHeader->start);
2594 scb->clientMplsHeader->start = NULL;
2595 }
2596 free(scb->clientMplsHeader);
2597 scb->clientMplsHeader = NULL;
2598 if (scb->serverMplsHeader->start != NULL )
2599 {
2600 free(scb->serverMplsHeader->start);
2601 scb->serverMplsHeader->start = NULL;
2602 }
2603 free(scb->serverMplsHeader);
2604 scb->serverMplsHeader = NULL;
2605 }
2606
2607 static void initMplsHeaders(SessionControlBlock *scb)
2608 {
2609 scb->clientMplsHeader = (MPLS_Hdr*)SnortAlloc(sizeof(MPLS_Hdr));
2610 scb->serverMplsHeader = (MPLS_Hdr*)SnortAlloc(sizeof(MPLS_Hdr));
2611 }
2612
2613
2614 static void *createSession(SessionCache* session_cache, Packet *p, const SessionKey *key )
2615 {
2616 SessionControlBlock *scb = NULL;
2617 SFXHASH_NODE *hnode;
2618 StreamFlowData *flowdata;
2619 time_t timestamp = p ? p->pkth->ts.tv_sec : packet_time();
2620
2621 if( session_cache == NULL )
2622 return NULL;
2623
2624 hnode = sfxhash_get_node(session_cache->hashTable, key);
2625 if (!hnode)
2626 {
2627 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, clean One Way Sessions.\n"););
2628 if( pruneOneWaySessions( session_cache ) == 0 )
2629 {
2630 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "No One Way Sessions, clean timedout sessions.\n"););
2631 if( pruneSessionCache(session_cache, timestamp, NULL, 0) == 0 )
2632 {
2633 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "No timedout sessions, clean least recently used.\n"););
2634 pruneSessionCache(session_cache, 0, NULL, 0);
2635 }
2636 }
2637
2638 /* Should have some freed nodes now */
2639 hnode = sfxhash_get_node(session_cache->hashTable, key);
2640 #ifdef DEBUG_MSGS
2641 if (!hnode)
2642 LogMessage("%s(%d) Problem, no freed nodes\n", __FILE__, __LINE__);
2643 #endif
2644 }
2645
2646 if (hnode && hnode->data)
2647 {
2648 scb = hnode->data;
2649
2650 /* Zero everything out */
2651 memset(scb, 0, sizeof(SessionControlBlock));
2652
2653 /* Save the session key for future use */
2654 scb->key = hnode->key;
2655 scb->session_state = STREAM_STATE_NONE;
2656 scb->session_established = false;
2657 scb->protocol = key->protocol;
2658 scb->last_data_seen = timestamp;
2659 scb->flowdata = mempool_alloc(&sessionFlowMempool);
2660 if( scb->flowdata )
2661 {
2662 flowdata = scb->flowdata->data;
2663 boInitStaticBITOP(&(flowdata->boFlowbits), getFlowbitSizeInBytes(), flowdata->flowb);
2664 }
2665
2666 scb->stream_config_stale = true;
2667 scb->stream_config = NULL;
2668 scb->proto_policy = NULL;
2669 scb->napPolicyId = SF_POLICY_UNBOUND;
2670 scb->ipsPolicyId = SF_POLICY_UNBOUND;
2671 scb->session_config = session_configuration;
2672
2673 scb->port_guess = true;
2674
2675 #ifdef MPLS
2676 if( p != NULL )
2677 {
2678 uint8_t layerIndex;
2679 for(layerIndex=0; layerIndex < p->next_layer; layerIndex++)
2680 {
2681 if( p->layers[layerIndex].proto == PROTO_MPLS && p->layers[layerIndex].start != NULL )
2682 {
2683 initMplsHeaders(scb);
2684 break;
2685 }
2686 }
2687 }
2688 #endif
2689
2690 #ifdef ENABLE_HA
2691 if (session_configuration->enable_ha)
2692 {
2693 scb->ha_flags |= HA_FLAG_NEW;
2694 /* Calculate the threshold time for the first HA update message. */
2695 packet_gettimeofday(&scb->ha_next_update);
2696 if (session_configuration->ha_config)
2697 {
2698 scb->ha_next_update.tv_usec += session_configuration->ha_config->min_session_lifetime.tv_usec;
2699 if (scb->ha_next_update.tv_usec > 1000000)
2700 {
2701 scb->ha_next_update.tv_usec -= 1000000;
2702 scb->ha_next_update.tv_sec++;
2703 }
2704 scb->ha_next_update.tv_sec += session_configuration->ha_config->min_session_lifetime.tv_sec;
2705 }
2706
2707 memset( &scb->ha_state, '\0', sizeof( StreamHAState ) );
2708 scb->cached_ha_state = scb->ha_state;
2709 scb->new_session = true;
2710 }
2711 #endif
2712
2713 // all sessions are one-way when created so add to oneway session list...
2714 insertIntoOneWaySessionList( session_cache, scb );
2715
2716 if (pkt_trace_enabled)
2717 addPktTraceData(VERDICT_REASON_NO_BLOCK, snprintf(trace_line, MAX_TRACE_LINE,
2718 "Session: new snort session\n"));
2719 }
2720
2721 return scb;
2722 }
2723
2724 static bool isSessionVerified( void *ssn )
2725 {
2726 if ( ssn != NULL )
2727 return ( ( SessionControlBlock * ) ssn )->session_established;
2728 else
2729 return false;
2730 }
2731
2732 static void removeSessionFromProtoOneWayList( uint32_t proto, void *scb )
2733 {
2734 if( proto < SESSION_PROTO_MAX )
2735 {
2736 removeFromOneWaySessionList( proto_session_caches[ proto ], ( SessionControlBlock * ) scb );
2737 }
2738 else
2739 {
2740 WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, proto);
2741 }
2742 }
2743
2744 static void cleanProtocolSessionsPool( uint32_t protocol )
2745 {
2746 if( protocol < SESSION_PROTO_MAX )
2747 {
2748 if( proto_session_caches[protocol] )
2749 mempool_clean( proto_session_caches[protocol]->protocol_session_pool );
2750 }
2751 else
2752 {
2753 WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
2754 }
2755 }
2756
2757 static void freeProtocolSessionsPool( uint32_t protocol, void *scb )
2758 {
2759 if( protocol < SESSION_PROTO_MAX )
2760 {
2761 if( proto_session_caches[protocol] )
2762 mempool_free( proto_session_caches[protocol]->protocol_session_pool,
2763 ( ( SessionControlBlock * ) scb )->proto_specific_data );
2764 }
2765 else
2766 {
2767 WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
2768 }
2769 }
2770
2771 static void *allocateProtocolSession( uint32_t protocol )
2772 {
2773 if( protocol < SESSION_PROTO_MAX )
2774 {
2775 if( proto_session_caches[protocol] )
2776 return mempool_force_alloc( proto_session_caches[protocol]->protocol_session_pool );
2777 }
2778 else
2779 {
2780 WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, protocol);
2781 }
2782
2783 return NULL;
2784 }
2785
2786
2787 static uint32_t HashFunc(SFHASHFCN *p, unsigned char *d, int n)
2788 {
2789 uint32_t a,b,c;
2790 uint32_t offset = 0;
2791 #ifdef MPLS
2792 uint32_t tmp = 0;
2793 #endif
2794 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2795 uint32_t tmp2 = 0;
2796 #endif
2797
2798 a = *(uint32_t*)d; /* IPv6 lo[0] */
2799 b = *(uint32_t*)(d+4); /* IPv6 lo[1] */
2800 c = *(uint32_t*)(d+8); /* IPv6 lo[2] */
2801
2802 mix(a,b,c);
2803
2804 a += *(uint32_t*)(d+12); /* IPv6 lo[3] */
2805 b += *(uint32_t*)(d+16); /* IPv6 hi[0] */
2806 c += *(uint32_t*)(d+20); /* IPv6 hi[1] */
2807
2808 mix(a,b,c);
2809
2810 a += *(uint32_t*)(d+24); /* IPv6 hi[2] */
2811 b += *(uint32_t*)(d+28); /* IPv6 hi[3] */
2812 c += *(uint32_t*)(d+32); /* port lo & port hi */
2813
2814 mix(a,b,c);
2815
2816 offset=36;
2817 a += *(uint32_t*)(d+offset); /* vlan, protocol, & pad */
2818 #ifdef MPLS
2819 tmp = *(uint32_t *)(d+offset+4);
2820 if( tmp )
2821 {
2822 b += tmp; /* mpls label */
2823 }
2824 offset += 8; /* skip past vlan/proto/ipver & mpls label */
2825 #else
2826 offset += 4; /* skip past vlan/proto/ipver */
2827 #endif
2828 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2829 tmp2 = *(uint32_t*)(d+offset); /* after offset that has been moved */
2830 c += tmp2; /* address space id and 16bits of zero'd pad */
2831 #endif
2832 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2833 mix(a,b,c);
2834 a += *(uint32_t*)(d+offset+4);
2835 #endif
2836
2837 final(a,b,c);
2838
2839 return c;
2840 }
2841
2842 static int HashKeyCmp(const void *s1, const void *s2, size_t n)
2843 {
2844 #ifndef SPARCV9 /* ie, everything else, use 64bit comparisons */
2845 uint64_t *a,*b;
2846
2847 a = (uint64_t*)s1;
2848 b = (uint64_t*)s2;
2849 if(*a - *b) return 1; /* Compares IPv4 lo/hi */
2850 /* Compares IPv6 low[0,1] */
2851
2852 a++;
2853 b++;
2854 if(*a - *b) return 1; /* Compares port lo/hi, vlan, protocol, pad */
2855 /* Compares IPv6 low[2,3] */
2856
2857 a++;
2858 b++;
2859 if(*a - *b) return 1; /* Compares IPv6 hi[0,1] */
2860
2861 a++;
2862 b++;
2863 if(*a - *b) return 1; /* Compares IPv6 hi[2,3] */
2864
2865 a++;
2866 b++;
2867 if(*a - *b) return 1; /* Compares port lo/hi, vlan, protocol, pad */
2868
2869 #ifdef MPLS
2870 a++;
2871 b++;
2872 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2873 if (*a - *b) return 1; /* Compares MPLS label, AddressSpace ID and 16bit pad */
2874 #else
2875 {
2876 uint32_t *x, *y;
2877 x = (uint32_t *)a;
2878 y = (uint32_t *)b;
2879 //x++;
2880 //y++;
2881 if (*x - *y) return 1; /* Compares mpls label, no pad */
2882 }
2883 #endif
2884 #else
2885 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2886 a++;
2887 b++;
2888 {
2889 uint16_t *x, *y;
2890 x = (uint16_t *)a;
2891 y = (uint16_t *)b;
2892 //x++;
2893 //y++;
2894 if (*x - *y) return 1; /* Compares addressSpaceID, no pad */
2895 }
2896 #endif
2897 #endif
2898 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2899 a++;
2900 b++;
2901 {
2902 uint32_t *x, *y;
2903 x = (uint32_t *)a;
2904 y = (uint32_t *)b;
2905 if (*x - *y) return 1; /* Compares carrierID */
2906 }
2907 #endif
2908
2909 #else /* SPARCV9 */
2910 uint32_t *a,*b;
2911
2912 a = (uint32_t*)s1;
2913 b = (uint32_t*)s2;
2914 if ((*a - *b) || (*(a+1) - *(b+1))) return 1; /* Compares IPv4 lo/hi */
2915 /* Compares IPv6 low[0,1] */
2916
2917 a+=2;
2918 b+=2;
2919 if ((*a - *b) || (*(a+1) - *(b+1))) return 1; /* Compares port lo/hi, vlan, protocol, pad */
2920 /* Compares IPv6 low[2,3] */
2921
2922 a+=2;
2923 b+=2;
2924 if ((*a - *b) || (*(a+1) - *(b+1))) return 1; /* Compares IPv6 hi[0,1] */
2925
2926 a+=2;
2927 b+=2;
2928 if ((*a - *b) || (*(a+1) - *(b+1))) return 1; /* Compares IPv6 hi[2,3] */
2929
2930 a+=2;
2931 b+=2;
2932 if ((*a - *b) || (*(a+1) - *(b+1))) return 1; /* Compares port lo/hi, vlan, protocol, pad */
2933
2934 #ifdef MPLS
2935 a+=2;
2936 b+=2;
2937 {
2938 uint32_t *x, *y;
2939 x = (uint32_t *)a;
2940 y = (uint32_t *)b;
2941 //x++;
2942 //y++;
2943 if (*x - *y) return 1; /* Compares mpls label */
2944 }
2945 #endif
2946 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
2947 #ifdef MPLS
2948 a++;
2949 b++;
2950 #else
2951 a+=2;
2952 b+=2;
2953 #endif
2954 {
2955 uint16_t *x, *y;
2956 x = (uint16_t *)a;
2957 y = (uint16_t *)b;
2958 //x++;
2959 //y++;
2960 if (*x - *y) return 1; /* Compares addressSpaceID, no pad */
2961 }
2962 #endif
2963 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
2964 a++;
2965 b++;
2966 {
2967 uint32_t *x, *y;
2968 x = (uint32_t *)a;
2969 y = (uint32_t *)b;
2970 if (*x - *y) return 1; /* Compares carrierID */
2971 }
2972 #endif
2973 #endif /* SPARCV9 */
2974
2975 return 0;
2976 }
2977
2978 static SessionCache* initSessionCache(uint32_t session_type, uint32_t protocol_scb_size, SessionCleanup cleanup_fcn)
2979 {
2980 int hashTableSize;
2981 SessionCache *sessionCache = NULL;
2982 uint32_t max_sessions = 0, session_timeout_min = 0, session_timeout_max = 0;
2983 uint32_t cleanup_sessions = 5;
2984
2985 switch ( session_type )
2986 {
2987 case SESSION_PROTO_TCP:
2988 if( session_configuration->track_tcp_sessions == STREAM_TRACK_YES )
2989 {
2990 max_sessions = session_configuration->max_tcp_sessions;
2991 if (session_configuration->memcap > (max_sessions * protocol_scb_size))
2992 session_configuration->memcap = session_configuration->memcap
2993 - (max_sessions * protocol_scb_size);
2994 session_timeout_min = session_configuration->tcp_cache_pruning_timeout;
2995 session_timeout_max = session_configuration->tcp_cache_nominal_timeout;
2996 }
2997 break;
2998
2999 case SESSION_PROTO_UDP:
3000 if( session_configuration->track_udp_sessions == STREAM_TRACK_YES )
3001 {
3002 max_sessions = session_configuration->max_udp_sessions;
3003 session_timeout_min = session_configuration->udp_cache_pruning_timeout;
3004 session_timeout_max = session_configuration->udp_cache_nominal_timeout;
3005 }
3006 break;
3007
3008 case SESSION_PROTO_ICMP:
3009 if( session_configuration->track_icmp_sessions == STREAM_TRACK_YES )
3010 {
3011 max_sessions = session_configuration->max_icmp_sessions;
3012 session_timeout_min = 30;
3013 session_timeout_max = 3 * session_timeout_min;
3014 }
3015 break;
3016
3017 case SESSION_PROTO_IP:
3018 if( session_configuration->track_ip_sessions == STREAM_TRACK_YES )
3019 {
3020 max_sessions = session_configuration->max_ip_sessions;
3021 session_timeout_min = 30;
3022 session_timeout_max = 3 * session_timeout_min;
3023 }
3024 break;
3025
3026 default:
3027 WarningMessage("%s(%d) Invalid session protocol type: %d", file_name, file_line, session_type);
3028 return NULL;
3029 break;
3030 }
3031
3032 // only create a case for session controls for this protocol if tracking is enabled
3033 if( max_sessions > 0 )
3034 {
3035 // set hash table size to max sessions value...adjust up to avoid collisions????
3036 hashTableSize = max_sessions;
3037
3038 sessionCache = SnortAlloc( sizeof( SessionCache ) );
3039 if( sessionCache )
3040 {
3041 sessionCache->timeoutAggressive = session_timeout_min;
3042 sessionCache->timeoutNominal = session_timeout_max;
3043 sessionCache->max_sessions = max_sessions;
3044 if( cleanup_sessions < ( 2 * max_sessions ) )
3045 sessionCache->cleanup_sessions = cleanup_sessions;
3046 else
3047 sessionCache->cleanup_sessions = ( max_sessions / 2 );
3048 if( sessionCache->cleanup_sessions == 0 )
3049 sessionCache->cleanup_sessions = 1;
3050
3051 sessionCache->cleanup_fcn = cleanup_fcn;
3052
3053 // init one way sessions list control block...
3054 sessionCache->ows_list.head = NULL;
3055 sessionCache->ows_list.tail = NULL;
3056 sessionCache->ows_list.num_sessions = 0;
3057 // tune these values for managing pruning of one-way sessions
3058 sessionCache->ows_list.prune_threshold = max_sessions * 0.05;
3059 if( sessionCache->ows_list.prune_threshold == 0 )
3060 sessionCache->ows_list.prune_threshold = 10;
3061 sessionCache->ows_list.prune_max = sessionCache->ows_list.prune_threshold * 0.25;
3062
3063 /* Okay, now create the table */
3064 sessionCache->hashTable = sfxhash_new( hashTableSize, sizeof(SessionKey), sizeof(SessionControlBlock),
3065 //maxSessionMem + tableMem, 0, NULL, NULL, 1);
3066 0, 0, NULL, NULL, 1 );
3067
3068 sfxhash_set_max_nodes( sessionCache->hashTable, max_sessions );
3069 sfxhash_set_keyops( sessionCache->hashTable, HashFunc, HashKeyCmp );
3070
3071 // now alloc and initial memory for protocol specific session blocks
3072 if( protocol_scb_size > 0 )
3073 {
3074 sessionCache->protocol_session_pool = SnortAlloc(sizeof(MemPool));
3075 if( mempool_init( sessionCache->protocol_session_pool, max_sessions, protocol_scb_size ) != 0 )
3076 {
3077 FatalError( "%s(%d) Could not initialize protocol session memory pool.\n",
3078 __FILE__, __LINE__ );
3079 }
3080 }
3081 }
3082 else
3083 {
3084 FatalError( "%s(%d) Unable to create a stream session cache for protocol type: %d.\n",
3085 file_name, file_line, session_type);
3086 }
3087 }
3088 else
3089 {
3090 WarningMessage("%s(%d) Protocol tracking disabled for protocol type: %d\n",
3091 file_name, file_line, session_type);
3092 }
3093
3094 proto_session_caches[ session_type ] = sessionCache;
3095 return sessionCache;
3096 }
3097
3098 static void printSessionCache(SessionCache* sessionCache)
3099 {
3100 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "%lu sessions active\n",
3101 sfxhash_count( sessionCache->hashTable ) ););
3102 }
3103
3104 static void checkCacheFlowTimeout(uint32_t flowCount, time_t cur_time, SessionCache *cache)
3105 {
3106 uint32_t flowRetiredCount = 0, flowExaminedCount = 0;
3107 SessionControlBlock *scb;
3108 SFXHASH_NODE *hnode, *hnode_prev;
3109
3110 if( !cache )
3111 return;
3112
3113 hnode_prev = cache->nextTimeoutEvalNode;
3114 while( flowRetiredCount < flowCount && flowExaminedCount < ( 2 * flowCount ) )
3115 {
3116 if( !( hnode = hnode_prev ) && !( hnode = sfxhash_lru_node( cache->hashTable ) ) )
3117 break;
3118
3119 scb = ( SessionControlBlock * ) hnode->data;
3120 if( ( time_t ) ( scb->last_data_seen + cache->timeoutNominal ) > cur_time )
3121 {
3122 uint64_t time_jiffies;
3123 /* Give extra 1 second delay*/
3124 time_jiffies = ((uint64_t)cur_time - 1) * TCP_HZ;
3125
3126 if( !( ( scb->expire_time != 0 ) && ( cur_time != 0 ) && ( scb->expire_time <= time_jiffies ) ) )
3127 break;
3128 }
3129
3130 hnode_prev = hnode->gprev;
3131 flowExaminedCount++;
3132
3133 #ifdef ENABLE_HA
3134 if( scb->ha_flags & HA_FLAG_STANDBY )
3135 continue;
3136 #endif
3137
3138 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "retiring stale session\n"););
3139 scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
3140 deleteSession(cache, scb, "stale/timeout", false);
3141 flowRetiredCount++;
3142 }
3143
3144 cache->nextTimeoutEvalNode = hnode_prev;
3145 }
3146
3147 /*get next flow from session cache. */
3148 static void checkSessionTimeout(uint32_t flowCount, time_t cur_time)
3149 {
3150 Active_Suspend( );
3151 checkCacheFlowTimeout(flowCount, cur_time, proto_session_caches[SESSION_PROTO_TCP]);
3152 checkCacheFlowTimeout(flowCount, cur_time, proto_session_caches[SESSION_PROTO_UDP]);
3153 checkCacheFlowTimeout(flowCount, cur_time, proto_session_caches[SESSION_PROTO_IP]);
3154 //icmp_lws_cache does not need cleaning
3155 Active_Resume( );
3156 }
3157
3158 static int isProtocolTrackingEnabled( IpProto proto )
3159 {
3160 int tracking_enabled = false;
3161
3162 switch ( proto )
3163 {
3164 case SESSION_PROTO_TCP:
3165 tracking_enabled = session_configuration->track_tcp_sessions;
3166 break;
3167
3168 case SESSION_PROTO_UDP:
3169 tracking_enabled = session_configuration->track_udp_sessions;
3170 break;
3171
3172 case SESSION_PROTO_ICMP:
3173 tracking_enabled = session_configuration->track_icmp_sessions;
3174 break;
3175
3176 case SESSION_PROTO_IP:
3177 tracking_enabled = session_configuration->track_ip_sessions;
3178 break;
3179
3180 default:
3181 WarningMessage("%s(%d) Invalid session protocol id: %d", file_name, file_line, proto);
3182 break;
3183 }
3184
3185 return ( tracking_enabled );
3186 }
3187
3188 static int setApplicationData( void *scbptr, uint32_t protocol, void *data, StreamAppDataFree free_func )
3189 {
3190 SessionControlBlock *scb;
3191 StreamAppData *appData = NULL;
3192 if (scbptr)
3193 {
3194 scb = ( SessionControlBlock * ) scbptr;
3195 appData = scb->appDataList;
3196 while (appData)
3197 {
3198 if (appData->protocol == protocol)
3199 {
3200 /* If changing the pointer to the data, free old one */
3201 if ((appData->freeFunc) && (appData->dataPointer != data))
3202 {
3203 if ( appData->dataPointer )
3204 appData->freeFunc(appData->dataPointer);
3205 }
3206 else
3207 {
3208 /* Same pointer, same protocol. Go away */
3209 break;
3210 }
3211
3212 appData->dataPointer = NULL;
3213 break;
3214 }
3215
3216 appData = appData->next;
3217 }
3218
3219 /* If there isn't one for this protocol, allocate */
3220 if (!appData)
3221 {
3222 appData = SnortAlloc(sizeof(StreamAppData));
3223
3224 /* And add it to the list */
3225 if (scb->appDataList)
3226 {
3227 scb->appDataList->prev = appData;
3228 }
3229 appData->next = scb->appDataList;
3230 scb->appDataList = appData;
3231 }
3232
3233 /* This will reset free_func if it already exists */
3234 appData->protocol = protocol;
3235 appData->freeFunc = free_func;
3236 appData->dataPointer = data;
3237
3238 return 0;
3239 }
3240 return -1;
3241 }
3242
3243 static void *getApplicationData( void *scbptr, uint32_t protocol )
3244 {
3245 SessionControlBlock *scb;
3246 StreamAppData *appData = NULL;
3247 void *data = NULL;
3248 if (scbptr)
3249 {
3250 scb = ( SessionControlBlock* ) scbptr;
3251 appData = scb->appDataList;
3252 while (appData)
3253 {
3254 if (appData->protocol == protocol)
3255 {
3256 data = appData->dataPointer;
3257 break;
3258 }
3259 appData = appData->next;
3260 }
3261 }
3262 return data;
3263 }
3264
3265 static void * getSessionHandle(const SessionKey *key)
3266 {
3267 SessionControlBlock *scb;
3268
3269 switch(key->protocol)
3270 {
3271 case IPPROTO_TCP:
3272 scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_TCP], key);
3273 break;
3274 case IPPROTO_UDP:
3275 scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_UDP], key);
3276 break;
3277 case IPPROTO_ICMP:
3278 scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_ICMP], key);
3279 if (scb) break;
3280 /* fall through */
3281 default:
3282 scb = getSessionControlBlockFromKey(proto_session_caches[SESSION_PROTO_IP], key);
3283 break;
3284 }
3285
3286 return (void *)scb;
3287 }
3288
3289 static void *getSessionHandleFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
3290 sfaddr_t* dstIP, uint16_t dstPort,
3291 char ip_protocol, uint16_t vlan,
3292 uint32_t mplsId,
3293 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3294 uint32_t carrierId,
3295 #endif
3296 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3297 uint16_t address_space_id_src,
3298 uint16_t address_space_id_dst
3299 #else
3300 uint16_t addressSpaceId
3301 #endif
3302 )
3303 {
3304 SessionKey key;
3305
3306 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3307 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3308 initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3309 vlan, mplsId, address_space_id_src,
3310 address_space_id_dst, carrierId, &key);
3311 #else
3312 initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3313 vlan, mplsId, addressSpaceId, carrierId, &key);
3314 #endif
3315 #else /* No carrier id support */
3316 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3317 initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3318 vlan, mplsId, address_space_id_src,
3319 address_space_id_dst, &key);
3320 #else
3321 initSessionKeyFromPktHeader(srcIP, srcPort, dstIP, dstPort, ip_protocol,
3322 vlan, mplsId, addressSpaceId, &key);
3323 #endif
3324 #endif
3325
3326 return (void*)getSessionHandle(&key);
3327 }
3328
3329 static const StreamSessionKey *getKeyFromSession( const void *scbptr )
3330 {
3331 return ( ( SessionControlBlock * ) scbptr)->key;
3332 }
3333
3334 static StreamSessionKey *getSessionKeyFromPacket( Packet *p )
3335 {
3336 SessionKey *key = calloc(1, sizeof(*key));
3337
3338 if (!key)
3339 return NULL;
3340
3341 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3342 uint32_t cid = p->pkth->carrier_id;
3343
3344 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3345 uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
3346 uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
3347
3348 initSessionKeyFromPktHeader(GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp,
3349 GET_IPH_PROTO(p), p->vh ? VTH_VLAN(p->vh) : 0,
3350 p->mplsHdr.label, sAsId, dAsId, cid, key);
3351 #else
3352 uint16_t addressSpaceId = 0;
3353 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
3354 addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
3355 #endif
3356
3357 initSessionKeyFromPktHeader( GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp, GET_IPH_PROTO(p),
3358 p->vh ? VTH_VLAN(p->vh) : 0,
3359 p->mplsHdr.label, addressSpaceId, cid, key);
3360 #endif
3361 #else /* No carrier id support */
3362 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3363 uint16_t sAsId = DAQ_GetSourceAddressSpaceID(p->pkth);
3364 uint16_t dAsId = DAQ_GetDestinationAddressSpaceID(p->pkth);
3365
3366 initSessionKeyFromPktHeader(GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp,
3367 GET_IPH_PROTO(p), p->vh ? VTH_VLAN(p->vh) : 0,
3368 p->mplsHdr.label, sAsId, dAsId, key);
3369 #else
3370 uint16_t addressSpaceId = 0;
3371 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
3372 addressSpaceId = DAQ_GetAddressSpaceID(p->pkth);
3373 #endif
3374
3375 initSessionKeyFromPktHeader( GET_SRC_IP(p), p->sp, GET_DST_IP(p), p->dp, GET_IPH_PROTO(p),
3376 p->vh ? VTH_VLAN(p->vh) : 0,
3377 p->mplsHdr.label, addressSpaceId, key);
3378 #endif
3379 #endif
3380 return key;
3381 }
3382
3383 static void * getApplicationDataFromSessionKey(const StreamSessionKey *key, uint32_t protocol)
3384 {
3385 SessionControlBlock *scb = getSessionHandle(key);
3386 return getApplicationData(scb, protocol);
3387 }
3388
3389 static void *getApplicationDataFromIpPort( sfaddr_t* srcIP, uint16_t srcPort,
3390 sfaddr_t* dstIP, uint16_t dstPort,
3391 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3392 uint16_t address_space_id_src,
3393 uint16_t address_space_id_dst,
3394 #else
3395 uint16_t addressSpaceID,
3396 #endif
3397 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3398 uint32_t carrierId,
3399 #endif
3400 char ip_protocol, uint16_t vlan,
3401 uint32_t mplsId, uint32_t protocol
3402 )
3403 {
3404 SessionControlBlock *scb;
3405
3406 #if !defined(SFLINUX) && defined(DAQ_CAPA_CARRIER_ID)
3407 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3408 scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort,
3409 dstIP, dstPort,
3410 ip_protocol, vlan,
3411 mplsId, carrierId, address_space_id_src,
3412 address_space_id_dst);
3413 #else
3414 scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort, dstIP,
3415 dstPort, ip_protocol, vlan,
3416 mplsId, carrierId, addressSpaceID);
3417 #endif
3418 #else /* No carrier id support */
3419 #if !defined(SFLINUX) && defined(DAQ_CAPA_VRF)
3420 scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort,
3421 dstIP, dstPort,
3422 ip_protocol, vlan,
3423 mplsId, address_space_id_src, address_space_id_dst);
3424 #else
3425 scb = (SessionControlBlock *) getSessionHandleFromIpPort(srcIP, srcPort, dstIP,
3426 dstPort, ip_protocol, vlan,
3427 mplsId, addressSpaceID);
3428 #endif
3429 #endif
3430
3431 return getApplicationData(scb, protocol);
3432 }
3433
3434 static void deleteSessionIfClosed( Packet* p )
3435 {
3436 SessionControlBlock* scb;
3437
3438 if (!p || !p->ssnptr)
3439 return;
3440
3441 scb = ( SessionControlBlock * ) p->ssnptr;
3442 if( !scb->session_established )
3443 return;
3444
3445 if (scb->session_state & STREAM_STATE_CLOSED)
3446 {
3447 if (scb->is_session_deletion_delayed) {
3448 setSessionExpirationTime( p, scb, STREAM_DELAY_TIMEOUT_AFTER_CONNECTION_ENDED);
3449 return;
3450 }
3451 switch (scb->protocol)
3452 {
3453 case IPPROTO_TCP:
3454 deleteSession(proto_session_caches[SESSION_PROTO_TCP], scb, "closed normally", true);
3455 p->ssnptr = NULL;
3456 break;
3457 case IPPROTO_UDP:
3458 deleteSession(proto_session_caches[SESSION_PROTO_UDP], scb, "closed normally", true);
3459 p->ssnptr = NULL;
3460 break;
3461 case IPPROTO_ICMP: /* matching how sessionPacketProcessor() stores ICMP sessions */
3462 if ( SessionTrackingEnabled( session_configuration, SESSION_PROTO_ICMP ) )
3463 {
3464 deleteSession(proto_session_caches[SESSION_PROTO_ICMP], scb, "closed normally", true);
3465 p->ssnptr = NULL;
3466 break;
3467 }
3468 // fall thru, not tracking ICMP, treat as IP packet...
3469 case IPPROTO_IP:
3470 default: /* matching how sessionPacketProcessor() stores default sessions */
3471 deleteSession(proto_session_caches[SESSION_PROTO_IP], scb, "closed normally", true);
3472 p->ssnptr = NULL;
3473 break;
3474 }
3475 }
3476 }
3477
3478 static void setSessionExpirationTime(Packet *p, void *scb, uint32_t timeout)
3479 {
3480 ( ( SessionControlBlock * ) scb)->expire_time = CalcJiffies(p) + (timeout * TCP_HZ);
3481 return;
3482 }
3483
3484 static int getSessionExpirationTime(Packet *p, void *scb)
3485 {
3486 if ( ( ( SessionControlBlock * ) scb)->expire_time == 0 ) return 0;
3487 return ( CalcJiffies(p) > ( ( SessionControlBlock * ) scb)->expire_time );
3488 }
3489
3490 #
3491 static uint32_t setSessionFlags( void *scbptr, uint32_t flags )
3492 {
3493 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3494 if( scb)
3495 {
3496 if( ( scb->ha_state.session_flags & flags ) != flags )
3497 {
3498 #ifdef ENABLE_HA
3499 scb->ha_flags |= HA_FLAG_MODIFIED;
3500 if((scb->ha_state.session_flags & HA_CRITICAL_SESSION_FLAGS) != (flags & HA_CRITICAL_SESSION_FLAGS))
3501 scb->ha_flags |= HA_FLAG_CRITICAL_CHANGE;
3502
3503 if( scb->protocol == IPPROTO_TCP
3504 &&
3505 ( scb->ha_state.session_flags & HA_TCP_MAJOR_SESSION_FLAGS )
3506 != ( flags & HA_TCP_MAJOR_SESSION_FLAGS ) )
3507 scb->ha_flags |= HA_FLAG_MAJOR_CHANGE;
3508
3509 #endif
3510 scb->ha_state.session_flags |= flags;
3511 }
3512 return scb->ha_state.session_flags;
3513 }
3514
3515 return 0;
3516 }
3517
3518 static uint32_t getSessionFlags( void *scbptr )
3519 {
3520 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3521 if( scb )
3522 return scb->ha_state.session_flags;
3523
3524 return 0;
3525 }
3526
3527 static tSfPolicyId getSessionPolicy( void *scbptr, int policy_type )
3528 {
3529 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3530
3531 if( policy_type == SNORT_NAP_POLICY )
3532 return scb->napPolicyId;
3533 else
3534 return scb->ipsPolicyId;
3535 }
3536
3537 void setSessionPolicy( void *scbptr, int policy_type, tSfPolicyId id )
3538 {
3539 SessionControlBlock *scb = (SessionControlBlock *) scbptr;
3540
3541 if ( scb == NULL )
3542 return;
3543
3544 if( policy_type == SNORT_NAP_POLICY )
3545 scb->napPolicyId = id;
3546 else
3547 scb->ipsPolicyId = id;
3548 }
3549
3550 static void setSessionDeletionDelayed( void *scbptr, bool delay_session_deletion_flag)
3551 {
3552 SessionControlBlock *scb = (SessionControlBlock *) scbptr;
3553 if ( scb == NULL )
3554 return;
3555
3556 scb->is_session_deletion_delayed = delay_session_deletion_flag;
3557 }
3558
3559 static bool isSessionDeletionDelayed( void *scbptr )
3560 {
3561 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3562 if( scb == NULL )
3563 return !STREAM_DELAY_SESSION_DELETION;
3564
3565 return scb->is_session_deletion_delayed;
3566 }
3567
3568 static int ignoreChannel( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort,
3569 sfaddr_t* dstIP, uint16_t dstPort, uint8_t protocol, uint32_t preprocId,
3570 char direction, char flags, struct _ExpectNode** packetExpectedNode )
3571 {
3572 return StreamExpectAddChannel( ctrlPkt, srcIP, srcPort, dstIP, dstPort, direction, flags,
3573 protocol, STREAM_EXPECTED_CHANNEL_TIMEOUT, 0, preprocId, NULL, NULL,
3574 packetExpectedNode );
3575 }
3576
3577 static int getIgnoreDirection( void *scbptr )
3578 {
3579 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3580 if( scb == NULL )
3581 return SSN_DIR_NONE;
3582
3583 return scb->ha_state.ignore_direction;
3584 }
3585
3586 static int setIgnoreDirection( void *scbptr, int ignore_direction )
3587 {
3588 SessionControlBlock *scb = (SessionControlBlock *)scbptr;
3589 if( scb == NULL )
3590 return 0;
3591 if( scb->ha_state.ignore_direction != ignore_direction )
3592 {
3593 scb->ha_state.ignore_direction = ignore_direction;
3594 #ifdef ENABLE_HA
3595 ha_track_modify( scb );
3596 #endif
3597 }
3598 return scb->ha_state.ignore_direction;
3599 }
3600
3601 static void disableInspection( void *scbptr, Packet *p )
3602 {
3603 /*
3604 * Don't want to mess up PortScan by "dropping"
3605 * this packet.
3606 *
3607 * Also still want the perfmon to collect the stats.
3608 *
3609 * And don't want to do any detection with rules
3610 */
3611 DisableDetect( p );
3612 otn_tmp = NULL;
3613 }
3614
3615 static void stopInspection( void * scbptr, Packet *p, char dir, int32_t bytes, int response )
3616 {
3617 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3618
3619 if( scb == NULL )
3620 return;
3621
3622 switch( dir )
3623 {
3624 case SSN_DIR_BOTH:
3625 case SSN_DIR_FROM_CLIENT:
3626 case SSN_DIR_FROM_SERVER:
3627 if( scb->ha_state.ignore_direction != dir )
3628 {
3629 scb->ha_state.ignore_direction = dir;
3630 #ifdef ENABLE_HA
3631 ha_track_modify( scb );
3632 #endif
3633 }
3634 break;
3635 }
3636
3637 /* Flush any queued data on the client and/or server */
3638 if( scb->protocol == IPPROTO_TCP )
3639 {
3640 if( scb->ha_state.ignore_direction & SSN_DIR_TO_CLIENT )
3641 if( getSessionPlugins()->flush_client_stream != NULL )
3642 getSessionPlugins()->flush_client_stream( p, scb );
3643
3644 if( scb->ha_state.ignore_direction & SSN_DIR_TO_SERVER )
3645 if( getSessionPlugins()->flush_server_stream != NULL )
3646 getSessionPlugins()->flush_server_stream( p, scb );
3647 }
3648
3649 /* TODO: Handle bytes/response parameters */
3650
3651 disableInspection( scb, p );
3652 }
3653
3654 static void resumeInspection( void *scbptr, char dir )
3655 {
3656 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3657
3658 if( !scb )
3659 return;
3660
3661 switch( dir )
3662 {
3663 case SSN_DIR_BOTH:
3664 case SSN_DIR_FROM_CLIENT:
3665 case SSN_DIR_FROM_SERVER:
3666 if( scb->ha_state.ignore_direction & dir )
3667 {
3668 scb->ha_state.ignore_direction &= ~dir;
3669 #ifdef ENABLE_HA
3670 ha_track_modify( scb );
3671 #endif
3672 }
3673 break;
3674 }
3675
3676 }
3677
3678 static uint32_t getPacketDirection( Packet *p )
3679 {
3680 SessionControlBlock *scb;
3681
3682 if( ( p == NULL ) || ( p->ssnptr == NULL ) )
3683 return 0;
3684
3685 scb = ( SessionControlBlock * ) p->ssnptr;
3686
3687 setPacketDirectionFlag( p, scb );
3688
3689 return ( p->packet_flags & ( PKT_FROM_SERVER | PKT_FROM_CLIENT ) );
3690 }
3691
3692 static void dropTraffic( Packet* p, void *scbptr, char dir )
3693 {
3694 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3695
3696 if( scb == NULL )
3697 return;
3698
3699 if( ( dir & SSN_DIR_FROM_CLIENT ) && !( scb->ha_state.session_flags & SSNFLAG_DROP_CLIENT ) )
3700 {
3701 scb->ha_state.session_flags |= SSNFLAG_DROP_CLIENT;
3702 if ( Active_PacketForceDropped() )
3703 scb->ha_state.session_flags |= SSNFLAG_FORCE_BLOCK;
3704 #ifdef ENABLE_HA
3705 scb->ha_flags |= ( HA_FLAG_MODIFIED | HA_FLAG_CRITICAL_CHANGE );
3706 #endif
3707 }
3708
3709 if( ( dir & SSN_DIR_FROM_SERVER ) && !( scb->ha_state.session_flags & SSNFLAG_DROP_SERVER ) )
3710 {
3711 scb->ha_state.session_flags |= SSNFLAG_DROP_SERVER;
3712 if( Active_PacketForceDropped() )
3713 scb->ha_state.session_flags |= SSNFLAG_FORCE_BLOCK;
3714 #ifdef ENABLE_HA
3715 scb->ha_flags |= ( HA_FLAG_MODIFIED | HA_FLAG_CRITICAL_CHANGE );
3716 #endif
3717 }
3718 }
3719
3720 static StreamFlowData *getFlowData( Packet *p )
3721 {
3722 SessionControlBlock *scb = ( SessionControlBlock * ) p->ssnptr;
3723
3724 if ( ( scb == NULL ) || ( scb->flowdata == NULL ) )
3725 return NULL;
3726
3727 return (StreamFlowData *)scb->flowdata->data;
3728 }
3729
3730 static uint16_t getPreprocessorStatusBit( void )
3731 {
3732 static uint16_t preproc_filter_status_bit = PORT_MONITOR_SESSION;
3733
3734 preproc_filter_status_bit <<= 1;
3735
3736 return preproc_filter_status_bit;
3737 }
3738
3739 static int setAppProtocolIdExpected( const Packet *ctrlPkt, sfaddr_t* srcIP, uint16_t srcPort,
3740 sfaddr_t* dstIP, uint16_t dstPort, uint8_t protocol, int16_t protoId, uint32_t preprocId,
3741 void *protoData, void (*protoDataFreeFn)(void*), struct _ExpectNode** packetExpectedNode)
3742 {
3743 return StreamExpectAddChannel( ctrlPkt, srcIP, srcPort, dstIP, dstPort, SSN_DIR_BOTH, 0, protocol,
3744 STREAM_EXPECTED_CHANNEL_TIMEOUT, protoId, preprocId, protoData, protoDataFreeFn,
3745 packetExpectedNode );
3746 }
3747
3748 #ifdef TARGET_BASED
3749 void setIpProtocol( SessionControlBlock *scb )
3750 {
3751 switch (scb->protocol)
3752 {
3753 case IPPROTO_TCP:
3754 if (scb->ha_state.ipprotocol != protocolReferenceTCP)
3755 {
3756 scb->ha_state.ipprotocol = protocolReferenceTCP;
3757 #ifdef ENABLE_HA
3758 ha_track_modify(scb);
3759 #endif
3760 }
3761 break;
3762 case IPPROTO_UDP:
3763 if (scb->ha_state.ipprotocol != protocolReferenceUDP)
3764 {
3765 scb->ha_state.ipprotocol = protocolReferenceUDP;
3766 #ifdef ENABLE_HA
3767 ha_track_modify(scb);
3768 #endif
3769 }
3770 break;
3771 case IPPROTO_ICMP:
3772 if (scb->ha_state.ipprotocol != protocolReferenceICMP)
3773 {
3774 scb->ha_state.ipprotocol = protocolReferenceICMP;
3775 #ifdef ENABLE_HA
3776 ha_track_modify(scb);
3777 #endif
3778 }
3779 break;
3780 }
3781 }
3782
3783 void setAppProtocolIdFromHostEntry( SessionControlBlock *scb, HostAttributeEntry *host_entry, int direction )
3784 {
3785 int16_t application_protocol;
3786
3787 if ( ( scb == NULL ) || ( host_entry == NULL ) )
3788 return;
3789
3790 /* Cool, its already set! */
3791 if( scb->ha_state.application_protocol != 0 )
3792 return;
3793
3794 if( scb->ha_state.ipprotocol == 0 )
3795 {
3796 setIpProtocol( scb );
3797 }
3798
3799 if( direction == SSN_DIR_FROM_SERVER )
3800 {
3801 application_protocol = getApplicationProtocolId( host_entry, scb->ha_state.ipprotocol,
3802 ntohs( scb->server_port ), SFAT_SERVICE );
3803 }
3804 else
3805 {
3806 application_protocol = getApplicationProtocolId( host_entry, scb->ha_state.ipprotocol,
3807 ntohs( scb->client_port ), SFAT_SERVICE );
3808 }
3809
3810 if( scb->ha_state.application_protocol != application_protocol )
3811 {
3812 scb->ha_state.application_protocol = application_protocol;
3813 #ifdef ENABLE_HA
3814 ha_track_modify( scb );
3815 #endif
3816 // modify enabled preprocs mask to include only those always run and the ones
3817 // registered for this application id
3818 scb->enabled_pps = appHandlerDispatchMask[ application_protocol ]
3819 |
3820 ( scb->enabled_pps & ( PP_CLASS_NETWORK | PP_CLASS_NGFW ) );
3821
3822 }
3823 }
3824
3825 #ifdef TARGET_BASED
3826 #ifdef ACTIVE_RESPONSE
3827 static void initActiveResponse( Packet *p, void *pv )
3828 {
3829 SessionControlBlock *scb = ( SessionControlBlock * ) pv;
3830
3831 if ( scb == NULL )
3832 return;
3833
3834 scb->response_count = 1;
3835
3836 if ( session_configuration->max_active_responses > 1 )
3837 {
3838 #if defined(DAQ_CAPA_CST_TIMEOUT)
3839 if (!Daq_Capa_Timeout)
3840 #endif
3841 setSessionExpirationTime( p, scb, session_configuration->min_response_seconds );
3842 }
3843 }
3844 #endif
3845 #endif
3846
3847 #ifdef TARGET_BASED
3848 static uint8_t getHopLimit( void* pv, char dir, int outer )
3849 {
3850 SessionControlBlock *scb = (SessionControlBlock*)pv;
3851
3852 if ( scb == NULL )
3853 return 255;
3854
3855 if ( SSN_DIR_FROM_CLIENT == dir )
3856 return outer ? scb->outer_client_ttl : scb->inner_client_ttl;
3857
3858 return outer ? scb->outer_server_ttl : scb->inner_server_ttl;
3859 }
3860 #endif
3861
3862
3863 static void registerApplicationHandler( uint32_t preproc_id, int16_t app_id )
3864 {
3865
3866 if( app_id < 0 )
3867 {
3868 WarningMessage( "(%s)(%d) Invalid application id: %d. Application handler registration failed.",
3869 __FILE__, __LINE__, app_id );
3870 return;
3871 }
3872
3873 // set bit for this preproc in the dispatch mask
3874 appHandlerDispatchMask[ app_id ] |= ( UINT64_C(1) << preproc_id );
3875 }
3876
3877 static int16_t getAppProtocolId( void *scbptr )
3878 {
3879 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3880 /* Not caching the source and dest host_entry in the session so we can
3881 * swap the table out after processing this packet if we need
3882 * to. */
3883 HostAttributeEntry *host_entry = NULL;
3884 int16_t protocol = 0;
3885
3886 if( scb == NULL )
3887 return protocol;
3888
3889 if( scb->ha_state.application_protocol == -1 )
3890 return 0;
3891
3892 if( scb->ha_state.application_protocol != 0 )
3893 return scb->ha_state.application_protocol;
3894
3895 if( !IsAdaptiveConfigured( ) )
3896 return scb->ha_state.application_protocol;
3897
3898 if( scb->ha_state.ipprotocol == 0 )
3899 {
3900 setIpProtocol(scb);
3901 }
3902
3903 host_entry = SFAT_LookupHostEntryByIP(IP_ARG(scb->server_ip));
3904 if( host_entry )
3905 {
3906 setAppProtocolIdFromHostEntry(scb, host_entry, SSN_DIR_FROM_SERVER);
3907
3908 if( scb->ha_state.application_protocol != 0 )
3909 {
3910 return scb->ha_state.application_protocol;
3911 }
3912 }
3913
3914 host_entry = SFAT_LookupHostEntryByIP( IP_ARG( scb->client_ip ) );
3915 if( host_entry )
3916 {
3917 setAppProtocolIdFromHostEntry( scb, host_entry, SSN_DIR_FROM_CLIENT );
3918 if( scb->ha_state.application_protocol != 0 )
3919 {
3920 return scb->ha_state.application_protocol;
3921 }
3922 }
3923
3924 scb->ha_state.application_protocol = -1;
3925
3926 return scb->ha_state.application_protocol;
3927 }
3928
3929 static int16_t setAppProtocolId( void *scbptr, int16_t id )
3930 {
3931 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3932 if( scb == NULL )
3933 return 0;
3934
3935 // modify enabled preprocs mask to include only those always run and the ones
3936 // registered for this application id
3937 scb->enabled_pps = appHandlerDispatchMask[ id ] | ( scb->enabled_pps & ( PP_CLASS_NETWORK | PP_CLASS_NGFW ) );
3938
3939 if( !IsAdaptiveConfigured( ) )
3940 return 0;
3941
3942 if( scb->ha_state.application_protocol != id )
3943 {
3944 scb->ha_state.application_protocol = id;
3945 #ifdef ENABLE_HA
3946 ha_track_modify( scb );
3947 #endif
3948 }
3949
3950 if( !scb->ha_state.ipprotocol )
3951 setIpProtocol( scb );
3952
3953 if( !(scb->protocol == IPPROTO_TCP) || !StreamIsSessionDecryptedTcp( scb ) )
3954 SFAT_UpdateApplicationProtocol( IP_ARG( scb->server_ip ), ntohs( scb->server_port ),
3955 scb->ha_state.ipprotocol, id );
3956
3957 if( scb->protocol == IPPROTO_TCP &&
3958 scb->ha_state.application_protocol > 0 )
3959 set_service_based_flush_policy(scb);
3960
3961 return id;
3962 }
3963
3964 static sfaddr_t* getSessionIpAddress( void *scbptr, uint32_t direction )
3965 {
3966 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3967
3968 if( scb != NULL )
3969 {
3970 switch( direction )
3971 {
3972 case SSN_DIR_FROM_SERVER:
3973 return ( sfaddr_t* ) ( &( ( SessionControlBlock * ) scb)->server_ip );
3974
3975 case SSN_DIR_FROM_CLIENT:
3976 return ( sfaddr_t* ) ( &( ( SessionControlBlock * ) scb)->client_ip );
3977
3978 default:
3979 break;
3980 }
3981 }
3982
3983 return NULL;
3984 }
3985
3986 static void getSessionPorts( void *scbptr, uint16_t *client_port, uint16_t *server_port )
3987 {
3988 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
3989
3990 if( scb != NULL )
3991 {
3992 if(client_port)
3993 {
3994 *client_port = ntohs(scb->client_port);
3995 }
3996 if(server_port)
3997 {
3998 *server_port = ntohs(scb->server_port);
3999 }
4000 }
4001
4002 return;
4003 }
4004 #endif
4005
4006 static void getMaxSessions( tSfPolicyId policyId, StreamSessionLimits* limits )
4007 {
4008 if( session_configuration )
4009 {
4010 limits->tcp_session_limit = session_configuration->track_tcp_sessions ?
4011 session_configuration->max_tcp_sessions : 0;
4012
4013 limits->udp_session_limit = session_configuration->track_udp_sessions ?
4014 session_configuration->max_udp_sessions : 0;
4015
4016 limits->icmp_session_limit = session_configuration->track_icmp_sessions ?
4017 session_configuration->max_icmp_sessions : 0;
4018
4019 limits->ip_session_limit = session_configuration->track_ip_sessions ?
4020 session_configuration->max_ip_sessions : 0;
4021 }
4022 else
4023 memset( limits, 0, sizeof( *limits ) );
4024 }
4025
4026 static void disablePreprocForSession( void *scbptr, uint32_t preproc_id )
4027 {
4028 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
4029
4030 if( scb != NULL )
4031 scb->enabled_pps &= ~( UINT64_C(1) << preproc_id );
4032 }
4033
4034
4035 static void enablePreprocForPort( SnortConfig *sc, uint32_t preproc_id, uint32_t proto, uint16_t port )
4036 {
4037 tSfPolicyId policy_id = getParserPolicy( sc );
4038 SnortPolicy *policy = sc->targeted_policies[ policy_id ];
4039
4040 if( policy == NULL )
4041 {
4042 WarningMessage( "Invalid policy id: %d. No snort policy allocated", policy_id );
4043 return;
4044 }
4045
4046 policy->pp_enabled[ port ] |= ( UINT64_C(1) << preproc_id );
4047 }
4048
4049 static void enablePreprocAllPorts( SnortConfig *sc, uint32_t preproc_id, uint32_t proto )
4050 {
4051 tSfPolicyId policy_id = getParserPolicy( sc );
4052 SnortPolicy *policy = sc->targeted_policies[ policy_id ];
4053 uint32_t port;
4054
4055 if( policy == NULL )
4056 {
4057 WarningMessage( "Invalid policy id: %d. No snort policy allocated", policy_id );
4058 return;
4059 }
4060
4061 for( port = 0; port < MAX_PORTS; port++ )
4062 policy->pp_enabled[ port ] |= ( UINT64_C(1) << preproc_id );
4063 }
4064
4065 static void enablePreprocAllPortsAllPolicies( SnortConfig *sc, uint32_t preproc_id, uint32_t proto )
4066 {
4067 uint32_t i;
4068
4069 for( i = 0; i < sc->num_policies_allocated; i++ )
4070 if( ( sc->targeted_policies[ i ] != NULL ) && ( sc->targeted_policies[ i ]->num_preprocs > 0 ) )
4071 {
4072 setParserPolicy( sc, i );
4073 enablePreprocAllPorts( sc, preproc_id, proto );
4074 }
4075 }
4076
4077 static bool isPreprocEnabledForPort( uint32_t preproc_id, uint16_t port )
4078 {
4079 tSfPolicyId policy_id = getNapRuntimePolicy();
4080 SnortPolicy *policy = snort_conf->targeted_policies[ policy_id ];
4081
4082 if( policy->pp_enabled[ port ] & ( UINT64_C(1) << preproc_id ) )
4083 return true;
4084 else
4085 return false;
4086 }
4087
4088 static void registerNapSelector( nap_selector nap_selector_func )
4089 {
4090 struct session_plugins *pfunks = getSessionPlugins( );
4091
4092 if( nap_selector_func != NULL )
4093 pfunks->select_session_nap = nap_selector_func;
4094 }
4095
4096 static void registerGetHttpXffPrecedence(GetHttpXffPrecedenceFunc fn)
4097 {
4098 if (!getHttpXffPrecedenceFunc) getHttpXffPrecedenceFunc = fn;
4099 }
4100
4101 static char** getHttpXffPrecedence(void* ssn, uint32_t flags, int* nFields)
4102 {
4103 if (getHttpXffPrecedenceFunc) return getHttpXffPrecedenceFunc(ssn, flags, nFields);
4104 else return NULL;
4105 }
4106
4107 static void setReputationUpdateCount (void *scbptr, uint8_t count)
4108 {
4109 SessionControlBlock *scb = ( SessionControlBlock * ) scbptr;
4110 if ( scb )
4111 scb->iprep_update_counter = count;
4112 }
4113
4114 #ifdef SNORT_RELOAD
4115 static void reloadSessionConfiguration( struct _SnortConfig *sc, char *args, void **new_config )
4116 {
4117 SessionConfiguration *session_config = ( SessionConfiguration * ) *new_config;
4118
4119 // session config is only in default policy... fatal error if not parsing default
4120 if( getParserPolicy( sc ) != getDefaultPolicy( ) )
4121 {
4122 FatalError("%s(%d) Session configuration included in non-default policy.\n", __FILE__, __LINE__);
4123 }
4124
4125 if ( session_config == NULL )
4126 {
4127 session_config = initSessionConfiguration( );
4128 parseSessionConfiguration( session_config, args );
4129 *new_config = session_config;
4130
4131 session_reload_configuration = session_config;
4132
4133 sc->run_flags |= RUN_FLAG__STATEFUL;
4134 }
4135 else
4136 {
4137 #if 0
4138 // EDM-TBD
4139 FatalError("stream5_global must only be configured once.\n");
4140 #else
4141 WarningMessage("stream5_global must only be configured once. Ignoring this configuration element\n");
4142 *new_config = NULL;
4143 #endif
4144 }
4145 }
4146
4147 void SessionReload(SessionCache* lws_cache, uint32_t max_sessions,
4148 uint32_t aggressiveTimeout, uint32_t nominalTimeout
4149 #ifdef REG_TEST
4150 , const char* name
4151 #endif
4152 )
4153 {
4154 if (lws_cache)
4155 {
4156 #ifdef REG_TEST
4157 if (REG_TEST_FLAG_SESSION_RELOAD & getRegTestFlags())
4158 {
4159 const char* excessCountStr;
4160 excessCountStr = (sfxhash_total_count(lws_cache->hashTable) > max_sessions) ? "" : "no ";
4161 if (lws_cache->protocol_session_pool)
4162 {
4163 const char *excessProtocolCountStr;
4164 excessProtocolCountStr = (mempool_numTotalBuckets(lws_cache->protocol_session_pool) > max_sessions) ? "" : "no ";
4165 printf("Setting %s max sessions to %u with %sexcess sessions and %sexcess protocol entries\n",
4166 name, max_sessions, excessCountStr, excessProtocolCountStr);
4167 }
4168 else
4169 {
4170 printf("Setting %s max sessions to %u with %sexcess sessions\n",
4171 name, max_sessions, excessCountStr);
4172 }
4173 printf("Setting %s aggressive timeout to %u and nominal timeout to %u\n",
4174 name, aggressiveTimeout, nominalTimeout);
4175 }
4176 #endif
4177 #if defined(DAQ_CAPA_CST_TIMEOUT)
4178 if (!Daq_Capa_Timeout)
4179 #endif
4180 {
4181 lws_cache->timeoutNominal = nominalTimeout;
4182 }
4183 lws_cache->timeoutAggressive = aggressiveTimeout;
4184 sfxhash_set_max_nodes(lws_cache->hashTable, max_sessions);
4185 if (lws_cache->protocol_session_pool)
4186 mempool_setNumObjects(lws_cache->protocol_session_pool, max_sessions);
4187 }
4188 }
4189
4190 unsigned SessionProtocolReloadAdjust(SessionCache* lws_cache, uint32_t max_sessions,
4191 unsigned maxWork, uint32_t memcap
4192 #ifdef REG_TEST
4193 , const char* name
4194 #endif
4195 )
4196 {
4197 if (lws_cache)
4198 {
4199 SessionControlBlock *scb;
4200
4201 for (; maxWork && sfxhash_total_count(lws_cache->hashTable) > max_sessions; maxWork--)
4202 {
4203 if (sfxhash_free_anr(lws_cache->hashTable) != SFXHASH_OK)
4204 {
4205 scb = (SessionControlBlock *)sfxhash_lru(lws_cache->hashTable);
4206 if (scb)
4207 {
4208 scb->ha_state.session_flags |= SSNFLAG_PRUNED;
4209 deleteSession(lws_cache, scb, "reload adjust", false);
4210 }
4211 else
4212 break;
4213 }
4214 }
4215
4216 if (!maxWork)
4217 return 0;
4218
4219 if (memcap)
4220 {
4221 while (maxWork && session_mem_in_use > memcap)
4222 {
4223 scb = (SessionControlBlock *)sfxhash_lru(lws_cache->hashTable);
4224 if (scb)
4225 {
4226 if (isSessionBlocked(scb))
4227 moveHashNodeToFront(lws_cache);
4228 else
4229 {
4230 scb->ha_state.session_flags |= SSNFLAG_PRUNED;
4231 deleteSession(lws_cache, scb, "reload adjust", false);
4232 maxWork--;
4233 }
4234 }
4235 else
4236 break;
4237 }
4238
4239 if (!maxWork)
4240 return 0;
4241 }
4242
4243 if (lws_cache->protocol_session_pool)
4244 {
4245 for (; maxWork && mempool_numTotalBuckets(lws_cache->protocol_session_pool) > max_sessions; maxWork--)
4246 {
4247 if (mempool_free_bucket(lws_cache->protocol_session_pool))
4248 break;
4249 }
4250 }
4251 }
4252 return maxWork;
4253 }
4254
4255 static bool SessionReloadAdjust(bool idle, tSfPolicyId raPolicyId, void* userData)
4256 {
4257 unsigned initialMaxWork = idle ? 512 : 5;
4258 unsigned maxWork;
4259
4260 Active_Suspend();
4261 maxWork = SessionTCPReloadAdjust(initialMaxWork);
4262
4263 if (!maxWork)
4264 {
4265 Active_Resume();
4266 return false;
4267 }
4268
4269 maxWork = SessionUDPReloadAdjust(maxWork);
4270
4271 if (!maxWork)
4272 {
4273 Active_Resume();
4274 return false;
4275 }
4276
4277 maxWork = SessionIPReloadAdjust(maxWork);
4278
4279 if (!maxWork)
4280 {
4281 Active_Resume();
4282 return false;
4283 }
4284
4285 maxWork = SessionICMPReloadAdjust(maxWork);
4286
4287 if (!maxWork)
4288 {
4289 Active_Resume();
4290 return false;
4291 }
4292
4293 for (; maxWork && mempool_numTotalBuckets(&sessionFlowMempool) > session_configuration->max_sessions; maxWork--)
4294 {
4295 if (mempool_free_bucket(&sessionFlowMempool))
4296 break;
4297 }
4298
4299 #ifdef REG_TEST
4300 if (REG_TEST_FLAG_SESSION_RELOAD & getRegTestFlags())
4301 {
4302 if (maxWork == initialMaxWork)
4303 {
4304 SessionCache* lws_cache;
4305
4306 if ((lws_cache = proto_session_caches[SESSION_PROTO_TCP]))
4307 {
4308 printf("TCP session count %u, protocol count %u\n",
4309 sfxhash_total_count(lws_cache->hashTable),
4310 mempool_numTotalBuckets(lws_cache->protocol_session_pool));
4311 printf("TCP aggressive timeout %u, nominal timeout %u\n",
4312 lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4313 }
4314 if ((lws_cache = proto_session_caches[SESSION_PROTO_UDP]))
4315 {
4316 printf("UDP session count %u, protocol count %u\n",
4317 sfxhash_total_count(lws_cache->hashTable),
4318 mempool_numTotalBuckets(lws_cache->protocol_session_pool));
4319 printf("UDP aggressive timeout %u, nominal timeout %u\n",
4320 lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4321 }
4322 if ((lws_cache = proto_session_caches[SESSION_PROTO_ICMP]))
4323 {
4324 printf("ICMP session count %u, protocol count %u\n",
4325 sfxhash_total_count(lws_cache->hashTable),
4326 mempool_numTotalBuckets(lws_cache->protocol_session_pool));
4327 printf("ICMP aggressive timeout %u, nominal timeout %u\n",
4328 lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4329 }
4330 if ((lws_cache = proto_session_caches[SESSION_PROTO_IP]))
4331 {
4332 printf("IP session count %u\n",
4333 sfxhash_total_count(lws_cache->hashTable));
4334 printf("IP aggressive timeout %u, nominal timeout %u\n",
4335 lws_cache->timeoutAggressive, lws_cache->timeoutNominal);
4336 }
4337 printf("Flow pool count %u\n", mempool_numTotalBuckets(&sessionFlowMempool));
4338
4339 printf("Memory in use %s the memory cap\n",
4340 (session_mem_in_use > session_configuration->memcap) ?
4341 "greater than" : "less than or equal to");
4342 fflush(stdout);
4343 }
4344 }
4345 #endif
4346 return (maxWork == initialMaxWork) ? true : false;
4347 }
4348
4349 #ifdef ENABLE_HA
4350 static bool verifyConfigOptionUnchanged( uint32_t new, uint32_t old, char *name, SessionConfiguration *config )
4351 {
4352 if( old == new )
4353 return false;
4354
4355 ErrorMessage("Session Reload: Changing \"%s\" requires a restart.\n", name);
4356 return true;
4357 }
4358 #endif
4359
4360 static int verifyReloadedSessionConfiguration( struct _SnortConfig *sc, void *swap_config )
4361 {
4362 static const char* SESSION_RELOAD = "Session";
4363 SessionConfiguration *ssc = ( SessionConfiguration * ) swap_config;
4364 tSfPolicyId tmp_policy_id = getParserPolicy( sc );
4365 bool restart_required = false;
4366
4367 if( ( session_configuration == NULL ) || ( ssc == NULL ) )
4368 {
4369 FatalError("%s(%d) Session config is NULL.\n", __FILE__, __LINE__);
4370 }
4371
4372 if( ( ssc->track_tcp_sessions != session_configuration->track_tcp_sessions ) ||
4373 ( ssc->track_udp_sessions != session_configuration->track_udp_sessions ) ||
4374 ( ssc->track_icmp_sessions != session_configuration->track_icmp_sessions ) ||
4375 ( ssc->track_ip_sessions != session_configuration->track_ip_sessions ) )
4376 {
4377 ErrorMessage("Session Reload: Changing tracking of TCP, UDP ICMP, or IP "
4378 "sessions requires a restart.\n");
4379 return -1;
4380 }
4381
4382 if (ssc->track_tcp_sessions != STREAM_TRACK_YES)
4383 {
4384 ssc->memcap = 0;
4385 ssc->max_tcp_sessions = 0;
4386 }
4387 if (ssc->track_udp_sessions != STREAM_TRACK_YES)
4388 ssc->max_udp_sessions = 0;
4389 if (ssc->track_icmp_sessions != STREAM_TRACK_YES)
4390 ssc->max_icmp_sessions = 0;
4391 if (ssc->track_ip_sessions != STREAM_TRACK_YES)
4392 ssc->max_ip_sessions = 0;
4393
4394 #ifdef ENABLE_HA
4395 restart_required |= verifyConfigOptionUnchanged( ssc->enable_ha,
4396 session_configuration->enable_ha,
4397 "enable_ha", ssc );
4398 #endif
4399
4400 if( restart_required )
4401 {
4402 // options were changed that require a restart, let's get out of here...
4403 ErrorMessage("Session Reload: Verify Failed, Restart Required\n");
4404 return -1;
4405 }
4406
4407 setParserPolicy( sc, getDefaultPolicy() );
4408 enablePreprocAllPorts( sc, PP_SESSION, PROTO_BIT__ALL );
4409 AddFuncToPreprocList(sc, sessionPacketProcessor, PP_SESSION_PRIORITY, PP_SESSION, PROTO_BIT__ALL);
4410 setParserPolicy( sc, tmp_policy_id );
4411
4412 initializeMaxExpectedFlows( session_configuration );
4413
4414 ssc->numSnortPolicies = sc->num_policies_allocated;
4415 ssc->policy_ref_count = calloc( sc->num_policies_allocated, sizeof( uint32_t ) );
4416 if (!ssc->policy_ref_count)
4417 FatalError("%s(%d) policy_ref_count allocation failed.\n", __FILE__, __LINE__);
4418
4419 ssc->max_sessions = ssc->max_tcp_sessions + ssc->max_udp_sessions +
4420 ssc->max_icmp_sessions + ssc->max_ip_sessions;
4421 if (session_configuration->memcap > ssc->memcap ||
4422 session_configuration->max_udp_sessions > ssc->max_udp_sessions ||
4423 session_configuration->max_tcp_sessions > ssc->max_tcp_sessions ||
4424 session_configuration->max_ip_sessions > ssc->max_ip_sessions ||
4425 session_configuration->max_icmp_sessions > ssc->max_icmp_sessions)
4426 {
4427 ReloadAdjustSessionRegister(sc, SESSION_RELOAD, tmp_policy_id,
4428 &SessionReloadAdjust, NULL, NULL);
4429 }
4430 printSessionConfiguration(session_configuration);
4431
4432 return 0;
4433 }
4434
4435 static void *activateSessionConfiguration( struct _SnortConfig *sc, void *data )
4436 {
4437 SessionConfiguration *old_config = NULL;
4438 unsigned int i;
4439
4440 if( data == NULL )
4441 return NULL;
4442
4443 old_config = session_configuration;
4444 session_configuration = ( SessionConfiguration * ) data;
4445
4446 SessionTCPReload(session_configuration->max_tcp_sessions,
4447 session_configuration->tcp_cache_pruning_timeout,
4448 session_configuration->tcp_cache_nominal_timeout);
4449 SessionUDPReload(session_configuration->max_udp_sessions,
4450 session_configuration->udp_cache_pruning_timeout,
4451 session_configuration->udp_cache_nominal_timeout);
4452 SessionICMPReload(session_configuration->max_icmp_sessions,
4453 30, 3 * 30);
4454 SessionIPReload(session_configuration->max_ip_sessions,
4455 30, 3 * 30);
4456 #ifdef REG_TEST
4457 if (REG_TEST_FLAG_SESSION_RELOAD & getRegTestFlags())
4458 {
4459 const char* excessStr;
4460
4461 excessStr = (mempool_numTotalBuckets(&sessionFlowMempool) > session_configuration->max_sessions) ? "" : "no ";
4462 printf("Setting flow pool max sessions to %u with %sexcess entries\n",
4463 session_configuration->max_sessions, excessStr);
4464 excessStr = (session_mem_in_use > session_configuration->memcap) ? "" : "no ";
4465 printf("Setting memcap to %u with %sexcess memory\n",
4466 session_configuration->memcap, excessStr);
4467 }
4468 #endif
4469 mempool_setNumObjects(&sessionFlowMempool, session_configuration->max_sessions);
4470 session_reload_configuration = NULL;
4471
4472 #ifdef REG_TEST
4473 fflush(stdout);
4474 #endif
4475
4476 for( i = 0; i < old_config->numSnortPolicies; i++ )
4477 {
4478 if( old_config->policy_ref_count[ i ] > 0 )
4479 {
4480 // some sessions still using config from old policy...
4481 LogMessage("Session Reload: Reference Count Non-zero for old configuration.\n");
4482 return NULL;
4483 }
4484 }
4485
4486 return old_config;
4487 }
4488
4489 static void freeSessionConfiguration( void *data )
4490 {
4491 if( data == NULL )
4492 return;
4493
4494 LogMessage("Session Reload: Freeing Session Configuration Memory.\n");
4495 SessionFreeConfig( ( SessionConfiguration * ) data );
4496 }
4497
4498 #endif
4499