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
27 * @author Christian Grothoff
30 * - keep multiple peers/mesh tunnels ready as alternative exits /
31 * recover from tunnel-to-exit failure gracefully
34 #include "gnunet_util_lib.h"
35 #include "gnunet_common.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_applications.h"
38 #include "gnunet_mesh_service.h"
39 #include "gnunet_statistics_service.h"
40 #include "gnunet_constants.h"
41 #include "gnunet_tun_lib.h"
42 #include "gnunet_regex_service.h"
48 * Maximum number of messages we allow in the queue for mesh.
50 #define MAX_MESSAGE_QUEUE_SIZE 4
53 * Maximum regex string length for use with GNUNET_REGEX_ipv4toregex
55 #define GNUNET_REGEX_IPV4_REGEXLEN 32 + 6
58 * Maximum regex string length for use with GNUNET_REGEX_ipv6toregex
60 #define GNUNET_REGEX_IPV6_REGEXLEN 128 + 6
64 * State we keep for each of our tunnels.
70 * Information we track for each IP address to determine which tunnel
71 * to send the traffic over to the destination.
73 struct DestinationEntry
77 * Key under which this entry is in the 'destination_map' (only valid
78 * if 'heap_node != NULL').
80 struct GNUNET_HashCode key;
83 * Pre-allocated tunnel for this destination, or NULL for none.
85 struct TunnelState *ts;
88 * Entry for this entry in the destination_heap.
90 struct GNUNET_CONTAINER_HeapNode *heap_node;
93 * GNUNET_NO if this is a tunnel to an Internet-exit,
94 * GNUNET_YES if this tunnel is to a service.
99 * Details about the connection (depending on is_service).
107 * The description of the service (only used for service tunnels).
109 struct GNUNET_HashCode service_descriptor;
112 * Peer offering the service.
114 struct GNUNET_PeerIdentity target;
116 } service_destination;
122 * Address family used (AF_INET or AF_INET6).
127 * IP address of the ultimate destination (only used for exit tunnels).
132 * Address if af is AF_INET.
137 * Address if af is AF_INET6.
150 * A messages we have in queue for a particular tunnel.
152 struct TunnelMessageQueueEntry
155 * This is a doubly-linked list.
157 struct TunnelMessageQueueEntry *next;
160 * This is a doubly-linked list.
162 struct TunnelMessageQueueEntry *prev;
165 * Number of bytes in 'msg'.
170 * Message to transmit, allocated at the end of this struct.
177 * State we keep for each of our tunnels.
183 * Information about the tunnel to use, NULL if no tunnel
184 * is available right now.
186 struct GNUNET_MESH_Tunnel *tunnel;
189 * Active query with REGEX to locate exit.
191 struct GNUNET_REGEX_Search *search;
194 * Active transmission handle, NULL for none.
196 struct GNUNET_MESH_TransmitHandle *th;
199 * Entry for this entry in the tunnel_heap, NULL as long as this
200 * tunnel state is not fully bound.
202 struct GNUNET_CONTAINER_HeapNode *heap_node;
205 * Head of list of messages scheduled for transmission.
207 struct TunnelMessageQueueEntry *tmq_head;
210 * Tail of list of messages scheduled for transmission.
212 struct TunnelMessageQueueEntry *tmq_tail;
215 * Client that needs to be notified about the tunnel being
216 * up as soon as a peer is connected; NULL for none.
218 struct GNUNET_SERVER_Client *client;
221 * Destination entry that has a pointer to this tunnel state;
222 * NULL if this tunnel state is in the tunnel map.
224 struct DestinationEntry *destination_container;
227 * ID of the client request that caused us to setup this entry.
232 * Destination to which this tunnel leads. Note that
233 * this struct is NOT in the destination_map (but a
234 * local copy) and that the 'heap_node' should always
237 struct DestinationEntry destination;
240 * Task scheduled to destroy the tunnel (or NO_TASK).
242 GNUNET_SCHEDULER_TaskIdentifier destroy_task;
245 * Addess family used for this tunnel on the local TUN interface.
250 * Length of the doubly linked 'tmq_head/tmq_tail' list.
252 unsigned int tmq_length;
255 * IPPROTO_TCP or IPPROTO_UDP once bound.
260 * IP address of the source on our end, initially uninitialized.
265 * Address if af is AF_INET.
270 * Address if af is AF_INET6.
277 * Destination IP address used by the source on our end (this is the IP
278 * that we pick freely within the VPN's tunnel IP range).
283 * Address if af is AF_INET.
288 * Address if af is AF_INET6.
295 * Source port used by the sender on our end; 0 for uninitialized.
297 uint16_t source_port;
300 * Destination port used by the sender on our end; 0 for uninitialized.
302 uint16_t destination_port;
308 * Return value from 'main'.
310 static int global_ret;
313 * Configuration we use.
315 static const struct GNUNET_CONFIGURATION_Handle *cfg;
318 * Handle to the mesh service.
320 static struct GNUNET_MESH_Handle *mesh_handle;
323 * Map from IP address to destination information (possibly with a
324 * MESH tunnel handle for fast setup).
326 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
329 * Min-Heap sorted by activity time to expire old mappings.
331 static struct GNUNET_CONTAINER_Heap *destination_heap;
334 * Map from source and destination address (IP+port) to connection
335 * information (mostly with the respective MESH tunnel handle).
337 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
340 * Min-Heap sorted by activity time to expire old mappings; values are
341 * of type 'struct TunnelState'.
343 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
348 static struct GNUNET_STATISTICS_Handle *stats;
351 * The handle to the VPN helper process "gnunet-helper-vpn".
353 static struct GNUNET_HELPER_Handle *helper_handle;
356 * Arguments to the vpn helper.
358 static char *vpn_argv[7];
361 * Length of the prefix of the VPN's IPv6 network.
363 static unsigned long long ipv6prefix;
366 * Notification context for sending replies to clients.
368 static struct GNUNET_SERVER_NotificationContext *nc;
371 * If there are more than this number of address-mappings, old ones
374 static unsigned long long max_destination_mappings;
377 * If there are more than this number of open tunnels, old ones
380 static unsigned long long max_tunnel_mappings;
384 * Compute the key under which we would store an entry in the
385 * destination_map for the given IP address.
387 * @param af address family (AF_INET or AF_INET6)
388 * @param address IP address, struct in_addr or struct in6_addr
389 * @param key where to store the key
392 get_destination_key_from_ip (int af,
394 struct GNUNET_HashCode *key)
399 GNUNET_CRYPTO_hash (address,
400 sizeof (struct in_addr),
404 GNUNET_CRYPTO_hash (address,
405 sizeof (struct in6_addr),
416 * Compute the key under which we would store an entry in the
417 * tunnel_map for the given socket address pair.
419 * @param af address family (AF_INET or AF_INET6)
420 * @param protocol IPPROTO_TCP or IPPROTO_UDP
421 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
422 * @param source_port sender's source port
423 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
424 * @param destination_port sender's destination port
425 * @param key where to store the key
428 get_tunnel_key_from_ips (int af,
430 const void *source_ip,
431 uint16_t source_port,
432 const void *destination_ip,
433 uint16_t destination_port,
434 struct GNUNET_HashCode *key)
438 memset (key, 0, sizeof (struct GNUNET_HashCode));
439 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
440 so we put the ports in there (and hope for few collisions) */
442 memcpy (off, &source_port, sizeof (uint16_t));
443 off += sizeof (uint16_t);
444 memcpy (off, &destination_port, sizeof (uint16_t));
445 off += sizeof (uint16_t);
449 memcpy (off, source_ip, sizeof (struct in_addr));
450 off += sizeof (struct in_addr);
451 memcpy (off, destination_ip, sizeof (struct in_addr));
452 off += sizeof (struct in_addr);
455 memcpy (off, source_ip, sizeof (struct in6_addr));
456 off += sizeof (struct in6_addr);
457 memcpy (off, destination_ip, sizeof (struct in6_addr));
458 off += sizeof (struct in6_addr);
464 memcpy (off, &protocol, sizeof (uint8_t));
465 off += sizeof (uint8_t);
470 * Notify the client about the result of its request.
472 * @param client client to notify
473 * @param request_id original request ID to include in response
474 * @param result_af resulting address family
475 * @param addr resulting IP address
478 send_client_reply (struct GNUNET_SERVER_Client *client,
483 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN;
484 struct RedirectToIpResponseMessage *res;
490 rlen = sizeof (struct in_addr);
493 rlen = sizeof (struct in6_addr);
502 res = (struct RedirectToIpResponseMessage *) buf;
503 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
504 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
505 res->result_af = htonl (result_af);
506 res->request_id = request_id;
507 memcpy (&res[1], addr, rlen);
508 GNUNET_SERVER_notification_context_add (nc, client);
509 GNUNET_SERVER_notification_context_unicast (nc,
517 * Free resources associated with a tunnel state.
519 * @param ts state to free
522 free_tunnel_state (struct TunnelState *ts)
524 struct GNUNET_HashCode key;
525 struct TunnelMessageQueueEntry *tnq;
526 struct GNUNET_MESH_Tunnel *tunnel;
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Cleaning up tunnel state\n");
530 GNUNET_STATISTICS_update (stats,
531 gettext_noop ("# Active tunnels"),
533 while (NULL != (tnq = ts->tmq_head))
535 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
541 GNUNET_assert (0 == ts->tmq_length);
544 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
547 GNUNET_assert (NULL == ts->destination.heap_node);
548 if (NULL != (tunnel = ts->tunnel))
551 GNUNET_MESH_tunnel_destroy (tunnel);
553 if (NULL != ts->search)
555 GNUNET_REGEX_search_cancel (ts->search);
558 if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
560 GNUNET_SCHEDULER_cancel (ts->destroy_task);
561 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
563 if (NULL != ts->heap_node)
565 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
566 ts->heap_node = NULL;
567 get_tunnel_key_from_ips (ts->af,
572 ts->destination_port,
574 GNUNET_assert (GNUNET_YES ==
575 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
579 if (NULL != ts->destination_container)
581 GNUNET_assert (ts == ts->destination_container->ts);
582 ts->destination_container->ts = NULL;
583 ts->destination_container = NULL;
590 * Destroy the mesh tunnel.
592 * @param cls the 'struct TunnelState' with the tunnel to destroy
593 * @param tc scheduler context
596 destroy_tunnel_task (void *cls,
597 const struct GNUNET_SCHEDULER_TaskContext *tc)
599 struct TunnelState *ts = cls;
600 struct GNUNET_MESH_Tunnel *tunnel;
602 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
603 GNUNET_assert (NULL != ts->tunnel);
606 GNUNET_MESH_tunnel_destroy (tunnel);
607 free_tunnel_state (ts);
612 * Method called whenever a peer has disconnected from the tunnel.
615 * @param peer peer identity the tunnel stopped working with
618 tunnel_peer_disconnect_handler (void *cls,
620 GNUNET_PeerIdentity * peer)
622 struct TunnelState *ts = cls;
624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
625 "Peer %s disconnected from tunnel.\n",
627 GNUNET_STATISTICS_update (stats,
628 gettext_noop ("# peers connected to mesh tunnels"),
632 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
635 if (ts->destination.is_service)
636 return; /* hope for reconnect eventually */
637 /* as we are most likely going to change the exit node now,
638 we should just destroy the tunnel entirely... */
639 if (GNUNET_SCHEDULER_NO_TASK == ts->destroy_task)
640 ts->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_tunnel_task, ts);
645 * Method called whenever a peer has connected to the tunnel. Notifies
646 * the waiting client that the tunnel is now up.
649 * @param peer peer identity the tunnel was created to, NULL on timeout
650 * @param atsi performance data for the connection
653 tunnel_peer_connect_handler (void *cls,
654 const struct GNUNET_PeerIdentity
657 GNUNET_ATS_Information * atsi)
659 struct TunnelState *ts = cls;
661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662 "Peer %s connected to tunnel.\n",
664 GNUNET_STATISTICS_update (stats,
665 gettext_noop ("# peers connected to mesh tunnels"),
667 if (NULL == ts->client)
668 return; /* nothing to do */
669 send_client_reply (ts->client,
672 &ts->destination_ip);
678 * Send a message from the message queue via mesh.
680 * @param cls the 'struct TunnelState' with the message queue
681 * @param size number of bytes available in buf
682 * @param buf where to copy the message
683 * @return number of bytes copied to buf
686 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
688 struct TunnelState *ts = cls;
689 struct TunnelMessageQueueEntry *tnq;
696 GNUNET_assert (NULL != tnq);
697 GNUNET_assert (size >= tnq->len);
698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
699 "Sending %u bytes via mesh tunnel\n",
701 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
705 memcpy (buf, tnq->msg, tnq->len);
708 if (NULL != (tnq = ts->tmq_head))
709 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
710 GNUNET_NO /* cork */,
711 GNUNET_TIME_UNIT_FOREVER_REL,
714 &send_to_peer_notify_callback,
716 GNUNET_STATISTICS_update (stats,
717 gettext_noop ("# Bytes given to mesh for transmission"),
724 * Add the given message to the given tunnel and trigger the
725 * transmission process.
727 * @param tnq message to queue
728 * @param ts tunnel to queue the message for
731 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
732 struct TunnelState *ts)
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735 "Queueing %u bytes for transmission via mesh tunnel\n",
737 GNUNET_assert (NULL != ts->tunnel);
738 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
742 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
744 struct TunnelMessageQueueEntry *dq;
747 GNUNET_assert (dq != tnq);
748 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
752 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
754 GNUNET_STATISTICS_update (stats,
755 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
761 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
762 GNUNET_NO /* cork */,
763 GNUNET_TIME_UNIT_FOREVER_REL,
766 &send_to_peer_notify_callback,
772 * Create a string with binary IP notation for the given 'addr' in 'str'.
774 * @param af address family of the given 'addr'.
775 * @param addr address that should be converted to a string.
776 * struct in_addr * for IPv4 and struct in6_addr * for IPv6.
777 * @param str string that will contain binary notation of 'addr'. Expected
778 * to be at least 33 bytes long for IPv4 and 129 bytes long for IPv6.
781 iptobinstr (const int af, const void *addr, char *str)
789 uint32_t b = htonl (((struct in_addr *) addr)->s_addr);
793 for (i = 31; i >= 0; i--)
795 *str = (b & 1) + '0';
803 struct in6_addr b = *(const struct in6_addr *) addr;
807 for (i = 127; i >= 0; i--)
809 *str = (b.s6_addr[i / 8] & 1) + '0';
811 b.s6_addr[i / 8] >>= 1;
820 * Get the ipv4 network prefix from the given 'netmask'.
822 * @param netmask netmask for which to get the prefix len.
824 * @return length of ipv4 prefix for 'netmask'.
827 ipv4netmasktoprefixlen (const char *netmask)
833 if (1 != inet_pton (AF_INET, netmask, &a))
836 for (t = htonl (~a.s_addr); 0 != t; t >>= 1)
843 * Create a regex in 'rxstr' from the given 'ip' and 'netmask'.
845 * @param ip IPv4 representation.
846 * @param netmask netmask for the ip.
847 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV4_REGEXLEN
851 ipv4toregex (const struct in_addr *ip, const char *netmask,
856 pfxlen = ipv4netmasktoprefixlen (netmask);
857 iptobinstr (AF_INET, ip, rxstr);
858 rxstr[pfxlen] = '\0';
860 strcat (rxstr, "(0|1)+");
865 * Create a regex in 'rxstr' from the given 'ipv6' and 'prefixlen'.
867 * @param ipv6 IPv6 representation.
868 * @param prefixlen length of the ipv6 prefix.
869 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV6_REGEXLEN
873 ipv6toregex (const struct in6_addr *ipv6, unsigned int prefixlen,
876 iptobinstr (AF_INET6, ipv6, rxstr);
877 rxstr[prefixlen] = '\0';
879 strcat (rxstr, "(0|1)+");
884 * Regex has found a potential exit peer for us; consider using it.
886 * @param cls the 'struct TunnelState'
887 * @param id Peer providing a regex that matches the string.
888 * @param get_path Path of the get request.
889 * @param get_path_length Lenght of get_path.
890 * @param put_path Path of the put request.
891 * @param put_path_length Length of the put_path.
894 handle_regex_result (void *cls,
895 const struct GNUNET_PeerIdentity *id,
896 const struct GNUNET_PeerIdentity *get_path,
897 unsigned int get_path_length,
898 const struct GNUNET_PeerIdentity *put_path,
899 unsigned int put_path_length)
901 struct TunnelState *ts = cls;
903 GNUNET_REGEX_search_cancel (ts->search);
905 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
907 &tunnel_peer_connect_handler,
908 &tunnel_peer_disconnect_handler,
910 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
916 * Initialize the given destination entry's mesh tunnel.
918 * @param de destination entry for which we need to setup a tunnel
919 * @param client client to notify on successful tunnel setup, or NULL for none
920 * @param client_af address family of the address returned to the client
921 * @param request_id request ID to send in client notification (unused if client is NULL)
922 * @return tunnel state of the tunnel that was created
924 static struct TunnelState *
925 create_tunnel_to_destination (struct DestinationEntry *de,
926 struct GNUNET_SERVER_Client *client,
930 struct TunnelState *ts;
932 GNUNET_STATISTICS_update (stats,
933 gettext_noop ("# Mesh tunnels created"),
935 GNUNET_assert (NULL == de->ts);
936 ts = GNUNET_malloc (sizeof (struct TunnelState));
940 ts->request_id = request_id;
943 ts->destination = *de;
944 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
946 ts->destination_container = de; /* we are referenced from de */
949 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
951 &tunnel_peer_connect_handler,
952 &tunnel_peer_disconnect_handler,
954 if (NULL == ts->tunnel)
956 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
957 _("Failed to setup mesh tunnel!\n"));
961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
962 "Creating tunnel to peer %s offering service %s\n",
963 GNUNET_i2s (&de->details.service_destination.target),
964 GNUNET_h2s (&de->details.service_destination.service_descriptor));
965 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
966 &de->details.service_destination.target);
972 switch (de->details.exit_destination.af)
976 char address[GNUNET_REGEX_IPV4_REGEXLEN];
978 ipv4toregex (&de->details.exit_destination.ip.v4,
979 "255.255.255.255", address);
980 GNUNET_asprintf (&policy, "%s%s%s",
981 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
988 char address[GNUNET_REGEX_IPV6_REGEXLEN];
990 ipv6toregex (&de->details.exit_destination.ip.v6,
992 GNUNET_asprintf (&policy, "%s%s%s",
993 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1004 "Requesting connect by string: %s\n",
1006 ts->search = GNUNET_REGEX_search (cfg,
1008 &handle_regex_result,
1010 GNUNET_free (policy);
1017 * We have too many active tunnels. Clean up the oldest tunnel.
1019 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
1022 expire_tunnel (struct TunnelState *except)
1024 struct TunnelState *ts;
1026 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
1027 GNUNET_assert (NULL != ts);
1029 return; /* can't do this */
1030 free_tunnel_state (ts);
1035 * Route a packet via mesh to the given destination.
1037 * @param destination description of the destination
1038 * @param af address family on this end (AF_INET or AF_INET6)
1039 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
1040 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
1041 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
1042 * @param payload payload of the packet after the IP header
1043 * @param payload_length number of bytes in payload
1046 route_packet (struct DestinationEntry *destination,
1049 const void *source_ip,
1050 const void *destination_ip,
1051 const void *payload,
1052 size_t payload_length)
1054 struct GNUNET_HashCode key;
1055 struct TunnelState *ts;
1056 struct TunnelMessageQueueEntry *tnq;
1060 const struct GNUNET_TUN_UdpHeader *udp;
1061 const struct GNUNET_TUN_TcpHeader *tcp;
1062 const struct GNUNET_TUN_IcmpHeader *icmp;
1063 uint16_t source_port;
1064 uint16_t destination_port;
1070 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1076 tcp = NULL; /* make compiler happy */
1077 icmp = NULL; /* make compiler happy */
1079 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1081 GNUNET_break_op (0);
1084 source_port = ntohs (udp->source_port);
1085 destination_port = ntohs (udp->destination_port);
1086 get_tunnel_key_from_ips (af,
1097 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1103 udp = NULL; /* make compiler happy */
1104 icmp = NULL; /* make compiler happy */
1106 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1108 GNUNET_break_op (0);
1111 source_port = ntohs (tcp->source_port);
1112 destination_port = ntohs (tcp->destination_port);
1113 get_tunnel_key_from_ips (af,
1123 case IPPROTO_ICMPV6:
1125 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1130 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1136 tcp = NULL; /* make compiler happy */
1137 udp = NULL; /* make compiler happy */
1140 destination_port = 0;
1141 get_tunnel_key_from_ips (af,
1151 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1152 _("Protocol %u not supported, dropping\n"),
1153 (unsigned int) protocol);
1156 if (! destination->is_service)
1158 switch (destination->details.exit_destination.af)
1161 alen = sizeof (struct in_addr);
1164 alen = sizeof (struct in6_addr);
1172 char sbuf[INET6_ADDRSTRLEN];
1173 char dbuf[INET6_ADDRSTRLEN];
1174 char xbuf[INET6_ADDRSTRLEN];
1176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1177 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1178 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1179 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1181 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1183 inet_ntop (destination->details.exit_destination.af,
1184 &destination->details.exit_destination.ip,
1185 xbuf, sizeof (xbuf)),
1191 /* make compiler happy */
1194 char sbuf[INET6_ADDRSTRLEN];
1195 char dbuf[INET6_ADDRSTRLEN];
1197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1198 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1199 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1200 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1202 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1204 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1205 GNUNET_i2s (&destination->details.service_destination.target));
1210 /* see if we have an existing tunnel for this destination */
1211 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
1215 /* need to either use the existing tunnel from the destination (if still
1216 available) or create a fresh one */
1217 is_new = GNUNET_YES;
1218 if (NULL == destination->ts)
1219 ts = create_tunnel_to_destination (destination, NULL, af, 0);
1221 ts = destination->ts;
1224 destination->ts = NULL;
1225 ts->destination_container = NULL; /* no longer 'contained' */
1226 /* now bind existing "unbound" tunnel to our IP/port tuple */
1227 ts->protocol = protocol;
1231 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1232 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1236 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1237 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1239 ts->source_port = source_port;
1240 ts->destination_port = destination_port;
1241 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1243 GNUNET_TIME_absolute_get ().abs_value);
1244 GNUNET_assert (GNUNET_YES ==
1245 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1248 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1249 GNUNET_STATISTICS_update (stats,
1250 gettext_noop ("# Active tunnels"),
1252 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1258 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1260 GNUNET_TIME_absolute_get ().abs_value);
1262 GNUNET_assert (NULL != ts->tunnel);
1264 /* send via tunnel */
1268 if (destination->is_service)
1270 struct GNUNET_EXIT_UdpServiceMessage *usm;
1272 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1273 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1274 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1279 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1282 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1283 usm->header.size = htons ((uint16_t) mlen);
1284 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1285 /* if the source port is below 32000, we assume it has a special
1286 meaning; if not, we pick a random port (this is a heuristic) */
1287 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1288 usm->destination_port = udp->destination_port;
1289 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1292 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1296 struct GNUNET_EXIT_UdpInternetMessage *uim;
1297 struct in_addr *ip4dst;
1298 struct in6_addr *ip6dst;
1301 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1302 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1303 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1308 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1312 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1313 uim->header.size = htons ((uint16_t) mlen);
1314 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1315 uim->af = htonl (destination->details.exit_destination.af);
1316 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1317 uim->destination_port = udp->destination_port;
1318 switch (destination->details.exit_destination.af)
1321 ip4dst = (struct in_addr *) &uim[1];
1322 *ip4dst = destination->details.exit_destination.ip.v4;
1323 payload = &ip4dst[1];
1326 ip6dst = (struct in6_addr *) &uim[1];
1327 *ip6dst = destination->details.exit_destination.ip.v6;
1328 payload = &ip6dst[1];
1335 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1341 if (destination->is_service)
1343 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1345 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1346 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1347 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1352 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1355 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1356 tsm->header.size = htons ((uint16_t) mlen);
1357 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1358 tsm->reserved = htonl (0);
1359 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1360 tsm->tcp_header = *tcp;
1363 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1367 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1368 struct in_addr *ip4dst;
1369 struct in6_addr *ip6dst;
1372 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1373 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1374 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1379 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1382 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1383 tim->header.size = htons ((uint16_t) mlen);
1384 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1385 tim->af = htonl (destination->details.exit_destination.af);
1386 tim->tcp_header = *tcp;
1387 switch (destination->details.exit_destination.af)
1390 ip4dst = (struct in_addr *) &tim[1];
1391 *ip4dst = destination->details.exit_destination.ip.v4;
1392 payload = &ip4dst[1];
1395 ip6dst = (struct in6_addr *) &tim[1];
1396 *ip6dst = destination->details.exit_destination.ip.v6;
1397 payload = &ip6dst[1];
1404 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1409 struct GNUNET_EXIT_TcpDataMessage *tdm;
1411 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1412 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1413 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1418 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1421 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1422 tdm->header.size = htons ((uint16_t) mlen);
1423 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1424 tdm->reserved = htonl (0);
1425 tdm->tcp_header = *tcp;
1428 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1432 case IPPROTO_ICMPV6:
1433 if (destination->is_service)
1435 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1437 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1438 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1439 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1444 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1446 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1447 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1448 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1449 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1450 ism->icmp_header = *icmp;
1451 /* ICMP protocol translation will be done by the receiver (as we don't know
1452 the target AF); however, we still need to possibly discard the payload
1453 depending on the ICMP type */
1459 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1460 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1462 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1463 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1464 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1465 /* throw away ICMP payload, won't be useful for the other side anyway */
1466 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1469 GNUNET_STATISTICS_update (stats,
1470 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1474 /* end of AF_INET */
1479 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1480 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1481 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1482 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1483 /* throw away ICMP payload, won't be useful for the other side anyway */
1484 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1486 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1487 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1490 GNUNET_STATISTICS_update (stats,
1491 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1495 /* end of AF_INET6 */
1502 /* update length calculations, as payload_length may have changed */
1503 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1504 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1506 ism->header.size = htons ((uint16_t) mlen);
1507 /* finally, copy payload (if there is any left...) */
1510 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1514 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1515 struct in_addr *ip4dst;
1516 struct in6_addr *ip6dst;
1519 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1520 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1521 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1526 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1529 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1530 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1531 iim->icmp_header = *icmp;
1532 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1533 and throw away ICMP payload depending on ICMP message type */
1539 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1540 if (destination->details.exit_destination.af == AF_INET6)
1541 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1543 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1544 if (destination->details.exit_destination.af == AF_INET6)
1545 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1547 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1548 if (destination->details.exit_destination.af == AF_INET6)
1549 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1550 /* throw away IP-payload, exit will have to make it up anyway */
1551 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1553 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1554 if (destination->details.exit_destination.af == AF_INET6)
1555 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1556 /* throw away IP-payload, exit will have to make it up anyway */
1557 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1559 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1560 if (destination->details.exit_destination.af == AF_INET6)
1562 GNUNET_STATISTICS_update (stats,
1563 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1568 /* throw away IP-payload, exit will have to make it up anyway */
1569 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1572 GNUNET_STATISTICS_update (stats,
1573 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1578 /* end of AF_INET */
1583 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1584 if (destination->details.exit_destination.af == AF_INET6)
1585 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1586 /* throw away IP-payload, exit will have to make it up anyway */
1587 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1589 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1590 if (destination->details.exit_destination.af == AF_INET)
1591 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1592 /* throw away IP-payload, exit will have to make it up anyway */
1593 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1595 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1596 if (destination->details.exit_destination.af == AF_INET)
1598 GNUNET_STATISTICS_update (stats,
1599 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1604 /* throw away IP-payload, exit will have to make it up anyway */
1605 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1607 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1608 if (destination->details.exit_destination.af == AF_INET)
1610 GNUNET_STATISTICS_update (stats,
1611 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1616 /* throw away IP-payload, exit will have to make it up anyway */
1617 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1619 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1620 if (destination->details.exit_destination.af == AF_INET)
1621 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1623 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1624 if (destination->details.exit_destination.af == AF_INET)
1625 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1628 GNUNET_STATISTICS_update (stats,
1629 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1634 /* end of AF_INET6 */
1639 /* update length calculations, as payload_length may have changed */
1640 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1641 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1643 iim->header.size = htons ((uint16_t) mlen);
1645 /* need to tell destination ICMP protocol family! */
1646 iim->af = htonl (destination->details.exit_destination.af);
1647 switch (destination->details.exit_destination.af)
1650 ip4dst = (struct in_addr *) &iim[1];
1651 *ip4dst = destination->details.exit_destination.ip.v4;
1652 payload = &ip4dst[1];
1655 ip6dst = (struct in6_addr *) &iim[1];
1656 *ip6dst = destination->details.exit_destination.ip.v6;
1657 payload = &ip6dst[1];
1664 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1668 /* not supported above, how can we get here !? */
1672 send_to_tunnel (tnq, ts);
1677 * Receive packets from the helper-process (someone send to the local
1678 * virtual tunnel interface). Find the destination mapping, and if it
1679 * exists, identify the correct MESH tunnel (or possibly create it)
1680 * and forward the packet.
1682 * @param cls closure, NULL
1683 * @param client NULL
1684 * @param message message we got from the client (VPN tunnel interface)
1687 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1688 const struct GNUNET_MessageHeader *message)
1690 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1692 struct GNUNET_HashCode key;
1693 struct DestinationEntry *de;
1695 GNUNET_STATISTICS_update (stats,
1696 gettext_noop ("# Packets received from TUN interface"),
1698 mlen = ntohs (message->size);
1699 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1700 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1705 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1706 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1707 switch (ntohs (tun->proto))
1711 const struct GNUNET_TUN_IPv6Header *pkt6;
1713 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1719 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1720 get_destination_key_from_ip (AF_INET6,
1721 &pkt6->destination_address,
1723 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1724 /* FIXME: do we need to guard against hash collision?
1725 (if so, we need to also store the local destination IP in the
1726 destination entry and then compare here; however, the risk
1727 of collision seems minimal AND the impact is unlikely to be
1728 super-problematic as well... */
1731 char buf[INET6_ADDRSTRLEN];
1733 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1734 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1735 inet_ntop (AF_INET6,
1736 &pkt6->destination_address,
1744 &pkt6->source_address,
1745 &pkt6->destination_address,
1747 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1752 struct GNUNET_TUN_IPv4Header *pkt4;
1754 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1760 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1761 get_destination_key_from_ip (AF_INET,
1762 &pkt4->destination_address,
1764 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1765 /* FIXME: do we need to guard against hash collision?
1766 (if so, we need to also store the local destination IP in the
1767 destination entry and then compare here; however, the risk
1768 of collision seems minimal AND the impact is unlikely to be
1769 super-problematic as well... */
1772 char buf[INET_ADDRSTRLEN];
1774 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1775 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1777 &pkt4->destination_address,
1782 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1784 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1785 _("Received IPv4 packet with options (dropping it)\n"));
1791 &pkt4->source_address,
1792 &pkt4->destination_address,
1794 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1798 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1799 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1800 (unsigned int) ntohs (tun->proto));
1808 * Synthesize a plausible ICMP payload for an ICMP error
1809 * response on the given tunnel.
1811 * @param ts tunnel information
1812 * @param ipp IPv4 header to fill in (ICMP payload)
1813 * @param udp "UDP" header to fill in (ICMP payload); might actually
1814 * also be the first 8 bytes of the TCP header
1817 make_up_icmpv4_payload (struct TunnelState *ts,
1818 struct GNUNET_TUN_IPv4Header *ipp,
1819 struct GNUNET_TUN_UdpHeader *udp)
1821 GNUNET_TUN_initialize_ipv4_header (ipp,
1823 sizeof (struct GNUNET_TUN_TcpHeader),
1825 &ts->destination_ip.v4);
1826 udp->source_port = htons (ts->source_port);
1827 udp->destination_port = htons (ts->destination_port);
1828 udp->len = htons (0);
1829 udp->crc = htons (0);
1834 * Synthesize a plausible ICMP payload for an ICMP error
1835 * response on the given tunnel.
1837 * @param ts tunnel information
1838 * @param ipp IPv6 header to fill in (ICMP payload)
1839 * @param udp "UDP" header to fill in (ICMP payload); might actually
1840 * also be the first 8 bytes of the TCP header
1843 make_up_icmpv6_payload (struct TunnelState *ts,
1844 struct GNUNET_TUN_IPv6Header *ipp,
1845 struct GNUNET_TUN_UdpHeader *udp)
1847 GNUNET_TUN_initialize_ipv6_header (ipp,
1849 sizeof (struct GNUNET_TUN_TcpHeader),
1851 &ts->destination_ip.v6);
1852 udp->source_port = htons (ts->source_port);
1853 udp->destination_port = htons (ts->destination_port);
1854 udp->len = htons (0);
1855 udp->crc = htons (0);
1860 * We got an ICMP packet back from the MESH tunnel. Pass it on to the
1861 * local virtual interface via the helper.
1863 * @param cls closure, NULL
1864 * @param tunnel connection to the other end
1865 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1866 * @param sender who sent the message
1867 * @param message the actual message
1868 * @param atsi performance data for the connection
1869 * @return GNUNET_OK to keep the connection open,
1870 * GNUNET_SYSERR to close it (signal serious error)
1873 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1874 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1875 const struct GNUNET_MessageHeader *message,
1876 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1878 struct TunnelState *ts = *tunnel_ctx;
1879 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1882 GNUNET_STATISTICS_update (stats,
1883 gettext_noop ("# ICMP packets received from mesh"),
1885 mlen = ntohs (message->size);
1886 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1888 GNUNET_break_op (0);
1889 return GNUNET_SYSERR;
1891 if (NULL == ts->heap_node)
1893 GNUNET_break_op (0);
1894 return GNUNET_SYSERR;
1896 if (AF_UNSPEC == ts->af)
1898 GNUNET_break_op (0);
1899 return GNUNET_SYSERR;
1901 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1902 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1904 char sbuf[INET6_ADDRSTRLEN];
1905 char dbuf[INET6_ADDRSTRLEN];
1907 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1908 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1909 (unsigned int) mlen,
1910 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1911 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1917 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1918 + sizeof (struct GNUNET_TUN_IcmpHeader)
1919 + sizeof (struct GNUNET_MessageHeader) +
1920 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1923 /* reserve some extra space in case we have an ICMP type here where
1924 we will need to make up the payload ourselves */
1925 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1926 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1927 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1928 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1929 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1930 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1931 tun->flags = htons (0);
1932 tun->proto = htons (ETH_P_IPV4);
1933 GNUNET_TUN_initialize_ipv4_header (ipv4,
1935 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1936 &ts->destination_ip.v4,
1938 *icmp = i2v->icmp_header;
1942 /* For some ICMP types, we need to adjust (make up) the payload here.
1943 Also, depending on the AF used on the other side, we have to
1944 do ICMP PT (translate ICMP types) */
1945 switch (ntohl (i2v->af))
1950 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1951 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1953 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1954 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1955 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1957 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1958 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1962 /* sender did not strip ICMP payload? */
1963 GNUNET_break_op (0);
1964 return GNUNET_SYSERR;
1966 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1967 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1968 make_up_icmpv4_payload (ts, ipp, udp);
1972 GNUNET_break_op (0);
1973 GNUNET_STATISTICS_update (stats,
1974 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1976 return GNUNET_SYSERR;
1981 /* ICMP PT 6-to-4 and possibly making up payloads */
1984 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1985 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1987 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1988 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1992 /* sender did not strip ICMP payload? */
1993 GNUNET_break_op (0);
1994 return GNUNET_SYSERR;
1996 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1997 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1998 make_up_icmpv4_payload (ts, ipp, udp);
2001 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2002 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2004 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
2005 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2009 /* sender did not strip ICMP payload? */
2010 GNUNET_break_op (0);
2011 return GNUNET_SYSERR;
2013 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2014 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2015 make_up_icmpv4_payload (ts, ipp, udp);
2018 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2019 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2020 GNUNET_STATISTICS_update (stats,
2021 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2024 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2025 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2027 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2028 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2031 GNUNET_break_op (0);
2032 GNUNET_STATISTICS_update (stats,
2033 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2035 return GNUNET_SYSERR;
2040 GNUNET_break_op (0);
2041 return GNUNET_SYSERR;
2043 msg->size = htons (size);
2044 GNUNET_TUN_calculate_icmp_checksum (icmp,
2047 (void) GNUNET_HELPER_send (helper_handle,
2056 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2057 + sizeof (struct GNUNET_TUN_IcmpHeader)
2058 + sizeof (struct GNUNET_MessageHeader) +
2059 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2062 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2063 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2064 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2065 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2066 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
2067 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2068 tun->flags = htons (0);
2069 tun->proto = htons (ETH_P_IPV6);
2070 GNUNET_TUN_initialize_ipv6_header (ipv6,
2072 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
2073 &ts->destination_ip.v6,
2075 *icmp = i2v->icmp_header;
2080 /* For some ICMP types, we need to adjust (make up) the payload here.
2081 Also, depending on the AF used on the other side, we have to
2082 do ICMP PT (translate ICMP types) */
2083 switch (ntohl (i2v->af))
2086 /* ICMP PT 4-to-6 and possibly making up payloads */
2089 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2090 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2092 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2093 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2095 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2096 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2098 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2099 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2103 /* sender did not strip ICMP payload? */
2104 GNUNET_break_op (0);
2105 return GNUNET_SYSERR;
2107 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2108 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2109 make_up_icmpv6_payload (ts, ipp, udp);
2112 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2113 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2115 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2116 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2120 /* sender did not strip ICMP payload? */
2121 GNUNET_break_op (0);
2122 return GNUNET_SYSERR;
2124 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2125 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2126 make_up_icmpv6_payload (ts, ipp, udp);
2129 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2130 GNUNET_STATISTICS_update (stats,
2131 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2135 GNUNET_break_op (0);
2136 GNUNET_STATISTICS_update (stats,
2137 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2139 return GNUNET_SYSERR;
2146 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2147 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2148 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2149 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2151 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2152 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2156 /* sender did not strip ICMP payload? */
2157 GNUNET_break_op (0);
2158 return GNUNET_SYSERR;
2160 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2161 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2162 make_up_icmpv6_payload (ts, ipp, udp);
2165 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2168 GNUNET_break_op (0);
2169 GNUNET_STATISTICS_update (stats,
2170 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2172 return GNUNET_SYSERR;
2177 GNUNET_break_op (0);
2178 return GNUNET_SYSERR;
2180 msg->size = htons (size);
2181 GNUNET_TUN_calculate_icmp_checksum (icmp,
2183 (void) GNUNET_HELPER_send (helper_handle,
2193 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2195 GNUNET_TIME_absolute_get ().abs_value);
2201 * We got a UDP packet back from the MESH tunnel. Pass it on to the
2202 * local virtual interface via the helper.
2204 * @param cls closure, NULL
2205 * @param tunnel connection to the other end
2206 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2207 * @param sender who sent the message
2208 * @param message the actual message
2209 * @param atsi performance data for the connection
2210 * @return GNUNET_OK to keep the connection open,
2211 * GNUNET_SYSERR to close it (signal serious error)
2214 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2215 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
2216 const struct GNUNET_MessageHeader *message,
2217 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2219 struct TunnelState *ts = *tunnel_ctx;
2220 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2223 GNUNET_STATISTICS_update (stats,
2224 gettext_noop ("# UDP packets received from mesh"),
2226 mlen = ntohs (message->size);
2227 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2229 GNUNET_break_op (0);
2230 return GNUNET_SYSERR;
2232 if (NULL == ts->heap_node)
2234 GNUNET_break_op (0);
2235 return GNUNET_SYSERR;
2237 if (AF_UNSPEC == ts->af)
2239 GNUNET_break_op (0);
2240 return GNUNET_SYSERR;
2242 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2243 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2245 char sbuf[INET6_ADDRSTRLEN];
2246 char dbuf[INET6_ADDRSTRLEN];
2248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2249 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2250 (unsigned int) mlen,
2251 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2252 ts->destination_port,
2253 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2260 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2261 + sizeof (struct GNUNET_TUN_UdpHeader)
2262 + sizeof (struct GNUNET_MessageHeader) +
2263 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2266 char buf[size] GNUNET_ALIGN;
2267 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2268 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2269 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2270 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2271 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2272 msg->size = htons (size);
2273 tun->flags = htons (0);
2274 tun->proto = htons (ETH_P_IPV4);
2275 GNUNET_TUN_initialize_ipv4_header (ipv4,
2277 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2278 &ts->destination_ip.v4,
2280 if (0 == ntohs (reply->source_port))
2281 udp->source_port = htons (ts->destination_port);
2283 udp->source_port = reply->source_port;
2284 if (0 == ntohs (reply->destination_port))
2285 udp->destination_port = htons (ts->source_port);
2287 udp->destination_port = reply->destination_port;
2288 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2289 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2296 (void) GNUNET_HELPER_send (helper_handle,
2305 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2306 + sizeof (struct GNUNET_TUN_UdpHeader)
2307 + sizeof (struct GNUNET_MessageHeader) +
2308 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2311 char buf[size] GNUNET_ALIGN;
2312 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2313 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2314 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2315 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2316 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2317 msg->size = htons (size);
2318 tun->flags = htons (0);
2319 tun->proto = htons (ETH_P_IPV6);
2320 GNUNET_TUN_initialize_ipv6_header (ipv6,
2322 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2323 &ts->destination_ip.v6,
2325 if (0 == ntohs (reply->source_port))
2326 udp->source_port = htons (ts->destination_port);
2328 udp->source_port = reply->source_port;
2329 if (0 == ntohs (reply->destination_port))
2330 udp->destination_port = htons (ts->source_port);
2332 udp->destination_port = reply->destination_port;
2333 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2334 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2340 (void) GNUNET_HELPER_send (helper_handle,
2350 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2352 GNUNET_TIME_absolute_get ().abs_value);
2358 * We got a TCP packet back from the MESH tunnel. Pass it on to the
2359 * local virtual interface via the helper.
2361 * @param cls closure, NULL
2362 * @param tunnel connection to the other end
2363 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2364 * @param sender who sent the message
2365 * @param message the actual message
2366 * @param atsi performance data for the connection
2367 * @return GNUNET_OK to keep the connection open,
2368 * GNUNET_SYSERR to close it (signal serious error)
2371 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2373 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2374 const struct GNUNET_MessageHeader *message,
2375 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2377 struct TunnelState *ts = *tunnel_ctx;
2378 const struct GNUNET_EXIT_TcpDataMessage *data;
2381 GNUNET_STATISTICS_update (stats,
2382 gettext_noop ("# TCP packets received from mesh"),
2384 mlen = ntohs (message->size);
2385 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2387 GNUNET_break_op (0);
2388 return GNUNET_SYSERR;
2390 if (NULL == ts->heap_node)
2392 GNUNET_break_op (0);
2393 return GNUNET_SYSERR;
2395 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2396 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2398 char sbuf[INET6_ADDRSTRLEN];
2399 char dbuf[INET6_ADDRSTRLEN];
2401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2402 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2403 (unsigned int) mlen,
2404 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2405 ts->destination_port,
2406 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2409 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2411 GNUNET_break_op (0);
2412 return GNUNET_SYSERR;
2418 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2419 + sizeof (struct GNUNET_TUN_TcpHeader)
2420 + sizeof (struct GNUNET_MessageHeader) +
2421 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2424 char buf[size] GNUNET_ALIGN;
2425 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2426 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2427 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2428 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2429 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2430 msg->size = htons (size);
2431 tun->flags = htons (0);
2432 tun->proto = htons (ETH_P_IPV4);
2433 GNUNET_TUN_initialize_ipv4_header (ipv4,
2435 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2436 &ts->destination_ip.v4,
2438 *tcp = data->tcp_header;
2439 tcp->source_port = htons (ts->destination_port);
2440 tcp->destination_port = htons (ts->source_port);
2441 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2448 (void) GNUNET_HELPER_send (helper_handle,
2457 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2458 + sizeof (struct GNUNET_TUN_TcpHeader)
2459 + sizeof (struct GNUNET_MessageHeader) +
2460 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2463 char buf[size] GNUNET_ALIGN;
2464 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2465 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2466 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2467 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2468 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2469 msg->size = htons (size);
2470 tun->flags = htons (0);
2471 tun->proto = htons (ETH_P_IPV6);
2472 GNUNET_TUN_initialize_ipv6_header (ipv6,
2474 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2475 &ts->destination_ip.v6,
2477 *tcp = data->tcp_header;
2478 tcp->source_port = htons (ts->destination_port);
2479 tcp->destination_port = htons (ts->source_port);
2480 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2487 (void) GNUNET_HELPER_send (helper_handle,
2495 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2497 GNUNET_TIME_absolute_get ().abs_value);
2503 * Allocate an IPv4 address from the range of the tunnel
2504 * for a new redirection.
2506 * @param v4 where to store the address
2507 * @return GNUNET_OK on success,
2508 * GNUNET_SYSERR on error
2511 allocate_v4_address (struct in_addr *v4)
2513 const char *ipv4addr = vpn_argv[4];
2514 const char *ipv4mask = vpn_argv[5];
2515 struct in_addr addr;
2516 struct in_addr mask;
2518 struct GNUNET_HashCode key;
2521 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2522 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2523 /* Given 192.168.0.1/255.255.0.0, we want a mask
2524 of '192.168.255.255', thus: */
2525 mask.s_addr = addr.s_addr | ~mask.s_addr;
2532 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2533 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2534 return GNUNET_SYSERR;
2536 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2537 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2539 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2540 get_destination_key_from_ip (AF_INET,
2544 while ( (GNUNET_YES ==
2545 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2547 (v4->s_addr == addr.s_addr) ||
2548 (v4->s_addr == mask.s_addr) );
2554 * Allocate an IPv6 address from the range of the tunnel
2555 * for a new redirection.
2557 * @param v6 where to store the address
2558 * @return GNUNET_OK on success,
2559 * GNUNET_SYSERR on error
2562 allocate_v6_address (struct in6_addr *v6)
2564 const char *ipv6addr = vpn_argv[2];
2565 struct in6_addr addr;
2566 struct in6_addr mask;
2567 struct in6_addr rnd;
2569 struct GNUNET_HashCode key;
2572 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2573 GNUNET_assert (ipv6prefix < 128);
2574 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2577 for (i=127;i>=ipv6prefix;i--)
2578 mask.s6_addr[i / 8] |= (1 << (i % 8));
2580 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2587 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2588 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2589 return GNUNET_SYSERR;
2594 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2597 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2599 get_destination_key_from_ip (AF_INET6,
2603 while ( (GNUNET_YES ==
2604 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2608 sizeof (struct in6_addr))) ||
2611 sizeof (struct in6_addr))) );
2617 * Free resources occupied by a destination entry.
2619 * @param de entry to free
2622 free_destination_entry (struct DestinationEntry *de)
2624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2625 "Cleaning up destination entry\n");
2626 GNUNET_STATISTICS_update (stats,
2627 gettext_noop ("# Active destinations"),
2631 free_tunnel_state (de->ts);
2632 GNUNET_assert (NULL == de->ts);
2634 if (NULL != de->heap_node)
2636 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2637 de->heap_node = NULL;
2638 GNUNET_assert (GNUNET_YES ==
2639 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2648 * We have too many active destinations. Clean up the oldest destination.
2650 * @param except destination that must NOT be cleaned up, even if it is the oldest
2653 expire_destination (struct DestinationEntry *except)
2655 struct DestinationEntry *de;
2657 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2658 GNUNET_assert (NULL != de);
2660 return; /* can't do this */
2661 free_destination_entry (de);
2666 * Allocate an IP address for the response.
2668 * @param result_af desired address family; set to the actual
2669 * address family; can initially be AF_UNSPEC if there
2670 * is no preference; will be set to AF_UNSPEC if the
2672 * @param addr set to either v4 or v6 depending on which
2673 * storage location was used; set to NULL if allocation failed
2674 * @param v4 storage space for an IPv4 address
2675 * @param v6 storage space for an IPv6 address
2676 * @return GNUNET_OK normally, GNUNET_SYSERR if '*result_af' was
2677 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2680 allocate_response_ip (int *result_af,
2683 struct in6_addr *v6)
2690 allocate_v4_address (v4))
2691 *result_af = AF_UNSPEC;
2697 allocate_v6_address (v6))
2698 *result_af = AF_UNSPEC;
2704 allocate_v4_address (v4))
2707 *result_af = AF_INET;
2709 else if (GNUNET_OK ==
2710 allocate_v6_address (v6))
2713 *result_af = AF_INET6;
2718 return GNUNET_SYSERR;
2725 * A client asks us to setup a redirection via some exit
2726 * node to a particular IP. Setup the redirection and
2727 * give the client the allocated IP.
2730 * @param client requesting client
2731 * @param message redirection request (a 'struct RedirectToIpRequestMessage')
2734 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2735 const struct GNUNET_MessageHeader *message)
2739 const struct RedirectToIpRequestMessage *msg;
2745 struct DestinationEntry *de;
2746 struct GNUNET_HashCode key;
2747 struct TunnelState *ts;
2749 /* validate and parse request */
2750 mlen = ntohs (message->size);
2751 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2754 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2757 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2758 msg = (const struct RedirectToIpRequestMessage *) message;
2759 addr_af = (int) htonl (msg->addr_af);
2763 if (alen != sizeof (struct in_addr))
2766 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2771 if (alen != sizeof (struct in6_addr))
2774 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2780 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2784 /* allocate response IP */
2785 result_af = (int) htonl (msg->result_af);
2786 if (GNUNET_OK != allocate_response_ip (&result_af,
2790 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2793 if ( (result_af == AF_UNSPEC) ||
2794 (GNUNET_NO == ntohl (msg->nac)) )
2796 /* send reply "instantly" */
2797 send_client_reply (client,
2802 if (result_af == AF_UNSPEC)
2804 /* failure, we're done */
2805 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2810 char sbuf[INET6_ADDRSTRLEN];
2811 char dbuf[INET6_ADDRSTRLEN];
2813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2814 "Allocated address %s for redirection via exit to %s\n",
2815 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2817 &msg[1], dbuf, sizeof (dbuf)));
2820 /* setup destination record */
2821 de = GNUNET_malloc (sizeof (struct DestinationEntry));
2822 de->is_service = GNUNET_NO;
2823 de->details.exit_destination.af = addr_af;
2824 memcpy (&de->details.exit_destination.ip,
2827 get_destination_key_from_ip (result_af,
2831 GNUNET_assert (GNUNET_OK ==
2832 GNUNET_CONTAINER_multihashmap_put (destination_map,
2835 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2836 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2838 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2839 GNUNET_STATISTICS_update (stats,
2840 gettext_noop ("# Active destinations"),
2842 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2843 expire_destination (de);
2845 /* setup tunnel to destination */
2846 ts = create_tunnel_to_destination (de,
2847 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2853 ts->destination_ip.v4 = v4;
2856 ts->destination_ip.v6 = v6;
2862 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2867 * A client asks us to setup a redirection to a particular peer
2868 * offering a service. Setup the redirection and give the client the
2872 * @param client requesting client
2873 * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
2876 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2877 const struct GNUNET_MessageHeader *message)
2879 const struct RedirectToServiceRequestMessage *msg;
2884 struct DestinationEntry *de;
2885 struct GNUNET_HashCode key;
2886 struct TunnelState *ts;
2889 msg = (const struct RedirectToServiceRequestMessage *) message;
2891 /* allocate response IP */
2892 result_af = (int) htonl (msg->result_af);
2893 if (GNUNET_OK != allocate_response_ip (&result_af,
2897 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2900 if ( (result_af == AF_UNSPEC) ||
2901 (GNUNET_NO == ntohl (msg->nac)) )
2903 /* send reply "instantly" */
2904 send_client_reply (client,
2909 if (result_af == AF_UNSPEC)
2911 /* failure, we're done */
2912 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2913 _("Failed to allocate IP address for new destination\n"));
2914 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2919 char sbuf[INET6_ADDRSTRLEN];
2921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2922 "Allocated address %s for redirection to service %s on peer %s\n",
2923 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2924 GNUNET_h2s (&msg->service_descriptor),
2925 GNUNET_i2s (&msg->target));
2928 /* setup destination record */
2929 de = GNUNET_malloc (sizeof (struct DestinationEntry));
2930 de->is_service = GNUNET_YES;
2931 de->details.service_destination.service_descriptor = msg->service_descriptor;
2932 de->details.service_destination.target = msg->target;
2933 get_destination_key_from_ip (result_af,
2937 GNUNET_assert (GNUNET_OK ==
2938 GNUNET_CONTAINER_multihashmap_put (destination_map,
2941 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2942 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2944 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2945 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2946 expire_destination (de);
2947 ts = create_tunnel_to_destination (de,
2948 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2954 ts->destination_ip.v4 = v4;
2957 ts->destination_ip.v6 = v6;
2963 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2969 * Function called for inbound tunnels. As we don't offer
2970 * any mesh services, this function should never be called.
2972 * @param cls closure
2973 * @param tunnel new handle to the tunnel
2974 * @param initiator peer that started the tunnel
2975 * @param atsi performance information for the tunnel
2976 * @return initial tunnel context for the tunnel
2977 * (can be NULL -- that's not an error)
2980 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
2981 const struct GNUNET_PeerIdentity *initiator,
2982 const struct GNUNET_ATS_Information *atsi)
2984 /* How can and why should anyone open an inbound tunnel to vpn? */
2991 * Function called whenever an inbound tunnel is destroyed. Should clean up
2992 * any associated state.
2994 * @param cls closure (set from GNUNET_MESH_connect)
2995 * @param tunnel connection to the other end (henceforth invalid)
2996 * @param tunnel_ctx place where local state associated
2997 * with the tunnel is stored (our 'struct TunnelState')
3000 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
3002 /* we don't have inbound tunnels, so this function should never be called */
3008 * Free memory occupied by an entry in the destination map.
3012 * @param value a 'struct DestinationEntry *'
3013 * @return GNUNET_OK (continue to iterate)
3016 cleanup_destination (void *cls,
3017 const struct GNUNET_HashCode *key,
3020 struct DestinationEntry *de = value;
3022 free_destination_entry (de);
3028 * Free memory occupied by an entry in the tunnel map.
3032 * @param value a 'struct TunnelState *'
3033 * @return GNUNET_OK (continue to iterate)
3036 cleanup_tunnel (void *cls,
3037 const struct GNUNET_HashCode *key,
3040 struct TunnelState *ts = value;
3042 free_tunnel_state (ts);
3048 * Function scheduled as very last function, cleans up after us
3054 cleanup (void *cls GNUNET_UNUSED,
3055 const struct GNUNET_SCHEDULER_TaskContext *tc)
3059 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3060 "VPN is shutting down\n");
3061 if (NULL != destination_map)
3063 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
3064 &cleanup_destination,
3066 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
3067 destination_map = NULL;
3069 if (NULL != destination_heap)
3071 GNUNET_CONTAINER_heap_destroy (destination_heap);
3072 destination_heap = NULL;
3074 if (NULL != tunnel_map)
3076 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
3079 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
3082 if (NULL != tunnel_heap)
3084 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
3087 if (NULL != mesh_handle)
3089 GNUNET_MESH_disconnect (mesh_handle);
3092 if (NULL != helper_handle)
3094 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3095 helper_handle = NULL;
3099 GNUNET_SERVER_notification_context_destroy (nc);
3104 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3108 GNUNET_free_non_null (vpn_argv[i]);
3113 * A client disconnected, clean up all references to it.
3115 * @param cls the client that disconnected
3117 * @param value a 'struct TunnelState *'
3118 * @return GNUNET_OK (continue to iterate)
3121 cleanup_tunnel_client (void *cls,
3122 const struct GNUNET_HashCode *key,
3125 struct GNUNET_SERVER_Client *client = cls;
3126 struct TunnelState *ts = value;
3128 if (client == ts->client)
3135 * A client disconnected, clean up all references to it.
3137 * @param cls the client that disconnected
3139 * @param value a 'struct DestinationEntry *'
3140 * @return GNUNET_OK (continue to iterate)
3143 cleanup_destination_client (void *cls,
3144 const struct GNUNET_HashCode *key,
3147 struct GNUNET_SERVER_Client *client = cls;
3148 struct DestinationEntry *de = value;
3149 struct TunnelState *ts;
3151 if (NULL == (ts = de->ts))
3153 if (client == ts->client)
3160 * A client has disconnected from us. If we are currently building
3161 * a tunnel for it, cancel the operation.
3164 * @param client handle to the client that disconnected
3167 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
3169 if (NULL != tunnel_map)
3170 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
3171 &cleanup_tunnel_client,
3173 if (NULL != destination_map)
3174 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
3175 &cleanup_destination_client,
3181 * Main function that will be run by the scheduler.
3183 * @param cls closure
3184 * @param server the initialized server
3185 * @param cfg_ configuration
3189 struct GNUNET_SERVER_Handle *server,
3190 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3192 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
3193 /* callback, cls, type, size */
3194 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
3195 { &service_redirect_to_service, NULL,
3196 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3197 sizeof (struct RedirectToServiceRequestMessage) },
3200 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
3201 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
3202 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
3203 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
3206 static const GNUNET_MESH_ApplicationType types[] = {
3207 GNUNET_APPLICATION_TYPE_END
3218 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
3221 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
3224 "`%s' is not SUID, refusing to run.\n",
3225 "gnunet-helper-vpn");
3226 GNUNET_free (binary);
3230 GNUNET_free (binary);
3232 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3234 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
3235 &max_destination_mappings))
3236 max_destination_mappings = 200;
3238 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
3239 &max_tunnel_mappings))
3240 max_tunnel_mappings = 200;
3242 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3243 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3244 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2, GNUNET_NO);
3245 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3248 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3249 if (GNUNET_SYSERR ==
3250 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
3252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3253 "No entry 'IFNAME' in configuration!\n");
3254 GNUNET_SCHEDULER_shutdown ();
3257 vpn_argv[1] = ifname;
3258 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3260 if ( (GNUNET_SYSERR ==
3261 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
3263 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3266 "No valid entry 'IPV6ADDR' in configuration!\n");
3267 GNUNET_SCHEDULER_shutdown ();
3270 vpn_argv[2] = ipv6addr;
3271 if (GNUNET_SYSERR ==
3272 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
3275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3276 "No entry 'IPV6PREFIX' in configuration!\n");
3277 GNUNET_SCHEDULER_shutdown ();
3280 vpn_argv[3] = ipv6prefix_s;
3282 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
3285 (ipv6prefix >= 127) )
3287 GNUNET_SCHEDULER_shutdown ();
3293 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3294 _("IPv6 support disabled as this system does not support IPv6\n"));
3295 vpn_argv[2] = GNUNET_strdup ("-");
3296 vpn_argv[3] = GNUNET_strdup ("-");
3298 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3300 if ( (GNUNET_SYSERR ==
3301 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3303 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3305 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3306 "No valid entry for 'IPV4ADDR' in configuration!\n");
3307 GNUNET_SCHEDULER_shutdown ();
3310 vpn_argv[4] = ipv4addr;
3311 if ( (GNUNET_SYSERR ==
3312 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3314 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3316 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3317 "No valid entry 'IPV4MASK' in configuration!\n");
3318 GNUNET_SCHEDULER_shutdown ();
3321 vpn_argv[5] = ipv4mask;
3325 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3326 _("IPv4 support disabled as this system does not support IPv4\n"));
3327 vpn_argv[4] = GNUNET_strdup ("-");
3328 vpn_argv[5] = GNUNET_strdup ("-");
3333 GNUNET_MESH_connect (cfg_, NULL,
3338 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3339 "gnunet-helper-vpn", vpn_argv,
3340 &message_token, NULL, NULL);
3341 nc = GNUNET_SERVER_notification_context_create (server, 1);
3342 GNUNET_SERVER_add_handlers (server, service_handlers);
3343 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
3344 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3349 * The main function of the VPN service.
3351 * @param argc number of arguments from the command line
3352 * @param argv command line arguments
3353 * @return 0 ok, 1 on error
3356 main (int argc, char *const *argv)
3358 return (GNUNET_OK ==
3359 GNUNET_SERVICE_run (argc, argv, "vpn",
3360 GNUNET_SERVICE_OPTION_NONE,
3361 &run, NULL)) ? global_ret : 1;
3364 /* end of gnunet-service-vpn.c */