Commit f16eab13 authored by 's avatar
Browse files

fixes in libnids


git-svn-id: file:///home/svn/mapi/trunk@220 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent f530671e
......@@ -34,23 +34,16 @@ static int threshold = 0;
static unsigned int timeout = 0;
//unsigned int client_size = 0,server_size=0;
struct mapidlibflow *mod_flow = NULL;
char* to_free = NULL;
char* to_free2 = NULL;
struct headers_data *headers = NULL;
extern struct pcap_pkthdr *nids_last_pcap_header;
mapid_pkthdr_t *last_mapid_header;
int status;
unsigned char *last_dev_pkt;
struct mapidlibflow *cook_tmp_flow=NULL;
static int cooking_id=0;
extern struct tcp_stream *find_stream(struct tcphdr * this_tcphdr, struct ip * this_iphdr,int *from_client,int id);
void create_mod_pkt(unsigned char *dev_pkt,struct mapidlibflow *flow,mapid_pkthdr_t *pkt_head);
void process_flushed_data(struct mapidlibflow *flow);
static int cook_instance(mapidflib_function_instance_t* instance, flist_t *flist, mapidflib_flow_mod_t *flow_mod,function_manipulation_t* manip)
{
......@@ -145,7 +138,6 @@ void tcp_callback(struct tcp_stream *ns, void **param)
ns->client.read = 0;
ns->client.total_read = 0;
if(ns->client.headers==NULL) {
fprintf(stderr,"Initing 2..\n");
ns->client.headers = (flist_t *)malloc(sizeof(flist_t));
flist_init(ns->client.headers);
}
......@@ -346,8 +338,7 @@ void tcp_callback(struct tcp_stream *ns, void **param)
return;
}
static int cook_init(mapidflib_function_instance_t *instance,
flist_t *flist)
static int cook_init(mapidflib_function_instance_t *instance,flist_t *flist)
{
mapiFunctArg* fargs;
struct pcap desc;
......@@ -365,6 +356,7 @@ static int cook_init(mapidflib_function_instance_t *instance,
desc.linktype = instance->hwinfo->link_type;
desc.bufsize = instance->hwinfo->cap_length;
printf("INiting::: %d\n",data->id);
nids_mapi_init(&desc, instance->hwinfo->link_type,data->id);
nids_mapi_register_tcp(tcp_callback,data->id);
......@@ -382,7 +374,7 @@ static int cook_init(mapidflib_function_instance_t *instance,
// return 1 in order for processing to continue in other functions
// return 0 not to
static int cook_process(mapidflib_function_instance_t *instance,const unsigned char* dev_pkt,const unsigned char* link_pkt, mapid_pkthdr_t* pkt_head)
static int cook_process(mapidflib_function_instance_t *instance,const unsigned char* dev_pkt,unsigned char* link_pkt, mapid_pkthdr_t* pkt_head)
{
struct pcap_pkthdr h;
......@@ -391,21 +383,23 @@ static int cook_process(mapidflib_function_instance_t *instance,const unsigned c
struct tcphdr *tcph;
int ether_len = 0, ip_len = 0;
struct mapidlibflow *flow;
struct cooking_data* data;
struct headers_data *headers;
data= (struct cooking_data*)(instance->internal_data);
threshold = data->threshold;
timeout = data->timeout;
flow=data->flow;
//fprintf(stderr,"I am COOKING\n");
last_dev_pkt= link_pkt;
last_mapid_header = pkt_head;
h.caplen=pkt_head->caplen;
h.len=pkt_head->wlen;
h.ts.tv_sec=pkt_head->ts; //XXX
h.ts.tv_usec=pkt_head->ts;
struct cooking_data* data = (struct cooking_data*)(instance->internal_data);
threshold = data->threshold;
timeout = data->timeout;
flow=data->flow;
status = NON_CHECKED;
......@@ -413,7 +407,6 @@ static int cook_process(mapidflib_function_instance_t *instance,const unsigned c
flow->ret_server_data = NULL;
flow->client_size=flow->server_size=0;
eth = (ether_header*)link_pkt;
ether_len = sizeof(ether_header);
iph = (struct ip*)(link_pkt + ether_len);
......@@ -431,7 +424,6 @@ static int cook_process(mapidflib_function_instance_t *instance,const unsigned c
tcph = (struct tcphdr *)(link_pkt + ether_len + ip_len);
//XXX replace 0
stream= find_stream(tcph,iph,&from_client,data->id);
if(stream) {
//fprintf(stderr,"\tStream found\n");
......@@ -480,7 +472,6 @@ static int cook_process(mapidflib_function_instance_t *instance,const unsigned c
headers->ts.tv_sec = pkt_head->ts; //XXX
headers->ts.tv_usec = pkt_head->ts;
//XXX replace 0
stream= find_stream(tcph,iph,&from_client,data->id);
if(stream==NULL) {
//fprintf(stderr,"\tNULL stream %d %d\n",headers->ts.tv_sec,headers->ts.tv_usec);
......
......@@ -95,13 +95,13 @@ struct ipq {
This fragment handler is a bit of a heap. On the other hand it works
quite happily and handles things quite well.
*/
static struct hostfrags **fragtable;
static struct hostfrags *this_host;
static struct hostfrags **fragtable[MAX_LIBNIDS_INSTANCES];
static struct hostfrags *this_host[MAX_LIBNIDS_INSTANCES];
static int numpack = 0;
static int hash_size;
static int timenow;
static unsigned int time0;
static struct timer_list *timer_head = 0, *timer_tail = 0;
static struct timer_list *timer_head[MAX_LIBNIDS_INSTANCES], *timer_tail[MAX_LIBNIDS_INSTANCES];
#define int_ntoa(x) inet_ntoa(*((struct in_addr *)&x))
......@@ -146,69 +146,69 @@ panic(char *str)
}
static void
add_timer(struct timer_list * x)
add_timer(struct timer_list * x,int id)
{
if (timer_tail) {
timer_tail->next = x;
x->prev = timer_tail;
if (timer_tail[id]) {
timer_tail[id]->next = x;
x->prev = timer_tail[id];
x->next = 0;
timer_tail = x;
timer_tail[id] = x;
}
else {
x->prev = 0;
x->next = 0;
timer_tail = timer_head = x;
timer_tail[id] = timer_head[id] = x;
}
}
static void
del_timer(struct timer_list * x)
del_timer(struct timer_list * x,int id)
{
if (x->prev)
x->prev->next = x->next;
else
timer_head = x->next;
timer_head[id] = x->next;
if (x->next)
x->next->prev = x->prev;
else
timer_tail = x->prev;
timer_tail[id] = x->prev;
}
static void
frag_kfree_skb(struct sk_buff * skb, int type)
frag_kfree_skb(struct sk_buff * skb, int type,int id)
{
if (this_host)
atomic_sub(skb->truesize, &this_host->ip_frag_mem);
if (this_host[id])
atomic_sub(skb->truesize, &this_host[id]->ip_frag_mem);
kfree_skb(skb, type);
}
static void
frag_kfree_s(void *ptr, int len)
frag_kfree_s(void *ptr, int len,int id)
{
if (this_host)
atomic_sub(len, &this_host->ip_frag_mem);
if (this_host[id])
atomic_sub(len, &this_host[id]->ip_frag_mem);
free(ptr);
}
static void *
frag_kmalloc(int size, int dummy)
frag_kmalloc(int size, int dummy,int id)
{
void *vp = (void *) malloc(size);
(void)dummy;
if (!vp)
return NULL;
atomic_add(size, &this_host->ip_frag_mem);
atomic_add(size, &this_host[id]->ip_frag_mem);
return vp;
}
/* Create a new fragment entry. */
static struct ipfrag *
ip_frag_create(int offset, int end, struct sk_buff * skb, unsigned char *ptr)
ip_frag_create(int offset, int end, struct sk_buff * skb, unsigned char *ptr,int id)
{
struct ipfrag *fp;
fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC,id);
if (fp == NULL) {
// NETDEBUG(printk("IP: frag_create: no memory left !\n"));
nids_params.no_mem("ip_frag_create");
......@@ -224,7 +224,7 @@ ip_frag_create(int offset, int end, struct sk_buff * skb, unsigned char *ptr)
fp->ptr = ptr;
/* Charge for the SKB as well. */
this_host->ip_frag_mem += skb->truesize;
this_host[id]->ip_frag_mem += skb->truesize;
return (fp);
}
......@@ -238,59 +238,59 @@ frag_index(struct ip * iph)
}
static int
hostfrag_find(struct ip * iph)
hostfrag_find(struct ip * iph,int id)
{
int hash_index = frag_index(iph);
struct hostfrags *hf;
this_host = 0;
for (hf = fragtable[hash_index]; hf; hf = hf->next) {
this_host[id] = 0;
for (hf = fragtable[id][hash_index]; hf; hf = hf->next) {
if (hf->ip == iph->ip_dst.s_addr) {
this_host = hf;
this_host[id] = hf;
break;
}
}
if (!this_host)
if (!this_host[id])
return 0;
else
return 1;
}
static void
hostfrag_create(struct ip * iph)
hostfrag_create(struct ip * iph,int id)
{
struct hostfrags *hf = mknew(struct hostfrags);
int hash_index = frag_index(iph);
hf->prev = 0;
hf->next = fragtable[hash_index];
hf->next = fragtable[id][hash_index];
if (hf->next)
hf->next->prev = hf;
fragtable[hash_index] = hf;
fragtable[id][hash_index] = hf;
hf->ip = iph->ip_dst.s_addr;
hf->ipqueue = 0;
hf->ip_frag_mem = 0;
hf->hash_index = hash_index;
this_host = hf;
this_host[id] = hf;
}
static void
rmthis_host()
rmthis_host(int id)
{
int hash_index = this_host->hash_index;
int hash_index = this_host[id]->hash_index;
if (this_host->prev) {
this_host->prev->next = this_host->next;
if (this_host->next)
this_host->next->prev = this_host->prev;
if (this_host[id]->prev) {
this_host[id]->prev->next = this_host[id]->next;
if (this_host[id]->next)
this_host[id]->next->prev = this_host[id]->prev;
}
else {
fragtable[hash_index] = this_host->next;
if (this_host->next)
this_host->next->prev = 0;
fragtable[id][hash_index] = this_host[id]->next;
if (this_host[id]->next)
this_host[id]->next->prev = 0;
}
free(this_host);
this_host = 0;
free(this_host[id]);
this_host[id] = 0;
}
/*
......@@ -298,18 +298,18 @@ rmthis_host()
IP datagram, and return the queue entry address if found.
*/
static struct ipq *
ip_find(struct ip * iph)
ip_find(struct ip * iph,int id)
{
struct ipq *qp;
struct ipq *qplast;
qplast = NULL;
for (qp = this_host->ipqueue; qp != NULL; qplast = qp, qp = qp->next) {
for (qp = this_host[id]->ipqueue; qp != NULL; qplast = qp, qp = qp->next) {
if (iph->ip_id == qp->iph->ip_id &&
iph->ip_src.s_addr == qp->iph->ip_src.s_addr &&
iph->ip_dst.s_addr == qp->iph->ip_dst.s_addr &&
iph->ip_p == qp->iph->ip_p) {
del_timer(&qp->timer); /* So it doesn't vanish on us. The timer will
del_timer(&qp->timer,id); /* So it doesn't vanish on us. The timer will
be reset anyway */
return (qp);
}
......@@ -323,21 +323,21 @@ ip_find(struct ip * iph)
timed out.
*/
static void
ip_free(struct ipq * qp)
ip_free(struct ipq * qp,int id)
{
struct ipfrag *fp;
struct ipfrag *xp;
/* Stop the timer for this entry. */
del_timer(&qp->timer);
del_timer(&qp->timer,id);
/* Remove this entry from the "incomplete datagrams" queue. */
if (qp->prev == NULL) {
this_host->ipqueue = qp->next;
if (this_host->ipqueue != NULL)
this_host->ipqueue->prev = NULL;
this_host[id]->ipqueue = qp->next;
if (this_host[id]->ipqueue != NULL)
this_host[id]->ipqueue->prev = NULL;
else
rmthis_host();
rmthis_host(id);
}
else {
qp->prev->next = qp->next;
......@@ -348,27 +348,27 @@ ip_free(struct ipq * qp)
fp = qp->fragments;
while (fp != NULL) {
xp = fp->next;
frag_kfree_skb(fp->skb, FREE_READ);
frag_kfree_s(fp, sizeof(struct ipfrag));
frag_kfree_skb(fp->skb, FREE_READ,id);
frag_kfree_s(fp, sizeof(struct ipfrag),id);
fp = xp;
}
/* Release the IP header. */
frag_kfree_s(qp->iph, 64 + 8);
frag_kfree_s(qp->iph, 64 + 8,id);
/* Finally, release the queue descriptor itself. */
frag_kfree_s(qp, sizeof(struct ipq));
frag_kfree_s(qp, sizeof(struct ipq),id);
}
/* Oops- a fragment queue timed out. Kill it and send an ICMP reply. */
static void
ip_expire(unsigned long arg)
ip_expire(unsigned long arg,int id)
{
struct ipq *qp;
qp = (struct ipq *) arg;
/* Nuke the fragment queue. */
ip_free(qp);
ip_free(qp,id);
}
/*
......@@ -376,13 +376,13 @@ ip_expire(unsigned long arg)
queue until we are back under the low threshold.
*/
static void
ip_evictor(void)
ip_evictor(int id)
{
// fprintf(stderr, "ip_evict:numpack=%i\n", numpack);
while (this_host->ip_frag_mem > IPFRAG_LOW_THRESH) {
if (!this_host->ipqueue)
while (this_host[id]->ip_frag_mem > IPFRAG_LOW_THRESH) {
if (!this_host[id]->ipqueue)
panic("ip_evictor: memcount");
ip_free(this_host->ipqueue);
ip_free(this_host[id]->ipqueue,id);
}
}
......@@ -393,12 +393,12 @@ ip_evictor(void)
will insert the received fragments at their respective positions.
*/
static struct ipq *
ip_create(struct ip * iph)
ip_create(struct ip * iph,int id)
{
struct ipq *qp;
int ihlen;
qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC);
qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC,id);
if (qp == NULL) {
// NETDEBUG(printk("IP: create: no memory left !\n"));
nids_params.no_mem("ip_create");
......@@ -408,31 +408,31 @@ ip_create(struct ip * iph)
/* Allocate memory for the IP header (plus 8 octets for ICMP). */
ihlen = iph->ip_hl * 4;
qp->iph = (struct ip *) frag_kmalloc(64 + 8, GFP_ATOMIC);
qp->iph = (struct ip *) frag_kmalloc(64 + 8, GFP_ATOMIC,id);
if (qp->iph == NULL) {
//NETDEBUG(printk("IP: create: no memory left !\n"));
nids_params.no_mem("ip_create");
frag_kfree_s(qp, sizeof(struct ipq));
frag_kfree_s(qp, sizeof(struct ipq),id);
return (NULL);
}
memcpy(qp->iph, iph, ihlen + 8);
qp->len = 0;
qp->ihlen = ihlen;
qp->fragments = NULL;
qp->hf = this_host;
qp->hf = this_host[id];
/* Start a timer for this entry. */
qp->timer.expires = jiffies() + IP_FRAG_TIME; /* about 30 seconds */
qp->timer.data = (unsigned long) qp; /* pointer to queue */
qp->timer.function = ip_expire; /* expire function */
add_timer(&qp->timer);
add_timer(&qp->timer,id);
/* Add this entry to the queue. */
qp->prev = NULL;
qp->next = this_host->ipqueue;
qp->next = this_host[id]->ipqueue;
if (qp->next != NULL)
qp->next->prev = qp;
this_host->ipqueue = qp;
this_host[id]->ipqueue = qp;
return (qp);
}
......@@ -470,7 +470,7 @@ ip_done(struct ipq * qp)
not going to touch this with a bargepole.
*/
static char *
ip_glue(struct ipq * qp)
ip_glue(struct ipq * qp,int id)
{
char *skb;
struct ip *iph;
......@@ -484,13 +484,13 @@ ip_glue(struct ipq * qp)
if (len > 65535) {
// NETDEBUG(printk("Oversized IP packet from %s.\n", int_ntoa(qp->iph->ip_src.s_addr)));
nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_OVERSIZED, qp->iph, 0);
ip_free(qp);
ip_free(qp,id);
return NULL;
}
if ((skb = (char *) malloc(len)) == NULL) {
// NETDEBUG(printk("IP: queue_glue: no memory for gluing queue %p\n", qp));
nids_params.no_mem("ip_glue");
ip_free(qp);
ip_free(qp,id);
return (NULL);
}
/* Fill in the basic details. */
......@@ -505,7 +505,7 @@ ip_glue(struct ipq * qp)
if (fp->len < 0 || fp->offset + qp->ihlen + fp->len > len) {
//NETDEBUG(printk("Invalid fragment list: Fragment over size.\n"));
nids_params.syslog(NIDS_WARN_IP, NIDS_WARN_IP_INVLIST, qp->iph, 0);
ip_free(qp);
ip_free(qp,id);
//kfree_skb(skb, FREE_WRITE);
//ip_statistics.IpReasmFails++;
free(skb);
......@@ -516,7 +516,7 @@ ip_glue(struct ipq * qp)
fp = fp->next;
}
/* We glued together all fragments, so remove the queue entry. */
ip_free(qp);
ip_free(qp,id);
/* Done with all fragments. Fixup the new IP header. */
iph = (struct ip *) skb;
......@@ -529,7 +529,7 @@ ip_glue(struct ipq * qp)
/* Process an incoming IP datagram fragment. */
static char *
ip_defrag(struct ip *iph, struct sk_buff *skb)
ip_defrag(struct ip *iph, struct sk_buff *skb,int id)
{
struct ipfrag *prev, *next, *tmp;
struct ipfrag *tfp;
......@@ -539,17 +539,17 @@ ip_defrag(struct ip *iph, struct sk_buff *skb)
int flags, offset;
int i, ihl, end;
if (!hostfrag_find(iph) && skb)
hostfrag_create(iph);
if (!hostfrag_find(iph,id) && skb)
hostfrag_create(iph,id);
/* Start by cleaning up the memory. */
if (this_host)
if (this_host->ip_frag_mem > IPFRAG_HIGH_THRESH)
ip_evictor();
if (this_host[id])
if (this_host[id]->ip_frag_mem > IPFRAG_HIGH_THRESH)
ip_evictor(id);
/* Find the entry of this IP datagram in the "incomplete datagrams" queue. */
if (this_host)
qp = ip_find(iph);
if (this_host[id])
qp = ip_find(iph,id);
else
qp = 0;
......@@ -559,7 +559,7 @@ ip_defrag(struct ip *iph, struct sk_buff *skb)
offset &= IP_OFFSET;
if (((flags & IP_MF) == 0) && (offset == 0)) {
if (qp != NULL)
ip_free(qp); /* Fragmented frame replaced by full
ip_free(qp,id); /* Fragmented frame replaced by full
unfragmented copy */
return 0;
}
......@@ -578,15 +578,15 @@ ip_defrag(struct ip *iph, struct sk_buff *skb)
qp->ihlen = ihl;
memcpy(qp->iph, iph, ihl + 8);
}
del_timer(&qp->timer);
del_timer(&qp->timer,id);
qp->timer.expires = jiffies() + IP_FRAG_TIME; /* about 30 seconds */
qp->timer.data = (unsigned long) qp; /* pointer to queue */
qp->timer.function = ip_expire; /* expire function */
add_timer(&qp->timer);
add_timer(&qp->timer,id);
}
else {
/* If we failed to create it, then discard the frame. */
if ((qp = ip_create(iph)) == NULL) {
if ((qp = ip_create(iph,id)) == NULL) {
kfree_skb(skb, FREE_READ);
return NULL;
}
......@@ -660,13 +660,13 @@ ip_defrag(struct ip *iph, struct sk_buff *skb)
next = tfp; /* We have killed the original next frame */
frag_kfree_skb(tmp->skb, FREE_READ);
frag_kfree_s(tmp, sizeof(struct ipfrag));
frag_kfree_skb(tmp->skb, FREE_READ,id);
frag_kfree_s(tmp, sizeof(struct ipfrag),id);
}
}
/* Insert this fragment in the chain of fragments. */
tfp = NULL;
tfp = ip_frag_create(offset, end, skb, ptr);
tfp = ip_frag_create(offset, end, skb, ptr,id);
/*
No memory to save the fragment - so throw the lot. If we failed
......@@ -694,29 +694,29 @@ ip_defrag(struct ip *iph, struct sk_buff *skb)
layer...
*/
if (ip_done(qp)) {
skb2 = ip_glue(qp); /* glue together the fragments */
skb2 = ip_glue(qp,id); /* glue together the fragments */
return (skb2);
}
return (NULL);
}
int
ip_defrag_stub(struct ip *iph, struct ip **defrag)
ip_defrag_stub(struct ip *iph, struct ip **defrag,int id)
{
int offset, flags, tot_len;
struct sk_buff *skb;
numpack++;
timenow = 0;
while (timer_head && timer_head->expires < jiffies()) {
this_host = ((struct ipq *) (timer_head->data))->hf;
timer_head->function(timer_head->data);
while (timer_head[id] && timer_head[id]->expires < jiffies()) {
this_host[id] = ((struct ipq *) (timer_head[id]->data))->hf;
timer_head[id]->function(timer_head[id]->data);
}
offset = ntohs(iph->ip_off);
flags = offset & ~IP_OFFSET;
offset &= IP_OFFSET;
if (((flags & IP_MF) == 0) && (offset == 0)) {
ip_defrag(iph, 0);
ip_defrag(iph, 0,id);
return IPF_NOTF;
}
tot_len = ntohs(iph->ip_len