1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/*
* $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",
iph->saddr, iph->daddr, iph->id, 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, h->saddr, h->daddr, h->id, h->protocol, len, h->len, h->resolved);
#endif
if (!(iph->frag_off & 0xff1f)) {
/* 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;
}
|