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

host_db.c

/* Network traffic analyzer
 * (c) 2001-2003, Emil Mikulic.
 */

/* Host database */
#include "host_db.h"
#include "acct.h"
#include <string.h>



/* Global database */
db host_db[256];



void host_db_init(void)
{
      int i;
      for (i=0; i<256; i++)
            db_init(&host_db[i]);
}

void host_db_free(void)
{
      int a;

      for (a=0; a<256; a++)
      {
            dword i;
            for (i=0; i<host_db[a].used; i++)
                  free(host_db[a].records[i]);
      }
}



inline dword host_db_used(void)
{
      int a, used = 0;
      for (a=0; a<256; a++) used += host_db[a].used;

      return used;
}



/* host_record needs to be deallocated when it's no longer needed */
inline host_record *host_make(const dword ip_addr)
{
      host_record *h = (host_record*)malloc(sizeof(host_record));

      h->ip_addr = ip_addr;
      h->hostname = NULL;
      SET64(h->data_in, 0, 0);
      SET64(h->data_out, 0, 0);

      return h;
}



/* update transfer amount */
inline void host_update_in(host_record *h, const dword in)
{
      i64add32(h->data_in, in);
}

inline void host_update_out(host_record *h, const dword out)
{
      i64add32(h->data_out, out);
}



/* add or find a host, depending on whether it exists in the db or not */
inline host_record *host_from_ip(const dword ip)
{
      int i, a;
      host_record *h = NULL;

      if (local_host_rec && ip == local_ip) return local_host_rec;

      /* search backwards - more likely to find a more recent host quickly */
      a = CLASSA(ip);
      for (i=host_db[a].used-1; i>=0; i--)
      {
            host_record *tmp = (host_record*)db_get(host_db[a], i);
            if (tmp->ip_addr == ip) h = tmp;
      }

      if (!h)
      {
            h = host_make(ip);
            if (!db_add(&host_db[a], h))
                  freakout("Couldn't add to host_db in host_from_ip()");
      }

      return h;
}



inline void host_transfer_in(const dword ip, const dword in)
{
      host_update_in(host_from_ip(ip), in);
}

inline void host_transfer_out(const dword ip, const dword out)
{
      host_update_out(host_from_ip(ip), out);
}



inline dword ip_from_quad(const int a, const int b, const int c, const int d)
{
      return ( ((a & 255) << 24) |
             ((b & 255) << 16) |
             ((c & 255) <<  8) |
              (d & 255) );
}



void host_db_save(FILE *fp)
{
      dword i, a, used = host_db_used();

      fwrite(&used, sizeof(used), 1, fp);

      for (a=0; a<256; a++)
      for (i=0; i<host_db[a].used; i++)
      {
            host_record *h = (host_record*)db_get(host_db[a], i);
            byte len;
      
            if (!h->hostname)
                  len = 0;
            else
                  len = strlen(h->hostname);

            fwrite(&(h->ip_addr), sizeof(h->ip_addr), 1, fp);
            fwrite(&len, 1, 1, fp);
            if (len) fwrite(h->hostname, len, 1, fp);
            fwrite64(h->data_in, fp);
            fwrite64(h->data_out, fp);
      }
}



int host_db_load(FILE *fp)
{
      int read;
      dword used, i;

      read = fread(&used, sizeof(used), 1, fp);
      if (!read) return 0;

      for (i = 0; i<used; i++)
      {
            dword ip;
            byte len;
            host_record *h;

            /* load IP */
            read = fread(&ip, sizeof(ip), 1, fp);
            if (!read) return 0;

            h = host_make(ip);

            /* load hostname string */
            read = fread(&len, sizeof(len), 1, fp);
            if (!read) return 0;

            if (len)
            {
                  h->hostname = (char*)malloc(len + 1);
                  read = fread(h->hostname, len, 1, fp);
                  if (!read) return 0;

                  h->hostname[len] = 0;
            }

            /* load in/out amounts */
            fread64(h->data_in, fp, read);
            if (!read) return 0;

            fread64(h->data_out, fp, read);
            if (!read) return 0;

            /* add to db */
            if (!db_add(&(host_db[CLASSA(ip)]), h)) return 0;
      }

      return 1;
}



void host_qs_swap(host_record **list, int64 *amount, int a, int b)
{
      int64 t64;
      host_record *thr;

      t64 = amount[a];
      amount[a] = amount[b];
      amount[b] = t64;

      thr = list[a];
      list[a] = list[b];
      list[b] = thr;
}



void host_quicksort(host_record **list, int64 *amount, int left, int right)
{
      int i, j;
      int64 v;

      if(right > left) {
            v = amount[right];
            i = left - 1;
            j = right;
            for(;;) {
                  do {
                        i++;
                        if (i >= j) break;
                  } while (i64smaller(amount[i], v));

                  do {
                        j--;
                        if (i >= j) break;
                  } while (i64bigger(amount[j], v));

                  if (i >= j) break;
                  host_qs_swap(list, amount, i, j);
            }
            host_qs_swap(list, amount, i, right);
            host_quicksort(list, amount, left, i - 1);
            host_quicksort(list, amount, i + 1, right);
      }
}



/* note: it'd be a good idea to lock the host_db mutex before doing this */
inline host_record **host_db_sort(sort_type st)
{
      host_record **list;
      int64 *amount;
      int num, used = host_db_used();
      dword a, i;

      list = (host_record**) malloc(used * sizeof(host_record*));
      amount = (int64*) malloc(used * sizeof(int64));

      if (!list || !amount)
            freakout("Out of memory in host_db_sort()!");

      for (num=0, a=0; a<256; a++)
      for (i=0; i<host_db[a].used; i++,num++)
      {
            /* initialize host record */
            list[num] = (host_record*)db_get(host_db[a], i);

            /* initialize amount */
            switch(st)
            {
            case MAIN:
                  SET64(amount[num], 0, -(list[num]->ip_addr));
                  break;
            case TOTAL:
                  amount[num] = list[num]->data_in;
                  i64add64(amount[num], list[num]->data_out);
                  break;
            case IN:
                  amount[num] = list[num]->data_in;
                  break;
            case OUT:
                  amount[num] = list[num]->data_out;
                  break;
            default:
                  freakout("invalid sort_type passed to host_db_sort()");
            }
      }

      host_quicksort(list, amount, 0, used-1);

      free(amount);
      return list;
}


Generated by  Doxygen 1.6.0   Back to index