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);
542 if (NULL != ts->client)
544 GNUNET_SERVER_client_drop (ts->client);
549 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
552 GNUNET_assert (NULL == ts->destination.heap_node);
553 if (NULL != (tunnel = ts->tunnel))
556 GNUNET_MESH_tunnel_destroy (tunnel);
558 if (NULL != ts->search)
560 GNUNET_REGEX_search_cancel (ts->search);
563 if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
565 GNUNET_SCHEDULER_cancel (ts->destroy_task);
566 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
568 if (NULL != ts->heap_node)
570 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
571 ts->heap_node = NULL;
572 get_tunnel_key_from_ips (ts->af,
577 ts->destination_port,
579 GNUNET_assert (GNUNET_YES ==
580 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
584 if (NULL != ts->destination_container)
586 GNUNET_assert (ts == ts->destination_container->ts);
587 ts->destination_container->ts = NULL;
588 ts->destination_container = NULL;
595 * Destroy the mesh tunnel.
597 * @param cls the 'struct TunnelState' with the tunnel to destroy
598 * @param tc scheduler context
601 destroy_tunnel_task (void *cls,
602 const struct GNUNET_SCHEDULER_TaskContext *tc)
604 struct TunnelState *ts = cls;
605 struct GNUNET_MESH_Tunnel *tunnel;
607 ts->destroy_task = GNUNET_SCHEDULER_NO_TASK;
608 GNUNET_assert (NULL != ts->tunnel);
611 GNUNET_MESH_tunnel_destroy (tunnel);
612 free_tunnel_state (ts);
617 * Method called whenever a peer has disconnected from the tunnel.
620 * @param peer peer identity the tunnel stopped working with
623 tunnel_peer_disconnect_handler (void *cls,
625 GNUNET_PeerIdentity * peer)
627 struct TunnelState *ts = cls;
629 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
630 "Peer %s disconnected from tunnel.\n",
632 GNUNET_STATISTICS_update (stats,
633 gettext_noop ("# peers connected to mesh tunnels"),
637 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
640 if (ts->destination.is_service)
641 return; /* hope for reconnect eventually */
642 /* as we are most likely going to change the exit node now,
643 we should just destroy the tunnel entirely... */
644 if (GNUNET_SCHEDULER_NO_TASK == ts->destroy_task)
645 ts->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_tunnel_task, ts);
650 * Method called whenever a peer has connected to the tunnel. Notifies
651 * the waiting client that the tunnel is now up.
654 * @param peer peer identity the tunnel was created to, NULL on timeout
655 * @param atsi performance data for the connection
658 tunnel_peer_connect_handler (void *cls,
659 const struct GNUNET_PeerIdentity
662 GNUNET_ATS_Information * atsi)
664 struct TunnelState *ts = cls;
666 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
667 "Peer %s connected to tunnel.\n",
669 GNUNET_STATISTICS_update (stats,
670 gettext_noop ("# peers connected to mesh tunnels"),
672 if (NULL == ts->client)
673 return; /* nothing to do */
674 send_client_reply (ts->client,
677 &ts->destination_ip);
678 GNUNET_SERVER_client_drop (ts->client);
684 * Send a message from the message queue via mesh.
686 * @param cls the 'struct TunnelState' with the message queue
687 * @param size number of bytes available in buf
688 * @param buf where to copy the message
689 * @return number of bytes copied to buf
692 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
694 struct TunnelState *ts = cls;
695 struct TunnelMessageQueueEntry *tnq;
702 GNUNET_assert (NULL != tnq);
703 GNUNET_assert (size >= tnq->len);
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "Sending %u bytes via mesh tunnel\n",
707 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
711 memcpy (buf, tnq->msg, tnq->len);
714 if (NULL != (tnq = ts->tmq_head))
715 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
716 GNUNET_NO /* cork */,
717 GNUNET_TIME_UNIT_FOREVER_REL,
720 &send_to_peer_notify_callback,
722 GNUNET_STATISTICS_update (stats,
723 gettext_noop ("# Bytes given to mesh for transmission"),
730 * Add the given message to the given tunnel and trigger the
731 * transmission process.
733 * @param tnq message to queue
734 * @param ts tunnel to queue the message for
737 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
738 struct TunnelState *ts)
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
741 "Queueing %u bytes for transmission via mesh tunnel\n",
743 GNUNET_assert (NULL != ts->tunnel);
744 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
748 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
750 struct TunnelMessageQueueEntry *dq;
753 GNUNET_assert (dq != tnq);
754 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
758 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
760 GNUNET_STATISTICS_update (stats,
761 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
767 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
768 GNUNET_NO /* cork */,
769 GNUNET_TIME_UNIT_FOREVER_REL,
772 &send_to_peer_notify_callback,
778 * Create a string with binary IP notation for the given 'addr' in 'str'.
780 * @param af address family of the given 'addr'.
781 * @param addr address that should be converted to a string.
782 * struct in_addr * for IPv4 and struct in6_addr * for IPv6.
783 * @param str string that will contain binary notation of 'addr'. Expected
784 * to be at least 33 bytes long for IPv4 and 129 bytes long for IPv6.
787 iptobinstr (const int af, const void *addr, char *str)
795 uint32_t b = htonl (((struct in_addr *) addr)->s_addr);
799 for (i = 31; i >= 0; i--)
801 *str = (b & 1) + '0';
809 struct in6_addr b = *(const struct in6_addr *) addr;
813 for (i = 127; i >= 0; i--)
815 *str = (b.s6_addr[i / 8] & 1) + '0';
817 b.s6_addr[i / 8] >>= 1;
826 * Get the ipv4 network prefix from the given 'netmask'.
828 * @param netmask netmask for which to get the prefix len.
830 * @return length of ipv4 prefix for 'netmask'.
833 ipv4netmasktoprefixlen (const char *netmask)
839 if (1 != inet_pton (AF_INET, netmask, &a))
842 for (t = htonl (~a.s_addr); 0 != t; t >>= 1)
849 * Create a regex in 'rxstr' from the given 'ip' and 'netmask'.
851 * @param ip IPv4 representation.
852 * @param netmask netmask for the ip.
853 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV4_REGEXLEN
857 ipv4toregex (const struct in_addr *ip, const char *netmask,
862 pfxlen = ipv4netmasktoprefixlen (netmask);
863 iptobinstr (AF_INET, ip, rxstr);
864 rxstr[pfxlen] = '\0';
866 strcat (rxstr, "(0|1)+");
871 * Create a regex in 'rxstr' from the given 'ipv6' and 'prefixlen'.
873 * @param ipv6 IPv6 representation.
874 * @param prefixlen length of the ipv6 prefix.
875 * @param rxstr generated regex, must be at least GNUNET_REGEX_IPV6_REGEXLEN
879 ipv6toregex (const struct in6_addr *ipv6, unsigned int prefixlen,
882 iptobinstr (AF_INET6, ipv6, rxstr);
883 rxstr[prefixlen] = '\0';
885 strcat (rxstr, "(0|1)+");
890 * Regex has found a potential exit peer for us; consider using it.
892 * @param cls the 'struct TunnelState'
893 * @param id Peer providing a regex that matches the string.
894 * @param get_path Path of the get request.
895 * @param get_path_length Lenght of get_path.
896 * @param put_path Path of the put request.
897 * @param put_path_length Length of the put_path.
900 handle_regex_result (void *cls,
901 const struct GNUNET_PeerIdentity *id,
902 const struct GNUNET_PeerIdentity *get_path,
903 unsigned int get_path_length,
904 const struct GNUNET_PeerIdentity *put_path,
905 unsigned int put_path_length)
907 struct TunnelState *ts = cls;
909 GNUNET_REGEX_search_cancel (ts->search);
911 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
913 &tunnel_peer_connect_handler,
914 &tunnel_peer_disconnect_handler,
916 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
922 * Initialize the given destination entry's mesh tunnel.
924 * @param de destination entry for which we need to setup a tunnel
925 * @param client client to notify on successful tunnel setup, or NULL for none
926 * @param client_af address family of the address returned to the client
927 * @param request_id request ID to send in client notification (unused if client is NULL)
928 * @return tunnel state of the tunnel that was created
930 static struct TunnelState *
931 create_tunnel_to_destination (struct DestinationEntry *de,
932 struct GNUNET_SERVER_Client *client,
936 struct TunnelState *ts;
938 GNUNET_STATISTICS_update (stats,
939 gettext_noop ("# Mesh tunnels created"),
941 GNUNET_assert (NULL == de->ts);
942 ts = GNUNET_malloc (sizeof (struct TunnelState));
946 ts->request_id = request_id;
948 GNUNET_SERVER_client_keep (client);
950 ts->destination = *de;
951 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
953 ts->destination_container = de; /* we are referenced from de */
956 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
958 &tunnel_peer_connect_handler,
959 &tunnel_peer_disconnect_handler,
961 if (NULL == ts->tunnel)
963 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
964 _("Failed to setup mesh tunnel!\n"));
966 GNUNET_SERVER_client_drop (client);
970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
971 "Creating tunnel to peer %s offering service %s\n",
972 GNUNET_i2s (&de->details.service_destination.target),
973 GNUNET_h2s (&de->details.service_destination.service_descriptor));
974 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
975 &de->details.service_destination.target);
981 switch (de->details.exit_destination.af)
985 char address[GNUNET_REGEX_IPV4_REGEXLEN];
987 ipv4toregex (&de->details.exit_destination.ip.v4,
988 "255.255.255.255", address);
989 GNUNET_asprintf (&policy, "%s%s%s",
990 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
997 char address[GNUNET_REGEX_IPV6_REGEXLEN];
999 ipv6toregex (&de->details.exit_destination.ip.v6,
1001 GNUNET_asprintf (&policy, "%s%s%s",
1002 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1013 "Requesting connect by string: %s\n",
1015 ts->search = GNUNET_REGEX_search (cfg,
1017 &handle_regex_result,
1019 GNUNET_free (policy);
1026 * We have too many active tunnels. Clean up the oldest tunnel.
1028 * @param except tunnel that must NOT be cleaned up, even if it is the oldest
1031 expire_tunnel (struct TunnelState *except)
1033 struct TunnelState *ts;
1035 ts = GNUNET_CONTAINER_heap_peek (tunnel_heap);
1036 GNUNET_assert (NULL != ts);
1038 return; /* can't do this */
1039 free_tunnel_state (ts);
1044 * Route a packet via mesh to the given destination.
1046 * @param destination description of the destination
1047 * @param af address family on this end (AF_INET or AF_INET6)
1048 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
1049 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
1050 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
1051 * @param payload payload of the packet after the IP header
1052 * @param payload_length number of bytes in payload
1055 route_packet (struct DestinationEntry *destination,
1058 const void *source_ip,
1059 const void *destination_ip,
1060 const void *payload,
1061 size_t payload_length)
1063 struct GNUNET_HashCode key;
1064 struct TunnelState *ts;
1065 struct TunnelMessageQueueEntry *tnq;
1069 const struct GNUNET_TUN_UdpHeader *udp;
1070 const struct GNUNET_TUN_TcpHeader *tcp;
1071 const struct GNUNET_TUN_IcmpHeader *icmp;
1072 uint16_t source_port;
1073 uint16_t destination_port;
1079 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1085 tcp = NULL; /* make compiler happy */
1086 icmp = NULL; /* make compiler happy */
1088 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1090 GNUNET_break_op (0);
1093 source_port = ntohs (udp->source_port);
1094 destination_port = ntohs (udp->destination_port);
1095 get_tunnel_key_from_ips (af,
1106 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1112 udp = NULL; /* make compiler happy */
1113 icmp = NULL; /* make compiler happy */
1115 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1117 GNUNET_break_op (0);
1120 source_port = ntohs (tcp->source_port);
1121 destination_port = ntohs (tcp->destination_port);
1122 get_tunnel_key_from_ips (af,
1132 case IPPROTO_ICMPV6:
1134 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1139 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1145 tcp = NULL; /* make compiler happy */
1146 udp = NULL; /* make compiler happy */
1149 destination_port = 0;
1150 get_tunnel_key_from_ips (af,
1160 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1161 _("Protocol %u not supported, dropping\n"),
1162 (unsigned int) protocol);
1165 if (! destination->is_service)
1167 switch (destination->details.exit_destination.af)
1170 alen = sizeof (struct in_addr);
1173 alen = sizeof (struct in6_addr);
1181 char sbuf[INET6_ADDRSTRLEN];
1182 char dbuf[INET6_ADDRSTRLEN];
1183 char xbuf[INET6_ADDRSTRLEN];
1185 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1187 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1188 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1190 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1192 inet_ntop (destination->details.exit_destination.af,
1193 &destination->details.exit_destination.ip,
1194 xbuf, sizeof (xbuf)),
1200 /* make compiler happy */
1203 char sbuf[INET6_ADDRSTRLEN];
1204 char dbuf[INET6_ADDRSTRLEN];
1206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1207 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1208 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1209 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1211 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1213 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1214 GNUNET_i2s (&destination->details.service_destination.target));
1219 /* see if we have an existing tunnel for this destination */
1220 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
1224 /* need to either use the existing tunnel from the destination (if still
1225 available) or create a fresh one */
1226 is_new = GNUNET_YES;
1227 if (NULL == destination->ts)
1228 ts = create_tunnel_to_destination (destination, NULL, af, 0);
1230 ts = destination->ts;
1233 destination->ts = NULL;
1234 ts->destination_container = NULL; /* no longer 'contained' */
1235 /* now bind existing "unbound" tunnel to our IP/port tuple */
1236 ts->protocol = protocol;
1240 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1241 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1245 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1246 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1248 ts->source_port = source_port;
1249 ts->destination_port = destination_port;
1250 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
1252 GNUNET_TIME_absolute_get ().abs_value);
1253 GNUNET_assert (GNUNET_YES ==
1254 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
1257 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1258 GNUNET_STATISTICS_update (stats,
1259 gettext_noop ("# Active tunnels"),
1261 while (GNUNET_CONTAINER_multihashmap_size (tunnel_map) > max_tunnel_mappings)
1267 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1269 GNUNET_TIME_absolute_get ().abs_value);
1271 GNUNET_assert (NULL != ts->tunnel);
1273 /* send via tunnel */
1277 if (destination->is_service)
1279 struct GNUNET_EXIT_UdpServiceMessage *usm;
1281 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1282 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1283 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1288 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1291 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1292 usm->header.size = htons ((uint16_t) mlen);
1293 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1294 /* if the source port is below 32000, we assume it has a special
1295 meaning; if not, we pick a random port (this is a heuristic) */
1296 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1297 usm->destination_port = udp->destination_port;
1298 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1301 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1305 struct GNUNET_EXIT_UdpInternetMessage *uim;
1306 struct in_addr *ip4dst;
1307 struct in6_addr *ip6dst;
1310 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1311 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1312 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1317 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1321 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1322 uim->header.size = htons ((uint16_t) mlen);
1323 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1324 uim->af = htonl (destination->details.exit_destination.af);
1325 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1326 uim->destination_port = udp->destination_port;
1327 switch (destination->details.exit_destination.af)
1330 ip4dst = (struct in_addr *) &uim[1];
1331 *ip4dst = destination->details.exit_destination.ip.v4;
1332 payload = &ip4dst[1];
1335 ip6dst = (struct in6_addr *) &uim[1];
1336 *ip6dst = destination->details.exit_destination.ip.v6;
1337 payload = &ip6dst[1];
1344 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1350 if (destination->is_service)
1352 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1354 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1355 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1356 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1361 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1364 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1365 tsm->header.size = htons ((uint16_t) mlen);
1366 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1367 tsm->reserved = htonl (0);
1368 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1369 tsm->tcp_header = *tcp;
1372 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1376 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1377 struct in_addr *ip4dst;
1378 struct in6_addr *ip6dst;
1381 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1382 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1383 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1388 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1391 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1392 tim->header.size = htons ((uint16_t) mlen);
1393 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1394 tim->af = htonl (destination->details.exit_destination.af);
1395 tim->tcp_header = *tcp;
1396 switch (destination->details.exit_destination.af)
1399 ip4dst = (struct in_addr *) &tim[1];
1400 *ip4dst = destination->details.exit_destination.ip.v4;
1401 payload = &ip4dst[1];
1404 ip6dst = (struct in6_addr *) &tim[1];
1405 *ip6dst = destination->details.exit_destination.ip.v6;
1406 payload = &ip6dst[1];
1413 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1418 struct GNUNET_EXIT_TcpDataMessage *tdm;
1420 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1421 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1422 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1427 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1430 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1431 tdm->header.size = htons ((uint16_t) mlen);
1432 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1433 tdm->reserved = htonl (0);
1434 tdm->tcp_header = *tcp;
1437 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1441 case IPPROTO_ICMPV6:
1442 if (destination->is_service)
1444 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1446 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1447 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1448 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1453 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1455 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1456 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1457 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1458 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1459 ism->icmp_header = *icmp;
1460 /* ICMP protocol translation will be done by the receiver (as we don't know
1461 the target AF); however, we still need to possibly discard the payload
1462 depending on the ICMP type */
1468 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1469 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1471 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1472 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1473 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1474 /* throw away ICMP payload, won't be useful for the other side anyway */
1475 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1478 GNUNET_STATISTICS_update (stats,
1479 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1483 /* end of AF_INET */
1488 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1489 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1490 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1491 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1492 /* throw away ICMP payload, won't be useful for the other side anyway */
1493 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1495 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1496 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1499 GNUNET_STATISTICS_update (stats,
1500 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1504 /* end of AF_INET6 */
1511 /* update length calculations, as payload_length may have changed */
1512 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1513 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1515 ism->header.size = htons ((uint16_t) mlen);
1516 /* finally, copy payload (if there is any left...) */
1519 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1523 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1524 struct in_addr *ip4dst;
1525 struct in6_addr *ip6dst;
1528 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1529 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1530 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1535 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
1538 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1539 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1540 iim->icmp_header = *icmp;
1541 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1542 and throw away ICMP payload depending on ICMP message type */
1548 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1549 if (destination->details.exit_destination.af == AF_INET6)
1550 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1552 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1553 if (destination->details.exit_destination.af == AF_INET6)
1554 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1556 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1557 if (destination->details.exit_destination.af == AF_INET6)
1558 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1559 /* throw away IP-payload, exit will have to make it up anyway */
1560 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1562 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1563 if (destination->details.exit_destination.af == AF_INET6)
1564 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1565 /* throw away IP-payload, exit will have to make it up anyway */
1566 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1568 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1569 if (destination->details.exit_destination.af == AF_INET6)
1571 GNUNET_STATISTICS_update (stats,
1572 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1577 /* throw away IP-payload, exit will have to make it up anyway */
1578 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1581 GNUNET_STATISTICS_update (stats,
1582 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1587 /* end of AF_INET */
1592 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1593 if (destination->details.exit_destination.af == AF_INET6)
1594 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1595 /* throw away IP-payload, exit will have to make it up anyway */
1596 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1598 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1599 if (destination->details.exit_destination.af == AF_INET)
1600 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1601 /* throw away IP-payload, exit will have to make it up anyway */
1602 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1604 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1605 if (destination->details.exit_destination.af == AF_INET)
1607 GNUNET_STATISTICS_update (stats,
1608 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1613 /* throw away IP-payload, exit will have to make it up anyway */
1614 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1616 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1617 if (destination->details.exit_destination.af == AF_INET)
1619 GNUNET_STATISTICS_update (stats,
1620 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1625 /* throw away IP-payload, exit will have to make it up anyway */
1626 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1628 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1629 if (destination->details.exit_destination.af == AF_INET)
1630 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1632 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1633 if (destination->details.exit_destination.af == AF_INET)
1634 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1637 GNUNET_STATISTICS_update (stats,
1638 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1643 /* end of AF_INET6 */
1648 /* update length calculations, as payload_length may have changed */
1649 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1650 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1652 iim->header.size = htons ((uint16_t) mlen);
1654 /* need to tell destination ICMP protocol family! */
1655 iim->af = htonl (destination->details.exit_destination.af);
1656 switch (destination->details.exit_destination.af)
1659 ip4dst = (struct in_addr *) &iim[1];
1660 *ip4dst = destination->details.exit_destination.ip.v4;
1661 payload = &ip4dst[1];
1664 ip6dst = (struct in6_addr *) &iim[1];
1665 *ip6dst = destination->details.exit_destination.ip.v6;
1666 payload = &ip6dst[1];
1673 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1677 /* not supported above, how can we get here !? */
1681 send_to_tunnel (tnq, ts);
1686 * Receive packets from the helper-process (someone send to the local
1687 * virtual tunnel interface). Find the destination mapping, and if it
1688 * exists, identify the correct MESH tunnel (or possibly create it)
1689 * and forward the packet.
1691 * @param cls closure, NULL
1692 * @param client NULL
1693 * @param message message we got from the client (VPN tunnel interface)
1696 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1697 const struct GNUNET_MessageHeader *message)
1699 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1701 struct GNUNET_HashCode key;
1702 struct DestinationEntry *de;
1704 GNUNET_STATISTICS_update (stats,
1705 gettext_noop ("# Packets received from TUN interface"),
1707 mlen = ntohs (message->size);
1708 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1709 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1714 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1715 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1716 switch (ntohs (tun->proto))
1720 const struct GNUNET_TUN_IPv6Header *pkt6;
1722 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1728 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1729 get_destination_key_from_ip (AF_INET6,
1730 &pkt6->destination_address,
1732 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1733 /* FIXME: do we need to guard against hash collision?
1734 (if so, we need to also store the local destination IP in the
1735 destination entry and then compare here; however, the risk
1736 of collision seems minimal AND the impact is unlikely to be
1737 super-problematic as well... */
1740 char buf[INET6_ADDRSTRLEN];
1742 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1743 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1744 inet_ntop (AF_INET6,
1745 &pkt6->destination_address,
1753 &pkt6->source_address,
1754 &pkt6->destination_address,
1756 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1761 struct GNUNET_TUN_IPv4Header *pkt4;
1763 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1769 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1770 get_destination_key_from_ip (AF_INET,
1771 &pkt4->destination_address,
1773 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1774 /* FIXME: do we need to guard against hash collision?
1775 (if so, we need to also store the local destination IP in the
1776 destination entry and then compare here; however, the risk
1777 of collision seems minimal AND the impact is unlikely to be
1778 super-problematic as well... */
1781 char buf[INET_ADDRSTRLEN];
1783 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1784 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1786 &pkt4->destination_address,
1791 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1793 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1794 _("Received IPv4 packet with options (dropping it)\n"));
1800 &pkt4->source_address,
1801 &pkt4->destination_address,
1803 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1807 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1808 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1809 (unsigned int) ntohs (tun->proto));
1817 * Synthesize a plausible ICMP payload for an ICMP error
1818 * response on the given tunnel.
1820 * @param ts tunnel information
1821 * @param ipp IPv4 header to fill in (ICMP payload)
1822 * @param udp "UDP" header to fill in (ICMP payload); might actually
1823 * also be the first 8 bytes of the TCP header
1826 make_up_icmpv4_payload (struct TunnelState *ts,
1827 struct GNUNET_TUN_IPv4Header *ipp,
1828 struct GNUNET_TUN_UdpHeader *udp)
1830 GNUNET_TUN_initialize_ipv4_header (ipp,
1832 sizeof (struct GNUNET_TUN_TcpHeader),
1834 &ts->destination_ip.v4);
1835 udp->source_port = htons (ts->source_port);
1836 udp->destination_port = htons (ts->destination_port);
1837 udp->len = htons (0);
1838 udp->crc = htons (0);
1843 * Synthesize a plausible ICMP payload for an ICMP error
1844 * response on the given tunnel.
1846 * @param ts tunnel information
1847 * @param ipp IPv6 header to fill in (ICMP payload)
1848 * @param udp "UDP" header to fill in (ICMP payload); might actually
1849 * also be the first 8 bytes of the TCP header
1852 make_up_icmpv6_payload (struct TunnelState *ts,
1853 struct GNUNET_TUN_IPv6Header *ipp,
1854 struct GNUNET_TUN_UdpHeader *udp)
1856 GNUNET_TUN_initialize_ipv6_header (ipp,
1858 sizeof (struct GNUNET_TUN_TcpHeader),
1860 &ts->destination_ip.v6);
1861 udp->source_port = htons (ts->source_port);
1862 udp->destination_port = htons (ts->destination_port);
1863 udp->len = htons (0);
1864 udp->crc = htons (0);
1869 * We got an ICMP packet back from the MESH tunnel. Pass it on to the
1870 * local virtual interface via the helper.
1872 * @param cls closure, NULL
1873 * @param tunnel connection to the other end
1874 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1875 * @param sender who sent the message
1876 * @param message the actual message
1877 * @param atsi performance data for the connection
1878 * @return GNUNET_OK to keep the connection open,
1879 * GNUNET_SYSERR to close it (signal serious error)
1882 receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1883 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1884 const struct GNUNET_MessageHeader *message,
1885 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1887 struct TunnelState *ts = *tunnel_ctx;
1888 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1891 GNUNET_STATISTICS_update (stats,
1892 gettext_noop ("# ICMP packets received from mesh"),
1894 mlen = ntohs (message->size);
1895 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1897 GNUNET_break_op (0);
1898 return GNUNET_SYSERR;
1900 if (NULL == ts->heap_node)
1902 GNUNET_break_op (0);
1903 return GNUNET_SYSERR;
1905 if (AF_UNSPEC == ts->af)
1907 GNUNET_break_op (0);
1908 return GNUNET_SYSERR;
1910 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1911 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1913 char sbuf[INET6_ADDRSTRLEN];
1914 char dbuf[INET6_ADDRSTRLEN];
1916 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1917 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1918 (unsigned int) mlen,
1919 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1920 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1926 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1927 + sizeof (struct GNUNET_TUN_IcmpHeader)
1928 + sizeof (struct GNUNET_MessageHeader) +
1929 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1932 /* reserve some extra space in case we have an ICMP type here where
1933 we will need to make up the payload ourselves */
1934 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1935 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1936 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1937 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1938 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1939 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1940 tun->flags = htons (0);
1941 tun->proto = htons (ETH_P_IPV4);
1942 GNUNET_TUN_initialize_ipv4_header (ipv4,
1944 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1945 &ts->destination_ip.v4,
1947 *icmp = i2v->icmp_header;
1951 /* For some ICMP types, we need to adjust (make up) the payload here.
1952 Also, depending on the AF used on the other side, we have to
1953 do ICMP PT (translate ICMP types) */
1954 switch (ntohl (i2v->af))
1959 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1960 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1962 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1963 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1964 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1966 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1967 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1971 /* sender did not strip ICMP payload? */
1972 GNUNET_break_op (0);
1973 return GNUNET_SYSERR;
1975 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1976 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1977 make_up_icmpv4_payload (ts, ipp, udp);
1981 GNUNET_break_op (0);
1982 GNUNET_STATISTICS_update (stats,
1983 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1985 return GNUNET_SYSERR;
1990 /* ICMP PT 6-to-4 and possibly making up payloads */
1993 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1994 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1996 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1997 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2001 /* sender did not strip ICMP payload? */
2002 GNUNET_break_op (0);
2003 return GNUNET_SYSERR;
2005 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2006 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2007 make_up_icmpv4_payload (ts, ipp, udp);
2010 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2011 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2013 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
2014 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2018 /* sender did not strip ICMP payload? */
2019 GNUNET_break_op (0);
2020 return GNUNET_SYSERR;
2022 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2023 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2024 make_up_icmpv4_payload (ts, ipp, udp);
2027 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2028 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2029 GNUNET_STATISTICS_update (stats,
2030 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2033 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2034 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2036 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2037 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2040 GNUNET_break_op (0);
2041 GNUNET_STATISTICS_update (stats,
2042 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2044 return GNUNET_SYSERR;
2049 GNUNET_break_op (0);
2050 return GNUNET_SYSERR;
2052 msg->size = htons (size);
2053 GNUNET_TUN_calculate_icmp_checksum (icmp,
2056 (void) GNUNET_HELPER_send (helper_handle,
2065 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2066 + sizeof (struct GNUNET_TUN_IcmpHeader)
2067 + sizeof (struct GNUNET_MessageHeader) +
2068 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2071 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2072 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2073 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2074 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2075 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
2076 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2077 tun->flags = htons (0);
2078 tun->proto = htons (ETH_P_IPV6);
2079 GNUNET_TUN_initialize_ipv6_header (ipv6,
2081 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
2082 &ts->destination_ip.v6,
2084 *icmp = i2v->icmp_header;
2089 /* For some ICMP types, we need to adjust (make up) the payload here.
2090 Also, depending on the AF used on the other side, we have to
2091 do ICMP PT (translate ICMP types) */
2092 switch (ntohl (i2v->af))
2095 /* ICMP PT 4-to-6 and possibly making up payloads */
2098 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2099 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2101 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2102 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2104 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2105 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2107 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2108 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2112 /* sender did not strip ICMP payload? */
2113 GNUNET_break_op (0);
2114 return GNUNET_SYSERR;
2116 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2117 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2118 make_up_icmpv6_payload (ts, ipp, udp);
2121 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2122 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2124 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2125 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2129 /* sender did not strip ICMP payload? */
2130 GNUNET_break_op (0);
2131 return GNUNET_SYSERR;
2133 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2134 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2135 make_up_icmpv6_payload (ts, ipp, udp);
2138 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2139 GNUNET_STATISTICS_update (stats,
2140 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2144 GNUNET_break_op (0);
2145 GNUNET_STATISTICS_update (stats,
2146 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2148 return GNUNET_SYSERR;
2155 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2156 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2157 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2158 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2160 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
2161 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2165 /* sender did not strip ICMP payload? */
2166 GNUNET_break_op (0);
2167 return GNUNET_SYSERR;
2169 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2170 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2171 make_up_icmpv6_payload (ts, ipp, udp);
2174 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2177 GNUNET_break_op (0);
2178 GNUNET_STATISTICS_update (stats,
2179 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2181 return GNUNET_SYSERR;
2186 GNUNET_break_op (0);
2187 return GNUNET_SYSERR;
2189 msg->size = htons (size);
2190 GNUNET_TUN_calculate_icmp_checksum (icmp,
2192 (void) GNUNET_HELPER_send (helper_handle,
2202 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2204 GNUNET_TIME_absolute_get ().abs_value);
2210 * We got a UDP packet back from the MESH tunnel. Pass it on to the
2211 * local virtual interface via the helper.
2213 * @param cls closure, NULL
2214 * @param tunnel connection to the other end
2215 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2216 * @param sender who sent the message
2217 * @param message the actual message
2218 * @param atsi performance data for the connection
2219 * @return GNUNET_OK to keep the connection open,
2220 * GNUNET_SYSERR to close it (signal serious error)
2223 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2224 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
2225 const struct GNUNET_MessageHeader *message,
2226 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2228 struct TunnelState *ts = *tunnel_ctx;
2229 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2232 GNUNET_STATISTICS_update (stats,
2233 gettext_noop ("# UDP packets received from mesh"),
2235 mlen = ntohs (message->size);
2236 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2238 GNUNET_break_op (0);
2239 return GNUNET_SYSERR;
2241 if (NULL == ts->heap_node)
2243 GNUNET_break_op (0);
2244 return GNUNET_SYSERR;
2246 if (AF_UNSPEC == ts->af)
2248 GNUNET_break_op (0);
2249 return GNUNET_SYSERR;
2251 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2252 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2254 char sbuf[INET6_ADDRSTRLEN];
2255 char dbuf[INET6_ADDRSTRLEN];
2257 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2258 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2259 (unsigned int) mlen,
2260 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2261 ts->destination_port,
2262 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2269 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2270 + sizeof (struct GNUNET_TUN_UdpHeader)
2271 + sizeof (struct GNUNET_MessageHeader) +
2272 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2275 char buf[size] GNUNET_ALIGN;
2276 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2277 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2278 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2279 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2280 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2281 msg->size = htons (size);
2282 tun->flags = htons (0);
2283 tun->proto = htons (ETH_P_IPV4);
2284 GNUNET_TUN_initialize_ipv4_header (ipv4,
2286 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2287 &ts->destination_ip.v4,
2289 if (0 == ntohs (reply->source_port))
2290 udp->source_port = htons (ts->destination_port);
2292 udp->source_port = reply->source_port;
2293 if (0 == ntohs (reply->destination_port))
2294 udp->destination_port = htons (ts->source_port);
2296 udp->destination_port = reply->destination_port;
2297 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2298 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2305 (void) GNUNET_HELPER_send (helper_handle,
2314 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2315 + sizeof (struct GNUNET_TUN_UdpHeader)
2316 + sizeof (struct GNUNET_MessageHeader) +
2317 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2320 char buf[size] GNUNET_ALIGN;
2321 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2322 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2323 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2324 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2325 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2326 msg->size = htons (size);
2327 tun->flags = htons (0);
2328 tun->proto = htons (ETH_P_IPV6);
2329 GNUNET_TUN_initialize_ipv6_header (ipv6,
2331 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2332 &ts->destination_ip.v6,
2334 if (0 == ntohs (reply->source_port))
2335 udp->source_port = htons (ts->destination_port);
2337 udp->source_port = reply->source_port;
2338 if (0 == ntohs (reply->destination_port))
2339 udp->destination_port = htons (ts->source_port);
2341 udp->destination_port = reply->destination_port;
2342 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2343 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2349 (void) GNUNET_HELPER_send (helper_handle,
2359 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2361 GNUNET_TIME_absolute_get ().abs_value);
2367 * We got a TCP packet back from the MESH tunnel. Pass it on to the
2368 * local virtual interface via the helper.
2370 * @param cls closure, NULL
2371 * @param tunnel connection to the other end
2372 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2373 * @param sender who sent the message
2374 * @param message the actual message
2375 * @param atsi performance data for the connection
2376 * @return GNUNET_OK to keep the connection open,
2377 * GNUNET_SYSERR to close it (signal serious error)
2380 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2382 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2383 const struct GNUNET_MessageHeader *message,
2384 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2386 struct TunnelState *ts = *tunnel_ctx;
2387 const struct GNUNET_EXIT_TcpDataMessage *data;
2390 GNUNET_STATISTICS_update (stats,
2391 gettext_noop ("# TCP packets received from mesh"),
2393 mlen = ntohs (message->size);
2394 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2396 GNUNET_break_op (0);
2397 return GNUNET_SYSERR;
2399 if (NULL == ts->heap_node)
2401 GNUNET_break_op (0);
2402 return GNUNET_SYSERR;
2404 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2405 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2407 char sbuf[INET6_ADDRSTRLEN];
2408 char dbuf[INET6_ADDRSTRLEN];
2410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2411 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2412 (unsigned int) mlen,
2413 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2414 ts->destination_port,
2415 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2418 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2420 GNUNET_break_op (0);
2421 return GNUNET_SYSERR;
2427 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2428 + sizeof (struct GNUNET_TUN_TcpHeader)
2429 + sizeof (struct GNUNET_MessageHeader) +
2430 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2433 char buf[size] GNUNET_ALIGN;
2434 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2435 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2436 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2437 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2438 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2439 msg->size = htons (size);
2440 tun->flags = htons (0);
2441 tun->proto = htons (ETH_P_IPV4);
2442 GNUNET_TUN_initialize_ipv4_header (ipv4,
2444 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2445 &ts->destination_ip.v4,
2447 *tcp = data->tcp_header;
2448 tcp->source_port = htons (ts->destination_port);
2449 tcp->destination_port = htons (ts->source_port);
2450 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2457 (void) GNUNET_HELPER_send (helper_handle,
2466 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2467 + sizeof (struct GNUNET_TUN_TcpHeader)
2468 + sizeof (struct GNUNET_MessageHeader) +
2469 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2472 char buf[size] GNUNET_ALIGN;
2473 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2474 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2475 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2476 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2477 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2478 msg->size = htons (size);
2479 tun->flags = htons (0);
2480 tun->proto = htons (ETH_P_IPV6);
2481 GNUNET_TUN_initialize_ipv6_header (ipv6,
2483 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2484 &ts->destination_ip.v6,
2486 *tcp = data->tcp_header;
2487 tcp->source_port = htons (ts->destination_port);
2488 tcp->destination_port = htons (ts->source_port);
2489 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2496 (void) GNUNET_HELPER_send (helper_handle,
2504 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
2506 GNUNET_TIME_absolute_get ().abs_value);
2512 * Allocate an IPv4 address from the range of the tunnel
2513 * for a new redirection.
2515 * @param v4 where to store the address
2516 * @return GNUNET_OK on success,
2517 * GNUNET_SYSERR on error
2520 allocate_v4_address (struct in_addr *v4)
2522 const char *ipv4addr = vpn_argv[4];
2523 const char *ipv4mask = vpn_argv[5];
2524 struct in_addr addr;
2525 struct in_addr mask;
2527 struct GNUNET_HashCode key;
2530 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2531 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2532 /* Given 192.168.0.1/255.255.0.0, we want a mask
2533 of '192.168.255.255', thus: */
2534 mask.s_addr = addr.s_addr | ~mask.s_addr;
2541 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2542 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2543 return GNUNET_SYSERR;
2545 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2546 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2548 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2549 get_destination_key_from_ip (AF_INET,
2553 while ( (GNUNET_YES ==
2554 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2556 (v4->s_addr == addr.s_addr) ||
2557 (v4->s_addr == mask.s_addr) );
2563 * Allocate an IPv6 address from the range of the tunnel
2564 * for a new redirection.
2566 * @param v6 where to store the address
2567 * @return GNUNET_OK on success,
2568 * GNUNET_SYSERR on error
2571 allocate_v6_address (struct in6_addr *v6)
2573 const char *ipv6addr = vpn_argv[2];
2574 struct in6_addr addr;
2575 struct in6_addr mask;
2576 struct in6_addr rnd;
2578 struct GNUNET_HashCode key;
2581 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2582 GNUNET_assert (ipv6prefix < 128);
2583 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2586 for (i=127;i>=ipv6prefix;i--)
2587 mask.s6_addr[i / 8] |= (1 << (i % 8));
2589 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2596 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2597 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2598 return GNUNET_SYSERR;
2603 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2606 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2608 get_destination_key_from_ip (AF_INET6,
2612 while ( (GNUNET_YES ==
2613 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2617 sizeof (struct in6_addr))) ||
2620 sizeof (struct in6_addr))) );
2626 * Free resources occupied by a destination entry.
2628 * @param de entry to free
2631 free_destination_entry (struct DestinationEntry *de)
2633 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2634 "Cleaning up destination entry\n");
2635 GNUNET_STATISTICS_update (stats,
2636 gettext_noop ("# Active destinations"),
2640 free_tunnel_state (de->ts);
2641 GNUNET_assert (NULL == de->ts);
2643 if (NULL != de->heap_node)
2645 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2646 de->heap_node = NULL;
2647 GNUNET_assert (GNUNET_YES ==
2648 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2657 * We have too many active destinations. Clean up the oldest destination.
2659 * @param except destination that must NOT be cleaned up, even if it is the oldest
2662 expire_destination (struct DestinationEntry *except)
2664 struct DestinationEntry *de;
2666 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2667 GNUNET_assert (NULL != de);
2669 return; /* can't do this */
2670 free_destination_entry (de);
2675 * Allocate an IP address for the response.
2677 * @param result_af desired address family; set to the actual
2678 * address family; can initially be AF_UNSPEC if there
2679 * is no preference; will be set to AF_UNSPEC if the
2681 * @param addr set to either v4 or v6 depending on which
2682 * storage location was used; set to NULL if allocation failed
2683 * @param v4 storage space for an IPv4 address
2684 * @param v6 storage space for an IPv6 address
2685 * @return GNUNET_OK normally, GNUNET_SYSERR if '*result_af' was
2686 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2689 allocate_response_ip (int *result_af,
2692 struct in6_addr *v6)
2699 allocate_v4_address (v4))
2700 *result_af = AF_UNSPEC;
2706 allocate_v6_address (v6))
2707 *result_af = AF_UNSPEC;
2713 allocate_v4_address (v4))
2716 *result_af = AF_INET;
2718 else if (GNUNET_OK ==
2719 allocate_v6_address (v6))
2722 *result_af = AF_INET6;
2727 return GNUNET_SYSERR;
2734 * A client asks us to setup a redirection via some exit
2735 * node to a particular IP. Setup the redirection and
2736 * give the client the allocated IP.
2739 * @param client requesting client
2740 * @param message redirection request (a 'struct RedirectToIpRequestMessage')
2743 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2744 const struct GNUNET_MessageHeader *message)
2748 const struct RedirectToIpRequestMessage *msg;
2754 struct DestinationEntry *de;
2755 struct GNUNET_HashCode key;
2756 struct TunnelState *ts;
2758 /* validate and parse request */
2759 mlen = ntohs (message->size);
2760 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2763 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2766 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2767 msg = (const struct RedirectToIpRequestMessage *) message;
2768 addr_af = (int) htonl (msg->addr_af);
2772 if (alen != sizeof (struct in_addr))
2775 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2780 if (alen != sizeof (struct in6_addr))
2783 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2789 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2793 /* allocate response IP */
2794 result_af = (int) htonl (msg->result_af);
2795 if (GNUNET_OK != allocate_response_ip (&result_af,
2799 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2802 if ( (result_af == AF_UNSPEC) ||
2803 (GNUNET_NO == ntohl (msg->nac)) )
2805 /* send reply "instantly" */
2806 send_client_reply (client,
2811 if (result_af == AF_UNSPEC)
2813 /* failure, we're done */
2814 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2819 char sbuf[INET6_ADDRSTRLEN];
2820 char dbuf[INET6_ADDRSTRLEN];
2822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2823 "Allocated address %s for redirection via exit to %s\n",
2824 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2826 &msg[1], dbuf, sizeof (dbuf)));
2829 /* setup destination record */
2830 de = GNUNET_malloc (sizeof (struct DestinationEntry));
2831 de->is_service = GNUNET_NO;
2832 de->details.exit_destination.af = addr_af;
2833 memcpy (&de->details.exit_destination.ip,
2836 get_destination_key_from_ip (result_af,
2840 GNUNET_assert (GNUNET_OK ==
2841 GNUNET_CONTAINER_multihashmap_put (destination_map,
2844 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2845 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2847 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2848 GNUNET_STATISTICS_update (stats,
2849 gettext_noop ("# Active destinations"),
2851 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2852 expire_destination (de);
2854 /* setup tunnel to destination */
2855 ts = create_tunnel_to_destination (de,
2856 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2862 ts->destination_ip.v4 = v4;
2865 ts->destination_ip.v6 = v6;
2871 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2876 * A client asks us to setup a redirection to a particular peer
2877 * offering a service. Setup the redirection and give the client the
2881 * @param client requesting client
2882 * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
2885 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
2886 const struct GNUNET_MessageHeader *message)
2888 const struct RedirectToServiceRequestMessage *msg;
2893 struct DestinationEntry *de;
2894 struct GNUNET_HashCode key;
2895 struct TunnelState *ts;
2898 msg = (const struct RedirectToServiceRequestMessage *) message;
2900 /* allocate response IP */
2901 result_af = (int) htonl (msg->result_af);
2902 if (GNUNET_OK != allocate_response_ip (&result_af,
2906 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2909 if ( (result_af == AF_UNSPEC) ||
2910 (GNUNET_NO == ntohl (msg->nac)) )
2912 /* send reply "instantly" */
2913 send_client_reply (client,
2918 if (result_af == AF_UNSPEC)
2920 /* failure, we're done */
2921 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2922 _("Failed to allocate IP address for new destination\n"));
2923 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2928 char sbuf[INET6_ADDRSTRLEN];
2930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2931 "Allocated address %s for redirection to service %s on peer %s\n",
2932 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2933 GNUNET_h2s (&msg->service_descriptor),
2934 GNUNET_i2s (&msg->target));
2937 /* setup destination record */
2938 de = GNUNET_malloc (sizeof (struct DestinationEntry));
2939 de->is_service = GNUNET_YES;
2940 de->details.service_destination.service_descriptor = msg->service_descriptor;
2941 de->details.service_destination.target = msg->target;
2942 get_destination_key_from_ip (result_af,
2946 GNUNET_assert (GNUNET_OK ==
2947 GNUNET_CONTAINER_multihashmap_put (destination_map,
2950 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2951 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2953 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
2954 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2955 expire_destination (de);
2956 ts = create_tunnel_to_destination (de,
2957 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
2963 ts->destination_ip.v4 = v4;
2966 ts->destination_ip.v6 = v6;
2972 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2978 * Function called for inbound tunnels. As we don't offer
2979 * any mesh services, this function should never be called.
2981 * @param cls closure
2982 * @param tunnel new handle to the tunnel
2983 * @param initiator peer that started the tunnel
2984 * @param atsi performance information for the tunnel
2985 * @return initial tunnel context for the tunnel
2986 * (can be NULL -- that's not an error)
2989 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
2990 const struct GNUNET_PeerIdentity *initiator,
2991 const struct GNUNET_ATS_Information *atsi)
2993 /* How can and why should anyone open an inbound tunnel to vpn? */
3000 * Function called whenever an inbound tunnel is destroyed. Should clean up
3001 * any associated state.
3003 * @param cls closure (set from GNUNET_MESH_connect)
3004 * @param tunnel connection to the other end (henceforth invalid)
3005 * @param tunnel_ctx place where local state associated
3006 * with the tunnel is stored (our 'struct TunnelState')
3009 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
3011 /* we don't have inbound tunnels, so this function should never be called */
3017 * Free memory occupied by an entry in the destination map.
3021 * @param value a 'struct DestinationEntry *'
3022 * @return GNUNET_OK (continue to iterate)
3025 cleanup_destination (void *cls,
3026 const struct GNUNET_HashCode *key,
3029 struct DestinationEntry *de = value;
3031 free_destination_entry (de);
3037 * Free memory occupied by an entry in the tunnel map.
3041 * @param value a 'struct TunnelState *'
3042 * @return GNUNET_OK (continue to iterate)
3045 cleanup_tunnel (void *cls,
3046 const struct GNUNET_HashCode *key,
3049 struct TunnelState *ts = value;
3051 free_tunnel_state (ts);
3057 * Function scheduled as very last function, cleans up after us
3063 cleanup (void *cls GNUNET_UNUSED,
3064 const struct GNUNET_SCHEDULER_TaskContext *tc)
3068 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3069 "VPN is shutting down\n");
3070 if (NULL != destination_map)
3072 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
3073 &cleanup_destination,
3075 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
3076 destination_map = NULL;
3078 if (NULL != destination_heap)
3080 GNUNET_CONTAINER_heap_destroy (destination_heap);
3081 destination_heap = NULL;
3083 if (NULL != tunnel_map)
3085 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
3088 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
3091 if (NULL != tunnel_heap)
3093 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
3096 if (NULL != mesh_handle)
3098 GNUNET_MESH_disconnect (mesh_handle);
3101 if (NULL != helper_handle)
3103 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3104 helper_handle = NULL;
3108 GNUNET_SERVER_notification_context_destroy (nc);
3113 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3117 GNUNET_free_non_null (vpn_argv[i]);
3122 * A client disconnected, clean up all references to it.
3124 * @param cls the client that disconnected
3126 * @param value a 'struct TunnelState *'
3127 * @return GNUNET_OK (continue to iterate)
3130 cleanup_tunnel_client (void *cls,
3131 const struct GNUNET_HashCode *key,
3134 struct GNUNET_SERVER_Client *client = cls;
3135 struct TunnelState *ts = value;
3137 if (client == ts->client)
3139 GNUNET_SERVER_client_drop (ts->client);
3147 * A client disconnected, clean up all references to it.
3149 * @param cls the client that disconnected
3151 * @param value a 'struct DestinationEntry *'
3152 * @return GNUNET_OK (continue to iterate)
3155 cleanup_destination_client (void *cls,
3156 const struct GNUNET_HashCode *key,
3159 struct GNUNET_SERVER_Client *client = cls;
3160 struct DestinationEntry *de = value;
3161 struct TunnelState *ts;
3163 if (NULL == (ts = de->ts))
3165 if (client == ts->client)
3167 GNUNET_SERVER_client_drop (ts->client);
3175 * A client has disconnected from us. If we are currently building
3176 * a tunnel for it, cancel the operation.
3179 * @param client handle to the client that disconnected
3182 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
3184 if (NULL != tunnel_map)
3185 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
3186 &cleanup_tunnel_client,
3188 if (NULL != destination_map)
3189 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
3190 &cleanup_destination_client,
3196 * Main function that will be run by the scheduler.
3198 * @param cls closure
3199 * @param server the initialized server
3200 * @param cfg_ configuration
3204 struct GNUNET_SERVER_Handle *server,
3205 const struct GNUNET_CONFIGURATION_Handle *cfg_)
3207 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
3208 /* callback, cls, type, size */
3209 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
3210 { &service_redirect_to_service, NULL,
3211 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3212 sizeof (struct RedirectToServiceRequestMessage) },
3215 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
3216 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
3217 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
3218 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
3221 static const GNUNET_MESH_ApplicationType types[] = {
3222 GNUNET_APPLICATION_TYPE_END
3233 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
3236 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
3239 "`%s' is not SUID, refusing to run.\n",
3240 "gnunet-helper-vpn");
3241 GNUNET_free (binary);
3245 GNUNET_free (binary);
3247 stats = GNUNET_STATISTICS_create ("vpn", cfg);
3249 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
3250 &max_destination_mappings))
3251 max_destination_mappings = 200;
3253 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
3254 &max_tunnel_mappings))
3255 max_tunnel_mappings = 200;
3257 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
3258 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3259 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2, GNUNET_NO);
3260 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3263 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
3264 if (GNUNET_SYSERR ==
3265 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
3267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3268 "No entry 'IFNAME' in configuration!\n");
3269 GNUNET_SCHEDULER_shutdown ();
3272 vpn_argv[1] = ifname;
3273 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
3275 if ( (GNUNET_SYSERR ==
3276 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
3278 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
3280 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3281 "No valid entry 'IPV6ADDR' in configuration!\n");
3282 GNUNET_SCHEDULER_shutdown ();
3285 vpn_argv[2] = ipv6addr;
3286 if (GNUNET_SYSERR ==
3287 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
3290 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3291 "No entry 'IPV6PREFIX' in configuration!\n");
3292 GNUNET_SCHEDULER_shutdown ();
3295 vpn_argv[3] = ipv6prefix_s;
3297 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
3300 (ipv6prefix >= 127) )
3302 GNUNET_SCHEDULER_shutdown ();
3308 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3309 _("IPv6 support disabled as this system does not support IPv6\n"));
3310 vpn_argv[2] = GNUNET_strdup ("-");
3311 vpn_argv[3] = GNUNET_strdup ("-");
3313 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3315 if ( (GNUNET_SYSERR ==
3316 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3318 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3321 "No valid entry for 'IPV4ADDR' in configuration!\n");
3322 GNUNET_SCHEDULER_shutdown ();
3325 vpn_argv[4] = ipv4addr;
3326 if ( (GNUNET_SYSERR ==
3327 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3329 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3331 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3332 "No valid entry 'IPV4MASK' in configuration!\n");
3333 GNUNET_SCHEDULER_shutdown ();
3336 vpn_argv[5] = ipv4mask;
3340 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3341 _("IPv4 support disabled as this system does not support IPv4\n"));
3342 vpn_argv[4] = GNUNET_strdup ("-");
3343 vpn_argv[5] = GNUNET_strdup ("-");
3348 GNUNET_MESH_connect (cfg_, NULL,
3353 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3354 "gnunet-helper-vpn", vpn_argv,
3355 &message_token, NULL, NULL);
3356 nc = GNUNET_SERVER_notification_context_create (server, 1);
3357 GNUNET_SERVER_add_handlers (server, service_handlers);
3358 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
3359 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3364 * The main function of the VPN service.
3366 * @param argc number of arguments from the command line
3367 * @param argv command line arguments
3368 * @return 0 ok, 1 on error
3371 main (int argc, char *const *argv)
3373 return (GNUNET_OK ==
3374 GNUNET_SERVICE_run (argc, argv, "vpn",
3375 GNUNET_SERVICE_OPTION_NONE,
3376 &run, NULL)) ? global_ret : 1;
3379 /* end of gnunet-service-vpn.c */