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

pcrm.c

Go to the documentation of this file.
00001 /*
00002 **  $Id$
00003 **
00004 **  pcrm.c
00005 **
00006 **  Copyright (C) 2002 Sourcefire,Inc
00007 **  Marc Norton <mnorton@sourcefire.com>
00008 **  Dan Roelker <droelker@sourcefire.com>
00009 **
00010 **  NOTES
00011 **  5.15.02   - Initial version of pcrm.c distributed. - Norton/Roelker
00012 **
00013 **  This program is free software; you can redistribute it and/or modify
00014 **  it under the terms of the GNU General Public License as published by
00015 **  the Free Software Foundation; either version 2 of the License, or
00016 **  (at your option) any later version.
00017 **
00018 **  This program is distributed in the hope that it will be useful,
00019 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 **  GNU General Public License for more details.
00022 **
00023 **  You should have received a copy of the GNU General Public License
00024 **  along with this program; if not, write to the Free Software
00025 **  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00026 */
00027 
00028 /*
00029 ** 
00030 **  Packet Classificationa and Rule Manager
00031 **
00032 **
00033 **  A Fast Packet Classification method for Rule and Pattern Matching in SNORT
00034 **  --------------------------------------------------------------------------
00035 **
00036 **  A simple method for grouping rules into lists and looking them up quickly 
00037 **  in realtime. 
00038 **
00039 **  There is a natural problem when aggregating rules into pattern groups for 
00040 **  performing multi-pattern matching not seen with single pattern Boyer-Moore 
00041 **  strategies.  The problem is how to group the rules efficiently when 
00042 **  considering that there are multiple parameters which govern what rules to
00043 **  apply to each packet or connection. The paramters, sip, dip, sport, dport,
00044 **  and flags form an enormous address space of possible packets that
00045 **  must be tested in realtime against a subset of rule patterns. Methods to 
00046 **  group patterns precisely based on all of these parameters can quickly 
00047 **  become complicated by both algorithmic implications and implementation 
00048 **  details.  The procedure described herein is quick and simple.
00049 **
00050 **  The methodology presented here to solve this problem is based on the 
00051 **  premise that we can use the source and destination ports to isolate 
00052 **  pattern groups for pattern matching, and rely on an event validation 
00053 **  procedure to authenticate other parameters such as sip, dip and flags after 
00054 **  a pattern match is made. An instrinsic assumption here is that most sip 
00055 **  and dip values will be acceptable and that the big gain in performance 
00056 **  is due to the fact that by isolating traffic based on services (ports) 
00057 **  we gain the most benefit.  Additionally, and just as important, is the
00058 **  requirement that we can perform a multi-pattern recognition-inspection phase
00059 **  on a large set of patterns many times quicker than we can apply a single 
00060 **  pattern test against many single patterns.
00061 **
00062 **  The current implementation assumes that for each rule the src and dst ports
00063 **  each have one of 2 possible values.  Either a specific port number or the 
00064 **  ANYPORT designation. This does allow us to handle port ranges, and NOT port
00065 **  rules as well.
00066 **
00067 **  We make the following assumptions about classifying packets based on ports:
00068 **
00069 **    1) There are Unique ports which represent special sevices.  For example,
00070 **       ports 21,25,80,110,etc.
00071 **
00072 **    2) Patterns can be grouped into Unique Pattern groups, and a Generic 
00073 **       Pattern Group
00074 **       a) Unique pattern groups exist for source ports 21,25,80,110,etc.
00075 **       b) Unique pattern groups exist for destination ports 21,25,80,etc.
00076 **       c) A Generic pattern group exists for rules applied to every 
00077 **          combination of source and destination ports.
00078 **   
00079 **  We make the following assumptions about packet traffic:
00080 **  
00081 **    1) Well behaved traffic has one Unique port and one ephemeral port for 
00082 **       most packets and sometimes legitmately, as in the case of  DNS, has 
00083 **       two unique ports that are the same. But we always determine that 
00084 **       packets with two different but Unique ports is bogus, and should 
00085 **       generate an alert.  For example, if you have traffic going from
00086 **       port 80 to port 20.
00087 **    
00088 **    2) In fact, state could tell us which side of this connection is a 
00089 **       service and which side is a client. Than we could handle this packet 
00090 **       more precisely, but this is a rare situation and is still bogus. We 
00091 **       can choose not to do pattern inspections on these packets, or to do
00092 **       complete inspections.
00093 **
00094 **  Rules are placed into each group as follows:
00095 **    
00096 **    1) Src Port == Unique Service, Dst Port == ANY -> Unique Src Port Table
00097 **       Src Port == Unique Service, Dst Port == 
00098 **       Unique -> Unique Src & Dst Port Tables
00099 **    2) Dst Port == Unqiue Service, Src Port == ANY -> Unique Dst Port Table
00100 **       Dst Port == Unqiue Service, Src Port == 
00101 **       Unique -> Unique Dst & Src Port Tables
00102 **    3) Dst Port == ANY, Src Port == ANY -> Generic Rule Set, 
00103 **       And add to all Unique Src/Dst Rule Sets that have entries 
00104 **    4) !Dst or !Src Port is the same as ANY Dst or ANY Src port respectively
00105 **    5) DstA:DstB is treated as an ANY port group, same for SrcA:SrcB
00106 **  
00107 **  Initialization
00108 **  --------------
00109 **  For each rule check the dst-port, if it's specific, than add it to the 
00110 **  dst table.  If the dst-port is Any port, than do not add it to the dst 
00111 **  port table. Repeat this for the src-port.
00112 **
00113 **  If the rule has Any for both ports than it's added generic rule list.
00114 **
00115 **  Also, fill in the Unique-Conflicts array, this indicates if it's OK to have
00116 **  the same Unique service port for both destination and source. This will 
00117 **  force an alert if it's not ok.  We optionally, pattern match against this
00118 **  anyways.
00119 **
00120 **  Procsessing Rules
00121 **  -----------------
00122 **  When packets arrive:
00123 **
00124 **   Categorize the Port Uniqueness:
00125 **   
00126 **   a)Check the DstPort[DstPort] for possible rules, 
00127 **     if no entry than no rules exist for this packet with this destination.
00128 **
00129 **   b)Check the SrcPort[SrcPort] for possible rules, 
00130 **     if no entry than no rules exist for this packet with this source.
00131 **     
00132 **   Process the Uniqueness:
00133 **     
00134 **   If a AND !b has rules or !a AND b has rules than 
00135 **      match agaionst those rules
00136 **   
00137 **   If a AND b has rules than 
00138 **      if( sourcePort != DstPort ) 
00139 **         Alert on this traffic, and optionally match both rule sets
00140 **      else if( SourcePort == DstPort ) 
00141 **         Check the Unique-Conflicts array for allowable conflicts
00142 **             if( NOT allowed ) 
00143 **             Alert on this traffic, optionally match the rules
00144 **          else 
00145 **             match both sets of tules against this traffic
00146 **  
00147 **   If( !a AND ! b )  than
00148 **      Pattern Match against the Generic Rules ( these apply to all packets)
00149 ** 
00150 **
00151 **  example.c
00152 **  ---------
00153 **
00154 **   PORT_RULE_MAP * prm;
00155 **   PORT_GROUP  *src, *dst, *generic;
00156 **
00157 **   RULE * prule; //user defined rule structure for user rules
00158 **
00159 **   prm = prmNewMap();
00160 **
00161 **   for( each rule )
00162 **   {
00163 **      prule = ....get a rule pointer
00164 **
00165 **      prmAddRule( prm, prule->dport, prule->sport, prule );
00166 **   }
00167 **
00168 **   prmCompileGroups( prm );
00169 ** 
00170 **   while( sniff-packets )
00171 **   {
00172 **      ....
00173 **
00174 **      stat = prmFindRuleGroup( prm, dport, sport, &src, &dst, &generic );
00175 **      switch( stat )
00176 **      {
00177 **         case 0:  // No rules at all
00178 **          break;
00179 **         case 1:  // Dst Rules
00180 **           // pass 'dst->pgPatData', 'dst->pgPatDataUri' to the pattern engine
00181 **          break;
00182 **         case 2:  // Src Rules
00183 **           // pass 'src->pgPatData', 'src->pgPatDataUri' to the pattern engine
00184 **          break;
00185 **         case 3:  // Src/Dst Rules - Both ports represent Unique service ports
00186 **           // pass 'src->pgPatData' ,'src->pgPatDataUri' to the pattern engine
00187 **           // pass 'dst->pgPatData'  'src->pgPatDataUri' to the pattern engine
00188 **          break;
00189 **         case 4:  // Generic Rules Only
00190 **           // pass 'generic->pgPatData' to the pattern engine
00191 **           // pass 'generic->pgPatDataUri' to the pattern engine
00192 **          break;
00193 **      }
00194 **   }
00195 **
00196 */
00197 
00198 #ifdef HAVE_CONFIG_H
00199 #include "config.h"
00200 #endif
00201 
00202 #include <stdio.h>
00203 #include <stdlib.h>
00204 #include <string.h>
00205 
00206 #include "pcrm.h"
00207 
00208 /*
00209 ** 
00210 **  NAME
00211 **    prmNewMap::
00212 **
00213 **  DESCRIPTION
00214 **    Allocate new PORT_RULE_MAP and return pointer.
00215 **
00216 **  FORMAL INPUTS
00217 **    None
00218 **
00219 **  FORMAL OUTPUT
00220 **    PORT_RULE_MAP * - NULL if failed, ptr otherwise.
00221 **
00222 */
00223 PORT_RULE_MAP * prmNewMap( )
00224 {
00225     PORT_RULE_MAP * p;
00226 
00227     p = (PORT_RULE_MAP *)calloc(1, sizeof(PORT_RULE_MAP) );
00228 
00229     return p;
00230 }
00231 
00232 /*
00233 ** 
00234 **  NAME
00235 **    prmNewByteMap::
00236 **
00237 **  DESCRIPTION
00238 **    Allocate new BYTE_RULE_MAP and return pointer.
00239 **
00240 **  FORMAL INPUTS
00241 **    None
00242 **
00243 **  FORMAL OUTPUT
00244 **    BYTE_RULE_MAP * - NULL if failed, ptr otherwise.
00245 **
00246 */
00247 BYTE_RULE_MAP * prmNewByteMap( )
00248 {
00249     BYTE_RULE_MAP * p;
00250 
00251     p = (BYTE_RULE_MAP *)calloc(1, sizeof(BYTE_RULE_MAP) );
00252 
00253     return p;
00254 }
00255 
00256 
00257 /*
00258 **
00259 **  NAME
00260 **    prmxFreeGroup::
00261 **
00262 **  DESCRIPTION
00263 **    Frees a PORT_GROUP of it's RuleNodes.
00264 **
00265 **  FORMAL INPUTS
00266 **    PORT_GROUP * - port group to free
00267 **
00268 **  FORMAL OUTPUT
00269 **    None
00270 **
00271 */
00272 static void prmxFreeGroup(PORT_GROUP *pg)
00273 {
00274      RULE_NODE * rn, *rx;
00275 
00276      rn = pg->pgHead;
00277 
00278      while( rn )
00279      {
00280        rx = rn->rnNext;       
00281        free( rn ); 
00282        rn = rx;
00283      }         
00284 }
00285 
00286 /*
00287 **
00288 **  NAME
00289 **    prmFreeMap
00290 **
00291 **  DESCRIPTION
00292 **    Frees the memory utilized by a PORT_RULE_MAP.
00293 **
00294 **  FORMAL INPUTS
00295 **    PORT_RULE_MAP * - PORT_RULE_MAP to free
00296 **
00297 **  FORMAL OUTPUT
00298 **    None
00299 ** 
00300 */
00301 void prmFreeMap( PORT_RULE_MAP * p )
00302 {
00303      int i;
00304 
00305      if( p )
00306      {
00307        for(i=0;i<MAX_PORTS;i++)
00308        {
00309            if(p->prmSrcPort[i])
00310            {
00311                prmxFreeGroup( p->prmSrcPort[i] );     
00312                free(p->prmSrcPort[i]);
00313            }
00314        }
00315 
00316        for(i=0;i<MAX_PORTS;i++)
00317        {
00318            if(p->prmDstPort[i])
00319            {
00320                prmxFreeGroup( p->prmDstPort[i] );     
00321                free(p->prmDstPort[i]);
00322            }
00323        }
00324 
00325        if(p->prmGeneric)
00326        {
00327            prmxFreeGroup( p->prmGeneric );     
00328            free(p->prmGeneric);
00329        }
00330 
00331        free( p ); 
00332      }
00333 }
00334 
00335 /*
00336 **
00337 **  NAME
00338 **    prmFreeByteMap
00339 **
00340 **  DESCRIPTION
00341 **    Frees the memory utilized by a BYTE_RULE_MAP.
00342 **
00343 **  FORMAL INPUTS
00344 **    BYTE_RULE_MAP * - BYTE_RULE_MAP to free
00345 **
00346 **  FORMAL OUTPUT
00347 **    None
00348 ** 
00349 */
00350 void prmFreeByteMap( BYTE_RULE_MAP * p )
00351 {
00352      int i;
00353 
00354      if( p )
00355      {
00356        for(i=0;i<256;i++)
00357        {
00358           prmxFreeGroup( &p->prmByteGroup[i] );     
00359        }
00360 
00361        prmxFreeGroup( &p->prmGeneric );     
00362 
00363        free( p ); 
00364      }
00365 }
00366 
00367 /*
00368 **
00369 **  NAME
00370 **    prmxAddPortRule::
00371 **
00372 **  DESCRIPTION
00373 **    Adds a RULE_NODE to a PORT_GROUP.  This particular
00374 **    function is specific in that it adds "content" rules.
00375 **    A "content" rule is a snort rule that has a content
00376 **    flag.
00377 **
00378 **    Each RULE_NODE in a PORT_GROUP is given a RULE_NODE
00379 **    ID.  This allows us to track particulars as to what
00380 **    rules have been alerted upon, and allows other neat
00381 **    things like correlating events on different streams.
00382 **    The RULE_NODE IDs may not be consecutive, because
00383 **    we can add RULE_NODES into "content", "uri", and
00384 **    "no content" lists.  
00385 **
00386 **  FORMAL INPUTS
00387 **    PORT_GROUP * - PORT_GROUP to add the rule to.
00388 **    RULE_PTR - void ptr to the user information
00389 **
00390 **  FORMAL OUTPUT
00391 **    int - 0 is successful, 1 is failure
00392 **
00393 */
00394 static int prmxAddPortRule( PORT_GROUP *p, RULE_PTR rd )
00395 {
00396     if( !p->pgHead )
00397     {
00398          p->pgHead = (RULE_NODE*) malloc( sizeof(RULE_NODE) );
00399          if( !p->pgHead )return 1;
00400          
00401          p->pgHead->rnNext      = 0;
00402          p->pgHead->rnRuleData  = rd;
00403          p->pgTail              = p->pgHead;
00404     }
00405     else
00406     {
00407          p->pgTail->rnNext = (RULE_NODE*)malloc( sizeof(RULE_NODE) );
00408          if(!p->pgTail->rnNext)return 1;
00409          
00410          p->pgTail             = p->pgTail->rnNext;
00411          p->pgTail->rnNext     = 0;
00412          p->pgTail->rnRuleData = rd;
00413     }
00414 
00415     /*
00416     **  Set RULE_NODE ID to unique identifier
00417     */
00418     p->pgTail->iRuleNodeID = p->pgCount;
00419    
00420     /*
00421     **  Update the total Rule Node Count for this PORT_GROUP
00422     */
00423     p->pgCount++;  
00424     
00425     p->pgContentCount++;
00426 
00427     return 0;
00428 }
00429 
00430 /*
00431 **
00432 **  NAME
00433 **    prmxAddPortRuleUri::
00434 **
00435 **  DESCRIPTION
00436 **    Adds a RULE_NODE to a PORT_GROUP.  This particular
00437 **    function is specific in that it adds "uri" rules.
00438 **    A "uri" rule is a snort rule that has a uri
00439 **    flag.
00440 **
00441 **    Each RULE_NODE in a PORT_GROUP is given a RULE_NODE
00442 **    ID.  This allows us to track particulars as to what
00443 **    rules have been alerted upon, and allows other neat
00444 **    things like correlating events on different streams.
00445 **    The RULE_NODE IDs may not be consecutive, because
00446 **    we can add RULE_NODES into "content", "uri", and
00447 **    "no content" lists.  
00448 **
00449 **  FORMAL INPUTS
00450 **    PORT_GROUP * - PORT_GROUP to add the rule to.
00451 **    RULE_PTR - void ptr to the user information
00452 **
00453 **  FORMAL OUTPUT
00454 **    int - 0 is successful, 1 is failure
00455 **
00456 */
00457 static int prmxAddPortRuleUri( PORT_GROUP *p, RULE_PTR rd )
00458 {
00459     if( !p->pgUriHead )
00460     {
00461          p->pgUriHead = (RULE_NODE*) malloc( sizeof(RULE_NODE) );
00462          if( !p->pgUriHead ) return 1;
00463          
00464          p->pgUriTail              = p->pgUriHead;
00465          p->pgUriHead->rnNext      = 0;
00466          p->pgUriHead->rnRuleData  = rd;
00467     }
00468     else
00469     {
00470          p->pgUriTail->rnNext = (RULE_NODE*)malloc( sizeof(RULE_NODE) );
00471          if( !p->pgUriTail->rnNext) return 1;
00472          
00473          p->pgUriTail             = p->pgUriTail->rnNext;
00474          p->pgUriTail->rnNext     = 0;
00475          p->pgUriTail->rnRuleData = rd;
00476     }
00477 
00478     /*
00479     **  Set RULE_NODE ID to unique identifier
00480     */
00481     p->pgUriTail->iRuleNodeID = p->pgCount;
00482    
00483     /*
00484     **  Update the total Rule Node Count for this PORT_GROUP
00485     */
00486     p->pgCount++; 
00487 
00488     p->pgUriContentCount++;
00489 
00490     return 0;
00491 }
00492 
00493 /*
00494 **
00495 **  NAME
00496 **    prmxAddPortRuleNC::
00497 **
00498 **  DESCRIPTION
00499 **    Adds a RULE_NODE to a PORT_GROUP.  This particular
00500 **    function is specific in that it adds "no content" rules.
00501 **    A "no content" rule is a snort rule that has no "content"
00502 **    or "uri" flag, and hence does not need to be pattern
00503 **    matched.
00504 **
00505 **    Each RULE_NODE in a PORT_GROUP is given a RULE_NODE
00506 **    ID.  This allows us to track particulars as to what
00507 **    rules have been alerted upon, and allows other neat
00508 **    things like correlating events on different streams.
00509 **    The RULE_NODE IDs may not be consecutive, because
00510 **    we can add RULE_NODES into "content", "uri", and
00511 **    "no content" lists.  
00512 **
00513 **  FORMAL INPUTS
00514 **    PORT_GROUP * - PORT_GROUP to add the rule to.
00515 **    RULE_PTR - void ptr to the user information
00516 **
00517 **  FORMAL OUTPUT
00518 **    int - 0 is successful, 1 is failure
00519 **
00520 */
00521 static int prmxAddPortRuleNC( PORT_GROUP *p, RULE_PTR rd )
00522 {
00523     if( !p->pgHeadNC )
00524     {
00525          p->pgHeadNC = (RULE_NODE*) malloc( sizeof(RULE_NODE) );
00526          if( !p->pgHeadNC )return 1;
00527          
00528          p->pgTailNC             = p->pgHeadNC;
00529          p->pgHeadNC->rnNext     = 0;
00530          p->pgHeadNC->rnRuleData = rd;
00531     }
00532     else
00533     {
00534          p->pgTailNC->rnNext = (RULE_NODE*)malloc( sizeof(RULE_NODE) );
00535          if(!p->pgTailNC->rnNext)return 1;
00536          
00537          p->pgTailNC             = p->pgTailNC->rnNext;
00538          p->pgTailNC->rnNext     = 0;
00539          p->pgTailNC->rnRuleData = rd;
00540     }
00541 
00542     /*
00543     **  Set RULE_NODE ID to unique identifier
00544     */
00545     p->pgTailNC->iRuleNodeID = p->pgCount;
00546    
00547     /*
00548     **  Update the Total Rule Node Count for this PORT_GROUP
00549     */
00550     p->pgCount++; 
00551 
00552     p->pgNoContentCount++;
00553 
00554     return 0;
00555 }
00556 
00557 /*
00558 **
00559 **  NAME
00560 **    prmAddNotNode::
00561 **
00562 **  DESCRIPTION
00563 **    NOT SUPPORTED YET.  Build a list of pur NOT nodes i.e. content !"this" 
00564 **    content:!"that".
00565 **
00566 */
00567 void prmAddNotNode( PORT_GROUP * pg, int id )
00568 {
00569     NOT_RULE_NODE * p = malloc(sizeof( NOT_RULE_NODE));
00570 
00571     if( !p ) return ;
00572     
00573     p->iPos = id;
00574     
00575     if( !pg->pgNotRuleList )
00576     {
00577        pg->pgNotRuleList = p;
00578        p->next = 0;
00579     }
00580     else
00581     {
00582        p->next = pg->pgNotRuleList;
00583        pg->pgNotRuleList = p;
00584     }
00585 }
00586 
00587 
00588 /*
00589 **
00590 **  NAME
00591 **    prmGetFirstRule::
00592 **
00593 **  DESCRIPTION
00594 **    This function returns the first rule user data in
00595 **    the "content" list of a PORT_GROUP.
00596 **
00597 **  FORMAL INPUTS
00598 **    PORT_GROUP * - PORT_GROUP to retrieve data from.
00599 **
00600 **  FORMAL OUTPUT
00601 **    RULE_PTR - the ptr to the user data.
00602 **    
00603 */
00604 RULE_PTR prmGetFirstRule( PORT_GROUP * pg )
00605 {
00606     pg->pgCur = pg->pgHead;
00607     
00608     if( !pg->pgCur ) 
00609         return 0;
00610      
00611     return pg->pgCur->rnRuleData;
00612 }  
00613 
00614 /*
00615 **
00616 **  NAME
00617 **    prmGetNextRule::
00618 **
00619 **  DESCRIPTION
00620 **    Gets the next "content" rule.  This function allows easy
00621 **    walking of the "content" rule list.
00622 **
00623 **  FORMAL INPUTS
00624 **    PORT_GROUP * - PORT_GROUP to retrieve data from.
00625 **
00626 **  FORMAL OUTPUT
00627 **    RULE_PTR - ptr to the user data
00628 **    
00629 */
00630 RULE_PTR prmGetNextRule( PORT_GROUP * pg )
00631 {
00632     if( pg->pgCur ) 
00633         pg->pgCur = pg->pgCur->rnNext;
00634      
00635     if( !pg->pgCur ) 
00636         return 0;
00637     
00638     return pg->pgCur->rnRuleData;
00639 }
00640 
00641 /*
00642 **
00643 **  NAME
00644 **    prmGetFirstRuleUri::
00645 **
00646 **  DESCRIPTION
00647 **    This function returns the first rule user data in
00648 **    the "uri" list of a PORT_GROUP.
00649 **
00650 **  FORMAL INPUTS
00651 **    PORT_GROUP * - PORT_GROUP to retrieve data from.
00652 **
00653 **  FORMAL OUTPUT
00654 **    RULE_PTR - the ptr to the user data.
00655 **    
00656 */
00657 RULE_PTR prmGetFirstRuleUri( PORT_GROUP * pg )
00658 {
00659     pg->pgUriCur = pg->pgUriHead;
00660     
00661     if( !pg->pgUriCur ) 
00662         return 0;
00663      
00664     return pg->pgUriCur->rnRuleData;
00665 }  
00666 
00667 /*
00668 **
00669 **  NAME
00670 **    prmGetNextRuleUri::
00671 **
00672 **  DESCRIPTION
00673 **    Gets the next "uri" rule.  This function allows easy
00674 **    walking of the "uri" rule list.
00675 **
00676 **  FORMAL INPUTS
00677 **    PORT_GROUP * - PORT_GROUP to retrieve data from.
00678 **
00679 **  FORMAL OUTPUT
00680 **    RULE_PTR - ptr to the user data
00681 **    
00682 */
00683 RULE_PTR prmGetNextRuleUri( PORT_GROUP * pg )
00684 {
00685     if( pg->pgUriCur ) 
00686         pg->pgUriCur = pg->pgUriCur->rnNext;
00687      
00688     if( !pg->pgUriCur ) 
00689         return 0;
00690     
00691     return pg->pgUriCur->rnRuleData;
00692 }  
00693 
00694 /*
00695 **
00696 **  NAME
00697 **    prmGetFirstRuleNC::
00698 **
00699 **  DESCRIPTION
00700 **    This function returns the first rule user data in
00701 **    the "no content" list of a PORT_GROUP.
00702 **
00703 **  FORMAL INPUTS
00704 **    PORT_GROUP * - PORT_GROUP to retrieve data from.
00705 **
00706 **  FORMAL OUTPUT
00707 **    RULE_PTR - the ptr to the user data.
00708 **    
00709 */
00710 RULE_PTR prmGetFirstRuleNC( PORT_GROUP * pg )
00711 {
00712     pg->pgCurNC = pg->pgHeadNC;
00713     
00714     if( !pg->pgCurNC ) 
00715         return 0;
00716      
00717     return pg->pgCurNC->rnRuleData;
00718 }  
00719 
00720 /*
00721 **
00722 **  NAME
00723 **    prmGetNextRuleNC::
00724 **
00725 **  DESCRIPTION
00726 **    Gets the next "no content" rule.  This function allows easy
00727 **    walking of the "no content" rule list.
00728 **
00729 **  FORMAL INPUTS
00730 **    PORT_GROUP * - PORT_GROUP to retrieve data from.
00731 **
00732 **  FORMAL OUTPUT
00733 **    RULE_PTR - ptr to the user data
00734 **    
00735 */
00736 RULE_PTR prmGetNextRuleNC( PORT_GROUP * pg )
00737 {
00738     if( pg->pgCurNC ) 
00739         pg->pgCurNC = pg->pgCurNC->rnNext;
00740      
00741     if( !pg->pgCurNC ) 
00742         return 0;
00743     
00744     return pg->pgCurNC->rnRuleData;
00745 }  
00746 
00747 /*
00748 **
00749 **  NAME
00750 **    prmAddRule::
00751 **
00752 **  DESCRIPTION
00753 **    This function adds a rule to a PORT_RULE_MAP.  Depending on the
00754 **    values of the sport and dport, the rule gets added in different
00755 **    groups (src,dst,generic).  The values for dport and sport
00756 **    can be: 0 -> 64K or -1 for generic (meaning that the rule applies
00757 **    to all values.
00758 **
00759 **    Warning: Consider this carefully.
00760 **    Some rules use 6000:6005 -> any  for a port designation, we could
00761 **    add each rule to it's own group, in this case Src=6000 to 6005.
00762 **    But we opt to add them as ANY rules for now, to reduce groups.
00763 **
00764 **    IMPORTANT:
00765 **    This function adds a rule to the "content" list of rules.
00766 **
00767 **  FORMAL INPUTS
00768 **    PORT_RULE_MAP * - PORT_RULE_MAP to add rule to.
00769 **    int - the dst port value.
00770 **    int - the src port value.
00771 **    RULE_PTR - the ptr to the user data for the rule.
00772 **
00773 **  FORMAL OUTPUT
00774 **    int - 0 is successful, 1 is failure.
00775 **  
00776 */
00777 int prmAddRule( PORT_RULE_MAP * p, int dport, int sport, RULE_PTR rd )
00778 {
00779     if( dport != ANYPORT && dport < MAX_PORTS )  /* dst=21,25,80,110,139 */
00780     {
00781        p->prmNumDstRules++;
00782 
00783        /*
00784        **  Check to see if this PORT_GROUP has been initialized
00785        */
00786        if(p->prmDstPort[dport] == NULL)
00787        {
00788            p->prmDstPort[dport] = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
00789            if(p->prmDstPort[dport] == NULL)
00790            {
00791                return 1;
00792            }
00793        }
00794 
00795        if(p->prmDstPort[dport]->pgCount==0) p->prmNumDstGroups++;
00796 
00797        prmxAddPortRule( p->prmDstPort[ dport ], rd );
00798     }
00799     
00800     if( sport != ANYPORT && sport < MAX_PORTS) /* src=ANY, SRC=80,21,25,etc. */
00801     {
00802        p->prmNumSrcRules++;
00803 
00804        /*
00805        **  Check to see if this PORT_GROUP has been initialized
00806        */
00807        if(p->prmSrcPort[sport] == NULL)
00808        {
00809            p->prmSrcPort[sport] = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
00810            if(p->prmSrcPort[sport] == NULL)
00811            {
00812                return 1;
00813            }
00814        }
00815 
00816        if(p->prmSrcPort[sport]->pgCount==0) p->prmNumSrcGroups++;
00817 
00818        prmxAddPortRule( p->prmSrcPort[ sport ], rd );
00819     }
00820     
00821     if( sport == ANYPORT && dport == ANYPORT) /* dst=ANY, src=ANY */
00822     {
00823        p->prmNumGenericRules++;
00824 
00825        /*
00826        **  Check to see if this PORT_GROUP has been initialized
00827        */
00828        if(p->prmGeneric == NULL)
00829        {
00830            p->prmGeneric = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
00831            if(p->prmGeneric == NULL)
00832            {
00833                return 1;
00834            }
00835        }
00836 
00837        prmxAddPortRule( p->prmGeneric, rd );
00838     }
00839 
00840   return 0;
00841 }
00842 
00843 int prmAddByteRule( BYTE_RULE_MAP * p, int dport, RULE_PTR rd )
00844 {
00845     if( dport != ANYPORT && dport < 256 )  /* dst=21,25,80,110,139 */
00846     {
00847        p->prmNumRules++;
00848        if( p->prmByteGroup[dport].pgCount==0 ) p->prmNumGroups++;
00849 
00850        prmxAddPortRule( &(p->prmByteGroup[ dport ]), rd );
00851     }
00852     
00853     else if( dport == ANYPORT ) /* dst=ANY, src=ANY */
00854     {
00855        p->prmNumGenericRules++;
00856 
00857        prmxAddPortRule( &(p->prmGeneric), rd );
00858     }
00859 
00860   return 0;
00861 }
00862 
00863 /*
00864 **
00865 **  NAME
00866 **    prmAddRuleUri::
00867 **
00868 **  DESCRIPTION
00869 **    This function adds a rule to a PORT_RULE_MAP.  Depending on the
00870 **    values of the sport and dport, the rule gets added in different
00871 **    groups (src,dst,generic).  The values for dport and sport
00872 **    can be: 0 -> 64K or -1 for generic (meaning that the rule applies
00873 **    to all values.
00874 **
00875 **    Warning: Consider this carefully.
00876 **    Some rules use 6000:6005 -> any  for a port designation, we could
00877 **    add each rule to it's own group, in this case Src=6000 to 6005.
00878 **    But we opt to add them as ANY rules for now, to reduce groups.
00879 **
00880 **    IMPORTANT:
00881 **    This function adds a rule to the "uri" list of rules.
00882 **
00883 **  FORMAL INPUTS
00884 **    PORT_RULE_MAP * - PORT_RULE_MAP to add rule to.
00885 **    int - the dst port value.
00886 **    int - the src port value.
00887 **    RULE_PTR - the ptr to the user data for the rule.
00888 **
00889 **  FORMAL OUTPUT
00890 **    int - 0 is successful, 1 is failure.
00891 **  
00892 */
00893 int prmAddRuleUri( PORT_RULE_MAP * p, int dport, int sport, RULE_PTR rd )
00894 {
00895     if( dport != ANYPORT && dport < MAX_PORTS )  /* dst=21,25,80,110,139 */
00896     {
00897        p->prmNumDstRules++;
00898 
00899        /*
00900        **  Check to see if this PORT_GROUP has been initialized
00901        */
00902        if(p->prmDstPort[dport] == NULL)
00903        {
00904            p->prmDstPort[dport] = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
00905            if(p->prmDstPort[dport] == NULL)
00906            {
00907                return 1;
00908            }
00909        }
00910 
00911        if(p->prmDstPort[dport]->pgCount==0) p->prmNumDstGroups++;
00912 
00913        prmxAddPortRuleUri( p->prmDstPort[ dport ], rd );
00914     }
00915     
00916     if( sport != ANYPORT && sport < MAX_PORTS) /* src=ANY, SRC=80,21,25,etc. */
00917     {
00918        p->prmNumSrcRules++;
00919 
00920        /*
00921        **  Check to see if this PORT_GROUP has been initialized
00922        */
00923        if(p->prmSrcPort[sport] == NULL)
00924        {
00925            p->prmSrcPort[sport] = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
00926            if(p->prmSrcPort[sport] == NULL)
00927            {
00928                return 1;
00929            }
00930        }
00931 
00932        if(p->prmSrcPort[sport]->pgCount==0) p->prmNumSrcGroups++;
00933 
00934        prmxAddPortRuleUri( p->prmSrcPort[ sport ], rd );
00935     }
00936     
00937     if( sport == ANYPORT && dport == ANYPORT) /* dst=ANY, src=ANY */
00938     {
00939        p->prmNumGenericRules++;
00940 
00941        /*
00942        **  Check to see if this PORT_GROUP has been initialized
00943        */
00944        if(p->prmGeneric == NULL)
00945        {
00946            p->prmGeneric = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
00947            if(p->prmGeneric == NULL)
00948            {
00949                return 1;
00950            }
00951        }
00952 
00953        prmxAddPortRuleUri( p->prmGeneric, rd );
00954     }
00955 
00956   return 0;
00957 }
00958 
00959 /*
00960 **
00961 **  NAME
00962 **    prmAddRuleNC::
00963 **
00964 **  DESCRIPTION
00965 **    This function adds a rule to a PORT_RULE_MAP.  Depending on the
00966 **    values of the sport and dport, the rule gets added in different
00967 **    groups (src,dst,generic).  The values for dport and sport
00968 **    can be: 0 -> 64K or -1 for generic (meaning that the rule applies
00969 **    to all values.
00970 **
00971 **    Warning: Consider this carefully.
00972 **    Some rules use 6000:6005 -> any  for a port designation, we could
00973 **    add each rule to it's own group, in this case Src=6000 to 6005.
00974 **    But we opt to add them as ANY rules for now, to reduce groups.
00975 **
00976 **    IMPORTANT:
00977 **    This function adds a rule to the "no content" list of rules.
00978 **
00979 **  FORMAL INPUTS
00980 **    PORT_RULE_MAP * - PORT_RULE_MAP to add rule to.
00981 **    int - the dst port value.
00982 **    int - the src port value.
00983 **    RULE_PTR - the ptr to the user data for the rule.
00984 **
00985 **  FORMAL OUTPUT
00986 **    int - 0 is successful, 1 is failure.
00987 **  
00988 */
00989 int prmAddRuleNC( PORT_RULE_MAP * p, int dport, int sport, RULE_PTR rd )
00990 {
00991     if( dport != ANYPORT && dport < MAX_PORTS )  /* dst=21,25,80,110,139 */
00992     {
00993        p->prmNumDstRules++;
00994 
00995        /*
00996        **  Check to see if this PORT_GROUP has been initialized
00997        */
00998        if(p->prmDstPort[dport] == NULL)
00999        {
01000            p->prmDstPort[dport] = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
01001            if(p->prmDstPort[dport] == NULL)
01002            {
01003                return 1;
01004            }
01005        }
01006 
01007        if(p->prmDstPort[dport]->pgCount==0) p->prmNumDstGroups++;
01008 
01009        prmxAddPortRuleNC( p->prmDstPort[ dport ], rd );
01010     }
01011     
01012     if( sport != ANYPORT && sport < MAX_PORTS) /* src=ANY, SRC=80,21,25,etc. */
01013     {
01014        p->prmNumSrcRules++;
01015 
01016        /*
01017        **  Check to see if this PORT_GROUP has been initialized
01018        */
01019        if(p->prmSrcPort[sport] == NULL)
01020        {
01021            p->prmSrcPort[sport] = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
01022            if(p->prmSrcPort[sport] == NULL)
01023            {
01024                return 1;
01025            }
01026        }
01027 
01028        if(p->prmSrcPort[sport]->pgCount==0) p->prmNumSrcGroups++;
01029 
01030        prmxAddPortRuleNC( p->prmSrcPort[ sport ], rd );
01031     }
01032     
01033     if( sport == ANYPORT && dport == ANYPORT) /* dst=ANY, src=ANY */
01034     {
01035        p->prmNumGenericRules++;
01036 
01037        /*
01038        **  Check to see if this PORT_GROUP has been initialized
01039        */
01040        if(p->prmGeneric == NULL)
01041        {
01042            p->prmGeneric = (PORT_GROUP *)calloc(1, sizeof(PORT_GROUP));
01043            if(p->prmGeneric == NULL)
01044            {
01045                return 1;
01046            }
01047        }
01048 
01049        prmxAddPortRuleNC( p->prmGeneric, rd );
01050     }
01051 
01052   return 0;
01053 }
01054 
01055 
01056 int prmAddByteRuleNC( BYTE_RULE_MAP * p, int dport, RULE_PTR rd )
01057 {
01058     if( dport != ANYPORT && dport < 256 )  /* dst=21,25,80,110,139 */
01059     {
01060        p->prmNumRules++;
01061        if(p->prmByteGroup[dport].pgCount==0) p->prmNumGroups++;
01062 
01063        prmxAddPortRuleNC( &(p->prmByteGroup[ dport ]), rd );
01064     }
01065     
01066     else if( dport == ANYPORT) /* dst=ANY, src=ANY */
01067     {
01068        p->prmNumGenericRules++;
01069 
01070        prmxAddPortRuleNC( &(p->prmGeneric), rd );
01071     }
01072 
01073   return 0;
01074 }
01075 
01076 /*
01077 **
01078 **  NAME
01079 **    prmFindRuleGroup::
01080 **
01081 **  DESCRIPTION
01082 **    Given a PORT_RULE_MAP, this function selects the PORT_GROUP or
01083 **    PORT_GROUPs necessary to fully match a given dport, sport pair.
01084 **    The selection logic looks at both the dport and sport and
01085 **    determines if one or both are unique.  If one is unique, then 
01086 **    the appropriate PORT_GROUP ptr is set.  If both are unique, then
01087 **    both th src and dst PORT_GROUP ptrs are set.  If neither of the
01088 **    ports are unique, then the gen PORT_GROUP ptr is set.
01089 **
01090 **  FORMAL INPUTS
01091 **    PORT_RULE_MAP * - the PORT_RULE_MAP to pick PORT_GROUPs from.
01092 **    int             - the dst port value (0->64K or -1 for generic)
01093 **    int             - the src port value (0->64K or -1 for generic)
01094 **    PORT_GROUP **   - the src PORT_GROUP ptr to set.
01095 **    PORT_GROUP **   - the dst PORT_GROUP ptr to set.
01096 **    PORT_GROUP **   - the generic PORT_GROUP ptr to set.
01097 **
01098 **  FORMAL OUTPUT
01099 **    int -  0: No rules
01100 **           1: Use Dst Rules
01101 **           2: Use Src Rules
01102 **           3: Use Both Dst and Src Rules
01103 **           4: Use Generic Rules
01104 **
01105 **  NOTES
01106 **    Currently, if there is a "unique conflict", we return both the src
01107 **    and dst PORT_GROUPs.  This conflict forces us to do two searches, one
01108 **    for the src and one for the dst.  So we are taking twice the time to
01109 **    inspect a packet then usual.  Obviously, this is not good.  There
01110 **    are several options that we have to deal with unique conflicts, but
01111 **    have not implemented any currently.  The optimum solution will be to
01112 **    incorporate streaming and protocol analysis to a session so we know
01113 **    what to match against.
01114 **
01115 */
01116 int prmFindRuleGroup( PORT_RULE_MAP * p, int dport, int sport, PORT_GROUP ** src, PORT_GROUP **dst , PORT_GROUP ** gen)
01117 {
01118     int stat= 0;
01119 
01120     if( (dport != ANYPORT && dport < MAX_PORTS) && p->prmDstPort[dport] )
01121     {
01122          *dst  = p->prmDstPort[dport];
01123          stat = 1;
01124 
01125     }else{
01126       
01127        *dst=NULL;
01128     }
01129 
01130     if( (sport != ANYPORT && sport < MAX_PORTS ) && p->prmSrcPort[sport])
01131     {
01132        *src   = p->prmSrcPort[sport];
01133         stat |= 2;
01134        
01135     }else{
01136        *src = NULL;
01137     }
01138 
01139     /* If no Src/Dst rules - use the generic set, if any exist  */
01140     if( !stat &&  (p->prmGeneric > 0) ) 
01141     {
01142        *gen  = p->prmGeneric;
01143         stat = 4;
01144 
01145     }else{
01146      
01147       *gen = NULL;
01148     }
01149 
01150     
01151     return stat;
01152 }
01153 
01154 /*
01155 *
01156 */
01157 int prmFindByteRuleGroup( BYTE_RULE_MAP * p, int dport, PORT_GROUP **dst , PORT_GROUP ** gen)
01158 {
01159     int stat= 0;
01160 
01161     if( (dport != ANYPORT && dport < 256 ) && p->prmByteGroup[dport].pgCount  )
01162     {
01163          *dst  = &p->prmByteGroup[dport];
01164          stat = 1;
01165 
01166     }else{
01167       
01168        *dst=0;
01169     }
01170 
01171     /* If no Src/Dst rules - use the generic set, if any exist  */
01172     if( !stat &&  (p->prmGeneric.pgCount > 0) ) 
01173     {
01174        *gen  = &p->prmGeneric;
01175         stat = 4;
01176 
01177     }else{
01178      
01179       *gen = 0;
01180     }
01181 
01182     
01183     return stat;
01184 }
01185 
01186 /*
01187 ** Access each Rule group by index (0-MAX_PORTS)
01188 */
01189 PORT_GROUP * prmFindDstRuleGroup( PORT_RULE_MAP * p, int port )
01190 {
01191     if( port < 0 || port >= MAX_PORTS ) return 0;
01192         
01193     if( p->prmDstPort[port])
01194         return p->prmDstPort[port];
01195         
01196     return 0;
01197 }
01198 
01199 /*
01200 ** Access each Rule group by index (0-MAX_PORTS)
01201 */
01202 PORT_GROUP * prmFindSrcRuleGroup( PORT_RULE_MAP * p, int port )
01203 {
01204     if( port < 0 || port >= MAX_PORTS ) return 0;
01205         
01206     if( p->prmSrcPort[port])    
01207       return p->prmSrcPort[port];
01208     
01209     return 0;
01210 }
01211 
01212 /*
01213 ** Access each Rule group by index (0-MAX_PORTS)
01214 */
01215 PORT_GROUP * prmFindByteRuleGroupUnique( BYTE_RULE_MAP * p, int port )
01216 {
01217     if( port < 0 || port >= MAX_PORTS ) return 0;
01218         
01219     if( p->prmByteGroup[port].pgCount ) 
01220       return &p->prmByteGroup[port];
01221     
01222     return 0;
01223 }
01224 
01225 
01226 /*
01227 ** Assign the pattern matching data to this group
01228 */
01229 int prmSetGroupPatData( PORT_GROUP * pg, void * data )
01230 {
01231     pg->pgPatData = data;
01232     return 0;
01233 }
01234 
01235 /*
01236 ** Get the patttern matching data for this group
01237 */
01238 void * prmGetGroupPatData( PORT_GROUP * pg )
01239 {
01240     return pg->pgPatData;
01241 }  
01242 
01243 /*
01244 **
01245 **  NAME
01246 **    prmCompileGroups::
01247 **
01248 **  DESCRIPTION
01249 **    Add Generic rules to each Unique rule group, this could be 
01250 **    optimized a bit, right now we will process generic rules 
01251 **    twice when packets have 2 unique ports, but this will not 
01252 **    occur often.
01253 **
01254 **    The generic rues are added to the Unique rule groups, so that 
01255 **    the setwise methodology can be taking advantage of.
01256 **
01257 **  FORMAL INPUTS
01258 **    PORT_RULE_MAP * - the PORT_RULE_MAP to compile generice rules.
01259 **
01260 **  FORMAL OUTPUT
01261 **    int - 0 is successful;
01262 **
01263 */
01264 int prmCompileGroups( PORT_RULE_MAP * p )
01265 {
01266    PORT_GROUP *pgGen, *pgSrc, *pgDst;
01267    RULE_PTR   *prule;
01268    int  i;
01269 
01270    /*
01271    **  Add Generic to Src and Dst groups 
01272    */
01273    pgGen = p->prmGeneric;
01274 
01275    if(!pgGen)
01276         return 0;
01277    
01278    for(i=0;i<MAX_PORTS;i++)  
01279    {
01280      /* Add to the Unique Src and Dst Groups as well, 
01281      ** but don't inc thier prmNUMxxx counts, we want these to be true Uniqe counts
01282      ** we can add the Generic numbers if we want these, besides
01283      ** each group has it's own count.
01284      */
01285 
01286      if(p->prmSrcPort[i])
01287      {
01288         pgSrc = p->prmSrcPort[i];  
01289          
01290         prule = prmGetFirstRule( pgGen );
01291         while( prule )
01292         {
01293            prmxAddPortRule( pgSrc, prule );
01294            prule = prmGetNextRule( pgGen );
01295         }
01296 
01297         prule = prmGetFirstRuleUri( pgGen );
01298         while( prule )
01299         {
01300            prmxAddPortRuleUri( pgSrc, prule );
01301            prule = prmGetNextRuleUri( pgGen );
01302         }
01303 
01304         prule = prmGetFirstRuleNC( pgGen );
01305         while( prule )
01306         {
01307            prmxAddPortRuleNC( pgSrc, prule );
01308            prule = prmGetNextRuleNC( pgGen );
01309         }
01310      }
01311 
01312      if(p->prmDstPort[i]) 
01313      {
01314         pgDst = p->prmDstPort[i];   
01315         
01316         prule = prmGetFirstRule( pgGen );
01317         while( prule )
01318         {
01319            prmxAddPortRule( pgDst, prule );
01320            prule = prmGetNextRule( pgGen );
01321         }
01322 
01323         prule = prmGetFirstRuleUri( pgGen );
01324         while( prule )
01325         {
01326            prmxAddPortRuleUri( pgDst, prule );
01327            prule = prmGetNextRuleUri( pgGen );
01328         }
01329 
01330         prule = prmGetFirstRuleNC( pgGen );
01331         while( prule )
01332         {
01333            prmxAddPortRuleNC( pgDst, prule );
01334            prule = prmGetNextRuleNC( pgGen );
01335         }
01336      }
01337      
01338    }
01339 
01340    return 0;
01341 }
01342 
01343 
01344 /*
01345 *
01346 *
01347 */
01348 int prmCompileByteGroups( BYTE_RULE_MAP * p )
01349 {
01350    PORT_GROUP *pgGen, *pgByte;
01351    RULE_PTR   *prule;
01352    int  i;
01353 
01354    /*
01355    **  Add Generic to Unique groups 
01356    */
01357    pgGen = &p->prmGeneric;
01358 
01359    if( !pgGen->pgCount )
01360         return 0;
01361    
01362    for(i=0;i<256;i++)  
01363    {
01364       if(p->prmByteGroup[i].pgCount)
01365       {
01366         pgByte = &p->prmByteGroup[i];  
01367          
01368         prule = prmGetFirstRule( pgGen );
01369         while( prule )
01370         {
01371            prmxAddPortRule( pgByte, prule );
01372            prule = prmGetNextRule( pgGen );
01373         }
01374 
01375         prule = prmGetFirstRuleNC( pgGen );
01376         while( prule )
01377         {
01378            prmxAddPortRuleNC( pgByte, prule );
01379            prule = prmGetNextRuleNC( pgGen );
01380         }
01381      }
01382    }
01383    
01384    return 0;
01385 }
01386 
01387 /*
01388 **
01389 **  NAME
01390 **    prmShowStats::
01391 **
01392 **  DESCRIPTION
01393 **    This function shows some basic stats on the fast packet
01394 **    classification.  It show the the number of PORT_GROUPS 
01395 **    for a PORT_RULE_MAP, and the break down of the different
01396 **    rule types (content, uri, no content).
01397 **
01398 **  FORMAL INPUTS
01399 **    PORT_RULE_MAP * - the PORT_RULE_MAP to show stats on.
01400 **
01401 **  FORMAL OUTPUT
01402 **    int - 0 is successful.
01403 **
01404 */
01405 int prmShowStats( PORT_RULE_MAP * p )
01406 {
01407    int i;
01408    PORT_GROUP * pg;
01409 
01410    printf("Packet Classification Rule Manager Stats ----\n");
01411    printf("NumDstGroups   : %d\n",p->prmNumDstGroups);
01412    printf("NumSrcGroups   : %d\n",p->prmNumSrcGroups);
01413    printf("\n");
01414    printf("NumDstRules    : %d\n",p->prmNumDstRules);
01415    printf("NumSrcRules    : %d\n",p->prmNumSrcRules);
01416    printf("NumGenericRules: %d\n",p->prmNumGenericRules);
01417    printf("\n");
01418 
01419    printf("%d Dst Groups In Use, %d Unique Rules, includes generic\n",p->prmNumDstGroups,p->prmNumDstRules);
01420    for(i=0;i<MAX_PORTS;i++)
01421    {
01422      pg = prmFindDstRuleGroup( p, i );
01423      if(pg)
01424      {
01425        printf("  Dst Port %5d : %d uricontent, %d content, %d nocontent \n",i, 
01426                  pg->pgUriContentCount,pg->pgContentCount,pg->pgNoContentCount);
01427        if( pg->avgLen )
01428        {
01429          printf("MinLen=%d MaxLen=%d AvgLen=%d",pg->minLen,pg->maxLen,pg->avgLen);
01430          if(pg->c1)printf(" [1]=%d",pg->c1);   
01431          if(pg->c2)printf(" [2]=%d",pg->c2);   
01432          if(pg->c3)printf(" [3]=%d",pg->c3);   
01433          if(pg->c4)printf(" [4]=%d",pg->c4);   
01434          printf("\n");
01435        }
01436      }
01437    }
01438 
01439    printf("%d Src Groups In Use, %d Unique Rules, includes generic\n",p->prmNumSrcGroups,p->prmNumSrcRules);
01440    for(i=0;i<MAX_PORTS;i++)
01441    {
01442      pg = prmFindSrcRuleGroup( p, i );
01443      if(pg){
01444         printf("  Src Port %5d : %d uricontent, %d content, %d nocontent \n",i, 
01445                  pg->pgUriContentCount,pg->pgContentCount,pg->pgNoContentCount);
01446         if( pg->avgLen )
01447         {  
01448            printf("MinLen=%d MaxLen=%d AvgLen=%d",pg->minLen,pg->maxLen,pg->avgLen);
01449           if(pg->c1)printf(" [1]=%d",pg->c1);   
01450           if(pg->c2)printf(" [2]=%d",pg->c2);   
01451           if(pg->c3)printf(" [3]=%d",pg->c3);   
01452           if(pg->c4)printf(" [4]=%d",pg->c4);   
01453           printf("\n");
01454         }
01455      }
01456    }
01457 
01458    pg = p->prmGeneric;
01459      if(pg){
01460         printf("   Generic Rules : %d uricontent, %d content, %d nocontent \n",
01461                  pg->pgUriContentCount,pg->pgContentCount,pg->pgNoContentCount);
01462         if( pg->avgLen )
01463         {
01464           printf("MinLen=%d MaxLen=%d AvgLen=%d",pg->minLen,pg->maxLen,pg->avgLen);
01465           if(pg->c1)printf(" [1]=%d",pg->c1);   
01466           if(pg->c2)printf(" [2]=%d",pg->c2);   
01467           if(pg->c3)printf(" [3]=%d",pg->c3);   
01468           if(pg->c4)printf(" [4]=%d",pg->c4);   
01469           printf("\n");
01470         }
01471      }
01472 
01473    return 0;
01474 }
01475 
01476 
01477 int prmShowByteStats( BYTE_RULE_MAP * p )
01478 {
01479    int i;
01480    PORT_GROUP * pg;
01481 
01482    printf("Packet Classification Rule Manager Stats ----\n");
01483    printf("NumGroups   : %d\n",p->prmNumGroups);
01484    printf("\n");
01485    printf("NumRules    : %d\n",p->prmNumRules);
01486    printf("NumGenericRules: %d\n",p->prmNumGenericRules);
01487    printf("\n");
01488 
01489    printf("%d Byte Groups In Use, %d Unique Rules, includes generic\n",p->prmNumGroups,p->prmNumRules);
01490    for(i=0;i<256;i++)
01491    {
01492      pg = prmFindByteRuleGroupUnique( p, i );
01493      if(pg)
01494      {
01495        printf("  Proto/Type %5d : %d content, %d nocontent \n",i, 
01496                  pg->pgContentCount,pg->pgNoContentCount);
01497        if( pg->avgLen )
01498        {
01499          printf("MinLen=%d MaxLen=%d AvgLen=%d",pg->minLen,pg->maxLen,pg->avgLen);
01500          if(pg->c1)printf(" [1]=%d",pg->c1);   
01501          if(pg->c2)printf(" [2]=%d",pg->c2);   
01502          if(pg->c3)printf(" [3]=%d",pg->c3);   
01503          if(pg->c4)printf(" [4]=%d",pg->c4);   
01504          printf("\n");
01505        }
01506      }
01507    }
01508 
01509  
01510    pg = &p->prmGeneric;
01511      if(pg){
01512         printf("   Generic Rules : %d content, %d nocontent \n",
01513                 pg->pgContentCount,pg->pgNoContentCount);
01514         if( pg->avgLen )
01515         {
01516           printf("MinLen=%d MaxLen=%d AvgLen=%d",pg->minLen,pg->maxLen,pg->avgLen);
01517           if(pg->c1)printf(" [1]=%d",pg->c1);   
01518           if(pg->c2)printf(" [2]=%d",pg->c2);   
01519           if(pg->c3)printf(" [3]=%d",pg->c3);   
01520           if(pg->c4)printf(" [4]=%d",pg->c4);   
01521           printf("\n");
01522         }
01523      }
01524 
01525    return 0;
01526 }
01527 
01528 /*
01529 **
01530 **  NAME
01531 **    prmShowEventStats::
01532 **
01533 **  DESCRIPTION
01534 **    This function is used at the close of the Fast Packet
01535 **    inspection.  It tells how many non-qualified and qualified
01536 **    hits occurred for each PORT_GROUP.  A non-qualified hit
01537 **    is defined by an initial match against a packet, but upon
01538 **    further inspection a hit was not validated.  Non-qualified
01539 **    hits occur because we can match on the most unique aspect
01540 **    of a packet, this is the content.  Snort has other flags
01541 **    then content though, so once we hit a content match we must
01542 **    verify these additional flags.  Sometimes these flags do
01543 **    not pass the validation.  A qualified hit is an event that
01544 **    has been fully qualified, and has been put in the event
01545 **    cache for event selection.  Qualified hits are not a subset
01546 **    of non-qualified hits.  Ideally, non-qualified hits should
01547 **    be zero.  The reason for these stats is that it allows
01548 **    users to trouble shoot PORT_GROUPs.  A poorly written rule
01549 **    may cause many non-qualified events, and these stats
01550 **    allow the user to track this down.
01551 **
01552 **  FORMAL INPUTS
01553 **    PORT_RULE_MAP * -  the PORT_RULE_MAP to show stats on.
01554 **
01555 **  FORMAL OUTPUT
01556 **    int - 0 is successful.
01557 **
01558 */
01559 int prmShowEventStats( PORT_RULE_MAP * p )
01560 {
01561    int i;
01562    PORT_GROUP * pg;
01563 
01564    int NQEvents = 0;
01565    int QEvents = 0;
01566 
01567    printf("Packet Classification Rule Manager Stats ----\n");
01568    printf("NumDstGroups   : %d\n",p->prmNumDstGroups);
01569    printf("NumSrcGroups   : %d\n",p->prmNumSrcGroups);
01570    printf("\n");
01571    printf("NumDstRules    : %d\n",p->prmNumDstRules);
01572    printf("NumSrcRules    : %d\n",p->prmNumSrcRules);
01573    printf("NumGenericRules: %d\n",p->prmNumGenericRules);
01574    printf("\n");
01575 
01576    printf("%d Dst Groups In Use, %d Unique Rules, includes generic\n",p->prmNumDstGroups,p->prmNumDstRules);
01577    for(i=0;i<MAX_PORTS;i++)
01578    {
01579      pg = prmFindDstRuleGroup( p, i );
01580      if(pg)
01581      {
01582        NQEvents += pg->pgNQEvents;
01583        QEvents  += pg->pgQEvents;
01584 
01585        if( pg->pgNQEvents + pg->pgQEvents )
01586        {
01587           printf("  Dst Port %5d : %d group entries \n",i, pg->pgCount);
01588           printf("    NQ Events  : %d\n", pg->pgNQEvents);
01589           printf("     Q Events  : %d\n", pg->pgQEvents);
01590        }
01591      }
01592    }
01593 
01594    printf("%d Src Groups In Use, %d Unique Rules, includes generic\n",p->prmNumSrcGroups,p->prmNumSrcRules);
01595    for(i=0;i<MAX_PORTS;i++)
01596    {
01597      pg = prmFindSrcRuleGroup( p, i );
01598      if(pg)
01599      {
01600 
01601         NQEvents += pg->pgNQEvents;
01602         QEvents += pg->pgQEvents;
01603     
01604         if( pg->pgNQEvents + pg->pgQEvents )
01605         {
01606           printf("  Src Port %5d : %d group entries \n",i, pg->pgCount);
01607           printf("    NQ Events  : %d\n", pg->pgNQEvents);
01608           printf("     Q Events  : %d\n", pg->pgQEvents);
01609         }
01610      }
01611    }
01612 
01613    pg = p->prmGeneric;
01614    if(pg)
01615    {
01616       NQEvents += pg->pgNQEvents;
01617       QEvents += pg->pgQEvents;
01618 
01619       if( pg->pgNQEvents + pg->pgQEvents )
01620       {
01621         printf("  Generic Rules : %d group entries\n", pg->pgCount);
01622         printf("    NQ Events   : %d\n", pg->pgNQEvents);
01623         printf("     Q Events   : %d\n", pg->pgQEvents);
01624       }
01625    }
01626 
01627    printf("Total NQ Events : %d\n", NQEvents);
01628    printf("Total  Q Events  : %d\n", QEvents);
01629 
01630    return 0;
01631 }
01632 
01633 int prmShowEventByteStats( BYTE_RULE_MAP * p )
01634 {
01635    int i;
01636    PORT_GROUP * pg;
01637 
01638    int NQEvents = 0;
01639    int QEvents = 0;
01640 
01641    printf("Packet Classification Rule Manager Stats ----\n");
01642    printf("NumGroups   : %d\n",p->prmNumGroups);
01643    printf("\n");
01644    printf("NumRules    : %d\n",p->prmNumRules);
01645    printf("NumGenericRules: %d\n",p->prmNumGenericRules);
01646    printf("\n");
01647 
01648    printf("%d Byte Groups In Use, %d Unique Rules, includes generic\n",p->prmNumGroups,p->prmNumRules);
01649    for(i=0;i<256;i++)
01650    {
01651      pg = prmFindByteRuleGroupUnique( p, i );
01652      if(pg)
01653      {
01654        NQEvents += pg->pgNQEvents;
01655        QEvents  += pg->pgQEvents;
01656 
01657        if( pg->pgNQEvents + pg->pgQEvents )
01658        {
01659           printf("  Proto/Type %5d : %d group entries \n",i, pg->pgCount);
01660           printf("      NQ Events  : %d\n", pg->pgNQEvents);
01661           printf("       Q Events  : %d\n", pg->pgQEvents);
01662        }
01663      }
01664    }
01665 
01666    pg = &p->prmGeneric;
01667    if(pg)
01668    {
01669       NQEvents += pg->pgNQEvents;
01670       QEvents += pg->pgQEvents;
01671 
01672       if( pg->pgNQEvents + pg->pgQEvents )
01673       {
01674         printf("  Generic Rules : %d group entries\n", pg->pgCount);
01675         printf("    NQ Events   : %d\n", pg->pgNQEvents);
01676         printf("     Q Events   : %d\n", pg->pgQEvents);
01677       }
01678    }
01679 
01680    printf("Total NQ Events : %d\n", NQEvents);
01681    printf("Total  Q Events  : %d\n", QEvents);
01682 
01683    return 0;
01684 }

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