⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sfghash.c

📁 著名的入侵检测系统snort的最新版本的源码
💻 C
字号:
/**************************************************************************** * * Copyright (C) 2003-2007 Sourcefire, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation.  You may not use, modify or * distribute this program under any other version of the GNU General * Public License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************//***  sfghash.c**  Generic hash table library.**  This hash table maps unique keys to void data pointers.**  Features:*    1) Keys may be ascii strings of variable size, or*       fixed length (per table) binary byte sequences.  This*       allows use as a Mapping for String+Data pairs, or a *       generic hashing.*    2) User can allocate keys, or pass copies and we can *       allocate space and save keys.*    3) User can pass a free function to free up user data*       when the table is deleted.*    4) Table rows sizes can be automatically adjusted to*       the nearest prime number size.**  6/10/03 - man - Upgraded the hash function to a Hardened hash function,*      it has no predictable cycles, and each hash table gets a different*      randomized hashing function. So even with the source code, you cannot predict *      anything with this function.  If an  attacker can can setup a feedback*      loop he might gain some knowledge of how to muck with us, but even in that case*      his odds are astronomically skinny.  This is actually the same problem as solved*      early on with hashing functions where degenerate data with close keys could*      produce very long bucket chains.**  8/31/06 - man - Added prime tables to speed up prime number lookup.* * Author: Marc Norton**/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include "sfghash.h"#include "sfprimetable.h"/**  Private Malloc*/static void * s_alloc( int n ){     return calloc( 1,n );}/**  Private Free*/static void s_free( void * p ){   if( p )free( p );}/***    Create a new hash table**    nrows    : number of rows in hash table, primes are best.*               > 0  => we use the nearest prime internally*               < 0  => we use the magnitude as nrows.*    keysize  : > 0 => bytes in each key, keys are binary bytes,*               all keys are the same size.*               ==0 => keys are strings and are null terminated, *               allowing random key lengths. *    userkeys : > 0 => indicates user owns the key data*               and we should not allocate or free space for it,*               nor should we attempt to free the user key. We just*               save the pointer to the key. *               ==0 => we should copy the keys and manage them internally*    userfree : routine to free users data, null if we should not *               free user data in sfghash_delete(). The routine*               should be of the form 'void userfree(void * userdata)',*               'free' works for simple allocations.*/SFGHASH * sfghash_new( int nrows, int keysize, int userkeys, void (*userfree)(void*p) ){   int    i;   SFGHASH * h;   if( nrows > 0 ) /* make sure we have a prime number */   {      nrows = sf_nearest_prime( nrows );   }   else   /* use the magnitude or nrows as is */   {       nrows = -nrows;   }   h = (SFGHASH*)s_alloc( sizeof(SFGHASH) );   if( !h ) 	   return 0;   memset( h, 0, sizeof(SFGHASH) );   h->sfhashfcn = sfhashfcn_new( nrows );   if( !h->sfhashfcn )    {       free(h);	   return 0;   }   h->table = (SFGHASH_NODE**) s_alloc( sizeof(SFGHASH_NODE*) * nrows );   if( !h->table )    {       free(h->sfhashfcn);       free(h);	   return 0;   }   for( i=0; i<nrows; i++ )   {      h->table[i] = 0;   }   h->userkey = userkeys;   h->keysize = keysize;   h->nrows = nrows;   h->count = 0;   h->userfree = userfree;   h->crow = 0; // findfirst/next current row   h->cnode = 0; // findfirst/next current node ptr   return h;}/**  Set Splay mode : Splays nodes to front of list on each access*/void sfghash_splaymode( SFGHASH * t, int n ){   t->splay = n;}/**  Delete the hash Table **  free key's, free node's, and free the users data, if they*  supply a free function */void sfghash_delete( SFGHASH * h ){  int            i;  SFGHASH_NODE * node, * onode;  if( !h ) return;   sfhashfcn_free( h->sfhashfcn );  if( h->table )  {      for(i=0;i<h->nrows;i++)    {      for( node=h->table[i]; node;  )      {        onode = node;        node  = node->next;        if( !h->userkey && onode->key )             s_free( onode->key );        if( h->userfree && onode->data )            h->userfree( onode->data ); /* free users data, with users function */        s_free( onode );      }    }    s_free( h->table );    h->table = 0;  }  s_free( h );}/**  Get the # of Nodes in HASH the table*/int sfghash_count( SFGHASH * t ){  return t->count;}/**  Add a key + data pair*  ---------------------**  key + data should both be non-zero, although data can be zero**  t    - hash table*  key  - users key data (should be unique in this table)*         may be ascii strings or fixed size binary keys*  data - users data pointer**  returns  SF_HASH_NOMEM: alloc error*           SF_HASH_INTABLE : key already in table (t->cnode points to the node)*           SF_OK: added a node for this key + data pair**  Notes:*  If the key node already exists, then t->cnode points to it on return,*  this allows you to do something with the node - like add the data to a *  linked list of data items held by the node, or track a counter, or whatever.**/int sfghash_add( SFGHASH * t, void * key, void * data ){    unsigned    hashkey;	int         klen;    int         index;    SFGHASH_NODE  *hnode;    /*    *   Get proper Key Size    */      if( t->keysize > 0  )    {        klen = t->keysize;    }    else    {	     /* need the null byte for strcmp() in sfghash_find() */        klen = strlen( (char*)key ) + 1;    }        hashkey = t->sfhashfcn->hash_fcn(  t->sfhashfcn, (unsigned char*) key, klen );        index = hashkey % t->nrows;    /*    *  Uniqueness:     *  Check 1st to see if the key is already in the table    *  Just bail if it is.    */    for( hnode=t->table[index]; hnode; hnode=hnode->next )    {       if( t->keysize > 0 )       {          if( !t->sfhashfcn->keycmp_fcn(hnode->key,key,klen) )          {              t->cnode = hnode; /* save pointer to the node */              return SFGHASH_INTABLE; /* found it */          }       }       else       {         if( !strcmp((const char *)hnode->key,(const char*)key) )         {             t->cnode = hnode; /* save pointer to the node */             return SFGHASH_INTABLE; /* found it */         }       }    }    /*     *  Create new node     */    hnode = (SFGHASH_NODE*)s_alloc(sizeof(SFGHASH_NODE));    if( !hnode )         return SFGHASH_NOMEM;        /* Add the Key */    if( t->userkey )    {      /* Use the Users key */      hnode->key = key;    }    else    {      /* Create new key */      hnode->key = s_alloc( klen );      if( !hnode->key )      {           free(hnode);           return SFGHASH_NOMEM;      }      /* Copy key  */      memcpy(hnode->key,key,klen);    }        /* Add The Node */    if( t->table[index] ) /* add the node to the existing list */    {        hnode->prev = 0;  // insert node as head node        hnode->next=t->table[index];        hnode->data=data;        t->table[index]->prev = hnode;        t->table[index] = hnode;    }    else /* 1st node in this list */    {        hnode->prev=0;        hnode->next=0;        hnode->data=data;        t->table[index] = hnode;    }    t->count++;    return SFGHASH_OK;}/**  move a node to the front of the list*/static void movetofront( SFGHASH *t , int index, SFGHASH_NODE * n ){    if( t->table[index] != n ) // if not at front of list already...    {      /* Unlink the node */      if( n->prev ) n->prev->next = n->next;      if( n->next ) n->next->prev = n->prev;            /* Link at front of list */      n->prev=0;      n->next=t->table[index];      t->table[index]->prev=n;    }}/**  Find a Node based on the key, return users data.*/static SFGHASH_NODE * sfghash_find_node( SFGHASH * t, void * key){    unsigned    hashkey;    int         index, klen;    SFGHASH_NODE  *hnode;    if( t->keysize  )    {	klen = t->keysize;    }    else    {	klen = strlen( (char*) key ) + 1;    }    hashkey = t->sfhashfcn->hash_fcn(  t->sfhashfcn, (unsigned char*) key, klen );        index = hashkey % t->nrows;       for( hnode=t->table[index]; hnode; hnode=hnode->next )    {        if( t->keysize == 0 )        {           if( !strcmp((char*)hnode->key,(char*)key) )           {               if( t->splay  > 0 )                   movetofront(t,index,hnode);               return hnode;           }        }        else        {           if( !t->sfhashfcn->keycmp_fcn(hnode->key,key,t->keysize) )           {               if( t->splay  > 0 )                   movetofront(t,index,hnode);               return hnode;           }        }    }   return NULL;}/**  Find a Node based on the key, return users data.*/void * sfghash_find( SFGHASH * t, void * key){    SFGHASH_NODE * hnode;    hnode = sfghash_find_node( t, key );    if( hnode ) return hnode->data;    return NULL;}/**  Unlink and free the node*/static int sfghash_free_node( SFGHASH * t, unsigned index, SFGHASH_NODE * hnode ){    if( !t->userkey && hnode->key )         s_free( hnode->key );    hnode->key = 0;    if( t->userfree && hnode->data )        t->userfree( hnode->data ); /* free users data, with users function */    if( hnode->prev )  // not the 1st node    {          hnode->prev->next = hnode->next;          if( hnode->next ) hnode->next->prev = hnode->prev;    }    else if( t->table[index] )  // 1st node    {           t->table[index] = t->table[index]->next;           if( t->table[index] )t->table[index]->prev = 0;    }    s_free( hnode );    t->count--;    return SFGHASH_OK;}/**  Remove a Key/Data Pair from the table - find it, unlink it, and free the memory for it.**  returns : 0 - OK*           -1 - node not found*/int sfghash_remove( SFGHASH * t, void * key){    SFGHASH_NODE * hnode;    int klen;    unsigned hashkey, index;    if( t->keysize > 0 )    {       klen = t->keysize;    }    else    {       klen = strlen((char*)key) + 1;    }    hashkey = t->sfhashfcn->hash_fcn(  t->sfhashfcn, (unsigned char*) key, klen );        index = hashkey % t->nrows;    for( hnode=t->table[index]; hnode; hnode=hnode->next )    {       if( t->keysize > 0 )       {         if( !t->sfhashfcn->keycmp_fcn(hnode->key,key,klen) )         {             return sfghash_free_node( t, index, hnode );         }       }       else       {         if( !strcmp((const char *)hnode->key,(const char*)key) )         {             return sfghash_free_node( t, index, hnode );         }       }    }   return SFGHASH_ERR;  }/* Internal use only */static void sfghash_next( SFGHASH * t ){    if( !t->cnode )        return ;     /* Next node in current node list */    t->cnode = t->cnode->next;    if( t->cnode )    {        return;    }    /* Next row */     /* Get 1st node in next non-emtoy row/node list */    for( t->crow++; t->crow < t->nrows; t->crow++ )    {           t->cnode = t->table[ t->crow ];       if( t->cnode )        {           return;       }    }}/**   Get First Hash Table Node*/SFGHASH_NODE * sfghash_findfirst( SFGHASH * t ){    SFGHASH_NODE * n;    /* Start with 1st row */    for( t->crow=0; t->crow < t->nrows; t->crow++ )    {           /* Get 1st Non-Null node in row list */       t->cnode = t->table[ t->crow ];       if( t->cnode )       {         n = t->cnode;         sfghash_next( t ); // load t->cnode with the next entry         return n;       }    }  return NULL;}/**   Get Next Hash Table Node*/SFGHASH_NODE * sfghash_findnext( SFGHASH * t ){    SFGHASH_NODE * n;    n = t->cnode;    if( !n ) /* Done, no more entries */    {        return NULL;    }    /*       Preload next node into current node     */    sfghash_next( t );     return  n;}/***   Test Driver for Hashing*  */#ifdef SFGHASH_MAIN void myfree ( void * p ){	printf("freeing '%s'\n",p);	free(p);}/**       Hash test program  */int main ( int argc, char ** argv ){   int         i;   SFGHASH      * t;   SFGHASH_NODE * n, *m;   char str[256],*p;   int  num=100;   if( argc > 1 )       num = atoi(argv[1]);   sfatom_init();   /* Create a Hash Table */   t = sfghash_new( 1000, 0 , GH_COPYKEYS , myfree  );   /* Add Nodes to the Hash Table */   for(i=0;i<num;i++)    {       snprintf(str, sizeof(str), "KeyWord%d",i+1);       str[sizeof(str) - 1] = '\0';       sfghash_add( t, str,  strupr(strdup(str)) );       sfatom_add( str,  strupr(strdup(str)) );   }     /* Find and Display Nodes in the Hash Table */   printf("\n** FIND KEY TEST\n");   for(i=0;i<num;i++)    {      snprintf(str, sizeof(str), "KeyWord%d",i+1);      str[sizeof(str) - 1] = '\0';      p = (char*) sfghash_find( t, str );      printf("Hash-key=%*s, data=%*s\n", strlen(str),str, strlen(str), p );      p = (char*) sfatom_find( str );      printf("Atom-key=%*s, data=%*s\n", strlen(str),str, strlen(str), p );   }     /* Display All Nodes in the Hash Table */   printf("\n** FINDFIRST / FINDNEXT TEST\n");   for( n = sfghash_findfirst(t); n; n = sfghash_findnext(t) )   {      printf("hash-findfirst/next: key=%s, data=%s\n", n->key, n->data );      // hashing code frees user data using 'myfree' above ....      if( sfghash_remove(t,n->key) )             printf("Could not remove the key node\n");      else              printf("key node removed\n");   }   for( n = sfatom_findfirst(); n; n = sfatom_findnext() )   {      printf("atom-findfirst/next: key=%s, data=%s\n", n->key, n->data );      free( n->data );  //since atom data is not freed automatically   }   /* Free the table and it's user data */   printf("****sfghash_delete\n");   sfghash_delete( t );   printf("****sfatom_reset\n");   sfatom_reset();   printf("\nnormal pgm finish\n\n");   return 0;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -