Logo Search packages:      
Sourcecode: netdiag version File versions

frag.c

/*
 * $Id: frag.c,v 1.1 1997/08/12 16:37:50 begemot Exp begemot $
 * $Log: frag.c,v $
 * Revision 1.1  1997/08/12 16:37:50  begemot
 * Initial revision
 *
 */

/*
 * Copyright (C) 1994-1996 D.Gorodchanin. See COPYING for more info.
 */

#include "trafshow.h"

#define HASH_BITS 8
#define HASH_SIZE (1 << HASH_BITS)
#define HASH(x) ((x ^ (x >> 8)) & (HASH_SIZE - 1))

#define TABLE_SIZE (FRAGS_COUNT + 1)
     
struct hash_entry  {
      unsigned long next;
      unsigned long saddr;
      unsigned long daddr;
      unsigned long type;
      unsigned long len;
      unsigned long seq;
      unsigned short id;
      char resolved;
      char protocol;
};

static struct hash_entry table[TABLE_SIZE];
static unsigned int hash_table[HASH_SIZE];

static unsigned long lookup_no = 1;

static struct hash_entry * lookup(const struct iphdr * iph)
{
      int h;
      
      h = hash_table[HASH(iph->id)];
#ifdef FRAG_DEBUG
      fprintf(stderr, "Lookup id %x h %d ", iph->id, h);
#endif
      
      while ( h )  {
            if  (iph->id == table[h].id &&
                 iph->saddr == table[h].saddr &&
                 iph->daddr == table[h].daddr &&
                 iph->protocol == table[h].protocol) {
                  table[h].seq = ++lookup_no;
#ifdef FRAG_DEBUG
                  fprintf(stderr, "returns %p (%d)\n", table+h, h);
#endif
                  return table + h;
            }
            h = table[h].next;
      }
#ifdef FRAG_DEBUG
      fprintf(stderr, "returns NULL\n");
#endif
      return NULL;
}

static struct hash_entry * insert(const struct iphdr * iph)
{
      unsigned int i;
      unsigned long minseq = lookup_no;
      unsigned int minno = 0;
      
      for (i = 1; i < TABLE_SIZE; i++) {
            if (table[i].seq < minseq)  {
                  minno = i;
                  if (!(minseq = table[i].seq))  {
                        break;
                  }
            }
      }
#ifdef FRAG_DEBUG
      fprintf(stderr, "Insert id = %x, minno = %d, minseq = %d ",
            iph->id, minno, minseq);
#endif
      if (minseq)  {
            i = hash_table[HASH(table[minno].id)];
            if (i == minno)  {
                  hash_table[HASH(table[minno].id)] = table[i].next;
            } else  {
                  while (table[i].next != minno)  {
                        if (!table[i].next)  {
#ifdef FRAG_DEBUG
                              fprintf (stderr,"frag: Internal logic error in hash management!!!!\n");
#endif
                              exit(1);
                        }
                        i = table[i].next;
                  }
                  table[i].next = table[minno].next;
            }
      }

      table[minno].seq = ++lookup_no;
      table[minno].saddr = iph->saddr;          
      table[minno].daddr = iph->daddr;
      table[minno].protocol = iph->protocol;
      table[minno].id = iph->id;
      table[minno].len = 0;
      table[minno].resolved = 0;
      table[minno].next = hash_table[HASH(iph->id)];
      hash_table[HASH(iph->id)] = minno;
#ifdef FRAG_DEBUG
      fprintf(stderr, "returns %p (%d)\n", table + minno, minno);
#endif
      return table + minno;
}


int handle_fragment(struct iphdr * iph, int len)
{
      struct hash_entry * h;

#ifdef FRAG_DEBUG
      fprintf(stderr, "packet : src %x dst %x id %x frag %x proto %x len %x\n",
            ntohl(iph->saddr), ntohl(iph->daddr), ntohs(iph->id), ntohs(iph->frag_off),
            iph->protocol, len);
#endif
      if (!(h = lookup(iph)))  {
#ifdef FRAG_DEBUG
            fprintf(stderr, "Lookup failed !\n");
#endif
            h = insert(iph);
      }

#ifdef FRAG_DEBUG
      fprintf(stderr,"entry:  %p src %x dst %x id %x proto %x len %d h->len %d resolved %d\n",
            h, ntohl(h->saddr), ntohl(h->daddr), ntohs(h->id), h->protocol, len, h->len,
            h->resolved);
#endif
      if (!(ntohs(iph->frag_off) & 0x1fff)) {
            /* First fragment */
            len += h->len;
            h->len = 0;
            h->resolved = 1;
            memcpy(&h->type, (unsigned long *)iph + iph->ihl, 4);
#ifdef FRAG_DEBUG
            fprintf(stderr, "first fragment, return %d\n", len);
#endif
            return len;
      }
      if (h->resolved) {
            memcpy((unsigned long *)iph + iph->ihl, &h->type, 4);
#ifdef FRAG_DEBUG
            fprintf(stderr, "header copied, return %d\n", len);
#endif
            return len;
      }
      h->len += len;
#ifdef FRAG_DEBUG
      fprintf(stderr, "no first, h->len %d\n", h->len);
#endif
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index