aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-06 23:18:26 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-06 23:18:26 +0000
commitf07938e02ddc22a8c61e26f0a81d7dc4d5c814b4 (patch)
tree5589a378f0ccf79e1f09e49f2e0ecaa77fa27f4e /src/vpn
parent9e4ffd173145ed63e458a6f3c1dbe80c3ff43da6 (diff)
downloadgnunet-f07938e02ddc22a8c61e26f0a81d7dc4d5c814b4.tar.gz
gnunet-f07938e02ddc22a8c61e26f0a81d7dc4d5c814b4.zip
-importing from gnunet-daemon-vpn to gnunet-service-vpn what can likely be re-used
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/Makefile.am10
-rw-r--r--src/vpn/gnunet-service-vpn.c1340
2 files changed, 1349 insertions, 1 deletions
diff --git a/src/vpn/Makefile.am b/src/vpn/Makefile.am
index 1fb1dd3f6..380db4446 100644
--- a/src/vpn/Makefile.am
+++ b/src/vpn/Makefile.am
@@ -26,7 +26,7 @@ endif
26 26
27 27
28bin_PROGRAMS = \ 28bin_PROGRAMS = \
29 gnunet-daemon-exit gnunet-daemon-vpn $(VPNBIN) $(HIJACKBIN) 29 gnunet-daemon-exit gnunet-daemon-vpn $(VPNBIN) gnunet-service-vpn
30 30
31 31
32gnunet_helper_vpn_SOURCES = \ 32gnunet_helper_vpn_SOURCES = \
@@ -43,6 +43,14 @@ gnunet_daemon_vpn_LDADD = \
43 $(top_builddir)/src/dns/libgnunetdns.la \ 43 $(top_builddir)/src/dns/libgnunetdns.la \
44 $(GN_LIBINTL) 44 $(GN_LIBINTL)
45 45
46gnunet_service_vpn_SOURCES = \
47 gnunet-service-vpn.c
48gnunet_service_vpn_LDADD = \
49 $(top_builddir)/src/statistics/libgnunetstatistics.la \
50 $(top_builddir)/src/util/libgnunetutil.la \
51 $(top_builddir)/src/mesh/libgnunetmesh.la \
52 $(GN_LIBINTL)
53
46gnunet_daemon_exit_SOURCES = \ 54gnunet_daemon_exit_SOURCES = \
47 gnunet-daemon-exit.c 55 gnunet-daemon-exit.c
48gnunet_daemon_exit_LDADD = \ 56gnunet_daemon_exit_LDADD = \
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c
new file mode 100644
index 000000000..098d8b944
--- /dev/null
+++ b/src/vpn/gnunet-service-vpn.c
@@ -0,0 +1,1340 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010, 2011, 2012 Christian Grothoff
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file vpn/gnunet-service-vpn.c
23 * @brief service that opens a virtual interface and allows its clients
24 * to allocate IPs on the virtual interface and to then redirect
25 * IP traffic received on those IPs via the GNUnet mesh
26 * @author Philipp Toelke
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet-vpn-packet.h"
31#include "gnunet_common.h"
32#include "gnunet_protocols.h"
33#include "gnunet_applications.h"
34#include "gnunet_mesh_service.h"
35#include "gnunet_constants.h"
36
37
38
39struct map_entry
40{
41 /** The description of the service (used for service) */
42 GNUNET_HashCode desc;
43
44 /** The real address of the service (used for remote) */
45 char addrlen;
46 char addr[16];
47
48 struct GNUNET_MESH_Tunnel *tunnel;
49 uint16_t namelen;
50 char additional_ports[8192];
51
52 struct GNUNET_CONTAINER_HeapNode *heap_node;
53 GNUNET_HashCode hash;
54
55};
56
57
58struct remote_addr
59{
60 char addrlen;
61 unsigned char addr[16];
62 char proto;
63};
64
65
66struct tunnel_notify_queue
67{
68 struct tunnel_notify_queue *next;
69 struct tunnel_notify_queue *prev;
70 size_t len;
71 void *cls;
72};
73
74
75struct tunnel_state
76{
77 struct GNUNET_MESH_TransmitHandle *th;
78 struct tunnel_notify_queue *head, *tail;
79
80 int addrlen;
81};
82
83
84
85/**
86 * Configuration we use.
87 */
88static const struct GNUNET_CONFIGURATION_Handle *cfg;
89
90/**
91 * Handle to the mesh service.
92 */
93static struct GNUNET_MESH_Handle *mesh_handle;
94
95/**
96 * FIXME
97 */
98static struct GNUNET_CONTAINER_MultiHashMap *hashmap;
99
100/**
101 * FIXME
102 */
103static struct GNUNET_CONTAINER_Heap *heap;
104
105/**
106 * The handle to the VPN helper process "gnunet-helper-vpn".
107 */
108static struct GNUNET_HELPER_Handle *helper_handle;
109
110/**
111 * Arguments to the exit helper.
112 */
113static char *vpn_argv[7];
114
115/**
116 * If there are at least this many address-mappings, old ones will be removed
117 */
118static unsigned long long max_mappings;
119
120
121/**
122 * @return the hash of the IP-Address if a mapping exists, NULL otherwise
123 */
124static GNUNET_HashCode *
125address6_mapping_exists (struct in6_addr *v6addr)
126{
127 unsigned char *addr = (unsigned char*) v6addr;
128 GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode));
129 unsigned char *k = (unsigned char *) key;
130
131 memset (key, 0, sizeof (GNUNET_HashCode));
132 unsigned int i;
133
134 for (i = 0; i < 16; i++)
135 k[15 - i] = addr[i];
136
137 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key))
138 return key;
139 else
140 {
141 GNUNET_free (key);
142 return NULL;
143 }
144}
145
146/**
147 * @return the hash of the IP-Address if a mapping exists, NULL otherwise
148 */
149static GNUNET_HashCode *
150address4_mapping_exists (uint32_t addr)
151{
152 GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode));
153
154 memset (key, 0, sizeof (GNUNET_HashCode));
155 unsigned char *c = (unsigned char *) &addr;
156 unsigned char *k = (unsigned char *) key;
157 unsigned int i;
158
159 for (i = 0; i < 4; i++)
160 k[3 - i] = c[i];
161
162 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
163 "a4_m_e: getting with key %08x, addr is %08x, %d.%d.%d.%d\n",
164 *((uint32_t *) (key)), addr, c[0], c[1], c[2], c[3]);
165
166 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key))
167 return key;
168 else
169 {
170 GNUNET_free (key);
171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mapping not found!\n");
172 return NULL;
173 }
174}
175
176
177static void *
178initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th)
179{
180 struct tunnel_state *ts = GNUNET_malloc (sizeof *ts);
181
182 ts->addrlen = addrlen;
183 ts->th = th;
184 return ts;
185}
186
187
188static void
189send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
190{
191 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
192 return;
193
194 struct ip_icmp *request = cls;
195
196 struct ip_icmp *response = alloca (ntohs (request->shdr.size));
197
198 GNUNET_assert (response != NULL);
199 memset (response, 0, ntohs (request->shdr.size));
200
201 response->shdr.size = request->shdr.size;
202 response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
203
204 response->tun.flags = 0;
205 response->tun.type = htons (0x0800);
206
207 response->ip_hdr.hdr_lngth = 5;
208 response->ip_hdr.version = 4;
209 response->ip_hdr.proto = 0x01;
210 response->ip_hdr.dadr = request->ip_hdr.sadr;
211 response->ip_hdr.sadr = request->ip_hdr.dadr;
212 response->ip_hdr.tot_lngth = request->ip_hdr.tot_lngth;
213
214 response->ip_hdr.chks =
215 GNUNET_CRYPTO_crc16_n ((uint16_t *) & response->ip_hdr, 20);
216
217 response->icmp_hdr.code = 0;
218 response->icmp_hdr.type = 0x0;
219
220 /* Magic, more Magic! */
221 response->icmp_hdr.chks = request->icmp_hdr.chks + 0x8;
222
223 /* Copy the rest of the packet */
224 memcpy (response + 1, request + 1,
225 ntohs (request->shdr.size) - sizeof (struct ip_icmp));
226
227 (void) GNUNET_HELPER_send (helper_handle,
228 &response->shdr,
229 GNUNET_YES,
230 NULL, NULL);
231 GNUNET_free (request);
232}
233
234
235static void
236send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
237{
238 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
239 return;
240
241 struct ip6_icmp *request = cls;
242
243 struct ip6_icmp *response = alloca (ntohs (request->shdr.size));
244
245 GNUNET_assert (response != NULL);
246 memset (response, 0, ntohs (request->shdr.size));
247
248 response->shdr.size = request->shdr.size;
249 response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
250
251 response->tun.flags = 0;
252 response->tun.type = htons (0x86dd);
253
254 response->ip6_hdr.hoplmt = 255;
255 response->ip6_hdr.paylgth = request->ip6_hdr.paylgth;
256 response->ip6_hdr.nxthdr = 0x3a;
257 response->ip6_hdr.version = 6;
258 memcpy (&response->ip6_hdr.sadr, &request->ip6_hdr.dadr, 16);
259 memcpy (&response->ip6_hdr.dadr, &request->ip6_hdr.sadr, 16);
260
261 response->icmp_hdr.code = 0;
262 response->icmp_hdr.type = 0x81;
263
264 /* Magic, more Magic! */
265 response->icmp_hdr.chks = request->icmp_hdr.chks - 0x1;
266
267 /* Copy the rest of the packet */
268 memcpy (response + 1, request + 1,
269 ntohs (request->shdr.size) - sizeof (struct ip6_icmp));
270
271 (void) GNUNET_HELPER_send (helper_handle,
272 &response->shdr,
273 GNUNET_YES,
274 NULL, NULL);
275 GNUNET_free (request);
276}
277
278
279/**
280 * cls is the pointer to a GNUNET_MessageHeader that is
281 * followed by the service-descriptor and the packet that should be sent;
282 */
283static size_t
284send_pkt_to_peer_notify_callback (void *cls, size_t size, void *buf)
285{
286 struct GNUNET_MESH_Tunnel **tunnel = cls;
287
288 struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel);
289
290 ts->th = NULL;
291
292 if (NULL != buf)
293 {
294 struct GNUNET_MessageHeader *hdr =
295 (struct GNUNET_MessageHeader *) (tunnel + 1);
296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
297 "send_pkt_to_peer_notify_callback: buf = %x; size = %u;\n", buf,
298 size);
299 GNUNET_assert (size >= ntohs (hdr->size));
300 memcpy (buf, hdr, ntohs (hdr->size));
301 size = ntohs (hdr->size);
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent!\n");
303 }
304 else
305 size = 0;
306
307 if (NULL != ts->head)
308 {
309 struct tunnel_notify_queue *element = ts->head;
310
311 GNUNET_CONTAINER_DLL_remove (ts->head, ts->tail, element);
312
313 ts->th =
314 GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42,
315 GNUNET_TIME_relative_divide
316 (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
317 (const struct GNUNET_PeerIdentity *)
318 NULL, element->len,
319 send_pkt_to_peer_notify_callback,
320 element->cls);
321
322 /* save the handle */
323 GNUNET_free (element);
324 }
325 GNUNET_free (cls);
326
327 return size;
328}
329
330
331static void
332send_pkt_to_peer (void *cls, const struct GNUNET_PeerIdentity *peer,
333 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
334{
335 /* peer == NULL means that all peers in this request are connected */
336 if (peer == NULL)
337 return;
338 struct GNUNET_MESH_Tunnel **tunnel = cls;
339 struct GNUNET_MessageHeader *hdr =
340 (struct GNUNET_MessageHeader *) (tunnel + 1);
341
342 GNUNET_assert (NULL != tunnel);
343 GNUNET_assert (NULL != *tunnel);
344
345 struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel);
346
347 if (NULL == ts->th)
348 {
349 ts->th =
350 GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42,
351 GNUNET_TIME_relative_divide
352 (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
353 (const struct GNUNET_PeerIdentity *)
354 NULL, ntohs (hdr->size),
355 send_pkt_to_peer_notify_callback,
356 cls);
357 }
358 else
359 {
360 struct tunnel_notify_queue *element = GNUNET_malloc (sizeof *element);
361
362 element->cls = cls;
363 element->len = ntohs (hdr->size);
364
365 GNUNET_CONTAINER_DLL_insert_tail (ts->head, ts->tail, element);
366 }
367}
368
369
370
371
372/**
373 * Receive packets from the helper-process
374 */
375static void
376message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
377 const struct GNUNET_MessageHeader *message)
378{
379 GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER);
380
381 struct tun_pkt *pkt_tun = (struct tun_pkt *) message;
382 GNUNET_HashCode *key;
383
384 /* ethertype is ipv6 */
385 if (ntohs (pkt_tun->tun.type) == 0x86dd)
386 {
387 struct ip6_pkt *pkt6 = (struct ip6_pkt *) message;
388
389 GNUNET_assert (pkt6->ip6_hdr.version == 6);
390 struct ip6_tcp *pkt6_tcp;
391 struct ip6_udp *pkt6_udp;
392 struct ip6_icmp *pkt6_icmp;
393
394 pkt6_udp = NULL; /* make compiler happy */
395 switch (pkt6->ip6_hdr.nxthdr)
396 {
397 case IPPROTO_UDP:
398 pkt6_udp = (struct ip6_udp *) pkt6;
399 /* Send dns-packets to the service-dns */
400 /* fall through */
401 case IPPROTO_TCP:
402 pkt6_tcp = (struct ip6_tcp *) pkt6;
403
404 if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
405 {
406 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
407
408 GNUNET_assert (me != NULL);
409 GNUNET_free (key);
410
411 size_t size =
412 sizeof (struct GNUNET_MESH_Tunnel *) +
413 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
414 ntohs (pkt6->ip6_hdr.paylgth);
415
416 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
417 struct GNUNET_MessageHeader *hdr =
418 (struct GNUNET_MessageHeader *) (cls + 1);
419 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
420
421 hdr->size =
422 htons (sizeof (struct GNUNET_MessageHeader) +
423 sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth));
424
425 GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */
426
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
428 me->addrlen);
429 if (me->addrlen == 0)
430 {
431 /* This is a mapping to a gnunet-service */
432 *hc = me->desc;
433
434 if (me->tunnel == NULL && NULL != cls)
435 {
436 *cls =
437 GNUNET_MESH_tunnel_create (mesh_handle,
438 initialize_tunnel_state (16, NULL),
439 &send_pkt_to_peer, NULL, cls);
440
441 GNUNET_MESH_peer_request_connect_add (*cls,
442 (struct GNUNET_PeerIdentity *)
443 &me->desc);
444 me->tunnel = *cls;
445 }
446 else if (NULL != cls)
447 {
448 *cls = me->tunnel;
449 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
450 }
451 }
452 else
453 {
454 /* This is a mapping to a "real" address */
455 struct remote_addr *s = (struct remote_addr *) hc;
456
457 s->addrlen = me->addrlen;
458 memcpy (s->addr, me->addr, me->addrlen);
459 s->proto = pkt6->ip6_hdr.nxthdr;
460 if (s->proto == IPPROTO_UDP)
461 {
462 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
463 memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
464 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
465 }
466 else if (s->proto == IPPROTO_TCP)
467 {
468 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
469 memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
470 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
471 }
472 else
473 {
474 GNUNET_assert (0);
475 }
476 if (me->tunnel == NULL && NULL != cls)
477 {
478 *cls =
479 GNUNET_MESH_tunnel_create (mesh_handle,
480 initialize_tunnel_state (16, NULL),
481 &send_pkt_to_peer, NULL, cls);
482
483 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
484 me->tunnel = *cls;
485 }
486 else if (NULL != cls)
487 {
488 *cls = me->tunnel;
489 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
490 }
491 }
492 }
493 else
494 {
495 char pbuf[INET6_ADDRSTRLEN];
496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
497 "Packet to %s, which has no mapping\n",
498 inet_ntop (AF_INET6,
499 &pkt6->ip6_hdr.dadr,
500 pbuf,
501 sizeof (pbuf)));
502 }
503 break;
504 case 0x3a:
505 /* ICMPv6 */
506 pkt6_icmp = (struct ip6_icmp *) pkt6;
507 /* If this packet is an icmp-echo-request and a mapping exists, answer */
508 if (pkt6_icmp->icmp_hdr.type == 0x80 &&
509 (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
510 {
511 GNUNET_free (key);
512 pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size));
513 memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size));
514 GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp);
515 }
516 break;
517 }
518 }
519 /* ethertype is ipv4 */
520 else if (ntohs (pkt_tun->tun.type) == 0x0800)
521 {
522 struct ip_pkt *pkt = (struct ip_pkt *) message;
523 //struct ip_udp *udp = (struct ip_udp *) message;
524 struct ip_tcp *pkt_tcp;
525 struct ip_udp *pkt_udp;
526 struct ip_icmp *pkt_icmp;
527
528 GNUNET_assert (pkt->ip_hdr.version == 4);
529
530 {
531 uint32_t dadr = pkt->ip_hdr.dadr.s_addr;
532 unsigned char *c = (unsigned char *) &dadr;
533
534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n",
535 c[0], c[1], c[2], c[3], pkt->ip_hdr.proto);
536 switch (pkt->ip_hdr.proto)
537 {
538 case IPPROTO_TCP:
539 case IPPROTO_UDP:
540 pkt_tcp = (struct ip_tcp *) pkt;
541 pkt_udp = (struct ip_udp *) pkt;
542
543 if ((key = address4_mapping_exists (dadr)) != NULL)
544 {
545 struct map_entry *me =
546 GNUNET_CONTAINER_multihashmap_get (hashmap, key);
547 GNUNET_assert (me != NULL);
548 GNUNET_free (key);
549
550 size_t size =
551 sizeof (struct GNUNET_MESH_Tunnel *) +
552 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
553 ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth;
554
555 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
556 struct GNUNET_MessageHeader *hdr =
557 (struct GNUNET_MessageHeader *) (cls + 1);
558 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
559
560 hdr->size =
561 htons (sizeof (struct GNUNET_MessageHeader) +
562 sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) -
563 4 * pkt->ip_hdr.hdr_lngth);
564
565 GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */
566
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
568 me->addrlen);
569 if (me->addrlen == 0)
570 {
571 /* This is a mapping to a gnunet-service */
572 *hc = me->desc;
573
574 if (me->tunnel == NULL && NULL != cls)
575 {
576 *cls =
577 GNUNET_MESH_tunnel_create (mesh_handle,
578 initialize_tunnel_state (4, NULL),
579 send_pkt_to_peer, NULL, cls);
580 GNUNET_MESH_peer_request_connect_add (*cls,
581 (struct GNUNET_PeerIdentity
582 *) &me->desc);
583 me->tunnel = *cls;
584 }
585 else if (NULL != cls)
586 {
587 *cls = me->tunnel;
588 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
589 }
590 }
591 else
592 {
593 /* This is a mapping to a "real" address */
594 struct remote_addr *s = (struct remote_addr *) hc;
595
596 s->addrlen = me->addrlen;
597 memcpy (s->addr, me->addr, me->addrlen);
598 s->proto = pkt->ip_hdr.proto;
599 if (s->proto == IPPROTO_UDP)
600 {
601 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
602 memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
603 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
604 }
605 else if (s->proto == IPPROTO_TCP)
606 {
607 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
608 memcpy (hc + 1, &pkt_tcp->tcp_hdr,
609 ntohs (pkt->ip_hdr.tot_lngth) -
610 4 * pkt->ip_hdr.hdr_lngth);
611 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
612 }
613 else
614 GNUNET_assert (0);
615 if (me->tunnel == NULL && NULL != cls)
616 {
617 *cls =
618 GNUNET_MESH_tunnel_create (mesh_handle,
619 initialize_tunnel_state (4, NULL),
620 send_pkt_to_peer, NULL, cls);
621
622 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
623 me->tunnel = *cls;
624 }
625 else if (NULL != cls)
626 {
627 *cls = me->tunnel;
628 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
629 }
630 }
631 }
632 else
633 {
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Packet to %x which has no mapping\n", dadr);
636 }
637 break;
638 case 0x01:
639 /* ICMP */
640 pkt_icmp = (struct ip_icmp *) pkt;
641 if (pkt_icmp->icmp_hdr.type == 0x8 &&
642 (key = address4_mapping_exists (dadr)) != NULL)
643 {
644 GNUNET_free (key);
645 pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size));
646 memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size));
647 GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp);
648 }
649 break;
650 }
651 }
652 }
653}
654
655
656
657
658
659/**
660 * Create a new Address from an answer-packet
661 */
662static void
663new_ip6addr (struct in6_addr *v6addr,
664 const GNUNET_HashCode * peer,
665 const GNUNET_HashCode * service_desc)
666{ /* {{{ */
667 unsigned char *buf = (unsigned char*) v6addr;
668 char *ipv6addr;
669 unsigned long long ipv6prefix;
670
671 GNUNET_assert (GNUNET_OK ==
672 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
673 &ipv6addr));
674 GNUNET_assert (GNUNET_OK ==
675 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
676 "IPV6PREFIX",
677 &ipv6prefix));
678 GNUNET_assert (ipv6prefix < 127);
679 ipv6prefix = (ipv6prefix + 7) / 8;
680
681 inet_pton (AF_INET6, ipv6addr, buf);
682 GNUNET_free (ipv6addr);
683
684 int peer_length = 16 - ipv6prefix - 6;
685
686 if (peer_length <= 0)
687 peer_length = 0;
688
689 int service_length = 16 - ipv6prefix - peer_length;
690
691 if (service_length <= 0)
692 service_length = 0;
693
694 memcpy (buf + ipv6prefix, service_desc, service_length);
695 memcpy (buf + ipv6prefix + service_length, peer, peer_length);
696}
697
698/*}}}*/
699
700
701/**
702 * Create a new Address from an answer-packet
703 */
704static void
705new_ip6addr_remote (struct in6_addr *v6addr,
706 unsigned char *addr, char addrlen)
707{ /* {{{ */
708 unsigned char *buf = (unsigned char*) v6addr;
709 char *ipv6addr;
710 unsigned long long ipv6prefix;
711
712 GNUNET_assert (GNUNET_OK ==
713 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
714 &ipv6addr));
715 GNUNET_assert (GNUNET_OK ==
716 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
717 "IPV6PREFIX",
718 &ipv6prefix));
719 GNUNET_assert (ipv6prefix < 127);
720 ipv6prefix = (ipv6prefix + 7) / 8;
721
722 inet_pton (AF_INET6, ipv6addr, buf);
723 GNUNET_free (ipv6addr);
724
725 int local_length = 16 - ipv6prefix;
726
727 memcpy (buf + ipv6prefix, addr, GNUNET_MIN (addrlen, local_length));
728}
729
730/*}}}*/
731
732/**
733 * Create a new Address from an answer-packet
734 */
735static void
736new_ip4addr_remote (unsigned char *buf, unsigned char *addr, char addrlen)
737{ /* {{{ */
738 char *ipv4addr;
739 char *ipv4mask;
740
741 GNUNET_assert (GNUNET_OK ==
742 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
743 &ipv4addr));
744 GNUNET_assert (GNUNET_OK ==
745 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
746 &ipv4mask));
747 uint32_t mask;
748
749 inet_pton (AF_INET, ipv4addr, buf);
750 int r = inet_pton (AF_INET, ipv4mask, &mask);
751
752 mask = htonl (mask);
753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inet_pton: %d; %m; mask: %08x\n", r,
754 mask);
755
756 GNUNET_free (ipv4addr);
757
758 int c;
759
760 if (mask)
761 {
762 mask = (mask ^ (mask - 1)) >> 1;
763 for (c = 0; mask; c++)
764 {
765 mask >>= 1;
766 }
767 }
768 else
769 {
770 c = CHAR_BIT * sizeof (mask);
771 }
772
773 c = 32 - c;
774 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The mask %s has %d leading 1s.\n",
775 ipv4mask, c);
776
777 GNUNET_free (ipv4mask);
778
779 if (c % 8 == 0)
780 c = c / 8;
781 else
782 GNUNET_assert (0);
783
784 memcpy (buf + c, addr, GNUNET_MIN (addrlen, 4 - c));
785}
786
787/*}}}*/
788
789
790
791/**
792 * FIXME: document.
793 */
794static int
795receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
796 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
797 const struct GNUNET_MessageHeader *message,
798 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
799{
800 GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
801 struct remote_addr *s = (struct remote_addr *) desc;
802 struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
803 const struct GNUNET_PeerIdentity *other = sender;
804 struct tunnel_state *ts = *tunnel_ctx;
805
806 if (16 == ts->addrlen)
807 {
808 size_t size =
809 sizeof (struct ip6_udp) + ntohs (pkt->len) - 1 -
810 sizeof (struct udp_pkt);
811
812 struct ip6_udp *pkt6 = alloca (size);
813
814 GNUNET_assert (pkt6 != NULL);
815
816 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK)
817 new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
818 else
819 new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
820
821 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
822 "Relaying calc:%d gnu:%d udp:%d bytes!\n", size,
823 ntohs (message->size), ntohs (pkt->len));
824
825 pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
826 pkt6->shdr.size = htons (size);
827
828 pkt6->tun.flags = 0;
829 pkt6->tun.type = htons (0x86dd);
830
831 pkt6->ip6_hdr.version = 6;
832 pkt6->ip6_hdr.tclass_h = 0;
833 pkt6->ip6_hdr.tclass_l = 0;
834 pkt6->ip6_hdr.flowlbl = 0;
835 pkt6->ip6_hdr.paylgth = pkt->len;
836 pkt6->ip6_hdr.nxthdr = IPPROTO_UDP;
837 pkt6->ip6_hdr.hoplmt = 0xff;
838
839 {
840 char *ipv6addr;
841
842 GNUNET_assert (GNUNET_OK ==
843 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
844 "IPV6ADDR",
845 &ipv6addr));
846 inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
847 GNUNET_free (ipv6addr);
848 }
849 memcpy (&pkt6->udp_hdr, pkt, ntohs (pkt->len));
850
851 GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
852
853 GNUNET_assert (key != NULL);
854
855 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
856
857 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
858 GNUNET_TIME_absolute_get ().abs_value);
859
860 GNUNET_free (key);
861
862 GNUNET_assert (me != NULL);
863
864 pkt6->udp_hdr.crc = 0;
865 uint32_t sum = 0;
866
867 sum =
868 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
869 sum =
870 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
871 uint32_t tmp = (pkt6->udp_hdr.len & 0xffff);
872
873 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
874 tmp = htons (((pkt6->ip6_hdr.nxthdr & 0x00ff)));
875 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
876
877 sum =
878 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->udp_hdr,
879 ntohs (pkt->len));
880 pkt6->udp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
881
882 (void) GNUNET_HELPER_send (helper_handle,
883 &pkt6->shdr,
884 GNUNET_YES,
885 NULL, NULL);
886 }
887 else
888 {
889 size_t size =
890 sizeof (struct ip_udp) + ntohs (pkt->len) - 1 - sizeof (struct udp_pkt);
891
892 struct ip_udp *pkt4 = alloca (size);
893
894 GNUNET_assert (pkt4 != NULL);
895
896 GNUNET_assert (ntohs (message->type) ==
897 GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
898 uint32_t sadr;
899
900 new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
901 pkt4->ip_hdr.sadr.s_addr = sadr;
902
903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
904 "Relaying calc:%d gnu:%d udp:%d bytes!\n", size,
905 ntohs (message->size), ntohs (pkt->len));
906
907 pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
908 pkt4->shdr.size = htons (size);
909
910 pkt4->tun.flags = 0;
911 pkt4->tun.type = htons (0x0800);
912
913 pkt4->ip_hdr.version = 4;
914 pkt4->ip_hdr.hdr_lngth = 5;
915 pkt4->ip_hdr.diff_serv = 0;
916 pkt4->ip_hdr.tot_lngth = htons (20 + ntohs (pkt->len));
917 pkt4->ip_hdr.ident = 0;
918 pkt4->ip_hdr.flags = 0;
919 pkt4->ip_hdr.frag_off = 0;
920 pkt4->ip_hdr.ttl = 255;
921 pkt4->ip_hdr.proto = IPPROTO_UDP;
922 pkt4->ip_hdr.chks = 0; /* Will be calculated later */
923
924 {
925 char *ipv4addr;
926 uint32_t dadr;
927
928 GNUNET_assert (GNUNET_OK ==
929 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
930 "IPV4ADDR",
931 &ipv4addr));
932 inet_pton (AF_INET, ipv4addr, &dadr);
933 GNUNET_free (ipv4addr);
934 pkt4->ip_hdr.dadr.s_addr = dadr;
935 }
936 memcpy (&pkt4->udp_hdr, pkt, ntohs (pkt->len));
937
938 GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
939
940 GNUNET_assert (key != NULL);
941
942 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
943
944 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
945 GNUNET_TIME_absolute_get ().abs_value);
946
947 GNUNET_free (key);
948
949 GNUNET_assert (me != NULL);
950
951 pkt4->udp_hdr.crc = 0; /* Optional for IPv4 */
952
953 pkt4->ip_hdr.chks =
954 GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
955
956 (void) GNUNET_HELPER_send (helper_handle,
957 &pkt4->shdr,
958 GNUNET_YES,
959 NULL, NULL);
960 }
961
962 return GNUNET_OK;
963}
964
965
966/**
967 * FIXME: document.
968 */
969static int
970receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
971 void **tunnel_ctx,
972 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
973 const struct GNUNET_MessageHeader *message,
974 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
975{
976 GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
977 struct remote_addr *s = (struct remote_addr *) desc;
978 struct tcp_pkt *pkt = (struct tcp_pkt *) (desc + 1);
979 const struct GNUNET_PeerIdentity *other = sender;
980 struct tunnel_state *ts = *tunnel_ctx;
981
982 size_t pktlen =
983 ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
984 sizeof (GNUNET_HashCode);
985
986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
987 "Received TCP-Packet back, addrlen = %d\n", s->addrlen);
988
989 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK ||
990 ts->addrlen == 16)
991 {
992 size_t size = pktlen + sizeof (struct ip6_tcp) - 1;
993
994 struct ip6_tcp *pkt6 = alloca (size);
995
996 memset (pkt6, 0, size);
997
998 GNUNET_assert (pkt6 != NULL);
999
1000 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK)
1001 new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
1002 else
1003 new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
1004
1005 pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1006 pkt6->shdr.size = htons (size);
1007
1008 pkt6->tun.flags = 0;
1009 pkt6->tun.type = htons (0x86dd);
1010
1011 pkt6->ip6_hdr.version = 6;
1012 pkt6->ip6_hdr.tclass_h = 0;
1013 pkt6->ip6_hdr.tclass_l = 0;
1014 pkt6->ip6_hdr.flowlbl = 0;
1015 pkt6->ip6_hdr.paylgth = htons (pktlen);
1016 pkt6->ip6_hdr.nxthdr = IPPROTO_TCP;
1017 pkt6->ip6_hdr.hoplmt = 0xff;
1018
1019 {
1020 char *ipv6addr;
1021
1022 GNUNET_assert (GNUNET_OK ==
1023 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1024 "IPV6ADDR",
1025 &ipv6addr));
1026 inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
1027 GNUNET_free (ipv6addr);
1028 }
1029 memcpy (&pkt6->tcp_hdr, pkt, pktlen);
1030
1031 GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
1032
1033 GNUNET_assert (key != NULL);
1034
1035 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1036
1037 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1038 GNUNET_TIME_absolute_get ().abs_value);
1039
1040 GNUNET_free (key);
1041
1042 GNUNET_assert (me != NULL);
1043
1044 pkt6->tcp_hdr.crc = 0;
1045 uint32_t sum = 0;
1046 uint32_t tmp;
1047
1048 sum =
1049 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
1050 sum =
1051 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
1052 tmp = htonl (pktlen);
1053 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1054 tmp = htonl (((pkt6->ip6_hdr.nxthdr & 0x000000ff)));
1055 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1056
1057 sum =
1058 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->tcp_hdr,
1059 ntohs (pkt6->ip6_hdr.paylgth));
1060 pkt6->tcp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
1061
1062 (void) GNUNET_HELPER_send (helper_handle,
1063 &pkt6->shdr,
1064 GNUNET_YES,
1065 NULL, NULL);
1066 }
1067 else
1068 {
1069 size_t size = pktlen + sizeof (struct ip_tcp) - 1;
1070
1071 struct ip_tcp *pkt4 = alloca (size);
1072
1073 GNUNET_assert (pkt4 != NULL);
1074 memset (pkt4, 0, size);
1075
1076 GNUNET_assert (ntohs (message->type) ==
1077 GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
1078 uint32_t sadr;
1079
1080 new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
1081 pkt4->ip_hdr.sadr.s_addr = sadr;
1082
1083 pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1084 pkt4->shdr.size = htons (size);
1085
1086 pkt4->tun.flags = 0;
1087 pkt4->tun.type = htons (0x0800);
1088
1089 pkt4->ip_hdr.version = 4;
1090 pkt4->ip_hdr.hdr_lngth = 5;
1091 pkt4->ip_hdr.diff_serv = 0;
1092 pkt4->ip_hdr.tot_lngth = htons (20 + pktlen);
1093 pkt4->ip_hdr.ident = 0;
1094 pkt4->ip_hdr.flags = 0;
1095 pkt4->ip_hdr.frag_off = 0;
1096 pkt4->ip_hdr.ttl = 255;
1097 pkt4->ip_hdr.proto = IPPROTO_TCP;
1098 pkt4->ip_hdr.chks = 0; /* Will be calculated later */
1099
1100 {
1101 char *ipv4addr;
1102 uint32_t dadr;
1103
1104 GNUNET_assert (GNUNET_OK ==
1105 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1106 "IPV4ADDR",
1107 &ipv4addr));
1108 inet_pton (AF_INET, ipv4addr, &dadr);
1109 GNUNET_free (ipv4addr);
1110 pkt4->ip_hdr.dadr.s_addr = dadr;
1111 }
1112
1113 memcpy (&pkt4->tcp_hdr, pkt, pktlen);
1114
1115 GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
1116
1117 GNUNET_assert (key != NULL);
1118
1119 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1120
1121 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1122 GNUNET_TIME_absolute_get ().abs_value);
1123
1124 GNUNET_free (key);
1125
1126 GNUNET_assert (me != NULL);
1127 pkt4->tcp_hdr.crc = 0;
1128 uint32_t sum = 0;
1129 uint32_t tmp;
1130
1131 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) &pkt4->ip_hdr.sadr, 4);
1132 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) &pkt4->ip_hdr.dadr, 4);
1133
1134 tmp = (0x06 << 16) | (0xffff & pktlen); // 0x06 for TCP?
1135
1136 tmp = htonl (tmp);
1137
1138 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1139
1140 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt4->tcp_hdr, pktlen);
1141 pkt4->tcp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
1142
1143 pkt4->ip_hdr.chks =
1144 GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1145
1146 (void) GNUNET_HELPER_send (helper_handle,
1147 &pkt4->shdr,
1148 GNUNET_YES,
1149 NULL, NULL);
1150
1151 }
1152
1153 return GNUNET_OK;
1154}
1155
1156
1157/**
1158 * FIXME: document.
1159 */
1160static void *
1161new_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1162 const struct GNUNET_PeerIdentity *initiator,
1163 const struct GNUNET_ATS_Information *atsi)
1164{
1165 /* Why should anyone open an inbound tunnel to vpn? */
1166 GNUNET_break (0);
1167 return NULL;
1168}
1169
1170
1171/**
1172 * FIXME: document.
1173 */
1174static void
1175tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
1176{
1177 /* Why should anyone open an inbound tunnel to vpn? */
1178 /* FIXME: is this not also called for outbound tunnels that go down!? */
1179 GNUNET_break (0);
1180}
1181
1182
1183/**
1184 * Function scheduled as very last function, cleans up after us
1185 */
1186static void
1187cleanup (void *cls GNUNET_UNUSED,
1188 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1189{
1190 unsigned int i;
1191
1192 if (mesh_handle != NULL)
1193 {
1194 GNUNET_MESH_disconnect (mesh_handle);
1195 mesh_handle = NULL;
1196 }
1197 if (helper_handle != NULL)
1198 {
1199 GNUNET_HELPER_stop (helper_handle);
1200 helper_handle = NULL;
1201 }
1202 for (i=0;i<5;i++)
1203 GNUNET_free_non_null (vpn_argv[i]);
1204}
1205
1206
1207/**
1208 * Main function that will be run by the scheduler.
1209 *
1210 * @param cls closure
1211 * @param server the initialized server
1212 * @param cfg_ configuration
1213 */
1214static void
1215run (void *cls,
1216 struct GNUNET_SERVER_Handle *server,
1217 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1218{
1219 static const struct GNUNET_MESH_MessageHandler handlers[] = {
1220 {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK, 0},
1221 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK, 0},
1222 {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK, 0},
1223 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
1224 {NULL, 0, 0}
1225 };
1226 static const GNUNET_MESH_ApplicationType types[] = {
1227 GNUNET_APPLICATION_TYPE_END
1228 };
1229 char *ifname;
1230 char *ipv6addr;
1231 char *ipv6prefix_s;
1232 char *ipv4addr;
1233 char *ipv4mask;
1234 struct in_addr v4;
1235 struct in6_addr v6;
1236 unsigned long long ipv6prefix;
1237
1238 cfg = cfg_;
1239 hashmap = GNUNET_CONTAINER_multihashmap_create (65536);
1240 heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1241
1242 if (GNUNET_OK !=
1243 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
1244 &max_mappings))
1245 max_mappings = 200;
1246
1247 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1248 if (GNUNET_SYSERR ==
1249 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1250 {
1251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1252 "No entry 'IFNAME' in configuration!\n");
1253 GNUNET_SCHEDULER_shutdown ();
1254 return;
1255 }
1256 vpn_argv[1] = ifname;
1257 if ( (GNUNET_SYSERR ==
1258 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
1259 &ipv6addr) ||
1260 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1261 {
1262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1263 "No valid entry 'IPV6ADDR' in configuration!\n");
1264 GNUNET_SCHEDULER_shutdown ();
1265 return;
1266 }
1267 vpn_argv[2] = ipv6addr;
1268 if (GNUNET_SYSERR ==
1269 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1270 &ipv6prefix_s))
1271 {
1272 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1273 "No entry 'IPV6PREFIX' in configuration!\n");
1274 GNUNET_SCHEDULER_shutdown ();
1275 return;
1276 }
1277 vpn_argv[3] = ipv6prefix_s;
1278 if ( (GNUNET_OK !=
1279 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
1280 "IPV6PREFIX",
1281 &ipv6prefix)) ||
1282 (ipv6prefix >= 127) )
1283 {
1284 GNUNET_SCHEDULER_shutdown ();
1285 return;
1286 }
1287
1288 if ( (GNUNET_SYSERR ==
1289 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
1290 &ipv4addr) ||
1291 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1292 {
1293 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1294 "No valid entry for 'IPV4ADDR' in configuration!\n");
1295 GNUNET_SCHEDULER_shutdown ();
1296 return;
1297 }
1298 vpn_argv[4] = ipv4addr;
1299 if ( (GNUNET_SYSERR ==
1300 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
1301 &ipv4mask) ||
1302 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1303 {
1304 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1305 "No valid entry 'IPV4MASK' in configuration!\n");
1306 GNUNET_SCHEDULER_shutdown ();
1307 return;
1308 }
1309 vpn_argv[5] = ipv4mask;
1310 vpn_argv[6] = NULL;
1311
1312 mesh_handle =
1313 GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL,
1314 &new_tunnel,
1315 &tunnel_cleaner,
1316 handlers,
1317 types);
1318 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
1319 &message_token, NULL);
1320 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1321}
1322
1323
1324/**
1325 * The main function of the VPN service.
1326 *
1327 * @param argc number of arguments from the command line
1328 * @param argv command line arguments
1329 * @return 0 ok, 1 on error
1330 */
1331int
1332main (int argc, char *const *argv)
1333{
1334 return (GNUNET_OK ==
1335 GNUNET_SERVICE_run (argc, argv, "vpn",
1336 GNUNET_SERVICE_OPTION_NONE,
1337 &run, NULL)) ? 0 : 1;
1338}
1339
1340/* end of gnunet-service-vpn.c */