[vde_switch] created vde_switch subdir and moved vde_switch inside it
[vde.git] / vde-2 / vde_over_ns / pstack.c
blob16f27bf093986e5902e63b96afc2e6cb590503ff
1 /* ----------------------------------------------------------------------------
3 VDE_OVER_NS
4 (C) 2007 Daniele Lacamera
6 Derived from:
7 NSTX -- tunneling network-packets over DNS
9 (C) 2000 by Florian Heinz and Julien Oster
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License version 2, as
13 published by the Free Software Foundation.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 -------------------------------------------------------------------------- */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/time.h>
34 #include <netinet/in.h>
36 #include "fun.h"
37 #include "pstack.h"
39 static struct nstx_item * get_item_by_id(unsigned int id);
40 static struct nstx_item * alloc_item(unsigned int id);
41 static char * dealloc_item(struct nstx_item *ptr, int *l);
42 static int add_data(struct nstx_item *item, struct nstxhdr *pkt, int datalen);
43 static void check_timeouts(void);
45 static struct nstx_item *nstx_list = NULL;
47 void
48 nstx_handlepacket(const char *ptr, size_t len,
49 void (*nstx_usepacket)(const char*, size_t))
51 struct nstxhdr *nstxpkt = (struct nstxhdr *) ptr;
52 struct nstx_item *nstxitem;
53 char *netpacket;
54 int netpacketlen;
56 if ((!ptr) || (signed int) len < (signed int) sizeof(struct nstxhdr))
57 return;
59 if (!nstxpkt->id)
60 return;
62 nstxitem = get_item_by_id(nstxpkt->id);
64 if (!nstxitem)
65 nstxitem = alloc_item(nstxpkt->id);
67 if (add_data(nstxitem, nstxpkt, len)) {
68 netpacket = dealloc_item(nstxitem, &netpacketlen);
69 nstx_usepacket(netpacket, netpacketlen);
71 check_timeouts();
74 static struct nstx_item * get_item_by_id(unsigned int id) {
75 struct nstx_item *ptr = nstx_list;
77 if (!ptr)
78 return NULL;
80 while (ptr) {
81 if (ptr->id == id)
82 return ptr;
83 ptr = ptr->next;
85 return NULL;
88 static struct nstx_item * alloc_item(unsigned int id) {
89 struct nstx_item *ptr;
91 ptr = malloc(sizeof(struct nstx_item));
92 memset(ptr, 0, sizeof(struct nstx_item));
93 ptr->next = nstx_list;
94 if (ptr->next)
95 ptr->next->prev = ptr;
96 nstx_list = ptr;
98 ptr->id = id;
99 return ptr;
102 static char * dealloc_item(struct nstx_item *ptr, int *l) {
103 static char *data = NULL;
104 int len = 0;
105 struct clist *c, *tmp;
107 if (ptr->prev)
108 ptr->prev->next = ptr->next;
109 else
110 nstx_list = ptr->next;
111 if (ptr->next)
112 ptr->next->prev = ptr->prev;
114 c = ptr->chunks;
115 while (c) {
116 data = realloc(data, len+c->len);
117 memcpy(data+len, c->data, c->len);
118 len += c->len;
119 free(c->data);
120 tmp = c->next;
121 free(c);
122 c = tmp;
124 free(ptr);
126 if (l)
127 *l = len;
128 return data;
131 static void add_data_chunk(struct nstx_item *item, int seq,
132 char *data, int len) {
133 struct clist *next, *prev, *ptr;
135 prev = next = NULL;
136 if (!item->chunks)
137 ptr = item->chunks = malloc(sizeof(struct clist));
138 else if (item->chunks->seq == seq)
139 return;
140 else if (item->chunks->seq > seq) {
141 next = item->chunks;
142 ptr = item->chunks = malloc(sizeof(struct clist));
143 } else {
144 prev = item->chunks;
145 while (prev->next && (prev->next->seq < seq))
146 prev = prev->next;
147 next = prev->next;
148 if (next && (next->seq == seq))
149 return;
150 ptr = malloc(sizeof(struct clist));
152 memset(ptr, 0, sizeof(struct clist));
153 if (prev)
154 prev->next = ptr;
155 ptr->next = next;
156 ptr->seq = seq;
157 ptr->len = len;
158 ptr->data = malloc(len);
159 memcpy(ptr->data, data, len);
162 static int find_sequence (struct nstx_item *item) {
163 struct clist *list;
164 int i;
166 for (i = 0, list = item->chunks; list; i++, list = list->next)
167 if (list->seq != i)
168 break;
170 return i;
173 static int add_data(struct nstx_item *item, struct nstxhdr *pkt, int datalen) {
174 char *payload;
176 payload = ((char *) pkt) + sizeof(struct nstxhdr);
177 item->timestamp = time(NULL);
178 if (pkt->flags & NSTX_LF) {
179 item->frc = pkt->seq+1;
182 add_data_chunk(item, pkt->seq, payload, datalen-sizeof(struct nstxhdr));
183 if (item->frc && (find_sequence(item) == item->frc)) {
184 return 1;
186 return 0;
189 static void check_timeouts(void) {
190 unsigned int now;
191 struct nstx_item *ptr = nstx_list, *ptr2;
193 now = time(NULL);
195 while (ptr) {
196 ptr2 = ptr;
197 ptr = ptr->next;
198 if (now > (ptr2->timestamp + NSTX_TIMEOUT)) {
199 dealloc_item(ptr2, NULL);