"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