Example #1
0
/* name       : export_ipflows
 * remarks    : 
 */
static int export_ipflows( probe_t *probe, time_t now, int flag )
{
    ipflow_t     *flows = probe->ipflows;
    ipflowinfo_t *n, *node;
    int          a=0, d=0, e=0;
    uint64_t     msec_start;
    uint64_t     msec_end;

    if ( flows->biflows )
        return export_biflows( probe, now, flag );

    node = flows?flows->flows:NULL;
    while( node ) {
        msec_start = ((uint64_t)node->tstart.tv_sec*1000)
            +((uint64_t)node->tstart.tv_usec/1000);
        msec_end   = ((uint64_t)node->tlast.tv_sec*1000)
            +((uint64_t)node->tlast.tv_usec/1000);
        a++;

        /* check if the flow is idle
         */
        if ( flag
             || (g_par.ipflow_timeout 
                 && ((now - node->tlast.tv_sec) > g_par.ipflow_timeout))
             || (g_par.ipflow_lifetime
                 && ((node->tlast.tv_sec-node->tstart.tv_sec)
                     > g_par.ipflow_lifetime)) ) {
            if ( mlog_get_vlevel() > 2 ) {
                if ( g_par.ipflow_timeout 
                     && ((now - node->tlast.tv_sec) > g_par.ipflow_timeout) ) {
                    mlogf( 3, "[%s] %ds idle timeout expired! "
                           "id=%d, start=%ld, duration=%ld, idle=%ld\n",
                           g_par.progname, g_par.ipflow_timeout,
                           node->flowid, node->tstart.tv_sec,
                           node->tlast.tv_sec-node->tstart.tv_sec,
                           now - node->tlast.tv_sec );
                }
                else if ( g_par.ipflow_lifetime
                          && ((node->tlast.tv_sec-node->tstart.tv_sec)
                              > g_par.ipflow_lifetime) ) {
                    mlogf( 3, "[%s] %ds flow lifetime expired! "
                           "id=%d, start=%ld, duration=%ld, idle=%ld\n",
                           g_par.progname, g_par.ipflow_lifetime,
                           node->flowid, node->tstart.tv_sec,
                           node->tlast.tv_sec-node->tstart.tv_sec,
                           now - node->tlast.tv_sec );
                }
            }
            /* flow has expired
             * -> export flow end
             * -> delete node
             */
            (void) ipfix_export( probe->ipfix, 
                                 (node->elems.version==6)?
                                 probe->templ6:probe->templ,
                                 &msec_start, &msec_end,
                                 node->saddr, node->daddr, 
                                 &node->elems.sport, 
                                 &node->elems.dport,
                                 &node->elems.protocol,
                                 &node->elems.tos,
                                 &node->packets, &node->bytes );

            n = node->next;
            (void) flow_drop( flows, node );
            node = n;
            e++;
            d++;
            continue;
        }

        if ( (g_par.ipflow_timeout<1) && (node->packets) ) {
            /* flow is still active
             * -> export counters
             */
            msec_end = 0;
            (void) ipfix_export( probe->ipfix, 
                                 (node->elems.version==6)?
                                 probe->templ6:probe->templ,
                                 &msec_start, &msec_end,
                                 node->saddr, node->daddr, 
                                 &node->elems.sport, 
                                 &node->elems.dport,
                                 &node->elems.protocol,
                                 &node->elems.tos,
                                 &node->packets, &node->bytes );

            node->packets =0;
            node->bytes   =0;
            e++;
        }
        
        node = node->next;
    }

    if ( ipfix_export_flush( probe->ipfix ) <0 ) {
        mlogf( 3, "[%s] ipfix_export() failed: %s\n", 
               __func__, strerror(errno) );
    } else {
        mlogf( 2, "[%s] %d active flows, %d exported, %d dropped.\n",
               g_par.progname, a, e, d );
    }

    probe->npkts  = 0;
    probe->nbytes = 0;
    return 0;
}
void flow_drop( ipflow_t *flows, ipflowinfo_t *flownode )
{
    ipflowinfo_t *r = NULL;
    ipflowinfo_t *last, *node;  /* look in hashtab */

#ifdef DEBUG
    if ( mlog_vlevel>3 ) {
        mlogf( 4, "[ipflow] FLOW_DROP START: %p\n", flownode );
        ipflow_listflows( stderr, flows );
    }
#endif

    /* remove flownode from list */
    if ( flows->flows == flownode ) {
        flows->flows = flownode->next;
        if ( flows->flows )
            flows->flows->prev = NULL;
    }
    else {
        if ( flownode->prev )
            flownode->prev->next = flownode->next;
        if ( flownode->next )
            flownode->next->prev = flownode->prev;
    }

    /* remove flownode from hashtab */
    node = flows->hashtab[flownode->hash];
    if ( node == flownode ) {
        flows->hashtab[flownode->hash] = flownode->nexthash;
        flows->nhashes --;
    }
    else {
        for ( last=node; node!=NULL; node=node->nexthash ) {
            if ( node == flownode )
                break;
            last = node;
        }

        if ( node ) {
            last->nexthash = node->nexthash;
            flows->nhashes --;
        }
        else {
            mlogf( 0, "[ipflow] INTERNAL ERROR: "
                   "INVALID FLOW NODE, hash=%d\n",
                   flownode->hash );
            exit(1);
        }
    }
    
    if ( flows->biflows && flownode->rflow ) {
        r = flownode->rflow;
        r->rflow = NULL;
    }

    _free_flownode( flownode );
    flows->nflows--;
        
    if ( flows->biflows && r ) {
        /* drop reverse flow */
        flow_drop( flows, r );
    }

#ifdef DEBUG
    if ( mlog_vlevel>3 ) {
        mlogf( 4, "[ipflow] FLOW_DROP END: %p\n", flownode );
        ipflow_listflows( stderr, flows );
    }
#endif
    return;
}