2 This file is part of GNUnet.
3 (C) 2010, 2011, 2012 Christian Grothoff
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.
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.
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.
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
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"
41 /** The description of the service (used for service) */
44 /** The real address of the service (used for remote) */
48 struct GNUNET_MESH_Tunnel *tunnel;
50 char additional_ports[8192];
52 struct GNUNET_CONTAINER_HeapNode *heap_node;
61 unsigned char addr[16];
66 struct tunnel_notify_queue
68 struct tunnel_notify_queue *next;
69 struct tunnel_notify_queue *prev;
77 struct GNUNET_MESH_TransmitHandle *th;
78 struct tunnel_notify_queue *head, *tail;
86 * Configuration we use.
88 static const struct GNUNET_CONFIGURATION_Handle *cfg;
91 * Handle to the mesh service.
93 static struct GNUNET_MESH_Handle *mesh_handle;
98 static struct GNUNET_CONTAINER_MultiHashMap *hashmap;
103 static struct GNUNET_CONTAINER_Heap *heap;
106 * The handle to the VPN helper process "gnunet-helper-vpn".
108 static struct GNUNET_HELPER_Handle *helper_handle;
111 * Arguments to the exit helper.
113 static char *vpn_argv[7];
116 * If there are at least this many address-mappings, old ones will be removed
118 static unsigned long long max_mappings;
122 * @return the hash of the IP-Address if a mapping exists, NULL otherwise
124 static GNUNET_HashCode *
125 address6_mapping_exists (struct in6_addr *v6addr)
127 unsigned char *addr = (unsigned char*) v6addr;
128 GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode));
129 unsigned char *k = (unsigned char *) key;
131 memset (key, 0, sizeof (GNUNET_HashCode));
134 for (i = 0; i < 16; i++)
137 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key))
147 * @return the hash of the IP-Address if a mapping exists, NULL otherwise
149 static GNUNET_HashCode *
150 address4_mapping_exists (uint32_t addr)
152 GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode));
154 memset (key, 0, sizeof (GNUNET_HashCode));
155 unsigned char *c = (unsigned char *) &addr;
156 unsigned char *k = (unsigned char *) key;
159 for (i = 0; i < 4; i++)
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]);
166 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key))
171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mapping not found!\n");
178 initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th)
180 struct tunnel_state *ts = GNUNET_malloc (sizeof *ts);
182 ts->addrlen = addrlen;
189 send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
191 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
194 struct ip_icmp *request = cls;
196 struct ip_icmp *response = alloca (ntohs (request->shdr.size));
198 GNUNET_assert (response != NULL);
199 memset (response, 0, ntohs (request->shdr.size));
201 response->shdr.size = request->shdr.size;
202 response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
204 response->tun.flags = 0;
205 response->tun.type = htons (0x0800);
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;
214 response->ip_hdr.chks =
215 GNUNET_CRYPTO_crc16_n ((uint16_t *) & response->ip_hdr, 20);
217 response->icmp_hdr.code = 0;
218 response->icmp_hdr.type = 0x0;
220 /* Magic, more Magic! */
221 response->icmp_hdr.chks = request->icmp_hdr.chks + 0x8;
223 /* Copy the rest of the packet */
224 memcpy (response + 1, request + 1,
225 ntohs (request->shdr.size) - sizeof (struct ip_icmp));
227 (void) GNUNET_HELPER_send (helper_handle,
231 GNUNET_free (request);
236 send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
238 if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
241 struct ip6_icmp *request = cls;
243 struct ip6_icmp *response = alloca (ntohs (request->shdr.size));
245 GNUNET_assert (response != NULL);
246 memset (response, 0, ntohs (request->shdr.size));
248 response->shdr.size = request->shdr.size;
249 response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
251 response->tun.flags = 0;
252 response->tun.type = htons (0x86dd);
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);
261 response->icmp_hdr.code = 0;
262 response->icmp_hdr.type = 0x81;
264 /* Magic, more Magic! */
265 response->icmp_hdr.chks = request->icmp_hdr.chks - 0x1;
267 /* Copy the rest of the packet */
268 memcpy (response + 1, request + 1,
269 ntohs (request->shdr.size) - sizeof (struct ip6_icmp));
271 (void) GNUNET_HELPER_send (helper_handle,
275 GNUNET_free (request);
280 * cls is the pointer to a GNUNET_MessageHeader that is
281 * followed by the service-descriptor and the packet that should be sent;
284 send_pkt_to_peer_notify_callback (void *cls, size_t size, void *buf)
286 struct GNUNET_MESH_Tunnel **tunnel = cls;
288 struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel);
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,
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");
307 if (NULL != ts->head)
309 struct tunnel_notify_queue *element = ts->head;
311 GNUNET_CONTAINER_DLL_remove (ts->head, ts->tail, element);
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 *)
319 send_pkt_to_peer_notify_callback,
322 /* save the handle */
323 GNUNET_free (element);
332 send_pkt_to_peer (void *cls, const struct GNUNET_PeerIdentity *peer,
333 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
335 /* peer == NULL means that all peers in this request are connected */
338 struct GNUNET_MESH_Tunnel **tunnel = cls;
339 struct GNUNET_MessageHeader *hdr =
340 (struct GNUNET_MessageHeader *) (tunnel + 1);
342 GNUNET_assert (NULL != tunnel);
343 GNUNET_assert (NULL != *tunnel);
345 struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel);
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,
360 struct tunnel_notify_queue *element = GNUNET_malloc (sizeof *element);
363 element->len = ntohs (hdr->size);
365 GNUNET_CONTAINER_DLL_insert_tail (ts->head, ts->tail, element);
373 * Receive packets from the helper-process
376 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
377 const struct GNUNET_MessageHeader *message)
379 GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER);
381 struct tun_pkt *pkt_tun = (struct tun_pkt *) message;
382 GNUNET_HashCode *key;
384 /* ethertype is ipv6 */
385 if (ntohs (pkt_tun->tun.type) == 0x86dd)
387 struct ip6_pkt *pkt6 = (struct ip6_pkt *) message;
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;
394 pkt6_udp = NULL; /* make compiler happy */
395 switch (pkt6->ip6_hdr.nxthdr)
398 pkt6_udp = (struct ip6_udp *) pkt6;
399 /* Send dns-packets to the service-dns */
402 pkt6_tcp = (struct ip6_tcp *) pkt6;
404 if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
406 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
408 GNUNET_assert (me != NULL);
412 sizeof (struct GNUNET_MESH_Tunnel *) +
413 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
414 ntohs (pkt6->ip6_hdr.paylgth);
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);
422 htons (sizeof (struct GNUNET_MessageHeader) +
423 sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth));
425 GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
429 if (me->addrlen == 0)
431 /* This is a mapping to a gnunet-service */
434 if (me->tunnel == NULL && NULL != cls)
437 GNUNET_MESH_tunnel_create (mesh_handle,
438 initialize_tunnel_state (16, NULL),
439 &send_pkt_to_peer, NULL, cls);
441 GNUNET_MESH_peer_request_connect_add (*cls,
442 (struct GNUNET_PeerIdentity *)
446 else if (NULL != cls)
449 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
454 /* This is a mapping to a "real" address */
455 struct remote_addr *s = (struct remote_addr *) hc;
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)
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;
466 else if (s->proto == IPPROTO_TCP)
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;
476 if (me->tunnel == NULL && NULL != cls)
479 GNUNET_MESH_tunnel_create (mesh_handle,
480 initialize_tunnel_state (16, NULL),
481 &send_pkt_to_peer, NULL, cls);
483 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
486 else if (NULL != cls)
489 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
495 char pbuf[INET6_ADDRSTRLEN];
496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
497 "Packet to %s, which has no mapping\n",
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)
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);
519 /* ethertype is ipv4 */
520 else if (ntohs (pkt_tun->tun.type) == 0x0800)
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;
528 GNUNET_assert (pkt->ip_hdr.version == 4);
531 uint32_t dadr = pkt->ip_hdr.dadr.s_addr;
532 unsigned char *c = (unsigned char *) &dadr;
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)
540 pkt_tcp = (struct ip_tcp *) pkt;
541 pkt_udp = (struct ip_udp *) pkt;
543 if ((key = address4_mapping_exists (dadr)) != NULL)
545 struct map_entry *me =
546 GNUNET_CONTAINER_multihashmap_get (hashmap, key);
547 GNUNET_assert (me != NULL);
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;
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);
561 htons (sizeof (struct GNUNET_MessageHeader) +
562 sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) -
563 4 * pkt->ip_hdr.hdr_lngth);
565 GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
569 if (me->addrlen == 0)
571 /* This is a mapping to a gnunet-service */
574 if (me->tunnel == NULL && NULL != 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
585 else if (NULL != cls)
588 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
593 /* This is a mapping to a "real" address */
594 struct remote_addr *s = (struct remote_addr *) hc;
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)
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;
605 else if (s->proto == IPPROTO_TCP)
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;
615 if (me->tunnel == NULL && NULL != cls)
618 GNUNET_MESH_tunnel_create (mesh_handle,
619 initialize_tunnel_state (4, NULL),
620 send_pkt_to_peer, NULL, cls);
622 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
625 else if (NULL != cls)
628 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
635 "Packet to %x which has no mapping\n", dadr);
640 pkt_icmp = (struct ip_icmp *) pkt;
641 if (pkt_icmp->icmp_hdr.type == 0x8 &&
642 (key = address4_mapping_exists (dadr)) != NULL)
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);
660 * Create a new Address from an answer-packet
663 new_ip6addr (struct in6_addr *v6addr,
664 const GNUNET_HashCode * peer,
665 const GNUNET_HashCode * service_desc)
667 unsigned char *buf = (unsigned char*) v6addr;
669 unsigned long long ipv6prefix;
671 GNUNET_assert (GNUNET_OK ==
672 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
674 GNUNET_assert (GNUNET_OK ==
675 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
678 GNUNET_assert (ipv6prefix < 127);
679 ipv6prefix = (ipv6prefix + 7) / 8;
681 inet_pton (AF_INET6, ipv6addr, buf);
682 GNUNET_free (ipv6addr);
684 int peer_length = 16 - ipv6prefix - 6;
686 if (peer_length <= 0)
689 int service_length = 16 - ipv6prefix - peer_length;
691 if (service_length <= 0)
694 memcpy (buf + ipv6prefix, service_desc, service_length);
695 memcpy (buf + ipv6prefix + service_length, peer, peer_length);
702 * Create a new Address from an answer-packet
705 new_ip6addr_remote (struct in6_addr *v6addr,
706 unsigned char *addr, char addrlen)
708 unsigned char *buf = (unsigned char*) v6addr;
710 unsigned long long ipv6prefix;
712 GNUNET_assert (GNUNET_OK ==
713 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
715 GNUNET_assert (GNUNET_OK ==
716 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
719 GNUNET_assert (ipv6prefix < 127);
720 ipv6prefix = (ipv6prefix + 7) / 8;
722 inet_pton (AF_INET6, ipv6addr, buf);
723 GNUNET_free (ipv6addr);
725 int local_length = 16 - ipv6prefix;
727 memcpy (buf + ipv6prefix, addr, GNUNET_MIN (addrlen, local_length));
733 * Create a new Address from an answer-packet
736 new_ip4addr_remote (unsigned char *buf, unsigned char *addr, char addrlen)
741 GNUNET_assert (GNUNET_OK ==
742 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
744 GNUNET_assert (GNUNET_OK ==
745 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
749 inet_pton (AF_INET, ipv4addr, buf);
750 int r = inet_pton (AF_INET, ipv4mask, &mask);
753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inet_pton: %d; %m; mask: %08x\n", r,
756 GNUNET_free (ipv4addr);
762 mask = (mask ^ (mask - 1)) >> 1;
763 for (c = 0; mask; c++)
770 c = CHAR_BIT * sizeof (mask);
774 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The mask %s has %d leading 1s.\n",
777 GNUNET_free (ipv4mask);
784 memcpy (buf + c, addr, GNUNET_MIN (addrlen, 4 - c));
795 receive_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)
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;
806 if (16 == ts->addrlen)
809 sizeof (struct ip6_udp) + ntohs (pkt->len) - 1 -
810 sizeof (struct udp_pkt);
812 struct ip6_udp *pkt6 = alloca (size);
814 GNUNET_assert (pkt6 != NULL);
816 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK)
817 new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
819 new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
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));
825 pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
826 pkt6->shdr.size = htons (size);
829 pkt6->tun.type = htons (0x86dd);
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;
842 GNUNET_assert (GNUNET_OK ==
843 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
846 inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
847 GNUNET_free (ipv6addr);
849 memcpy (&pkt6->udp_hdr, pkt, ntohs (pkt->len));
851 GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
853 GNUNET_assert (key != NULL);
855 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
857 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
858 GNUNET_TIME_absolute_get ().abs_value);
862 GNUNET_assert (me != NULL);
864 pkt6->udp_hdr.crc = 0;
868 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
870 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
871 uint32_t tmp = (pkt6->udp_hdr.len & 0xffff);
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);
878 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->udp_hdr,
880 pkt6->udp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
882 (void) GNUNET_HELPER_send (helper_handle,
890 sizeof (struct ip_udp) + ntohs (pkt->len) - 1 - sizeof (struct udp_pkt);
892 struct ip_udp *pkt4 = alloca (size);
894 GNUNET_assert (pkt4 != NULL);
896 GNUNET_assert (ntohs (message->type) ==
897 GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
900 new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
901 pkt4->ip_hdr.sadr.s_addr = sadr;
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));
907 pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
908 pkt4->shdr.size = htons (size);
911 pkt4->tun.type = htons (0x0800);
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 */
928 GNUNET_assert (GNUNET_OK ==
929 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
932 inet_pton (AF_INET, ipv4addr, &dadr);
933 GNUNET_free (ipv4addr);
934 pkt4->ip_hdr.dadr.s_addr = dadr;
936 memcpy (&pkt4->udp_hdr, pkt, ntohs (pkt->len));
938 GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
940 GNUNET_assert (key != NULL);
942 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
944 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
945 GNUNET_TIME_absolute_get ().abs_value);
949 GNUNET_assert (me != NULL);
951 pkt4->udp_hdr.crc = 0; /* Optional for IPv4 */
954 GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
956 (void) GNUNET_HELPER_send (helper_handle,
970 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
972 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
973 const struct GNUNET_MessageHeader *message,
974 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
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;
983 ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
984 sizeof (GNUNET_HashCode);
986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
987 "Received TCP-Packet back, addrlen = %d\n", s->addrlen);
989 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK ||
992 size_t size = pktlen + sizeof (struct ip6_tcp) - 1;
994 struct ip6_tcp *pkt6 = alloca (size);
996 memset (pkt6, 0, size);
998 GNUNET_assert (pkt6 != NULL);
1000 if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK)
1001 new_ip6addr (&pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
1003 new_ip6addr_remote (&pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
1005 pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1006 pkt6->shdr.size = htons (size);
1008 pkt6->tun.flags = 0;
1009 pkt6->tun.type = htons (0x86dd);
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;
1022 GNUNET_assert (GNUNET_OK ==
1023 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1026 inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.dadr);
1027 GNUNET_free (ipv6addr);
1029 memcpy (&pkt6->tcp_hdr, pkt, pktlen);
1031 GNUNET_HashCode *key = address6_mapping_exists (&pkt6->ip6_hdr.sadr);
1033 GNUNET_assert (key != NULL);
1035 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1037 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1038 GNUNET_TIME_absolute_get ().abs_value);
1042 GNUNET_assert (me != NULL);
1044 pkt6->tcp_hdr.crc = 0;
1049 GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
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);
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);
1062 (void) GNUNET_HELPER_send (helper_handle,
1069 size_t size = pktlen + sizeof (struct ip_tcp) - 1;
1071 struct ip_tcp *pkt4 = alloca (size);
1073 GNUNET_assert (pkt4 != NULL);
1074 memset (pkt4, 0, size);
1076 GNUNET_assert (ntohs (message->type) ==
1077 GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
1080 new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen);
1081 pkt4->ip_hdr.sadr.s_addr = sadr;
1083 pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1084 pkt4->shdr.size = htons (size);
1086 pkt4->tun.flags = 0;
1087 pkt4->tun.type = htons (0x0800);
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 */
1104 GNUNET_assert (GNUNET_OK ==
1105 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
1108 inet_pton (AF_INET, ipv4addr, &dadr);
1109 GNUNET_free (ipv4addr);
1110 pkt4->ip_hdr.dadr.s_addr = dadr;
1113 memcpy (&pkt4->tcp_hdr, pkt, pktlen);
1115 GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr.s_addr);
1117 GNUNET_assert (key != NULL);
1119 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
1121 GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
1122 GNUNET_TIME_absolute_get ().abs_value);
1126 GNUNET_assert (me != NULL);
1127 pkt4->tcp_hdr.crc = 0;
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);
1134 tmp = (0x06 << 16) | (0xffff & pktlen); // 0x06 for TCP?
1138 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & tmp, 4);
1140 sum = GNUNET_CRYPTO_crc16_step (sum, (uint16_t *) & pkt4->tcp_hdr, pktlen);
1141 pkt4->tcp_hdr.crc = GNUNET_CRYPTO_crc16_finish (sum);
1144 GNUNET_CRYPTO_crc16_n ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1146 (void) GNUNET_HELPER_send (helper_handle,
1161 new_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1162 const struct GNUNET_PeerIdentity *initiator,
1163 const struct GNUNET_ATS_Information *atsi)
1165 /* Why should anyone open an inbound tunnel to vpn? */
1175 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
1177 /* Why should anyone open an inbound tunnel to vpn? */
1178 /* FIXME: is this not also called for outbound tunnels that go down!? */
1184 * Function scheduled as very last function, cleans up after us
1187 cleanup (void *cls GNUNET_UNUSED,
1188 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1192 if (mesh_handle != NULL)
1194 GNUNET_MESH_disconnect (mesh_handle);
1197 if (helper_handle != NULL)
1199 GNUNET_HELPER_stop (helper_handle);
1200 helper_handle = NULL;
1203 GNUNET_free_non_null (vpn_argv[i]);
1208 * Main function that will be run by the scheduler.
1210 * @param cls closure
1211 * @param server the initialized server
1212 * @param cfg_ configuration
1216 struct GNUNET_SERVER_Handle *server,
1217 const struct GNUNET_CONFIGURATION_Handle *cfg_)
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},
1226 static const GNUNET_MESH_ApplicationType types[] = {
1227 GNUNET_APPLICATION_TYPE_END
1236 unsigned long long ipv6prefix;
1239 hashmap = GNUNET_CONTAINER_multihashmap_create (65536);
1240 heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1243 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
1247 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1248 if (GNUNET_SYSERR ==
1249 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1252 "No entry 'IFNAME' in configuration!\n");
1253 GNUNET_SCHEDULER_shutdown ();
1256 vpn_argv[1] = ifname;
1257 if ( (GNUNET_SYSERR ==
1258 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
1260 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1262 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1263 "No valid entry 'IPV6ADDR' in configuration!\n");
1264 GNUNET_SCHEDULER_shutdown ();
1267 vpn_argv[2] = ipv6addr;
1268 if (GNUNET_SYSERR ==
1269 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1272 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1273 "No entry 'IPV6PREFIX' in configuration!\n");
1274 GNUNET_SCHEDULER_shutdown ();
1277 vpn_argv[3] = ipv6prefix_s;
1279 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
1282 (ipv6prefix >= 127) )
1284 GNUNET_SCHEDULER_shutdown ();
1288 if ( (GNUNET_SYSERR ==
1289 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
1291 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1293 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1294 "No valid entry for 'IPV4ADDR' in configuration!\n");
1295 GNUNET_SCHEDULER_shutdown ();
1298 vpn_argv[4] = ipv4addr;
1299 if ( (GNUNET_SYSERR ==
1300 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
1302 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1304 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1305 "No valid entry 'IPV4MASK' in configuration!\n");
1306 GNUNET_SCHEDULER_shutdown ();
1309 vpn_argv[5] = ipv4mask;
1313 GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL,
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);
1325 * The main function of the VPN service.
1327 * @param argc number of arguments from the command line
1328 * @param argv command line arguments
1329 * @return 0 ok, 1 on error
1332 main (int argc, char *const *argv)
1334 return (GNUNET_OK ==
1335 GNUNET_SERVICE_run (argc, argv, "vpn",
1336 GNUNET_SERVICE_OPTION_NONE,
1337 &run, NULL)) ? 0 : 1;
1340 /* end of gnunet-service-vpn.c */