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

unique_tracker.c

Go to the documentation of this file.
00001 /**
00002  * @file   unique_tracker.c
00003  * @author Chris Green <cmg@sourcefire.com>
00004  * @date   Fri Jun  6 10:32:17 2003
00005  * 
00006  * @brief  track the uniqueness of an address's connections
00007  * 
00008  * This "uniqueness tracker" is meant to give a long running view of
00009  * what is unique to a particular session.
00010  *
00011  * It's basically a hash of everything in the FLOWKEY save for the
00012  * source port.  This should be hit for every "new connection".
00013  *
00014  */
00015 
00016 #ifdef HAVE_CONFIG_H
00017 #include "config.h"
00018 #endif
00019 
00020 #include "unique_tracker.h"
00021 #include "sfxhash.h"
00022 
00023 typedef struct _UT_KEY
00024 {
00025     u_int32_t sip;
00026     u_int32_t dip;
00027     u_int16_t dport;
00028     char     protocol;
00029 } UT_KEY;
00030 
00031 static UT_KEY s_ut_key; /* static entry that will always be zeroed out at init */
00032 static int s_debug = 0;
00033 
00034 /* utility */
00035 static void ut_init_entry(void);
00036 
00037 
00038 int ut_init(UNIQUE_TRACKER *utp, unsigned int rows, int memcap)
00039 {
00040     if(!utp)
00041         return FLOW_ENULL;
00042 
00043     ut_init_entry();
00044     
00045     memset(utp, 0, sizeof(UNIQUE_TRACKER));
00046     
00047     /* what size should we do? */
00048     utp->ipv4_table = sfxhash_new(rows,             /* # of rows in HT*/
00049                                   sizeof(UT_KEY),    /* size of the key  */
00050                                   0,                 /* data size */
00051                                   memcap,            /* how much memory is alloted */
00052                                   1,                 /* auto recover nodes */
00053                                   NULL,              /* autorecovery function */
00054                                   NULL,              /* free function for the data */
00055                                   1);                /* recycle old nodes */
00056 
00057     if(utp->ipv4_table == NULL)
00058     {
00059         if(s_debug)
00060             flow_printf("ran out of memory!\n");
00061         return FLOW_ENOMEM;
00062     }
00063 
00064     return FLOW_SUCCESS;
00065 }
00066 
00067 /** 
00068  * Destroy a table completely
00069  * 
00070  * @param utp table to kill
00071  * 
00072  * @return FLOW_SUCCESS when table is gone
00073  */
00074 int ut_destroy(UNIQUE_TRACKER *utp)
00075 {
00076     if(!utp)
00077         return FLOW_ENULL;
00078 
00079     if(!utp->ipv4_table)
00080         return FLOW_SUCCESS;
00081 
00082     sfxhash_delete(utp->ipv4_table);
00083     
00084     return FLOW_SUCCESS;
00085 }
00086 
00087 /** 
00088  * Determine if a flowkey is sufficiently unique to be called new
00089  *
00090  * This assumes that sfxhash_add performs a splay to the top on an
00091  * INTABLE add.  This must be updated if that's ever changed.
00092  *
00093  * @param utp tracker to use
00094  * @param keyp key to check
00095  * @param 
00096  * @return FLOW_SUCCESS if the check went OK
00097  */
00098 int ut_check(UNIQUE_TRACKER *utp, FLOWKEY *keyp, UT_TYPE *retval)
00099 {
00100     int ret;
00101     UT_KEY *utkeyp = &s_ut_key;  /* always a key that has been initialize */
00102 
00103     if(!retval || !utp || !utp->ipv4_table)
00104         return FLOW_ENULL;
00105 
00106     utkeyp->protocol = keyp->protocol;
00107     utkeyp->sip      = keyp->init_address;
00108     utkeyp->dip      = keyp->resp_address;
00109     utkeyp->dport    = keyp->resp_port;
00110 
00111     ret = sfxhash_add(utp->ipv4_table, utkeyp, NULL);
00112 
00113     switch(ret)
00114     {
00115     case SFXHASH_NOMEM:
00116         /* NOMEM means that we would add it if we could but we're
00117          *  hard-core out of space.  So, just assume we added it.
00118          */
00119     case SFXHASH_OK:
00120         *retval = UT_NEW;
00121         break;
00122     case SFXHASH_INTABLE:
00123         *retval = UT_OLD;
00124         break;
00125     }
00126 
00127     return FLOW_SUCCESS;        
00128 }
00129 
00130     
00131 
00132 /** 
00133  * initialize the static s_init_key variable once and only once.This
00134  * is used to zero out the key so that if the compiler pads the
00135  * structure, we still have 0's in this keylookup.
00136  * 
00137  */
00138 static void ut_init_entry(void)
00139 {
00140     static int init_once = 1;
00141 
00142     if(init_once)
00143     {
00144         init_once = 0;
00145         memset(&s_ut_key, 0, sizeof(UT_KEY));
00146     }
00147 }
00148 
00149 /** 
00150  * Print out the entirety of the unique tracker
00151  * 
00152  * @param ssp unique tracker
00153  */
00154 void unique_tracker_dump(UNIQUE_TRACKER *ssp)
00155 {
00156     SFXHASH_NODE *nodep;
00157     char buf[32 + 1];
00158     
00159     if(ssp && ssp->ipv4_table)
00160     {
00161         for( nodep = sfxhash_ghead(ssp->ipv4_table);
00162              nodep != NULL;
00163              nodep = sfxhash_gnext(nodep) )
00164         {
00165             UT_KEY *kp = (UT_KEY *) nodep->key;
00166 
00167             snprintf(buf, 32, "%15s", inet_ntoa(*(struct in_addr *)&kp->sip));
00168             buf[32] = '\0';
00169             
00170             flow_printf("%s -> (proto:%d %s:%d)\n",
00171                         buf,
00172                         kp->protocol,
00173                         inet_ntoa(*(struct in_addr *)&kp->dip),
00174                         kp->dport);
00175         }
00176     }
00177     else
00178     {
00179         flow_printf("nothing to dump!\n");
00180     }
00181 }
00182 
00183 
00184 /** 
00185  * 
00186  * 
00187  * @param utp unique tracker ptr
00188  * @param dumpall if 1, dump the contents of the tracker
00189  */
00190 void ut_stats(UNIQUE_TRACKER *utp, int dumpall)
00191 {
00192     unsigned total   = sfxhash_find_total(utp->ipv4_table);
00193     unsigned fail    = sfxhash_find_fail(utp->ipv4_table);
00194     unsigned success = sfxhash_find_success(utp->ipv4_table);
00195     
00196     flow_printf("UNIQUE_TRACKER STATS\n");
00197     flow_printf("   Memcap: %u  Overhead Bytes: %u\n",
00198                 ut_memcap(utp), ut_overhead_bytes(utp));
00199     
00200     flow_printf("   Finds: %u (Sucessful: %u(%%%lf) Unsucessful: %u(%%%lf))\n",
00201                 total,
00202                 success, calc_percent(success,total),
00203                 fail, calc_percent(fail,total));
00204 
00205     flow_printf("   Nodes: %u\n", sfxhash_count(utp->ipv4_table));
00206     
00207     flow_printf("   Recovered Nodes: %u\n", sfxhash_anr_count(utp->ipv4_table));
00208 
00209     if(dumpall)
00210         unique_tracker_dump(utp);
00211         
00212 }
00213 
00214 
00215 /** 
00216  * get the memcap
00217  * 
00218  * @param utp ptr to get the memcap of something
00219  * 
00220  * @return memcap or -1
00221  */
00222 int ut_memcap(UNIQUE_TRACKER *utp)
00223 {
00224     if(utp != NULL && utp->ipv4_table != NULL)        
00225         return utp->ipv4_table->mc.memcap;
00226 
00227     return -1;            
00228 }
00229 
00230 /** 
00231  * get the # of rows in table
00232  * 
00233  * @param sbp ut ptr to return the memcap of
00234  * 
00235  * @return nrows or -1
00236  */
00237 int ut_row_count(UNIQUE_TRACKER *utp)
00238 {
00239     if(utp != NULL && utp->ipv4_table != NULL)        
00240         return utp->ipv4_table->nrows;
00241 
00242     return -1;            
00243 }
00244 
00245 /** 
00246  * get the overhead # of bytes
00247  * 
00248  * @param sbp UNIQUE_TRACKER ptr to return the memcap of
00249  * 
00250  * @return nrows or -1
00251  */
00252 int ut_overhead_bytes(UNIQUE_TRACKER *sbp)
00253 {
00254     if(sbp != NULL && sbp->ipv4_table != NULL)
00255         return sfxhash_overhead_bytes(sbp->ipv4_table);
00256 
00257     return -1;            
00258 }
00259 

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