flow_cache.c

来自「snort-2.1.0入侵检测」· C语言 代码 · 共 568 行 · 第 1/2 页

C
568
字号
/** * @file   flow_cache.c * @author Chris Green <cmg@sourcefire.com> * @date   Fri Jun 20 09:04:51 2003 *  * @brief  where flows are stored *  * The FlowCache is a memory-capped storage area for the FLOW * datatype.  It is inspired by spp_conversation, ipaudit, stream4 and * frag2.  * * * Each FLOW is uniquely identified by the 5-tuple (ipproto,sip,dip,sport,dport) * * Currently we only support IPV4 but new protocols will only require * the addition of additional protocol specific hash tables.  Ideally, * the API will stay the same and just do a switch on the key type to * support the various address families. * * This is meant to centralize the state management routines so that * it's easy to just worry about higher level protocols in other * modules. * * This is built on top of sfxhash currently and relies on it for * memory management. flow_hash.c contains the hashing keys  *  */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <stdio.h>#include "flow_cache.h"#include "flow_callback.h"#include "flow_hash.h"/* helper functions */static int flowcache_anrfree( void *key, void *data);static int flowcache_usrfree( void *key, void *data);/* minor optimization functions */static INLINE int flowcache_mru(FLOWCACHE *flowcachep, FLOW **flowpp);static INLINE int flowcache_lru(FLOWCACHE *flowcachep, FLOW **flowpp);/* statistics functions */static INLINE int FCS_find(FLOWCACHE *flowcachecp, FLOWKEY *keyp);static INLINE int FCS_revfind(FLOWCACHE *flowcachecp, FLOWKEY *keyp);static INLINE int FCS_new(FLOWCACHE *flowcachecp, FLOWKEY *keyp);static INLINE int FCS_find_success(FLOWCACHE *flowcachecp, FLOWKEY *keyp);static INLINE int FCS_find_fail(FLOWCACHE *flowcachecp, FLOWKEY *keyp);int flowcache_init(FLOWCACHE *flowcachep, unsigned int rows,                   int memcap, FLOWHASHID hashid){    int ret;        if(!flowcachep)    {        return FLOW_ENULL;    }    if(memcap <= (sizeof(FLOW) + sizeof(SFXHASH_NODE)))    {        /* come on man, you gotta give me enough memory to store 1. */        return FLOW_EINVALID;    }    if(rows < 1)        return FLOW_EINVALID;    /* zero out the struct for all the additional data strctures */    memset(flowcachep, 0, sizeof(FLOWCACHE));    /* what size should we do? */    flowcachep->ipv4_table =        sfxhash_new(rows,             /* # of nodes in HT*/                    sizeof(FLOWKEY),   /* size of the key  */                    sizeof(FLOW),      /* data size */                    memcap,            /* how much memory is alloted */                    1,                 /* auto recover nodes */                    flowcache_anrfree, /* autorecovery function */                    flowcache_usrfree, /* free function for the data */                    1);                /* recycle old nodes */    if(flowcachep->ipv4_table == NULL)    {        return FLOW_ENOMEM;    }    /* set our hash function to something that understands ipv4 flowkeys */    switch(hashid)    {    case HASH1:        ret = sfxhash_set_keyops(flowcachep->ipv4_table,                                 flowkey_hashfcn1,                                 flowkeycmp_fcn);        break;    case HASH2:        ret = sfxhash_set_keyops(flowcachep->ipv4_table,                                 flowkey_hashfcn2,                                 flowkeycmp_fcn);        break;    default:        ret = FLOW_EINVALID;    }    /* if setting the hash function or setting the comparison function fails,       abort */    if(ret != 0)    {        sfxhash_delete(flowcachep->ipv4_table);        return FLOW_BADJUJU;    }        return FLOW_SUCCESS;}int flowcache_destroy(FLOWCACHE *flowcachep){    if(!flowcachep)    {        return FLOW_ENULL;    }    sfxhash_delete(flowcachep->ipv4_table);    flowcachep->ipv4_table = NULL;        return FLOW_SUCCESS;}unsigned flowcache_overhead_blocks(FLOWCACHE *fcp){    return sfxhash_overhead_blocks(fcp->ipv4_table);}int flowcache_releaseflow(FLOWCACHE *flowcachep, FLOW **flowpp){    FLOWKEY *key;    FLOWKEY search_key;        if(!flowcachep || !flowpp || !(*flowpp))    {        return FLOW_ENULL;    }    /** @todo remove any associated data with the flow */    key = &(*flowpp)->key;        flowkey_normalize(&search_key, key);    if(sfxhash_remove(flowcachep->ipv4_table, &search_key) != 0)    {        return FLOW_NOTFOUND;    }    /* we've successfully removed the node from the table */        *flowpp = NULL;    return FLOW_SUCCESS;}int flowcache_newflow(FLOWCACHE *flowcachep, FLOWKEY *keyp, FLOW **flowpp){    static int run_once = 1;    static FLOW zeroflow;    static FLOWKEY searchkey;    int ret;        if(!flowcachep || !keyp || !flowpp)    {        return FLOW_ENULL;    }    FCS_new(flowcachep, keyp);        if(run_once)    {        /* all the time that we're running this, we're actually going           to be filling in the key, and having zero'd out counters */         memset(&zeroflow, 0, sizeof(FLOW));        memset(&searchkey, 0, sizeof(FLOWKEY));                run_once = 0;    }    flowkey_normalize(&searchkey, keyp);        if(flow_init(&zeroflow, keyp->protocol,                 keyp->init_address, keyp->init_port,                 keyp->resp_address, keyp->resp_port))    {        return FLOW_ENULL;    }    ret = sfxhash_add(flowcachep->ipv4_table, &searchkey, &zeroflow);    switch(ret)    {    case SFXHASH_OK:        if(flowcache_mru(flowcachep,flowpp) != FLOW_SUCCESS)        {            /* something's wrong because we just added this thing!\n */            flow_printf("Unable to find a key I just added!\n");            return FLOW_BADJUJU;        }        return FLOW_SUCCESS;            case SFXHASH_NOMEM:        return FLOW_ENOMEM;    case SFXHASH_INTABLE:    default:        return FLOW_EINVALID;    }}/**  * Get the most recently used flow from the cache *  * @param flowcachep flow cache to operate on * @param flowp where to put the flow *  * @return FLOW_SUCCESS on sucess */static INLINE int flowcache_mru(FLOWCACHE *flowcachep, FLOW **flowpp){    if(!flowcachep  || !flowpp)        return FLOW_EINVALID;    *flowpp = sfxhash_mru(flowcachep->ipv4_table);    if(*flowpp == NULL)        return FLOW_NOTFOUND;        return FLOW_SUCCESS;}/**  * Get the least recently used flow from the cache *  * @param flowcachep flow cache to operate on * @param flowp where to put the flow *  * @return FLOW_SUCCESS on sucess */static INLINE int flowcache_lru(FLOWCACHE *flowcachep, FLOW **flowpp){    if(!flowcachep  || !flowpp)        return FLOW_EINVALID;    *flowpp = sfxhash_lru(flowcachep->ipv4_table);    if(*flowpp == NULL)        return FLOW_NOTFOUND;        return FLOW_SUCCESS;}/**  * Look for the data in the flow tables. *  * @param flowcachep cache to look in * @param keyp pointer to searching key data * @param flowpp pointer to set with this module * @param direction pass back argument (FROM_INITIATOR or FROM_RESPONDER) *  * @return FLOW_SUCCESS on success, FLOW_NOTFOUND when not found, else usage error */int flowcache_find(FLOWCACHE *flowcachep, FLOWKEY *keyp, FLOW **flowpp, int *direction){    FLOWKEY search_key;    FLOW *fp;    int way;        if(!flowcachep || !keyp || !flowpp || !direction)    {

⌨️ 快捷键说明

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