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

sfthd.c

Go to the documentation of this file.
00001 /*!
00002  *
00003  * \file sfthd.c  
00004  *
00005  * An Abstracted Event Thresholding System
00006  *
00007  * Copyright (C) 2003 Sourcefire,Inc.
00008  * Marc Norton
00009  *
00010  */
00011 
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <string.h>
00015 
00016 #include "sflsq.h"
00017 #include "sfghash.h"
00018 #include "sfxhash.h"
00019 
00020 #include "sfthd.h"
00021     
00022 static int s_id = 1;  /* thd_id generator for both local and global thresholds */
00023 
00024 /*
00025  *  Debug Printing
00026  */
00027 
00028 /* #define THD_DEBUG */
00029 
00030 
00031 /*
00032  *   This disables adding and testing of Threshold objects
00033  */
00034 /*
00035 #define CRIPPLE
00036 */
00037 
00038 /*!
00039   Create a threshold table, initialize the threshold system, 
00040   and optionally limit it's memory usage.
00041    
00042   @param nbytes maximum memory to use for thresholding objects, in bytes.
00043 
00044   @return  THD_STRUCT*
00045   @retval  0 error
00046   @retval !0 valid THD_STRUCT
00047 */
00048 THD_STRUCT * sfthd_new( unsigned nbytes )
00049 {
00050     THD_STRUCT * thd;
00051     int          nrows;
00052 
00053     /* Create the THD struct */   
00054     thd = (THD_STRUCT*) calloc(1,sizeof(THD_STRUCT));
00055     if( !thd )
00056     {
00057         return 0;
00058     }
00059 
00060     /* Calc max ip nodes for this memory */
00061     nrows = nbytes /( sizeof(THD_IP_NODE)+sizeof(THD_IP_NODE_KEY) );
00062 
00063 #ifndef CRIPPLE 
00064     /* Create global hash table for all of the IP Nodes */
00065     thd->ip_nodes = sfxhash_new( nrows,  /* try one node per row - for speed */
00066                                  sizeof(THD_IP_NODE_KEY), /* keys size */
00067                                  sizeof(THD_IP_NODE),     /* data size */
00068                                  nbytes,                  /* memcap **/
00069                                  1,         /* ANR flag - true ?- Automatic Node Recovery=ANR */
00070                                  0,         /* ANR callback - none */
00071                                  0,         /* user freemem callback - none */
00072                                  1 ) ;      /* Recycle nodes ?*/
00073     if( !thd->ip_nodes )
00074     {
00075 #ifdef THD_DEBUG            
00076             printf("Could not allocate the sfxhash table\n");
00077 #endif      
00078             free(thd);
00079             return 0;
00080     }
00081     
00082             
00083     /* Calc max ip nodes for global thresholding memory */
00084     nrows = nbytes /( sizeof(THD_IP_GNODE)+sizeof(THD_IP_GNODE_KEY) );
00085 
00086     /* Create global hash table for all of the Global-Thresholding IP Nodes */
00087     thd->ip_gnodes = sfxhash_new( nrows,  /* try one node per row - for speed */
00088                                   sizeof(THD_IP_GNODE_KEY), /* keys size */
00089                                   sizeof(THD_IP_GNODE),     /* data size */
00090                                   nbytes,                  /* memcap **/
00091                                   1,         /* ANR flag - true ?- Automatic Node Recovery=ANR */
00092                                   0,         /* ANR callback - none */
00093                                   0,         /* user freemem callback - none */
00094                                   1 ) ;      /* Recycle nodes ?*/
00095     if( !thd->ip_gnodes )
00096     {
00097 #ifdef THD_DEBUG            
00098             printf("Could not allocate the sfxhash table\n");
00099 #endif      
00100             free(thd);
00101             return 0;
00102     }
00103 
00104 
00105 #endif    
00106 
00107     return thd;
00108 }
00109 
00110 /*!
00111 
00112 Add a permanent threshold object to the threshold table. Multiple
00113 objects may be defined for each gen_id and sig_id pair. Internally
00114 a unique threshold id is generated for each pair.
00115 
00116 Threshold objects track the number of events seen during the time
00117 interval specified by seconds. Depending on the type of threshold
00118 object and the count value, the thresholding object determines if
00119 the current event should be logged or dropped.
00120 
00121 @param thd Threshold object from sfthd_new()
00122 @param gen_id Generator id
00123 @param sig_id Signauture id
00124 @param tracking Selects tracking by src ip or by dst ip
00125 @param type  Thresholding type: Limit, Threshold, or Limt+Threshold, Suppress  
00126 @param priority Assigns a relative priority to this object, higher numbers imply higher priority
00127 
00128 @param count Number of events
00129 @param seconds Time duration over which this threshold object acts.
00130 @param ip      IP address, for supression
00131 @param ip-mask IP mask, applied with ip_mask, for supression
00132 
00133 @return integer
00134 @retval  0 successfully added the thresholding object
00135 @retval !0 failed 
00136 
00137 */
00138 static
00139 int 
00140 sfthd_create_threshold_local(   THD_STRUCT * thd,
00141                                 unsigned     gen_id,
00142                                 unsigned     sig_id,
00143                                 int          tracking,
00144                                 int          type,
00145                                 int          priority,
00146                                 int          count,
00147                                 int          seconds,
00148                                 unsigned     ip_address,
00149                                 unsigned     ip_mask,
00150                 unsigned     not_flag)
00151 {
00152     SFGHASH  * sfthd_hash;
00153     int        nrows;
00154     int        hstatus;
00155     THD_ITEM * sfthd_item;
00156     THD_NODE * sfthd_node;
00157     THD_NODE * sfthd_n;
00158     SF_LNODE * lnode;
00159 
00160 
00161     if( !thd )
00162         return -1;
00163 
00164     if( gen_id >= THD_MAX_GENID )
00165         return -1;
00166 
00167 #ifdef CRIPPLE
00168     return 0;
00169 #endif    
00170     
00171     /* Check for an existing 'gen_id' entry, if none found than create one. */
00172     if( !thd->sfthd_array[ gen_id ] )
00173     {
00174         if( gen_id == 1 )/* patmatch rules gen_id, many rules */
00175         {
00176             nrows= THD_GEN_ID_1_ROWS;
00177         }
00178         else  /* other gen_id's */
00179         {
00180             nrows= THD_GEN_ID_ROWS;
00181         }
00182 
00183         /* Create the hash table for this gen_id */
00184         sfthd_hash = sfghash_new( nrows, sizeof(sig_id), 0, 0 );
00185         if( !sfthd_hash )
00186         {
00187             return -2; 
00188         }
00189 
00190         thd->sfthd_array[gen_id] = sfthd_hash;
00191     }
00192     else
00193     {
00194         /* Get the hash table for this gen_id */
00195         sfthd_hash = thd->sfthd_array[gen_id];
00196     }
00197 
00198     if( !sfthd_hash )
00199     {
00200          return -2;
00201     }
00202    
00203     
00204     /* Check if sig_id is already in the table - if not allocate it and add it */
00205     sfthd_item = (THD_ITEM*)sfghash_find( sfthd_hash, (void*)&sig_id );
00206     if( !sfthd_item )
00207     {  
00208         /* Create the sfthd_item hash node data */
00209         sfthd_item = (THD_ITEM*)calloc(1,sizeof(THD_ITEM));
00210         if( !sfthd_item )
00211         {
00212             return -3;
00213         }
00214 
00215         sfthd_item->gen_id          = gen_id;
00216         sfthd_item->sig_id          = sig_id;
00217         sfthd_item->sfthd_node_list = sflist_new();
00218 
00219         if(!sfthd_item->sfthd_node_list)
00220             return -4;
00221 
00222         /* Add the sfthd_item to the hash table */
00223         hstatus = sfghash_add( sfthd_hash, (void*)&sig_id, sfthd_item );
00224         if( hstatus )
00225         {
00226             return -5;
00227         }
00228     }     
00229 
00230     /* 
00231      * Test that we only have one Limit/Threshold/Both Object at the tail,
00232      * we can have multiple suppression nodes at the head
00233      */
00234     if( sfthd_item->sfthd_node_list->count > 0  )
00235     {
00236       THD_NODE * p;
00237       if( !sfthd_item->sfthd_node_list->tail) 
00238       {
00239               return -10; /* can you say paranoid- if there is a count, there should be a tail */
00240       }
00241       p = (THD_NODE*)sfthd_item->sfthd_node_list->tail->ndata;
00242       if(p) /* just to be safe- if thers a tail, there is is node data */
00243       {
00244          if( p->type != THD_TYPE_SUPPRESS && type != THD_TYPE_SUPPRESS )
00245          {
00246 #ifdef THD_DEBUG
00247              printf("THD_DEBUG: Could not add a 2nd Threshold object, you can onlky have 1 per sid: gid=%u, sid=%u\n",gen_id,sig_id);
00248 #endif   
00249              return THD_TOO_MANY_THDOBJ;/* cannot add more than one threshold per sid in version 3.0, wait for 3.2 and CIDR blocks */    
00250          }
00251       }
00252     }
00253 
00254     /* Create a THD_NODE for this THD_ITEM (Object) */
00255     sfthd_node = (THD_NODE*)calloc(1,sizeof(THD_NODE));
00256     if( !sfthd_node )
00257     {
00258         return -6;
00259     }
00260 
00261     /* Limit priorities to force supression nodes to highest priority */
00262     if( priority >= THD_PRIORITY_SUPPRESS )
00263     {
00264         priority  = THD_PRIORITY_SUPPRESS - 1;
00265     }
00266 
00267     /* Copy the node parameters */
00268     sfthd_node->thd_id    = s_id++;   /* produce a unique thd_id for this node */
00269     sfthd_node->gen_id    = gen_id;   
00270     sfthd_node->sig_id    = sig_id;   
00271     sfthd_node->tracking  = tracking; /* by_src, by_dst */
00272     sfthd_node->type      = type;
00273     sfthd_node->priority  = priority;
00274     sfthd_node->count     = count;
00275     sfthd_node->seconds   = seconds;
00276     sfthd_node->ip_address= ip_address;
00277     sfthd_node->ip_mask   = ip_mask;
00278     sfthd_node->not_flag  = not_flag;
00279    
00280     if( type == THD_TYPE_SUPPRESS )
00281     {
00282         sfthd_node->priority = THD_PRIORITY_SUPPRESS;
00283 
00284         if( sfthd_node->ip_mask == 0 && sfthd_node->ip_address != 0 )
00285         {
00286             sfthd_node->ip_mask = 0xffffffff;
00287         }
00288     }
00289 
00290     thd->count++;
00291 
00292     /*
00293       If sfthd_node list is empty - add as head node 
00294     */
00295     if( !sfthd_item->sfthd_node_list->count )
00296     {
00297 #ifdef THD_DEBUG
00298             printf("Threshold node added to head of list\n");fflush(stdout);
00299 #endif      
00300         sflist_add_head(sfthd_item->sfthd_node_list,sfthd_node);
00301     }
00302 
00303     /*
00304       else add the sfthd_node using priority to determine where in the list it belongs
00305 
00306       3.0 we can  have only 1 threshold object but several suppression objects plus a 
00307       single threshold object is ok.  Blocking multiple threshold objects is done above.
00308 
00309       Suppressions have the highest priority and are at the front of the list, the tail node
00310       is either a supprssion node or the only pure thresholding node.
00311     */
00312     else  
00313     {
00314         /* Walk the list and insert based on priorities if suppress */
00315         /* */
00316         for( lnode = sflist_first_node(sfthd_item->sfthd_node_list); 
00317              lnode; 
00318              lnode = sflist_next_node(sfthd_item->sfthd_node_list) )
00319         {
00320             sfthd_n = (THD_NODE*)lnode->ndata;
00321 
00322             /* check if the new node is higher priority */
00323             if( sfthd_node->priority > sfthd_n->priority  )
00324             {
00325                 /* insert before current node */
00326 #ifdef THD_DEBUG
00327             printf("Threshold node added after based on priority\n");fflush(stdout);
00328 #endif      
00329                 sflist_add_before(sfthd_item->sfthd_node_list,lnode,sfthd_node);
00330                 return 0;
00331             }
00332 
00333             /* last node, just insert it here */
00334             if( !lnode->next  ) 
00335             {
00336                 /* if last node, insert at end of list */
00337 #ifdef THD_DEBUG
00338             printf("Threshold node added to tail\n");fflush(stdout);
00339 #endif      
00340                 sflist_add_tail(sfthd_item->sfthd_node_list,sfthd_node);
00341                 return 0;
00342             }
00343         }
00344     }
00345 
00346     return 0;
00347 }
00348 
00349 
00350 /*
00351  *
00352  *
00353  */
00354 static
00355 int 
00356 sfthd_create_threshold_global(  THD_STRUCT * thd,
00357                                 unsigned     gen_id,
00358                                 unsigned     sig_id,
00359                                 int          tracking,
00360                                 int          type,
00361                                 int          priority,
00362                                 int          count,
00363                                 int          seconds,
00364                                 unsigned     ip_address,
00365                                 unsigned     ip_mask )
00366 {
00367     THD_NODE * sfthd_node;
00368            
00369     sfthd_node = (THD_NODE*)calloc(1,sizeof(THD_NODE));
00370     if( !sfthd_node )
00371     {
00372         return -2;
00373     }
00374 
00375     /* Copy the node parameters */
00376     sfthd_node->thd_id    = s_id++;   /* produce a unique thd_id for this node */
00377     sfthd_node->gen_id    = gen_id;   
00378     sfthd_node->sig_id    = sig_id;  /* -1 for global thresholds */ 
00379     sfthd_node->tracking  = tracking; /* by_src, by_dst */
00380     sfthd_node->type      = type;
00381     sfthd_node->priority  = priority;
00382     sfthd_node->count     = count;
00383     sfthd_node->seconds   = seconds;
00384     sfthd_node->ip_address= ip_address;
00385     sfthd_node->ip_mask   = ip_mask;
00386    
00387     if( sfthd_node->ip_mask == 0 && sfthd_node->ip_address != 0 )
00388     {
00389         sfthd_node->ip_mask = 0xffffffff;
00390     }
00391 
00392     /* need a hash of these where the key=[gen_id,sig_id] => THD_GNODE_KEY, the data = THD_NODE's */
00393     if( gen_id == 0)/* do em all */
00394     {
00395        int i;
00396        for(i=0;i<THD_MAX_GENID;i++)
00397            thd->sfthd_garray [ i ] =  sfthd_node;
00398     }
00399     else
00400     { 
00401        thd->sfthd_garray [ gen_id ] =  sfthd_node;
00402     }
00403 
00404 #ifdef THD_DEBUG
00405     printf("THD_DEBUG-GLOBAL: created global threshold object for gen_id=%d\n",gen_id);
00406     fflush(stdout);
00407 #endif    
00408     
00409     return 0;   
00410 }
00411 
00412 
00413 /*!
00414 
00415 Add a permanent threshold object to the threshold table. Multiple
00416 objects may be defined for each gen_id and sig_id pair. Internally
00417 a unique threshold id is generated for each pair.
00418 
00419 Threshold objects track the number of events seen during the time
00420 interval specified by seconds. Depending on the type of threshold
00421 object and the count value, the thresholding object determines if
00422 the current event should be logged or dropped.
00423 
00424 @param thd Threshold object from sfthd_new()
00425 @param gen_id Generator id
00426 @param sig_id Signauture id
00427 @param tracking Selects tracking by src ip or by dst ip
00428 @param type  Thresholding type: Limit, Threshold, or Limt+Threshold, Suppress  
00429 @param priority Assigns a relative priority to this object, higher numbers imply higher priority
00430 
00431 @param count Number of events
00432 @param seconds Time duration over which this threshold object acts.
00433 @param ip      IP address, for supression
00434 @param ip-mask IP mask, applied with ip_mask, for supression
00435 
00436 @return integer
00437 @retval  0 successfully added the thresholding object
00438 @retval !0 failed 
00439 
00440  --- Local and Global Thresholding is setup here  ---
00441 
00442 */
00443 int sfthd_create_threshold(     THD_STRUCT * thd,
00444                                 unsigned     gen_id,
00445                                 unsigned     sig_id,
00446                                 int          tracking,
00447                                 int          type,
00448                                 int          priority,
00449                                 int          count,
00450                                 int          seconds,
00451                                 unsigned     ip_address,
00452                 unsigned     ip_mask,
00453                 unsigned     not_flag)
00454 {
00455 
00456   if( sig_id == 0 )
00457   {
00458           return  sfthd_create_threshold_global( thd,
00459                                      gen_id,
00460                                      sig_id,
00461                                      tracking,
00462                                      type,
00463                                      priority,
00464                                      count,
00465                                      seconds,
00466                                      ip_address,
00467                                      ip_mask );
00468 
00469   }
00470   else
00471   {
00472       if( gen_id == 0 )
00473               return -1;
00474       
00475       return  sfthd_create_threshold_local( thd,
00476                                             gen_id,
00477                                             sig_id,
00478                                             tracking,
00479                                             type,
00480                                             priority,
00481                                             count,
00482                                             seconds,
00483                                             ip_address,
00484                                             ip_mask,
00485                                             not_flag );
00486   }
00487 }
00488 
00489 #ifdef THD_DEBUG
00490 static char * printIP(unsigned u )
00491 {
00492         static char s[80];
00493         snprintf(s,80,"%d.%d.%d.%d", (u>>24)&0xff, (u>>16)&0xff, (u>>8)&0xff, u&0xff );
00494         s[79]=0;
00495         return s;
00496 }
00497 #endif
00498 
00499 /*!
00500  *
00501  *  Find/Test/Add an event against a single threshold object.
00502  *  Events without thresholding objects are automatically loggable.
00503  *  
00504  *  @param thd     Threshold table pointer
00505  *  @param sfthd_node Permanent Thresholding Object
00506  *  @param sip     Event/Packet Src IP address- should be host ordered for comparison
00507  *  @param dip     Event/Packet Dst IP address
00508  *  @param curtime Current Event/Packet time in seconds
00509  *    
00510  *  @return  integer
00511  *  @retval   0 : Event is loggable 
00512  *  @retval  >0 : Event should not be logged, try next thd object
00513  *  @retval  <0 : Event should never be logged to this user! Suppressed Event+IP
00514  *
00515  */
00516 static
00517 int sfthd_test_object(  THD_STRUCT * thd,
00518                         THD_NODE   * sfthd_node,
00519                         unsigned     sip,   
00520                         unsigned     dip,
00521                         time_t       curtime )  
00522 {
00523     THD_IP_NODE_KEY key;
00524     THD_IP_NODE     data,*sfthd_ip_node;
00525     int             status=0;
00526     unsigned        ip,dt;
00527 
00528 #ifdef THD_DEBUG
00529         printf("THD_DEBUG: Key THD_NODE IP=%s,",printIP((unsigned)sfthd_node->ip_address) );
00530         printf(" MASK=%s\n",printIP((unsigned)sfthd_node->ip_mask) );
00531         printf("THD_DEBUG:        PKT  SIP=%s\n",printIP((unsigned)sip) );
00532         printf("THD_DEBUG:        PKT  DIP=%s\n",printIP((unsigned)dip) );
00533         fflush(stdout);
00534 #endif
00535 
00536     /*
00537      *  Get The correct IP  
00538      */
00539     if( sfthd_node->tracking== THD_TRK_SRC ) 
00540     {
00541        ip = sip;
00542     }
00543     else
00544     {
00545        ip = dip;
00546     }
00547     
00548     /*
00549      *  Check for and test Suppression of this event to this IP 
00550      */
00551     if( sfthd_node->type == THD_TYPE_SUPPRESS )
00552     {
00553 #ifdef THD_DEBUG
00554         printf("THD_DEBUG: SUPPRESS NODE Testing...\n");fflush(stdout);
00555 #endif
00556         if((sfthd_node->ip_address == (sfthd_node->ip_mask & ip) && !sfthd_node->not_flag) ||
00557            (sfthd_node->ip_address != (sfthd_node->ip_mask & ip) && sfthd_node->not_flag))
00558         { 
00559 #ifdef THD_DEBUG
00560             printf("THD_DEBUG: SUPPRESS NODE, do not log events with this IP\n");fflush(stdout);
00561 #endif
00562             return -1; /* Don't log, and stop looking( event's to this address for this gen_id+sig_id) */
00563         }
00564         return 1; /* Keep looking for other suppressors */
00565     }
00566 
00567     /*
00568     *  Go on and do standard thresholding
00569     */
00570     
00571     /* Set up the key */
00572     key.ip     = ip;
00573     key.thd_id = sfthd_node->thd_id;
00574 
00575     /* Set up a new data element */
00576     data.ip     = ip;
00577     data.count  = 1;
00578     data.tstart = curtime; /* Event time */
00579 
00580     /* 
00581      * Check for any Permanent sig_id objects for this gen_id  or add this one ...
00582      */
00583     status = sfxhash_add( thd->ip_nodes, (void*)&key, &data );
00584     
00585     if( status == SFXHASH_INTABLE )
00586     {
00587         /* Already in the table */
00588         sfthd_ip_node = thd->ip_nodes->cnode->data;
00589 
00590         /* Increment the event count */
00591         sfthd_ip_node->count++;
00592     }
00593     else if (status )
00594     {
00595         /* hash error */
00596         return 1; /*  check the next threshold object */
00597     }
00598     else
00599     {
00600         /* Was not in the table - it was added - work with our copy of the data */
00601         sfthd_ip_node = &data;
00602     }
00603 
00604 
00605     /*
00606      *  Do the appropriate test for the Threshold Object Type 
00607      */
00608     
00609     /*
00610       Limit
00611     */
00612     if( sfthd_node->type == THD_TYPE_LIMIT )
00613     {
00614 #ifdef THD_DEBUG
00615         printf("\n...Limit Test\n");
00616         fflush(stdout);
00617 #endif          
00618         dt = curtime - sfthd_ip_node->tstart;
00619         if( dt > sfthd_node->seconds )
00620         {   /* reset */
00621             sfthd_ip_node->tstart = curtime;
00622             sfthd_ip_node->count  = 1;
00623         }
00624 
00625 #ifdef THD_DEBUG
00626         printf("...dt=%d, sfthd_node->seconds=%d\n",dt,sfthd_node->seconds );
00627         printf("...sfthd_ip_node->count=%d, sfthd_node->count=%d\n",sfthd_ip_node->count,sfthd_node->count );
00628         fflush(stdout);
00629 #endif
00630         if( sfthd_ip_node->count <= sfthd_node->count )
00631         {
00632             return 0; /* Log it, stop looking: only log the 1st 'count' events */
00633         }
00634 
00635         return -1; /* Don't Log yet, don't keep looking : already logged our limit, don't log this sid  */
00636     }
00637     
00638     else if( sfthd_node->type == THD_TYPE_THRESHOLD )
00639     {
00640 #ifdef THD_DEBUG
00641         printf("\n...Threshold Test\n");
00642         fflush(stdout);
00643 #endif          
00644         dt = curtime - sfthd_ip_node->tstart;
00645         if( dt > sfthd_node->seconds )
00646         {
00647             sfthd_ip_node->tstart = curtime;
00648             sfthd_ip_node->count  = 1;
00649 
00650             return -1; /* Don't Log, keep looking: only log after we reach count, which must be > '1' */
00651         }
00652         else
00653         {
00654             if( sfthd_ip_node->count >= sfthd_node->count ) 
00655             {
00656                 /* reset */
00657                 sfthd_ip_node->count = 0;
00658                 sfthd_ip_node->tstart= curtime;
00659                         
00660                 return 0; /* Log it, stop looking */ 
00661             }
00662             return -1; /* don't log yet */
00663         }
00664     }
00665 
00666     else if( sfthd_node->type == THD_TYPE_BOTH )
00667     {
00668 #ifdef THD_DEBUG
00669         printf("\n...Threshold+Limit Test\n");
00670         fflush(stdout);
00671 #endif
00672         dt = curtime - sfthd_ip_node->tstart;
00673         if( dt > sfthd_node->seconds )
00674         {
00675             sfthd_ip_node->tstart = curtime;
00676             sfthd_ip_node->count  = 1;
00677 
00678             return -1; /* Don't Log yet, keep looking: only log after we reach count, which must be > '1' */
00679         }
00680         else
00681         {
00682             if( sfthd_ip_node->count >= sfthd_node->count ) 
00683             {
00684                 if( sfthd_ip_node->count >  sfthd_node->count ) 
00685                 {
00686                     return -1; /* don't log it, stop  looking, log once per time interval - than block it */
00687                 }
00688                 return 0; /* Log it, stop looking, log the 1st event we see past 'count' events */
00689             }
00690             else  /* Block it from logging */
00691             {
00692               return -1; /* don't log it, stop  looking,  we must see at least count events 1st */
00693             }
00694         }
00695     }
00696 
00697 #ifdef THD_DEBUG
00698         printf("THD_DEBUG: You should not be here...\n");
00699         fflush(stdout);
00700 #endif
00701 
00702         return 0;  /* should not get here, so log it just to be safe */
00703 }
00704 /*
00705  *
00706  *
00707  *
00708  *   Test a global thresholding object 
00709  *
00710  * 
00711  *   
00712  */ 
00713 static
00714 int sfthd_test_gobject( THD_STRUCT * thd,
00715                         THD_NODE   * sfthd_node,  
00716                         unsigned     gen_id,     /* from current event */
00717                         unsigned     sig_id,     /* from current event */
00718                         unsigned     sip,        /* " */
00719                         unsigned     dip,        /* " */
00720                         time_t       curtime )   
00721 {
00722     THD_IP_GNODE_KEY key;
00723     THD_IP_GNODE     data, *sfthd_ip_node;
00724     int              status=0;
00725     unsigned         ip, dt;
00726 
00727 #ifdef THD_DEBUG
00728         printf("THD_DEBUG-GLOBAL:  gen_id=%u, sig_id=%u\n",gen_id,sig_id);
00729         printf("THD_DEBUG: Global THD_NODE IP=%s,",printIP((unsigned)sfthd_node->ip_address) );
00730         printf(" MASK=%s\n",printIP((unsigned)sfthd_node->ip_mask) );
00731         printf("THD_DEBUG:        PKT  SIP=%s\n",printIP((unsigned)sip) );
00732         printf("THD_DEBUG:        PKT  DIP=%s\n",printIP((unsigned)dip) );
00733         fflush(stdout);
00734 #endif
00735 
00736     /*
00737      *  Get The correct IP  
00738      */
00739     if( sfthd_node->tracking== THD_TRK_SRC ) 
00740     {
00741        ip = sip;
00742     }
00743     else
00744     {
00745        ip = dip;
00746     }
00747     
00748     /*
00749      *  Check for and test Suppression of this event to this IP 
00750      */
00751     if( sfthd_node->type == THD_TYPE_SUPPRESS )
00752     {
00753 #ifdef THD_DEBUG
00754         printf("THD_DEBUG: G-SUPPRESS NODE Testing...\n");fflush(stdout);
00755 #endif
00756         if( sfthd_node->ip_address == (sfthd_node->ip_mask & ip) )
00757         { 
00758 #ifdef THD_DEBUG
00759             printf("THD_DEBUG: G-SUPPRESS NODE, do not log events with this IP\n");fflush(stdout);
00760 #endif
00761             return -1; /* Don't log, and stop looking( event's to this address for this gen_id+sig_id) */
00762         }
00763         return 1; /* Keep looking for other suppressors */
00764     }
00765 
00766     /*
00767     *  Go on and do standard thresholding
00768     */
00769     
00770     /* Set up the key */
00771     key.ip     = ip;
00772     key.gen_id = sfthd_node->gen_id;
00773     key.sig_id = sig_id;
00774 
00775     /* Set up a new data element */
00776     data.count  = 1;
00777     data.tstart = curtime; /* Event time */
00778 
00779     /* 
00780      * Check for any Permanent sig_id objects for this gen_id  or add this one ...
00781      */
00782     status = sfxhash_add( thd->ip_gnodes, (void*)&key, &data );
00783     
00784     if( status == SFXHASH_INTABLE )
00785     {
00786         /* Already in the table */
00787         sfthd_ip_node = thd->ip_gnodes->cnode->data;
00788 
00789         /* Increment the event count */
00790         sfthd_ip_node->count++;
00791     }
00792     else if (status )
00793     {
00794         /* hash error */
00795         return 1; /*  check the next threshold object */
00796     }
00797     else
00798     {
00799         /* Was not in the table - it was added - work with our copy of the data */
00800         sfthd_ip_node = &data;
00801     }
00802 
00803 
00804     /*
00805      *  Do the appropriate test for the Threshold Object Type 
00806      */
00807     
00808     /*
00809       Limit
00810     */
00811     if( sfthd_node->type == THD_TYPE_LIMIT )
00812     {
00813 #ifdef THD_DEBUG
00814         printf("\n...Limit Test\n");
00815         fflush(stdout);
00816 #endif          
00817         dt = curtime - sfthd_ip_node->tstart;
00818         if( dt > sfthd_node->seconds )
00819         {   /* reset */
00820             sfthd_ip_node->tstart = curtime;
00821             sfthd_ip_node->count  = 1;
00822         }
00823 
00824 #ifdef THD_DEBUG
00825         printf("...dt=%d, sfthd_node->seconds=%d\n",dt, sfthd_node->seconds );
00826         printf("...sfthd_ip_node->count=%d, sfthd_node->count=%d\n",sfthd_ip_node->count,sfthd_node->count );
00827         fflush(stdout);
00828 #endif
00829         if( sfthd_ip_node->count <= sfthd_node->count )
00830         {
00831             return 0; /* Log it, stop looking: only log the 1st 'count' events */
00832         }
00833 
00834         return -1; /* Don't Log yet, don't keep looking : already logged our limit, don't log this sid  */
00835     }
00836     
00837     else if( sfthd_node->type == THD_TYPE_THRESHOLD )
00838     {
00839 #ifdef THD_DEBUG
00840         printf("\n...Threshold Test\n");
00841         fflush(stdout);
00842 #endif          
00843         dt = curtime - sfthd_ip_node->tstart;
00844         if( dt > sfthd_node->seconds )
00845         {
00846             sfthd_ip_node->tstart = curtime;
00847             sfthd_ip_node->count  = 1;
00848 
00849             return -1; /* Don't Log, keep looking: only log after we reach count, which must be > '1' */
00850         }
00851         else
00852         {
00853             if( sfthd_ip_node->count >= sfthd_node->count ) 
00854             {
00855                 /* reset */
00856                 sfthd_ip_node->count = 0;
00857                 sfthd_ip_node->tstart= curtime;
00858                         
00859                 return 0; /* Log it, stop looking */ 
00860             }
00861             return -1; /* don't log yet */
00862         }
00863     }
00864 
00865     else if( sfthd_node->type == THD_TYPE_BOTH )
00866     {
00867 #ifdef THD_DEBUG
00868         printf("\n...Threshold+Limit Test\n");
00869         fflush(stdout);
00870 #endif
00871         dt = curtime - sfthd_ip_node->tstart;
00872         if( dt > sfthd_node->seconds )
00873         {
00874             sfthd_ip_node->tstart = curtime;
00875             sfthd_ip_node->count  = 1;
00876 
00877             return -1; /* Don't Log yet, keep looking: only log after we reach count, which must be > '1' */
00878         }
00879         else
00880         {
00881             if( sfthd_ip_node->count >= sfthd_node->count ) 
00882             {
00883                 if( sfthd_ip_node->count >  sfthd_node->count ) 
00884                 {
00885                     return -1; /* don't log it, stop  looking, log once per time interval - than block it */
00886                 }
00887                 return 0; /* Log it, stop looking, log the 1st event we see past 'count' events */
00888             }
00889             else  /* Block it from logging */
00890             {
00891               return -1; /* don't log it, stop  looking,  we must see at least count events 1st */
00892             }
00893         }
00894     }
00895 
00896 #ifdef THD_DEBUG
00897         printf("THD_DEBUG: You should not be here...\n");
00898         fflush(stdout);
00899 #endif
00900 
00901         return 0;  /* should not get here, so log it just to be safe */
00902 }
00903 
00904 
00905 /*!
00906  *
00907  *  Test a an event against the threshold database.  
00908  *  Events without thresholding objects are automatically 
00909  *  loggable.
00910  *  
00911  *  @param thd     Threshold table pointer
00912  *  @param gen_id  Generator Id from the event
00913  *  @param sig_id  Signature Id from the event
00914  *  @param sip     Event/Packet Src IP address
00915  *  @param dip     Event/Packet Dst IP address
00916  *  @param curtime Current Event/Packet time
00917  *    
00918  *  @return  integer
00919  *  @retval  0 : Event is loggable 
00920  *  @retval !0 : Event should not be logged
00921  *
00922  */
00923 int sfthd_test_threshold( THD_STRUCT * thd,
00924                           unsigned gen_id,  
00925                           unsigned sig_id,
00926                           unsigned sip,   
00927                           unsigned dip,
00928                           long     curtime )  
00929 {
00930     SFGHASH  * sfthd_hash; 
00931     THD_ITEM * sfthd_item;
00932     THD_NODE * sfthd_node, * g_thd_node;
00933     int cnt;
00934     int status=0;
00935 
00936 #ifdef CRIPPLE
00937     return 0;
00938 #endif
00939 
00940 #ifdef THD_DEBUG
00941     printf("sfthd_test_threshold...\n");fflush(stdout);
00942 #endif    
00943     if( gen_id >= THD_MAX_GENID )
00944     {
00945 #ifdef THD_DEBUG
00946         printf("THD_DEBUG: invalid gen_id=%u\n",gen_id);
00947         fflush(stdout);
00948 #endif  
00949         return 0; /* bogus gen_id */
00950     }
00951 
00952     /*
00953      *  Get the hash table for this gen_id
00954      */
00955     sfthd_hash = thd->sfthd_array [ gen_id ];
00956     if( !sfthd_hash )
00957     {
00958 #ifdef THD_DEBUG
00959         printf("THD_DEBUG: no hash table entry for gen_id=%u\n",gen_id);
00960         fflush(stdout);
00961 #endif      
00962         goto global_test;       
00963         /* return 0; */ /* no threshold objects for this gen_id, log it ! */
00964     }
00965 
00966     /* 
00967      * Check for any Permanent sig_id objects for this gen_id 
00968      */
00969     sfthd_item = (THD_ITEM*)sfghash_find( sfthd_hash, (void*)&sig_id );
00970     if( !sfthd_item )
00971     {
00972 #ifdef THD_DEBUG
00973         printf("THD_DEBUG: no THD objects for gen_id=%u, sig_id=%u\n",gen_id,sig_id);
00974         fflush(stdout);
00975 #endif       
00976         goto global_test;       
00977         /* return 0; */ /* no matching permanent sig_id objects so, log it ! */
00978     }
00979    
00980     /* No List of Threshold objects - bail and log it */ 
00981     if( !sfthd_item->sfthd_node_list )
00982     {
00983           goto global_test;     
00984           /*  return 0; */
00985     }
00986                     
00987     /* For each permanent thresholding object, test/add/update the thd object */
00988     /* We maintain a list of thd objects for each gen_id+sig_id */
00989     /* each object has it's own unique thd_id */
00990     /* Suppression nodes have a very high priority, so they are tested 1st */
00991     cnt=0;
00992     for( sfthd_node  = (THD_NODE*)sflist_first(sfthd_item->sfthd_node_list);
00993          sfthd_node != 0;
00994          sfthd_node  = (THD_NODE*)sflist_next(sfthd_item->sfthd_node_list) )
00995     {
00996         cnt++;
00997         
00998 #ifdef THD_DEBUG
00999         printf("THD_DEBUG: gen_id=%u sig_id=%u testing thd_id=%d thd_type=%d\n",
01000                         gen_id, sig_id, sfthd_node->thd_id, sfthd_node->type);
01001         fflush(stdout);
01002 #endif
01003         /*
01004          *   Test SUPPRESSION and THRESHOLDING
01005          *
01006          *   For 3.0 SUPPRESSION returns -1 to suppress, +1 to keep on testing the next object
01007          *           THRESHOLDING returns -1 to suppress, and 0 to log
01008          */
01009         status = sfthd_test_object( thd, sfthd_node, sip, dip, curtime );
01010         
01011         if( status < 0 ) /* -1 == Don't log and stop looking */
01012         {
01013 #ifdef THD_DEBUG
01014                 printf("THD_DEBUG: gen_id=%u sig_id=%u, UnLoggable\n\n",gen_id, sig_id,cnt);
01015                 fflush(stdout);
01016 #endif
01017                 return 1;  /* 1 == Don't log it*/
01018         }
01019         else if( status == 0 )  /* Log it and stop looking */
01020         {
01021 #ifdef THD_DEBUG
01022                 printf("THD_DEBUG: gen_id=%u sig_id=%u tested %d THD_NODE's, Loggable\n\n",sfthd_item->gen_id, sfthd_item->sig_id,cnt);
01023                 fflush(stdout);
01024 #endif
01025                 return 0; /* 0 == Log the event */
01026         }
01027         /* status > 0 : Log it later but Keep looking....check the next threshold object for a blocking action ... 
01028         *              For 3.0 SUPPRESS objects return +1 if they don't suppress... so we can fall out of this loop
01029         *              to log by returning 0 below....
01030         */
01031     }
01032 
01033 
01034     /*
01035      * 
01036      * 
01037      *  Test for a global threshold object  - we're here cause ther were no threshold objects for this gen_id/sig_id pair
01038      *
01039      *  
01040      */
01041 global_test:
01042 
01043 #ifdef THD_DEBUG
01044     printf("THD_DEBUG-GLOBAL: doing global object test\n");
01045 #endif    
01046      
01047      g_thd_node = thd->sfthd_garray[ gen_id ];
01048      if( g_thd_node )
01049      {
01050          status = sfthd_test_gobject( thd, g_thd_node, sig_id, gen_id, sip, dip, curtime );
01051          if( status < 0 ) /* -1 == Don't log and stop looking */
01052          {
01053 #ifdef THD_DEBUG
01054             printf("THD_DEBUG-GLOBAL: gen_id=%u sig_id=%u THD_NODE's, UnLoggable\n\n",gen_id, sig_id);
01055             fflush(stdout);
01056 #endif
01057             return 1;  /* 1 == Don't log it*/
01058          }
01059 
01060          /* Log it ! */
01061 #ifdef THD_DEBUG
01062         printf("THD_DEBUG-GLOBAL: gen_id=%u sig_id=%u  THD_NODE's, Loggable\n\n",gen_id, sig_id);
01063         fflush(stdout);
01064 #endif
01065      }
01066      else
01067      {
01068 #ifdef THD_DEBUG
01069         printf("THD_DEBUG-GLOBAL: no Global THD Object for gen_id=%u, sig_id=%u\n\n",gen_id, sig_id);
01070         fflush(stdout);
01071 #endif
01072      }
01073      
01074     return 0; /* Default: Log it if we did not block the logging action */
01075 }
01076 
01077 /*!
01078  *   A function to print the thresholding objects to stdout.
01079  *
01080  */
01081 int sfthd_show_objects( THD_STRUCT * thd )
01082 {
01083     SFGHASH  * sfthd_hash; 
01084     THD_ITEM * sfthd_item;
01085     THD_NODE * sfthd_node;
01086     int        gen_id;
01087     SFGHASH_NODE * item_hash_node;
01088 
01089     for(gen_id=0;gen_id < THD_MAX_GENID ; gen_id++ )
01090     {
01091         sfthd_hash = thd->sfthd_array [ gen_id ];
01092         if( !sfthd_hash )
01093         {
01094             continue;
01095         }
01096 
01097         printf("...GEN_ID = %u\n",gen_id);
01098 
01099         for(item_hash_node  = sfghash_findfirst( sfthd_hash );
01100             item_hash_node != 0; 
01101             item_hash_node  = sfghash_findnext( sfthd_hash ) )
01102         {
01103             /* Check for any Permanent sig_id objects for this gen_id */
01104             sfthd_item = (THD_ITEM*)item_hash_node->data;
01105 
01106             printf(".....GEN_ID = %u, SIG_ID = %u\n",gen_id,sfthd_item->sig_id);
01107      
01108             /* For each permanent thresholding object, test/add/update the thd object */
01109             /* We maintain a list of thd objects for each gen_id+sig_id */
01110             /* each object has it's own unique thd_id */
01111 
01112             for( sfthd_node  = (THD_NODE*)sflist_first(sfthd_item->sfthd_node_list);
01113                  sfthd_node != 0;
01114                  sfthd_node = (THD_NODE*)sflist_next(sfthd_item->sfthd_node_list) )
01115             {
01116                 printf(".........THD_ID  =%d\n",sfthd_node->thd_id );
01117                
01118                 if( sfthd_node->type == THD_TYPE_SUPPRESS )
01119                 printf(".........type    =Suppress\n");
01120                 if( sfthd_node->type == THD_TYPE_LIMIT )
01121                 printf(".........type    =Limit\n");
01122                 if( sfthd_node->type == THD_TYPE_THRESHOLD )
01123                 printf(".........type    =Threshold\n");
01124                 if( sfthd_node->type == THD_TYPE_BOTH )
01125                 printf(".........type    =Both\n");
01126                 
01127                 printf(".........tracking=%d\n",sfthd_node->tracking);
01128                 printf(".........priority=%d\n",sfthd_node->priority);
01129                   
01130                 if( sfthd_node->type == THD_TYPE_SUPPRESS )
01131                 {
01132                     printf(".........ip      =%d\n",sfthd_node->ip_address);
01133                     printf(".........mask    =%d\n",sfthd_node->ip_mask);
01134                     printf(".........not_flag=%d\n",sfthd_node->ip_mask);
01135                 }
01136                 else
01137                 {
01138                     printf(".........count   =%d\n",sfthd_node->count);
01139                     printf(".........seconds =%d\n",sfthd_node->seconds);
01140                 }
01141             }
01142         }
01143     }
01144 
01145     return 0;
01146 }
01147 

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