2 This file is part of GNUnet.
3 Copyright (C) 2010, 2011, 2012, 2016, 2017 Christian Grothoff
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file vpn/gnunet-service-vpn.c
21 * @brief service that opens a virtual interface and allows its clients
22 * to allocate IPs on the virtual interface and to then redirect
23 * IP traffic received on those IPs via the GNUnet cadet
24 * @author Philipp Toelke
25 * @author Christian Grothoff
28 * - keep multiple peers/cadet channels ready as alternative exits /
29 * detect & recover from channel-to-exit failure gracefully
32 #include "gnunet_util_lib.h"
33 #include "gnunet_common.h"
34 #include "gnunet_protocols.h"
35 #include "gnunet_applications.h"
36 #include "gnunet_cadet_service.h"
37 #include "gnunet_statistics_service.h"
38 #include "gnunet_constants.h"
39 #include "gnunet_tun_lib.h"
40 #include "gnunet_regex_service.h"
46 * Maximum number of messages we allow in the queue for cadet.
48 #define MAX_MESSAGE_QUEUE_SIZE 4
52 * State we keep for each of our channels.
57 * Information we track for each IP address to determine which channel
58 * to send the traffic over to the destination.
60 struct DestinationEntry;
63 * List of channels we keep for each destination port for a given
66 struct DestinationChannel
72 struct DestinationChannel *next;
77 struct DestinationChannel *prev;
80 * Destination entry list this `struct DestinationChannel` belongs with.
82 struct DestinationEntry *destination;
85 * Destination port this channel state is used for.
87 uint16_t destination_port;
93 * Information we track for each IP address to determine which channel
94 * to send the traffic over to the destination.
96 struct DestinationEntry
100 * Key under which this entry is in the 'destination_map' (only valid
101 * if 'heap_node != NULL').
103 struct GNUNET_HashCode key;
106 * Head of DLL of channels associated with this destination.
108 struct DestinationChannel *dt_head;
111 * Tail of DLL of channels associated with this destination.
113 struct DestinationChannel *dt_tail;
116 * Entry for this entry in the destination_heap.
118 struct GNUNET_CONTAINER_HeapNode *heap_node;
121 * #GNUNET_NO if this is a channel to an Internet-exit,
122 * #GNUNET_YES if this channel is to a service.
127 * Details about the connection (depending on is_service).
135 * The description of the service (only used for service channels).
137 struct GNUNET_HashCode service_descriptor;
140 * Peer offering the service.
142 struct GNUNET_PeerIdentity target;
144 } service_destination;
150 * Address family used (AF_INET or AF_INET6).
155 * IP address of the ultimate destination (only used for exit channels).
160 * Address if af is AF_INET.
165 * Address if af is AF_INET6.
178 * A messages we have in queue for a particular channel.
180 struct ChannelMessageQueueEntry
183 * This is a doubly-linked list.
185 struct ChannelMessageQueueEntry *next;
188 * This is a doubly-linked list.
190 struct ChannelMessageQueueEntry *prev;
193 * Number of bytes in @e msg.
198 * Message to transmit, allocated at the end of this struct.
205 * State we keep for each of our channels.
211 * Information about the channel to use, NULL if no channel
212 * is available right now.
214 struct GNUNET_CADET_Channel *channel;
217 * Active query with REGEX to locate exit.
219 struct GNUNET_REGEX_Search *search;
222 * Entry for this entry in the channel_heap, NULL as long as this
223 * channel state is not fully bound.
225 struct GNUNET_CONTAINER_HeapNode *heap_node;
228 * Head of list of messages scheduled for transmission.
230 struct ChannelMessageQueueEntry *tmq_head;
233 * Tail of list of messages scheduled for transmission.
235 struct ChannelMessageQueueEntry *tmq_tail;
238 * Destination to which this channel leads. Note that
239 * this struct is NOT in the destination_map (but a
240 * local copy) and that the 'heap_node' should always
243 struct DestinationEntry destination;
246 * Addess family used for this channel on the local TUN interface.
251 * Is this channel new (#GNUNET_NO), or did we exchange messages with the
252 * other side already (#GNUNET_YES)?
257 * Length of the doubly linked 'tmq_head/tmq_tail' list.
259 unsigned int tmq_length;
262 * IPPROTO_TCP or IPPROTO_UDP once bound.
267 * IP address of the source on our end, initially uninitialized.
272 * Address if af is AF_INET.
277 * Address if af is AF_INET6.
284 * Destination IP address used by the source on our end (this is the IP
285 * that we pick freely within the VPN's channel IP range).
290 * Address if af is AF_INET.
295 * Address if af is AF_INET6.
302 * Source port used by the sender on our end; 0 for uninitialized.
304 uint16_t source_port;
307 * Destination port used by the sender on our end; 0 for uninitialized.
309 uint16_t destination_port;
315 * Return value from #main().
317 static int global_ret;
320 * Configuration we use.
322 static const struct GNUNET_CONFIGURATION_Handle *cfg;
325 * Handle to the cadet service.
327 static struct GNUNET_CADET_Handle *cadet_handle;
330 * Map from IP address to destination information (possibly with a
331 * CADET channel handle for fast setup).
333 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
336 * Min-Heap sorted by activity time to expire old mappings.
338 static struct GNUNET_CONTAINER_Heap *destination_heap;
341 * Map from source and destination address (IP+port) to connection
342 * information (mostly with the respective CADET channel handle).
344 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
347 * Min-Heap sorted by activity time to expire old mappings; values are
348 * of type 'struct ChannelState'.
350 static struct GNUNET_CONTAINER_Heap *channel_heap;
355 static struct GNUNET_STATISTICS_Handle *stats;
358 * The handle to the VPN helper process "gnunet-helper-vpn".
360 static struct GNUNET_HELPER_Handle *helper_handle;
363 * Arguments to the vpn helper.
365 static char *vpn_argv[7];
368 * Length of the prefix of the VPN's IPv6 network.
370 static unsigned long long ipv6prefix;
373 * If there are more than this number of address-mappings, old ones
376 static unsigned long long max_destination_mappings;
379 * If there are more than this number of open channels, old ones
382 static unsigned long long max_channel_mappings;
386 * Compute the key under which we would store an entry in the
387 * #destination_map for the given IP address.
389 * @param af address family (AF_INET or AF_INET6)
390 * @param address IP address, struct in_addr or struct in6_addr
391 * @param key where to store the key
394 get_destination_key_from_ip (int af,
396 struct GNUNET_HashCode *key)
401 GNUNET_CRYPTO_hash (address,
402 sizeof (struct in_addr),
406 GNUNET_CRYPTO_hash (address,
407 sizeof (struct in6_addr),
418 * Compute the key under which we would store an entry in the
419 * channel_map for the given socket address pair.
421 * @param af address family (AF_INET or AF_INET6)
422 * @param protocol IPPROTO_TCP or IPPROTO_UDP
423 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
424 * @param source_port sender's source port
425 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
426 * @param destination_port sender's destination port
427 * @param key where to store the key
430 get_channel_key_from_ips (int af,
432 const void *source_ip,
433 uint16_t source_port,
434 const void *destination_ip,
435 uint16_t destination_port,
436 struct GNUNET_HashCode *key)
440 memset (key, 0, sizeof (struct GNUNET_HashCode));
441 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
442 so we put the ports in there (and hope for few collisions) */
444 GNUNET_memcpy (off, &source_port, sizeof (uint16_t));
445 off += sizeof (uint16_t);
446 GNUNET_memcpy (off, &destination_port, sizeof (uint16_t));
447 off += sizeof (uint16_t);
451 GNUNET_memcpy (off, source_ip, sizeof (struct in_addr));
452 off += sizeof (struct in_addr);
453 GNUNET_memcpy (off, destination_ip, sizeof (struct in_addr));
454 off += sizeof (struct in_addr);
457 GNUNET_memcpy (off, source_ip, sizeof (struct in6_addr));
458 off += sizeof (struct in6_addr);
459 GNUNET_memcpy (off, destination_ip, sizeof (struct in6_addr));
460 off += sizeof (struct in6_addr);
466 GNUNET_memcpy (off, &protocol, sizeof (uint8_t));
467 /* off += sizeof (uint8_t); */
472 * Notify the client about the result of its request.
474 * @param client client to notify
475 * @param request_id original request ID to include in response
476 * @param result_af resulting address family
477 * @param addr resulting IP address
480 send_client_reply (struct GNUNET_SERVICE_Client *client,
485 struct GNUNET_MQ_Envelope *env;
486 struct RedirectToIpResponseMessage *res;
492 rlen = sizeof (struct in_addr);
495 rlen = sizeof (struct in6_addr);
504 env = GNUNET_MQ_msg_extra (res,
506 GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
507 res->result_af = htonl (result_af);
508 res->request_id = request_id;
509 GNUNET_memcpy (&res[1],
512 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
518 * Free resources associated with a channel state.
520 * @param ts state to free
523 free_channel_state (struct ChannelState *ts)
525 struct GNUNET_HashCode key;
526 struct ChannelMessageQueueEntry *tnq;
527 struct GNUNET_CADET_Channel *channel;
529 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
530 "Cleaning up channel state\n");
531 if (NULL != (channel = ts->channel))
534 GNUNET_CADET_channel_destroy (channel);
537 GNUNET_STATISTICS_update (stats,
538 gettext_noop ("# Active channels"),
540 while (NULL != (tnq = ts->tmq_head))
542 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
548 GNUNET_assert (0 == ts->tmq_length);
549 GNUNET_assert (NULL == ts->destination.heap_node);
550 if (NULL != ts->search)
552 GNUNET_REGEX_search_cancel (ts->search);
555 if (NULL != ts->heap_node)
557 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
558 ts->heap_node = NULL;
559 get_channel_key_from_ips (ts->af,
564 ts->destination_port,
566 GNUNET_assert (GNUNET_YES ==
567 GNUNET_CONTAINER_multihashmap_remove (channel_map,
576 * Add the given message to the given channel and trigger the
577 * transmission process.
579 * @param ts channel to queue the message for
580 * @param env message to queue
583 send_to_channel (struct ChannelState *ts,
584 struct GNUNET_MQ_Envelope *env)
586 struct GNUNET_MQ_Handle *mq;
588 GNUNET_assert (NULL != ts->channel);
589 mq = GNUNET_CADET_get_mq (ts->channel);
592 if (GNUNET_MQ_get_length (mq) > MAX_MESSAGE_QUEUE_SIZE)
594 env = GNUNET_MQ_unsent_head (mq);
595 GNUNET_assert (NULL != env);
596 GNUNET_STATISTICS_update (stats,
597 gettext_noop ("# Messages dropped in cadet queue (overflow)"),
600 GNUNET_MQ_discard (env);
606 * Output destination of a channel for diagnostics.
608 * @param de destination to process
609 * @return diagnostic string describing destination
612 print_channel_destination (const struct DestinationEntry *de)
614 static char dest[256];
618 GNUNET_snprintf (dest,
621 GNUNET_i2s (&de->details.service_destination.target),
622 GNUNET_h2s (&de->details.service_destination.service_descriptor));
626 inet_ntop (de->details.exit_destination.af,
627 &de->details.exit_destination.ip,
636 * Function called whenever a channel is destroyed. Should clean up
637 * any associated state.
639 * @param cls our `struct ChannelState`
640 * @param channel connection to the other end (henceforth invalid)
643 channel_cleaner (void *cls,
644 const struct GNUNET_CADET_Channel *channel)
646 struct ChannelState *ts = cls;
648 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
649 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
650 "CADET notified us about death of channel to `%s'\n",
651 print_channel_destination (&ts->destination));
652 free_channel_state (ts);
657 * Synthesize a plausible ICMP payload for an ICMP error
658 * response on the given channel.
660 * @param ts channel information
661 * @param ipp IPv4 header to fill in (ICMP payload)
662 * @param udp "UDP" header to fill in (ICMP payload); might actually
663 * also be the first 8 bytes of the TCP header
666 make_up_icmpv4_payload (struct ChannelState *ts,
667 struct GNUNET_TUN_IPv4Header *ipp,
668 struct GNUNET_TUN_UdpHeader *udp)
670 GNUNET_TUN_initialize_ipv4_header (ipp,
672 sizeof (struct GNUNET_TUN_TcpHeader),
674 &ts->destination_ip.v4);
675 udp->source_port = htons (ts->source_port);
676 udp->destination_port = htons (ts->destination_port);
677 udp->len = htons (0);
678 udp->crc = htons (0);
683 * Synthesize a plausible ICMP payload for an ICMP error
684 * response on the given channel.
686 * @param ts channel information
687 * @param ipp IPv6 header to fill in (ICMP payload)
688 * @param udp "UDP" header to fill in (ICMP payload); might actually
689 * also be the first 8 bytes of the TCP header
692 make_up_icmpv6_payload (struct ChannelState *ts,
693 struct GNUNET_TUN_IPv6Header *ipp,
694 struct GNUNET_TUN_UdpHeader *udp)
696 GNUNET_TUN_initialize_ipv6_header (ipp,
698 sizeof (struct GNUNET_TUN_TcpHeader),
700 &ts->destination_ip.v6);
701 udp->source_port = htons (ts->source_port);
702 udp->destination_port = htons (ts->destination_port);
703 udp->len = htons (0);
704 udp->crc = htons (0);
709 * We got an ICMP packet back from the CADET channel. Check it is OK.
711 * @param cls our `struct ChannelState *`
712 * @param message the actual message
713 * @return #GNUNET_OK to keep the connection open,
714 * #GNUNET_SYSERR to close it (signal serious error)
717 check_icmp_back (void *cls,
718 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
720 struct ChannelState *ts = cls;
722 if (NULL == ts->heap_node)
725 return GNUNET_SYSERR;
727 if (AF_UNSPEC == ts->af)
730 return GNUNET_SYSERR;
737 * We got an ICMP packet back from the CADET channel. Pass it on to the
738 * local virtual interface via the helper.
740 * @param cls our `struct ChannelState *`
741 * @param message the actual message
744 handle_icmp_back (void *cls,
745 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
747 struct ChannelState *ts = cls;
750 GNUNET_STATISTICS_update (stats,
751 gettext_noop ("# ICMP packets received from cadet"),
754 mlen = ntohs (i2v->header.size) - sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
756 char sbuf[INET6_ADDRSTRLEN];
757 char dbuf[INET6_ADDRSTRLEN];
759 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
760 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
762 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
763 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
769 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
770 + sizeof (struct GNUNET_TUN_IcmpHeader)
771 + sizeof (struct GNUNET_MessageHeader) +
772 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
775 /* reserve some extra space in case we have an ICMP type here where
776 we will need to make up the payload ourselves */
777 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
778 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
779 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
780 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
781 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
782 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
783 tun->flags = htons (0);
784 tun->proto = htons (ETH_P_IPV4);
785 GNUNET_TUN_initialize_ipv4_header (ipv4,
787 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
788 &ts->destination_ip.v4,
790 *icmp = i2v->icmp_header;
791 GNUNET_memcpy (&icmp[1],
794 /* For some ICMP types, we need to adjust (make up) the payload here.
795 Also, depending on the AF used on the other side, we have to
796 do ICMP PT (translate ICMP types) */
797 switch (ntohl (i2v->af))
802 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
803 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
805 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
806 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
807 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
809 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
810 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
814 /* sender did not strip ICMP payload? */
818 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
819 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
820 make_up_icmpv4_payload (ts, ipp, udp);
825 GNUNET_STATISTICS_update (stats,
826 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
833 /* ICMP PT 6-to-4 and possibly making up payloads */
836 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
837 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
839 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
840 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
844 /* sender did not strip ICMP payload? */
848 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
849 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
850 make_up_icmpv4_payload (ts, ipp, udp);
853 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
854 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
856 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
857 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
861 /* sender did not strip ICMP payload? */
865 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
866 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
867 make_up_icmpv4_payload (ts, ipp, udp);
870 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
871 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
872 GNUNET_STATISTICS_update (stats,
873 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
876 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
877 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
879 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
880 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
884 GNUNET_STATISTICS_update (stats,
885 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
895 msg->size = htons (size);
896 GNUNET_TUN_calculate_icmp_checksum (icmp,
899 (void) GNUNET_HELPER_send (helper_handle,
908 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
909 + sizeof (struct GNUNET_TUN_IcmpHeader)
910 + sizeof (struct GNUNET_MessageHeader) +
911 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
914 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
915 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
916 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
917 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
918 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
919 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
920 tun->flags = htons (0);
921 tun->proto = htons (ETH_P_IPV6);
922 GNUNET_TUN_initialize_ipv6_header (ipv6,
924 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
925 &ts->destination_ip.v6,
927 *icmp = i2v->icmp_header;
928 GNUNET_memcpy (&icmp[1],
932 /* For some ICMP types, we need to adjust (make up) the payload here.
933 Also, depending on the AF used on the other side, we have to
934 do ICMP PT (translate ICMP types) */
935 switch (ntohl (i2v->af))
938 /* ICMP PT 4-to-6 and possibly making up payloads */
941 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
942 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
944 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
945 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
947 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
948 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
950 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
951 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
955 /* sender did not strip ICMP payload? */
959 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
960 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
961 make_up_icmpv6_payload (ts, ipp, udp);
964 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
965 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
967 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
968 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
972 /* sender did not strip ICMP payload? */
976 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
977 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
978 make_up_icmpv6_payload (ts, ipp, udp);
981 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
982 GNUNET_STATISTICS_update (stats,
983 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
988 GNUNET_STATISTICS_update (stats,
989 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
998 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
999 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1000 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1001 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1003 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1004 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1008 /* sender did not strip ICMP payload? */
1009 GNUNET_break_op (0);
1012 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1013 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1014 make_up_icmpv6_payload (ts, ipp, udp);
1017 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1020 GNUNET_break_op (0);
1021 GNUNET_STATISTICS_update (stats,
1022 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1029 GNUNET_break_op (0);
1032 msg->size = htons (size);
1033 GNUNET_TUN_calculate_icmp_checksum (icmp,
1035 (void) GNUNET_HELPER_send (helper_handle,
1045 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1046 GNUNET_TIME_absolute_get ().abs_value_us);
1047 GNUNET_CADET_receive_done (ts->channel);
1052 * We got a UDP packet back from the CADET channel. Check that it is OK.
1054 * @param cls our `struct ChannelState *`
1055 * @param reply the actual message
1056 * @return #GNUNET_OK to keep the connection open,
1057 * #GNUNET_SYSERR to close it (signal serious error)
1060 check_udp_back (void *cls,
1061 const struct GNUNET_EXIT_UdpReplyMessage *reply)
1063 struct ChannelState *ts = cls;
1065 if (NULL == ts->heap_node)
1067 GNUNET_break_op (0);
1068 return GNUNET_SYSERR;
1070 if (AF_UNSPEC == ts->af)
1072 GNUNET_break_op (0);
1073 return GNUNET_SYSERR;
1080 * We got a UDP packet back from the CADET channel. Pass it on to the
1081 * local virtual interface via the helper.
1083 * @param cls our `struct ChannelState *`
1084 * @param reply the actual message
1087 handle_udp_back (void *cls,
1088 const struct GNUNET_EXIT_UdpReplyMessage *reply)
1090 struct ChannelState *ts = cls;
1093 GNUNET_STATISTICS_update (stats,
1094 gettext_noop ("# UDP packets received from cadet"),
1097 mlen = ntohs (reply->header.size) - sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1099 char sbuf[INET6_ADDRSTRLEN];
1100 char dbuf[INET6_ADDRSTRLEN];
1102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1103 "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1104 (unsigned int) mlen,
1105 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1106 ts->destination_port,
1107 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1114 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1115 + sizeof (struct GNUNET_TUN_UdpHeader)
1116 + sizeof (struct GNUNET_MessageHeader) +
1117 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1120 char buf[size] GNUNET_ALIGN;
1121 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1122 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1123 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1124 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1125 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1126 msg->size = htons (size);
1127 tun->flags = htons (0);
1128 tun->proto = htons (ETH_P_IPV4);
1129 GNUNET_TUN_initialize_ipv4_header (ipv4,
1131 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1132 &ts->destination_ip.v4,
1134 if (0 == ntohs (reply->source_port))
1135 udp->source_port = htons (ts->destination_port);
1137 udp->source_port = reply->source_port;
1138 if (0 == ntohs (reply->destination_port))
1139 udp->destination_port = htons (ts->source_port);
1141 udp->destination_port = reply->destination_port;
1142 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1143 GNUNET_TUN_calculate_udp4_checksum (ipv4,
1147 GNUNET_memcpy (&udp[1],
1150 (void) GNUNET_HELPER_send (helper_handle,
1159 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1160 + sizeof (struct GNUNET_TUN_UdpHeader)
1161 + sizeof (struct GNUNET_MessageHeader) +
1162 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1165 char buf[size] GNUNET_ALIGN;
1166 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1167 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1168 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1169 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1170 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1171 msg->size = htons (size);
1172 tun->flags = htons (0);
1173 tun->proto = htons (ETH_P_IPV6);
1174 GNUNET_TUN_initialize_ipv6_header (ipv6,
1176 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1177 &ts->destination_ip.v6,
1179 if (0 == ntohs (reply->source_port))
1180 udp->source_port = htons (ts->destination_port);
1182 udp->source_port = reply->source_port;
1183 if (0 == ntohs (reply->destination_port))
1184 udp->destination_port = htons (ts->source_port);
1186 udp->destination_port = reply->destination_port;
1187 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1188 GNUNET_TUN_calculate_udp6_checksum (ipv6,
1191 GNUNET_memcpy (&udp[1],
1194 (void) GNUNET_HELPER_send (helper_handle,
1204 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1205 GNUNET_TIME_absolute_get ().abs_value_us);
1206 GNUNET_CADET_receive_done (ts->channel);
1211 * We got a TCP packet back from the CADET channel. Check it is OK.
1213 * @param cls our `struct ChannelState *`
1214 * @param data the actual message
1215 * @return #GNUNET_OK to keep the connection open,
1216 * #GNUNET_SYSERR to close it (signal serious error)
1219 check_tcp_back (void *cls,
1220 const struct GNUNET_EXIT_TcpDataMessage *data)
1222 struct ChannelState *ts = cls;
1224 if (NULL == ts->heap_node)
1226 GNUNET_break_op (0);
1227 return GNUNET_SYSERR;
1229 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1231 GNUNET_break_op (0);
1232 return GNUNET_SYSERR;
1239 * We got a TCP packet back from the CADET channel. Pass it on to the
1240 * local virtual interface via the helper.
1242 * @param cls our `struct ChannelState *`
1243 * @param data the actual message
1246 handle_tcp_back (void *cls,
1247 const struct GNUNET_EXIT_TcpDataMessage *data)
1249 struct ChannelState *ts = cls;
1252 GNUNET_STATISTICS_update (stats,
1253 gettext_noop ("# TCP packets received from cadet"),
1256 mlen = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1258 char sbuf[INET6_ADDRSTRLEN];
1259 char dbuf[INET6_ADDRSTRLEN];
1261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1262 "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1263 (unsigned int) mlen,
1264 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1265 ts->destination_port,
1266 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1273 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1274 + sizeof (struct GNUNET_TUN_TcpHeader)
1275 + sizeof (struct GNUNET_MessageHeader) +
1276 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1279 char buf[size] GNUNET_ALIGN;
1280 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1281 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1282 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1283 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1284 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1285 msg->size = htons (size);
1286 tun->flags = htons (0);
1287 tun->proto = htons (ETH_P_IPV4);
1288 GNUNET_TUN_initialize_ipv4_header (ipv4,
1290 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1291 &ts->destination_ip.v4,
1293 *tcp = data->tcp_header;
1294 tcp->source_port = htons (ts->destination_port);
1295 tcp->destination_port = htons (ts->source_port);
1296 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
1300 GNUNET_memcpy (&tcp[1],
1303 (void) GNUNET_HELPER_send (helper_handle,
1312 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1313 + sizeof (struct GNUNET_TUN_TcpHeader)
1314 + sizeof (struct GNUNET_MessageHeader) +
1315 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1318 char buf[size] GNUNET_ALIGN;
1319 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1320 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1321 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1322 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1323 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1324 msg->size = htons (size);
1325 tun->flags = htons (0);
1326 tun->proto = htons (ETH_P_IPV6);
1327 GNUNET_TUN_initialize_ipv6_header (ipv6,
1329 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1330 &ts->destination_ip.v6,
1332 *tcp = data->tcp_header;
1333 tcp->source_port = htons (ts->destination_port);
1334 tcp->destination_port = htons (ts->source_port);
1335 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
1339 GNUNET_memcpy (&tcp[1],
1342 (void) GNUNET_HELPER_send (helper_handle,
1350 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1351 GNUNET_TIME_absolute_get ().abs_value_us);
1352 GNUNET_CADET_receive_done (ts->channel);
1357 * Create a channel for @a ts to @a target at @a port
1359 * @param ts channel state to create the channel for
1360 * @param target peer to connect to
1361 * @param port destination port
1362 * @return the channel handle
1364 static struct GNUNET_CADET_Channel *
1365 create_channel (struct ChannelState *ts,
1366 const struct GNUNET_PeerIdentity *target,
1367 const struct GNUNET_HashCode *port)
1369 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1370 GNUNET_MQ_hd_var_size (udp_back,
1371 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY,
1372 struct GNUNET_EXIT_UdpReplyMessage,
1374 GNUNET_MQ_hd_var_size (tcp_back,
1375 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN,
1376 struct GNUNET_EXIT_TcpDataMessage,
1378 GNUNET_MQ_hd_var_size (icmp_back,
1379 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN,
1380 struct GNUNET_EXIT_IcmpToVPNMessage,
1382 GNUNET_MQ_handler_end()
1385 return GNUNET_CADET_channel_create (cadet_handle,
1389 GNUNET_CADET_OPTION_DEFAULT,
1397 * Regex has found a potential exit peer for us; consider using it.
1399 * @param cls the `struct ChannelState`
1400 * @param id Peer providing a regex that matches the string.
1401 * @param get_path Path of the get request.
1402 * @param get_path_length Lenght of @a get_path.
1403 * @param put_path Path of the put request.
1404 * @param put_path_length Length of the @a put_path.
1407 handle_regex_result (void *cls,
1408 const struct GNUNET_PeerIdentity *id,
1409 const struct GNUNET_PeerIdentity *get_path,
1410 unsigned int get_path_length,
1411 const struct GNUNET_PeerIdentity *put_path,
1412 unsigned int put_path_length)
1414 struct ChannelState *ts = cls;
1415 struct GNUNET_HashCode port;
1417 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1418 "Exit %s found for destination %s!\n",
1420 print_channel_destination (&ts->destination));
1421 GNUNET_REGEX_search_cancel (ts->search);
1426 /* these must match the strings used in gnunet-daemon-exit */
1427 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
1428 strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
1432 /* these must match the strings used in gnunet-daemon-exit */
1433 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
1434 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
1441 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1442 "Creating tunnel to %s for destination %s!\n",
1444 print_channel_destination (&ts->destination));
1445 ts->channel = create_channel (ts,
1452 * Initialize the given destination entry's cadet channel.
1454 * @param dt destination channel for which we need to setup a channel
1455 * @param client_af address family of the address returned to the client
1456 * @return channel state of the channel that was created
1458 static struct ChannelState *
1459 create_channel_to_destination (struct DestinationChannel *dt,
1462 struct ChannelState *ts;
1464 GNUNET_STATISTICS_update (stats,
1465 gettext_noop ("# Cadet channels created"),
1468 ts = GNUNET_new (struct ChannelState);
1470 ts->destination = *dt->destination;
1471 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
1472 ts->destination_port = dt->destination_port;
1473 if (dt->destination->is_service)
1475 struct GNUNET_HashCode cadet_port;
1477 GNUNET_TUN_compute_service_cadet_port (&ts->destination.details.service_destination.service_descriptor,
1478 ts->destination_port,
1480 ts->channel = create_channel (ts,
1481 &dt->destination->details.service_destination.target,
1484 if (NULL == ts->channel)
1490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1491 "Creating channel to peer %s offering service %s on port %u\n",
1492 GNUNET_i2s (&dt->destination->details.service_destination.target),
1493 GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor),
1494 (unsigned int) ts->destination_port);
1500 switch (dt->destination->details.exit_destination.af)
1504 char address[GNUNET_TUN_IPV4_REGEXLEN];
1506 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
1507 dt->destination_port,
1509 GNUNET_asprintf (&policy,
1511 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1517 char address[GNUNET_TUN_IPV6_REGEXLEN];
1519 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
1520 dt->destination_port,
1522 GNUNET_asprintf (&policy,
1524 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1533 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1534 "Requesting connect by string: %s\n",
1536 ts->search = GNUNET_REGEX_search (cfg,
1538 &handle_regex_result,
1540 GNUNET_free (policy);
1547 * We have too many active channels. Clean up the oldest channel.
1549 * @param except channel that must NOT be cleaned up, even if it is the oldest
1552 expire_channel (struct ChannelState *except)
1554 struct ChannelState *ts;
1556 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
1557 GNUNET_assert (NULL != ts);
1559 return; /* can't do this */
1560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1561 "Tearing down expired channel to %s\n",
1562 print_channel_destination (&except->destination));
1563 free_channel_state (ts);
1568 * Route a packet via cadet to the given destination.
1570 * @param destination description of the destination
1571 * @param af address family on this end (AF_INET or AF_INET6)
1572 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
1573 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
1574 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
1575 * @param payload payload of the packet after the IP header
1576 * @param payload_length number of bytes in @a payload
1579 route_packet (struct DestinationEntry *destination,
1582 const void *source_ip,
1583 const void *destination_ip,
1584 const void *payload,
1585 size_t payload_length)
1587 struct GNUNET_HashCode key;
1588 struct ChannelState *ts;
1591 struct GNUNET_MQ_Envelope *env;
1592 const struct GNUNET_TUN_UdpHeader *udp;
1593 const struct GNUNET_TUN_TcpHeader *tcp;
1594 const struct GNUNET_TUN_IcmpHeader *icmp;
1595 struct DestinationChannel *dt;
1596 uint16_t source_port;
1597 uint16_t destination_port;
1603 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1609 tcp = NULL; /* make compiler happy */
1610 icmp = NULL; /* make compiler happy */
1612 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1614 GNUNET_break_op (0);
1617 source_port = ntohs (udp->source_port);
1618 destination_port = ntohs (udp->destination_port);
1619 get_channel_key_from_ips (af,
1630 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1636 udp = NULL; /* make compiler happy */
1637 icmp = NULL; /* make compiler happy */
1639 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1641 GNUNET_break_op (0);
1644 source_port = ntohs (tcp->source_port);
1645 destination_port = ntohs (tcp->destination_port);
1646 get_channel_key_from_ips (af,
1656 case IPPROTO_ICMPV6:
1658 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1663 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1669 tcp = NULL; /* make compiler happy */
1670 udp = NULL; /* make compiler happy */
1673 destination_port = 0;
1674 get_channel_key_from_ips (af,
1684 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1685 _("Protocol %u not supported, dropping\n"),
1686 (unsigned int) protocol);
1690 if (! destination->is_service)
1692 switch (destination->details.exit_destination.af)
1695 alen = sizeof (struct in_addr);
1698 alen = sizeof (struct in6_addr);
1705 char sbuf[INET6_ADDRSTRLEN];
1706 char dbuf[INET6_ADDRSTRLEN];
1707 char xbuf[INET6_ADDRSTRLEN];
1709 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1710 "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1711 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1722 inet_ntop (destination->details.exit_destination.af,
1723 &destination->details.exit_destination.ip,
1724 xbuf, sizeof (xbuf)),
1727 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1728 if (dt->destination_port == destination_port)
1734 char sbuf[INET6_ADDRSTRLEN];
1735 char dbuf[INET6_ADDRSTRLEN];
1737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1738 "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1739 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1750 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1751 GNUNET_i2s (&destination->details.service_destination.target));
1753 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1754 if (dt->destination_port == destination_port)
1759 dt = GNUNET_new (struct DestinationChannel);
1760 dt->destination = destination;
1761 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1762 destination->dt_tail,
1764 dt->destination_port = destination_port;
1767 /* see if we have an existing channel for this destination */
1768 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1773 "Creating new channel for key %s\n",
1775 /* need to either use the existing channel from the destination (if still
1776 available) or create a fresh one */
1777 ts = create_channel_to_destination (dt,
1781 /* now bind existing "unbound" channel to our IP/port tuple */
1782 ts->protocol = protocol;
1786 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1787 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1791 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1792 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1794 ts->source_port = source_port;
1795 ts->destination_port = destination_port;
1796 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1798 GNUNET_TIME_absolute_get ().abs_value_us);
1799 GNUNET_assert (GNUNET_YES ==
1800 GNUNET_CONTAINER_multihashmap_put (channel_map,
1803 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1804 GNUNET_STATISTICS_update (stats,
1805 gettext_noop ("# Active channels"),
1807 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1808 expire_channel (ts);
1812 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1813 GNUNET_TIME_absolute_get ().abs_value_us);
1815 if (NULL == ts->channel)
1817 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1818 "Packet dropped, channel to %s not yet ready (%s)\n",
1819 print_channel_destination (&ts->destination),
1820 (NULL == ts->search)
1821 ? "EXIT search failed"
1822 : "EXIT search active");
1823 GNUNET_STATISTICS_update (stats,
1824 gettext_noop ("# Packets dropped (channel not yet online)"),
1830 /* send via channel */
1834 if (destination->is_service)
1836 struct GNUNET_EXIT_UdpServiceMessage *usm;
1838 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1839 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1840 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1845 env = GNUNET_MQ_msg_extra (usm,
1846 payload_length - sizeof (struct GNUNET_TUN_UdpHeader),
1847 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1848 /* if the source port is below 32000, we assume it has a special
1849 meaning; if not, we pick a random port (this is a heuristic) */
1850 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1851 usm->destination_port = udp->destination_port;
1852 GNUNET_memcpy (&usm[1],
1854 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1858 struct GNUNET_EXIT_UdpInternetMessage *uim;
1859 struct in_addr *ip4dst;
1860 struct in6_addr *ip6dst;
1863 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1864 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1865 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1870 env = GNUNET_MQ_msg_extra (uim,
1871 payload_length + alen - sizeof (struct GNUNET_TUN_UdpHeader),
1872 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1873 uim->af = htonl (destination->details.exit_destination.af);
1874 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1875 uim->destination_port = udp->destination_port;
1876 switch (destination->details.exit_destination.af)
1879 ip4dst = (struct in_addr *) &uim[1];
1880 *ip4dst = destination->details.exit_destination.ip.v4;
1881 payload = &ip4dst[1];
1884 ip6dst = (struct in6_addr *) &uim[1];
1885 *ip6dst = destination->details.exit_destination.ip.v6;
1886 payload = &ip6dst[1];
1891 GNUNET_memcpy (payload,
1893 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1897 if (GNUNET_NO == ts->is_established)
1899 if (destination->is_service)
1901 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1903 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1904 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1905 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1910 env = GNUNET_MQ_msg_extra (tsm,
1911 payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1912 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1913 tsm->reserved = htonl (0);
1914 tsm->tcp_header = *tcp;
1915 GNUNET_memcpy (&tsm[1],
1917 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1921 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1922 struct in_addr *ip4dst;
1923 struct in6_addr *ip6dst;
1926 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1927 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1928 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1933 env = GNUNET_MQ_msg_extra (tim,
1934 payload_length + alen - sizeof (struct GNUNET_TUN_TcpHeader),
1935 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1936 tim->af = htonl (destination->details.exit_destination.af);
1937 tim->tcp_header = *tcp;
1938 switch (destination->details.exit_destination.af)
1941 ip4dst = (struct in_addr *) &tim[1];
1942 *ip4dst = destination->details.exit_destination.ip.v4;
1943 payload = &ip4dst[1];
1946 ip6dst = (struct in6_addr *) &tim[1];
1947 *ip6dst = destination->details.exit_destination.ip.v6;
1948 payload = &ip6dst[1];
1953 GNUNET_memcpy (payload,
1955 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1960 struct GNUNET_EXIT_TcpDataMessage *tdm;
1962 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1963 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1964 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1969 env = GNUNET_MQ_msg_extra (tdm,
1970 payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1971 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1972 tdm->reserved = htonl (0);
1973 tdm->tcp_header = *tcp;
1974 GNUNET_memcpy (&tdm[1],
1976 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1980 case IPPROTO_ICMPV6:
1981 if (destination->is_service)
1983 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1985 /* ICMP protocol translation will be done by the receiver (as we don't know
1986 the target AF); however, we still need to possibly discard the payload
1987 depending on the ICMP type */
1993 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1994 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1996 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1997 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1998 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1999 /* throw away ICMP payload, won't be useful for the other side anyway */
2000 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2003 GNUNET_STATISTICS_update (stats,
2004 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
2008 /* end of AF_INET */
2013 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2014 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2015 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2016 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2017 /* throw away ICMP payload, won't be useful for the other side anyway */
2018 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2020 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2021 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2024 GNUNET_STATISTICS_update (stats,
2025 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
2029 /* end of AF_INET6 */
2036 /* update length calculations, as payload_length may have changed */
2037 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
2038 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2039 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2045 env = GNUNET_MQ_msg_extra (ism,
2046 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2047 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
2048 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
2049 ism->icmp_header = *icmp;
2050 GNUNET_memcpy (&ism[1],
2052 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2056 struct GNUNET_EXIT_IcmpInternetMessage *iim;
2057 struct in_addr *ip4dst;
2058 struct in6_addr *ip6dst;
2062 new_type = icmp->type;
2063 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2064 and throw away ICMP payload depending on ICMP message type */
2070 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2071 if (destination->details.exit_destination.af == AF_INET6)
2072 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2074 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2075 if (destination->details.exit_destination.af == AF_INET6)
2076 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2078 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2079 if (destination->details.exit_destination.af == AF_INET6)
2080 new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2081 /* throw away IP-payload, exit will have to make it up anyway */
2082 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2084 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2085 if (destination->details.exit_destination.af == AF_INET6)
2086 new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2087 /* throw away IP-payload, exit will have to make it up anyway */
2088 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2090 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2091 if (destination->details.exit_destination.af == AF_INET6)
2093 GNUNET_STATISTICS_update (stats,
2094 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2098 /* throw away IP-payload, exit will have to make it up anyway */
2099 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2102 GNUNET_STATISTICS_update (stats,
2103 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2107 /* end of AF_INET */
2112 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2113 if (destination->details.exit_destination.af == AF_INET)
2114 new_type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2115 /* throw away IP-payload, exit will have to make it up anyway */
2116 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2118 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2119 if (destination->details.exit_destination.af == AF_INET)
2120 new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2121 /* throw away IP-payload, exit will have to make it up anyway */
2122 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2124 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2125 if (destination->details.exit_destination.af == AF_INET)
2127 GNUNET_STATISTICS_update (stats,
2128 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2132 /* throw away IP-payload, exit will have to make it up anyway */
2133 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2135 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2136 if (destination->details.exit_destination.af == AF_INET)
2138 GNUNET_STATISTICS_update (stats,
2139 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2143 /* throw away IP-payload, exit will have to make it up anyway */
2144 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2146 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2147 if (destination->details.exit_destination.af == AF_INET)
2148 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2150 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2151 if (destination->details.exit_destination.af == AF_INET)
2152 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2155 GNUNET_STATISTICS_update (stats,
2156 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2160 /* end of AF_INET6 */
2166 /* update length calculations, as payload_length may have changed */
2167 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
2168 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2169 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2174 env = GNUNET_MQ_msg_extra (iim,
2175 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2176 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
2177 iim->icmp_header = *icmp;
2178 iim->icmp_header.type = new_type;
2179 iim->af = htonl (destination->details.exit_destination.af);
2180 switch (destination->details.exit_destination.af)
2183 ip4dst = (struct in_addr *) &iim[1];
2184 *ip4dst = destination->details.exit_destination.ip.v4;
2185 payload = &ip4dst[1];
2188 ip6dst = (struct in6_addr *) &iim[1];
2189 *ip6dst = destination->details.exit_destination.ip.v6;
2190 payload = &ip6dst[1];
2195 GNUNET_memcpy (payload,
2197 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2201 /* not supported above, how can we get here !? */
2205 ts->is_established = GNUNET_YES;
2206 send_to_channel (ts,
2212 * Receive packets from the helper-process (someone send to the local
2213 * virtual channel interface). Find the destination mapping, and if it
2214 * exists, identify the correct CADET channel (or possibly create it)
2215 * and forward the packet.
2217 * @param cls closure, NULL
2218 * @param message message we got from the client (VPN channel interface)
2219 * @return #GNUNET_OK on success,
2220 * #GNUNET_NO to stop further processing (no error)
2221 * #GNUNET_SYSERR to stop further processing with error
2224 message_token (void *cls,
2225 const struct GNUNET_MessageHeader *message)
2227 const struct GNUNET_TUN_Layer2PacketHeader *tun;
2229 struct GNUNET_HashCode key;
2230 struct DestinationEntry *de;
2232 GNUNET_STATISTICS_update (stats,
2233 gettext_noop ("# Packets received from TUN interface"),
2235 mlen = ntohs (message->size);
2236 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2237 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
2242 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2243 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
2244 switch (ntohs (tun->proto))
2248 const struct GNUNET_TUN_IPv6Header *pkt6;
2250 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
2256 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2257 get_destination_key_from_ip (AF_INET6,
2258 &pkt6->destination_address,
2260 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2263 char buf[INET6_ADDRSTRLEN];
2265 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2266 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2267 inet_ntop (AF_INET6,
2268 &pkt6->destination_address,
2276 &pkt6->source_address,
2277 &pkt6->destination_address,
2279 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
2284 struct GNUNET_TUN_IPv4Header *pkt4;
2286 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
2292 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2293 get_destination_key_from_ip (AF_INET,
2294 &pkt4->destination_address,
2296 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2299 char buf[INET_ADDRSTRLEN];
2301 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2302 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2304 &pkt4->destination_address,
2309 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2311 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2312 _("Received IPv4 packet with options (dropping it)\n"));
2318 &pkt4->source_address,
2319 &pkt4->destination_address,
2321 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
2325 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2326 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2327 (unsigned int) ntohs (tun->proto));
2335 * Allocate an IPv4 address from the range of the channel
2336 * for a new redirection.
2338 * @param v4 where to store the address
2339 * @return #GNUNET_OK on success,
2340 * #GNUNET_SYSERR on error
2343 allocate_v4_address (struct in_addr *v4)
2345 const char *ipv4addr = vpn_argv[4];
2346 const char *ipv4mask = vpn_argv[5];
2347 struct in_addr addr;
2348 struct in_addr mask;
2350 struct GNUNET_HashCode key;
2353 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2354 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2355 /* Given 192.168.0.1/255.255.0.0, we want a mask
2356 of '192.168.255.255', thus: */
2357 mask.s_addr = addr.s_addr | ~mask.s_addr;
2364 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2365 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2366 return GNUNET_SYSERR;
2368 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2369 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2371 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2372 get_destination_key_from_ip (AF_INET,
2376 while ( (GNUNET_YES ==
2377 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2379 (v4->s_addr == addr.s_addr) ||
2380 (v4->s_addr == mask.s_addr) );
2386 * Allocate an IPv6 address from the range of the channel
2387 * for a new redirection.
2389 * @param v6 where to store the address
2390 * @return #GNUNET_OK on success,
2391 * #GNUNET_SYSERR on error
2394 allocate_v6_address (struct in6_addr *v6)
2396 const char *ipv6addr = vpn_argv[2];
2397 struct in6_addr addr;
2398 struct in6_addr mask;
2399 struct in6_addr rnd;
2401 struct GNUNET_HashCode key;
2404 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2405 GNUNET_assert (ipv6prefix < 128);
2406 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2409 for (i=127;i>=ipv6prefix;i--)
2410 mask.s6_addr[i / 8] |= (1 << (i % 8));
2412 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2419 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2420 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2421 return GNUNET_SYSERR;
2426 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2429 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2431 get_destination_key_from_ip (AF_INET6,
2435 while ( (GNUNET_YES ==
2436 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2440 sizeof (struct in6_addr))) ||
2443 sizeof (struct in6_addr))) );
2449 * Free resources occupied by a destination entry.
2451 * @param de entry to free
2454 free_destination_entry (struct DestinationEntry *de)
2456 struct DestinationChannel *dt;
2458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2459 "Cleaning up destination entry `%s'\n",
2460 print_channel_destination (de));
2461 GNUNET_STATISTICS_update (stats,
2462 gettext_noop ("# Active destinations"),
2464 while (NULL != (dt = de->dt_head))
2466 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2471 if (NULL != de->heap_node)
2473 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2474 de->heap_node = NULL;
2475 GNUNET_assert (GNUNET_YES ==
2476 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2485 * We have too many active destinations. Clean up the oldest destination.
2487 * @param except destination that must NOT be cleaned up, even if it is the oldest
2490 expire_destination (struct DestinationEntry *except)
2492 struct DestinationEntry *de;
2494 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2495 GNUNET_assert (NULL != de);
2497 return; /* can't do this */
2498 free_destination_entry (de);
2503 * Allocate an IP address for the response.
2505 * @param result_af desired address family; set to the actual
2506 * address family; can initially be AF_UNSPEC if there
2507 * is no preference; will be set to AF_UNSPEC if the
2509 * @param addr set to either v4 or v6 depending on which
2510 * storage location was used; set to NULL if allocation failed
2511 * @param v4 storage space for an IPv4 address
2512 * @param v6 storage space for an IPv6 address
2513 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2514 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2517 allocate_response_ip (int *result_af,
2520 struct in6_addr *v6)
2527 allocate_v4_address (v4))
2528 *result_af = AF_UNSPEC;
2534 allocate_v6_address (v6))
2535 *result_af = AF_UNSPEC;
2541 allocate_v4_address (v4))
2544 *result_af = AF_INET;
2546 else if (GNUNET_OK ==
2547 allocate_v6_address (v6))
2550 *result_af = AF_INET6;
2555 return GNUNET_SYSERR;
2562 * A client asks us to setup a redirection via some exit node to a
2563 * particular IP. Check if @a msg is well-formed.
2566 * @param cls client requesting client
2567 * @param msg redirection request
2568 * @return #GNUNET_OK if @a msg is well-formed
2571 check_client_redirect_to_ip (void *cls,
2572 const struct RedirectToIpRequestMessage *msg)
2577 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2578 addr_af = (int) htonl (msg->addr_af);
2582 if (alen != sizeof (struct in_addr))
2585 return GNUNET_SYSERR;
2589 if (alen != sizeof (struct in6_addr))
2592 return GNUNET_SYSERR;
2597 return GNUNET_SYSERR;
2604 * A client asks us to setup a redirection via some exit node to a
2605 * particular IP. Setup the redirection and give the client the
2608 * @param cls client requesting client
2609 * @param msg redirection request
2612 handle_client_redirect_to_ip (void *cls,
2613 const struct RedirectToIpRequestMessage *msg)
2615 struct GNUNET_SERVICE_Client *client = cls;
2622 struct DestinationEntry *de;
2623 struct GNUNET_HashCode key;
2625 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2626 addr_af = (int) htonl (msg->addr_af);
2627 /* allocate response IP */
2628 result_af = (int) htonl (msg->result_af);
2629 if (GNUNET_OK != allocate_response_ip (&result_af,
2633 GNUNET_SERVICE_client_drop (client);
2636 /* send reply with our IP address */
2637 send_client_reply (client,
2641 if (result_af == AF_UNSPEC)
2643 /* failure, we're done */
2644 GNUNET_SERVICE_client_continue (client);
2649 char sbuf[INET6_ADDRSTRLEN];
2650 char dbuf[INET6_ADDRSTRLEN];
2652 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2653 "Allocated address %s for redirection via exit to %s\n",
2654 inet_ntop (result_af,
2664 /* setup destination record */
2665 de = GNUNET_new (struct DestinationEntry);
2666 de->is_service = GNUNET_NO;
2667 de->details.exit_destination.af = addr_af;
2668 GNUNET_memcpy (&de->details.exit_destination.ip,
2671 get_destination_key_from_ip (result_af,
2675 GNUNET_assert (GNUNET_OK ==
2676 GNUNET_CONTAINER_multihashmap_put (destination_map,
2679 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2680 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2682 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2683 GNUNET_STATISTICS_update (stats,
2684 gettext_noop ("# Active destinations"),
2686 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2687 expire_destination (de);
2688 GNUNET_SERVICE_client_continue (client);
2693 * A client asks us to setup a redirection to a particular peer
2694 * offering a service. Setup the redirection and give the client the
2697 * @param cls requesting client
2698 * @param msg redirection request
2701 handle_client_redirect_to_service (void *cls,
2702 const struct RedirectToServiceRequestMessage *msg)
2704 struct GNUNET_SERVICE_Client *client = cls;
2709 struct DestinationEntry *de;
2710 struct GNUNET_HashCode key;
2711 struct DestinationChannel *dt;
2713 /* allocate response IP */
2714 result_af = (int) htonl (msg->result_af);
2716 allocate_response_ip (&result_af,
2722 GNUNET_SERVICE_client_drop (client);
2725 send_client_reply (client,
2729 if (result_af == AF_UNSPEC)
2731 /* failure, we're done */
2732 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2733 _("Failed to allocate IP address for new destination\n"));
2734 GNUNET_SERVICE_client_continue (client);
2739 char sbuf[INET6_ADDRSTRLEN];
2741 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2742 "Allocated address %s for redirection to service %s on peer %s\n",
2743 inet_ntop (result_af,
2747 GNUNET_h2s (&msg->service_descriptor),
2748 GNUNET_i2s (&msg->target));
2751 /* setup destination record */
2752 de = GNUNET_new (struct DestinationEntry);
2753 de->is_service = GNUNET_YES;
2754 de->details.service_destination.target = msg->target;
2755 de->details.service_destination.service_descriptor = msg->service_descriptor;
2756 get_destination_key_from_ip (result_af,
2760 GNUNET_assert (GNUNET_OK ==
2761 GNUNET_CONTAINER_multihashmap_put (destination_map,
2764 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2766 = GNUNET_CONTAINER_heap_insert (destination_heap,
2768 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2769 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2770 expire_destination (de);
2772 dt = GNUNET_new (struct DestinationChannel);
2773 dt->destination = de;
2774 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2778 GNUNET_SERVICE_client_continue (client);
2784 * Free memory occupied by an entry in the destination map.
2788 * @param value a `struct DestinationEntry *`
2789 * @return #GNUNET_OK (continue to iterate)
2792 cleanup_destination (void *cls,
2793 const struct GNUNET_HashCode *key,
2796 struct DestinationEntry *de = value;
2798 free_destination_entry (de);
2804 * Free memory occupied by an entry in the channel map.
2808 * @param value a `struct ChannelState *`
2809 * @return #GNUNET_OK (continue to iterate)
2812 cleanup_channel (void *cls,
2813 const struct GNUNET_HashCode *key,
2816 struct ChannelState *ts = value;
2818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2819 "Tearing down channel to `%s' during cleanup\n",
2820 print_channel_destination (&ts->destination));
2821 free_channel_state (ts);
2827 * Function scheduled as very last function, cleans up after us
2836 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2837 "VPN is shutting down\n");
2838 if (NULL != destination_map)
2840 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2841 &cleanup_destination,
2843 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2844 destination_map = NULL;
2846 if (NULL != destination_heap)
2848 GNUNET_CONTAINER_heap_destroy (destination_heap);
2849 destination_heap = NULL;
2851 if (NULL != channel_map)
2853 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2856 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2859 if (NULL != channel_heap)
2861 GNUNET_CONTAINER_heap_destroy (channel_heap);
2862 channel_heap = NULL;
2864 if (NULL != cadet_handle)
2866 GNUNET_CADET_disconnect (cadet_handle);
2867 cadet_handle = NULL;
2869 if (NULL != helper_handle)
2871 GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2872 GNUNET_HELPER_wait (helper_handle);
2873 helper_handle = NULL;
2877 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2881 GNUNET_free_non_null (vpn_argv[i]);
2886 * Callback called when a client connects to the service.
2888 * @param cls closure for the service
2889 * @param c the new client that connected to the service
2890 * @param mq the message queue used to send messages to the client
2894 client_connect_cb (void *cls,
2895 struct GNUNET_SERVICE_Client *c,
2896 struct GNUNET_MQ_Handle *mq)
2903 * Callback called when a client disconnected from the service
2905 * @param cls closure for the service
2906 * @param c the client that disconnected
2907 * @param internal_cls should be equal to @a c
2910 client_disconnect_cb (void *cls,
2911 struct GNUNET_SERVICE_Client *c,
2914 GNUNET_assert (c == internal_cls);
2919 * Main function that will be run by the scheduler.
2921 * @param cls closure
2922 * @param cfg_ configuration
2923 * @param service the initialized service
2927 const struct GNUNET_CONFIGURATION_Handle *cfg_,
2928 struct GNUNET_SERVICE_Handle *service)
2939 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2942 GNUNET_OS_check_helper_binary (binary,
2944 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2947 "`%s' is not SUID, refusing to run.\n",
2948 "gnunet-helper-vpn");
2949 GNUNET_free (binary);
2951 /* we won't "really" exit here, as the 'service' is still running;
2952 however, as no handlers are registered, the service won't do
2956 GNUNET_free (binary);
2958 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2960 GNUNET_CONFIGURATION_get_value_number (cfg,
2963 &max_destination_mappings))
2964 max_destination_mappings = 200;
2966 GNUNET_CONFIGURATION_get_value_number (cfg,
2969 &max_channel_mappings))
2970 max_channel_mappings = 200;
2972 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2973 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2974 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2975 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2978 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2979 if (GNUNET_SYSERR ==
2980 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2982 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2983 GNUNET_SCHEDULER_shutdown ();
2986 vpn_argv[1] = ifname;
2988 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2990 if ( (GNUNET_SYSERR ==
2991 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2993 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2995 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2996 _("Must specify valid IPv6 address"));
2997 GNUNET_SCHEDULER_shutdown ();
2998 GNUNET_free_non_null (ipv6addr);
3001 vpn_argv[2] = ipv6addr;
3002 ipv6prefix_s = NULL;
3003 if (GNUNET_SYSERR ==
3004 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3007 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3008 GNUNET_SCHEDULER_shutdown ();
3009 GNUNET_free_non_null (ipv6prefix_s);
3012 vpn_argv[3] = ipv6prefix_s;
3014 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3017 (ipv6prefix >= 127) )
3019 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3020 _("Must specify valid IPv6 mask"));
3021 GNUNET_SCHEDULER_shutdown ();
3027 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3028 _("IPv6 support disabled as this system does not support IPv6\n"));
3029 vpn_argv[2] = GNUNET_strdup ("-");
3030 vpn_argv[3] = GNUNET_strdup ("-");
3032 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3035 if ( (GNUNET_SYSERR ==
3036 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3038 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3040 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3041 _("Must specify valid IPv4 address"));
3042 GNUNET_SCHEDULER_shutdown ();
3043 GNUNET_free_non_null (ipv4addr);
3046 vpn_argv[4] = ipv4addr;
3048 if ( (GNUNET_SYSERR ==
3049 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3051 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3053 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3054 _("Must specify valid IPv4 mask"));
3055 GNUNET_SCHEDULER_shutdown ();
3056 GNUNET_free_non_null (ipv4mask);
3059 vpn_argv[5] = ipv4mask;
3063 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3064 _("IPv4 support disabled as this system does not support IPv4\n"));
3065 vpn_argv[4] = GNUNET_strdup ("-");
3066 vpn_argv[5] = GNUNET_strdup ("-");
3070 cadet_handle = GNUNET_CADET_connect (cfg_);
3071 // FIXME never opens ports???
3072 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3073 "gnunet-helper-vpn", vpn_argv,
3074 &message_token, NULL, NULL);
3075 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3081 * Define "main" method using service macro.
3085 GNUNET_SERVICE_OPTION_NONE,
3088 &client_disconnect_cb,
3090 GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3091 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP,
3092 struct RedirectToIpRequestMessage,
3094 GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3095 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3096 struct RedirectToServiceRequestMessage,
3098 GNUNET_MQ_handler_end ());
3101 /* end of gnunet-service-vpn.c */