/* 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; }