tagging vde-2 version 2.3.2
[vde.git] / 2.3.2 / src / vde_over_ns / pstack.c
blob100876e01488d07bd1ed7065a4f8afba518b70fb
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 <config.h>
37 #include <vde.h>
38 #include <vdecommon.h>
40 #include "fun.h"
41 #include "pstack.h"
43 static struct nstx_item * get_item_by_id(unsigned int id);
44 static struct nstx_item * alloc_item(unsigned int id);
45 static char * dealloc_item(struct nstx_item *ptr, int *l);
46 static int add_data(struct nstx_item *item, struct nstxhdr *pkt, int datalen);
47 static void check_timeouts(void);
49 static struct nstx_item *nstx_list = NULL;
51 void
52 nstx_handlepacket(const char *ptr, size_t len,
53 void (*nstx_usepacket)(const char*, size_t))
55 struct nstxhdr *nstxpkt = (struct nstxhdr *) ptr;
56 struct nstx_item *nstxitem;
57 char *netpacket;
58 int netpacketlen;
60 if ((!ptr) || (signed int) len < (signed int) sizeof(struct nstxhdr))
61 return;
63 if (!nstxpkt->id)
64 return;
66 nstxitem = get_item_by_id(nstxpkt->id);
68 if (!nstxitem)
69 nstxitem = alloc_item(nstxpkt->id);
71 if (add_data(nstxitem, nstxpkt, len)) {
72 netpacket = dealloc_item(nstxitem, &netpacketlen);
73 nstx_usepacket(netpacket, netpacketlen);
75 check_timeouts();
78 static struct nstx_item * get_item_by_id(unsigned int id) {
79 struct nstx_item *ptr = nstx_list;
81 if (!ptr)
82 return NULL;
84 while (ptr) {
85 if (ptr->id == id)
86 return ptr;
87 ptr = ptr->next;
89 return NULL;
92 static struct nstx_item * alloc_item(unsigned int id) {
93 struct nstx_item *ptr;
95 ptr = malloc(sizeof(struct nstx_item));
96 memset(ptr, 0, sizeof(struct nstx_item));
97 ptr->next = nstx_list;
98 if (ptr->next)
99 ptr->next->prev = ptr;
100 nstx_list = ptr;
102 ptr->id = id;
103 return ptr;
106 static char * dealloc_item(struct nstx_item *ptr, int *l) {
107 static char *data = NULL;
108 int len = 0;
109 struct clist *c, *tmp;
111 if (ptr->prev)
112 ptr->prev->next = ptr->next;
113 else
114 nstx_list = ptr->next;
115 if (ptr->next)
116 ptr->next->prev = ptr->prev;
118 c = ptr->chunks;
119 while (c) {
120 data = realloc(data, len+c->len);
121 memcpy(data+len, c->data, c->len);
122 len += c->len;
123 free(c->data);
124 tmp = c->next;
125 free(c);
126 c = tmp;
128 free(ptr);
130 if (l)
131 *l = len;
132 return data;
135 static void add_data_chunk(struct nstx_item *item, int seq,
136 char *data, int len) {
137 struct clist *next, *prev, *ptr;
139 prev = next = NULL;
140 if (!item->chunks)
141 ptr = item->chunks = malloc(sizeof(struct clist));
142 else if (item->chunks->seq == seq)
143 return;
144 else if (item->chunks->seq > seq) {
145 next = item->chunks;
146 ptr = item->chunks = malloc(sizeof(struct clist));
147 } else {
148 prev = item->chunks;
149 while (prev->next && (prev->next->seq < seq))
150 prev = prev->next;
151 next = prev->next;
152 if (next && (next->seq == seq))
153 return;
154 ptr = malloc(sizeof(struct clist));
156 memset(ptr, 0, sizeof(struct clist));
157 if (prev)
158 prev->next = ptr;
159 ptr->next = next;
160 ptr->seq = seq;
161 ptr->len = len;
162 ptr->data = malloc(len);
163 memcpy(ptr->data, data, len);
166 static int find_sequence (struct nstx_item *item) {
167 struct clist *list;
168 int i;
170 for (i = 0, list = item->chunks; list; i++, list = list->next)
171 if (list->seq != i)
172 break;
174 return i;
177 static int add_data(struct nstx_item *item, struct nstxhdr *pkt, int datalen) {
178 char *payload;
180 payload = ((char *) pkt) + sizeof(struct nstxhdr);
181 item->timestamp = time(NULL);
182 if (pkt->flags & NSTX_LF) {
183 item->frc = pkt->seq+1;
186 add_data_chunk(item, pkt->seq, payload, datalen-sizeof(struct nstxhdr));
187 if (item->frc && (find_sequence(item) == item->frc)) {
188 return 1;
190 return 0;
193 static void check_timeouts(void) {
194 unsigned int now;
195 struct nstx_item *ptr = nstx_list, *ptr2;
197 now = time(NULL);
199 while (ptr) {
200 ptr2 = ptr;
201 ptr = ptr->next;
202 if (now > (ptr2->timestamp + NSTX_TIMEOUT)) {
203 dealloc_item(ptr2, NULL);