Azinix

limit.c

Go to the documentation of this file.
00001 
00002 #include "evl.h"
00003 
00004 /* Data structure for storing statistics */
00005 
00006 typedef struct Uc_Limit_t {
00007   int totalPkts;
00008   int maxPkts;
00009   util_timing_t lastArrivalTime;
00010   util_timing_t interval;
00011 } Uc_Limit_t;
00012 
00013 /**AutomaticStart */
00014 
00015 // prototypes of static functions
00016 static int Uc_UpdateLimit( Hash_t **hashPtr, char *argument );
00017 
00018 /**AutomaticEnd */
00019 
00020 
00021 /* \brief Code for limiting number of packets in a given time window.  
00022 
00023   Argument is of the form "double:int:string"
00024     - the double represents the time interval over which we measure
00025       the number of packets, in seconds
00026     - the int is the maximum number of packets we will allow
00027       in the specified time interval
00028     - the string represents the particular id of the calling rule
00029 
00030   Examples: "1.0:10:http req"  "0.01:1:ssh login"
00031 
00032   We need the string field, since there's a single function limit
00033   which may be used to limit the number of packets coming in more than
00034   one rule.  The string is used as a key in a hash table to get
00035   the corresponding limit structure.
00036 
00037 */
00038 
00039 int
00040 limit (Evl_Manager_t * mgr, Pkt_ProcessPkt_t * pp, void **mystate, void *argument )
00041 {
00042   static Hash_t *limitHash;
00043 
00044   return Uc_UpdateLimit( & limitHash, argument );
00045 }
00046 
00047 
00048 /** \brief Allocate and initialize the stats structure, add to hash */
00049 
00050 static Uc_Limit_t *
00051 Uc_GetLimitStruct( 
00052   Hash_t *hash,
00053   char *argument
00054 )
00055 {
00056   Uc_Limit_t *result;
00057 
00058   if ( Hash_Lookup( hash, argument, & result ) ) {
00059     return result;
00060   }
00061 
00062   result = ( Uc_Limit_t * ) malloc( sizeof( Uc_Limit_t ) );
00063 
00064   result->totalPkts = 0;
00065   util_timing_set( & result->lastArrivalTime );
00066 
00067   double interval;
00068   int maxPkts;
00069   sscanf( argument, "%lf %d", & interval, & maxPkts );
00070   result->interval = util_timing_pair( interval );
00071   result->maxPkts = maxPkts;
00072 
00073   Hash_Insert( hash, argument, result );
00074 
00075   return result;
00076 }
00077 
00078 
00079 /** \brief Update limits data */
00080 
00081 static int 
00082 Uc_UpdateLimit(
00083   Hash_t **hashPtr,
00084   char *argument
00085 )
00086 {
00087   if ( NIL( Hash_t ) == *hashPtr ) {
00088     // first ever call, so initialize the hashPtr
00089     *hashPtr = Hash_InitTable( strcmp, st_strhash );
00090   }
00091   Hash_t *hash = *hashPtr;
00092   Uc_Limit_t *limit = Uc_GetLimitStruct( hash, argument );
00093 
00094   util_timing_t currentTime;
00095   util_timing_set( & currentTime );
00096   util_timing_t diffTime = util_timing_diff( currentTime, limit->lastArrivalTime );
00097 
00098   if ( util_timing_compare( diffTime, limit->interval ) ) {
00099     limit->totalPkts++;
00100     if ( limit->totalPkts > limit->maxPkts ) {
00101       return 1; // should drop, over limit
00102     }
00103     else {
00104       return 0;
00105     }
00106   }
00107   else {
00108     // more than the interval time has elapsed, reset
00109     limit->lastArrivalTime = currentTime;
00110     limit->totalPkts = 0;
00111   }
00112   return 0;
00113 }