/* ----------------------------------------------------------------------------
NSTX -- tunneling network-packets over DNS
(C) 2000 by Florian Heinz and Julien Oster
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-------------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include "nstxfun.h"
#include "nstx_pstack.h"
static struct nstx_item * get_item_by_id(unsigned int id);
static struct nstx_item * alloc_item(unsigned int id);
static char * dealloc_item(struct nstx_item *ptr, int *l);
static int add_data(struct nstx_item *item, struct nstxhdr *pkt, int datalen);
static void check_timeouts(void);
static struct nstx_item *nstx_list = NULL;
void
nstx_handlepacket(const char *ptr, size_t len,
void (*nstx_usepacket)(const char*, size_t))
{
struct nstxhdr *nstxpkt = (struct nstxhdr *) ptr;
struct nstx_item *nstxitem;
char *netpacket;
int netpacketlen;
if ((!ptr) || (signed int) len < (signed int) sizeof(struct nstxhdr))
return;
if (!nstxpkt->id)
return;
nstxitem = get_item_by_id(nstxpkt->id);
if (!nstxitem)
nstxitem = alloc_item(nstxpkt->id);
if (add_data(nstxitem, nstxpkt, len)) {
netpacket = dealloc_item(nstxitem, &netpacketlen);
nstx_usepacket(netpacket, netpacketlen);
}
check_timeouts();
}
static struct nstx_item * get_item_by_id(unsigned int id) {
struct nstx_item *ptr = nstx_list;
if (!ptr)
return NULL;
while (ptr) {
if (ptr->id == id)
return ptr;
ptr = ptr->next;
}
return NULL;
}
static struct nstx_item * alloc_item(unsigned int id) {
struct nstx_item *ptr;
ptr = malloc(sizeof(struct nstx_item));
memset(ptr, 0, sizeof(struct nstx_item));
ptr->next = nstx_list;
if (ptr->next)
ptr->next->prev = ptr;
nstx_list = ptr;
ptr->id = id;
return ptr;
}
static char * dealloc_item(struct nstx_item *ptr, int *l) {
static char *data = NULL;
int len = 0;
struct clist *c, *tmp;
if (ptr->prev)
ptr->prev->next = ptr->next;
else
nstx_list = ptr->next;
if (ptr->next)
ptr->next->prev = ptr->prev;
c = ptr->chunks;
while (c) {
data = realloc(data, len+c->len);
memcpy(data+len, c->data, c->len);
len += c->len;
free(c->data);
tmp = c->next;
free(c);
c = tmp;
}
free(ptr);
if (l)
*l = len;
return data;
}
static void add_data_chunk(struct nstx_item *item, int seq,
char *data, int len) {
struct clist *next, *prev, *ptr;
prev = next = NULL;
if (!item->chunks)
ptr = item->chunks = malloc(sizeof(struct clist));
else if (item->chunks->seq == seq)
return;
else if (item->chunks->seq > seq) {
next = item->chunks;
ptr = item->chunks = malloc(sizeof(struct clist));
} else {
prev = item->chunks;
while (prev->next && (prev->next->seq < seq))
prev = prev->next;
next = prev->next;
if (next && (next->seq == seq))
return;
ptr = malloc(sizeof(struct clist));
}
memset(ptr, 0, sizeof(struct clist));
if (prev)
prev->next = ptr;
ptr->next = next;
ptr->seq = seq;
ptr->len = len;
ptr->data = malloc(len);
memcpy(ptr->data, data, len);
}
static int find_sequence (struct nstx_item *item) {
struct clist *list;
int i;
for (i = 0, list = item->chunks; list; i++, list = list->next)
if (list->seq != i)
break;
return i;
}
static int add_data(struct nstx_item *item, struct nstxhdr *pkt, int datalen) {
char *payload;
payload = ((char *) pkt) + sizeof(struct nstxhdr);
item->timestamp = time(NULL);
if (pkt->flags & NSTX_LF) {
item->frc = pkt->seq+1;
}
add_data_chunk(item, pkt->seq, payload, datalen-sizeof(struct nstxhdr));
if (item->frc && (find_sequence(item) == item->frc)) {
return 1;
}
return 0;
}
static void check_timeouts(void) {
unsigned int now;
struct nstx_item *ptr = nstx_list, *ptr2;
now = time(NULL);
while (ptr) {
ptr2 = ptr;
ptr = ptr->next;
if (now > (ptr2->timestamp + NSTX_TIMEOUT)) {
dealloc_item(ptr2, NULL);
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1