"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/preprocessors/Stream6/snort_stream_udp.c" (16 Oct 2020, 30282 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 "snort_stream_udp.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 /****************************************************************************
    2  *
    3  * Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    4  * Copyright (C) 2004-2013 Sourcefire, Inc.
    5  *
    6  * This program is free software; you can redistribute it and/or modify
    7  * it under the terms of the GNU General Public License Version 2 as
    8  * published by the Free Software Foundation.  You may not use, modify or
    9  * distribute this program under any other version of the GNU General
   10  * Public License.
   11  *
   12  * This program is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  * GNU General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU General Public License
   18  * along with this program; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   20  *
   21  ****************************************************************************/
   22 
   23 #ifdef HAVE_CONFIG_H
   24 #include "config.h"
   25 #endif
   26 
   27 #include "sf_types.h"
   28 #include "snort_debug.h"
   29 #include "detect.h"
   30 #include "plugbase.h"
   31 #include "mstring.h"
   32 #include "sfxhash.h"
   33 #include "util.h"
   34 #include "decode.h"
   35 
   36 #include "spp_session.h"
   37 #include "session_api.h"
   38 #include "snort_session.h"
   39 
   40 #include "stream_common.h"
   41 #include "stream_api.h"
   42 #include "session_expect.h"
   43 #include "snort_stream_udp.h"
   44 
   45 #include "plugin_enum.h"
   46 #include "rules.h"
   47 #include "treenodes.h"
   48 #include "snort.h"
   49 #include "active.h"
   50 
   51 #include "portscan.h" /* To know when to create sessions for all UDP */
   52 
   53 #include "dynamic-plugins/sp_dynamic.h"
   54 
   55 #include "profiler.h"
   56 #include "sfPolicy.h"
   57 #include "stream5_ha.h"
   58 
   59 #include "reg_test.h"
   60 
   61 #ifdef PERF_PROFILING
   62 PreprocStats s5UdpPerfStats;
   63 #endif
   64 
   65 /*  M A C R O S  **************************************************/
   66 /* actions */
   67 #define ACTION_NOTHING                  0x00000000
   68 
   69 /* sender/responder ip/port dereference */
   70 #define udp_sender_ip lwSsn->client_ip
   71 #define udp_sender_port lwSsn->client_port
   72 #define udp_responder_ip lwSsn->server_ip
   73 #define udp_responder_port lwSsn->server_port
   74 
   75 /*  D A T A  S T R U C T U R E S  ***********************************/
   76 typedef struct _UdpSession
   77 {
   78     SessionControlBlock *lwSsn;
   79 
   80     struct timeval ssn_time;
   81 
   82     //uint8_t    c_ttl;
   83     //uint8_t    s_ttl;
   84 
   85 } UdpSession;
   86 
   87 /*  G L O B A L S  **************************************************/
   88 static SessionCache* udp_lws_cache = NULL;
   89 
   90 /*  P R O T O T Y P E S  ********************************************/
   91 static void StreamParseUdpArgs(StreamUdpConfig *, char *, StreamUdpPolicy *);
   92 static void StreamPrintUdpConfig(StreamUdpPolicy *);
   93 static int ProcessUdp(SessionControlBlock *, Packet *, StreamUdpPolicy *, SFXHASH_NODE *);
   94 static int ProcessUdpCreate (Packet *);
   95 
   96 #ifdef ENABLE_HA
   97 
   98 //-------------------------------------------------------------------------
   99 // udp ha stuff
  100 // TBD there may be some refactoring possible once tcp, icmp, and udp
  101 // are complete
  102 
  103 static SessionControlBlock *StreamUDPCreateSession(const SessionKey *key)
  104 {
  105     setNapRuntimePolicy(getDefaultPolicy());
  106 
  107     SessionControlBlock *scb = session_api->create_session(udp_lws_cache, NULL, key );
  108     if (scb)
  109         s5stats.active_udp_sessions++;
  110 
  111     return scb;
  112 }
  113 
  114 static int StreamUDPDeleteSession(const SessionKey *key)
  115 {
  116      SessionControlBlock *scb = session_api->get_session_by_key(udp_lws_cache, key);
  117 
  118     if (scb)
  119     {
  120         if( StreamSetRuntimeConfiguration( scb, scb->protocol ) == 0 )
  121         {
  122             session_api->delete_session( udp_lws_cache, scb, "ha sync", false );
  123             s5stats.active_udp_sessions--;
  124         }
  125         else
  126             WarningMessage(" WARNING: Attempt to delete a UDP Session when no valid runtime configuration.\n" );
  127      }
  128 
  129     return 0;
  130 }
  131 
  132 
  133 static HA_Api ha_udp_api = {
  134     /*.get_lws = */ GetLWUdpSession,
  135 
  136     /*.create_session = */ StreamUDPCreateSession,
  137     /*.deactivate_session = */ NULL,
  138     /*.delete_session = */ StreamUDPDeleteSession,
  139 };
  140 
  141 #endif
  142 
  143 //-------------------------------------------------------------------------
  144 
  145 void StreamInitUdp( void )
  146 {
  147     /* Now UDP */
  148     if (udp_lws_cache == NULL)
  149     {
  150          udp_lws_cache = session_api->init_session_cache( SESSION_PROTO_UDP,
  151                                                           sizeof( UdpSession ),
  152                                                           &UdpSessionCleanup);
  153     }
  154 
  155 #ifdef ENABLE_HA
  156     ha_set_api(IPPROTO_UDP, &ha_udp_api);
  157 #endif
  158 }
  159 
  160 void setUdpDirectionAndPorts( Packet *p, SessionControlBlock *scb )
  161 {
  162     scb->ha_state.direction = FROM_SENDER;
  163     IP_COPY_VALUE(scb->client_ip, GET_SRC_IP(p));
  164     scb->client_port = p->udph->uh_sport;
  165     IP_COPY_VALUE(scb->server_ip, GET_DST_IP(p));
  166     scb->server_port = p->udph->uh_dport;
  167 }
  168 
  169 void StreamUdpPolicyInit(StreamUdpConfig *config, char *args)
  170 {
  171     StreamUdpPolicy *s5UdpPolicy;
  172 
  173     if (config == NULL)
  174         return;
  175 
  176     s5UdpPolicy = (StreamUdpPolicy *)SnortAlloc(sizeof(StreamUdpPolicy));
  177 
  178     StreamParseUdpArgs(config, args, s5UdpPolicy);
  179 
  180     config->num_policies++;
  181 
  182     /* Now add this context to the internal list */
  183     if (config->policy_list == NULL)
  184     {
  185         config->policy_list =
  186             (StreamUdpPolicy **)SnortAlloc(sizeof(StreamUdpPolicy *));
  187     }
  188     else
  189     {
  190         StreamUdpPolicy **tmpPolicyList =
  191             (StreamUdpPolicy **)SnortAlloc(sizeof(StreamUdpPolicy *) * config->num_policies);
  192 
  193         memcpy(tmpPolicyList, config->policy_list,
  194                sizeof(StreamUdpPolicy *) * (config->num_policies - 1));
  195 
  196         free(config->policy_list);
  197 
  198         config->policy_list = tmpPolicyList;
  199     }
  200 
  201     config->policy_list[config->num_policies - 1] = s5UdpPolicy;
  202 
  203     // register callback with Session that determines direction and client/server ports
  204     registerDirectionPortCallback( SESSION_PROTO_UDP, setUdpDirectionAndPorts );
  205 
  206     StreamPrintUdpConfig(s5UdpPolicy);
  207 
  208 #ifdef REG_TEST
  209     LogMessage("    UDP Session Size: %lu\n", (long unsigned int)sizeof(UdpSession));
  210 #endif
  211 }
  212 
  213 static void StreamParseUdpArgs(StreamUdpConfig *config, char *args, StreamUdpPolicy *s5UdpPolicy)
  214 {
  215     char **toks;
  216     int num_toks;
  217     int i;
  218     char *index;
  219     char **stoks = NULL;
  220     int s_toks;
  221     char *endPtr = NULL;
  222 
  223     if (s5UdpPolicy == NULL)
  224         return;
  225 
  226     s5UdpPolicy->session_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
  227     s5UdpPolicy->flags = 0;
  228 
  229     if(args != NULL && strlen(args) != 0)
  230     {
  231         toks = mSplit(args, ",", 6, &num_toks, 0);
  232 
  233         i=0;
  234 
  235         while(i < num_toks)
  236         {
  237             index = toks[i];
  238 
  239             while(isspace((int)*index)) index++;
  240 
  241             stoks = mSplit(index, " ", 3, &s_toks, 0);
  242 
  243             if (s_toks == 0)
  244             {
  245                 FatalError("%s(%d) => Missing parameter in Stream UDP config.\n",
  246                     file_name, file_line);
  247             }
  248 
  249             if(!strcasecmp(stoks[0], "timeout"))
  250             {
  251                 if(stoks[1])
  252                 {
  253                     s5UdpPolicy->session_timeout = strtoul(stoks[1], &endPtr, 10);
  254                 }
  255 
  256                 if (!stoks[1] || (endPtr == &stoks[1][0]) || *endPtr)
  257                 {
  258                     FatalError("%s(%d) => Invalid timeout in config file.  Integer parameter required.\n",
  259                             file_name, file_line);
  260                 }
  261 
  262                 if ((s5UdpPolicy->session_timeout > STREAM_MAX_SSN_TIMEOUT) ||
  263                     (s5UdpPolicy->session_timeout < STREAM_MIN_SSN_TIMEOUT))
  264                 {
  265                     FatalError("%s(%d) => Invalid timeout in config file.  "
  266                         "Must be between %d and %d\n",
  267                         file_name, file_line,
  268                         STREAM_MIN_SSN_TIMEOUT, STREAM_MAX_SSN_TIMEOUT);
  269                 }
  270 
  271                 if (s_toks > 2)
  272                 {
  273                     FatalError("%s(%d) => Invalid Stream UDP Policy option.  Missing comma?\n",
  274                         file_name, file_line);
  275                 }
  276             }
  277             else if (!strcasecmp(stoks[0], "ignore_any_rules"))
  278             {
  279                 s5UdpPolicy->flags |= STREAM_CONFIG_IGNORE_ANY;
  280 
  281                 if (s_toks > 1)
  282                 {
  283                     FatalError("%s(%d) => Invalid Stream UDP Policy option.  Missing comma?\n",
  284                         file_name, file_line);
  285                 }
  286             }
  287             else
  288             {
  289                 FatalError("%s(%d) => Invalid Stream UDP Policy option\n",
  290                             file_name, file_line);
  291             }
  292 
  293             mSplitFree(&stoks, s_toks);
  294             i++;
  295         }
  296 
  297         mSplitFree(&toks, num_toks);
  298     }
  299 
  300     if (s5UdpPolicy->bound_addrs == NULL)
  301     {
  302         if (config->default_policy != NULL)
  303         {
  304             FatalError("%s(%d) => Default Stream UDP Policy already set. "
  305                        "This policy must be bound to a specific host or "
  306                        "network.\n", file_name, file_line);
  307         }
  308 
  309         config->default_policy = s5UdpPolicy;
  310     }
  311     else
  312     {
  313         if (s5UdpPolicy->flags & STREAM_CONFIG_IGNORE_ANY)
  314         {
  315             FatalError("%s(%d) => \"ignore_any_rules\" option can be used only"
  316                        " with Default Stream UDP Policy\n", file_name, file_line);
  317         }
  318     }
  319 }
  320 
  321 static void StreamPrintUdpConfig(StreamUdpPolicy *s5UdpPolicy)
  322 {
  323     LogMessage("Stream UDP Policy config:\n");
  324     LogMessage("    Timeout: %d seconds\n", s5UdpPolicy->session_timeout);
  325     if (s5UdpPolicy->flags)
  326     {
  327         LogMessage("    Options:\n");
  328         if (s5UdpPolicy->flags & STREAM_CONFIG_IGNORE_ANY)
  329         {
  330             LogMessage("        Ignore Any -> Any Rules: YES\n");
  331         }
  332     }
  333     //IpAddrSetPrint("    Bound Addresses:", s5UdpPolicy->bound_addrs);
  334 }
  335 
  336 
  337 int StreamVerifyUdpConfig(struct _SnortConfig *sc, StreamUdpConfig *config, tSfPolicyId policyId)
  338 {
  339     if (config == NULL)
  340         return -1;
  341 
  342     if (!udp_lws_cache)
  343         return -1;
  344 
  345     if (config->num_policies == 0)
  346         return -1;
  347 
  348     /* Post-process UDP rules to establish UDP ports to inspect. */
  349     setPortFilterList(sc, config->port_filter, IPPROTO_UDP,
  350             (config->default_policy->flags & STREAM_CONFIG_IGNORE_ANY), policyId);
  351 
  352     //printf ("UDP Ports with Inspection/Monitoring\n");
  353     //s5PrintPortFilter(config->port_filter);
  354     return 0;
  355 }
  356 
  357 #ifdef STREAM_DEBUG_ENABLED
  358 static void PrintUdpSession(UdpSession *us)
  359 {
  360     LogMessage("UdpSession:\n");
  361     LogMessage("    ssn_time:           %lu\n", us->ssn_time.tv_sec);
  362     LogMessage("    sender IP:          0x%08X\n", us->udp_sender_ip);
  363     LogMessage("    responder IP:          0x%08X\n", us->udp_responder_ip);
  364     LogMessage("    sender port:        %d\n", us->udp_sender_port);
  365     LogMessage("    responder port:        %d\n", us->udp_responder_port);
  366 
  367     LogMessage("    flags:              0x%X\n", us->lwSsn->session_flags);
  368 }
  369 #endif
  370 
  371 SessionControlBlock *GetLWUdpSession( const SessionKey *key )
  372 {
  373     return session_api->get_session_by_key(udp_lws_cache, key);
  374 }
  375 
  376 void UdpSessionCleanup(void *ssn)
  377 {
  378     SessionControlBlock *scb = ( SessionControlBlock * ) ssn;
  379 
  380     UdpSession *udpssn = NULL;
  381 
  382     if (scb->ha_state.session_flags & SSNFLAG_PRUNED)
  383     {
  384         CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED);
  385     }
  386     else if (scb->ha_state.session_flags & SSNFLAG_TIMEDOUT)
  387     {
  388         CloseStreamSession(&sfBase, SESSION_CLOSED_TIMEDOUT);
  389     }
  390     else
  391     {
  392         CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY);
  393     }
  394 
  395     if (scb->proto_specific_data)
  396         udpssn = (UdpSession *)scb->proto_specific_data->data;
  397 
  398     if (!udpssn)
  399     {
  400         /* Huh? */
  401         return;
  402     }
  403 
  404     /* Cleanup the proto specific data */
  405     session_api->free_protocol_session_pool( SESSION_PROTO_UDP, scb );
  406     scb->proto_specific_data = NULL;
  407     scb->session_state = STREAM_STATE_NONE;
  408     scb->ha_state.session_flags = SSNFLAG_NONE;
  409     scb->expire_time = 0;
  410     scb->ha_state.ignore_direction = 0;
  411 
  412     StreamResetFlowBits(scb);
  413     session_api->free_application_data(scb);
  414 
  415     s5stats.udp_sessions_released++;
  416     s5stats.active_udp_sessions--;
  417 
  418     RemoveUDPSession(&sfBase);
  419 }
  420 
  421 uint32_t StreamGetUdpPrunes(void)
  422 {
  423     if( udp_lws_cache)
  424         return session_api->get_session_prune_count( SESSION_PROTO_UDP );
  425     else
  426         return s5stats.udp_prunes;
  427 }
  428 
  429 void StreamResetUdpPrunes(void)
  430 {
  431     session_api->reset_session_prune_count( SESSION_PROTO_UDP );
  432 }
  433 
  434 void StreamResetUdp(void)
  435 {
  436     session_api->purge_session_cache(udp_lws_cache);
  437     session_api->clean_protocol_session_pool( SESSION_PROTO_UDP );
  438 }
  439 
  440 void StreamCleanUdp(void)
  441 {
  442     if ( udp_lws_cache )
  443         s5stats.udp_prunes = session_api->get_session_prune_count( SESSION_PROTO_UDP );
  444 
  445     /* Clean up session cache */
  446     session_api->delete_session_cache( SESSION_PROTO_UDP );
  447     udp_lws_cache = NULL;
  448 
  449 }
  450 
  451 static int NewUdpSession(Packet *p,
  452                          SessionControlBlock *scb,
  453                          StreamUdpPolicy *s5UdpPolicy)
  454 {
  455     UdpSession *tmp;
  456     MemBucket *tmpBucket;
  457     /******************************************************************
  458      * create new sessions
  459      *****************************************************************/
  460     tmpBucket = session_api->alloc_protocol_session( SESSION_PROTO_UDP );
  461     if (tmpBucket == NULL)
  462         return -1;
  463 
  464     tmp = tmpBucket->data;
  465     DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  466                 "Creating new session tracker!\n"););
  467 
  468     tmp->ssn_time.tv_sec = p->pkth->ts.tv_sec;
  469     tmp->ssn_time.tv_usec = p->pkth->ts.tv_usec;
  470     scb->ha_state.session_flags |= SSNFLAG_SEEN_SENDER;
  471 
  472     DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  473                 "adding UdpSession to lightweight session\n"););
  474     scb->proto_specific_data = tmpBucket;
  475     scb->protocol = GET_IPH_PROTO(p);
  476     scb->ha_state.direction = FROM_SENDER;
  477     tmp->lwSsn = scb;
  478 
  479 #ifdef STREAM_DEBUG_ENABLED
  480     PrintUdpSession(tmp);
  481 #endif
  482     session_api->set_expire_timer(p, scb, s5UdpPolicy->session_timeout);
  483 
  484     s5stats.udp_sessions_created++;
  485     s5stats.active_udp_sessions++;
  486 
  487     AddUDPSession(&sfBase);
  488     if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
  489         UpdateFlowIPState(&sfFlow, IP_ARG(scb->client_ip), IP_ARG(scb->server_ip), SFS_STATE_UDP_CREATED);
  490 
  491     return 0;
  492 }
  493 
  494 //-------------------------------------------------------------------------
  495 /*
  496  * Main entry point for UDP
  497  */
  498 int StreamProcessUdp( Packet *p, SessionControlBlock *scb,
  499                       StreamUdpPolicy *s5UdpPolicy, SessionKey *skey)
  500 {
  501     SFXHASH_NODE *hash_node = NULL;
  502     PROFILE_VARS;
  503 
  504 // XXX-IPv6 StreamProcessUDP debugging
  505 
  506     PREPROC_PROFILE_START(s5UdpPerfStats);
  507 
  508     if( s5UdpPolicy == NULL )
  509     {
  510         int policyIndex;
  511         StreamUdpConfig *udp_config = ( ( StreamConfig * ) scb->stream_config )->udp_config;
  512         if( udp_config == NULL )
  513         {
  514             DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
  515                                     "[Stream] Could not find Udp Policy context "
  516                                     "for IP %s\n", inet_ntoa(GET_DST_ADDR(p))););
  517             PREPROC_PROFILE_END( s5UdpPerfStats );
  518             return 0;
  519         }
  520 
  521         /* Find an Udp policy for this packet */
  522         for( policyIndex = 0; policyIndex < udp_config->num_policies; policyIndex++ )
  523         {
  524             s5UdpPolicy = udp_config->policy_list[ policyIndex ];
  525 
  526             if( s5UdpPolicy->bound_addrs == NULL )
  527                 continue;
  528 
  529             /*
  530              * Does this policy handle packets to this IP address?
  531              */
  532             if( sfvar_ip_in( s5UdpPolicy->bound_addrs, GET_DST_IP( p ) ) )
  533             {
  534                 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
  535                                         "[Stream] Found udp policy in IpAddrSet\n"););
  536                 break;
  537             }
  538         }
  539 
  540         if( policyIndex == udp_config->num_policies )
  541             s5UdpPolicy = udp_config->default_policy;
  542 
  543         if( s5UdpPolicy == NULL )
  544         {
  545             DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
  546                                     "[Stream] Could not find Udp Policy context "
  547                                     "for IP %s\n", inet_ntoa(GET_DST_ADDR(p))););
  548             PREPROC_PROFILE_END(s5UdpPerfStats);
  549             return 0;
  550         }
  551    }
  552 
  553     /* UDP Sessions required */
  554     if ( !scb->session_established )
  555     {
  556         int rc;
  557 #if defined(DAQ_CAPA_CST_TIMEOUT)
  558         uint64_t timeout;
  559         if (Daq_Capa_Timeout)
  560         {
  561           GetTimeout(p,&timeout);
  562           s5UdpPolicy->session_timeout = timeout;
  563         }
  564 #endif
  565         scb->proto_policy = s5UdpPolicy;
  566 
  567         rc = isPacketFilterDiscard( p, s5UdpPolicy->flags & STREAM_CONFIG_IGNORE_ANY );
  568         if( ( rc == PORT_MONITOR_PACKET_DISCARD ) && !StreamExpectIsExpected( p, &hash_node ) )
  569         {
  570             //ignore the packet
  571             scb->session_state &= ~STREAM_STATE_PORT_INSPECT;
  572             UpdateFilteredPacketStats(&sfBase, IPPROTO_UDP);
  573             session_api->set_expire_timer(p, scb, s5UdpPolicy->session_timeout);
  574             PREPROC_PROFILE_END(s5UdpPerfStats);
  575             return 0;
  576         }
  577  
  578         scb->session_state |= STREAM_STATE_PORT_INSPECT;
  579         scb->session_established = true;
  580         s5stats.total_udp_sessions++;
  581         s5stats.active_udp_sessions++;
  582     }
  583 
  584     p->ssnptr = scb;
  585 
  586     /*
  587      * Check if the session is expired.
  588      * Should be done before we do something with the packet...
  589      * ie, Insert a packet, or handle state change SYN, FIN, RST, etc.
  590      */
  591     if( ( scb->session_state & STREAM_STATE_TIMEDOUT )
  592           ||
  593           StreamExpire( p, scb ) )
  594     {
  595         scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
  596 
  597         /* Session is timed out */
  598         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  599                     "Stream UDP session timedout!\n"););
  600 
  601 #ifdef ENABLE_HA
  602         /* Notify the HA peer of the session cleanup/reset by way of a deletion notification. */
  603         PREPROC_PROFILE_TMPEND(s5UdpPerfStats);
  604         SessionHANotifyDeletion(scb);
  605         PREPROC_PROFILE_TMPSTART(s5UdpPerfStats);
  606         scb->ha_flags = (HA_FLAG_NEW | HA_FLAG_MODIFIED | HA_FLAG_MAJOR_CHANGE);
  607 #endif
  608 
  609         /* Clean it up */
  610         UdpSessionCleanup(scb);
  611 
  612         ProcessUdp(scb, p, s5UdpPolicy, hash_node);
  613     }
  614     else
  615     {
  616         ProcessUdp(scb, p, s5UdpPolicy, hash_node);
  617         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  618                     "Finished Stream UDP cleanly!\n"
  619                     "---------------------------------------------------\n"););
  620     }
  621     MarkupPacketFlags(p, scb);
  622     session_api->set_expire_timer(p, scb, s5UdpPolicy->session_timeout);
  623     PREPROC_PROFILE_END(s5UdpPerfStats);
  624 
  625     return 0;
  626 }
  627 
  628 static int ProcessUdp( SessionControlBlock *scb, Packet *p, StreamUdpPolicy *s5UdpPolicy,
  629                        SFXHASH_NODE *hash_node )
  630 {
  631     char ignore;
  632     UdpSession *udpssn = NULL;
  633 
  634     if (scb->protocol != IPPROTO_UDP)
  635     {
  636         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  637                     "Lightweight session not UDP on UDP packet\n"););
  638         return ACTION_NOTHING;
  639     }
  640 
  641     if (scb->ha_state.session_flags & (SSNFLAG_DROP_CLIENT|SSNFLAG_DROP_SERVER))
  642     {
  643         /* Got a packet on a session that was dropped (by a rule). */
  644         session_api->set_packet_direction_flag(p, scb);
  645 
  646         /* Drop this packet */
  647         if (((p->packet_flags & PKT_FROM_SERVER) &&
  648              (scb->ha_state.session_flags & SSNFLAG_DROP_SERVER)) ||
  649             ((p->packet_flags & PKT_FROM_CLIENT) &&
  650              (scb->ha_state.session_flags & SSNFLAG_DROP_CLIENT)))
  651         {
  652             DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  653                         "Blocking %s packet as session was blocked\n",
  654                         p->packet_flags & PKT_FROM_SERVER ?
  655                         "server" : "client"););
  656             DisableDetect( p );
  657             if ( scb->ha_state.session_flags & SSNFLAG_FORCE_BLOCK )
  658                 Active_ForceDropSessionWithoutReset();
  659             else
  660                 Active_DropSessionWithoutReset(p);
  661 #ifdef ACTIVE_RESPONSE
  662             StreamActiveResponse(p, scb);
  663 #endif
  664             if (pkt_trace_enabled)
  665                 addPktTraceData(VERDICT_REASON_STREAM, snprintf(trace_line, MAX_TRACE_LINE,
  666                     "Stream: session was already blocked, %s\n", getPktTraceActMsg()));
  667             else addPktTraceData(VERDICT_REASON_STREAM, 0);
  668             return ACTION_NOTHING;
  669         }
  670     }
  671 
  672     if (scb->proto_specific_data != NULL)
  673         udpssn = (UdpSession *)scb->proto_specific_data->data;
  674 
  675     if (udpssn == NULL)
  676     {
  677         if (NewUdpSession(p, scb, s5UdpPolicy) == -1)
  678             return ACTION_NOTHING;
  679         udpssn = (UdpSession *)scb->proto_specific_data->data;
  680 
  681         /* Check if the session is to be ignored */
  682         if (hash_node)
  683             ignore = StreamExpectProcessNode(p, scb, hash_node);
  684         else
  685             ignore = StreamExpectCheck(p, scb);
  686         if (ignore)
  687         {
  688             /* Set the directions to ignore... */
  689             scb->ha_state.ignore_direction = ignore;
  690             DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  691                         "Stream: Ignoring packet from %d. "
  692                         "Marking session marked as ignore.\n",
  693                         p->packet_flags & PKT_FROM_CLIENT? "sender" : "responder"););
  694             session_api->disable_inspection(scb, p);
  695             return ACTION_NOTHING;
  696         }
  697     }
  698 
  699     /* figure out direction of this packet */
  700     session_api->set_packet_direction_flag(p, scb);
  701 
  702     if (((p->packet_flags & PKT_FROM_SERVER) && (scb->ha_state.ignore_direction & SSN_DIR_FROM_CLIENT)) ||
  703         ((p->packet_flags & PKT_FROM_CLIENT) && (scb->ha_state.ignore_direction & SSN_DIR_FROM_SERVER)))
  704     {
  705         session_api->disable_inspection(scb, p);
  706         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  707                     "Stream Ignoring packet from %d. "
  708                     "Session marked as ignore\n",
  709                     p->packet_flags & PKT_FROM_CLIENT? "sender" : "responder"););
  710         return ACTION_NOTHING;
  711     }
  712 
  713     /* if both seen, mark established */
  714     if(p->packet_flags & PKT_FROM_SERVER)
  715     {
  716         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  717                     "Stream: Updating on packet from responder\n"););
  718         scb->ha_state.session_flags |= SSNFLAG_SEEN_RESPONDER;
  719 #ifdef ACTIVE_RESPONSE
  720         SetTTL(scb, p, 0);
  721 #endif
  722     }
  723     else
  724     {
  725         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  726                     "Stream: Updating on packet from client\n"););
  727         /* if we got here we had to see the SYN already... */
  728         scb->ha_state.session_flags |= SSNFLAG_SEEN_SENDER;
  729 #ifdef ACTIVE_RESPONSE
  730         SetTTL(scb, p, 1);
  731 #endif
  732     }
  733 
  734     if (!(scb->ha_state.session_flags & SSNFLAG_ESTABLISHED))
  735     {
  736         if ((scb->ha_state.session_flags & SSNFLAG_SEEN_SENDER) &&
  737             (scb->ha_state.session_flags & SSNFLAG_SEEN_RESPONDER))
  738         {
  739             scb->ha_state.session_flags |= SSNFLAG_ESTABLISHED;
  740         }
  741     }
  742 
  743     return ACTION_NOTHING;
  744 }
  745 
  746 int ProcessUdpCreate (Packet *p) 
  747 {
  748    SFXHASH_NODE *hash_node = NULL;
  749    SessionControlBlock *scb;
  750    StreamUdpPolicy *s5UdpPolicy;
  751    PROFILE_VARS;
  752 
  753    scb = p->ssnptr;
  754    if (!scb) {
  755        DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "[Stream] Could not find Udp session Control block "));
  756        return 0;
  757    }
  758 
  759    s5UdpPolicy = scb->proto_policy;
  760    if (s5UdpPolicy == NULL) {
  761        DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
  762                                "[Stream] Could not find Udp Policy context "
  763                                "for IP %s\n", inet_ntoa(GET_DST_ADDR(p))););
  764        return 0; 
  765     }
  766 
  767     PREPROC_PROFILE_START(s5UdpPerfStats);
  768     scb->session_established = true;
  769     s5stats.total_udp_sessions++;
  770 
  771     /*
  772      * Check if the session is expired.
  773      */
  774     if (( scb->session_state & STREAM_STATE_TIMEDOUT )
  775         || StreamExpire( p, scb )) {
  776 
  777         scb->ha_state.session_flags |= SSNFLAG_TIMEDOUT;
  778 
  779         /* Session is timed out */
  780         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  781                     "Stream UDP session timedout!\n"););
  782 
  783 #ifdef ENABLE_HA
  784         /* Notify the HA peer of the session cleanup/reset by way of a deletion notification. */
  785         PREPROC_PROFILE_TMPEND(s5UdpPerfStats);
  786         SessionHANotifyDeletion(scb);
  787         PREPROC_PROFILE_TMPSTART(s5UdpPerfStats);
  788         scb->ha_flags = (HA_FLAG_NEW | HA_FLAG_MODIFIED | HA_FLAG_MAJOR_CHANGE);
  789 #endif
  790 
  791         /* Clean it up */
  792         UdpSessionCleanup(scb);
  793         ProcessUdp(scb, p, s5UdpPolicy, hash_node);
  794 
  795     } else {
  796         ProcessUdp(scb, p, s5UdpPolicy, hash_node);
  797         DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE,
  798                     "Finished Stream UDP cleanly!\n"
  799                     "---------------------------------------------------\n"););
  800     }
  801     MarkupPacketFlags(p, scb);
  802     session_api->set_expire_timer(p, scb, s5UdpPolicy->session_timeout);
  803     PREPROC_PROFILE_END(s5UdpPerfStats);
  804 
  805     return 0;
  806 }
  807 
  808 void InspectPortFilterUdp (Packet *p)
  809 {
  810     int rc;
  811     SessionControlBlock *scb; 
  812     StreamUdpPolicy *s5UdpPolicy;
  813 
  814     scb = p->ssnptr;
  815     if (!scb) {
  816         DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"[Stream] Sesssion control does not exist"));
  817         return;
  818     }
  819 
  820     s5UdpPolicy = scb->proto_policy;
  821     if (s5UdpPolicy == NULL) {
  822         DEBUG_WRAP(DebugMessage(DEBUG_STREAM,
  823                                 "[Stream] Could not find Udp Policy context "
  824                                 "for IP %s\n", inet_ntoa(GET_DST_ADDR(p))););
  825         return;
  826     }
  827     // If NAP had set port to be filtered, now check IPS portlist. 
  828     if (!(scb->session_state & STREAM_STATE_PORT_INSPECT)) { 
  829 
  830         rc = isPacketFilterDiscardUdp(p, s5UdpPolicy->flags & STREAM_CONFIG_IGNORE_ANY);
  831         if (rc == PORT_MONITOR_PACKET_PROCESS) {
  832             // Port is not present in NAP, but present in IPS portlist, flow will be tracked.  
  833             scb->session_state |= STREAM_STATE_PORT_INSPECT;
  834             // Complete UDP session/flow creation as it needs to tracked. 
  835             ProcessUdpCreate(p);
  836         }
  837         /*
  838          * If return value from isPacketFilterDiscardUdp() was PORT_MONITOR_PACKET_DISCARD, 
  839          * packet is marked either inspected/filtered, based NAP/IPS portlist flag evaluation.
  840          */
  841     } 
  842     return;
  843 }
  844 
  845 void UdpUpdateDirection(SessionControlBlock *ssn, char dir, sfaddr_t* ip, uint16_t port)
  846 {
  847     UdpSession *udpssn = (UdpSession *)ssn->proto_specific_data->data;
  848     sfaddr_t tmpIp;
  849     uint16_t tmpPort;
  850 
  851     if (IP_EQUALITY(&udpssn->udp_sender_ip, ip) && (udpssn->udp_sender_port == port))
  852     {
  853         if ((dir == SSN_DIR_FROM_SENDER) && (ssn->ha_state.direction == SSN_DIR_FROM_SENDER))
  854         {
  855             /* Direction already set as SENDER */
  856             return;
  857         }
  858     }
  859     else if (IP_EQUALITY(&udpssn->udp_responder_ip, ip) && (udpssn->udp_responder_port == port))
  860     {
  861         if ((dir == SSN_DIR_FROM_RESPONDER) && (ssn->ha_state.direction == SSN_DIR_FROM_RESPONDER))
  862         {
  863             /* Direction already set as RESPONDER */
  864             return;
  865         }
  866     }
  867 
  868     /* Swap them -- leave ssn->ha_state.direction the same */
  869     tmpIp = udpssn->udp_sender_ip;
  870     tmpPort = udpssn->udp_sender_port;
  871     udpssn->udp_sender_ip = udpssn->udp_responder_ip;
  872     udpssn->udp_sender_port = udpssn->udp_responder_port;
  873     udpssn->udp_responder_ip = tmpIp;
  874     udpssn->udp_responder_port = tmpPort;
  875 }
  876 
  877 void s5UdpSetPortFilterStatus(struct _SnortConfig *sc, unsigned short port, uint16_t status, tSfPolicyId policyId, int parsing)
  878 {
  879     StreamConfig *config;
  880 
  881     config = getStreamPolicyConfig( policyId, parsing );
  882     if ( ( config != NULL ) && ( config->udp_config != NULL ) )
  883         config->udp_config->port_filter[ port ] |= status;
  884 }
  885 
  886 void s5UdpUnsetPortFilterStatus(struct _SnortConfig *sc, unsigned short port, uint16_t status, tSfPolicyId policyId, int parsing)
  887 {
  888     StreamConfig *config;
  889 
  890     config = getStreamPolicyConfig( policyId, parsing );
  891     if ( ( config != NULL ) && ( config->udp_config != NULL ) )
  892         config->udp_config->port_filter[ port ] &= ~status;
  893 }
  894 
  895 int s5UdpGetPortFilterStatus( struct _SnortConfig *sc, unsigned short port, tSfPolicyId policyId, int parsing)
  896 {
  897     StreamConfig *config;
  898 
  899     config = getStreamPolicyConfig( policyId, parsing );
  900     if ( ( config != NULL ) && ( config->udp_config != NULL ) )
  901         return ( int ) config->udp_config->port_filter[ port ];
  902     else
  903         return PORT_MONITOR_NONE;
  904 }
  905 
  906 int s5UdpGetIPSPortFilterStatus(struct _SnortConfig *sc, unsigned short sport, unsigned short dport, tSfPolicyId policyId)
  907 {
  908     if ( sc->udp_ips_port_filter_list && sc->udp_ips_port_filter_list[policyId] )
  909         return ( ((int) sc->udp_ips_port_filter_list[policyId]->port_filter[ sport ]) |
  910              ((int) sc->udp_ips_port_filter_list[policyId]->port_filter[ dport ]) ) ;
  911     else
  912         return PORT_MONITOR_NONE;
  913 }
  914 
  915 void StreamUdpConfigFree(StreamUdpConfig *config)
  916 {
  917     int i;
  918 
  919     if (config == NULL)
  920         return;
  921 
  922     /* Cleanup TCP Policies and the list */
  923     for (i = 0; i < config->num_policies; i++)
  924     {
  925         StreamUdpPolicy *policy = config->policy_list[i];
  926 
  927         if (policy->bound_addrs != NULL)
  928             sfvar_free(policy->bound_addrs);
  929         free(policy);
  930     }
  931 
  932     free(config->policy_list);
  933     free(config);
  934 }
  935 
  936 #ifdef SNORT_RELOAD
  937 void SessionUDPReload(uint32_t max_sessions, uint16_t pruningTimeout, uint16_t nominalTimeout)
  938 {
  939     SessionReload(udp_lws_cache, max_sessions, pruningTimeout, nominalTimeout
  940 #ifdef REG_TEST
  941                   , "UDP"
  942 #endif
  943                   );
  944 }
  945 
  946 unsigned SessionUDPReloadAdjust(unsigned maxWork)
  947 {
  948     return SessionProtocolReloadAdjust(udp_lws_cache, session_configuration->max_udp_sessions,
  949                                        maxWork, 0
  950 #ifdef REG_TEST
  951                                        , "UDP"
  952 #endif
  953                                        );
  954 }
  955 #endif
  956 
  957 size_t get_udp_used_mempool()
  958 {
  959     if (udp_lws_cache && udp_lws_cache->protocol_session_pool)
  960         return udp_lws_cache->protocol_session_pool->used_memory;
  961 
  962     return 0;
  963 }