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

📄 snort_stream5_session.c

📁 Snort为国际上著名的轻量型入侵防御系统,为国内多家著名“自主知识产权”网络安全公司所使用。
💻 C
字号:
/* $Id$ *//*** Copyright (C) 2005 Sourcefire, Inc.** AUTHOR: Steven Sturges <ssturges@sourcefire.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** 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.*//* snort_stream5_session.c *  * Purpose: Hash Table implementation of session management functions for *          Stream5 preprocessor. * * Arguments: *    * Effect: * * Comments: * * Any comments? * */#include "decode.h"#include "debug.h"#include "log.h"#include "util.h"#include "snort_stream5_session.h"#ifndef WIN32#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#endif#include "bitop_funcs.h"extern unsigned int giFlowbitSize;void PrintSessionKey(SessionKey *skey){    LogMessage("SessionKey:\n");    LogMessage("    ip_l     = 0x%08X\n", skey->ip_l);    LogMessage("    ip_h     = 0x%08X\n", skey->ip_h);    LogMessage("    prt_l    = %d\n", skey->port_l);    LogMessage("    prt_h    = %d\n", skey->port_h);    LogMessage("    vlan_tag = %d\n", skey->vlan_tag); }int GetLWSessionCount(Stream5SessionCache *sessionCache){    if (sessionCache && sessionCache->hashTable)        return sessionCache->hashTable->count;    else        return 0;}int GetLWSessionKey(Packet *p, SessionKey *key){    u_int16_t sport;    u_int16_t dport;    if (!key)        return 0;    switch (p->iph->ip_proto)    {        case IPPROTO_TCP:        case IPPROTO_UDP:            sport = p->sp;            dport = p->dp;            break;        case IPPROTO_ICMP:        default:            sport = dport = 0;            break;    }        if (p->iph->ip_src.s_addr < p->iph->ip_dst.s_addr)    {        key->ip_l = p->iph->ip_src.s_addr;        key->port_l = sport;        key->ip_h = p->iph->ip_dst.s_addr;        key->port_h = dport;    }    else if (p->iph->ip_src.s_addr == p->iph->ip_dst.s_addr)    {        key->ip_l = p->iph->ip_src.s_addr;        key->ip_h = p->iph->ip_dst.s_addr;        if (sport < dport)        {            key->port_l = sport;            key->port_h = dport;        }        else        {            key->port_l = dport;            key->port_h = sport;        }    }    else    {        key->ip_l = p->iph->ip_dst.s_addr;        key->port_l = dport;        key->ip_h = p->iph->ip_src.s_addr;        key->port_h = sport;    }    key->protocol = p->iph->ip_proto;    if (p->vh)        key->vlan_tag = VTH_VLAN(p->vh);    else        key->vlan_tag = 0;    key->pad = 0;    return 1;}void GetPacketDirection(Packet *p, Stream5LWSession *ssn){    if (p->iph->ip_src.s_addr == ssn->client_ip)    {        if ((p->iph->ip_proto == IPPROTO_TCP) &&            (p->tcph->th_sport == ssn->client_port))        {            p->packet_flags |= PKT_FROM_CLIENT;        }        else if ((p->iph->ip_proto == IPPROTO_UDP) &&                 (p->udph->uh_sport == ssn->client_port))        {            p->packet_flags |= PKT_FROM_CLIENT;        }        else if (p->iph->ip_proto == IPPROTO_ICMP)        {            p->packet_flags |= PKT_FROM_CLIENT;        }    }    else if (p->iph->ip_dst.s_addr == ssn->client_ip)    {        if ((p->iph->ip_proto == IPPROTO_TCP) &&            (p->tcph->th_dport == ssn->client_port))        {            p->packet_flags |= PKT_FROM_SERVER;        }        else if ((p->iph->ip_proto == IPPROTO_UDP) &&                 (p->udph->uh_dport == ssn->client_port))        {            p->packet_flags |= PKT_FROM_SERVER;        }        else if (p->iph->ip_proto == IPPROTO_ICMP)        {            p->packet_flags |= PKT_FROM_CLIENT;        }    }    else    {        /* Uh, no match of the packet to the session. */        /* Probably should log an error */    }}Stream5LWSession *GetLWSession(Stream5SessionCache *sessionCache, Packet *p, SessionKey *key){    Stream5LWSession *returned = NULL;    SFXHASH_NODE *hnode;    if (!GetLWSessionKey(p, key))        return NULL;    hnode = sfxhash_find_node(sessionCache->hashTable, key);    if (hnode && hnode->data)    {        /* This is a unique hnode, since the sfxhash finds the         * same key before returning this node.         */        returned = (Stream5LWSession *)hnode->data;    }    return returned;}Stream5LWSession *GetLWSessionFromKey(Stream5SessionCache *sessionCache, SessionKey *key){    Stream5LWSession *returned = NULL;    SFXHASH_NODE *hnode;    hnode = sfxhash_find_node(sessionCache->hashTable, key);    if (hnode && hnode->data)    {        /* This is a unique hnode, since the sfxhash finds the         * same key before returning this node.         */        returned = (Stream5LWSession *)hnode->data;    }    return returned;}/* For internal use only */void FreeLWApplicationData(Stream5LWSession *ssn){    Stream5AppData *tmpData, *appData = ssn->appDataList;    while (appData)    {        if (appData->freeFunc)        {            appData->freeFunc(appData->dataPointer);        }        tmpData = appData->next;        free(appData);        appData = tmpData;    }    ssn->appDataList = NULL;}/* For internal use only */int RemoveLWSession(Stream5SessionCache *sessionCache, Stream5LWSession *ssn){    mempool_free(&s5FlowMempool, ssn->flowdata);    return sfxhash_remove(sessionCache->hashTable, &(ssn->key));}int DeleteLWSession(Stream5SessionCache *sessionCache,                   Stream5LWSession *ssn){    /*      * Call callback to cleanup the protocol (TCP/UDP/ICMP)     * specific session details     */    if (sessionCache->cleanup_fcn)        sessionCache->cleanup_fcn(ssn);    FreeLWApplicationData(ssn);    return RemoveLWSession(sessionCache, ssn);}int PurgeLWSessionCache(Stream5SessionCache *sessionCache){    int retCount = 0;    Stream5LWSession *idx;    SFXHASH_NODE *hnode;    if (!sessionCache)        return 0;    hnode = sfxhash_mru_node(sessionCache->hashTable);    while (hnode)    {        idx = (Stream5LWSession *)hnode->data;        DeleteLWSession(sessionCache, idx);        hnode = sfxhash_mru_node(sessionCache->hashTable);        retCount++;    }    return retCount;}int PruneLWSessionCache(Stream5SessionCache *sessionCache,                   u_int32_t thetime,                   Stream5LWSession *save_me,                   int memCheck){    Stream5LWSession *idx;    u_int32_t pruned = 0;    if (thetime != 0)    {        char got_one;        idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable);        if(idx == NULL)        {            return 0;        }        do        {            got_one = 0;                        if(idx == save_me)            {                SFXHASH_NODE *lastNode = sfxhash_lru_node(sessionCache->hashTable);                sfxhash_gmovetofront(sessionCache->hashTable, lastNode);                lastNode = sfxhash_lru_node(sessionCache->hashTable);                if ((lastNode) && (lastNode->data != idx))                {                    idx = (Stream5LWSession *)lastNode->data;                    continue;                }                else                {                    return pruned;                }            }            if((idx->last_data_seen+sessionCache->timeout) < thetime)            {                Stream5LWSession *savidx = idx;                if(sfxhash_count(sessionCache->hashTable) > 1)                {                    DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning stale session\n"););                    DeleteLWSession(sessionCache, savidx);                    idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable);                    pruned++;                    got_one = 1;                }                else                {                    DeleteLWSession(sessionCache, savidx);                    pruned++;                    return pruned;                }            }            else            {                return pruned;            }            if (pruned > sessionCache->cleanup_sessions)            {                /* Don't bother cleaning more than XXX at a time */                break;            }        } while ((idx != NULL) && (got_one == 1));        return pruned;    }    else    {        /* Free up xxx sessions at a time until we get under the         * memcap or free enough sessions to be able to create         * new ones.         */        while ( sfxhash_count(sessionCache->hashTable) > sessionCache->max_sessions - sessionCache->cleanup_sessions)        {            unsigned int i;            idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable);            for (i=0;i<sessionCache->cleanup_sessions &&                      (sfxhash_count(sessionCache->hashTable) > 1); i++)            {                if(idx != save_me)                {                    DeleteLWSession(sessionCache, idx);                    pruned++;                    idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable);                }                else                {                    SFXHASH_NODE *lastNode = sfxhash_lru_node(sessionCache->hashTable);                    sfxhash_gmovetofront(sessionCache->hashTable, lastNode);                    lastNode = sfxhash_lru_node(sessionCache->hashTable);                    if ((lastNode) && (lastNode->data == idx))                    {                        /* Okay, this session is the only one left */                        break;                    }                    idx = (Stream5LWSession *) sfxhash_lru(sessionCache->hashTable);                    i--; /* Didn't clean this one */                }            }        }    }    return pruned;}Stream5LWSession *NewLWSession(Stream5SessionCache *sessionCache, Packet *p, SessionKey *key){    Stream5LWSession *retSsn = NULL;    SFXHASH_NODE *hnode;    StreamFlowData *flowdata;    hnode = sfxhash_get_node(sessionCache->hashTable, key);    if (!hnode)    {        DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, clean it\n"););        if (!PruneLWSessionCache(sessionCache, p->pkth->ts.tv_sec, NULL, 0))        {            DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, no timeouts, clean it\n"););            PruneLWSessionCache(sessionCache, 0, NULL, 0);        }        /* Should have some freed nodes now */        hnode = sfxhash_get_node(sessionCache->hashTable, key);#ifdef DEBUG        if (!hnode)        {            DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Problem, no freed nodes\n"););        }#endif    }    if (hnode && hnode->data)    {        retSsn = hnode->data;        /* Zero everything out */        memset(retSsn, 0, sizeof(Stream5LWSession));        /* Save the session key for future use */        memcpy(&(retSsn->key), key, sizeof(SessionKey));        retSsn->protocol = key->protocol;        retSsn->last_data_seen = p->pkth->ts.tv_sec;        retSsn->flowdata = mempool_alloc(&s5FlowMempool);        flowdata = retSsn->flowdata->data;        boInitStaticBITOP(&(flowdata->boFlowbits), giFlowbitSize,                flowdata->flowb);    }    return retSsn;}Stream5SessionCache *InitLWSessionCache(int max_sessions,                                        u_int32_t session_timeout,                                        u_int32_t cleanup_sessions,                                        u_int32_t cleanup_percent,                                        Stream5SessionCleanup cleanup_fcn){    Stream5SessionCache *sessionCache = NULL;    /* Rule of thumb, size should be 1.4 times max to avoid     * collisions.     */    int hashTableSize = sfxhash_calcrows((int) (max_sessions * 1.4));    /* Memory required for 1 node: LW Session + Session Key +     * Node + NodePtr.     */    int maxSessionMem = max_sessions * (                            sizeof(Stream5LWSession) +                            sizeof(SFXHASH_NODE) +                            sizeof(SessionKey) +                            sizeof(SFXHASH_NODE *));     /* Memory required for table entries */     int tableMem = (hashTableSize +1) * sizeof(SFXHASH_NODE*);     sessionCache = malloc(sizeof(Stream5SessionCache));     if (sessionCache)     {        sessionCache->timeout = session_timeout;        sessionCache->max_sessions = max_sessions;        if (cleanup_percent)        {            sessionCache->cleanup_sessions = max_sessions * cleanup_percent/100;            if (sessionCache->cleanup_sessions == 0)            {                sessionCache->cleanup_sessions = 1;            }        }        else        {            sessionCache->cleanup_sessions = cleanup_sessions;        }        sessionCache->cleanup_fcn = cleanup_fcn;        /* Okay, now create the table */        sessionCache->hashTable = sfxhash_new(            hashTableSize,            sizeof(SessionKey),            sizeof(Stream5LWSession),            maxSessionMem + tableMem, 0, NULL, NULL, 1);     }         return sessionCache;}void PrintLWSessionCache(Stream5SessionCache *sessionCache){    DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "%lu sessions active\n",                             sfxhash_count(sessionCache->hashTable)););}

⌨️ 快捷键说明

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