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 channels ready as alternative exits /
31 * detect & recover from channel-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
54 * State we keep for each of our channels.
59 * Information we track for each IP address to determine which channel
60 * to send the traffic over to the destination.
62 struct DestinationEntry;
65 * List of channels we keep for each destination port for a given
68 struct DestinationChannel
74 struct DestinationChannel *next;
79 struct DestinationChannel *prev;
82 * Destination entry list this `struct DestinationChannel` belongs with.
84 struct DestinationEntry *destination;
87 * Pre-allocated channel for this destination, or NULL for none.
89 struct ChannelState *ts;
92 * Destination port this channel state is used for.
94 uint16_t destination_port;
100 * Information we track for each IP address to determine which channel
101 * to send the traffic over to the destination.
103 struct DestinationEntry
107 * Key under which this entry is in the 'destination_map' (only valid
108 * if 'heap_node != NULL').
110 struct GNUNET_HashCode key;
113 * Head of DLL of channels associated with this destination.
115 struct DestinationChannel *dt_head;
118 * Tail of DLL of channels associated with this destination.
120 struct DestinationChannel *dt_tail;
123 * Entry for this entry in the destination_heap.
125 struct GNUNET_CONTAINER_HeapNode *heap_node;
128 * #GNUNET_NO if this is a channel to an Internet-exit,
129 * #GNUNET_YES if this channel is to a service.
134 * Details about the connection (depending on is_service).
142 * The description of the service (only used for service channels).
144 struct GNUNET_HashCode service_descriptor;
147 * Peer offering the service.
149 struct GNUNET_PeerIdentity target;
151 } service_destination;
157 * Address family used (AF_INET or AF_INET6).
162 * IP address of the ultimate destination (only used for exit channels).
167 * Address if af is AF_INET.
172 * Address if af is AF_INET6.
185 * A messages we have in queue for a particular channel.
187 struct ChannelMessageQueueEntry
190 * This is a doubly-linked list.
192 struct ChannelMessageQueueEntry *next;
195 * This is a doubly-linked list.
197 struct ChannelMessageQueueEntry *prev;
200 * Number of bytes in 'msg'.
205 * Message to transmit, allocated at the end of this struct.
212 * State we keep for each of our channels.
218 * Information about the channel to use, NULL if no channel
219 * is available right now.
221 struct GNUNET_MESH_Channel *channel;
224 * Active query with REGEX to locate exit.
226 struct GNUNET_REGEX_Search *search;
229 * Active transmission handle, NULL for none.
231 struct GNUNET_MESH_TransmitHandle *th;
234 * Entry for this entry in the channel_heap, NULL as long as this
235 * channel state is not fully bound.
237 struct GNUNET_CONTAINER_HeapNode *heap_node;
240 * Head of list of messages scheduled for transmission.
242 struct ChannelMessageQueueEntry *tmq_head;
245 * Tail of list of messages scheduled for transmission.
247 struct ChannelMessageQueueEntry *tmq_tail;
250 * Destination entry that has a pointer to this channel state;
251 * NULL if this channel state is in the channel map.
253 struct DestinationChannel *destination_container;
256 * Destination to which this channel leads. Note that
257 * this struct is NOT in the destination_map (but a
258 * local copy) and that the 'heap_node' should always
261 struct DestinationEntry destination;
264 * Addess family used for this channel on the local TUN interface.
269 * Length of the doubly linked 'tmq_head/tmq_tail' list.
271 unsigned int tmq_length;
274 * IPPROTO_TCP or IPPROTO_UDP once bound.
279 * IP address of the source on our end, initially uninitialized.
284 * Address if af is AF_INET.
289 * Address if af is AF_INET6.
296 * Destination IP address used by the source on our end (this is the IP
297 * that we pick freely within the VPN's channel IP range).
302 * Address if af is AF_INET.
307 * Address if af is AF_INET6.
314 * Source port used by the sender on our end; 0 for uninitialized.
316 uint16_t source_port;
319 * Destination port used by the sender on our end; 0 for uninitialized.
321 uint16_t destination_port;
327 * Return value from 'main'.
329 static int global_ret;
332 * Configuration we use.
334 static const struct GNUNET_CONFIGURATION_Handle *cfg;
337 * Handle to the mesh service.
339 static struct GNUNET_MESH_Handle *mesh_handle;
342 * Map from IP address to destination information (possibly with a
343 * MESH channel handle for fast setup).
345 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
348 * Min-Heap sorted by activity time to expire old mappings.
350 static struct GNUNET_CONTAINER_Heap *destination_heap;
353 * Map from source and destination address (IP+port) to connection
354 * information (mostly with the respective MESH channel handle).
356 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
359 * Min-Heap sorted by activity time to expire old mappings; values are
360 * of type 'struct ChannelState'.
362 static struct GNUNET_CONTAINER_Heap *channel_heap;
367 static struct GNUNET_STATISTICS_Handle *stats;
370 * The handle to the VPN helper process "gnunet-helper-vpn".
372 static struct GNUNET_HELPER_Handle *helper_handle;
375 * Arguments to the vpn helper.
377 static char *vpn_argv[7];
380 * Length of the prefix of the VPN's IPv6 network.
382 static unsigned long long ipv6prefix;
385 * Notification context for sending replies to clients.
387 static struct GNUNET_SERVER_NotificationContext *nc;
390 * If there are more than this number of address-mappings, old ones
393 static unsigned long long max_destination_mappings;
396 * If there are more than this number of open channels, old ones
399 static unsigned long long max_channel_mappings;
403 * Compute the key under which we would store an entry in the
404 * destination_map for the given IP address.
406 * @param af address family (AF_INET or AF_INET6)
407 * @param address IP address, struct in_addr or struct in6_addr
408 * @param key where to store the key
411 get_destination_key_from_ip (int af,
413 struct GNUNET_HashCode *key)
418 GNUNET_CRYPTO_hash (address,
419 sizeof (struct in_addr),
423 GNUNET_CRYPTO_hash (address,
424 sizeof (struct in6_addr),
435 * Compute the key under which we would store an entry in the
436 * channel_map for the given socket address pair.
438 * @param af address family (AF_INET or AF_INET6)
439 * @param protocol IPPROTO_TCP or IPPROTO_UDP
440 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
441 * @param source_port sender's source port
442 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
443 * @param destination_port sender's destination port
444 * @param key where to store the key
447 get_channel_key_from_ips (int af,
449 const void *source_ip,
450 uint16_t source_port,
451 const void *destination_ip,
452 uint16_t destination_port,
453 struct GNUNET_HashCode *key)
457 memset (key, 0, sizeof (struct GNUNET_HashCode));
458 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
459 so we put the ports in there (and hope for few collisions) */
461 memcpy (off, &source_port, sizeof (uint16_t));
462 off += sizeof (uint16_t);
463 memcpy (off, &destination_port, sizeof (uint16_t));
464 off += sizeof (uint16_t);
468 memcpy (off, source_ip, sizeof (struct in_addr));
469 off += sizeof (struct in_addr);
470 memcpy (off, destination_ip, sizeof (struct in_addr));
471 off += sizeof (struct in_addr);
474 memcpy (off, source_ip, sizeof (struct in6_addr));
475 off += sizeof (struct in6_addr);
476 memcpy (off, destination_ip, sizeof (struct in6_addr));
477 off += sizeof (struct in6_addr);
483 memcpy (off, &protocol, sizeof (uint8_t));
484 /* off += sizeof (uint8_t); */
489 * Notify the client about the result of its request.
491 * @param client client to notify
492 * @param request_id original request ID to include in response
493 * @param result_af resulting address family
494 * @param addr resulting IP address
497 send_client_reply (struct GNUNET_SERVER_Client *client,
502 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN;
503 struct RedirectToIpResponseMessage *res;
509 rlen = sizeof (struct in_addr);
512 rlen = sizeof (struct in6_addr);
521 res = (struct RedirectToIpResponseMessage *) buf;
522 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
523 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
524 res->result_af = htonl (result_af);
525 res->request_id = request_id;
526 memcpy (&res[1], addr, rlen);
527 GNUNET_SERVER_notification_context_add (nc, client);
528 GNUNET_SERVER_notification_context_unicast (nc,
536 * Free resources associated with a channel state.
538 * @param ts state to free
541 free_channel_state (struct ChannelState *ts)
543 struct GNUNET_HashCode key;
544 struct ChannelMessageQueueEntry *tnq;
545 struct GNUNET_MESH_Channel *channel;
547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 "Cleaning up channel state\n");
549 GNUNET_STATISTICS_update (stats,
550 gettext_noop ("# Active channels"),
552 while (NULL != (tnq = ts->tmq_head))
554 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
560 GNUNET_assert (0 == ts->tmq_length);
563 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
566 GNUNET_assert (NULL == ts->destination.heap_node);
567 if (NULL != (channel = ts->channel))
570 GNUNET_MESH_channel_destroy (channel);
572 if (NULL != ts->search)
574 GNUNET_REGEX_search_cancel (ts->search);
577 if (NULL != ts->heap_node)
579 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
580 ts->heap_node = NULL;
581 get_channel_key_from_ips (ts->af,
586 ts->destination_port,
588 GNUNET_assert (GNUNET_YES ==
589 GNUNET_CONTAINER_multihashmap_remove (channel_map,
593 if (NULL != ts->destination_container)
595 GNUNET_assert (ts == ts->destination_container->ts);
596 ts->destination_container->ts = NULL;
597 ts->destination_container = NULL;
604 * Send a message from the message queue via mesh.
606 * @param cls the `struct ChannelState` with the message queue
607 * @param size number of bytes available in @a buf
608 * @param buf where to copy the message
609 * @return number of bytes copied to @a buf
612 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
614 struct ChannelState *ts = cls;
615 struct ChannelMessageQueueEntry *tnq;
622 GNUNET_assert (NULL != tnq);
623 GNUNET_assert (size >= tnq->len);
624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
625 "Sending %u bytes via mesh channel\n",
627 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
631 memcpy (buf, tnq->msg, tnq->len);
634 if (NULL != (tnq = ts->tmq_head))
635 ts->th = GNUNET_MESH_notify_transmit_ready (ts->channel,
636 GNUNET_NO /* cork */,
637 GNUNET_TIME_UNIT_FOREVER_REL,
639 &send_to_peer_notify_callback,
641 GNUNET_STATISTICS_update (stats,
642 gettext_noop ("# Bytes given to mesh for transmission"),
649 * Add the given message to the given channel and trigger the
650 * transmission process.
652 * @param tnq message to queue
653 * @param ts channel to queue the message for
656 send_to_channel (struct ChannelMessageQueueEntry *tnq,
657 struct ChannelState *ts)
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "Queueing %u bytes for transmission via mesh channel\n",
662 GNUNET_assert (NULL != ts->channel);
663 GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head,
667 if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE)
669 struct ChannelMessageQueueEntry *dq;
672 GNUNET_assert (dq != tnq);
673 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
677 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
679 GNUNET_STATISTICS_update (stats,
680 gettext_noop ("# Bytes dropped in mesh queue (overflow)"),
686 ts->th = GNUNET_MESH_notify_transmit_ready (ts->channel,
687 GNUNET_NO /* cork */,
688 GNUNET_TIME_UNIT_FOREVER_REL,
690 &send_to_peer_notify_callback,
696 * Regex has found a potential exit peer for us; consider using it.
698 * @param cls the 'struct ChannelState'
699 * @param id Peer providing a regex that matches the string.
700 * @param get_path Path of the get request.
701 * @param get_path_length Lenght of @a get_path.
702 * @param put_path Path of the put request.
703 * @param put_path_length Length of the @a put_path.
706 handle_regex_result (void *cls,
707 const struct GNUNET_PeerIdentity *id,
708 const struct GNUNET_PeerIdentity *get_path,
709 unsigned int get_path_length,
710 const struct GNUNET_PeerIdentity *put_path,
711 unsigned int put_path_length)
713 struct ChannelState *ts = cls;
714 unsigned int apptype;
716 GNUNET_REGEX_search_cancel (ts->search);
721 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
724 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
730 ts->channel = GNUNET_MESH_channel_create (mesh_handle,
740 * Initialize the given destination entry's mesh channel.
742 * @param dt destination channel for which we need to setup a channel
743 * @param client_af address family of the address returned to the client
744 * @return channel state of the channel that was created
746 static struct ChannelState *
747 create_channel_to_destination (struct DestinationChannel *dt,
750 struct ChannelState *ts;
751 unsigned int apptype;
753 GNUNET_STATISTICS_update (stats,
754 gettext_noop ("# Mesh channels created"),
756 GNUNET_assert (NULL == dt->ts);
760 apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
763 apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
769 ts = GNUNET_new (struct ChannelState);
771 ts->destination = *dt->destination;
772 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
774 ts->destination_container = dt; /* we are referenced from dt */
775 if (dt->destination->is_service)
777 ts->channel = GNUNET_MESH_channel_create (mesh_handle,
779 &dt->destination->details.service_destination.target,
783 if (NULL == ts->channel)
785 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
786 _("Failed to setup mesh channel!\n"));
790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
791 "Creating channel to peer %s offering service %s\n",
792 GNUNET_i2s (&dt->destination->details.service_destination.target),
793 GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor));
799 switch (dt->destination->details.exit_destination.af)
803 char address[GNUNET_TUN_IPV4_REGEXLEN];
805 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
806 dt->destination_port,
808 GNUNET_asprintf (&policy, "%s%s",
809 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
815 char address[GNUNET_TUN_IPV6_REGEXLEN];
817 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
818 dt->destination_port,
820 GNUNET_asprintf (&policy, "%s%s",
821 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "Requesting connect by string: %s\n",
833 ts->search = GNUNET_REGEX_search (cfg,
835 &handle_regex_result,
837 GNUNET_free (policy);
844 * We have too many active channels. Clean up the oldest channel.
846 * @param except channel that must NOT be cleaned up, even if it is the oldest
849 expire_channel (struct ChannelState *except)
851 struct ChannelState *ts;
853 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
854 GNUNET_assert (NULL != ts);
856 return; /* can't do this */
857 free_channel_state (ts);
862 * Route a packet via mesh to the given destination.
864 * @param destination description of the destination
865 * @param af address family on this end (AF_INET or AF_INET6)
866 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
867 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
868 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
869 * @param payload payload of the packet after the IP header
870 * @param payload_length number of bytes in @a payload
873 route_packet (struct DestinationEntry *destination,
876 const void *source_ip,
877 const void *destination_ip,
879 size_t payload_length)
881 struct GNUNET_HashCode key;
882 struct ChannelState *ts;
883 struct ChannelMessageQueueEntry *tnq;
887 const struct GNUNET_TUN_UdpHeader *udp;
888 const struct GNUNET_TUN_TcpHeader *tcp;
889 const struct GNUNET_TUN_IcmpHeader *icmp;
890 struct DestinationChannel *dt;
891 uint16_t source_port;
892 uint16_t destination_port;
898 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
904 tcp = NULL; /* make compiler happy */
905 icmp = NULL; /* make compiler happy */
907 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
912 source_port = ntohs (udp->source_port);
913 destination_port = ntohs (udp->destination_port);
914 get_channel_key_from_ips (af,
925 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
931 udp = NULL; /* make compiler happy */
932 icmp = NULL; /* make compiler happy */
934 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
939 source_port = ntohs (tcp->source_port);
940 destination_port = ntohs (tcp->destination_port);
941 get_channel_key_from_ips (af,
953 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
958 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
964 tcp = NULL; /* make compiler happy */
965 udp = NULL; /* make compiler happy */
968 destination_port = 0;
969 get_channel_key_from_ips (af,
979 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
980 _("Protocol %u not supported, dropping\n"),
981 (unsigned int) protocol);
985 if (! destination->is_service)
987 switch (destination->details.exit_destination.af)
990 alen = sizeof (struct in_addr);
993 alen = sizeof (struct in6_addr);
1000 char sbuf[INET6_ADDRSTRLEN];
1001 char dbuf[INET6_ADDRSTRLEN];
1002 char xbuf[INET6_ADDRSTRLEN];
1004 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1005 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
1006 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1007 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1009 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1011 inet_ntop (destination->details.exit_destination.af,
1012 &destination->details.exit_destination.ip,
1013 xbuf, sizeof (xbuf)),
1016 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1017 if (dt->destination_port == destination_port)
1023 char sbuf[INET6_ADDRSTRLEN];
1024 char dbuf[INET6_ADDRSTRLEN];
1026 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1027 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
1028 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1029 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
1031 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
1033 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1034 GNUNET_i2s (&destination->details.service_destination.target));
1036 dt = destination->dt_head;
1040 dt = GNUNET_new (struct DestinationChannel);
1041 dt->destination = destination;
1042 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1043 destination->dt_tail,
1045 dt->destination_port = destination_port;
1048 /* see if we have an existing channel for this destination */
1049 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1053 /* need to either use the existing channel from the destination (if still
1054 available) or create a fresh one */
1055 is_new = GNUNET_YES;
1057 ts = create_channel_to_destination (dt, af);
1063 ts->destination_container = NULL; /* no longer 'contained' */
1064 /* now bind existing "unbound" channel to our IP/port tuple */
1065 ts->protocol = protocol;
1069 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1070 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1074 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1075 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1077 ts->source_port = source_port;
1078 ts->destination_port = destination_port;
1079 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1081 GNUNET_TIME_absolute_get ().abs_value_us);
1082 GNUNET_assert (GNUNET_YES ==
1083 GNUNET_CONTAINER_multihashmap_put (channel_map,
1086 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1087 GNUNET_STATISTICS_update (stats,
1088 gettext_noop ("# Active channels"),
1090 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1091 expire_channel (ts);
1096 GNUNET_CONTAINER_heap_update_cost (channel_heap,
1098 GNUNET_TIME_absolute_get ().abs_value_us);
1100 GNUNET_assert (NULL != ts->channel);
1102 /* send via channel */
1106 if (destination->is_service)
1108 struct GNUNET_EXIT_UdpServiceMessage *usm;
1110 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1111 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1112 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1117 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1120 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
1121 usm->header.size = htons ((uint16_t) mlen);
1122 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1123 /* if the source port is below 32000, we assume it has a special
1124 meaning; if not, we pick a random port (this is a heuristic) */
1125 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1126 usm->destination_port = udp->destination_port;
1127 usm->service_descriptor = destination->details.service_destination.service_descriptor;
1130 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1134 struct GNUNET_EXIT_UdpInternetMessage *uim;
1135 struct in_addr *ip4dst;
1136 struct in6_addr *ip6dst;
1139 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1140 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1141 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1146 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1149 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
1150 uim->header.size = htons ((uint16_t) mlen);
1151 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1152 uim->af = htonl (destination->details.exit_destination.af);
1153 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1154 uim->destination_port = udp->destination_port;
1155 switch (destination->details.exit_destination.af)
1158 ip4dst = (struct in_addr *) &uim[1];
1159 *ip4dst = destination->details.exit_destination.ip.v4;
1160 payload = &ip4dst[1];
1163 ip6dst = (struct in6_addr *) &uim[1];
1164 *ip6dst = destination->details.exit_destination.ip.v6;
1165 payload = &ip6dst[1];
1172 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1178 if (destination->is_service)
1180 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1182 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1183 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1184 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1189 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1192 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
1193 tsm->header.size = htons ((uint16_t) mlen);
1194 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1195 tsm->reserved = htonl (0);
1196 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
1197 tsm->tcp_header = *tcp;
1200 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1204 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1205 struct in_addr *ip4dst;
1206 struct in6_addr *ip6dst;
1209 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1210 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1211 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1216 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1219 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
1220 tim->header.size = htons ((uint16_t) mlen);
1221 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1222 tim->af = htonl (destination->details.exit_destination.af);
1223 tim->tcp_header = *tcp;
1224 switch (destination->details.exit_destination.af)
1227 ip4dst = (struct in_addr *) &tim[1];
1228 *ip4dst = destination->details.exit_destination.ip.v4;
1229 payload = &ip4dst[1];
1232 ip6dst = (struct in6_addr *) &tim[1];
1233 *ip6dst = destination->details.exit_destination.ip.v6;
1234 payload = &ip6dst[1];
1241 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1246 struct GNUNET_EXIT_TcpDataMessage *tdm;
1248 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1249 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1250 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1255 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1258 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1259 tdm->header.size = htons ((uint16_t) mlen);
1260 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1261 tdm->reserved = htonl (0);
1262 tdm->tcp_header = *tcp;
1265 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1269 case IPPROTO_ICMPV6:
1270 if (destination->is_service)
1272 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1274 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1275 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1276 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1281 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1283 ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1];
1284 ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
1285 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
1286 ism->service_descriptor = destination->details.service_destination.service_descriptor;
1287 ism->icmp_header = *icmp;
1288 /* ICMP protocol translation will be done by the receiver (as we don't know
1289 the target AF); however, we still need to possibly discard the payload
1290 depending on the ICMP type */
1296 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1297 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1299 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1300 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1301 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1302 /* throw away ICMP payload, won't be useful for the other side anyway */
1303 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1306 GNUNET_STATISTICS_update (stats,
1307 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
1311 /* end of AF_INET */
1316 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1317 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1318 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1319 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1320 /* throw away ICMP payload, won't be useful for the other side anyway */
1321 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1323 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1324 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1327 GNUNET_STATISTICS_update (stats,
1328 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
1332 /* end of AF_INET6 */
1339 /* update length calculations, as payload_length may have changed */
1340 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
1341 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1343 ism->header.size = htons ((uint16_t) mlen);
1344 /* finally, copy payload (if there is any left...) */
1347 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1351 struct GNUNET_EXIT_IcmpInternetMessage *iim;
1352 struct in_addr *ip4dst;
1353 struct in6_addr *ip6dst;
1356 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1357 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1358 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1363 tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen);
1365 iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1];
1366 iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
1367 iim->icmp_header = *icmp;
1368 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
1369 and throw away ICMP payload depending on ICMP message type */
1375 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1376 if (destination->details.exit_destination.af == AF_INET6)
1377 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1379 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1380 if (destination->details.exit_destination.af == AF_INET6)
1381 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1383 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1384 if (destination->details.exit_destination.af == AF_INET6)
1385 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1386 /* throw away IP-payload, exit will have to make it up anyway */
1387 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1389 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1390 if (destination->details.exit_destination.af == AF_INET6)
1391 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1392 /* throw away IP-payload, exit will have to make it up anyway */
1393 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1395 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1396 if (destination->details.exit_destination.af == AF_INET6)
1398 GNUNET_STATISTICS_update (stats,
1399 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1404 /* throw away IP-payload, exit will have to make it up anyway */
1405 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1408 GNUNET_STATISTICS_update (stats,
1409 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1414 /* end of AF_INET */
1419 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1420 if (destination->details.exit_destination.af == AF_INET6)
1421 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1422 /* throw away IP-payload, exit will have to make it up anyway */
1423 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1425 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1426 if (destination->details.exit_destination.af == AF_INET)
1427 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1428 /* throw away IP-payload, exit will have to make it up anyway */
1429 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1431 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1432 if (destination->details.exit_destination.af == AF_INET)
1434 GNUNET_STATISTICS_update (stats,
1435 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1440 /* throw away IP-payload, exit will have to make it up anyway */
1441 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1443 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1444 if (destination->details.exit_destination.af == AF_INET)
1446 GNUNET_STATISTICS_update (stats,
1447 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1452 /* throw away IP-payload, exit will have to make it up anyway */
1453 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
1455 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1456 if (destination->details.exit_destination.af == AF_INET)
1457 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1459 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1460 if (destination->details.exit_destination.af == AF_INET)
1461 iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1464 GNUNET_STATISTICS_update (stats,
1465 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1470 /* end of AF_INET6 */
1475 /* update length calculations, as payload_length may have changed */
1476 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
1477 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
1479 iim->header.size = htons ((uint16_t) mlen);
1481 /* need to tell destination ICMP protocol family! */
1482 iim->af = htonl (destination->details.exit_destination.af);
1483 switch (destination->details.exit_destination.af)
1486 ip4dst = (struct in_addr *) &iim[1];
1487 *ip4dst = destination->details.exit_destination.ip.v4;
1488 payload = &ip4dst[1];
1491 ip6dst = (struct in6_addr *) &iim[1];
1492 *ip6dst = destination->details.exit_destination.ip.v6;
1493 payload = &ip6dst[1];
1500 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
1504 /* not supported above, how can we get here !? */
1508 send_to_channel (tnq, ts);
1513 * Receive packets from the helper-process (someone send to the local
1514 * virtual channel interface). Find the destination mapping, and if it
1515 * exists, identify the correct MESH channel (or possibly create it)
1516 * and forward the packet.
1518 * @param cls closure, NULL
1519 * @param client NULL
1520 * @param message message we got from the client (VPN channel interface)
1523 message_token (void *cls,
1525 const struct GNUNET_MessageHeader *message)
1527 const struct GNUNET_TUN_Layer2PacketHeader *tun;
1529 struct GNUNET_HashCode key;
1530 struct DestinationEntry *de;
1532 GNUNET_STATISTICS_update (stats,
1533 gettext_noop ("# Packets received from TUN interface"),
1535 mlen = ntohs (message->size);
1536 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1537 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
1542 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1543 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
1544 switch (ntohs (tun->proto))
1548 const struct GNUNET_TUN_IPv6Header *pkt6;
1550 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
1556 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
1557 get_destination_key_from_ip (AF_INET6,
1558 &pkt6->destination_address,
1560 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1563 char buf[INET6_ADDRSTRLEN];
1565 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1566 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1567 inet_ntop (AF_INET6,
1568 &pkt6->destination_address,
1576 &pkt6->source_address,
1577 &pkt6->destination_address,
1579 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
1584 struct GNUNET_TUN_IPv4Header *pkt4;
1586 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
1592 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1593 get_destination_key_from_ip (AF_INET,
1594 &pkt4->destination_address,
1596 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1599 char buf[INET_ADDRSTRLEN];
1601 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1602 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1604 &pkt4->destination_address,
1609 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1611 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1612 _("Received IPv4 packet with options (dropping it)\n"));
1618 &pkt4->source_address,
1619 &pkt4->destination_address,
1621 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
1625 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1626 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1627 (unsigned int) ntohs (tun->proto));
1635 * Synthesize a plausible ICMP payload for an ICMP error
1636 * response on the given channel.
1638 * @param ts channel information
1639 * @param ipp IPv4 header to fill in (ICMP payload)
1640 * @param udp "UDP" header to fill in (ICMP payload); might actually
1641 * also be the first 8 bytes of the TCP header
1644 make_up_icmpv4_payload (struct ChannelState *ts,
1645 struct GNUNET_TUN_IPv4Header *ipp,
1646 struct GNUNET_TUN_UdpHeader *udp)
1648 GNUNET_TUN_initialize_ipv4_header (ipp,
1650 sizeof (struct GNUNET_TUN_TcpHeader),
1652 &ts->destination_ip.v4);
1653 udp->source_port = htons (ts->source_port);
1654 udp->destination_port = htons (ts->destination_port);
1655 udp->len = htons (0);
1656 udp->crc = htons (0);
1661 * Synthesize a plausible ICMP payload for an ICMP error
1662 * response on the given channel.
1664 * @param ts channel information
1665 * @param ipp IPv6 header to fill in (ICMP payload)
1666 * @param udp "UDP" header to fill in (ICMP payload); might actually
1667 * also be the first 8 bytes of the TCP header
1670 make_up_icmpv6_payload (struct ChannelState *ts,
1671 struct GNUNET_TUN_IPv6Header *ipp,
1672 struct GNUNET_TUN_UdpHeader *udp)
1674 GNUNET_TUN_initialize_ipv6_header (ipp,
1676 sizeof (struct GNUNET_TUN_TcpHeader),
1678 &ts->destination_ip.v6);
1679 udp->source_port = htons (ts->source_port);
1680 udp->destination_port = htons (ts->destination_port);
1681 udp->len = htons (0);
1682 udp->crc = htons (0);
1687 * We got an ICMP packet back from the MESH channel. Pass it on to the
1688 * local virtual interface via the helper.
1690 * @param cls closure, NULL
1691 * @param channel connection to the other end
1692 * @param channel_ctx pointer to our 'struct ChannelState *'
1693 * @param message the actual message
1694 * @return #GNUNET_OK to keep the connection open,
1695 * #GNUNET_SYSERR to close it (signal serious error)
1698 receive_icmp_back (void *cls,
1699 struct GNUNET_MESH_Channel *channel,
1701 const struct GNUNET_MessageHeader *message)
1703 struct ChannelState *ts = *channel_ctx;
1704 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
1707 GNUNET_STATISTICS_update (stats,
1708 gettext_noop ("# ICMP packets received from mesh"),
1710 mlen = ntohs (message->size);
1711 if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage))
1713 GNUNET_break_op (0);
1714 return GNUNET_SYSERR;
1716 if (NULL == ts->heap_node)
1718 GNUNET_break_op (0);
1719 return GNUNET_SYSERR;
1721 if (AF_UNSPEC == ts->af)
1723 GNUNET_break_op (0);
1724 return GNUNET_SYSERR;
1726 i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message;
1727 mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
1729 char sbuf[INET6_ADDRSTRLEN];
1730 char dbuf[INET6_ADDRSTRLEN];
1732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1733 "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n",
1734 (unsigned int) mlen,
1735 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1736 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
1742 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1743 + sizeof (struct GNUNET_TUN_IcmpHeader)
1744 + sizeof (struct GNUNET_MessageHeader) +
1745 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1748 /* reserve some extra space in case we have an ICMP type here where
1749 we will need to make up the payload ourselves */
1750 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
1751 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1752 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1753 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1754 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
1755 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1756 tun->flags = htons (0);
1757 tun->proto = htons (ETH_P_IPV4);
1758 GNUNET_TUN_initialize_ipv4_header (ipv4,
1760 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1761 &ts->destination_ip.v4,
1763 *icmp = i2v->icmp_header;
1767 /* For some ICMP types, we need to adjust (make up) the payload here.
1768 Also, depending on the AF used on the other side, we have to
1769 do ICMP PT (translate ICMP types) */
1770 switch (ntohl (i2v->af))
1775 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1776 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1778 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1779 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1780 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1782 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1783 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1787 /* sender did not strip ICMP payload? */
1788 GNUNET_break_op (0);
1789 return GNUNET_SYSERR;
1791 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1792 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1793 make_up_icmpv4_payload (ts, ipp, udp);
1797 GNUNET_break_op (0);
1798 GNUNET_STATISTICS_update (stats,
1799 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1801 return GNUNET_SYSERR;
1806 /* ICMP PT 6-to-4 and possibly making up payloads */
1809 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1810 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
1812 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1813 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1817 /* sender did not strip ICMP payload? */
1818 GNUNET_break_op (0);
1819 return GNUNET_SYSERR;
1821 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1822 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1823 make_up_icmpv4_payload (ts, ipp, udp);
1826 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1827 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
1829 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
1830 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1834 /* sender did not strip ICMP payload? */
1835 GNUNET_break_op (0);
1836 return GNUNET_SYSERR;
1838 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
1839 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1840 make_up_icmpv4_payload (ts, ipp, udp);
1843 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1844 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1845 GNUNET_STATISTICS_update (stats,
1846 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
1849 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1850 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
1852 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1853 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
1856 GNUNET_break_op (0);
1857 GNUNET_STATISTICS_update (stats,
1858 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1860 return GNUNET_SYSERR;
1865 GNUNET_break_op (0);
1866 return GNUNET_SYSERR;
1868 msg->size = htons (size);
1869 GNUNET_TUN_calculate_icmp_checksum (icmp,
1872 (void) GNUNET_HELPER_send (helper_handle,
1881 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1882 + sizeof (struct GNUNET_TUN_IcmpHeader)
1883 + sizeof (struct GNUNET_MessageHeader) +
1884 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1887 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
1888 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1889 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1890 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1891 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
1892 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1893 tun->flags = htons (0);
1894 tun->proto = htons (ETH_P_IPV6);
1895 GNUNET_TUN_initialize_ipv6_header (ipv6,
1897 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
1898 &ts->destination_ip.v6,
1900 *icmp = i2v->icmp_header;
1905 /* For some ICMP types, we need to adjust (make up) the payload here.
1906 Also, depending on the AF used on the other side, we have to
1907 do ICMP PT (translate ICMP types) */
1908 switch (ntohl (i2v->af))
1911 /* ICMP PT 4-to-6 and possibly making up payloads */
1914 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1915 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
1917 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1918 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
1920 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1921 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
1923 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1924 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1928 /* sender did not strip ICMP payload? */
1929 GNUNET_break_op (0);
1930 return GNUNET_SYSERR;
1932 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1933 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1934 make_up_icmpv6_payload (ts, ipp, udp);
1937 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1938 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
1940 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1941 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1945 /* sender did not strip ICMP payload? */
1946 GNUNET_break_op (0);
1947 return GNUNET_SYSERR;
1949 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1950 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1951 make_up_icmpv6_payload (ts, ipp, udp);
1954 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1955 GNUNET_STATISTICS_update (stats,
1956 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1960 GNUNET_break_op (0);
1961 GNUNET_STATISTICS_update (stats,
1962 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1964 return GNUNET_SYSERR;
1971 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1972 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1973 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1974 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1976 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1977 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1981 /* sender did not strip ICMP payload? */
1982 GNUNET_break_op (0);
1983 return GNUNET_SYSERR;
1985 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1986 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1987 make_up_icmpv6_payload (ts, ipp, udp);
1990 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1993 GNUNET_break_op (0);
1994 GNUNET_STATISTICS_update (stats,
1995 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1997 return GNUNET_SYSERR;
2002 GNUNET_break_op (0);
2003 return GNUNET_SYSERR;
2005 msg->size = htons (size);
2006 GNUNET_TUN_calculate_icmp_checksum (icmp,
2008 (void) GNUNET_HELPER_send (helper_handle,
2018 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2020 GNUNET_TIME_absolute_get ().abs_value_us);
2026 * We got a UDP packet back from the MESH channel. Pass it on to the
2027 * local virtual interface via the helper.
2029 * @param cls closure, NULL
2030 * @param channel connection to the other end
2031 * @param channel_ctx pointer to our 'struct ChannelState *'
2032 * @param message the actual message
2033 * @return #GNUNET_OK to keep the connection open,
2034 * #GNUNET_SYSERR to close it (signal serious error)
2037 receive_udp_back (void *cls,
2038 struct GNUNET_MESH_Channel *channel,
2040 const struct GNUNET_MessageHeader *message)
2042 struct ChannelState *ts = *channel_ctx;
2043 const struct GNUNET_EXIT_UdpReplyMessage *reply;
2046 GNUNET_STATISTICS_update (stats,
2047 gettext_noop ("# UDP packets received from mesh"),
2049 mlen = ntohs (message->size);
2050 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
2052 GNUNET_break_op (0);
2053 return GNUNET_SYSERR;
2055 if (NULL == ts->heap_node)
2057 GNUNET_break_op (0);
2058 return GNUNET_SYSERR;
2060 if (AF_UNSPEC == ts->af)
2062 GNUNET_break_op (0);
2063 return GNUNET_SYSERR;
2065 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
2066 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
2068 char sbuf[INET6_ADDRSTRLEN];
2069 char dbuf[INET6_ADDRSTRLEN];
2071 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2072 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2073 (unsigned int) mlen,
2074 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2075 ts->destination_port,
2076 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2083 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2084 + sizeof (struct GNUNET_TUN_UdpHeader)
2085 + sizeof (struct GNUNET_MessageHeader) +
2086 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2089 char buf[size] GNUNET_ALIGN;
2090 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2091 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2092 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2093 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2094 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2095 msg->size = htons (size);
2096 tun->flags = htons (0);
2097 tun->proto = htons (ETH_P_IPV4);
2098 GNUNET_TUN_initialize_ipv4_header (ipv4,
2100 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2101 &ts->destination_ip.v4,
2103 if (0 == ntohs (reply->source_port))
2104 udp->source_port = htons (ts->destination_port);
2106 udp->source_port = reply->source_port;
2107 if (0 == ntohs (reply->destination_port))
2108 udp->destination_port = htons (ts->source_port);
2110 udp->destination_port = reply->destination_port;
2111 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2112 GNUNET_TUN_calculate_udp4_checksum (ipv4,
2119 (void) GNUNET_HELPER_send (helper_handle,
2128 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2129 + sizeof (struct GNUNET_TUN_UdpHeader)
2130 + sizeof (struct GNUNET_MessageHeader) +
2131 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2134 char buf[size] GNUNET_ALIGN;
2135 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2136 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2137 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2138 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2139 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2140 msg->size = htons (size);
2141 tun->flags = htons (0);
2142 tun->proto = htons (ETH_P_IPV6);
2143 GNUNET_TUN_initialize_ipv6_header (ipv6,
2145 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
2146 &ts->destination_ip.v6,
2148 if (0 == ntohs (reply->source_port))
2149 udp->source_port = htons (ts->destination_port);
2151 udp->source_port = reply->source_port;
2152 if (0 == ntohs (reply->destination_port))
2153 udp->destination_port = htons (ts->source_port);
2155 udp->destination_port = reply->destination_port;
2156 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
2157 GNUNET_TUN_calculate_udp6_checksum (ipv6,
2163 (void) GNUNET_HELPER_send (helper_handle,
2173 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2175 GNUNET_TIME_absolute_get ().abs_value_us);
2181 * We got a TCP packet back from the MESH channel. Pass it on to the
2182 * local virtual interface via the helper.
2184 * @param cls closure, NULL
2185 * @param channel connection to the other end
2186 * @param channel_ctx pointer to our `struct ChannelState *`
2187 * @param message the actual message
2188 * @return #GNUNET_OK to keep the connection open,
2189 * #GNUNET_SYSERR to close it (signal serious error)
2192 receive_tcp_back (void *cls,
2193 struct GNUNET_MESH_Channel *channel,
2195 const struct GNUNET_MessageHeader *message)
2197 struct ChannelState *ts = *channel_ctx;
2198 const struct GNUNET_EXIT_TcpDataMessage *data;
2201 GNUNET_STATISTICS_update (stats,
2202 gettext_noop ("# TCP packets received from mesh"),
2204 mlen = ntohs (message->size);
2205 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2207 GNUNET_break_op (0);
2208 return GNUNET_SYSERR;
2210 if (NULL == ts->heap_node)
2212 GNUNET_break_op (0);
2213 return GNUNET_SYSERR;
2215 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
2216 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2218 char sbuf[INET6_ADDRSTRLEN];
2219 char dbuf[INET6_ADDRSTRLEN];
2221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2222 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
2223 (unsigned int) mlen,
2224 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
2225 ts->destination_port,
2226 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
2229 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2231 GNUNET_break_op (0);
2232 return GNUNET_SYSERR;
2238 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
2239 + sizeof (struct GNUNET_TUN_TcpHeader)
2240 + sizeof (struct GNUNET_MessageHeader) +
2241 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2244 char buf[size] GNUNET_ALIGN;
2245 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2246 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2247 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2248 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
2249 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2250 msg->size = htons (size);
2251 tun->flags = htons (0);
2252 tun->proto = htons (ETH_P_IPV4);
2253 GNUNET_TUN_initialize_ipv4_header (ipv4,
2255 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2256 &ts->destination_ip.v4,
2258 *tcp = data->tcp_header;
2259 tcp->source_port = htons (ts->destination_port);
2260 tcp->destination_port = htons (ts->source_port);
2261 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
2268 (void) GNUNET_HELPER_send (helper_handle,
2277 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
2278 + sizeof (struct GNUNET_TUN_TcpHeader)
2279 + sizeof (struct GNUNET_MessageHeader) +
2280 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
2283 char buf[size] GNUNET_ALIGN;
2284 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
2285 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
2286 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
2287 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
2288 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2289 msg->size = htons (size);
2290 tun->flags = htons (0);
2291 tun->proto = htons (ETH_P_IPV6);
2292 GNUNET_TUN_initialize_ipv6_header (ipv6,
2294 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
2295 &ts->destination_ip.v6,
2297 *tcp = data->tcp_header;
2298 tcp->source_port = htons (ts->destination_port);
2299 tcp->destination_port = htons (ts->source_port);
2300 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
2307 (void) GNUNET_HELPER_send (helper_handle,
2315 GNUNET_CONTAINER_heap_update_cost (channel_heap,
2317 GNUNET_TIME_absolute_get ().abs_value_us);
2323 * Allocate an IPv4 address from the range of the channel
2324 * for a new redirection.
2326 * @param v4 where to store the address
2327 * @return #GNUNET_OK on success,
2328 * #GNUNET_SYSERR on error
2331 allocate_v4_address (struct in_addr *v4)
2333 const char *ipv4addr = vpn_argv[4];
2334 const char *ipv4mask = vpn_argv[5];
2335 struct in_addr addr;
2336 struct in_addr mask;
2338 struct GNUNET_HashCode key;
2341 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2342 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2343 /* Given 192.168.0.1/255.255.0.0, we want a mask
2344 of '192.168.255.255', thus: */
2345 mask.s_addr = addr.s_addr | ~mask.s_addr;
2352 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2353 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2354 return GNUNET_SYSERR;
2356 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2357 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2359 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2360 get_destination_key_from_ip (AF_INET,
2364 while ( (GNUNET_YES ==
2365 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2367 (v4->s_addr == addr.s_addr) ||
2368 (v4->s_addr == mask.s_addr) );
2374 * Allocate an IPv6 address from the range of the channel
2375 * for a new redirection.
2377 * @param v6 where to store the address
2378 * @return #GNUNET_OK on success,
2379 * #GNUNET_SYSERR on error
2382 allocate_v6_address (struct in6_addr *v6)
2384 const char *ipv6addr = vpn_argv[2];
2385 struct in6_addr addr;
2386 struct in6_addr mask;
2387 struct in6_addr rnd;
2389 struct GNUNET_HashCode key;
2392 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2393 GNUNET_assert (ipv6prefix < 128);
2394 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2397 for (i=127;i>=ipv6prefix;i--)
2398 mask.s6_addr[i / 8] |= (1 << (i % 8));
2400 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2407 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2408 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2409 return GNUNET_SYSERR;
2414 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2417 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2419 get_destination_key_from_ip (AF_INET6,
2423 while ( (GNUNET_YES ==
2424 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2428 sizeof (struct in6_addr))) ||
2431 sizeof (struct in6_addr))) );
2437 * Free resources occupied by a destination entry.
2439 * @param de entry to free
2442 free_destination_entry (struct DestinationEntry *de)
2444 struct DestinationChannel *dt;
2446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2447 "Cleaning up destination entry\n");
2448 GNUNET_STATISTICS_update (stats,
2449 gettext_noop ("# Active destinations"),
2451 while (NULL != (dt = de->dt_head))
2455 free_channel_state (dt->ts);
2456 GNUNET_assert (NULL == dt->ts);
2458 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2463 if (NULL != de->heap_node)
2465 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2466 de->heap_node = NULL;
2467 GNUNET_assert (GNUNET_YES ==
2468 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2477 * We have too many active destinations. Clean up the oldest destination.
2479 * @param except destination that must NOT be cleaned up, even if it is the oldest
2482 expire_destination (struct DestinationEntry *except)
2484 struct DestinationEntry *de;
2486 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2487 GNUNET_assert (NULL != de);
2489 return; /* can't do this */
2490 free_destination_entry (de);
2495 * Allocate an IP address for the response.
2497 * @param result_af desired address family; set to the actual
2498 * address family; can initially be AF_UNSPEC if there
2499 * is no preference; will be set to AF_UNSPEC if the
2501 * @param addr set to either v4 or v6 depending on which
2502 * storage location was used; set to NULL if allocation failed
2503 * @param v4 storage space for an IPv4 address
2504 * @param v6 storage space for an IPv6 address
2505 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2506 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2509 allocate_response_ip (int *result_af,
2512 struct in6_addr *v6)
2519 allocate_v4_address (v4))
2520 *result_af = AF_UNSPEC;
2526 allocate_v6_address (v6))
2527 *result_af = AF_UNSPEC;
2533 allocate_v4_address (v4))
2536 *result_af = AF_INET;
2538 else if (GNUNET_OK ==
2539 allocate_v6_address (v6))
2542 *result_af = AF_INET6;
2547 return GNUNET_SYSERR;
2554 * A client asks us to setup a redirection via some exit node to a
2555 * particular IP. Setup the redirection and give the client the
2559 * @param client requesting client
2560 * @param message redirection request (a `struct RedirectToIpRequestMessage`)
2563 service_redirect_to_ip (void *cls,
2564 struct GNUNET_SERVER_Client *client,
2565 const struct GNUNET_MessageHeader *message)
2569 const struct RedirectToIpRequestMessage *msg;
2575 struct DestinationEntry *de;
2576 struct GNUNET_HashCode key;
2578 /* validate and parse request */
2579 mlen = ntohs (message->size);
2580 if (mlen < sizeof (struct RedirectToIpRequestMessage))
2583 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2586 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
2587 msg = (const struct RedirectToIpRequestMessage *) message;
2588 addr_af = (int) htonl (msg->addr_af);
2592 if (alen != sizeof (struct in_addr))
2595 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2600 if (alen != sizeof (struct in6_addr))
2603 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2609 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2613 /* allocate response IP */
2614 result_af = (int) htonl (msg->result_af);
2615 if (GNUNET_OK != allocate_response_ip (&result_af,
2619 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2622 /* send reply with our IP address */
2623 send_client_reply (client,
2627 if (result_af == AF_UNSPEC)
2629 /* failure, we're done */
2630 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2635 char sbuf[INET6_ADDRSTRLEN];
2636 char dbuf[INET6_ADDRSTRLEN];
2638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2639 "Allocated address %s for redirection via exit to %s\n",
2640 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2642 &msg[1], dbuf, sizeof (dbuf)));
2645 /* setup destination record */
2646 de = GNUNET_new (struct DestinationEntry);
2647 de->is_service = GNUNET_NO;
2648 de->details.exit_destination.af = addr_af;
2649 memcpy (&de->details.exit_destination.ip,
2652 get_destination_key_from_ip (result_af,
2656 GNUNET_assert (GNUNET_OK ==
2657 GNUNET_CONTAINER_multihashmap_put (destination_map,
2660 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2661 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2663 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2664 GNUNET_STATISTICS_update (stats,
2665 gettext_noop ("# Active destinations"),
2667 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2668 expire_destination (de);
2669 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2674 * A client asks us to setup a redirection to a particular peer
2675 * offering a service. Setup the redirection and give the client the
2679 * @param client requesting client
2680 * @param message redirection request (a `struct RedirectToPeerRequestMessage`)
2683 service_redirect_to_service (void *cls,
2684 struct GNUNET_SERVER_Client *client,
2685 const struct GNUNET_MessageHeader *message)
2687 const struct RedirectToServiceRequestMessage *msg;
2692 struct DestinationEntry *de;
2693 struct GNUNET_HashCode key;
2694 struct ChannelState *ts;
2695 struct DestinationChannel *dt;
2698 msg = (const struct RedirectToServiceRequestMessage *) message;
2700 /* allocate response IP */
2701 result_af = (int) htonl (msg->result_af);
2702 if (GNUNET_OK != allocate_response_ip (&result_af,
2706 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2709 send_client_reply (client,
2713 if (result_af == AF_UNSPEC)
2715 /* failure, we're done */
2716 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2717 _("Failed to allocate IP address for new destination\n"));
2718 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2723 char sbuf[INET6_ADDRSTRLEN];
2725 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2726 "Allocated address %s for redirection to service %s on peer %s\n",
2727 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
2728 GNUNET_h2s (&msg->service_descriptor),
2729 GNUNET_i2s (&msg->target));
2732 /* setup destination record */
2733 de = GNUNET_new (struct DestinationEntry);
2734 de->is_service = GNUNET_YES;
2735 de->details.service_destination.service_descriptor = msg->service_descriptor;
2736 de->details.service_destination.target = msg->target;
2737 get_destination_key_from_ip (result_af,
2741 GNUNET_assert (GNUNET_OK ==
2742 GNUNET_CONTAINER_multihashmap_put (destination_map,
2745 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2746 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2748 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2749 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2750 expire_destination (de);
2752 dt = GNUNET_new (struct DestinationChannel);
2753 dt->destination = de;
2754 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2757 ts = create_channel_to_destination (dt,
2762 ts->destination_ip.v4 = v4;
2765 ts->destination_ip.v6 = v6;
2771 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2776 * Function called whenever a channel is destroyed. Should clean up
2777 * any associated state.
2779 * @param cls closure (set from #GNUNET_MESH_connect)
2780 * @param channel connection to the other end (henceforth invalid)
2781 * @param channel_ctx place where local state associated
2782 * with the channel is stored (our `struct ChannelState`)
2785 channel_cleaner (void *cls,
2786 const struct GNUNET_MESH_Channel *channel,
2789 struct ChannelState *ts = channel_ctx;
2791 ts->channel = NULL; /* we must not call GNUNET_MESH_channel_destroy() anymore */
2792 free_channel_state (ts);
2797 * Free memory occupied by an entry in the destination map.
2801 * @param value a `struct DestinationEntry *`
2802 * @return #GNUNET_OK (continue to iterate)
2805 cleanup_destination (void *cls,
2806 const struct GNUNET_HashCode *key,
2809 struct DestinationEntry *de = value;
2811 free_destination_entry (de);
2817 * Free memory occupied by an entry in the channel map.
2821 * @param value a `struct ChannelState *`
2822 * @return #GNUNET_OK (continue to iterate)
2825 cleanup_channel (void *cls,
2826 const struct GNUNET_HashCode *key,
2829 struct ChannelState *ts = value;
2831 free_channel_state (ts);
2837 * Function scheduled as very last function, cleans up after us
2844 const struct GNUNET_SCHEDULER_TaskContext *tc)
2848 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2849 "VPN is shutting down\n");
2850 if (NULL != destination_map)
2852 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2853 &cleanup_destination,
2855 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2856 destination_map = NULL;
2858 if (NULL != destination_heap)
2860 GNUNET_CONTAINER_heap_destroy (destination_heap);
2861 destination_heap = NULL;
2863 if (NULL != channel_map)
2865 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2868 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2871 if (NULL != channel_heap)
2873 GNUNET_CONTAINER_heap_destroy (channel_heap);
2874 channel_heap = NULL;
2876 if (NULL != mesh_handle)
2878 GNUNET_MESH_disconnect (mesh_handle);
2881 if (NULL != helper_handle)
2883 GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
2884 helper_handle = NULL;
2888 GNUNET_SERVER_notification_context_destroy (nc);
2893 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2897 GNUNET_free_non_null (vpn_argv[i]);
2902 * Main function that will be run by the scheduler.
2904 * @param cls closure
2905 * @param server the initialized server
2906 * @param cfg_ configuration
2910 struct GNUNET_SERVER_Handle *server,
2911 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2913 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2914 /* callback, cls, type, size */
2915 { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2916 { &service_redirect_to_service, NULL,
2917 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2918 sizeof (struct RedirectToServiceRequestMessage) },
2921 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2922 { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0},
2923 { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0},
2924 { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0},
2936 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2939 GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2942 "`%s' is not SUID, refusing to run.\n",
2943 "gnunet-helper-vpn");
2944 GNUNET_free (binary);
2948 GNUNET_free (binary);
2950 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2952 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING",
2953 &max_destination_mappings))
2954 max_destination_mappings = 200;
2956 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS",
2957 &max_channel_mappings))
2958 max_channel_mappings = 200;
2960 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2961 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2962 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2963 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2966 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2967 if (GNUNET_SYSERR ==
2968 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2970 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2971 GNUNET_SCHEDULER_shutdown ();
2974 vpn_argv[1] = ifname;
2976 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2978 if ( (GNUNET_SYSERR ==
2979 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2981 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2983 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2984 _("Must specify valid IPv6 address"));
2985 GNUNET_SCHEDULER_shutdown ();
2986 GNUNET_free_non_null (ipv6addr);
2989 vpn_argv[2] = ipv6addr;
2990 ipv6prefix_s = NULL;
2991 if (GNUNET_SYSERR ==
2992 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
2995 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
2996 GNUNET_SCHEDULER_shutdown ();
2997 GNUNET_free_non_null (ipv6prefix_s);
3000 vpn_argv[3] = ipv6prefix_s;
3002 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3005 (ipv6prefix >= 127) )
3007 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3008 _("Must specify valid IPv6 mask"));
3009 GNUNET_SCHEDULER_shutdown ();
3015 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3016 _("IPv6 support disabled as this system does not support IPv6\n"));
3017 vpn_argv[2] = GNUNET_strdup ("-");
3018 vpn_argv[3] = GNUNET_strdup ("-");
3020 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3023 if ( (GNUNET_SYSERR ==
3024 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3026 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3028 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3029 _("Must specify valid IPv4 address"));
3030 GNUNET_SCHEDULER_shutdown ();
3031 GNUNET_free_non_null (ipv4addr);
3034 vpn_argv[4] = ipv4addr;
3036 if ( (GNUNET_SYSERR ==
3037 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3039 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3041 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3042 _("Must specify valid IPv4 mask"));
3043 GNUNET_SCHEDULER_shutdown ();
3044 GNUNET_free_non_null (ipv4mask);
3047 vpn_argv[5] = ipv4mask;
3051 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3052 _("IPv4 support disabled as this system does not support IPv4\n"));
3053 vpn_argv[4] = GNUNET_strdup ("-");
3054 vpn_argv[5] = GNUNET_strdup ("-");
3059 GNUNET_MESH_connect (cfg_, NULL,
3064 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3065 "gnunet-helper-vpn", vpn_argv,
3066 &message_token, NULL, NULL);
3067 nc = GNUNET_SERVER_notification_context_create (server, 1);
3068 GNUNET_SERVER_add_handlers (server, service_handlers);
3069 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3074 * The main function of the VPN service.
3076 * @param argc number of arguments from the command line
3077 * @param argv command line arguments
3078 * @return 0 ok, 1 on error
3081 main (int argc, char *const *argv)
3083 return (GNUNET_OK ==
3084 GNUNET_SERVICE_run (argc, argv, "vpn",
3085 GNUNET_SERVICE_OPTION_NONE,
3086 &run, NULL)) ? global_ret : 1;
3089 /* end of gnunet-service-vpn.c */