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
31 * - need some statistics
33 * - better message queue management (bounded state, drop oldest/RED?)
34 * - actually destroy "stale" tunnels once we have too many!
37 * - add back ICMP support (especially needed for IPv6)
40 * - consider moving IP-header building / checksumming code into shared library
41 * with dns/exit/vpn (libgnunettun_tcpip?)
44 #include "gnunet_util_lib.h"
45 #include "gnunet_common.h"
46 #include "gnunet_protocols.h"
47 #include "gnunet_applications.h"
48 #include "gnunet_mesh_service.h"
49 #include "gnunet_constants.h"
50 #include "tcpip_tun.h"
56 * State we keep for each of our tunnels.
62 * Information we track for each IP address to determine which tunnel
63 * to send the traffic over to the destination.
65 struct DestinationEntry
69 * Key under which this entry is in the 'destination_map' (only valid
70 * if 'heap_node != NULL'.
75 * Pre-allocated tunnel for this destination, or NULL for none.
77 struct TunnelState *ts;
80 * Entry for this entry in the destination_heap.
82 struct GNUNET_CONTAINER_HeapNode *heap_node;
85 * GNUNET_NO if this is a tunnel to an Internet-exit,
86 * GNUNET_YES if this tunnel is to a service.
91 * Details about the connection (depending on is_service).
99 * The description of the service (only used for service tunnels).
101 GNUNET_HashCode service_descriptor;
104 * Peer offering the service.
106 struct GNUNET_PeerIdentity target;
108 } service_destination;
114 * Address family used (AF_INET or AF_INET6).
119 * IP address of the ultimate destination (only used for exit tunnels).
124 * Address if af is AF_INET.
129 * Address if af is AF_INET6.
142 * A messages we have in queue for a particular tunnel.
144 struct TunnelMessageQueueEntry
147 * This is a doubly-linked list.
149 struct TunnelMessageQueueEntry *next;
152 * This is a doubly-linked list.
154 struct TunnelMessageQueueEntry *prev;
157 * Number of bytes in 'msg'.
162 * Message to transmit, allocated at the end of this struct.
169 * State we keep for each of our tunnels.
174 * Information about the tunnel to use, NULL if no tunnel
175 * is available right now.
177 struct GNUNET_MESH_Tunnel *tunnel;
180 * Active transmission handle, NULL for none.
182 struct GNUNET_MESH_TransmitHandle *th;
185 * Entry for this entry in the tunnel_heap, NULL as long as this
186 * tunnel state is not fully bound.
188 struct GNUNET_CONTAINER_HeapNode *heap_node;
191 * Head of list of messages scheduled for transmission.
193 struct TunnelMessageQueueEntry *head;
196 * Tail of list of messages scheduled for transmission.
198 struct TunnelMessageQueueEntry *tail;
201 * Client that needs to be notified about the tunnel being
202 * up as soon as a peer is connected; NULL for none.
204 struct GNUNET_SERVER_Client *client;
207 * ID of the client request that caused us to setup this entry.
212 * Destination to which this tunnel leads. Note that
213 * this struct is NOT in the destination_map (but a
214 * local copy) and that the 'heap_node' should always
217 struct DestinationEntry destination;
220 * Destination entry that has a pointer to this tunnel state;
221 * NULL if this tunnel state is in the tunnel map.
223 struct DestinationEntry *destination_container;
226 * Addess family used for this tunnel on the local TUN interface.
231 * IPPROTO_TCP or IPPROTO_UDP once bound.
236 * IP address of the source on our end, initially uninitialized.
241 * Address if af is AF_INET.
246 * Address if af is AF_INET6.
253 * Destination IP address used by the source on our end (this is the IP
254 * that we pick freely within the VPN's tunnel IP range).
259 * Address if af is AF_INET.
264 * Address if af is AF_INET6.
271 * Source port used by the sender on our end; 0 for uninitialized.
273 uint16_t source_port;
276 * Destination port used by the sender on our end; 0 for uninitialized.
278 uint16_t destination_port;
284 * Configuration we use.
286 static const struct GNUNET_CONFIGURATION_Handle *cfg;
289 * Handle to the mesh service.
291 static struct GNUNET_MESH_Handle *mesh_handle;
294 * Map from IP address to destination information (possibly with a
295 * MESH tunnel handle for fast setup).
297 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
300 * Min-Heap sorted by activity time to expire old mappings.
302 static struct GNUNET_CONTAINER_Heap *destination_heap;
305 * Map from source and destination address (IP+port) to connection
306 * information (mostly with the respective MESH tunnel handle).
308 static struct GNUNET_CONTAINER_MultiHashMap *tunnel_map;
311 * Min-Heap sorted by activity time to expire old mappings; values are
312 * of type 'struct TunnelState'.
314 static struct GNUNET_CONTAINER_Heap *tunnel_heap;
317 * The handle to the VPN helper process "gnunet-helper-vpn".
319 static struct GNUNET_HELPER_Handle *helper_handle;
322 * Arguments to the vpn helper.
324 static char *vpn_argv[7];
327 * Length of the prefix of the VPN's IPv6 network.
329 static unsigned long long ipv6prefix;
332 * Notification context for sending replies to clients.
334 static struct GNUNET_SERVER_NotificationContext *nc;
337 * If there are more than this number of address-mappings, old ones
340 static unsigned long long max_destination_mappings;
343 * If there are more than this number of open tunnels, old ones
346 static unsigned long long max_tunnel_mappings;
350 * Compute the key under which we would store an entry in the
351 * destination_map for the given IP address.
353 * @param af address family (AF_INET or AF_INET6)
354 * @param address IP address, struct in_addr or struct in6_addr
355 * @param key where to store the key
358 get_destination_key_from_ip (int af,
360 GNUNET_HashCode *key)
365 GNUNET_CRYPTO_hash (address,
366 sizeof (struct in_addr),
370 GNUNET_CRYPTO_hash (address,
371 sizeof (struct in6_addr),
382 * Compute the key under which we would store an entry in the
383 * tunnel_map for the given socket address pair.
385 * @param af address family (AF_INET or AF_INET6)
386 * @param protocol IPPROTO_TCP or IPPROTO_UDP
387 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
388 * @param source_port sender's source port
389 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
390 * @param destination_port sender's destination port
391 * @param key where to store the key
394 get_tunnel_key_from_ips (int af,
396 const void *source_ip,
397 uint16_t source_port,
398 const void *destination_ip,
399 uint16_t destination_port,
400 GNUNET_HashCode *key)
404 memset (key, 0, sizeof (GNUNET_HashCode));
405 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
406 so we put the ports in there (and hope for few collisions) */
408 memcpy (off, &source_port, sizeof (uint16_t));
409 off += sizeof (uint16_t);
410 memcpy (off, &destination_port, sizeof (uint16_t));
411 off += sizeof (uint16_t);
415 memcpy (off, source_ip, sizeof (struct in_addr));
416 off += sizeof (struct in_addr);
417 memcpy (off, destination_ip, sizeof (struct in_addr));
418 off += sizeof (struct in_addr);
421 memcpy (off, source_ip, sizeof (struct in6_addr));
422 off += sizeof (struct in6_addr);
423 memcpy (off, destination_ip, sizeof (struct in6_addr));
424 off += sizeof (struct in6_addr);
430 memcpy (off, &protocol, sizeof (uint8_t));
431 off += sizeof (uint8_t);
436 * Notify the client about the result of its request.
438 * @param client client to notify
439 * @param request_id original request ID to include in response
440 * @param result_af resulting address family
441 * @param addr resulting IP address
444 send_client_reply (struct GNUNET_SERVER_Client *client,
449 char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)];
450 struct RedirectToIpResponseMessage *res;
456 rlen = sizeof (struct in_addr);
459 rlen = sizeof (struct in6_addr);
468 res = (struct RedirectToIpResponseMessage *) buf;
469 res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen);
470 res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
471 res->result_af = htonl (result_af);
472 res->request_id = request_id;
473 memcpy (&res[1], addr, rlen);
474 GNUNET_SERVER_notification_context_add (nc, client);
475 GNUNET_SERVER_notification_context_unicast (nc,
483 * Method called whenever a peer has disconnected from the tunnel.
486 * @param peer peer identity the tunnel stopped working with
489 tunnel_peer_disconnect_handler (void *cls,
491 GNUNET_PeerIdentity * peer)
493 struct TunnelState *ts = cls;
495 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
496 "Peer %s disconnected from tunnel.\n",
500 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
503 if (ts->destination.is_service)
504 return; /* hope for reconnect eventually */
505 /* as we are most likely going to change the exit node now,
506 we should just destroy the tunnel entirely... */
507 GNUNET_MESH_tunnel_destroy (ts->tunnel);
512 * Method called whenever a peer has connected to the tunnel. Notifies
513 * the waiting client that the tunnel is now up.
516 * @param peer peer identity the tunnel was created to, NULL on timeout
517 * @param atsi performance data for the connection
520 tunnel_peer_connect_handler (void *cls,
521 const struct GNUNET_PeerIdentity
524 GNUNET_ATS_Information * atsi)
526 struct TunnelState *ts = cls;
528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
529 "Peer %s connected to tunnel.\n",
531 if (NULL == ts->client)
532 return; /* nothing to do */
533 send_client_reply (ts->client,
536 &ts->destination_ip);
537 GNUNET_SERVER_client_drop (ts->client);
543 * Send a message from the message queue via mesh.
545 * @param cls the 'struct TunnelState' with the message queue
546 * @param size number of bytes available in buf
547 * @param buf where to copy the message
548 * @return number of bytes copied to buf
551 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
553 struct TunnelState *ts = cls;
554 struct TunnelMessageQueueEntry *tnq;
561 GNUNET_assert (NULL != tnq);
562 GNUNET_assert (size >= tnq->len);
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564 "Sending %u bytes via mesh tunnel\n",
566 GNUNET_CONTAINER_DLL_remove (ts->head,
569 memcpy (buf, tnq->msg, tnq->len);
572 if (NULL != (tnq = ts->head))
573 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
574 GNUNET_NO /* cork */,
576 GNUNET_TIME_UNIT_FOREVER_REL,
579 &send_to_peer_notify_callback,
586 * Add the given message to the given tunnel and trigger the
587 * transmission process.
589 * FIXME: bound queue length!
591 * @param tnq message to queue
592 * @param ts tunnel to queue the message for
595 send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
596 struct TunnelState *ts)
598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
599 "Queueing %u bytes for transmission via mesh tunnel\n",
601 GNUNET_CONTAINER_DLL_insert_tail (ts->head,
605 ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel,
606 GNUNET_NO /* cork */,
608 GNUNET_TIME_UNIT_FOREVER_REL,
611 &send_to_peer_notify_callback,
617 * Initialize the given destination entry's mesh tunnel.
619 * @param de destination entry for which we need to setup a tunnel
620 * @param client client to notify on successful tunnel setup, or NULL for none
621 * @param request_id request ID to send in client notification (unused if client is NULL)
622 * @return tunnel state of the tunnel that was created
624 static struct TunnelState *
625 create_tunnel_to_destination (struct DestinationEntry *de,
626 struct GNUNET_SERVER_Client *client,
629 struct TunnelState *ts;
631 GNUNET_assert (NULL == de->ts);
632 ts = GNUNET_malloc (sizeof (struct TunnelState));
635 ts->request_id = request_id;
637 GNUNET_SERVER_client_keep (client);
639 ts->destination = *de;
640 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
642 ts->destination_container = de; /* we are referenced from de */
643 ts->af = AF_UNSPEC; /* so far, unknown */
644 ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
646 &tunnel_peer_connect_handler,
647 &tunnel_peer_disconnect_handler,
651 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652 "Creating tunnel to peer %s offering service %s\n",
653 GNUNET_i2s (&de->details.service_destination.target),
654 GNUNET_h2s (&de->details.service_destination.service_descriptor));
655 GNUNET_MESH_peer_request_connect_add (ts->tunnel,
656 &de->details.service_destination.target);
660 switch (de->details.exit_destination.af)
663 GNUNET_MESH_peer_request_connect_by_type (ts->tunnel,
664 GNUNET_APPLICATION_TYPE_IPV4_GATEWAY);
665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
666 "Creating tunnel to exit peer for %s\n",
670 GNUNET_MESH_peer_request_connect_by_type (ts->tunnel,
671 GNUNET_APPLICATION_TYPE_IPV6_GATEWAY);
672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
673 "Creating tunnel to exit peer for %s\n",
686 * Route a packet via mesh to the given destination.
688 * @param destination description of the destination
689 * @param af address family on this end (AF_INET or AF_INET6)
690 * @param protocol IPPROTO_TCP or IPPROTO_UDP
691 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
692 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
693 * @param payload payload of the packet after the IP header
694 * @param payload_length number of bytes in payload
697 route_packet (struct DestinationEntry *destination,
700 const void *source_ip,
701 const void *destination_ip,
703 size_t payload_length)
706 struct TunnelState *ts;
707 struct TunnelMessageQueueEntry *tnq;
711 const struct udp_packet *udp;
712 const struct tcp_packet *tcp;
720 if (payload_length < sizeof (struct udp_packet))
727 spt = ntohs (udp->spt);
728 dpt = ntohs (udp->dpt);
729 get_tunnel_key_from_ips (af,
740 if (payload_length < sizeof (struct tcp_packet))
747 spt = ntohs (tcp->spt);
748 dpt = ntohs (tcp->dpt);
749 get_tunnel_key_from_ips (af,
759 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
760 _("Protocol %u not supported, dropping\n"),
761 (unsigned int) protocol);
764 if (! destination->is_service)
766 switch (destination->details.exit_destination.af)
769 alen = sizeof (struct in_addr);
772 alen = sizeof (struct in6_addr);
780 char sbuf[INET6_ADDRSTRLEN];
781 char dbuf[INET6_ADDRSTRLEN];
782 char xbuf[INET6_ADDRSTRLEN];
784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
785 "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n",
786 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
787 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
789 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
791 inet_ntop (destination->details.exit_destination.af,
792 &destination->details.exit_destination.ip,
793 xbuf, sizeof (xbuf)));
798 /* make compiler happy */
801 char sbuf[INET6_ADDRSTRLEN];
802 char dbuf[INET6_ADDRSTRLEN];
804 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
805 "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n",
806 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
807 inet_ntop (af, source_ip, sbuf, sizeof (sbuf)),
809 inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)),
811 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
812 GNUNET_i2s (&destination->details.service_destination.target));
817 /* see if we have an existing tunnel for this destination */
818 ts = GNUNET_CONTAINER_multihashmap_get (tunnel_map,
822 /* need to either use the existing tunnel from the destination (if still
823 available) or create a fresh one */
825 if (NULL == destination->ts)
826 ts = create_tunnel_to_destination (destination, NULL, 0);
828 ts = destination->ts;
829 destination->ts = NULL;
830 ts->destination_container = NULL; /* no longer 'contained' */
831 /* now bind existing "unbound" tunnel to our IP/port tuple */
832 ts->protocol = protocol;
836 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
837 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
841 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
842 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
844 ts->source_port = spt;
845 ts->destination_port = dpt;
846 ts->heap_node = GNUNET_CONTAINER_heap_insert (tunnel_heap,
848 GNUNET_TIME_absolute_get ().abs_value);
849 GNUNET_assert (GNUNET_YES ==
850 GNUNET_CONTAINER_multihashmap_put (tunnel_map,
853 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
854 /* FIXME: expire OLD tunnels if we have too many! */
859 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
861 GNUNET_TIME_absolute_get ().abs_value);
864 /* send via tunnel */
868 if (destination->is_service)
870 struct GNUNET_EXIT_UdpServiceMessage *usm;
872 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
873 payload_length - sizeof (struct udp_packet);
874 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
879 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
880 usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1];
881 usm->header.size = htons ((uint16_t) mlen);
882 usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
883 /* if the source port is below 32000, we assume it has a special
884 meaning; if not, we pick a random port (this is a heuristic) */
885 usm->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
886 usm->destination_port = udp->dpt;
887 usm->service_descriptor = destination->details.service_destination.service_descriptor;
890 payload_length - sizeof (struct udp_packet));
894 struct GNUNET_EXIT_UdpInternetMessage *uim;
895 struct in_addr *ip4dst;
896 struct in6_addr *ip6dst;
899 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
900 alen + payload_length - sizeof (struct udp_packet);
901 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
906 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) +
908 uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1];
909 uim->header.size = htons ((uint16_t) mlen);
910 uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
911 uim->af = htonl (destination->details.exit_destination.af);
912 uim->source_port = (ntohs (udp->spt) < 32000) ? udp->spt : 0;
913 uim->destination_port = udp->dpt;
914 switch (destination->details.exit_destination.af)
917 ip4dst = (struct in_addr *) &uim[1];
918 *ip4dst = destination->details.exit_destination.ip.v4;
919 payload = &ip4dst[1];
922 ip6dst = (struct in6_addr *) &uim[1];
923 *ip6dst = destination->details.exit_destination.ip.v6;
924 payload = &ip6dst[1];
931 payload_length - sizeof (struct udp_packet));
937 if (destination->is_service)
939 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
941 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
942 payload_length - sizeof (struct tcp_packet);
943 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
948 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
949 tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1];
950 tsm->header.size = htons ((uint16_t) mlen);
951 tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
952 tsm->reserved = htonl (0);
953 tsm->service_descriptor = destination->details.service_destination.service_descriptor;
954 tsm->tcp_header = *tcp;
957 payload_length - sizeof (struct tcp_packet));
961 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
962 struct in_addr *ip4dst;
963 struct in6_addr *ip6dst;
966 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
967 alen + payload_length - sizeof (struct tcp_packet);
968 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
973 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
974 tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1];
975 tim->header.size = htons ((uint16_t) mlen);
976 tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
977 tim->af = htonl (destination->details.exit_destination.af);
978 tim->tcp_header = *tcp;
979 switch (destination->details.exit_destination.af)
982 ip4dst = (struct in_addr *) &tim[1];
983 *ip4dst = destination->details.exit_destination.ip.v4;
984 payload = &ip4dst[1];
987 ip6dst = (struct in6_addr *) &tim[1];
988 *ip6dst = destination->details.exit_destination.ip.v6;
989 payload = &ip6dst[1];
996 payload_length - sizeof (struct tcp_packet));
1001 struct GNUNET_EXIT_TcpDataMessage *tdm;
1003 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1004 alen + payload_length - sizeof (struct tcp_packet);
1005 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1010 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueueEntry) + mlen);
1011 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1012 tdm->header.size = htons ((uint16_t) mlen);
1013 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA);
1014 tdm->reserved = htonl (0);
1015 tdm->tcp_header = *tcp;
1018 payload_length - sizeof (struct tcp_packet));
1022 /* not supported above, how can we get here !? */
1026 send_to_tunnel (tnq, ts);
1031 * Receive packets from the helper-process (someone send to the local
1032 * virtual tunnel interface). Find the destination mapping, and if it
1033 * exists, identify the correct MESH tunnel (or possibly create it)
1034 * and forward the packet.
1036 * @param cls closure, NULL
1037 * @param client NULL
1038 * @param message message we got from the client (VPN tunnel interface)
1041 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
1042 const struct GNUNET_MessageHeader *message)
1044 const struct tun_header *tun;
1046 GNUNET_HashCode key;
1047 struct DestinationEntry *de;
1049 mlen = ntohs (message->size);
1050 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
1051 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header)) )
1056 tun = (const struct tun_header *) &message[1];
1057 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header));
1058 switch (ntohs (tun->proto))
1062 const struct ip6_header *pkt6;
1064 if (mlen < sizeof (struct ip6_header))
1070 pkt6 = (const struct ip6_header *) &tun[1];
1071 get_destination_key_from_ip (AF_INET6,
1072 &pkt6->destination_address,
1074 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1075 /* FIXME: do we need to guard against hash collision?
1076 (if so, we need to also store the local destination IP in the
1077 destination entry and then compare here; however, the risk
1078 of collision seems minimal AND the impact is unlikely to be
1079 super-problematic as well... */
1082 char buf[INET6_ADDRSTRLEN];
1084 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1085 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1086 inet_ntop (AF_INET6,
1087 &pkt6->destination_address,
1095 &pkt6->source_address,
1096 &pkt6->destination_address,
1098 mlen - sizeof (struct ip6_header));
1103 struct ip4_header *pkt4;
1105 if (mlen < sizeof (struct ip4_header))
1111 pkt4 = (struct ip4_header *) &tun[1];
1112 get_destination_key_from_ip (AF_INET,
1113 &pkt4->destination_address,
1115 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
1116 /* FIXME: do we need to guard against hash collision?
1117 (if so, we need to also store the local destination IP in the
1118 destination entry and then compare here; however, the risk
1119 of collision seems minimal AND the impact is unlikely to be
1120 super-problematic as well... */
1123 char buf[INET_ADDRSTRLEN];
1125 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1126 _("Packet received for unmapped destination `%s' (dropping it)\n"),
1128 &pkt4->destination_address,
1133 if (pkt4->header_length * 4 != sizeof (struct ip4_header))
1135 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1136 _("Received IPv4 packet with options (dropping it)\n"));
1142 &pkt4->source_address,
1143 &pkt4->destination_address,
1145 mlen - sizeof (struct ip4_header));
1149 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1150 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
1151 (unsigned int) ntohs (tun->proto));
1158 * We got a UDP packet back from the MESH tunnel. Pass it on to the
1159 * local virtual interface via the helper.
1161 * @param cls closure, NULL
1162 * @param tunnel connection to the other end
1163 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1164 * @param sender who sent the message
1165 * @param message the actual message
1166 * @param atsi performance data for the connection
1167 * @return GNUNET_OK to keep the connection open,
1168 * GNUNET_SYSERR to close it (signal serious error)
1171 receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1172 void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender,
1173 const struct GNUNET_MessageHeader *message,
1174 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1176 struct TunnelState *ts = *tunnel_ctx;
1177 const struct GNUNET_EXIT_UdpReplyMessage *reply;
1180 mlen = ntohs (message->size);
1181 if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage))
1183 GNUNET_break_op (0);
1184 return GNUNET_SYSERR;
1186 if (NULL == ts->heap_node)
1188 GNUNET_break_op (0);
1189 return GNUNET_SYSERR;
1191 if (AF_UNSPEC == ts->af)
1193 GNUNET_break_op (0);
1194 return GNUNET_SYSERR;
1196 reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message;
1197 mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1199 char sbuf[INET6_ADDRSTRLEN];
1200 char dbuf[INET6_ADDRSTRLEN];
1202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1203 "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1204 (unsigned int) mlen,
1205 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1206 ts->destination_port,
1207 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1214 size_t size = sizeof (struct ip4_header)
1215 + sizeof (struct udp_packet)
1216 + sizeof (struct GNUNET_MessageHeader) +
1217 sizeof (struct tun_header) +
1221 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1222 struct tun_header *tun = (struct tun_header*) &msg[1];
1223 struct ip4_header *ipv4 = (struct ip4_header *) &tun[1];
1224 struct udp_packet *udp = (struct udp_packet *) &ipv4[1];
1225 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1226 msg->size = htons (size);
1227 tun->flags = htons (0);
1228 tun->proto = htons (ETH_P_IPV4);
1230 ipv4->header_length = sizeof (struct ip4_header) / 4;
1231 ipv4->diff_serv = 0;
1232 ipv4->total_length = htons (sizeof (struct ip4_header) +
1233 sizeof (struct udp_packet) +
1235 ipv4->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1238 ipv4->fragmentation_offset = 0;
1240 ipv4->protocol = IPPROTO_UDP;
1242 ipv4->source_address = ts->destination_ip.v4;
1243 ipv4->destination_address = ts->source_ip.v4;
1245 GNUNET_CRYPTO_crc16_n (ipv4, sizeof (struct ip4_header));
1246 if (0 == ntohs (reply->source_port))
1247 udp->spt = htons (ts->destination_port);
1249 udp->spt = reply->source_port;
1250 if (0 == ntohs (reply->destination_port))
1251 udp->dpt = htons (ts->source_port);
1253 udp->dpt = reply->destination_port;
1254 udp->len = htons (mlen + sizeof (struct udp_packet));
1255 udp->crc = 0; // FIXME: optional, but we might want to calculate this one anyway
1259 (void) GNUNET_HELPER_send (helper_handle,
1268 size_t size = sizeof (struct ip6_header)
1269 + sizeof (struct udp_packet)
1270 + sizeof (struct GNUNET_MessageHeader) +
1271 sizeof (struct tun_header) +
1275 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1276 struct tun_header *tun = (struct tun_header*) &msg[1];
1277 struct ip6_header *ipv6 = (struct ip6_header *) &tun[1];
1278 struct udp_packet *udp = (struct udp_packet *) &ipv6[1];
1279 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1280 msg->size = htons (size);
1281 tun->flags = htons (0);
1282 tun->proto = htons (ETH_P_IPV6);
1283 ipv6->traffic_class_h = 0;
1285 ipv6->traffic_class_l = 0;
1286 ipv6->flow_label = 0;
1287 ipv6->payload_length = htons (sizeof (struct udp_packet) + sizeof (struct ip6_header) + mlen);
1288 ipv6->next_header = IPPROTO_UDP;
1289 ipv6->hop_limit = 255;
1290 ipv6->source_address = ts->destination_ip.v6;
1291 ipv6->destination_address = ts->source_ip.v6;
1292 if (0 == ntohs (reply->source_port))
1293 udp->spt = htons (ts->destination_port);
1295 udp->spt = reply->source_port;
1296 if (0 == ntohs (reply->destination_port))
1297 udp->dpt = htons (ts->source_port);
1299 udp->dpt = reply->destination_port;
1300 udp->len = htons (mlen + sizeof (struct udp_packet));
1308 GNUNET_CRYPTO_crc16_step (sum, &ipv6->source_address,
1309 sizeof (struct in6_addr) * 2);
1310 uint32_t tmp = udp->len;
1311 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1312 tmp = htons (IPPROTO_UDP);
1313 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1314 sum = GNUNET_CRYPTO_crc16_step (sum,
1317 udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1319 (void) GNUNET_HELPER_send (helper_handle,
1329 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1331 GNUNET_TIME_absolute_get ().abs_value);
1337 * We got a TCP packet back from the MESH tunnel. Pass it on to the
1338 * local virtual interface via the helper.
1340 * @param cls closure, NULL
1341 * @param tunnel connection to the other end
1342 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1343 * @param sender who sent the message
1344 * @param message the actual message
1345 * @param atsi performance data for the connection
1346 * @return GNUNET_OK to keep the connection open,
1347 * GNUNET_SYSERR to close it (signal serious error)
1350 receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1352 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1353 const struct GNUNET_MessageHeader *message,
1354 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1356 struct TunnelState *ts = *tunnel_ctx;
1357 const struct GNUNET_EXIT_TcpDataMessage *data;
1360 mlen = ntohs (message->size);
1361 if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1363 GNUNET_break_op (0);
1364 return GNUNET_SYSERR;
1366 if (NULL == ts->heap_node)
1368 GNUNET_break_op (0);
1369 return GNUNET_SYSERR;
1371 data = (const struct GNUNET_EXIT_TcpDataMessage *) message;
1372 mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
1374 char sbuf[INET6_ADDRSTRLEN];
1375 char dbuf[INET6_ADDRSTRLEN];
1377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1378 "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n",
1379 (unsigned int) mlen,
1380 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1381 ts->destination_port,
1382 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1389 size_t size = sizeof (struct ip4_header)
1390 + sizeof (struct tcp_packet)
1391 + sizeof (struct GNUNET_MessageHeader) +
1392 sizeof (struct tun_header) +
1396 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1397 struct tun_header *tun = (struct tun_header*) &msg[1];
1398 struct ip4_header *ipv4 = (struct ip4_header *) &tun[1];
1399 struct tcp_packet *tcp = (struct tcp_packet *) &ipv4[1];
1400 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1401 msg->size = htons (size);
1402 tun->flags = htons (0);
1403 tun->proto = htons (ETH_P_IPV4);
1405 ipv4->header_length = sizeof (struct ip4_header) / 4;
1406 ipv4->diff_serv = 0;
1407 ipv4->total_length = htons (sizeof (struct ip4_header) +
1408 sizeof (struct tcp_packet) +
1410 ipv4->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1413 ipv4->fragmentation_offset = 0;
1415 ipv4->protocol = IPPROTO_TCP;
1417 ipv4->source_address = ts->destination_ip.v4;
1418 ipv4->destination_address = ts->source_ip.v4;
1420 GNUNET_CRYPTO_crc16_n (ipv4, sizeof (struct ip4_header));
1421 *tcp = data->tcp_header;
1422 tcp->spt = htons (ts->destination_port);
1423 tcp->dpt = htons (ts->source_port);
1432 sum = GNUNET_CRYPTO_crc16_step (sum,
1433 &ipv4->source_address,
1434 2 * sizeof (struct in_addr));
1435 tmp = htonl ((IPPROTO_TCP << 16) | (mlen + sizeof (struct tcp_packet)));
1436 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1437 sum = GNUNET_CRYPTO_crc16_step (sum, tcp, mlen + sizeof (struct tcp_packet));
1438 tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1440 (void) GNUNET_HELPER_send (helper_handle,
1449 size_t size = sizeof (struct ip6_header)
1450 + sizeof (struct tcp_packet)
1451 + sizeof (struct GNUNET_MessageHeader) +
1452 sizeof (struct tun_header) +
1456 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1457 struct tun_header *tun = (struct tun_header*) &msg[1];
1458 struct ip6_header *ipv6 = (struct ip6_header *) &tun[1];
1459 struct tcp_packet *tcp = (struct tcp_packet *) &ipv6[1];
1460 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1461 msg->size = htons (size);
1462 tun->flags = htons (0);
1463 tun->proto = htons (ETH_P_IPV6);
1464 ipv6->traffic_class_h = 0;
1466 ipv6->traffic_class_l = 0;
1467 ipv6->flow_label = 0;
1468 ipv6->payload_length = htons (sizeof (struct tcp_packet) + sizeof (struct ip6_header) + mlen);
1469 ipv6->next_header = IPPROTO_TCP;
1470 ipv6->hop_limit = 255;
1471 ipv6->source_address = ts->destination_ip.v6;
1472 ipv6->destination_address = ts->source_ip.v6;
1473 tcp->spt = htons (ts->destination_port);
1474 tcp->dpt = htons (ts->source_port);
1480 sum = GNUNET_CRYPTO_crc16_step (sum, &ipv6->source_address, 2 * sizeof (struct in6_addr));
1481 tmp = htonl (sizeof (struct tcp_packet) + mlen);
1482 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1483 tmp = htonl (IPPROTO_TCP);
1484 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1485 sum = GNUNET_CRYPTO_crc16_step (sum, tcp,
1486 sizeof (struct tcp_packet) + mlen);
1487 tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1489 (void) GNUNET_HELPER_send (helper_handle,
1497 GNUNET_CONTAINER_heap_update_cost (tunnel_heap,
1499 GNUNET_TIME_absolute_get ().abs_value);
1505 * Allocate an IPv4 address from the range of the tunnel
1506 * for a new redirection.
1508 * @param v4 where to store the address
1509 * @return GNUNET_OK on success,
1510 * GNUNET_SYSERR on error
1513 allocate_v4_address (struct in_addr *v4)
1515 const char *ipv4addr = vpn_argv[4];
1516 const char *ipv4mask = vpn_argv[5];
1517 struct in_addr addr;
1518 struct in_addr mask;
1520 GNUNET_HashCode key;
1523 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
1524 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
1525 /* Given 192.168.0.1/255.255.0.0, we want a mask
1526 of '192.168.255.255', thus: */
1527 mask.s_addr = addr.s_addr | ~mask.s_addr;
1534 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1535 _("Failed to find unallocated IPv4 address in VPN's range\n"));
1536 return GNUNET_SYSERR;
1538 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1539 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1541 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1542 get_destination_key_from_ip (AF_INET,
1546 while ( (GNUNET_YES ==
1547 GNUNET_CONTAINER_multihashmap_contains (destination_map,
1549 (v4->s_addr == addr.s_addr) ||
1550 (v4->s_addr == mask.s_addr) );
1556 * Allocate an IPv6 address from the range of the tunnel
1557 * for a new redirection.
1559 * @param v6 where to store the address
1560 * @return GNUNET_OK on success,
1561 * GNUNET_SYSERR on error
1564 allocate_v6_address (struct in6_addr *v6)
1566 const char *ipv6addr = vpn_argv[2];
1567 struct in6_addr addr;
1568 struct in6_addr mask;
1569 struct in6_addr rnd;
1571 GNUNET_HashCode key;
1574 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
1575 GNUNET_assert (ipv6prefix < 128);
1576 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1579 for (i=127;i>=128-ipv6prefix;i--)
1580 mask.s6_addr[i / 8] |= (1 << (i % 8));
1582 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1589 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1590 _("Failed to find unallocated IPv6 address in VPN's range\n"));
1591 return GNUNET_SYSERR;
1596 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1599 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1601 get_destination_key_from_ip (AF_INET6,
1605 while ( (GNUNET_YES ==
1606 GNUNET_CONTAINER_multihashmap_contains (destination_map,
1610 sizeof (struct in6_addr))) ||
1613 sizeof (struct in6_addr))) );
1619 * A client asks us to setup a redirection via some exit
1620 * node to a particular IP. Setup the redirection and
1621 * give the client the allocated IP.
1624 * @param client requesting client
1625 * @param message redirection request (a 'struct RedirectToIpRequestMessage')
1628 service_redirect_to_ip (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1629 const struct GNUNET_MessageHeader *message)
1633 const struct RedirectToIpRequestMessage *msg;
1639 struct DestinationEntry *de;
1640 GNUNET_HashCode key;
1642 /* validate and parse request */
1643 mlen = ntohs (message->size);
1644 if (mlen < sizeof (struct RedirectToIpRequestMessage))
1647 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1650 alen = mlen - sizeof (struct RedirectToIpRequestMessage);
1651 msg = (const struct RedirectToIpRequestMessage *) message;
1652 addr_af = (int) htonl (msg->addr_af);
1656 if (alen != sizeof (struct in_addr))
1659 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1664 if (alen != sizeof (struct in6_addr))
1667 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1673 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1677 /* allocate response IP */
1679 result_af = (int) htonl (msg->result_af);
1684 allocate_v4_address (&v4))
1685 result_af = AF_UNSPEC;
1691 allocate_v6_address (&v6))
1692 result_af = AF_UNSPEC;
1698 allocate_v4_address (&v4))
1701 result_af = AF_INET;
1703 else if (GNUNET_OK ==
1704 allocate_v6_address (&v6))
1707 result_af = AF_INET6;
1712 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1715 if ( (result_af == AF_UNSPEC) ||
1716 (GNUNET_NO == ntohl (msg->nac)) )
1718 /* send reply "instantly" */
1719 send_client_reply (client,
1724 if (result_af == AF_UNSPEC)
1726 /* failure, we're done */
1727 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1732 char sbuf[INET6_ADDRSTRLEN];
1733 char dbuf[INET6_ADDRSTRLEN];
1735 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1736 "Allocated address %s for redirection via exit to %s\n",
1737 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
1739 &msg[1], dbuf, sizeof (dbuf)));
1742 /* setup destination record */
1743 de = GNUNET_malloc (sizeof (struct DestinationEntry));
1744 de->is_service = GNUNET_NO;
1745 de->details.exit_destination.af = addr_af;
1746 memcpy (&de->details.exit_destination.ip,
1749 get_destination_key_from_ip (result_af,
1753 GNUNET_assert (GNUNET_OK ==
1754 GNUNET_CONTAINER_multihashmap_put (destination_map,
1757 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1758 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1760 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1761 /* FIXME: expire OLD destinations if we have too many! */
1762 /* setup tunnel to destination */
1763 (void) create_tunnel_to_destination (de,
1764 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
1766 GNUNET_assert (NULL != de->ts);
1768 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1773 * A client asks us to setup a redirection to a particular peer
1774 * offering a service. Setup the redirection and give the client the
1778 * @param client requesting client
1779 * @param message redirection request (a 'struct RedirectToPeerRequestMessage')
1782 service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client,
1783 const struct GNUNET_MessageHeader *message)
1785 const struct RedirectToServiceRequestMessage *msg;
1790 struct DestinationEntry *de;
1791 GNUNET_HashCode key;
1794 msg = (const struct RedirectToServiceRequestMessage *) message;
1796 /* allocate response IP */
1798 result_af = (int) htonl (msg->result_af);
1803 allocate_v4_address (&v4))
1804 result_af = AF_UNSPEC;
1810 allocate_v6_address (&v6))
1811 result_af = AF_UNSPEC;
1817 allocate_v4_address (&v4))
1820 result_af = AF_INET;
1822 else if (GNUNET_OK ==
1823 allocate_v6_address (&v6))
1826 result_af = AF_INET6;
1831 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1834 if ( (result_af == AF_UNSPEC) ||
1835 (GNUNET_NO == ntohl (msg->nac)) )
1837 /* send reply "instantly" */
1838 send_client_reply (client,
1843 if (result_af == AF_UNSPEC)
1845 /* failure, we're done */
1846 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1847 _("Failed to allocate IP address for new destination\n"));
1848 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1853 char sbuf[INET6_ADDRSTRLEN];
1855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1856 "Allocated address %s for redirection to service %s on peer %s\n",
1857 inet_ntop (result_af, addr, sbuf, sizeof (sbuf)),
1858 GNUNET_h2s (&msg->service_descriptor),
1859 GNUNET_i2s (&msg->target));
1862 /* setup destination record */
1863 de = GNUNET_malloc (sizeof (struct DestinationEntry));
1864 de->is_service = GNUNET_YES;
1865 de->details.service_destination.service_descriptor = msg->service_descriptor;
1866 de->details.service_destination.target = msg->target;
1867 get_destination_key_from_ip (result_af,
1871 GNUNET_assert (GNUNET_OK ==
1872 GNUNET_CONTAINER_multihashmap_put (destination_map,
1875 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1876 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
1878 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value);
1879 /* FIXME: expire OLD destinations if we have too many! */
1880 (void) create_tunnel_to_destination (de,
1881 (GNUNET_NO == ntohl (msg->nac)) ? NULL : client,
1884 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1890 * Function called for inbound tunnels. As we don't offer
1891 * any mesh services, this function should never be called.
1893 * @param cls closure
1894 * @param tunnel new handle to the tunnel
1895 * @param initiator peer that started the tunnel
1896 * @param atsi performance information for the tunnel
1897 * @return initial tunnel context for the tunnel
1898 * (can be NULL -- that's not an error)
1901 inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel,
1902 const struct GNUNET_PeerIdentity *initiator,
1903 const struct GNUNET_ATS_Information *atsi)
1905 /* How can and why should anyone open an inbound tunnel to vpn? */
1912 * Free resources associated with a tunnel state.
1914 * @param ts state to free
1917 free_tunnel_state (struct TunnelState *ts)
1919 GNUNET_HashCode key;
1920 struct TunnelMessageQueueEntry *tnq;
1922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1923 "Cleaning up tunnel state\n");
1924 while (NULL != (tnq = ts->head))
1926 GNUNET_CONTAINER_DLL_remove (ts->head,
1931 if (NULL != ts->client)
1933 GNUNET_SERVER_client_drop (ts->client);
1938 GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
1941 GNUNET_assert (NULL == ts->destination.heap_node);
1942 if (NULL != ts->tunnel)
1944 GNUNET_MESH_tunnel_destroy (ts->tunnel);
1947 if (NULL != ts->heap_node)
1949 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
1950 ts->heap_node = NULL;
1951 get_tunnel_key_from_ips (ts->af,
1955 &ts->destination_ip,
1956 ts->destination_port,
1958 GNUNET_assert (GNUNET_YES ==
1959 GNUNET_CONTAINER_multihashmap_remove (tunnel_map,
1963 if (NULL != ts->destination_container)
1965 GNUNET_assert (ts == ts->destination_container->ts);
1966 ts->destination_container->ts = NULL;
1967 ts->destination_container = NULL;
1974 * Free resources occupied by a destination entry.
1976 * @param de entry to free
1979 free_destination_entry (struct DestinationEntry *de)
1981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1982 "Cleaning up destination entry\n");
1986 free_tunnel_state (de->ts);
1987 GNUNET_assert (NULL == de->ts);
1989 if (NULL != de->heap_node)
1991 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
1992 de->heap_node = NULL;
1993 GNUNET_assert (GNUNET_YES ==
1994 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2003 * Function called whenever an inbound tunnel is destroyed. Should clean up
2004 * any associated state.
2006 * @param cls closure (set from GNUNET_MESH_connect)
2007 * @param tunnel connection to the other end (henceforth invalid)
2008 * @param tunnel_ctx place where local state associated
2009 * with the tunnel is stored (our 'struct TunnelState')
2012 tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx)
2014 struct TunnelState *ts = tunnel_ctx;
2021 GNUNET_assert (ts->tunnel == tunnel);
2023 free_tunnel_state (ts);
2028 * Free memory occupied by an entry in the destination map.
2032 * @param value a 'struct DestinationEntry *'
2033 * @return GNUNET_OK (continue to iterate)
2036 cleanup_destination (void *cls,
2037 const GNUNET_HashCode *key,
2040 struct DestinationEntry *de = value;
2042 free_destination_entry (de);
2048 * Free memory occupied by an entry in the tunnel map.
2052 * @param value a 'struct TunnelState *'
2053 * @return GNUNET_OK (continue to iterate)
2056 cleanup_tunnel (void *cls,
2057 const GNUNET_HashCode *key,
2060 struct TunnelState *ts = value;
2062 free_tunnel_state (ts);
2068 * Function scheduled as very last function, cleans up after us
2074 cleanup (void *cls GNUNET_UNUSED,
2075 const struct GNUNET_SCHEDULER_TaskContext *tc)
2079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2080 "VPN is shutting down\n");
2081 if (NULL != destination_map)
2083 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2084 &cleanup_destination,
2086 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2087 destination_map = NULL;
2089 if (NULL != destination_heap)
2091 GNUNET_CONTAINER_heap_destroy (destination_heap);
2092 destination_heap = NULL;
2094 if (NULL != tunnel_map)
2096 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2099 GNUNET_CONTAINER_multihashmap_destroy (tunnel_map);
2102 if (NULL != tunnel_heap)
2104 GNUNET_CONTAINER_heap_destroy (tunnel_heap);
2107 if (NULL != mesh_handle)
2109 GNUNET_MESH_disconnect (mesh_handle);
2112 if (NULL != helper_handle)
2114 GNUNET_HELPER_stop (helper_handle);
2115 helper_handle = NULL;
2119 GNUNET_SERVER_notification_context_destroy (nc);
2123 GNUNET_free_non_null (vpn_argv[i]);
2128 * A client disconnected, clean up all references to it.
2130 * @param cls the client that disconnected
2132 * @param value a 'struct TunnelState *'
2133 * @return GNUNET_OK (continue to iterate)
2136 cleanup_tunnel_client (void *cls,
2137 const GNUNET_HashCode *key,
2140 struct GNUNET_SERVER_Client *client = cls;
2141 struct TunnelState *ts = value;
2143 if (client == ts->client)
2145 GNUNET_SERVER_client_drop (ts->client);
2153 * A client disconnected, clean up all references to it.
2155 * @param cls the client that disconnected
2157 * @param value a 'struct DestinationEntry *'
2158 * @return GNUNET_OK (continue to iterate)
2161 cleanup_destination_client (void *cls,
2162 const GNUNET_HashCode *key,
2165 struct GNUNET_SERVER_Client *client = cls;
2166 struct DestinationEntry *de = value;
2167 struct TunnelState *ts;
2169 if (NULL == (ts = de->ts))
2171 if (client == ts->client)
2173 GNUNET_SERVER_client_drop (ts->client);
2181 * A client has disconnected from us. If we are currently building
2182 * a tunnel for it, cancel the operation.
2185 * @param client handle to the client that disconnected
2188 client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
2190 if (NULL != tunnel_map)
2191 GNUNET_CONTAINER_multihashmap_iterate (tunnel_map,
2192 &cleanup_tunnel_client,
2194 if (NULL != destination_map)
2195 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2196 &cleanup_destination_client,
2202 * Main function that will be run by the scheduler.
2204 * @param cls closure
2205 * @param server the initialized server
2206 * @param cfg_ configuration
2210 struct GNUNET_SERVER_Handle *server,
2211 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2213 static const struct GNUNET_SERVER_MessageHandler service_handlers[] = {
2214 /* callback, cls, type, size */
2215 {&service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0},
2216 {&service_redirect_to_service, NULL,
2217 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
2218 sizeof (struct RedirectToServiceRequestMessage) },
2221 static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = {
2222 {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK, 0},
2223 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK, 0},
2224 {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK, 0},
2225 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
2228 static const GNUNET_MESH_ApplicationType types[] = {
2229 GNUNET_APPLICATION_TYPE_END
2241 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPING",
2242 &max_destination_mappings))
2243 max_destination_mappings = 200;
2245 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_TUNNELS",
2246 &max_tunnel_mappings))
2247 max_tunnel_mappings = 200;
2249 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2);
2250 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2251 tunnel_map = GNUNET_CONTAINER_multihashmap_create (max_tunnel_mappings * 2);
2252 tunnel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2255 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2256 if (GNUNET_SYSERR ==
2257 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
2259 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2260 "No entry 'IFNAME' in configuration!\n");
2261 GNUNET_SCHEDULER_shutdown ();
2264 vpn_argv[1] = ifname;
2265 if ( (GNUNET_SYSERR ==
2266 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR",
2268 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2270 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2271 "No valid entry 'IPV6ADDR' in configuration!\n");
2272 GNUNET_SCHEDULER_shutdown ();
2275 vpn_argv[2] = ipv6addr;
2276 if (GNUNET_SYSERR ==
2277 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
2280 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2281 "No entry 'IPV6PREFIX' in configuration!\n");
2282 GNUNET_SCHEDULER_shutdown ();
2285 vpn_argv[3] = ipv6prefix_s;
2287 GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
2290 (ipv6prefix >= 127) )
2292 GNUNET_SCHEDULER_shutdown ();
2296 if ( (GNUNET_SYSERR ==
2297 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
2299 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
2301 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2302 "No valid entry for 'IPV4ADDR' in configuration!\n");
2303 GNUNET_SCHEDULER_shutdown ();
2306 vpn_argv[4] = ipv4addr;
2307 if ( (GNUNET_SYSERR ==
2308 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
2310 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
2312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2313 "No valid entry 'IPV4MASK' in configuration!\n");
2314 GNUNET_SCHEDULER_shutdown ();
2317 vpn_argv[5] = ipv4mask;
2321 GNUNET_MESH_connect (cfg_, 42 /* queue length */, NULL,
2326 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
2327 &message_token, NULL);
2328 nc = GNUNET_SERVER_notification_context_create (server, 1);
2329 GNUNET_SERVER_add_handlers (server, service_handlers);
2330 GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL);
2331 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
2336 * The main function of the VPN service.
2338 * @param argc number of arguments from the command line
2339 * @param argv command line arguments
2340 * @return 0 ok, 1 on error
2343 main (int argc, char *const *argv)
2345 return (GNUNET_OK ==
2346 GNUNET_SERVICE_run (argc, argv, "vpn",
2347 GNUNET_SERVICE_OPTION_NONE,
2348 &run, NULL)) ? 0 : 1;
2351 /* end of gnunet-service-vpn.c */