Logo Search packages:      
Sourcecode: pktstat version File versions  Download package

flow.c

/* David Leonard, 2002. Public domain. */
/* $Id: flow.c 978 2006-01-27 15:01:08Z d $ */

/*
 * A flow is a grouped history of packets with some similarity.
 * Each flow is uniquely identified by a 'tag', which is
 * descriptive string. Some flows have extra descriptive
 * information, like FTP transferred file names. Flow data
 * structures are supposed to hang around for a while, even
 * if no packet activity in that flow has been seen.
 */

#if HAVE_CONFIG_H
# include "config.h"
#endif

#if STDC_HEADERS
# include  <string.h>
# include  <stdlib.h>
#endif
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif

#include "compat.h"
#include "flow.h"

int nflows = 0;
struct flow *flows;
static int maxflows = 0;

/* Generate a hash value for a tag */
static unsigned int
hash(tag)
      const char *tag;
{
      unsigned int result;

      for (result = 0; *tag; tag++) 
            result = (result << 1) ^ *tag;
      return result;
}

/* Find a flow by its tag */
struct flow *
findflow(tag)
      const char *tag;
{
      int i;
      unsigned int taghash = hash(tag);

      for (i = 0; i < nflows; i++)
            if (flows[i].taghash == taghash
                && strcmp(flows[i].tag, tag) == 0)
                  return &flows[i];
      if (nflows >= maxflows) {
            if (maxflows == 0) {
                  maxflows = 128;
                  flows = (struct flow *)malloc(maxflows * sizeof *flows);
            } else {
                  maxflows *= 2;
                  flows = (struct flow *)realloc(flows,
                      maxflows * sizeof *flows);
            }
            if (flows == NULL)
                  errx(1, "malloc/realloc");    
      }
      flows[nflows].taghash = taghash;
      strlcpy(flows[nflows].tag, tag, sizeof flows[nflows].tag);
      flows[nflows].desc[0] = '\0';
      flows[nflows].octets = 0;
      flows[nflows].total_octets = 0;
      flows[nflows].packets = 0;
      flows[nflows].total_packets = 0;
      flows[nflows].keepalive = -1;
      flows[nflows].dontdel = 0;
      flows[nflows].udata = NULL;
      flows[nflows].freeudata = NULL;
      return &flows[nflows++];
}

/* Compare flows by the number of octets they have carried (reverse order) */
int
octetcmp(a, b)
      const void *a;
      const void *b;
{
      const struct flow *fa = (const struct flow *)a;
      const struct flow *fb = (const struct flow *)b;
      return -(fa->octets - fb->octets);
}

/* Compare flows by their tag */
int
tagcmp(a, b)
      const void *a;
      const void *b;
{
      const struct flow *fa = (const struct flow *)a;
      const struct flow *fb = (const struct flow *)b;
      return strcmp(fa->tag, fb->tag);
}

/* Compare flows by the time they were last seen (reverse order) */
int
lastcmp(a, b)
      const void *a;
      const void *b;
{
      const struct flow *fa = (const struct flow *)a;
      const struct flow *fb = (const struct flow *)b;
      if (fb->lastseen.tv_sec - fa->lastseen.tv_sec == 0)
            if (fb->lastseen.tv_usec - fa->lastseen.tv_usec == 0)
                  return tagcmp(a, b);
            else
                  return fb->lastseen.tv_usec - fa->lastseen.tv_usec;
      else
            return fb->lastseen.tv_sec - fa->lastseen.tv_sec;
}

/* Compare flows by their packet count (reverse order) */
int
packetcmp(a, b)
      const void *a;
      const void *b;
{
      const struct flow *fa = (const struct flow *)a;
      const struct flow *fb = (const struct flow *)b;
      return fa->packets - fb->packets;
}

/* Zero the octet count on all flows */
void
flow_zero()
{
      int i;

      for (i = 0; i < nflows; i++) {
            flows[i].octets = 0;
            flows[i].packets = 0;
      }
}

/* Remove a flow */
void
flow_del(f)
      struct flow *f;
{
      int i = f - flows;

      if (f->freeudata)
            (*f->freeudata)(f->udata);
      if (nflows > 1 && i != nflows -1) {
            memcpy(f, &flows[nflows-1], sizeof (struct flow));
      }
      nflows--;
}

Generated by  Doxygen 1.6.0   Back to index