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.
17 * @file vpn/gnunet-service-vpn.c
18 * @brief service that opens a virtual interface and allows its clients
19 * to allocate IPs on the virtual interface and to then redirect
20 * IP traffic received on those IPs via the GNUnet cadet
21 * @author Philipp Toelke
22 * @author Christian Grothoff
25 * - keep multiple peers/cadet channels ready as alternative exits /
26 * detect & recover from channel-to-exit failure gracefully
29 #include "gnunet_util_lib.h"
30 #include "gnunet_common.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_applications.h"
33 #include "gnunet_cadet_service.h"
34 #include "gnunet_statistics_service.h"
35 #include "gnunet_constants.h"
36 #include "gnunet_tun_lib.h"
37 #include "gnunet_regex_service.h"
43 * Maximum number of messages we allow in the queue for cadet.
45 #define MAX_MESSAGE_QUEUE_SIZE 4
49 * State we keep for each of our channels.
54 * Information we track for each IP address to determine which channel
55 * to send the traffic over to the destination.
57 struct DestinationEntry;
60 * List of channels we keep for each destination port for a given
63 struct DestinationChannel
69 struct DestinationChannel *next;
74 struct DestinationChannel *prev;
77 * Destination entry list this `struct DestinationChannel` belongs with.
79 struct DestinationEntry *destination;
82 * Destination port this channel state is used for.
84 uint16_t destination_port;
90 * Information we track for each IP address to determine which channel
91 * to send the traffic over to the destination.
93 struct DestinationEntry
97 * Key under which this entry is in the 'destination_map' (only valid
98 * if 'heap_node != NULL').
100 struct GNUNET_HashCode key;
103 * Head of DLL of channels associated with this destination.
105 struct DestinationChannel *dt_head;
108 * Tail of DLL of channels associated with this destination.
110 struct DestinationChannel *dt_tail;
113 * Entry for this entry in the destination_heap.
115 struct GNUNET_CONTAINER_HeapNode *heap_node;
118 * #GNUNET_NO if this is a channel to an Internet-exit,
119 * #GNUNET_YES if this channel is to a service.
124 * Details about the connection (depending on is_service).
132 * The description of the service (only used for service channels).
134 struct GNUNET_HashCode service_descriptor;
137 * Peer offering the service.
139 struct GNUNET_PeerIdentity target;
141 } service_destination;
147 * Address family used (AF_INET or AF_INET6).
152 * IP address of the ultimate destination (only used for exit channels).
157 * Address if af is AF_INET.
162 * Address if af is AF_INET6.
175 * A messages we have in queue for a particular channel.
177 struct ChannelMessageQueueEntry
180 * This is a doubly-linked list.
182 struct ChannelMessageQueueEntry *next;
185 * This is a doubly-linked list.
187 struct ChannelMessageQueueEntry *prev;
190 * Number of bytes in @e msg.
195 * Message to transmit, allocated at the end of this struct.
202 * State we keep for each of our channels.
208 * Information about the channel to use, NULL if no channel
209 * is available right now.
211 struct GNUNET_CADET_Channel *channel;
214 * Active query with REGEX to locate exit.
216 struct GNUNET_REGEX_Search *search;
219 * Entry for this entry in the channel_heap, NULL as long as this
220 * channel state is not fully bound.
222 struct GNUNET_CONTAINER_HeapNode *heap_node;
225 * Head of list of messages scheduled for transmission.
227 struct ChannelMessageQueueEntry *tmq_head;
230 * Tail of list of messages scheduled for transmission.
232 struct ChannelMessageQueueEntry *tmq_tail;
235 * Destination to which this channel leads. Note that
236 * this struct is NOT in the destination_map (but a
237 * local copy) and that the 'heap_node' should always
240 struct DestinationEntry destination;
243 * Addess family used for this channel on the local TUN interface.
248 * Is this channel new (#GNUNET_NO), or did we exchange messages with the
249 * other side already (#GNUNET_YES)?
254 * Length of the doubly linked 'tmq_head/tmq_tail' list.
256 unsigned int tmq_length;
259 * IPPROTO_TCP or IPPROTO_UDP once bound.
264 * IP address of the source on our end, initially uninitialized.
269 * Address if af is AF_INET.
274 * Address if af is AF_INET6.
281 * Destination IP address used by the source on our end (this is the IP
282 * that we pick freely within the VPN's channel IP range).
287 * Address if af is AF_INET.
292 * Address if af is AF_INET6.
299 * Source port used by the sender on our end; 0 for uninitialized.
301 uint16_t source_port;
304 * Destination port used by the sender on our end; 0 for uninitialized.
306 uint16_t destination_port;
312 * Return value from #main().
314 static int global_ret;
317 * Configuration we use.
319 static const struct GNUNET_CONFIGURATION_Handle *cfg;
322 * Handle to the cadet service.
324 static struct GNUNET_CADET_Handle *cadet_handle;
327 * Map from IP address to destination information (possibly with a
328 * CADET channel handle for fast setup).
330 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
333 * Min-Heap sorted by activity time to expire old mappings.
335 static struct GNUNET_CONTAINER_Heap *destination_heap;
338 * Map from source and destination address (IP+port) to connection
339 * information (mostly with the respective CADET channel handle).
341 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
344 * Min-Heap sorted by activity time to expire old mappings; values are
345 * of type 'struct ChannelState'.
347 static struct GNUNET_CONTAINER_Heap *channel_heap;
352 static struct GNUNET_STATISTICS_Handle *stats;
355 * The handle to the VPN helper process "gnunet-helper-vpn".
357 static struct GNUNET_HELPER_Handle *helper_handle;
360 * Arguments to the vpn helper.
362 static char *vpn_argv[7];
365 * Length of the prefix of the VPN's IPv6 network.
367 static unsigned long long ipv6prefix;
370 * If there are more than this number of address-mappings, old ones
373 static unsigned long long max_destination_mappings;
376 * If there are more than this number of open channels, old ones
379 static unsigned long long max_channel_mappings;
383 * Compute the key under which we would store an entry in the
384 * #destination_map for the given IP address.
386 * @param af address family (AF_INET or AF_INET6)
387 * @param address IP address, struct in_addr or struct in6_addr
388 * @param key where to store the key
391 get_destination_key_from_ip (int af,
393 struct GNUNET_HashCode *key)
398 GNUNET_CRYPTO_hash (address,
399 sizeof (struct in_addr),
403 GNUNET_CRYPTO_hash (address,
404 sizeof (struct in6_addr),
415 * Compute the key under which we would store an entry in the
416 * channel_map for the given socket address pair.
418 * @param af address family (AF_INET or AF_INET6)
419 * @param protocol IPPROTO_TCP or IPPROTO_UDP
420 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
421 * @param source_port sender's source port
422 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
423 * @param destination_port sender's destination port
424 * @param key where to store the key
427 get_channel_key_from_ips (int af,
429 const void *source_ip,
430 uint16_t source_port,
431 const void *destination_ip,
432 uint16_t destination_port,
433 struct GNUNET_HashCode *key)
437 memset (key, 0, sizeof (struct GNUNET_HashCode));
438 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
439 so we put the ports in there (and hope for few collisions) */
441 GNUNET_memcpy (off, &source_port, sizeof (uint16_t));
442 off += sizeof (uint16_t);
443 GNUNET_memcpy (off, &destination_port, sizeof (uint16_t));
444 off += sizeof (uint16_t);
448 GNUNET_memcpy (off, source_ip, sizeof (struct in_addr));
449 off += sizeof (struct in_addr);
450 GNUNET_memcpy (off, destination_ip, sizeof (struct in_addr));
451 off += sizeof (struct in_addr);
454 GNUNET_memcpy (off, source_ip, sizeof (struct in6_addr));
455 off += sizeof (struct in6_addr);
456 GNUNET_memcpy (off, destination_ip, sizeof (struct in6_addr));
457 off += sizeof (struct in6_addr);
463 GNUNET_memcpy (off, &protocol, sizeof (uint8_t));
464 /* off += sizeof (uint8_t); */
469 * Notify the client about the result of its request.
471 * @param client client to notify
472 * @param request_id original request ID to include in response
473 * @param result_af resulting address family
474 * @param addr resulting IP address
477 send_client_reply (struct GNUNET_SERVICE_Client *client,
482 struct GNUNET_MQ_Envelope *env;
483 struct RedirectToIpResponseMessage *res;
489 rlen = sizeof (struct in_addr);
492 rlen = sizeof (struct in6_addr);
501 env = GNUNET_MQ_msg_extra (res,
503 GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
504 res->result_af = htonl (result_af);
505 res->request_id = request_id;
506 GNUNET_memcpy (&res[1],
509 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
515 * Free resources associated with a channel state.
517 * @param ts state to free
520 free_channel_state (struct ChannelState *ts)
522 struct GNUNET_HashCode key;
523 struct ChannelMessageQueueEntry *tnq;
524 struct GNUNET_CADET_Channel *channel;
526 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
527 "Cleaning up channel state\n");
528 if (NULL != (channel = ts->channel))
531 GNUNET_CADET_channel_destroy (channel);
534 GNUNET_STATISTICS_update (stats,
535 gettext_noop ("# Active channels"),
537 while (NULL != (tnq = ts->tmq_head))
539 GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
545 GNUNET_assert (0 == ts->tmq_length);
546 GNUNET_assert (NULL == ts->destination.heap_node);
547 if (NULL != ts->search)
549 GNUNET_REGEX_search_cancel (ts->search);
552 if (NULL != ts->heap_node)
554 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
555 ts->heap_node = NULL;
556 get_channel_key_from_ips (ts->af,
561 ts->destination_port,
563 GNUNET_assert (GNUNET_YES ==
564 GNUNET_CONTAINER_multihashmap_remove (channel_map,
573 * Add the given message to the given channel and trigger the
574 * transmission process.
576 * @param ts channel to queue the message for
577 * @param env message to queue
580 send_to_channel (struct ChannelState *ts,
581 struct GNUNET_MQ_Envelope *env)
583 struct GNUNET_MQ_Handle *mq;
585 GNUNET_assert (NULL != ts->channel);
586 mq = GNUNET_CADET_get_mq (ts->channel);
589 if (GNUNET_MQ_get_length (mq) > MAX_MESSAGE_QUEUE_SIZE)
591 env = GNUNET_MQ_unsent_head (mq);
592 GNUNET_assert (NULL != env);
593 GNUNET_STATISTICS_update (stats,
594 gettext_noop ("# Messages dropped in cadet queue (overflow)"),
597 GNUNET_MQ_discard (env);
603 * Output destination of a channel for diagnostics.
605 * @param de destination to process
606 * @return diagnostic string describing destination
609 print_channel_destination (const struct DestinationEntry *de)
611 static char dest[256];
615 GNUNET_snprintf (dest,
618 GNUNET_i2s (&de->details.service_destination.target),
619 GNUNET_h2s (&de->details.service_destination.service_descriptor));
623 inet_ntop (de->details.exit_destination.af,
624 &de->details.exit_destination.ip,
633 * Function called whenever a channel is destroyed. Should clean up
634 * any associated state.
636 * @param cls our `struct ChannelState`
637 * @param channel connection to the other end (henceforth invalid)
640 channel_cleaner (void *cls,
641 const struct GNUNET_CADET_Channel *channel)
643 struct ChannelState *ts = cls;
645 ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
647 "CADET notified us about death of channel to `%s'\n",
648 print_channel_destination (&ts->destination));
649 free_channel_state (ts);
654 * Synthesize a plausible ICMP payload for an ICMP error
655 * response on the given channel.
657 * @param ts channel information
658 * @param ipp IPv4 header to fill in (ICMP payload)
659 * @param udp "UDP" header to fill in (ICMP payload); might actually
660 * also be the first 8 bytes of the TCP header
663 make_up_icmpv4_payload (struct ChannelState *ts,
664 struct GNUNET_TUN_IPv4Header *ipp,
665 struct GNUNET_TUN_UdpHeader *udp)
667 GNUNET_TUN_initialize_ipv4_header (ipp,
669 sizeof (struct GNUNET_TUN_TcpHeader),
671 &ts->destination_ip.v4);
672 udp->source_port = htons (ts->source_port);
673 udp->destination_port = htons (ts->destination_port);
674 udp->len = htons (0);
675 udp->crc = htons (0);
680 * Synthesize a plausible ICMP payload for an ICMP error
681 * response on the given channel.
683 * @param ts channel information
684 * @param ipp IPv6 header to fill in (ICMP payload)
685 * @param udp "UDP" header to fill in (ICMP payload); might actually
686 * also be the first 8 bytes of the TCP header
689 make_up_icmpv6_payload (struct ChannelState *ts,
690 struct GNUNET_TUN_IPv6Header *ipp,
691 struct GNUNET_TUN_UdpHeader *udp)
693 GNUNET_TUN_initialize_ipv6_header (ipp,
695 sizeof (struct GNUNET_TUN_TcpHeader),
697 &ts->destination_ip.v6);
698 udp->source_port = htons (ts->source_port);
699 udp->destination_port = htons (ts->destination_port);
700 udp->len = htons (0);
701 udp->crc = htons (0);
706 * We got an ICMP packet back from the CADET channel. Check it is OK.
708 * @param cls our `struct ChannelState *`
709 * @param message the actual message
710 * @return #GNUNET_OK to keep the connection open,
711 * #GNUNET_SYSERR to close it (signal serious error)
714 check_icmp_back (void *cls,
715 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
717 struct ChannelState *ts = cls;
719 if (NULL == ts->heap_node)
722 return GNUNET_SYSERR;
724 if (AF_UNSPEC == ts->af)
727 return GNUNET_SYSERR;
734 * We got an ICMP packet back from the CADET channel. Pass it on to the
735 * local virtual interface via the helper.
737 * @param cls our `struct ChannelState *`
738 * @param message the actual message
741 handle_icmp_back (void *cls,
742 const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
744 struct ChannelState *ts = cls;
747 GNUNET_STATISTICS_update (stats,
748 gettext_noop ("# ICMP packets received from cadet"),
751 mlen = ntohs (i2v->header.size) - sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
753 char sbuf[INET6_ADDRSTRLEN];
754 char dbuf[INET6_ADDRSTRLEN];
756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
757 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
759 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
760 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
766 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
767 + sizeof (struct GNUNET_TUN_IcmpHeader)
768 + sizeof (struct GNUNET_MessageHeader) +
769 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
772 /* reserve some extra space in case we have an ICMP type here where
773 we will need to make up the payload ourselves */
774 char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
775 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
776 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
777 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
778 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
779 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
780 tun->flags = htons (0);
781 tun->proto = htons (ETH_P_IPV4);
782 GNUNET_TUN_initialize_ipv4_header (ipv4,
784 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
785 &ts->destination_ip.v4,
787 *icmp = i2v->icmp_header;
788 GNUNET_memcpy (&icmp[1],
791 /* For some ICMP types, we need to adjust (make up) the payload here.
792 Also, depending on the AF used on the other side, we have to
793 do ICMP PT (translate ICMP types) */
794 switch (ntohl (i2v->af))
799 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
800 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
802 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
803 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
804 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
806 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
807 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
811 /* sender did not strip ICMP payload? */
815 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
816 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
817 make_up_icmpv4_payload (ts, ipp, udp);
822 GNUNET_STATISTICS_update (stats,
823 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
830 /* ICMP PT 6-to-4 and possibly making up payloads */
833 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
834 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
836 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
837 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
841 /* sender did not strip ICMP payload? */
845 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
846 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
847 make_up_icmpv4_payload (ts, ipp, udp);
850 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
851 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
853 struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
854 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
858 /* sender did not strip ICMP payload? */
862 size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
863 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
864 make_up_icmpv4_payload (ts, ipp, udp);
867 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
868 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
869 GNUNET_STATISTICS_update (stats,
870 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
873 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
874 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
876 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
877 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
881 GNUNET_STATISTICS_update (stats,
882 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
892 msg->size = htons (size);
893 GNUNET_TUN_calculate_icmp_checksum (icmp,
896 (void) GNUNET_HELPER_send (helper_handle,
905 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
906 + sizeof (struct GNUNET_TUN_IcmpHeader)
907 + sizeof (struct GNUNET_MessageHeader) +
908 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
911 char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
912 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
913 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
914 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
915 struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
916 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
917 tun->flags = htons (0);
918 tun->proto = htons (ETH_P_IPV6);
919 GNUNET_TUN_initialize_ipv6_header (ipv6,
921 sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
922 &ts->destination_ip.v6,
924 *icmp = i2v->icmp_header;
925 GNUNET_memcpy (&icmp[1],
929 /* For some ICMP types, we need to adjust (make up) the payload here.
930 Also, depending on the AF used on the other side, we have to
931 do ICMP PT (translate ICMP types) */
932 switch (ntohl (i2v->af))
935 /* ICMP PT 4-to-6 and possibly making up payloads */
938 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
939 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
941 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
942 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
944 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
945 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
947 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
948 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
952 /* sender did not strip ICMP payload? */
956 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
957 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
958 make_up_icmpv6_payload (ts, ipp, udp);
961 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
962 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
964 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
965 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
969 /* sender did not strip ICMP payload? */
973 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
974 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
975 make_up_icmpv6_payload (ts, ipp, udp);
978 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
979 GNUNET_STATISTICS_update (stats,
980 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
985 GNUNET_STATISTICS_update (stats,
986 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
995 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
996 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
997 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
998 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1000 struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1001 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1005 /* sender did not strip ICMP payload? */
1006 GNUNET_break_op (0);
1009 size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1010 GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1011 make_up_icmpv6_payload (ts, ipp, udp);
1014 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1017 GNUNET_break_op (0);
1018 GNUNET_STATISTICS_update (stats,
1019 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1026 GNUNET_break_op (0);
1029 msg->size = htons (size);
1030 GNUNET_TUN_calculate_icmp_checksum (icmp,
1032 (void) GNUNET_HELPER_send (helper_handle,
1042 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1043 GNUNET_TIME_absolute_get ().abs_value_us);
1044 GNUNET_CADET_receive_done (ts->channel);
1049 * We got a UDP packet back from the CADET channel. Check that it is OK.
1051 * @param cls our `struct ChannelState *`
1052 * @param reply the actual message
1053 * @return #GNUNET_OK to keep the connection open,
1054 * #GNUNET_SYSERR to close it (signal serious error)
1057 check_udp_back (void *cls,
1058 const struct GNUNET_EXIT_UdpReplyMessage *reply)
1060 struct ChannelState *ts = cls;
1062 if (NULL == ts->heap_node)
1064 GNUNET_break_op (0);
1065 return GNUNET_SYSERR;
1067 if (AF_UNSPEC == ts->af)
1069 GNUNET_break_op (0);
1070 return GNUNET_SYSERR;
1077 * We got a UDP packet back from the CADET channel. Pass it on to the
1078 * local virtual interface via the helper.
1080 * @param cls our `struct ChannelState *`
1081 * @param reply the actual message
1084 handle_udp_back (void *cls,
1085 const struct GNUNET_EXIT_UdpReplyMessage *reply)
1087 struct ChannelState *ts = cls;
1090 GNUNET_STATISTICS_update (stats,
1091 gettext_noop ("# UDP packets received from cadet"),
1094 mlen = ntohs (reply->header.size) - sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1096 char sbuf[INET6_ADDRSTRLEN];
1097 char dbuf[INET6_ADDRSTRLEN];
1099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1100 "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1101 (unsigned int) mlen,
1102 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1103 ts->destination_port,
1104 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1111 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1112 + sizeof (struct GNUNET_TUN_UdpHeader)
1113 + sizeof (struct GNUNET_MessageHeader) +
1114 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1117 char buf[size] GNUNET_ALIGN;
1118 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1119 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1120 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1121 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1122 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1123 msg->size = htons (size);
1124 tun->flags = htons (0);
1125 tun->proto = htons (ETH_P_IPV4);
1126 GNUNET_TUN_initialize_ipv4_header (ipv4,
1128 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1129 &ts->destination_ip.v4,
1131 if (0 == ntohs (reply->source_port))
1132 udp->source_port = htons (ts->destination_port);
1134 udp->source_port = reply->source_port;
1135 if (0 == ntohs (reply->destination_port))
1136 udp->destination_port = htons (ts->source_port);
1138 udp->destination_port = reply->destination_port;
1139 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1140 GNUNET_TUN_calculate_udp4_checksum (ipv4,
1144 GNUNET_memcpy (&udp[1],
1147 (void) GNUNET_HELPER_send (helper_handle,
1156 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1157 + sizeof (struct GNUNET_TUN_UdpHeader)
1158 + sizeof (struct GNUNET_MessageHeader) +
1159 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1162 char buf[size] GNUNET_ALIGN;
1163 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1164 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1165 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1166 struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1167 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1168 msg->size = htons (size);
1169 tun->flags = htons (0);
1170 tun->proto = htons (ETH_P_IPV6);
1171 GNUNET_TUN_initialize_ipv6_header (ipv6,
1173 sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1174 &ts->destination_ip.v6,
1176 if (0 == ntohs (reply->source_port))
1177 udp->source_port = htons (ts->destination_port);
1179 udp->source_port = reply->source_port;
1180 if (0 == ntohs (reply->destination_port))
1181 udp->destination_port = htons (ts->source_port);
1183 udp->destination_port = reply->destination_port;
1184 udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1185 GNUNET_TUN_calculate_udp6_checksum (ipv6,
1188 GNUNET_memcpy (&udp[1],
1191 (void) GNUNET_HELPER_send (helper_handle,
1201 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1202 GNUNET_TIME_absolute_get ().abs_value_us);
1203 GNUNET_CADET_receive_done (ts->channel);
1208 * We got a TCP packet back from the CADET channel. Check it is OK.
1210 * @param cls our `struct ChannelState *`
1211 * @param data the actual message
1212 * @return #GNUNET_OK to keep the connection open,
1213 * #GNUNET_SYSERR to close it (signal serious error)
1216 check_tcp_back (void *cls,
1217 const struct GNUNET_EXIT_TcpDataMessage *data)
1219 struct ChannelState *ts = cls;
1221 if (NULL == ts->heap_node)
1223 GNUNET_break_op (0);
1224 return GNUNET_SYSERR;
1226 if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1228 GNUNET_break_op (0);
1229 return GNUNET_SYSERR;
1236 * We got a TCP packet back from the CADET channel. Pass it on to the
1237 * local virtual interface via the helper.
1239 * @param cls our `struct ChannelState *`
1240 * @param data the actual message
1243 handle_tcp_back (void *cls,
1244 const struct GNUNET_EXIT_TcpDataMessage *data)
1246 struct ChannelState *ts = cls;
1249 GNUNET_STATISTICS_update (stats,
1250 gettext_noop ("# TCP packets received from cadet"),
1253 mlen = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1255 char sbuf[INET6_ADDRSTRLEN];
1256 char dbuf[INET6_ADDRSTRLEN];
1258 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1259 "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1260 (unsigned int) mlen,
1261 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1262 ts->destination_port,
1263 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1270 size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1271 + sizeof (struct GNUNET_TUN_TcpHeader)
1272 + sizeof (struct GNUNET_MessageHeader) +
1273 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1276 char buf[size] GNUNET_ALIGN;
1277 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1278 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1279 struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1280 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1281 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1282 msg->size = htons (size);
1283 tun->flags = htons (0);
1284 tun->proto = htons (ETH_P_IPV4);
1285 GNUNET_TUN_initialize_ipv4_header (ipv4,
1287 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1288 &ts->destination_ip.v4,
1290 *tcp = data->tcp_header;
1291 tcp->source_port = htons (ts->destination_port);
1292 tcp->destination_port = htons (ts->source_port);
1293 GNUNET_TUN_calculate_tcp4_checksum (ipv4,
1297 GNUNET_memcpy (&tcp[1],
1300 (void) GNUNET_HELPER_send (helper_handle,
1309 size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1310 + sizeof (struct GNUNET_TUN_TcpHeader)
1311 + sizeof (struct GNUNET_MessageHeader) +
1312 sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1315 char buf[size] GNUNET_ALIGN;
1316 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1317 struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1318 struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1319 struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1320 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1321 msg->size = htons (size);
1322 tun->flags = htons (0);
1323 tun->proto = htons (ETH_P_IPV6);
1324 GNUNET_TUN_initialize_ipv6_header (ipv6,
1326 sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1327 &ts->destination_ip.v6,
1329 *tcp = data->tcp_header;
1330 tcp->source_port = htons (ts->destination_port);
1331 tcp->destination_port = htons (ts->source_port);
1332 GNUNET_TUN_calculate_tcp6_checksum (ipv6,
1336 GNUNET_memcpy (&tcp[1],
1339 (void) GNUNET_HELPER_send (helper_handle,
1347 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1348 GNUNET_TIME_absolute_get ().abs_value_us);
1349 GNUNET_CADET_receive_done (ts->channel);
1354 * Create a channel for @a ts to @a target at @a port
1356 * @param ts channel state to create the channel for
1357 * @param target peer to connect to
1358 * @param port destination port
1359 * @return the channel handle
1361 static struct GNUNET_CADET_Channel *
1362 create_channel (struct ChannelState *ts,
1363 const struct GNUNET_PeerIdentity *target,
1364 const struct GNUNET_HashCode *port)
1366 struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1367 GNUNET_MQ_hd_var_size (udp_back,
1368 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY,
1369 struct GNUNET_EXIT_UdpReplyMessage,
1371 GNUNET_MQ_hd_var_size (tcp_back,
1372 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN,
1373 struct GNUNET_EXIT_TcpDataMessage,
1375 GNUNET_MQ_hd_var_size (icmp_back,
1376 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN,
1377 struct GNUNET_EXIT_IcmpToVPNMessage,
1379 GNUNET_MQ_handler_end()
1382 return GNUNET_CADET_channel_create (cadet_handle,
1386 GNUNET_CADET_OPTION_DEFAULT,
1394 * Regex has found a potential exit peer for us; consider using it.
1396 * @param cls the `struct ChannelState`
1397 * @param id Peer providing a regex that matches the string.
1398 * @param get_path Path of the get request.
1399 * @param get_path_length Lenght of @a get_path.
1400 * @param put_path Path of the put request.
1401 * @param put_path_length Length of the @a put_path.
1404 handle_regex_result (void *cls,
1405 const struct GNUNET_PeerIdentity *id,
1406 const struct GNUNET_PeerIdentity *get_path,
1407 unsigned int get_path_length,
1408 const struct GNUNET_PeerIdentity *put_path,
1409 unsigned int put_path_length)
1411 struct ChannelState *ts = cls;
1412 struct GNUNET_HashCode port;
1414 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1415 "Exit %s found for destination %s!\n",
1417 print_channel_destination (&ts->destination));
1418 GNUNET_REGEX_search_cancel (ts->search);
1423 /* these must match the strings used in gnunet-daemon-exit */
1424 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
1425 strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
1429 /* these must match the strings used in gnunet-daemon-exit */
1430 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
1431 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
1438 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1439 "Creating tunnel to %s for destination %s!\n",
1441 print_channel_destination (&ts->destination));
1442 ts->channel = create_channel (ts,
1449 * Initialize the given destination entry's cadet channel.
1451 * @param dt destination channel for which we need to setup a channel
1452 * @param client_af address family of the address returned to the client
1453 * @return channel state of the channel that was created
1455 static struct ChannelState *
1456 create_channel_to_destination (struct DestinationChannel *dt,
1459 struct ChannelState *ts;
1461 GNUNET_STATISTICS_update (stats,
1462 gettext_noop ("# Cadet channels created"),
1465 ts = GNUNET_new (struct ChannelState);
1467 ts->destination = *dt->destination;
1468 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
1469 ts->destination_port = dt->destination_port;
1470 if (dt->destination->is_service)
1472 struct GNUNET_HashCode cadet_port;
1474 GNUNET_TUN_compute_service_cadet_port (&ts->destination.details.service_destination.service_descriptor,
1475 ts->destination_port,
1477 ts->channel = create_channel (ts,
1478 &dt->destination->details.service_destination.target,
1481 if (NULL == ts->channel)
1487 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1488 "Creating channel to peer %s offering service %s on port %u\n",
1489 GNUNET_i2s (&dt->destination->details.service_destination.target),
1490 GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor),
1491 (unsigned int) ts->destination_port);
1497 switch (dt->destination->details.exit_destination.af)
1501 char address[GNUNET_TUN_IPV4_REGEXLEN];
1503 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
1504 dt->destination_port,
1506 GNUNET_asprintf (&policy,
1508 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1514 char address[GNUNET_TUN_IPV6_REGEXLEN];
1516 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
1517 dt->destination_port,
1519 GNUNET_asprintf (&policy,
1521 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1531 "Requesting connect by string: %s\n",
1533 ts->search = GNUNET_REGEX_search (cfg,
1535 &handle_regex_result,
1537 GNUNET_free (policy);
1544 * We have too many active channels. Clean up the oldest channel.
1546 * @param except channel that must NOT be cleaned up, even if it is the oldest
1549 expire_channel (struct ChannelState *except)
1551 struct ChannelState *ts;
1553 ts = GNUNET_CONTAINER_heap_peek (channel_heap);
1554 GNUNET_assert (NULL != ts);
1556 return; /* can't do this */
1557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1558 "Tearing down expired channel to %s\n",
1559 print_channel_destination (&except->destination));
1560 free_channel_state (ts);
1565 * Route a packet via cadet to the given destination.
1567 * @param destination description of the destination
1568 * @param af address family on this end (AF_INET or AF_INET6)
1569 * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
1570 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
1571 * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
1572 * @param payload payload of the packet after the IP header
1573 * @param payload_length number of bytes in @a payload
1576 route_packet (struct DestinationEntry *destination,
1579 const void *source_ip,
1580 const void *destination_ip,
1581 const void *payload,
1582 size_t payload_length)
1584 struct GNUNET_HashCode key;
1585 struct ChannelState *ts;
1588 struct GNUNET_MQ_Envelope *env;
1589 const struct GNUNET_TUN_UdpHeader *udp;
1590 const struct GNUNET_TUN_TcpHeader *tcp;
1591 const struct GNUNET_TUN_IcmpHeader *icmp;
1592 struct DestinationChannel *dt;
1593 uint16_t source_port;
1594 uint16_t destination_port;
1600 if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1606 tcp = NULL; /* make compiler happy */
1607 icmp = NULL; /* make compiler happy */
1609 if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1611 GNUNET_break_op (0);
1614 source_port = ntohs (udp->source_port);
1615 destination_port = ntohs (udp->destination_port);
1616 get_channel_key_from_ips (af,
1627 if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1633 udp = NULL; /* make compiler happy */
1634 icmp = NULL; /* make compiler happy */
1636 if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1638 GNUNET_break_op (0);
1641 source_port = ntohs (tcp->source_port);
1642 destination_port = ntohs (tcp->destination_port);
1643 get_channel_key_from_ips (af,
1653 case IPPROTO_ICMPV6:
1655 if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1660 if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1666 tcp = NULL; /* make compiler happy */
1667 udp = NULL; /* make compiler happy */
1670 destination_port = 0;
1671 get_channel_key_from_ips (af,
1681 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1682 _("Protocol %u not supported, dropping\n"),
1683 (unsigned int) protocol);
1687 if (! destination->is_service)
1689 switch (destination->details.exit_destination.af)
1692 alen = sizeof (struct in_addr);
1695 alen = sizeof (struct in6_addr);
1702 char sbuf[INET6_ADDRSTRLEN];
1703 char dbuf[INET6_ADDRSTRLEN];
1704 char xbuf[INET6_ADDRSTRLEN];
1706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1707 "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1708 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1719 inet_ntop (destination->details.exit_destination.af,
1720 &destination->details.exit_destination.ip,
1721 xbuf, sizeof (xbuf)),
1724 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1725 if (dt->destination_port == destination_port)
1731 char sbuf[INET6_ADDRSTRLEN];
1732 char dbuf[INET6_ADDRSTRLEN];
1734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1735 "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1736 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1747 GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1748 GNUNET_i2s (&destination->details.service_destination.target));
1750 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1751 if (dt->destination_port == destination_port)
1756 dt = GNUNET_new (struct DestinationChannel);
1757 dt->destination = destination;
1758 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1759 destination->dt_tail,
1761 dt->destination_port = destination_port;
1764 /* see if we have an existing channel for this destination */
1765 ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1770 "Creating new channel for key %s\n",
1772 /* need to either use the existing channel from the destination (if still
1773 available) or create a fresh one */
1774 ts = create_channel_to_destination (dt,
1778 /* now bind existing "unbound" channel to our IP/port tuple */
1779 ts->protocol = protocol;
1783 ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1784 ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1788 ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1789 ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1791 ts->source_port = source_port;
1792 ts->destination_port = destination_port;
1793 ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1795 GNUNET_TIME_absolute_get ().abs_value_us);
1796 GNUNET_assert (GNUNET_YES ==
1797 GNUNET_CONTAINER_multihashmap_put (channel_map,
1800 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1801 GNUNET_STATISTICS_update (stats,
1802 gettext_noop ("# Active channels"),
1804 while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1805 expire_channel (ts);
1809 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1810 GNUNET_TIME_absolute_get ().abs_value_us);
1812 if (NULL == ts->channel)
1814 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1815 "Packet dropped, channel to %s not yet ready (%s)\n",
1816 print_channel_destination (&ts->destination),
1817 (NULL == ts->search)
1818 ? "EXIT search failed"
1819 : "EXIT search active");
1820 GNUNET_STATISTICS_update (stats,
1821 gettext_noop ("# Packets dropped (channel not yet online)"),
1827 /* send via channel */
1831 if (destination->is_service)
1833 struct GNUNET_EXIT_UdpServiceMessage *usm;
1835 mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1836 payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1837 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1842 env = GNUNET_MQ_msg_extra (usm,
1843 payload_length - sizeof (struct GNUNET_TUN_UdpHeader),
1844 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1845 /* if the source port is below 32000, we assume it has a special
1846 meaning; if not, we pick a random port (this is a heuristic) */
1847 usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1848 usm->destination_port = udp->destination_port;
1849 GNUNET_memcpy (&usm[1],
1851 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1855 struct GNUNET_EXIT_UdpInternetMessage *uim;
1856 struct in_addr *ip4dst;
1857 struct in6_addr *ip6dst;
1860 mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1861 alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1862 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1867 env = GNUNET_MQ_msg_extra (uim,
1868 payload_length + alen - sizeof (struct GNUNET_TUN_UdpHeader),
1869 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1870 uim->af = htonl (destination->details.exit_destination.af);
1871 uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1872 uim->destination_port = udp->destination_port;
1873 switch (destination->details.exit_destination.af)
1876 ip4dst = (struct in_addr *) &uim[1];
1877 *ip4dst = destination->details.exit_destination.ip.v4;
1878 payload = &ip4dst[1];
1881 ip6dst = (struct in6_addr *) &uim[1];
1882 *ip6dst = destination->details.exit_destination.ip.v6;
1883 payload = &ip6dst[1];
1888 GNUNET_memcpy (payload,
1890 payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1894 if (GNUNET_NO == ts->is_established)
1896 if (destination->is_service)
1898 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1900 mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1901 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1902 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1907 env = GNUNET_MQ_msg_extra (tsm,
1908 payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1909 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1910 tsm->reserved = htonl (0);
1911 tsm->tcp_header = *tcp;
1912 GNUNET_memcpy (&tsm[1],
1914 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1918 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1919 struct in_addr *ip4dst;
1920 struct in6_addr *ip6dst;
1923 mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1924 alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1925 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1930 env = GNUNET_MQ_msg_extra (tim,
1931 payload_length + alen - sizeof (struct GNUNET_TUN_TcpHeader),
1932 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1933 tim->af = htonl (destination->details.exit_destination.af);
1934 tim->tcp_header = *tcp;
1935 switch (destination->details.exit_destination.af)
1938 ip4dst = (struct in_addr *) &tim[1];
1939 *ip4dst = destination->details.exit_destination.ip.v4;
1940 payload = &ip4dst[1];
1943 ip6dst = (struct in6_addr *) &tim[1];
1944 *ip6dst = destination->details.exit_destination.ip.v6;
1945 payload = &ip6dst[1];
1950 GNUNET_memcpy (payload,
1952 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1957 struct GNUNET_EXIT_TcpDataMessage *tdm;
1959 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1960 payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1961 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1966 env = GNUNET_MQ_msg_extra (tdm,
1967 payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1968 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1969 tdm->reserved = htonl (0);
1970 tdm->tcp_header = *tcp;
1971 GNUNET_memcpy (&tdm[1],
1973 payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1977 case IPPROTO_ICMPV6:
1978 if (destination->is_service)
1980 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1982 /* ICMP protocol translation will be done by the receiver (as we don't know
1983 the target AF); however, we still need to possibly discard the payload
1984 depending on the ICMP type */
1990 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1991 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1993 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1994 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1995 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1996 /* throw away ICMP payload, won't be useful for the other side anyway */
1997 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2000 GNUNET_STATISTICS_update (stats,
2001 gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
2005 /* end of AF_INET */
2010 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2011 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2012 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2013 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2014 /* throw away ICMP payload, won't be useful for the other side anyway */
2015 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2017 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2018 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2021 GNUNET_STATISTICS_update (stats,
2022 gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
2026 /* end of AF_INET6 */
2033 /* update length calculations, as payload_length may have changed */
2034 mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
2035 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2036 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2042 env = GNUNET_MQ_msg_extra (ism,
2043 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2044 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
2045 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
2046 ism->icmp_header = *icmp;
2047 GNUNET_memcpy (&ism[1],
2049 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2053 struct GNUNET_EXIT_IcmpInternetMessage *iim;
2054 struct in_addr *ip4dst;
2055 struct in6_addr *ip6dst;
2059 new_type = icmp->type;
2060 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2061 and throw away ICMP payload depending on ICMP message type */
2067 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2068 if (destination->details.exit_destination.af == AF_INET6)
2069 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2071 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2072 if (destination->details.exit_destination.af == AF_INET6)
2073 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2075 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2076 if (destination->details.exit_destination.af == AF_INET6)
2077 new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2078 /* throw away IP-payload, exit will have to make it up anyway */
2079 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2081 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2082 if (destination->details.exit_destination.af == AF_INET6)
2083 new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2084 /* throw away IP-payload, exit will have to make it up anyway */
2085 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2087 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2088 if (destination->details.exit_destination.af == AF_INET6)
2090 GNUNET_STATISTICS_update (stats,
2091 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2095 /* throw away IP-payload, exit will have to make it up anyway */
2096 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2099 GNUNET_STATISTICS_update (stats,
2100 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2104 /* end of AF_INET */
2109 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2110 if (destination->details.exit_destination.af == AF_INET)
2111 new_type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2112 /* throw away IP-payload, exit will have to make it up anyway */
2113 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2115 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2116 if (destination->details.exit_destination.af == AF_INET)
2117 new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2118 /* throw away IP-payload, exit will have to make it up anyway */
2119 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2121 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2122 if (destination->details.exit_destination.af == AF_INET)
2124 GNUNET_STATISTICS_update (stats,
2125 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2129 /* throw away IP-payload, exit will have to make it up anyway */
2130 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2132 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2133 if (destination->details.exit_destination.af == AF_INET)
2135 GNUNET_STATISTICS_update (stats,
2136 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2140 /* throw away IP-payload, exit will have to make it up anyway */
2141 payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2143 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2144 if (destination->details.exit_destination.af == AF_INET)
2145 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2147 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2148 if (destination->details.exit_destination.af == AF_INET)
2149 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2152 GNUNET_STATISTICS_update (stats,
2153 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2157 /* end of AF_INET6 */
2163 /* update length calculations, as payload_length may have changed */
2164 mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
2165 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2166 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2171 env = GNUNET_MQ_msg_extra (iim,
2172 alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2173 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
2174 iim->icmp_header = *icmp;
2175 iim->icmp_header.type = new_type;
2176 iim->af = htonl (destination->details.exit_destination.af);
2177 switch (destination->details.exit_destination.af)
2180 ip4dst = (struct in_addr *) &iim[1];
2181 *ip4dst = destination->details.exit_destination.ip.v4;
2182 payload = &ip4dst[1];
2185 ip6dst = (struct in6_addr *) &iim[1];
2186 *ip6dst = destination->details.exit_destination.ip.v6;
2187 payload = &ip6dst[1];
2192 GNUNET_memcpy (payload,
2194 payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2198 /* not supported above, how can we get here !? */
2202 ts->is_established = GNUNET_YES;
2203 send_to_channel (ts,
2209 * Receive packets from the helper-process (someone send to the local
2210 * virtual channel interface). Find the destination mapping, and if it
2211 * exists, identify the correct CADET channel (or possibly create it)
2212 * and forward the packet.
2214 * @param cls closure, NULL
2215 * @param message message we got from the client (VPN channel interface)
2216 * @return #GNUNET_OK on success,
2217 * #GNUNET_NO to stop further processing (no error)
2218 * #GNUNET_SYSERR to stop further processing with error
2221 message_token (void *cls,
2222 const struct GNUNET_MessageHeader *message)
2224 const struct GNUNET_TUN_Layer2PacketHeader *tun;
2226 struct GNUNET_HashCode key;
2227 struct DestinationEntry *de;
2229 GNUNET_STATISTICS_update (stats,
2230 gettext_noop ("# Packets received from TUN interface"),
2232 mlen = ntohs (message->size);
2233 if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2234 (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
2239 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2240 mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
2241 switch (ntohs (tun->proto))
2245 const struct GNUNET_TUN_IPv6Header *pkt6;
2247 if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
2253 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2254 get_destination_key_from_ip (AF_INET6,
2255 &pkt6->destination_address,
2257 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2260 char buf[INET6_ADDRSTRLEN];
2262 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2263 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2264 inet_ntop (AF_INET6,
2265 &pkt6->destination_address,
2273 &pkt6->source_address,
2274 &pkt6->destination_address,
2276 mlen - sizeof (struct GNUNET_TUN_IPv6Header));
2281 struct GNUNET_TUN_IPv4Header *pkt4;
2283 if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
2289 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2290 get_destination_key_from_ip (AF_INET,
2291 &pkt4->destination_address,
2293 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2296 char buf[INET_ADDRSTRLEN];
2298 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2299 _("Packet received for unmapped destination `%s' (dropping it)\n"),
2301 &pkt4->destination_address,
2306 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2308 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2309 _("Received IPv4 packet with options (dropping it)\n"));
2315 &pkt4->source_address,
2316 &pkt4->destination_address,
2318 mlen - sizeof (struct GNUNET_TUN_IPv4Header));
2322 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2323 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2324 (unsigned int) ntohs (tun->proto));
2332 * Allocate an IPv4 address from the range of the channel
2333 * for a new redirection.
2335 * @param v4 where to store the address
2336 * @return #GNUNET_OK on success,
2337 * #GNUNET_SYSERR on error
2340 allocate_v4_address (struct in_addr *v4)
2342 const char *ipv4addr = vpn_argv[4];
2343 const char *ipv4mask = vpn_argv[5];
2344 struct in_addr addr;
2345 struct in_addr mask;
2347 struct GNUNET_HashCode key;
2350 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2351 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2352 /* Given 192.168.0.1/255.255.0.0, we want a mask
2353 of '192.168.255.255', thus: */
2354 mask.s_addr = addr.s_addr | ~mask.s_addr;
2361 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2362 _("Failed to find unallocated IPv4 address in VPN's range\n"));
2363 return GNUNET_SYSERR;
2365 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2366 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2368 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2369 get_destination_key_from_ip (AF_INET,
2373 while ( (GNUNET_YES ==
2374 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2376 (v4->s_addr == addr.s_addr) ||
2377 (v4->s_addr == mask.s_addr) );
2383 * Allocate an IPv6 address from the range of the channel
2384 * for a new redirection.
2386 * @param v6 where to store the address
2387 * @return #GNUNET_OK on success,
2388 * #GNUNET_SYSERR on error
2391 allocate_v6_address (struct in6_addr *v6)
2393 const char *ipv6addr = vpn_argv[2];
2394 struct in6_addr addr;
2395 struct in6_addr mask;
2396 struct in6_addr rnd;
2398 struct GNUNET_HashCode key;
2401 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2402 GNUNET_assert (ipv6prefix < 128);
2403 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2406 for (i=127;i>=ipv6prefix;i--)
2407 mask.s6_addr[i / 8] |= (1 << (i % 8));
2409 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2416 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2417 _("Failed to find unallocated IPv6 address in VPN's range\n"));
2418 return GNUNET_SYSERR;
2423 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2426 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2428 get_destination_key_from_ip (AF_INET6,
2432 while ( (GNUNET_YES ==
2433 GNUNET_CONTAINER_multihashmap_contains (destination_map,
2437 sizeof (struct in6_addr))) ||
2440 sizeof (struct in6_addr))) );
2446 * Free resources occupied by a destination entry.
2448 * @param de entry to free
2451 free_destination_entry (struct DestinationEntry *de)
2453 struct DestinationChannel *dt;
2455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2456 "Cleaning up destination entry `%s'\n",
2457 print_channel_destination (de));
2458 GNUNET_STATISTICS_update (stats,
2459 gettext_noop ("# Active destinations"),
2461 while (NULL != (dt = de->dt_head))
2463 GNUNET_CONTAINER_DLL_remove (de->dt_head,
2468 if (NULL != de->heap_node)
2470 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2471 de->heap_node = NULL;
2472 GNUNET_assert (GNUNET_YES ==
2473 GNUNET_CONTAINER_multihashmap_remove (destination_map,
2482 * We have too many active destinations. Clean up the oldest destination.
2484 * @param except destination that must NOT be cleaned up, even if it is the oldest
2487 expire_destination (struct DestinationEntry *except)
2489 struct DestinationEntry *de;
2491 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2492 GNUNET_assert (NULL != de);
2494 return; /* can't do this */
2495 free_destination_entry (de);
2500 * Allocate an IP address for the response.
2502 * @param result_af desired address family; set to the actual
2503 * address family; can initially be AF_UNSPEC if there
2504 * is no preference; will be set to AF_UNSPEC if the
2506 * @param addr set to either v4 or v6 depending on which
2507 * storage location was used; set to NULL if allocation failed
2508 * @param v4 storage space for an IPv4 address
2509 * @param v6 storage space for an IPv6 address
2510 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2511 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2514 allocate_response_ip (int *result_af,
2517 struct in6_addr *v6)
2524 allocate_v4_address (v4))
2525 *result_af = AF_UNSPEC;
2531 allocate_v6_address (v6))
2532 *result_af = AF_UNSPEC;
2538 allocate_v4_address (v4))
2541 *result_af = AF_INET;
2543 else if (GNUNET_OK ==
2544 allocate_v6_address (v6))
2547 *result_af = AF_INET6;
2552 return GNUNET_SYSERR;
2559 * A client asks us to setup a redirection via some exit node to a
2560 * particular IP. Check if @a msg is well-formed.
2563 * @param cls client requesting client
2564 * @param msg redirection request
2565 * @return #GNUNET_OK if @a msg is well-formed
2568 check_client_redirect_to_ip (void *cls,
2569 const struct RedirectToIpRequestMessage *msg)
2574 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2575 addr_af = (int) htonl (msg->addr_af);
2579 if (alen != sizeof (struct in_addr))
2582 return GNUNET_SYSERR;
2586 if (alen != sizeof (struct in6_addr))
2589 return GNUNET_SYSERR;
2594 return GNUNET_SYSERR;
2601 * A client asks us to setup a redirection via some exit node to a
2602 * particular IP. Setup the redirection and give the client the
2605 * @param cls client requesting client
2606 * @param msg redirection request
2609 handle_client_redirect_to_ip (void *cls,
2610 const struct RedirectToIpRequestMessage *msg)
2612 struct GNUNET_SERVICE_Client *client = cls;
2619 struct DestinationEntry *de;
2620 struct GNUNET_HashCode key;
2622 alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2623 addr_af = (int) htonl (msg->addr_af);
2624 /* allocate response IP */
2625 result_af = (int) htonl (msg->result_af);
2626 if (GNUNET_OK != allocate_response_ip (&result_af,
2630 GNUNET_SERVICE_client_drop (client);
2633 /* send reply with our IP address */
2634 send_client_reply (client,
2638 if (result_af == AF_UNSPEC)
2640 /* failure, we're done */
2641 GNUNET_SERVICE_client_continue (client);
2646 char sbuf[INET6_ADDRSTRLEN];
2647 char dbuf[INET6_ADDRSTRLEN];
2649 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2650 "Allocated address %s for redirection via exit to %s\n",
2651 inet_ntop (result_af,
2661 /* setup destination record */
2662 de = GNUNET_new (struct DestinationEntry);
2663 de->is_service = GNUNET_NO;
2664 de->details.exit_destination.af = addr_af;
2665 GNUNET_memcpy (&de->details.exit_destination.ip,
2668 get_destination_key_from_ip (result_af,
2672 GNUNET_assert (GNUNET_OK ==
2673 GNUNET_CONTAINER_multihashmap_put (destination_map,
2676 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2677 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2679 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2680 GNUNET_STATISTICS_update (stats,
2681 gettext_noop ("# Active destinations"),
2683 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2684 expire_destination (de);
2685 GNUNET_SERVICE_client_continue (client);
2690 * A client asks us to setup a redirection to a particular peer
2691 * offering a service. Setup the redirection and give the client the
2694 * @param cls requesting client
2695 * @param msg redirection request
2698 handle_client_redirect_to_service (void *cls,
2699 const struct RedirectToServiceRequestMessage *msg)
2701 struct GNUNET_SERVICE_Client *client = cls;
2706 struct DestinationEntry *de;
2707 struct GNUNET_HashCode key;
2708 struct DestinationChannel *dt;
2710 /* allocate response IP */
2711 result_af = (int) htonl (msg->result_af);
2713 allocate_response_ip (&result_af,
2719 GNUNET_SERVICE_client_drop (client);
2722 send_client_reply (client,
2726 if (result_af == AF_UNSPEC)
2728 /* failure, we're done */
2729 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2730 _("Failed to allocate IP address for new destination\n"));
2731 GNUNET_SERVICE_client_continue (client);
2736 char sbuf[INET6_ADDRSTRLEN];
2738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2739 "Allocated address %s for redirection to service %s on peer %s\n",
2740 inet_ntop (result_af,
2744 GNUNET_h2s (&msg->service_descriptor),
2745 GNUNET_i2s (&msg->target));
2748 /* setup destination record */
2749 de = GNUNET_new (struct DestinationEntry);
2750 de->is_service = GNUNET_YES;
2751 de->details.service_destination.target = msg->target;
2752 de->details.service_destination.service_descriptor = msg->service_descriptor;
2753 get_destination_key_from_ip (result_af,
2757 GNUNET_assert (GNUNET_OK ==
2758 GNUNET_CONTAINER_multihashmap_put (destination_map,
2761 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2763 = GNUNET_CONTAINER_heap_insert (destination_heap,
2765 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2766 while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2767 expire_destination (de);
2769 dt = GNUNET_new (struct DestinationChannel);
2770 dt->destination = de;
2771 GNUNET_CONTAINER_DLL_insert (de->dt_head,
2775 GNUNET_SERVICE_client_continue (client);
2781 * Free memory occupied by an entry in the destination map.
2785 * @param value a `struct DestinationEntry *`
2786 * @return #GNUNET_OK (continue to iterate)
2789 cleanup_destination (void *cls,
2790 const struct GNUNET_HashCode *key,
2793 struct DestinationEntry *de = value;
2795 free_destination_entry (de);
2801 * Free memory occupied by an entry in the channel map.
2805 * @param value a `struct ChannelState *`
2806 * @return #GNUNET_OK (continue to iterate)
2809 cleanup_channel (void *cls,
2810 const struct GNUNET_HashCode *key,
2813 struct ChannelState *ts = value;
2815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2816 "Tearing down channel to `%s' during cleanup\n",
2817 print_channel_destination (&ts->destination));
2818 free_channel_state (ts);
2824 * Function scheduled as very last function, cleans up after us
2833 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2834 "VPN is shutting down\n");
2835 if (NULL != destination_map)
2837 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2838 &cleanup_destination,
2840 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2841 destination_map = NULL;
2843 if (NULL != destination_heap)
2845 GNUNET_CONTAINER_heap_destroy (destination_heap);
2846 destination_heap = NULL;
2848 if (NULL != channel_map)
2850 GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2853 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2856 if (NULL != channel_heap)
2858 GNUNET_CONTAINER_heap_destroy (channel_heap);
2859 channel_heap = NULL;
2861 if (NULL != cadet_handle)
2863 GNUNET_CADET_disconnect (cadet_handle);
2864 cadet_handle = NULL;
2866 if (NULL != helper_handle)
2868 GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2869 GNUNET_HELPER_wait (helper_handle);
2870 helper_handle = NULL;
2874 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2878 GNUNET_free_non_null (vpn_argv[i]);
2883 * Callback called when a client connects to the service.
2885 * @param cls closure for the service
2886 * @param c the new client that connected to the service
2887 * @param mq the message queue used to send messages to the client
2891 client_connect_cb (void *cls,
2892 struct GNUNET_SERVICE_Client *c,
2893 struct GNUNET_MQ_Handle *mq)
2900 * Callback called when a client disconnected from the service
2902 * @param cls closure for the service
2903 * @param c the client that disconnected
2904 * @param internal_cls should be equal to @a c
2907 client_disconnect_cb (void *cls,
2908 struct GNUNET_SERVICE_Client *c,
2911 GNUNET_assert (c == internal_cls);
2916 * Main function that will be run by the scheduler.
2918 * @param cls closure
2919 * @param cfg_ configuration
2920 * @param service the initialized service
2924 const struct GNUNET_CONFIGURATION_Handle *cfg_,
2925 struct GNUNET_SERVICE_Handle *service)
2936 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2939 GNUNET_OS_check_helper_binary (binary,
2941 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2943 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2944 "`%s' is not SUID, refusing to run.\n",
2945 "gnunet-helper-vpn");
2946 GNUNET_free (binary);
2948 /* we won't "really" exit here, as the 'service' is still running;
2949 however, as no handlers are registered, the service won't do
2953 GNUNET_free (binary);
2955 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2957 GNUNET_CONFIGURATION_get_value_number (cfg,
2960 &max_destination_mappings))
2961 max_destination_mappings = 200;
2963 GNUNET_CONFIGURATION_get_value_number (cfg,
2966 &max_channel_mappings))
2967 max_channel_mappings = 200;
2969 destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2970 destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2971 channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2972 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2975 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2976 if (GNUNET_SYSERR ==
2977 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2979 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2980 GNUNET_SCHEDULER_shutdown ();
2983 vpn_argv[1] = ifname;
2985 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2987 if ( (GNUNET_SYSERR ==
2988 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2990 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2992 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2993 _("Must specify valid IPv6 address"));
2994 GNUNET_SCHEDULER_shutdown ();
2995 GNUNET_free_non_null (ipv6addr);
2998 vpn_argv[2] = ipv6addr;
2999 ipv6prefix_s = NULL;
3000 if (GNUNET_SYSERR ==
3001 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3004 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3005 GNUNET_SCHEDULER_shutdown ();
3006 GNUNET_free_non_null (ipv6prefix_s);
3009 vpn_argv[3] = ipv6prefix_s;
3011 GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3014 (ipv6prefix >= 127) )
3016 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3017 _("Must specify valid IPv6 mask"));
3018 GNUNET_SCHEDULER_shutdown ();
3024 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3025 _("IPv6 support disabled as this system does not support IPv6\n"));
3026 vpn_argv[2] = GNUNET_strdup ("-");
3027 vpn_argv[3] = GNUNET_strdup ("-");
3029 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3032 if ( (GNUNET_SYSERR ==
3033 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3035 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3037 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3038 _("Must specify valid IPv4 address"));
3039 GNUNET_SCHEDULER_shutdown ();
3040 GNUNET_free_non_null (ipv4addr);
3043 vpn_argv[4] = ipv4addr;
3045 if ( (GNUNET_SYSERR ==
3046 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3048 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3050 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3051 _("Must specify valid IPv4 mask"));
3052 GNUNET_SCHEDULER_shutdown ();
3053 GNUNET_free_non_null (ipv4mask);
3056 vpn_argv[5] = ipv4mask;
3060 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3061 _("IPv4 support disabled as this system does not support IPv4\n"));
3062 vpn_argv[4] = GNUNET_strdup ("-");
3063 vpn_argv[5] = GNUNET_strdup ("-");
3067 cadet_handle = GNUNET_CADET_connect (cfg_);
3068 // FIXME never opens ports???
3069 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3070 "gnunet-helper-vpn", vpn_argv,
3071 &message_token, NULL, NULL);
3072 GNUNET_SCHEDULER_add_shutdown (&cleanup,
3078 * Define "main" method using service macro.
3082 GNUNET_SERVICE_OPTION_NONE,
3085 &client_disconnect_cb,
3087 GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3088 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP,
3089 struct RedirectToIpRequestMessage,
3091 GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3092 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3093 struct RedirectToServiceRequestMessage,
3095 GNUNET_MQ_handler_end ());
3098 /* end of gnunet-service-vpn.c */