/** 
 * See if the flow needs to be shutdown and remove it from the
 * cache. This function should be placed AFTER all detection type
 * components.
 * 
 * @param p packet
 * 
 * @return 0 on success
 */
int CheckFlowShutdown(Packet *p)
{
    FLOWCACHE *fcache = &s_fcache;
    FLOW *flowp = (FLOW *) p->flow;
    PROFILE_VARS;
   
    /* Use TMPSTART to not add to 'checks' */
    PREPROC_PROFILE_TMPSTART(flowPerfStats);
    if(flowp != NULL)
    {
        if(flow_checkflag(flowp, FLOW_CLOSEME))
        {
            /* allow all the submodules to trigger their final stand */            
            flow_callbacks(FLOW_SHUTDOWN, flowp, FROM_INITIATOR, p);
            
            if(flowcache_releaseflow(fcache, &flowp) != FLOW_SUCCESS)
            {
                flow_printf("Can't release flow %p\n", p->flow);
                PREPROC_PROFILE_TMPEND(flowPerfStats);
                return FLOW_BADJUJU;
            }
        }
    }

    p->flow = NULL;

    PREPROC_PROFILE_TMPEND(flowPerfStats);
    return FLOW_SUCCESS;
}
Ejemplo n.º 2
0
/** 
 * Automatically recover nodes and make sure that all the other
 * references are taken care of.
 * 
 * @param key hash key
 * @param data ptr to FLOW data
 * 
 * @return 0 if this node can be removed
 */
static int flowcache_anrfree(void *key, void *data)
{
    FLOW *fp;

    if(data)
    {
        fp = (FLOW *) data;
        flow_callbacks(FLOW_SHUTDOWN, fp, 0, NULL);
    }
    
    return 0;
}
/** 
 * The runtime entry point for the flow module from snort
 *
 * 1) Assign each packet a flow
 * 2) Perform various callbacks based on the parameters for the flow
 * 
 * @param p packet to process
 */
static void FlowPreprocessor(Packet *p, void *context)
{
    int flow_class; /**< addressing scheme to use */
    int direction; /**< which way does the flow go */
    static time_t last_output = 0;
    FLOWKEY search_key;
    FLOW *fp;
    FLOWCACHE *fcache = &s_fcache;
    FLOWPACKET *pkt = (FLOWPACKET *) p;
    PROFILE_VARS;
        
    if(!FlowPacket(p))
    {
        return;
    }

    PREPROC_PROFILE_START(flowPerfStats);
    
    /* first find the addressing schema */
    if(flow_classifier(pkt, &flow_class) != FLOW_SUCCESS)
    {
        //LogMessage("Error classifying packet\n");
        return;
    }

    switch(flow_class)
    {
    case FLOW_IPV4:
        if(flowkey_make(&search_key, pkt) != FLOW_SUCCESS)
        {
            ErrorMessage("Unable to make a search key\n");
            PREPROC_PROFILE_END(flowPerfStats);
            return;
        }
        break;
    default:
        ErrorMessage("Unknown Flow Type: %d\n", flow_class);
        PREPROC_PROFILE_END(flowPerfStats);
        return;
    }

    /** this should return a direction too for the key */
    //printf("flowkey: "); flowkey_fprint(stdout, &search_key); printf("\n");
    
    if(flowcache_find(fcache, &search_key, &fp, &direction) == FLOW_SUCCESS)
    {
        /*
        **  We set flows for rebuilt pkts if there is one, otherwise
        **  we just bail.
        */
        if(p->packet_flags & PKT_REBUILT_STREAM)
        {
            p->flow = fp;
            PREPROC_PROFILE_END(flowPerfStats);
            return;
        }

        if(direction == FROM_RESPONDER && fp->stats.packets_recv == 0)
        {
            /* this is the first packet back from the guy */           
            flow_callbacks(FLOW_FIRST_BIDIRECTIONAL, fp, direction, p);
        }

        flow_callbacks(FLOW_ADDITIONAL, fp, direction, pkt);
    }
    else
    {
        /*
        **  If there's no flow for a rebuilt stream, then we don't
        **  care because something is screwed up.
        */
        if(p->packet_flags & PKT_REBUILT_STREAM)
        {
            PREPROC_PROFILE_END(flowPerfStats);
            return;
        }

        if(flowcache_newflow(fcache, &search_key, &fp) != FLOW_SUCCESS)
        {
            flow_printf("***ERROR: "); flowkey_print(&search_key); flow_printf("\n");
        }

        direction = FROM_INITIATOR;

        flow_callbacks(FLOW_NEW, fp, FROM_INITIATOR, pkt);
    }

    fp->stats.direction = direction;

    /* printout some verbose statistics */
    if(s_config.stats_interval  &&
       ((last_output + s_config.stats_interval) <= p->pkth->ts.tv_sec))
    {
        last_output =  p->pkth->ts.tv_sec;

        if(!pv.quiet_flag)
            flowcache_stats(stdout, fcache);
    }

    p->flow = fp;

    PREPROC_PROFILE_END(flowPerfStats);
}