"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/detect.c" (16 Oct 2020, 41082 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 "detect.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 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
    4 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    5 ** Copyright (C) 2002-2013 Sourcefire, Inc.
    6 **    Dan Roelker <droelker@sourcefire.com>
    7 **    Marc Norton <mnorton@sourcefire.com>
    8 **
    9 ** This program is free software; you can redistribute it and/or modify
   10 ** it under the terms of the GNU General Public License Version 2 as
   11 ** published by the Free Software Foundation.  You may not use, modify or
   12 ** distribute this program under any other version of the GNU General
   13 ** Public License.
   14 **
   15 ** This program is distributed in the hope that it will be useful,
   16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18 ** GNU General Public License for more details.
   19 **
   20 ** You should have received a copy of the GNU General Public License
   21 ** along with this program; if not, write to the Free Software
   22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   23 **
   24 ** NOTES
   25 **   5.7.02: Added interface for new detection engine. (Norton/Roelker)
   26 **
   27 */
   28 
   29 #define FASTPKT
   30 
   31 /*  I N C L U D E S  **********************************************/
   32 #ifdef HAVE_CONFIG_H
   33 #include "config.h"
   34 #endif
   35 
   36 #include <string.h>
   37 #include <stdlib.h>
   38 
   39 #include "snort.h"
   40 #include "detect.h"
   41 #include "plugbase.h"
   42 #include "snort_debug.h"
   43 #include "util.h"
   44 #include "mstring.h"
   45 #include "tag.h"
   46 #include "pcrm.h"
   47 #include "fpcreate.h"
   48 #include "fpdetect.h"
   49 #include "sfthreshold.h"
   50 #include "event_wrapper.h"
   51 #include "event_queue.h"
   52 #include "obfuscation.h"
   53 #include "profiler.h"
   54 #include "session_api.h"
   55 #include "session_common.h"
   56 #include "stream_api.h"
   57 #include "snort_stream_udp.h"
   58 #include "active.h"
   59 #include "signature.h"
   60 #include "ipv6_port.h"
   61 #include "ppm.h"
   62 #include "sf_types.h"
   63 #include "active.h"
   64 #include "detection_util.h"
   65 #include "preprocids.h"
   66 #if defined(FEAT_OPEN_APPID)
   67 #include "sp_appid.h"
   68 #include "appIdApi.h"
   69 #endif /* defined(FEAT_OPEN_APPID) */
   70 
   71 #ifdef PORTLISTS
   72 #include "sfutil/sfportobject.h"
   73 #endif
   74 #ifdef PERF_PROFILING
   75 PreprocStats detectPerfStats;
   76 #endif
   77 
   78 #ifdef TARGET_BASED
   79 #include "target-based/sftarget_protocol_reference.h"
   80 #endif
   81 #include "sfPolicy.h"
   82 
   83 /* #define ITERATIVE_ENGINE */
   84 
   85 
   86 OptTreeNode *otn_tmp = NULL;       /* OptTreeNode temp ptr */
   87 
   88 int do_detect;
   89 int do_detect_content;
   90 uint16_t event_id;
   91 static char check_tags_flag;
   92 
   93 static int CheckTagging(Packet *);
   94 
   95 #ifdef PERF_PROFILING
   96 PreprocStats eventqPerfStats;
   97 #endif
   98 
   99 static inline int preprocHandlesProto( Packet *p, PreprocEvalFuncNode *ppn )
  100 {
  101     return ( ( p->proto_bits & ppn->proto_mask ) || ( ppn->proto_mask == PROTO_BIT__ALL ) );
  102 }
  103 
  104 static inline bool processDecoderAlertsActionQ( Packet *p )
  105 {
  106     // with policy selected, process any decoder alerts and queued actions
  107     DecodePolicySpecific(p);
  108     // actions are queued only for IDS case
  109     sfActionQueueExecAll(decoderActionQ);
  110     return true;
  111 }
  112 
  113 static void DispatchPreprocessors( Packet *p, tSfPolicyId policy_id, SnortPolicy *policy )
  114 {
  115     SessionControlBlock *scb = NULL;
  116     PreprocEvalFuncNode *ppn;
  117     PreprocEnableMask pps_enabled_foo;
  118     bool alerts_processed = false;
  119 
  120 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
  121     uint64_t start=0, end=0;
  122 #endif
  123  
  124     // No expected sessions yet.
  125     p->expectedSession = NULL;
  126 
  127     // until we are in a Session context dispatch preprocs from the policy list if there is one
  128     p->cur_pp = policy->preproc_eval_funcs;
  129     if( p->cur_pp == NULL )
  130     {
  131         alerts_processed = processDecoderAlertsActionQ( p );
  132         LogMessage("WARNING: No preprocessors configured for policy %d.\n", policy_id);
  133         return;
  134     }
  135 
  136     pps_enabled_foo = policy->pp_enabled[ p->dp ] | policy->pp_enabled[ p->sp ];
  137     EnablePreprocessors( p, pps_enabled_foo );
  138     do {
  139         ppn = p->cur_pp;
  140         p->cur_pp = ppn->next;
  141 
  142         // if packet has no data and we are up to APP preprocs then get out
  143         if( p->dsize == 0 && ppn->priority >= PRIORITY_APPLICATION )
  144             break;
  145 
  146         if ( preprocHandlesProto( p, ppn ) && IsPreprocessorEnabled( p, ppn->preproc_bit ) )
  147         {
  148 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
  149             if (p->pkth && (p->pkth->flags & DAQ_PKT_FLAG_DEBUG_ON))
  150             {
  151                 get_clockticks(start);
  152                 ppn->func( p, ppn->context );
  153                 get_clockticks(end);
  154                 print_flow(p,NULL,ppn->preproc_id,start,end);
  155             }
  156             else
  157                 ppn->func( p, ppn->context );
  158 #else
  159             ppn->func( p, ppn->context );
  160 #endif 
  161         }
  162 
  163 
  164         if( !alerts_processed && ( p->ips_os_selected || ppn->preproc_id == PP_FW_RULE_ENGINE ) )
  165             alerts_processed = processDecoderAlertsActionQ( p );
  166 
  167         if( scb == NULL && p->ssnptr != NULL )
  168             scb = ( SessionControlBlock * ) p->ssnptr;
  169         // if we now have session, update enabled pps if changed by previous preproc
  170         if( scb != NULL && pps_enabled_foo != scb->enabled_pps )
  171         {
  172             EnablePreprocessors( p, scb->enabled_pps );
  173             pps_enabled_foo = scb->enabled_pps;
  174         }
  175  
  176         if( ( ppn->preproc_id == PP_FW_RULE_ENGINE ) && 
  177             ( ( IPH_IS_VALID( p ) ) && ( GET_IPH_PROTO( p ) == IPPROTO_UDP ) ) && 
  178             ( session_api->protocol_tracking_enabled( SESSION_PROTO_UDP ) ) ) 
  179         {
  180             InspectPortFilterUdp( p );
  181         }
  182 
  183     } while ( ( p->cur_pp != NULL ) && !( p->packet_flags & PKT_PASS_RULE ) );
  184 
  185     // queued decoder alerts are processed after the selection of the
  186     // IPS rule config for the flow, if not yet done then process them now
  187     if( !alerts_processed )
  188         alerts_processed = processDecoderAlertsActionQ( p );
  189 
  190     if( p->dsize == 0 )
  191         DisableDetect( p );
  192 }
  193 
  194 
  195 int Preprocess(Packet * p)
  196 {
  197     int retval = 0;
  198     int detect_retval = 0;
  199     tSfPolicyId policy_id;
  200 
  201    /* NAP runtime policy may have been updated during decode, 
  202     * but preprocess needs default nap policy for session
  203     * preprocessor selection, hence use default policy when
  204     * called without session pointer set.
  205     */
  206     if( !p->ssnptr )
  207         policy_id = getDefaultPolicy();
  208     else
  209         policy_id = getNapRuntimePolicy();
  210 
  211     SnortPolicy *policy = snort_conf->targeted_policies[policy_id];
  212 #ifdef PPM_MGR
  213     uint64_t pktcnt=0;
  214 #endif
  215     PROFILE_VARS;
  216 
  217     if (policy == NULL)
  218         return -1;
  219 
  220 #ifdef PPM_MGR
  221     /* Begin Packet Performance Monitoring  */
  222     if( PPM_PKTS_ENABLED() )
  223     {
  224         pktcnt = PPM_INC_PKT_CNT();
  225         PPM_GET_TIME();
  226         PPM_INIT_PKT_TIMER();
  227 #ifdef DEBUG
  228         if( PPM_DEBUG_PKTS() )
  229         {
  230            /* for debugging, info gathering, so don't worry about
  231            *  (unsigned) casting of pktcnt, were not likely to debug
  232            *  4G packets
  233            */
  234            LogMessage("PPM: Process-BeginPkt[%u] caplen=%u\n",
  235              (unsigned)pktcnt,p->pkth->caplen);
  236         }
  237 #endif
  238     }
  239 #endif
  240 
  241     // If the packet has errors or syn over rate, we won't analyze it.
  242     if ( p->error_flags )
  243     {
  244         // process any decoder alerts now that policy has been selected...
  245         DecodePolicySpecific(p);
  246 
  247         //actions are queued only for IDS case
  248         sfActionQueueExecAll(decoderActionQ);
  249         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  250             "Packet errors = 0x%x, ignoring traffic!\n", p->error_flags););
  251 
  252         if ( p->error_flags & PKT_ERR_BAD_TTL )
  253             pc.bad_ttl++;
  254         else if( p->error_flags & PKT_ERR_SYN_RL_DROP )
  255             pc.syn_rate_limit_drops++;
  256         else
  257             pc.invalid_checksums++;
  258     }
  259     else
  260     {
  261         /* Not a completely ideal place for this since any entries added on the
  262          * PacketCallback -> ProcessPacket -> Preprocess trail will get
  263          * obliterated - right now there isn't anything adding entries there.
  264          * Really need it here for stream5 clean exit, since all of the
  265          * flushed, reassembled packets are going to be injected directly into
  266          * this function and there may be enough that the obfuscation entry
  267          * table will overflow if we don't reset it.  Putting it here does
  268          * have the advantage of fewer entries per logging cycle */
  269         obApi->resetObfuscationEntries();
  270 
  271         do_detect = do_detect_content = !snort_conf->disable_all_policies;
  272 
  273         /*
  274         **  Reset the appropriate application-layer protocol fields
  275         */
  276         ClearHttpBuffers();
  277         p->alt_dsize = 0;
  278         DetectReset(p->data, p->dsize);
  279 
  280         // ok, dispatch all preprocs enabled for this packet/session
  281         DispatchPreprocessors( p, policy_id, policy );
  282 
  283         if ( do_detect ) 
  284         {
  285             detect_retval = Detect(p);
  286         }
  287     }
  288 
  289     check_tags_flag = 1;
  290 
  291 #ifdef DUMP_BUFFER
  292     dumped_state = false;
  293 #endif
  294 
  295     PREPROC_PROFILE_START(eventqPerfStats);
  296     retval = SnortEventqLog(snort_conf->event_queue, p);
  297 
  298 #ifdef DUMP_BUFFER
  299 
  300     /* dump_alert_only makes sure that bufferdump happens only when a rule is
  301     triggered.
  302 
  303     dumped_state avoids repetition of buffer dump for a packet that has an
  304     alert, when --buffer-dump is given as command line option.
  305 
  306     When --buffer-dump is given as command line option, BufferDump output
  307     plugin is called for each packet. bdfptr will be NULL for all other output
  308     plugins.
  309     */
  310 
  311     if (!dump_alert_only && !dumped_state)
  312     {
  313          OutputFuncNode *idx = LogList;
  314 
  315          while (idx != NULL)
  316          {
  317              if (idx->bdfptr != NULL)
  318                  idx->bdfptr(p, NULL , idx->arg, NULL);
  319 
  320              idx = idx->next;
  321          }
  322      }
  323 #endif
  324 
  325     SnortEventqReset();
  326     PREPROC_PROFILE_END(eventqPerfStats);
  327 
  328     /* Check for normally closed session */
  329     if( session_api )
  330         session_api->check_session_closed(p);
  331 
  332     if( session_api && p->ssnptr &&
  333       ( session_api->get_session_flags(p->ssnptr) & SSNFLAG_FREE_APP_DATA) )
  334     {
  335         SessionControlBlock *scb = ( SessionControlBlock * ) p->ssnptr;
  336         session_api->free_application_data(scb);
  337         scb->ha_state.session_flags &= ~SSNFLAG_FREE_APP_DATA;
  338     }
  339 
  340     /*
  341     ** By checking tagging here, we make sure that we log the
  342     ** tagged packet whether it generates an alert or not.
  343     */
  344     if (IPH_IS_VALID(p))
  345         CheckTagging(p);
  346 
  347     otn_tmp = NULL;
  348 
  349     /*
  350     **  If we found events in this packet, let's flush
  351     **  the stream to make sure that we didn't miss any
  352     **  attacks before this packet.
  353     */
  354     if(retval && IsTCP(p) && stream_api)
  355         stream_api->alert_flush_stream(p);
  356 
  357 #ifdef PPM_MGR
  358     if( PPM_PKTS_ENABLED() )
  359     {
  360         PPM_GET_TIME();
  361         PPM_TOTAL_PKT_TIME();
  362         PPM_ACCUM_PKT_TIME();
  363 #ifdef DEBUG
  364         if( PPM_DEBUG_PKTS() )
  365         {
  366             LogMessage("PPM: Pkt[%u] Used= ",(unsigned)pktcnt);
  367             PPM_PRINT_PKT_TIME("%g usecs\n");
  368             LogMessage("PPM: Process-EndPkt[%u]\n\n",(unsigned)pktcnt);
  369         }
  370 #endif
  371        // When detection is required to happen and it is skipped , then only we will print the trace. 
  372         if (do_detect && (!detect_retval)) 
  373             PPM_LATENCY_TRACE();
  374 
  375         PPM_PKT_LOG(p);
  376     }
  377     if( PPM_RULES_ENABLED() )
  378     {
  379         PPM_RULE_LOG(pktcnt, p);
  380     }
  381     if( PPM_PKTS_ENABLED() )
  382     {
  383         PPM_END_PKT_TIMER();
  384     }
  385 #endif
  386 
  387     return retval;
  388 }
  389 
  390 /*
  391 **  NAME
  392 **    CheckTagging::
  393 */
  394 /**
  395 **  This is where we check to see if we tag the packet.  We only do
  396 **  this if we've alerted on a non-pass rule and the packet is not
  397 **  rebuilt.
  398 **
  399 **  We don't log rebuilt packets because the output plugins log the
  400 **  individual packets of a rebuilt stream, so we don't want to dup
  401 **  tagged packets for rebuilt streams.
  402 **
  403 **  @return integer
  404 */
  405 static int CheckTagging(Packet *p)
  406 {
  407     Event event;
  408 
  409     if(check_tags_flag == 1 && !(p->packet_flags & PKT_REBUILT_STREAM))
  410     {
  411         void* listhead = NULL;
  412         DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "calling CheckTagList\n"););
  413 
  414         if(CheckTagList(p, &event, &listhead))
  415         {
  416             DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "Matching tag node found, "
  417                         "calling log functions\n"););
  418 
  419             /* if we find a match, we want to send the packet to the
  420              * logging mechanism
  421              */
  422             CallLogFuncs(p, "Tagged Packet", listhead, &event);
  423         }
  424     }
  425 
  426     return 0;
  427 }
  428 
  429 #if defined(FEAT_OPEN_APPID)
  430 static void updateEventAppName (Packet *p, OptTreeNode *otn, Event *event)
  431 {
  432     const char *appName;
  433     size_t appNameLen;
  434     AppIdOptionData *app_data = (AppIdOptionData*)otn->ds_list[PLUGIN_APPID];
  435 
  436     if (app_data && (app_data->matched_appid) && (appName = appIdApi.getApplicationName(app_data->matched_appid)))
  437     {
  438         appNameLen = strlen(appName);
  439         if (appNameLen >= sizeof(event->app_name))
  440             appNameLen = sizeof(event->app_name) - 1;
  441         memcpy(event->app_name, appName, appNameLen);
  442         event->app_name[appNameLen] = '\0';
  443     }
  444     else if (p->ssnptr)
  445     {
  446         //log most specific appid when rule didn't have any appId
  447         int16_t serviceProtoId, clientProtoId, payloadProtoId, miscProtoId, pickedProtoId;
  448 
  449         stream_api->get_application_id(p->ssnptr, &serviceProtoId, &clientProtoId, &payloadProtoId, &miscProtoId);
  450         if ((p->packet_flags & PKT_FROM_CLIENT))
  451         {
  452             if (!(pickedProtoId = payloadProtoId) &&  !(pickedProtoId = miscProtoId) && !(pickedProtoId = clientProtoId))
  453                 pickedProtoId = serviceProtoId;
  454         }
  455         else
  456         {
  457             if (!(pickedProtoId = payloadProtoId) &&  !(pickedProtoId = miscProtoId) && !(pickedProtoId = serviceProtoId))
  458                 pickedProtoId = clientProtoId;
  459         }
  460 
  461         if ((pickedProtoId) && (appName = appIdApi.getApplicationName(pickedProtoId)))
  462         {
  463             appNameLen = strlen(appName);
  464             if (appNameLen >= sizeof(event->app_name))
  465                 appNameLen = sizeof(event->app_name) - 1;
  466             memcpy(event->app_name, appName, appNameLen);
  467             event->app_name[appNameLen] = '\0';
  468         }
  469         else
  470         {
  471             event->app_name[0] = 0;
  472         }
  473     }
  474     else
  475     {
  476         event->app_name[0] = 0;
  477     }
  478 }
  479 #endif /* defined(FEAT_OPEN_APPID) */
  480 void CallLogFuncs(Packet *p, const char *message, ListHead *head, Event *event)
  481 {
  482     OutputFuncNode *idx = NULL;
  483 
  484     if (event->sig_generator != GENERATOR_TAG)
  485     {
  486         event->ref_time.tv_sec = p->pkth->ts.tv_sec;
  487         event->ref_time.tv_usec = p->pkth->ts.tv_usec;
  488     }
  489     /* set the event number */
  490     event->event_id = event_id | ScEventLogId();
  491 
  492     check_tags_flag = 0;
  493 
  494     pc.log_pkts++;
  495 
  496     if ( head == NULL || head->LogList == NULL )
  497     {
  498         CallLogPlugins(p, message, event);
  499         return;
  500     }
  501 
  502     idx = head->LogList;
  503     while ( idx != NULL )
  504     {
  505         idx->func(p, message, idx->arg, event);
  506         idx = idx->next;
  507     }
  508 }
  509 
  510 void CallLogPlugins(Packet * p, const char *message, Event *event)
  511 {
  512     OutputFuncNode *idx = LogList;
  513 
  514     while ( idx != NULL )
  515     {
  516         idx->func(p, message, idx->arg, event);
  517         idx = idx->next;
  518     }
  519 }
  520 
  521 /* Call the output functions that are directly attached to the signature */
  522 void CallSigOutputFuncs(Packet *p, OptTreeNode *otn, Event *event)
  523 {
  524     OutputFuncNode *idx = NULL;
  525 
  526     idx = otn->outputFuncs;
  527 
  528     while(idx)
  529     {
  530         idx->func(p, otn->sigInfo.message, idx->arg, event);
  531         idx = idx->next;
  532     }
  533 }
  534 
  535 void CallAlertFuncs(Packet * p, const char *message, ListHead * head, Event *event)
  536 {
  537     OutputFuncNode *idx = NULL;
  538 
  539     event->ref_time.tv_sec = p->pkth->ts.tv_sec;
  540     event->ref_time.tv_usec = p->pkth->ts.tv_usec;
  541 
  542     /* set the event number */
  543     event->event_id = event_id | ScEventLogId();
  544     /* set the event reference info */
  545     event->event_reference = event->event_id;
  546 
  547     pc.total_alert_pkts++;
  548 
  549     if ( event->sig_generator != GENERATOR_SPP_REPUTATION )
  550     {
  551         /* Don't include IP Reputation events in count */
  552         pc.alert_pkts++;
  553     }
  554 
  555     if ( head == NULL || head->AlertList == NULL )
  556     {
  557         CallAlertPlugins(p, message, event);
  558         return;
  559     }
  560 
  561     idx = head->AlertList;
  562     while ( idx != NULL )
  563     {
  564         idx->func(p, message, idx->arg, event);
  565         idx = idx->next;
  566     }
  567 }
  568 
  569 
  570 void CallAlertPlugins(Packet * p, const char *message, Event *event)
  571 {
  572     OutputFuncNode *idx = AlertList;
  573 
  574     while ( idx != NULL )
  575     {
  576         idx->func(p, message, idx->arg, event);
  577         idx = idx->next;
  578     }
  579 }
  580 
  581 /****************************************************************************
  582  *
  583  * Function: Detect(Packet *)
  584  *
  585  * Purpose: Apply the rules lists to the current packet
  586  *
  587  * Arguments: p => ptr to the decoded packet struct
  588  *
  589  * Returns: 1 == detection event
  590  *          0 == no detection
  591  *
  592  ***************************************************************************/
  593 int Detect(Packet * p)
  594 {
  595     int detected = 0;
  596     PROFILE_VARS;
  597 
  598 #if defined(DAQ_VERSION) && DAQ_VERSION > 9
  599     uint64_t start = 0, end = 0;
  600 #endif
  601 
  602     if ((p == NULL) || !IPH_IS_VALID(p))
  603     {
  604         return 0;
  605     }
  606     
  607     if (stream_api && stream_api->is_session_http2(p->ssnptr) 
  608         && !(p->packet_flags & PKT_REBUILT_STREAM)) 
  609     {
  610         return 0;
  611     }
  612 
  613     if (!snort_conf->ip_proto_array[GET_IPH_PROTO(p)])
  614     {
  615 #ifdef GRE
  616         switch (p->outer_family)
  617         {
  618             case AF_INET:
  619                 if (!snort_conf->ip_proto_array[p->outer_ip4h.ip_proto])
  620                     return 0;
  621                 break;
  622 
  623             case AF_INET6:
  624                 if (!snort_conf->ip_proto_array[p->outer_ip6h.next])
  625                     return 0;
  626                 break;
  627 
  628             default:
  629                 return 0;
  630         }
  631 #else
  632         return 0;
  633 #endif  /* GRE */
  634     }
  635 
  636     if (p->packet_flags & PKT_PASS_RULE)
  637     {
  638         /* If we've already seen a pass rule on this,
  639          * no need to continue do inspection.
  640          */
  641         return 0;
  642     }
  643 
  644 #ifdef PPM_MGR
  645     /*
  646      * Packet Performance Monitoring
  647      * (see if preprocessing took too long)
  648      */
  649     if( PPM_PKTS_ENABLED() )
  650     {
  651         PPM_GET_TIME();
  652         PPM_PACKET_TEST();
  653 
  654         if( PPM_PACKET_ABORT_FLAG() )
  655             return 0;
  656     }
  657 #endif
  658 
  659     /*
  660     **  This is where we short circuit so
  661     **  that we can do IP checks.
  662     */
  663     PREPROC_PROFILE_START(detectPerfStats);
  664  #if defined(DAQ_VERSION) && DAQ_VERSION > 9
  665     if (p->pkth && (p->pkth->flags & DAQ_PKT_FLAG_DEBUG_ON))
  666     {
  667         get_clockticks(start);
  668         detected = fpEvalPacket(p);
  669         get_clockticks(end);
  670         print_flow(p,"DETECTION",0,start,end);
  671     }
  672     else
  673         detected = fpEvalPacket(p);
  674  #else
  675     detected = fpEvalPacket(p);
  676 #endif
  677 
  678     PREPROC_PROFILE_END(detectPerfStats);
  679 
  680     return detected;
  681 }
  682 
  683 void TriggerResponses(Packet * p, OptTreeNode * otn)
  684 {
  685 
  686     RspFpList *idx;
  687 
  688     idx = otn->rsp_func;
  689 
  690     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"Triggering responses %p\n", idx););
  691 
  692     while(idx != NULL)
  693     {
  694         idx->func(p, idx->params);
  695         idx = idx->next;
  696     }
  697 
  698 }
  699 
  700 int CheckAddrPort(
  701                 sfip_var_t *rule_addr,
  702                 PortObject * po,
  703                 Packet *p,
  704                 uint32_t flags, int mode)
  705 {
  706     sfaddr_t* pkt_addr;              /* packet IP address */
  707     u_short pkt_port;                /* packet port */
  708     int global_except_addr_flag = 0; /* global exception flag is set */
  709     int any_port_flag = 0;           /* any port flag set */
  710     int except_port_flag = 0;        /* port exception flag set */
  711     int ip_match = 0;                /* flag to indicate addr match made */
  712 
  713     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckAddrPort: "););
  714     /* set up the packet particulars */
  715     if(mode & CHECK_SRC_IP)
  716     {
  717         pkt_addr = GET_SRC_IP(p);
  718         pkt_port = p->sp;
  719 
  720         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"SRC "););
  721 
  722         if(mode & INVERSE)
  723         {
  724             global_except_addr_flag = flags & EXCEPT_DST_IP;
  725             any_port_flag = flags & ANY_DST_PORT;
  726             except_port_flag = flags & EXCEPT_DST_PORT;
  727         }
  728         else
  729         {
  730             global_except_addr_flag = flags & EXCEPT_SRC_IP;
  731             any_port_flag = flags & ANY_SRC_PORT;
  732             except_port_flag = flags & EXCEPT_SRC_PORT;
  733         }
  734     }
  735     else
  736     {
  737         pkt_addr = GET_DST_IP(p);
  738         pkt_port = p->dp;
  739 
  740         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "DST "););
  741 
  742         if(mode & INVERSE)
  743         {
  744             global_except_addr_flag = flags & EXCEPT_SRC_IP;
  745             any_port_flag = flags & ANY_SRC_PORT;
  746             except_port_flag = flags & EXCEPT_SRC_PORT;
  747         }
  748         else
  749         {
  750             global_except_addr_flag = flags & EXCEPT_DST_IP;
  751             any_port_flag = flags & ANY_DST_PORT;
  752             except_port_flag = flags & EXCEPT_DST_PORT;
  753         }
  754     }
  755 
  756     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "addr %lx, port %d ", pkt_addr,
  757                 pkt_port););
  758 
  759     if(!rule_addr)
  760         goto bail;
  761 
  762     if(!(global_except_addr_flag)) /*modeled after Check{Src,Dst}IP function*/
  763     {
  764         if(sfvar_ip_in(rule_addr, pkt_addr))
  765             ip_match = 1;
  766     }
  767     else
  768     {
  769         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", global exception flag set"););
  770         /* global exception flag is up, we can't match on *any*
  771          * of the source addresses
  772          */
  773 
  774         if(sfvar_ip_in(rule_addr, pkt_addr))
  775             return 0;
  776 
  777         ip_match=1;
  778     }
  779 
  780 bail:
  781     if(!ip_match)
  782     {
  783         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", no address match,  "
  784                     "packet rejected\n"););
  785         return 0;
  786     }
  787 
  788     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", addresses accepted"););
  789 
  790     /* if the any port flag is up, we're all done (success) */
  791     if(any_port_flag)
  792     {
  793         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", any port match, "
  794                     "packet accepted\n"););
  795         return 1;
  796     }
  797 
  798 #ifdef TARGET_BASED
  799     if (!(mode & (CHECK_SRC_PORT | CHECK_DST_PORT)))
  800     {
  801         DEBUG_WRAP(
  802             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckAddrPort..."
  803                 "target-based-protocol=%d,ignoring ports\n",
  804                 GetProtocolReference(p)););
  805         return 1;
  806     }
  807     else
  808     {
  809         DEBUG_WRAP(
  810             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckAddrPort..."
  811                 "target-based-protocol=%d,not ignoring ports\n",
  812                 GetProtocolReference(p)););
  813     }
  814 #endif /* TARGET_BASED */
  815 
  816     /* check the packet port against the rule port */
  817     if( !PortObjectHasPort(po,pkt_port) )
  818     {
  819         /* if the exception flag isn't up, fail */
  820         if(!except_port_flag)
  821         {
  822             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", port mismatch,  "
  823                         "packet rejected\n"););
  824             return 0;
  825         }
  826         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", port mismatch exception"););
  827     }
  828     else
  829     {
  830         /* if the exception flag is up, fail */
  831         if(except_port_flag)
  832         {
  833             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  834                                     ", port match exception,  packet rejected\n"););
  835             return 0;
  836         }
  837         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", ports match"););
  838     }
  839 
  840     /* ports and address match */
  841     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, ", packet accepted!\n"););
  842     return 1;
  843 
  844 }
  845 
  846 /****************************************************************************
  847  *
  848  * Function: DumpList(IpAddrNode*)
  849  *
  850  * Purpose: print out the chain lists by header block node group
  851  *
  852  * Arguments: node => the head node
  853  *
  854  * Returns: void function
  855  *
  856  ***************************************************************************/
  857 void DumpList(IpAddrNode *idx, int negated)
  858 {
  859     DEBUG_WRAP(int i=0;);
  860     if(!idx)
  861         return;
  862 
  863     while(idx != NULL)
  864     {
  865        DEBUG_WRAP(DebugMessage(DEBUG_RULES,
  866                         "[%d]    %s",
  867                         i++, sfip_ntoa(&idx->ip->addr)););
  868 
  869        if(negated)
  870        {
  871            DEBUG_WRAP(DebugMessage(DEBUG_RULES,
  872                        "    (EXCEPTION_FLAG Active)\n"););
  873        }
  874        else
  875        {
  876            DEBUG_WRAP(DebugMessage(DEBUG_RULES, "\n"););
  877        }
  878 
  879        idx = idx->next;
  880     }
  881 }
  882 
  883 
  884 /****************************************************************************
  885  *
  886  * Function: DumpChain(RuleTreeNode *, char *, char *)
  887  *
  888  * Purpose: Iterate over RTNs calling DumpList on each
  889  *
  890  * Arguments: rtn_idx => the RTN index pointer
  891  *                       rulename => the name of the rule the list belongs to
  892  *            listname => the name of the list being printed out
  893  *
  894  * Returns: void function
  895  *
  896  ***************************************************************************/
  897 void DumpChain(RuleTreeNode * rtn_head, char *rulename, char *listname)
  898 {
  899     // XXX Not yet implemented - Rule chain dumping
  900 }
  901 
  902 #define CHECK_ADDR_SRC_ARGS(x) (x)->src_portobject
  903 #define CHECK_ADDR_DST_ARGS(x) (x)->dst_portobject
  904 
  905 int CheckBidirectional(Packet *p, struct _RuleTreeNode *rtn_idx,
  906         RuleFpList *fp_list, int check_ports)
  907 {
  908     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Checking bidirectional rule...\n"););
  909 
  910     if(CheckAddrPort(rtn_idx->sip, CHECK_ADDR_SRC_ARGS(rtn_idx), p,
  911                      rtn_idx->flags, CHECK_SRC_IP | (check_ports ? CHECK_SRC_PORT : 0)))
  912     {
  913         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   Src->Src check passed\n"););
  914         if(! CheckAddrPort(rtn_idx->dip, CHECK_ADDR_DST_ARGS(rtn_idx), p,
  915                            rtn_idx->flags, CHECK_DST_IP | (check_ports ? CHECK_DST_PORT : 0)))
  916         {
  917             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  918                                     "   Dst->Dst check failed,"
  919                                     " checking inverse combination\n"););
  920             if(CheckAddrPort(rtn_idx->dip, CHECK_ADDR_DST_ARGS(rtn_idx), p,
  921                              rtn_idx->flags, (CHECK_SRC_IP | INVERSE | (check_ports ? CHECK_SRC_PORT : 0))))
  922             {
  923                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  924                                     "   Inverse Dst->Src check passed\n"););
  925                 if(!CheckAddrPort(rtn_idx->sip, CHECK_ADDR_SRC_ARGS(rtn_idx), p,
  926                                   rtn_idx->flags, (CHECK_DST_IP | INVERSE | (check_ports ? CHECK_DST_PORT : 0))))
  927                 {
  928                     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  929                                     "   Inverse Src->Dst check failed\n"););
  930                     return 0;
  931                 }
  932                 else
  933                 {
  934                     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "Inverse addr/port match\n"););
  935                 }
  936             }
  937             else
  938             {
  939                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   Inverse Dst->Src check failed,"
  940                                         " trying next rule\n"););
  941                 return 0;
  942             }
  943         }
  944         else
  945         {
  946             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "dest IP/port match\n"););
  947         }
  948     }
  949     else
  950     {
  951         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  952                                 "   Src->Src check failed, trying inverse test\n"););
  953         if(CheckAddrPort(rtn_idx->dip, CHECK_ADDR_DST_ARGS(rtn_idx), p,
  954                          rtn_idx->flags, CHECK_SRC_IP | INVERSE | (check_ports ? CHECK_SRC_PORT : 0)))
  955         {
  956             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  957                         "   Dst->Src check passed\n"););
  958 
  959             if(!CheckAddrPort(rtn_idx->sip, CHECK_ADDR_SRC_ARGS(rtn_idx), p,
  960                         rtn_idx->flags, CHECK_DST_IP | INVERSE | (check_ports ? CHECK_DST_PORT : 0)))
  961             {
  962                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  963                             "   Src->Dst check failed\n"););
  964                 return 0;
  965             }
  966             else
  967             {
  968                 DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
  969                             "Inverse addr/port match\n"););
  970             }
  971         }
  972         else
  973         {
  974             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   Inverse test failed, "
  975                         "testing next rule...\n"););
  976             return 0;
  977         }
  978     }
  979 
  980     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   Bidirectional success!\n"););
  981     return 1;
  982 }
  983 
  984 
  985 /****************************************************************************
  986  *
  987  * Function: CheckSrcIp(Packet *, struct _RuleTreeNode *, RuleFpList *)
  988  *
  989  * Purpose: Test the source IP and see if it equals the SIP of the packet
  990  *
  991  * Arguments: p => ptr to the decoded packet data structure
  992  *            rtn_idx => ptr to the current rule data struct
  993  *            fp_list => ptr to the current function pointer node
  994  *
  995  * Returns: 0 on failure (no match), 1 on success (match)
  996  *
  997  ***************************************************************************/
  998 int CheckSrcIP(Packet * p, struct _RuleTreeNode * rtn_idx, RuleFpList * fp_list, int check_ports)
  999 {
 1000 
 1001     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckSrcIPEqual: "););
 1002 
 1003     if(!(rtn_idx->flags & EXCEPT_SRC_IP))
 1004     {
 1005         if( sfvar_ip_in(rtn_idx->sip, GET_SRC_IP(p)) )
 1006         {
 1007 // XXX NOT YET IMPLEMENTED - debugging in Snort6
 1008 #if 0
 1009 #ifdef DEBUG_MSGS
 1010             sfaddr_t ip;
 1011             if(idx->addr_flags & EXCEPT_IP) {
 1012                 DebugMessage(DEBUG_DETECT, "  SIP exception match\n");
 1013             }
 1014             else
 1015             {
 1016                 DebugMessage(DEBUG_DETECT, "  SIP match\n");
 1017             }
 1018 
 1019             ip = *iph_ret_src(p);    /* necessary due to referencing/dereferencing */
 1020             DebugMessage(DEBUG_DETECT, "Rule: %s     Packet: %s\n",
 1021                    inet_ntoa(idx->ip_addr), inet_ntoa(ip));
 1022 #endif /* DEBUG */
 1023 #endif
 1024 
 1025             /* the packet matches this test, proceed to the next test */
 1026             return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1027         }
 1028     }
 1029     else
 1030     {
 1031         /* global exception flag is up, we can't match on *any*
 1032          * of the source addresses
 1033          */
 1034         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"  global exception flag, \n"););
 1035 
 1036         if( sfvar_ip_in(rtn_idx->sip, GET_SRC_IP(p)) ) return 0;
 1037 
 1038         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1039     }
 1040 
 1041     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"  Mismatch on SIP\n"););
 1042 
 1043     return 0;
 1044 
 1045     /* return 0 on a failed test */
 1046     return 0;
 1047 }
 1048 
 1049 
 1050 /****************************************************************************
 1051  *
 1052  * Function: CheckDstIp(Packet *, struct _RuleTreeNode *, RuleFpList *)
 1053  *
 1054  * Purpose: Test the dest IP and see if it equals the DIP of the packet
 1055  *
 1056  * Arguments: p => ptr to the decoded packet data structure
 1057  *            rtn_idx => ptr to the current rule data struct
 1058  *            fp_list => ptr to the current function pointer node
 1059  *
 1060  * Returns: 0 on failure (no match), 1 on success (match)
 1061  *
 1062  ***************************************************************************/
 1063 int CheckDstIP(Packet *p, struct _RuleTreeNode *rtn_idx, RuleFpList *fp_list, int check_ports)
 1064 {
 1065 
 1066     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "CheckDstIPEqual: ");)
 1067 
 1068     if(!(rtn_idx->flags & EXCEPT_DST_IP))
 1069     {
 1070         if( sfvar_ip_in(rtn_idx->dip, GET_DST_IP(p)) )
 1071         {
 1072 // #ifdef DEBUG_MSGS
 1073 // XXX idx's equivalent is lost inside of sfvar_ip_in
 1074 //            DebugMessage(DEBUG_DETECT, "Rule: %s     Packet: ",
 1075 //                   inet_ntoa(idx->ip_addr));
 1076 //            DebugMessage(DEBUG_DETECT, "%s\n", sfip_ntoa(iph_ret_dst(p)));
 1077 // #endif
 1078 
 1079             /* the packet matches this test, proceed to the next test */
 1080             return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1081         }
 1082     }
 1083     else
 1084     {
 1085         /* global exception flag is up, we can't match on *any*
 1086          * of the source addresses */
 1087         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"  global exception flag, \n"););
 1088 
 1089         if( sfvar_ip_in(rtn_idx->dip, GET_DST_IP(p)) ) return 0;
 1090 
 1091         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1092     }
 1093 
 1094     return 0;
 1095 }
 1096 
 1097 
 1098 int CheckSrcPortEqual(Packet *p, struct _RuleTreeNode *rtn_idx,
 1099         RuleFpList *fp_list, int check_ports)
 1100 {
 1101     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckSrcPortEqual: "););
 1102 
 1103 #ifdef TARGET_BASED
 1104     /* Check if attributes provided match earlier */
 1105     if (check_ports == 0)
 1106     {
 1107         DEBUG_WRAP(
 1108             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckSrcPortEq..."
 1109                 "target-based-protocol=%d,ignoring ports\n",
 1110                 GetProtocolReference(p)););
 1111         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1112     }
 1113     else
 1114     {
 1115         DEBUG_WRAP(
 1116             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckSrcPortEq..."
 1117                 "target-based-protocol=%d,not ignoring ports\n",
 1118                 GetProtocolReference(p)););
 1119     }
 1120 #endif /* TARGET_BASED */
 1121     if( PortObjectHasPort(rtn_idx->src_portobject,p->sp) )
 1122     {
 1123         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  SP match!\n"););
 1124         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1125     }
 1126     else
 1127     {
 1128         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   SP mismatch!\n"););
 1129     }
 1130 
 1131     return 0;
 1132 }
 1133 
 1134 int CheckSrcPortNotEq(Packet *p, struct _RuleTreeNode *rtn_idx,
 1135         RuleFpList *fp_list, int check_ports)
 1136 {
 1137     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckSrcPortNotEq: "););
 1138 
 1139 #ifdef TARGET_BASED
 1140     /* Check if attributes provided match earlier */
 1141     if (check_ports == 0)
 1142     {
 1143         DEBUG_WRAP(
 1144             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckSrcPortNotEq..."
 1145                 "target-based-protocol=%d,ignoring ports\n",
 1146                 GetProtocolReference(p)););
 1147         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1148     }
 1149     else
 1150     {
 1151         DEBUG_WRAP(
 1152             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckSrcPortNotEq..."
 1153                 "target-based-protocol=%d,not ignoring ports\n",
 1154                 GetProtocolReference(p)););
 1155     }
 1156 #endif /* TARGET_BASED */
 1157     if( !PortObjectHasPort(rtn_idx->src_portobject,p->sp) )
 1158     {
 1159         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  !SP match!\n"););
 1160         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1161     }
 1162     else
 1163     {
 1164         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "  !SP mismatch!\n"););
 1165     }
 1166 
 1167     return 0;
 1168 }
 1169 
 1170 int CheckDstPortEqual(Packet *p, struct _RuleTreeNode *rtn_idx,
 1171         RuleFpList *fp_list, int check_ports)
 1172 {
 1173     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckDstPortEqual: "););
 1174 
 1175 #ifdef TARGET_BASED
 1176     /* Check if attributes provided match earlier */
 1177     if (check_ports == 0)
 1178     {
 1179         DEBUG_WRAP(
 1180             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckDstPortEq..."
 1181             "target-based-protocol=%d,ignoring ports\n",
 1182             GetProtocolReference(p)););
 1183         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1184     }
 1185     else
 1186     {
 1187         DEBUG_WRAP(
 1188             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckDstPortEq..."
 1189             "target-based-protocol=%d,not ignoring ports\n",
 1190             GetProtocolReference(p)););
 1191     }
 1192 #endif /* TARGET_BASED */
 1193     if( PortObjectHasPort(rtn_idx->dst_portobject,p->dp) )
 1194     {
 1195         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, " DP match!\n"););
 1196         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1197     }
 1198     else
 1199     {
 1200         DEBUG_WRAP(DebugMessage(DEBUG_DETECT," DP mismatch!\n"););
 1201     }
 1202     return 0;
 1203 }
 1204 
 1205 
 1206 int CheckDstPortNotEq(Packet *p, struct _RuleTreeNode *rtn_idx,
 1207         RuleFpList *fp_list, int check_ports)
 1208 {
 1209     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"CheckDstPortNotEq: "););
 1210 
 1211 #ifdef TARGET_BASED
 1212     /* Check if attributes provided match earlier */
 1213     if (check_ports == 0)
 1214     {
 1215         DEBUG_WRAP(
 1216             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckDstPortNotEq..."
 1217             "target-based-protocol=%d,ignoring ports\n",
 1218             GetProtocolReference(p)););
 1219         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1220     }
 1221     else
 1222     {
 1223         DEBUG_WRAP(
 1224             DebugMessage(DEBUG_ATTRIBUTE, "detect.c: CheckDstPortNotEq..."
 1225             "target-based-protocol=%d,not ignoring ports\n",
 1226             GetProtocolReference(p)););
 1227     }
 1228 #endif /* TARGET_BASED */
 1229     if( !PortObjectHasPort(rtn_idx->dst_portobject,p->dp) )
 1230     {
 1231         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, " !DP match!\n"););
 1232         return fp_list->next->RuleHeadFunc(p, rtn_idx, fp_list->next, check_ports);
 1233     }
 1234     else
 1235     {
 1236         DEBUG_WRAP(DebugMessage(DEBUG_DETECT," !DP mismatch!\n"););
 1237     }
 1238 
 1239     return 0;
 1240 }
 1241 
 1242 int RuleListEnd(Packet *p, struct _RuleTreeNode *rtn_idx,
 1243         RuleFpList *fp_list, int check_ports)
 1244 {
 1245     return 1;
 1246 }
 1247 
 1248 
 1249 int OptListEnd(void *option_data, Packet *p)
 1250 {
 1251     return DETECTION_OPTION_MATCH;
 1252 }
 1253 
 1254 /* Rule Match Action Functions */
 1255 int PassAction(void)
 1256 {
 1257     pc.pass_pkts++;
 1258 
 1259     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   => Pass rule, returning...\n"););
 1260     return 1;
 1261 }
 1262 
 1263 int AlertAction(Packet * p, OptTreeNode * otn, RuleTreeNode * rtn, Event * event)
 1264 {
 1265     if (!rtn)
 1266     {
 1267         // This function may be called from ppm, which doesn't do an RTN lookup
 1268         rtn = getRuntimeRtnFromOtn(otn);
 1269         if (!rtn)
 1270             return 0;
 1271     }
 1272 
 1273     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
 1274                 "        <!!> Generating alert! \"%s\", policyId %d\n", otn->sigInfo.message, getIpsRuntimePolicy()););
 1275 #if defined(FEAT_OPEN_APPID)
 1276     updateEventAppName (p, otn, event);
 1277 #endif /* defined(FEAT_OPEN_APPID) */
 1278 
 1279     /* Call OptTreeNode specific output functions */
 1280     if(otn->outputFuncs)
 1281         CallSigOutputFuncs(p, otn, event);
 1282 
 1283     if (ScAlertPacketCount())
 1284         print_packet_count();
 1285 
 1286     CallAlertFuncs(p, otn->sigInfo.message, rtn->listhead, event);
 1287 
 1288     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   => Finishing alert packet!\n"););
 1289 
 1290     CallLogFuncs(p, otn->sigInfo.message, rtn->listhead, event);
 1291 
 1292     /*
 1293     if(p->ssnptr != NULL && stream_api)
 1294     {
 1295         if(stream_api->alert_flush_stream(p) == 0)
 1296         {
 1297             CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
 1298         }
 1299     }
 1300     else
 1301     {
 1302         CallLogFuncs(p, otn->sigInfo.message, otn->rtn->listhead, event);
 1303     }
 1304     */
 1305 
 1306     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   => Alert packet finished, returning!\n"););
 1307 
 1308     return 1;
 1309 }
 1310 
 1311 int DropAction(Packet * p, OptTreeNode * otn, RuleTreeNode * rtn, Event * event)
 1312 {
 1313     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
 1314                "        <!!> Generating Alert and dropping! \"%s\"\n",
 1315                otn->sigInfo.message););
 1316 
 1317     if(stream_api && !stream_api->alert_inline_midstream_drops())
 1318     {
 1319         if(session_api->get_session_flags(p->ssnptr) & SSNFLAG_MIDSTREAM)
 1320         {
 1321             DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
 1322                 " <!!> Alert Came From Midstream Session Silently Drop! "
 1323                 "\"%s\"\n", otn->sigInfo.message););
 1324 
 1325             Active_DropSession(p);
 1326             if (pkt_trace_enabled)
 1327                 addPktTraceData(VERDICT_REASON_SNORT, snprintf(trace_line, MAX_TRACE_LINE,
 1328                     "Snort: gid %u, sid %u, midstream %s\n", otn->sigInfo.generator, otn->sigInfo.id, getPktTraceActMsg()));
 1329             else addPktTraceData(VERDICT_REASON_SNORT, 0);
 1330             return 1;
 1331         }
 1332     }
 1333 
 1334     /*
 1335     **  Set packet flag so output plugins will know we dropped the
 1336     **  packet we just logged.
 1337     */
 1338     Active_DropSession(p);
 1339 #if defined(FEAT_OPEN_APPID)
 1340     updateEventAppName (p, otn, event);
 1341 #endif /* defined(FEAT_OPEN_APPID) */
 1342 
 1343     CallAlertFuncs(p, otn->sigInfo.message, rtn->listhead, event);
 1344 
 1345     CallLogFuncs(p, otn->sigInfo.message, rtn->listhead, event);
 1346 
 1347     if (pkt_trace_enabled)
 1348         addPktTraceData(VERDICT_REASON_SNORT, snprintf(trace_line, MAX_TRACE_LINE,
 1349             "Snort detect_drop: gid %u, sid %u, %s\n", otn->sigInfo.generator, otn->sigInfo.id, getPktTraceActMsg()));
 1350     else addPktTraceData(VERDICT_REASON_SNORT, 0);
 1351     return 1;
 1352 }
 1353 
 1354 int SDropAction(Packet * p, OptTreeNode * otn, Event * event)
 1355 {
 1356     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
 1357                "        <!!> Dropping without Alerting! \"%s\"\n",
 1358                otn->sigInfo.message););
 1359 
 1360     // Let's silently drop the packet
 1361     Active_DropSession(p);
 1362     if (pkt_trace_enabled)
 1363         addPktTraceData(VERDICT_REASON_SNORT, snprintf(trace_line, MAX_TRACE_LINE,
 1364             "Snort detect_sdrop: gid %u, sid %u, %s\n", otn->sigInfo.generator, otn->sigInfo.id, getPktTraceActMsg()));
 1365     else addPktTraceData(VERDICT_REASON_SNORT, 0);
 1366     return 1;
 1367 }
 1368 
 1369 int LogAction(Packet * p, OptTreeNode * otn, RuleTreeNode * rtn, Event * event)
 1370 {
 1371     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,"   => Logging packet data and returning...\n"););
 1372 
 1373     CallLogFuncs(p, otn->sigInfo.message, rtn->listhead, event);
 1374 
 1375 #ifdef BENCHMARK
 1376     printf("        <!!> Check count = %d\n", check_count);
 1377     check_count = 0;
 1378     printf(" **** cmpcount: %d **** \n", cmpcount);
 1379 #endif
 1380 
 1381     return 1;
 1382 }
 1383 
 1384 /* end of rule action functions */
 1385