Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

fpdetect.c

Go to the documentation of this file.
00001 /*
00002 **  $Id$
00003 **
00004 **  fpdetect.c
00005 **
00006 **  Copyright (C) 2002-2005 Sourcefire,Inc
00007 **  Author(s):  Dan Roelker <droelker@sourcefire.com>
00008 **              Marc Norton <mnorton@sourcefire.com>
00009 **              Andrew R. Baker <andrewb@snort.org>
00010 **              Andrew J. Mullican <amullican@sourcefire.com>
00011 **              Steven Sturges <ssturges@sourcefire.com>
00012 **  NOTES
00013 **  5.15.02 - Initial Source Code. Norton/Roelker
00014 **  2002-12-06 - Modify event selection logic to fix broken custom rule types
00015 **               arbitrary rule type ordering (ARB)
00016 **  2005-02-08 - Track alerts per session so that they aren't double reported
00017 **               for rebuilt packets.  AJM.
00018 **  2005-02-17 - Track alerts per IP frag tracker so that they aren't double
00019 **               reported for rebuilt frags.  SAS (code similar to AJM's for
00020 **               per session tracking).
00021 **
00022 **
00023 **  This program is free software; you can redistribute it and/or modify
00024 **  it under the terms of the GNU General Public License as published by
00025 **  the Free Software Foundation; either version 2 of the License, or
00026 **  (at your option) any later version.
00027 **
00028 **  This program is distributed in the hope that it will be useful,
00029 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
00030 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00031 **  GNU General Public License for more details.
00032 **
00033 **  You should have received a copy of the GNU General Public License
00034 **  along with this program; if not, write to the Free Software
00035 **  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00036 **
00037 */
00038 #include "snort.h"
00039 #include "detect.h"
00040 #include "debug.h"
00041 #include "util.h"
00042 #include "tag.h"
00043 #include "rules.h"
00044 #include "pcrm.h"
00045 #include "fpcreate.h"
00046 #include "fpdetect.h"
00047 #include "mpse.h"
00048 #include "bitop.h"
00049 #include "perf-event.h"
00050 #include "sfthreshold.h"
00051 #include "event_queue.h"
00052 #include "inline.h"
00053 
00054 #include "sp_pattern_match.h"
00055 #include "spp_frag3.h"
00056 
00057 /*
00058 **  This define is for the number of unique events
00059 **  to match before choosing which event to log.
00060 **  (Since we can only log one.) This define is the limit.
00061 */
00062 #define MAX_EVENT_MATCH 100 
00063 
00064 /*
00065 **  This define enables set-wise signature detection for
00066 **  IP and ICMP packets.  During early testing, the old
00067 **  method of detection seemed faster for ICMP and IP 
00068 **  signatures, but with modifications to the set-wise engine
00069 **  performance became much better.  This define could be
00070 **  taken out, but is still in for regression testing.
00071 */
00072 #define FPSW
00073 
00074 /*
00075 **  GLOBALS
00076 **  These variables are local to this file and deal with
00077 **  configuration issues that are set in snort.conf through
00078 **  variables.
00079 */
00080 
00081 /*
00082 **  This structure holds the configuration options for the
00083 **  detection engine.  It is set by the functioncall:
00084 **  fpSetDetectionOptions() which passes a pointer.
00085 */
00086 static FPDETECT *fpDetect;
00087 
00088 /*
00089 **  Assorted global variables from the old detection engine
00090 **  for backwards compatibility.
00091 */
00092 extern PV          pv;  /* program vars (command line args) */
00093 extern int         active_dynamic_nodes;
00094 extern u_int16_t   event_id;
00095 extern char        check_tags_flag;
00096 extern OptTreeNode *otn_tmp;
00097 extern u_int8_t    DecodeBuffer[DECODE_BLEN];
00098 
00099 /*              
00100 **  MATCH_INFO
00101 **  The events that are matched get held in this structure,
00102 **  and iMatchIndex gets set to the event that holds the
00103 **  highest priority.
00104 */
00105 typedef struct {
00106 
00107  OTNX *MatchArray[MAX_EVENT_MATCH];
00108  int  iMatchCount;
00109  int  iMatchIndex;
00110  int  iMatchMaxLen;
00111  
00112 }MATCH_INFO;
00113 
00114 /*
00115 **  OTNX_MATCH_DATA
00116 **  This structure holds information that is
00117 **  referenced during setwise pattern matches.
00118 **  It also contains information regarding the
00119 **  number of matches that have occurred and
00120 **  the event to log based on the event comparison
00121 **  function.
00122 */
00123 typedef struct 
00124 {
00125     PORT_GROUP * pg;
00126     Packet * p;
00127     int check_ports;
00128 
00129     MATCH_INFO *matchInfo;
00130     int iMatchInfoArraySize;
00131 } OTNX_MATCH_DATA;
00132 
00133 /*
00134 **  Static function prototypes
00135 */
00136 static INLINE int fpEvalOTN(OptTreeNode *List, Packet *p);
00137 static INLINE int fpEvalRTN(RuleTreeNode *rtn,Packet *p, int check_ports);
00138 static INLINE int fpEvalHeader(PORT_GROUP *port_group, Packet *p, 
00139         int check_ports);
00140 static INLINE int fpEvalRTNSW(RuleTreeNode *rtn, OptTreeNode *otn, Packet *p, 
00141         int check_ports);
00142 static INLINE int fpEvalHeaderIp(Packet *p, int ip_proto);
00143 static INLINE int fpEvalHeaderIcmp(Packet *p);
00144 static INLINE int fpEvalHeaderTcp(Packet *p);
00145 static INLINE int fpEvalHeaderUdp(Packet *p);
00146 static INLINE int fpEvalHeaderSW(PORT_GROUP *port_group, Packet *p, 
00147         int check_ports);
00148 static int otnx_match (void* id, int index, void * data );               
00149 static INLINE int fpAddMatch( OTNX_MATCH_DATA *omd, OTNX *otnx, int pLen );
00150 static INLINE int fpAddSessionAlert(Packet *p, OTNX *otnx);
00151 static INLINE int fpSessionAlerted(Packet *p, OTNX *otnx);
00152         
00153 //static INLINE int fpLogEvent(RuleTreeNode *rtn, OptTreeNode *otn, Packet *p);
00154 
00155 extern u_int8_t *doe_ptr;
00156 
00157 static OTNX_MATCH_DATA omd;
00158 
00159 /* initialize the global OTNX_MATCH_DATA variable */
00160 int OtnXMatchDataInitialize()
00161 {
00162     omd.iMatchInfoArraySize = pv.num_rule_types;
00163     if(!(omd.matchInfo = calloc(omd.iMatchInfoArraySize, 
00164                     sizeof(MATCH_INFO))))
00165     {
00166         FatalError("Out of memory initializing detection engine\n");
00167     }
00168 
00169     return 0;
00170 }
00171     
00172 /*
00173 **  NAME
00174 **    fpSetDetectionOptions::
00175 **
00176 **  DESCRIPTION
00177 **    This function passes a pointer for us to set.  This pointer
00178 **    contains the detection configuration options.  We use these for 
00179 **    various optimizations.
00180 **
00181 **  FORMAL INPUTS
00182 **    FPDETECT * - the address of the configuration structure to pass
00183 **
00184 **  FORMAL OUTPUTS
00185 **    int - 0 is successful, failure code if otherwise.
00186 **
00187 */
00188 int fpSetDetectionOptions(FPDETECT *detect_options)
00189 {
00190     fpDetect = detect_options;
00191     return 0;
00192 }
00193 
00194 /*
00195 **
00196 **  NAME
00197 **    fpLogEvent::
00198 **
00199 **  DESCRIPTION
00200 **    This function takes the corresponding RTN and OTN for a snort rule
00201 **    and logs the event and packet that was alerted upon.  This 
00202 **    function was pulled out of fpEvalSomething, so now we can log an
00203 **    event no matter where we are.
00204 **
00205 **  FORMAL INPUTS
00206 **    RuleTreeNode * - rtn for snort rule
00207 **    OptTreeNode  * - otn for snort rule
00208 **    Packet       * - packet that iliicited event.
00209 */
00210 int fpLogEvent(RuleTreeNode *rtn, OptTreeNode *otn, Packet *p)
00211 {
00212     DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00213                 "   => Got rule match, rtn type = %d\n",
00214                 rtn->type););
00215 
00216     if(p->packet_flags & PKT_STREAM_UNEST_UNI &&
00217             pv.assurance_mode == ASSURE_EST &&
00218             (!(p->packet_flags & PKT_REBUILT_STREAM)) &&
00219             otn->stateless == 0)
00220     {
00221         return 1;
00222     }
00223         
00224     /*
00225      *  Perform Thresholding Tests - also done in
00226      * detect.c/CallLogFuncs & CallAlertFuncs
00227      */
00228     if(p->iph)
00229     {
00230         if( !sfthreshold_test( otn->event_data.sig_generator,
00231                                otn->event_data.sig_id,
00232                                p->iph->ip_src.s_addr,
00233                                p->iph->ip_dst.s_addr,
00234                                p->pkth->ts.tv_sec) )
00235         {
00236             /*
00237             **  If InlineMode is on, then we still want to drop packets
00238             **  that are drop rules.  We just don't want to see the alert.
00239             */
00240             if(InlineMode())
00241             {
00242                 if(rtn->type == RULE_DROP || rtn->type == RULE_SDROP)
00243                     InlineDrop();
00244             }
00245             
00246             return 1; /* Don't log it ! */
00247         }
00248     }
00249     else
00250     {
00251         if( !sfthreshold_test( otn->event_data.sig_generator,
00252                                otn->event_data.sig_id,
00253                                0,
00254                                0,
00255                                p->pkth->ts.tv_sec ) )
00256         {
00257             /*
00258             **  If InlineMode is on, then we still want to drop packets
00259             **  that are drop rules.  We just don't want to see the alert.
00260             */
00261             if(InlineMode())
00262             {
00263                 if(rtn->type == RULE_DROP || rtn->type == RULE_SDROP)
00264                     InlineDrop();
00265             }
00266 
00267             return 1; /* Don't log it ! */
00268         }
00269     }
00270 
00271     /*
00272     **  Set the ref_time to 0 so we make the logging work right.
00273     */
00274     otn->event_data.ref_time.tv_sec = 0;
00275     
00276     /*
00277     **  Set otn_tmp because log.c uses it to log details
00278     **  of the event.  Maybe we should look into making this
00279     **  part of the log routines and not a global variable.
00280     **  This way we could support multiple events per packet.
00281     */
00282     otn_tmp = otn;
00283 
00284     event_id++;
00285 
00286     TriggerResponses(p, otn);
00287 
00288     switch(rtn->type)
00289     {
00290         case RULE_PASS:
00291             PassAction();
00292             break;
00293 
00294         case RULE_ACTIVATE:
00295             ActivateAction(p, otn, &otn->event_data);
00296             break;
00297 
00298         case RULE_ALERT:
00299             AlertAction(p, otn, &otn->event_data);
00300             break;
00301 
00302         case RULE_DYNAMIC:
00303             DynamicAction(p, otn, &otn->event_data);
00304             break;
00305 
00306         case RULE_LOG:
00307             LogAction(p, otn, &otn->event_data);
00308             break;
00309 
00310         case RULE_DROP:
00311             DropAction(p, otn, &otn->event_data);
00312             break;
00313 
00314 #ifdef GIDS
00315         case RULE_SDROP:
00316             SDropAction(p, otn, &otn->event_data);
00317             break;
00318 
00319         case RULE_REJECT:
00320             RejectAction(p, otn, &otn->event_data);
00321             break;
00322 
00323         case RULE_REJECTBOTH:
00324             RejectBothAction(p, otn, &otn->event_data);
00325             break;
00326 
00327         case RULE_REJECTSRC:
00328             RejectSrcAction(p, otn, &otn->event_data);
00329             break;
00330 
00331         case RULE_REJECTDST:
00332             RejectDstAction(p, otn, &otn->event_data);
00333             break;
00334 
00335 #ifdef IPFW
00336         case RULE_REINJECT:
00337             ReinjectAction(p, otn, &otn->event_data);
00338             break;
00339 #endif /* IPFW */
00340 #endif /* GIDS */
00341     }
00342 
00343     SetTags(p, otn, event_id);
00344 
00345     if(rtn->type != RULE_PASS)
00346     {
00347         check_tags_flag = 0;
00348     }
00349 
00350     return 0;
00351 }
00352 
00353 /*
00354 **
00355 **  NAME
00356 **    InitMatchInfo::
00357 **
00358 **  DESCRIPTION
00359 **    Initialize the OTNX_MATCH_DATA structure.  We do this for
00360 **    every packet so calloc is not used as this would zero the
00361 **    whole space and this only sets the necessary counters to
00362 **    zero, and saves us time.
00363 **
00364 **  FORMAL INPUTS
00365 **    OTNX_MATCH_DATA * - pointer to structure to init.
00366 **
00367 **  FORMAL OUTPUT
00368 **    None
00369 **
00370 */
00371 static INLINE void InitMatchInfo(OTNX_MATCH_DATA *o)
00372 {
00373     int i = 0;
00374 
00375     for(i = 0; i < o->iMatchInfoArraySize; i++)
00376     {
00377         o->matchInfo[i].iMatchCount  = 0;
00378         o->matchInfo[i].iMatchIndex  = 0;
00379         o->matchInfo[i].iMatchMaxLen = 0;
00380     }
00381 }
00382 
00383 /*
00384 **
00385 **  NAME
00386 **    fpAddMatch::
00387 **
00388 **  DESCRIPTION
00389 **    Add and Event to the appropriate Match Queue: Alert, Pass, or Log.
00390 **    This allows us to find multiple events per packet and pick the 'best'
00391 **    one.  This function also allows us to change the order of alert,
00392 **    pass, and log signatures by cacheing them for decision later.
00393 **
00394 **    IMPORTANT NOTE:
00395 **    fpAddMatch must be called even when the queue has been maxed
00396 **    out.  This is because there are three different queues (alert,
00397 **    pass, log) and unless all three are filled (or at least the 
00398 **    queue that is in the highest priority), events must be looked
00399 **    at to see if they are members of a queue that is not maxed out.
00400 **
00401 **  FORMAL INPUTS
00402 **    OTNX_MATCH_DATA    * - the omd to add the event to.
00403 **    OTNX               * - the otnx to add.
00404 **    int pLen             - length of pattern that matched, 0 for no content
00405 **
00406 **  FORMAL OUTPUTS
00407 **    int - 1 max_events variable hit, 0 successful.
00408 **
00409 */
00410 static INLINE int fpAddMatch(OTNX_MATCH_DATA *omd, OTNX *otnx, int pLen )
00411 {
00412     MATCH_INFO * pmi;
00413     int evalIndex;
00414 
00415     evalIndex = otnx->otn->rtn->listhead->ruleListNode->evalIndex;
00416     
00417     pmi = &omd->matchInfo[evalIndex];
00418 
00419     /*
00420     **  If we hit the max number of unique events for any rule type alert,
00421     **  log or pass, then we don't add it to the list.
00422     */
00423     if( pmi->iMatchCount == fpDetect->max_queue_events || 
00424         pmi->iMatchCount == MAX_EVENT_MATCH)
00425     {
00426         return 1;
00427     }
00428 
00429     /*
00430     **  Add the event to the appropriate list
00431     */
00432     pmi->MatchArray[ pmi->iMatchCount ] = otnx;
00433 
00434     /*
00435     **  This means that we are adding a NC rule
00436     **  and we only set the index to this rule
00437     **  if there is no content rules in the
00438     **  same array.
00439     */
00440     if(pLen > 0)
00441     {
00442         /*
00443         **  Event Comparison Function
00444         **  Here the largest content match is the
00445         **  priority
00446         */
00447         if( pmi->iMatchMaxLen < pLen )
00448         {
00449             pmi->iMatchMaxLen = pLen;
00450             pmi->iMatchIndex  = pmi->iMatchCount;
00451         }
00452     }
00453 
00454     pmi->iMatchCount++;
00455   
00456     return 0;
00457 }
00458 
00459 /*
00460 **
00461 **  NAME
00462 **    fpEvalOTN::
00463 **
00464 **  DESCRIPTION
00465 **    Evaluates an OTN against a Packet.
00466 **
00467 **  FORMAL INPUTS
00468 **    OptTreeNode * - the OTN to check
00469 **    Packet *      - Packet to evaluate against OTN
00470 **
00471 **  FORMAL OUTPUT
00472 **    int - 0 if no match, 1 if match.
00473 **
00474 */
00475 static INLINE int fpEvalOTN(OptTreeNode *List, Packet *p)
00476 {
00477     Session *ssn;
00478 
00479     if(List == NULL)
00480         return 0;
00481 
00482     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   => Checking SID %d\n",
00483                List->sigInfo.id););
00484 
00485     if(List->type == RULE_DYNAMIC && !List->active_flag)
00486     {
00487         return 0;
00488     }
00489 
00490     if(List->opt_func == NULL)
00491     {
00492         FatalError("List->opt_func was NULL on option #%d!\n", 
00493                 List->chain_node_number);
00494     }
00495 
00496     if(snort_runtime.capabilities.stateful_inspection == 1)
00497     {
00498         if((List->established == 1) && !(p->packet_flags & PKT_STREAM_EST))
00499         {
00500             /*
00501             **  We check to see if this packet may have been picked up in
00502             **  midstream by stream4 on a timed out session.  If it was, then
00503             **  we'll go ahead and inspect it anyway because it might be a 
00504             **  packet that we dropped but the attacker has retransmitted after
00505             **  the stream4 session timed out.
00506             */
00507             if(InlineMode())
00508             {
00509                 switch(List->rtn->type)
00510                 {
00511                     case RULE_DROP:
00512                     case RULE_SDROP:
00513                         
00514                         ssn = (Session *)p->ssnptr;
00515                         if(ssn && !(ssn->session_flags & SSNFLAG_MIDSTREAM))
00516                         {
00517                             return 0;
00518                         }
00519                         break;
00520 
00521                     default:
00522                         return 0;
00523                 }
00524             }
00525             else
00526             {
00527                 /* 
00528                 ** This OTN requires an established connection and it isn't
00529                 ** in that state yet, so continue to the next OTN
00530                 */
00531                 return 0;
00532             }
00533         }
00534         else if((List->unestablished == 1) && (p->packet_flags & PKT_STREAM_EST))
00535         {
00536             /*
00537             **  We're looking for an unestablished stream, and this is
00538             **  established, so don't continue processing.
00539             */
00540             return 0;
00541         }
00542     }
00543 
00544     if(!List->opt_func->OptTestFunc(p, List, List->opt_func))
00545     {
00546         return 0;
00547     }
00548             
00549     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00550              "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"););
00551     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   => SID %d OTN Matched!\n",
00552                 List->sigInfo.id););
00553     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00554             "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"););
00555     /* 
00556     ** Rule match actions are called from EvalHeader. 
00557     */
00558     return 1;
00559 }
00560 
00561 /*
00562 **
00563 **  NAME
00564 **    fpEvalRTN::
00565 **
00566 **  DESCRIPTION
00567 **    Evaluates an RTN against a packet.  We can probably get rid of
00568 **    the check_ports variable, but it's in there for good luck.  :)
00569 **
00570 **  FORMAL INPUTS
00571 **    RuleTreeNode * - RTN to check packet against.
00572 **    Packet       * - Packet to evaluate
00573 **    int            - whether to do a quick enhancement against ports.
00574 **
00575 **  FORMAL OUTPUT
00576 **    int - 1 if match, 0 if match failed.
00577 **
00578 */
00579 static INLINE int fpEvalRTN(RuleTreeNode *rtn, Packet *p, int check_ports)
00580 {
00581     if(rtn == NULL)
00582     {
00583         return 0;
00584     }
00585 
00586     /*
00587     **  This used to be a speed improvement.  Might still be.
00588     */
00589     if(check_ports)
00590     {
00591         if(!(rtn->flags & EXCEPT_DST_PORT) && !(rtn->flags & BIDIRECTIONAL) &&
00592                 (p->dp < rtn->ldp))
00593         {
00594             return 0;
00595         }
00596     }
00597 
00598     if(rtn->type == RULE_DYNAMIC)
00599     {
00600         if(!active_dynamic_nodes)
00601         {
00602             return 0;
00603         }
00604 
00605         if(rtn->active_flag == 0)
00606         {
00607             return 0;
00608         }
00609     }
00610 
00611     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "[*] Rule Head %d\n", 
00612                 rtn->head_node_number);)
00613 
00614     if(!rtn->rule_func->RuleHeadFunc(p, rtn, rtn->rule_func))
00615     {
00616         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00617                     "   => Header check failed, checking next node\n"););
00618         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00619                     "   => returned from next node check\n"););
00620         return 0;
00621     }
00622 
00623     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00624              "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"););
00625     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   => RTN %d Matched!\n",
00626                 rtn->head_node_number););
00627     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00628             "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"););
00629     /*
00630     **  Return that there is a rule match and log the event outside
00631     **  of this routine.
00632     */
00633     return 1;
00634 }
00635 
00636 /*
00637 **  NAME
00638 **    fpEvalRTNSW::
00639 **
00640 **  DESCRIPTION
00641 **    This function checks the RTN for validation first and then checks the
00642 **    OTN for a pattern match.
00643 **  
00644 **  FORMAL INPUTS
00645 **    RuleTreeNode * - rtn to inspect packet against
00646 **    OptTreeNode *  - otn to inspect packet against
00647 **    Packet *       - packet to inspect against
00648 **    int            - whether to check ports for this packet
00649 **
00650 **  FORMAL OUTPUTS
00651 **    int - 1 is successful match
00652 **          0 is no match
00653 **
00654 */
00655 static INLINE int fpEvalRTNSW(RuleTreeNode *rtn, OptTreeNode *otn, Packet *p, int check_ports)
00656 {
00657     /*
00658     **  This is set to one, because we already have
00659     **  an OTN hit.
00660     */
00661     int rule_match = 0;
00662 
00663     /*
00664     **  Reset the last match offset for each OTN we touch... 
00665     */
00666     doe_ptr = NULL;
00667 
00668 
00669     if(rtn == NULL)
00670     {
00671         return 0;
00672     }
00673 
00674     /*
00675     **  Used to be a speed optimization.  Might still be.
00676     */
00677     if(check_ports)
00678     {
00679         if(!(rtn->flags & EXCEPT_DST_PORT) && !(rtn->flags & BIDIRECTIONAL) &&
00680                 (p->dp < rtn->ldp))
00681         {
00682             return 0;
00683         }
00684     }
00685 
00686     if(rtn->type == RULE_DYNAMIC)
00687     {
00688         if(!active_dynamic_nodes)
00689         {
00690             return 0;
00691         }
00692 
00693         if(rtn->active_flag == 0)
00694         {
00695             return 0;
00696         }
00697     }
00698 
00699     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "[*] Rule Head %d\n", 
00700                 rtn->head_node_number);)
00701 
00702     if(!rtn->rule_func->RuleHeadFunc(p, rtn, rtn->rule_func))
00703     {
00704         DEBUG_WRAP(DebugMessage(DEBUG_DETECT,
00705                     "   => Header check failed, checking next node\n"););
00706         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00707                     "   => returned from next node check\n"););
00708         return 0;
00709     }
00710 
00711     /*
00712     **  RTN is validated, now check the OTN.
00713     */
00714     rule_match = fpEvalOTN(otn, p);
00715 
00716     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00717              "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"););
00718     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, "   => RTN %d Matched!\n",
00719                 rtn->head_node_number););
00720     DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00721             "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"););
00722     return rule_match;
00723 }
00724 
00725 /*
00726 **
00727 **  NAME
00728 **    otnx_match::
00729 **
00730 **  DESCRIPTION
00731 **    When the pattern matcher finds a match, this routine
00732 **    is processed.  The match is checked to see whether the
00733 **    associated otn and rtn have already been validated for
00734 **    this packet, and if so does not do the check again.
00735 **    Otherwise, the otn/rtn validation occurs.
00736 **
00737 **  FORMAL INPUTS
00738 **
00739 **    unsigned  id              : users first handle/ptr-whatever to this pattern
00740 **    unsigned  id2             : users 2nd data 
00741 **    int index                 : index in packet data
00742 **    void *data                : user data passed in when pattern was loaded
00743 **
00744 **  FORMAL OUTPUT
00745 **    int 0 - continue processing
00746 **        1 - stop processing this packet for patterns
00747 **
00748 */
00749 static int otnx_match( void * id, int index, void * data)
00750 {
00751     OTNX_MATCH_DATA  *omd    = (OTNX_MATCH_DATA *)data;
00752     PMX              *pmx    = (PMX*)id;
00753     RULE_NODE        *rnNode = (RULE_NODE*)(pmx->RuleNode);
00754 
00755     OTNX             *otnx   = (OTNX*)(rnNode->rnRuleData);
00756     PatternMatchData *pmd    = (PatternMatchData*)pmx->PatternMatchData;
00757 
00758     /*
00759     **  This is where we check the RULE_NODE ID for
00760     **  previous hits.
00761     */
00762     if(boIsBitSet(&(omd->pg->boRuleNodeID), rnNode->iRuleNodeID))
00763     {
00764         return 0;
00765     }
00766 
00767     if( fpEvalRTNSW(otnx->rtn, otnx->otn, omd->p, omd->check_ports) )
00768     {
00769         /*
00770         **  We have a qualified event
00771         */
00772         omd->pg->pgQEvents++;
00773         UpdateQEvents();
00774 
00775         DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
00776                 "[**] SID %d added to event queue [**]\n", 
00777                 otnx->otn->sigInfo.id););
00778 
00779         fpAddMatch(omd, otnx, pmd->pattern_size );
00780     }
00781     else
00782     {
00783         /*
00784         ** This means that the event is non-qualified.
00785         */
00786         omd->pg->pgNQEvents++;
00787         UpdateNQEvents();
00788     }
00789      
00790     /*
00791     **  Here is where we set the bit array for each RULE_NODE that
00792     **  we hit.
00793     */
00794     if(boSetBit(&(omd->pg->boRuleNodeID), rnNode->iRuleNodeID))
00795     {
00796         /*
00797         **  There was an error, don't do anything right now.
00798         */
00799     }   
00800 
00801     return 0;
00802 }
00803 
00804 /*
00805 **
00806 **  NAME
00807 **    fpFinalSelectEvent::
00808 **
00809 **  DESCRIPTION
00810 **    fpFinalSelectEvent is called at the end of packet processing
00811 **    to decide, if there hasn't already been a selection, to decide
00812 **    what event to select.  This function is different from 
00813 **    fpSelectEvent by the fact that fpSelectEvent only selects an
00814 **    event if it is the first priority setting (pass or alert).
00815 **
00816 **    We also loop through the events we log, so that we don't log the
00817 **    same event twice.  This can happen with unique conflicts some
00818 **    of the time.
00819 **
00820 **    IMPORTANT NOTE:
00821 **    We call fpFinalSelectEvent() after all processing of the packet
00822 **    has been completed.  The reason this must be called afterwards is
00823 **    because of unique rule group conflicts for a packet.  If there is
00824 **    a unique conflict, then we inspect both rule groups and do the final
00825 **    event select after both rule groups have been inspected.  The
00826 **    problem came up with bi-directional rules with pass rule ordering
00827 **    as the first type of rule.  Before we would detect a alert rule in
00828 **    the first rule group, and since there was no pass rules we would
00829 **    log that alert rule.  However, if we had inspected the second rule
00830 **    group, we would have found a pass rule and that should have taken
00831 **    precedence.  We now inspect both rule groups before doing a final
00832 **    event select.
00833 **
00834 **  FORMAL INPUTS
00835 **    OTNX_MATCH_DATA * - omd to select event from.
00836 **    Packet *          - pointer to packet to log.
00837 **
00838 **  FORMAL OUTPUT
00839 **    int - return 0 if no match, 1 if match.
00840 **   
00841 */
00842 static INLINE int fpFinalSelectEvent(OTNX_MATCH_DATA *o, Packet *p)
00843 {
00844     int i;
00845     int j;
00846     int k;
00847     OTNX *otnx;
00848     Session *ssn = p->ssnptr;
00849 
00850     for(i = 0; i < o->iMatchInfoArraySize; i++)
00851     {
00852         if(o->matchInfo[i].iMatchCount)
00853         {
00854             for(j=0; j < o->matchInfo[i].iMatchCount; j++)
00855             {
00856                 otnx = o->matchInfo[i].MatchArray[j];
00857 
00858                 /*
00859                 **  Loop here so we don't log the same event
00860                 **  multiple times.
00861                 */
00862                 for(k = 0; k < j; k++)
00863                 {
00864                     if(o->matchInfo[i].MatchArray[k] == otnx)
00865                     {
00866                         otnx = NULL; 
00867                         break;
00868                     }
00869                 }
00870 
00871                 if(otnx && otnx->otn && !fpSessionAlerted(p, otnx) &&
00872                    !fpFragAlerted(p, otnx))
00873                 {
00874                     /*
00875                     **  QueueEvent
00876                     */
00877                     SnortEventqAdd(otnx->otn->sigInfo.generator, 
00878                                    otnx->otn->sigInfo.id,
00879                                    otnx->otn->sigInfo.rev,
00880                                    otnx->otn->sigInfo.class_id,
00881                                    otnx->otn->sigInfo.priority,
00882                                    otnx->otn->sigInfo.message,
00883                                    (void *)otnx);
00884                 }
00885                 
00886                 if ( ssn )
00887                 {                     
00888                     fpAddSessionAlert(p, otnx);
00889                 }
00890 
00891                 if ( p->fragtracker )
00892                 {
00893                     fpAddFragAlert(p, otnx);
00894                 }
00895             }
00896 
00897             return 1;
00898         }
00899     }
00900 
00901     return 0;
00902 }
00903 
00904 /*
00905 **  
00906 **  NAME
00907 **    fpAddSessionAlert::
00908 **
00909 **  DESCRIPTION
00910 **    This function flags an alert per session.
00911 **
00912 **  FORMAL INPUTS
00913 **    Packet *     - the packet to inspect
00914 **    OTNX *       - the rule that generated the alert
00915 **
00916 **  FORMAL OUTPUTS
00917 **    int - 0 if not flagged
00918 **          1 if flagged
00919 **
00920 */
00921 static INLINE int fpAddSessionAlert(Packet *p, OTNX *otnx)
00922 {
00923     Session *ssn = p->ssnptr;
00924 
00925     if ( !ssn )
00926         return 0;
00927 
00928     if ( !otnx )
00929         return 0;
00930 
00931     if ( !otnx->otn )
00932         return 0;
00933 
00934     /* Only track a certain number of alerts per session */
00935     if ( ssn->alert_count >= MAX_SESSION_ALERTS )
00936         return 0;
00937 
00938     ssn->alert_gid[ssn->alert_count] = otnx->otn->sigInfo.generator;
00939     ssn->alert_sid[ssn->alert_count] = otnx->otn->sigInfo.id;
00940     ssn->alert_count++;
00941 
00942     return 1;
00943 }
00944 
00945 /*
00946 **  
00947 **  NAME
00948 **    fpSessionAlerted::
00949 **
00950 **  DESCRIPTION
00951 **    This function indicates whether or not an alert has been generated previously
00952 **    in this session, but only if this is a rebuilt packet.
00953 **
00954 **  FORMAL INPUTS
00955 **    Packet *     - the packet to inspect
00956 **    OTNX *       - the rule that generated the alert
00957 **
00958 **  FORMAL OUTPUTS
00959 **    int - 0 if alert NOT previously generated
00960 **          1 if alert previously generated
00961 **
00962 */
00963 static INLINE int fpSessionAlerted(Packet *p, OTNX *otnx)
00964 {
00965     Session *ssn = p->ssnptr;
00966     SigInfo *si = &otnx->otn->sigInfo;
00967     int      i;
00968 
00969     if ( !ssn )
00970         return 0;
00971 
00972     for ( i = 0; i < ssn->alert_count; i++ )
00973     {
00974         /*  If this is a rebuilt packet and we've seen this alert before, return
00975          *  that we have previously alerted on a non-rebuilt packet.
00976          */
00977         if ( (p->packet_flags & PKT_REBUILT_STREAM)
00978                 && ssn->alert_gid[i] == si->generator && ssn->alert_sid[i] == si->id )
00979         {
00980             return 1;
00981         }
00982     }
00983 
00984     return 0;
00985 }
00986 
00987 
00988 /*
00989 **  fpEvalHeader::
00990 **
00991 **  This function is the old way of walking PORT_GROUPs.  We
00992 **  check the OTNs for matches and then check the RTN for
00993 **  validation if the OTN matches.
00994 **  Kept for backwards-compatibility
00995 */
00996 static INLINE int fpEvalHeader(PORT_GROUP *port_group, Packet *p, int check_ports)
00997 {
00998     RULE_NODE *rnWalk;
00999     OTNX *otnxWalk;
01000 
01001     /*
01002     **  Walk the content OTNs
01003     */
01004     for(rnWalk = port_group->pgHead; rnWalk; rnWalk = rnWalk->rnNext)
01005     {
01006         /*
01007         **  Reset the last match offset for each OTN we touch... 
01008         */
01009         doe_ptr = NULL;
01010         
01011         otnxWalk = (OTNX *)rnWalk->rnRuleData;
01012         /*
01013         **  Do the OTN check, if successful than we check
01014         **  the RTN for validation purposes.
01015         */
01016         if(fpEvalOTN(otnxWalk->otn, p))
01017         {
01018             /*
01019             **  OTN is match, check RTN
01020             */
01021             if(fpEvalRTN(otnxWalk->rtn, p, check_ports))
01022             {
01023                 fpLogEvent(otnxWalk->rtn, otnxWalk->otn, p);
01024                 return 1;
01025             }
01026             
01027             continue;
01028         }
01029     }
01030 
01031     /*
01032     **  Walk the non-content OTNs
01033     */
01034     for(rnWalk = port_group->pgHeadNC; rnWalk; rnWalk = rnWalk->rnNext)
01035     {
01036         /*
01037         **  Reset the last match offset for each OTN we touch... 
01038         */
01039         doe_ptr = NULL;
01040 
01041         otnxWalk = (OTNX *)rnWalk->rnRuleData;
01042         /*
01043         **  Do the OTN check, if successful than we check
01044         **  the RTN for validation purposes.
01045         */
01046         if(fpEvalOTN(otnxWalk->otn, p))
01047         {
01048             /*
01049             **  OTN is match, check RTN
01050             */
01051             if(fpEvalRTN(otnxWalk->rtn, p, check_ports))
01052             {
01053                 fpLogEvent(otnxWalk->rtn, otnxWalk->otn, p);
01054                 return 1;
01055             }
01056             
01057             continue;
01058         }
01059     }
01060 
01061     return 0;
01062 }
01063 
01064 /*
01065 **  
01066 **  NAME
01067 **    fpEvalHeaderSW::
01068 **
01069 **  DESCRIPTION
01070 **    This function does a set-wise match on content, and walks an otn list
01071 **    for non-content.  The otn list search will eventually be redone for 
01072 **    for performance purposes.
01073 **
01074 **  FORMAL INPUTS
01075 **    PORT_GROUP * - the port group to inspect
01076 **    Packet *     - the packet to inspect
01077 **    int          - whether src/dst ports should be checked (udp/tcp or icmp)
01078 **
01079 **  FORMAL OUTPUTS
01080 **    int - 0 for failed pattern match
01081 **          1 for sucessful pattern match
01082 **
01083 */
01084 static INLINE int fpEvalHeaderSW(PORT_GROUP *port_group, Packet *p, int check_ports)
01085 {
01086     RULE_NODE *rnWalk;
01087     OTNX *otnx = NULL;
01088     void * so;
01089     
01090     /* XXX it is not a good idea to allocate memory here */
01091  
01092     extern HttpUri  UriBufs[URI_COUNT]; /* decode.c */
01093 
01094     /*
01095     **  Init the info for rule ordering selection
01096     */
01097     //InitMatchInfo( &omd );
01098     
01099     /*
01100     **  PKT_STREAM_INSERT packets are being rebuilt and re-injected
01101     **  through this detection engine.  So in order to avoid pattern
01102     **  matching bytes twice, we wait until the PKT_STREAM_INSERT 
01103     **  packets are rebuilt and injected through the detection engine.
01104     **
01105     **  PROBLEM:
01106     **  If a stream gets stomped on before it gets re-injected, an attack
01107     **  would be missed.  So before a connection gets stomped, we 
01108     **  re-inject the stream we have.
01109     */
01110     if(fpDetect->inspect_stream_insert || 
01111        !(p->packet_flags & PKT_STREAM_INSERT))
01112     {
01113         /*
01114         **   Uri-Content Match
01115         **   This check indicates that http_decode found
01116         **   at least one uri
01117         */
01118         if( p->uri_count > 0)
01119         {
01120             int i;
01121             so = (void *)port_group->pgPatDataUri;
01122 
01123             if( so ) /* Do we have any URI rules ? */
01124             {
01125                 mpseSetRuleMask( so, &port_group->boRuleNodeID ); 
01126 
01127                 /*
01128                 **  Process all of the packet's URIs
01129                 */
01130                 for( i=0; i<p->uri_count; i++)
01131                 {
01132                     if(UriBufs[i].uri == NULL)
01133                         continue;
01134 
01135                     omd.pg = port_group;
01136                     omd.p  = p;
01137                     omd.check_ports= check_ports;
01138 
01139                     mpseSearch (so, UriBufs[i].uri, UriBufs[i].length, 
01140                          otnx_match, &omd);
01141                 }   
01142             }
01143         }
01144 
01145         /*
01146         **  If this is a pipeline request don't do the no-content
01147         **  rules since we already checked them during the
01148         **  first URI inspection.
01149         */
01150         if(UriBufs[0].decode_flags & HTTPURI_PIPELINE_REQ)
01151         {
01152             boResetBITOP(&(port_group->boRuleNodeID));
01153             return 0;
01154         }
01155 
01156         /*
01157         **  Decode Content Match
01158         **  We check to see if the packet has been normalized into
01159         **  the global (decode.c) DecodeBuffer.  Currently, only
01160         **  telnet normalization writes to this buffer.  So, if
01161         **  it is set, we do this the match against the normalized
01162         **  buffer and we do the check against the original 
01163         **  payload, in case any of the rules have the 
01164         **  'rawbytes' option.
01165         */
01166         so = (void *)port_group->pgPatData;
01167 
01168         if((p->packet_flags & PKT_ALT_DECODE) && so && p->alt_dsize) 
01169         {
01170             mpseSetRuleMask( so, &port_group->boRuleNodeID ); 
01171 
01172             omd.pg = port_group;
01173             omd.p = p;
01174             omd.check_ports= check_ports;
01175 
01176             mpseSearch ( so, DecodeBuffer, p->alt_dsize, 
01177                     otnx_match, &omd );
01178 
01179             /*
01180              **  The reason that we reset the bitops is because
01181              **  an OTN might not be verified using the DecodeBuffer
01182              **  because of the 'rawbytes' option, while the next pass
01183              **  will need to validate that same rule in the case
01184              **  of rawbytes.
01185              */
01186             boResetBITOP(&(port_group->boRuleNodeID));
01187         }
01188         
01189         /*
01190         **  Content-Match - If no Uri-Content matches, than do a Content search
01191         **
01192         **  NOTE:
01193         **    We may want to bail after the Content search if there
01194         **    has been a successful match.
01195         */
01196         if( so && p->data && p->dsize) 
01197         {
01198             mpseSetRuleMask( so, &port_group->boRuleNodeID ); 
01199 
01200             omd.pg = port_group;
01201             omd.p = p;
01202             omd.check_ports= check_ports;
01203 
01204             mpseSearch ( so, p->data, p->dsize, otnx_match, &omd );
01205         }
01206 
01207         boResetBITOP(&(port_group->boRuleNodeID));
01208     }
01209 
01210     /*
01211     **  PKT_REBUILT_STREAM packets are re-injected streams.  This means
01212     **  that the "packet headers" are completely bogus and only the 
01213     **  content matches are important.  So for PKT_REBUILT_STREAMs, we
01214     **  don't inspect against no-content OTNs since these deal with 
01215     **  packet headers, packet sizes, etc.
01216     **
01217     **  NOTE:
01218     **  This has been changed when evaluating no-content rules because
01219     **  it was interfering with the pass->alert ordering.  We still
01220     **  need to check no-contents against rebuilt packets, because of
01221     **  this problem.  Immediate solution is to have the detection plugins
01222     **  bail if the rule should only be inspected against packets, a.k.a
01223     **  dsize checks.
01224     */
01225 
01226     /*
01227     **  Walk and test the non-content OTNs
01228     */
01229     for(rnWalk = port_group->pgHeadNC; rnWalk; rnWalk = rnWalk->rnNext)
01230     {
01231         /*
01232         **  Reset the last match offset for each OTN we touch... 
01233         */
01234         doe_ptr = NULL;
01235 
01236         otnx = (OTNX *)rnWalk->rnRuleData;
01237         /*
01238         **  Do the OTN check, if successful than we check
01239         **  the RTN for validation purposes.
01240         */
01241         if(fpEvalOTN(otnx->otn, p))
01242         {
01243             /*
01244             *  OTN is match, check RTN
01245             */
01246             if(fpEvalRTN(otnx->rtn, p, check_ports))
01247             {
01248                 port_group->pgQEvents++;
01249                 UpdateQEvents();
01250 
01251                 /*
01252                 **  If the array if filled for this type
01253                 **  of event, then it wasn't added and there
01254                 **  is no reason to select the events again.
01255                 */
01256                 if( fpAddMatch(&omd, otnx, 0) )
01257                 {
01258                     continue;
01259                 }
01260             }
01261             else
01262             {
01263                 /*
01264                 **  This is a non-qualified event
01265                 */
01266                 port_group->pgNQEvents++;
01267                 UpdateNQEvents();
01268             }
01269 
01270             continue;
01271         }
01272     }
01273 
01274     return 0;
01275 }
01276 
01277 /*
01278 ** fpEvalHeaderUdp::
01279 */
01280 static INLINE int fpEvalHeaderUdp(Packet *p)
01281 {
01282     PORT_GROUP *src, *dst, *gen;
01283     int retval;
01284 
01285     retval = prmFindRuleGroupUdp(p->dp, p->sp, &src, &dst, &gen);
01286   
01287     switch(retval)
01288     {
01289         case 0:
01290             /* nothing */
01291             return 0;
01292         case 1:
01293             InitMatchInfo( &omd );
01294             
01295             /* destination groups */
01296             if(fpEvalHeaderSW(dst, p, 1))
01297             {
01298                 return 1;
01299             }
01300             break;
01301         case 2:
01302             InitMatchInfo( &omd );
01303             
01304             /*  source groups */
01305             if(fpEvalHeaderSW(src, p, 1))
01306             {
01307                 return 1;
01308             }
01309             break;
01310         case 3:
01311             InitMatchInfo( &omd );
01312             
01313             /*  both ports */
01314             if(fpEvalHeaderSW(dst, p, 1))
01315             {
01316                 return 1;
01317             }
01318             if(fpEvalHeaderSW(src, p, 1))
01319             {
01320                 return 1;
01321             }
01322             break;
01323         case 4:
01324             InitMatchInfo( &omd );
01325             
01326             /*  generic */
01327             if(fpEvalHeaderSW(gen, p, 1))
01328             {
01329                 return 1;
01330             }
01331             break;
01332         default:
01333             return 0;
01334     }
01335 
01336     return fpFinalSelectEvent(&omd, p);
01337 }
01338 
01339 /*
01340 **  fpEvalHeaderTcp::
01341 */
01342 static INLINE int fpEvalHeaderTcp(Packet *p)
01343 {
01344     PORT_GROUP *src, *dst, *gen;
01345     int retval;
01346 
01347     retval = prmFindRuleGroupTcp(p->dp, p->sp, &src, &dst, &gen);
01348  
01349     switch(retval)
01350     {
01351         case 0:
01352             /* nothing */
01353             return 0;
01354         case 1:
01355             InitMatchInfo( &omd );
01356             
01357             /* destination groups */
01358             if(fpEvalHeaderSW(dst, p, 1))
01359             {
01360                 return 1;
01361             }
01362             break;
01363         case 2:
01364             InitMatchInfo( &omd );
01365 
01366             /* source groups */
01367             if(fpEvalHeaderSW(src, p, 1))
01368             {
01369                 return 1;
01370             }
01371             break;
01372         case 3:
01373             InitMatchInfo( &omd );
01374 
01375             /*  both ports */
01376             if(fpEvalHeaderSW(dst, p, 1))
01377             {
01378                 return 1;
01379             }
01380             if(fpEvalHeaderSW(src, p, 1))
01381             {
01382                 return 1;
01383             }
01384             break;
01385         case 4:
01386             InitMatchInfo( &omd );
01387 
01388             /*  generic */
01389             if(fpEvalHeaderSW(gen, p, 1))
01390             {
01391                 return 1;
01392             }
01393             break;
01394         default:
01395             return 0;
01396     }
01397 
01398     return fpFinalSelectEvent(&omd, p);
01399 }
01400 
01401 /*
01402 **  fpEvalHeaderICMP::
01403 */
01404 static INLINE int fpEvalHeaderIcmp(Packet *p)
01405 {
01406     PORT_GROUP *gen, *type;
01407     int retval;
01408 
01409     retval = prmFindRuleGroupIcmp(p->icmph->type, &type, &gen);
01410  
01411     switch(retval)
01412     {
01413         case 0:
01414             return 0;
01415         case 1:
01416             InitMatchInfo( &omd );
01417             
01418             /* icmp type */
01419 #ifdef FPSW
01420             if(fpEvalHeaderSW(type, p, 0))
01421 #else
01422             if(fpEvalHeader(type, p, 0))
01423 #endif
01424             {
01425                 return 1;
01426             }
01427 
01428             break;
01429         case 2:
01430             return 0;
01431         case 3:
01432             return 0;
01433         case 4:
01434             InitMatchInfo( &omd );
01435             
01436             /*  generic */
01437 #ifdef FPSW
01438             if(fpEvalHeaderSW(gen, p, 0))
01439 #else
01440             if(fpEvalHeader(gen, p, 0))
01441 #endif
01442             {
01443                 return 1;
01444             }
01445 
01446             break;
01447         default:
01448             return 0;
01449     }
01450 
01451     return fpFinalSelectEvent(&omd, p);
01452 }
01453 
01454 /*
01455 **  fpEvalHeaderIP::
01456 */
01457 static INLINE int fpEvalHeaderIp(Packet *p, int ip_proto)
01458 {
01459     PORT_GROUP *gen, *ip_group;
01460     int retval;
01461 
01462     retval = prmFindRuleGroupIp(ip_proto, &ip_group, &gen);
01463  
01464     switch(retval)
01465     {
01466         case 0:
01467             return 0;
01468         case 1:
01469             InitMatchInfo( &omd );
01470             
01471             /* ip_group */
01472 #ifdef FPSW
01473             if(fpEvalHeaderSW(ip_group, p, 0))
01474 #else
01475             if(fpEvalHeader(ip_group, p, 0))
01476 #endif
01477             {
01478                 return 1;
01479             }
01480 
01481             break;
01482         case 2:
01483             return 0;
01484         case 3:
01485             return 0;
01486         case 4:
01487             InitMatchInfo( &omd );
01488             
01489             /* generic */
01490 #ifdef FPSW
01491             if(fpEvalHeaderSW(gen, p, 0))
01492 #else
01493             if(fpEvalHeader(gen, p, 0))
01494 #endif
01495             {
01496                 return 1;
01497             }
01498 
01499             break;
01500 
01501         default:
01502             return 0;
01503     }
01504 
01505     return fpFinalSelectEvent(&omd, p);
01506 }
01507 
01508 /*
01509 **
01510 **  NAME
01511 **    fpEvalPacket::
01512 **
01513 **  DESCRIPTION
01514 **    This function is the interface to the Detect() routine.  Here 
01515 **    the IP protocol is processed.  If it is TCP, UDP, or ICMP, we
01516 **    process the both that particular ruleset and the IP ruleset
01517 **    with in the fpEvalHeader for that protocol.  If the protocol
01518 **    is not TCP, UDP, or ICMP, we just process the packet against
01519 **    the IP rules at the end of the fpEvalPacket routine.  Since
01520 **    we are using a setwise methodology for snort rules, both the
01521 **    network layer rules and the transport layer rules are done
01522 **    at the same time.  While this is not the best for modularity,
01523 **    it is the best for performance, which is what we are working
01524 **    on currently.
01525 **
01526 **  FORMAL INPUTS
01527 **    Packet * - the packet to inspect
01528 **
01529 **  FORMAL OUTPUT
01530 **    int - 0 means that packet has been processed.
01531 **
01532 */
01533 int fpEvalPacket(Packet *p)
01534 {
01535     int ip_proto = p->iph->ip_proto;
01536 
01537     switch(ip_proto)
01538     {
01539         case IPPROTO_TCP:
01540             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
01541                         "Detecting on TcpList\n"););
01542 
01543             if(p->tcph == NULL)
01544             {
01545                 ip_proto = -1;
01546                 break;
01547             }
01548 
01549             return fpEvalHeaderTcp(p);
01550 
01551         case IPPROTO_UDP:
01552             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
01553                         "Detecting on UdpList\n"););
01554 
01555             if(p->udph == NULL)
01556             {
01557                 ip_proto = -1;
01558                 break;
01559             }
01560             
01561             return fpEvalHeaderUdp(p);
01562 
01563         case IPPROTO_ICMP:
01564             DEBUG_WRAP(DebugMessage(DEBUG_DETECT, 
01565                         "Detecting on IcmpList\n"););
01566 
01567             if(p->icmph == NULL)
01568             {
01569                 ip_proto = -1;
01570                 break; 
01571             }
01572 
01573             return fpEvalHeaderIcmp(p);
01574 
01575         default:
01576             break;
01577     }
01578 
01579     /*
01580     **  No Match on TCP/UDP, Do IP
01581     */
01582     return fpEvalHeaderIp(p, ip_proto);
01583 }
01584 

Generated on Sun May 14 14:51:13 2006 by  doxygen 1.4.2