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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file vpn/gnunet-service-vpn.c
23 * @brief service that opens a virtual interface and allows its clients
24 * to allocate IPs on the virtual interface and to then redirect
25 * IP traffic received on those IPs via the GNUnet cadet
26 * @author Philipp Toelke
27 * @author Christian Grothoff
30 * - keep multiple peers/cadet channels ready as alternative exits /
31 * detect & recover from channel-to-exit failure gracefully
34 #include "gnunet_util_lib.h"
35 #include "gnunet_common.h"
36 #include "gnunet_protocols.h"
37 #include "gnunet_applications.h"
38 #include "gnunet_cadet_service.h"
39 #include "gnunet_statistics_service.h"
40 #include "gnunet_constants.h"
41 #include "gnunet_tun_lib.h"
42 #include "gnunet_regex_service.h"
48 * Maximum number of messages we allow in the queue for cadet.
50 #define MAX_MESSAGE_QUEUE_SIZE 4
54 * State we keep for each of our channels.
59 * Information we track for each IP address to determine which channel
60 * to send the traffic over to the destination.
62 struct DestinationEntry;
65 * List of channels we keep for each destination port for a given
68 struct DestinationChannel
73 struct DestinationChannel *next;
78 struct DestinationChannel *prev;
81 * Destination entry list this `struct DestinationChannel` belongs with.
83 struct DestinationEntry *destination;
86 * Destination port this channel state is used for.
88 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
99 * Key under which this entry is in the 'destination_map' (only valid
100 * if 'heap_node != NULL').
102 struct GNUNET_HashCode key;
105 * Head of DLL of channels associated with this destination.
107 struct DestinationChannel *dt_head;
110 * Tail of DLL of channels associated with this destination.
112 struct DestinationChannel *dt_tail;
115 * Entry for this entry in the destination_heap.
117 struct GNUNET_CONTAINER_HeapNode *heap_node;
120 * #GNUNET_NO if this is a channel to an Internet-exit,
121 * #GNUNET_YES if this channel is to a service.
126 * Details about the connection (depending on is_service).
133 * The description of the service (only used for service channels).
135 struct GNUNET_HashCode service_descriptor;
138 * Peer offering the service.
140 struct GNUNET_PeerIdentity target;
141 } service_destination;
146 * Address family used (AF_INET or AF_INET6).
151 * IP address of the ultimate destination (only used for exit channels).
156 * Address if af is AF_INET.
161 * Address if af is AF_INET6.
171 * A messages we have in queue for a particular channel.
173 struct ChannelMessageQueueEntry
176 * This is a doubly-linked list.
178 struct ChannelMessageQueueEntry *next;
181 * This is a doubly-linked list.
183 struct ChannelMessageQueueEntry *prev;
186 * Number of bytes in @e msg.
191 * Message to transmit, allocated at the end of this struct.
198 * State we keep for each of our channels.
203 * Information about the channel to use, NULL if no channel
204 * is available right now.
206 struct GNUNET_CADET_Channel *channel;
209 * Active query with REGEX to locate exit.
211 struct GNUNET_REGEX_Search *search;
214 * Entry for this entry in the channel_heap, NULL as long as this
215 * channel state is not fully bound.
217 struct GNUNET_CONTAINER_HeapNode *heap_node;
220 * Head of list of messages scheduled for transmission.
222 struct ChannelMessageQueueEntry *tmq_head;
225 * Tail of list of messages scheduled for transmission.
227 struct ChannelMessageQueueEntry *tmq_tail;
230 * Destination to which this channel leads. Note that
231 * this struct is NOT in the destination_map (but a
232 * local copy) and that the 'heap_node' should always
235 struct DestinationEntry destination;
238 * Addess family used for this channel on the local TUN interface.
243 * Is this channel new (#GNUNET_NO), or did we exchange messages with the
244 * other side already (#GNUNET_YES)?
249 * Length of the doubly linked 'tmq_head/tmq_tail' list.
251 unsigned int tmq_length;
254 * IPPROTO_TCP or IPPROTO_UDP once bound.
259 * IP address of the source on our end, initially uninitialized.
264 * Address if af is AF_INET.
269 * Address if af is AF_INET6.
275 * Destination IP address used by the source on our end (this is the IP
276 * that we pick freely within the VPN's channel IP range).
281 * Address if af is AF_INET.
286 * Address if af is AF_INET6.
292 * Source port used by the sender on our end; 0 for uninitialized.
294 uint16_t source_port;
297 * Destination port used by the sender on our end; 0 for uninitialized.
299 uint16_t destination_port;
304 * Return value from #main().
306 static int global_ret;
309 * Configuration we use.
311 static const struct GNUNET_CONFIGURATION_Handle *cfg;
314 * Handle to the cadet service.
316 static struct GNUNET_CADET_Handle *cadet_handle;
319 * Map from IP address to destination information (possibly with a
320 * CADET channel handle for fast setup).
322 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
325 * Min-Heap sorted by activity time to expire old mappings.
327 static struct GNUNET_CONTAINER_Heap *destination_heap;
330 * Map from source and destination address (IP+port) to connection
331 * information (mostly with the respective CADET channel handle).
333 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
336 * Min-Heap sorted by activity time to expire old mappings; values are
337 * of type 'struct ChannelState'.
339 static struct GNUNET_CONTAINER_Heap *channel_heap;
344 static struct GNUNET_STATISTICS_Handle *stats;
347 * The handle to the VPN helper process "gnunet-helper-vpn".
349 static struct GNUNET_HELPER_Handle *helper_handle;
352 * Arguments to the vpn helper.
354 static char *vpn_argv[7];
357 * Length of the prefix of the VPN's IPv6 network.
359 static unsigned long long ipv6prefix;
362 * If there are more than this number of address-mappings, old ones
365 static unsigned long long max_destination_mappings;
368 * If there are more than this number of open channels, old ones
371 static unsigned long long max_channel_mappings;
375 * Compute the key under which we would store an entry in the
376 * #destination_map for the given IP address.
378 * @param af address family (AF_INET or AF_INET6)
379 * @param address IP address, struct in_addr or struct in6_addr
380 * @param key where to store the key
383 get_destination_key_from_ip (int af,
385 struct GNUNET_HashCode *key)
390 GNUNET_CRYPTO_hash (address, sizeof(struct in_addr), key);
394 GNUNET_CRYPTO_hash (address, sizeof(struct in6_addr), key);
405 * Compute the key under which we would store an entry in the
406 * channel_map for the given socket address pair.
408 * @param af address family (AF_INET or AF_INET6)
409 * @param protocol IPPROTO_TCP or IPPROTO_UDP
410 * @param source_ip sender's source IP, struct in_addr or struct in6_addr
411 * @param source_port sender's source port
412 * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
413 * @param destination_port sender's destination port
414 * @param key where to store the key
417 get_channel_key_from_ips (int af,
419 const void *source_ip,
420 uint16_t source_port,
421 const void *destination_ip,
422 uint16_t destination_port,
423 struct GNUNET_HashCode *key)
427 memset (key, 0, sizeof(struct GNUNET_HashCode));
428 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
429 so we put the ports in there (and hope for few collisions) */
431 GNUNET_memcpy (off, &source_port, sizeof(uint16_t));
432 off += sizeof(uint16_t);
433 GNUNET_memcpy (off, &destination_port, sizeof(uint16_t));
434 off += sizeof(uint16_t);
438 GNUNET_memcpy (off, source_ip, sizeof(struct in_addr));
439 off += sizeof(struct in_addr);
440 GNUNET_memcpy (off, destination_ip, sizeof(struct in_addr));
441 off += sizeof(struct in_addr);
445 GNUNET_memcpy (off, source_ip, sizeof(struct in6_addr));
446 off += sizeof(struct in6_addr);
447 GNUNET_memcpy (off, destination_ip, sizeof(struct in6_addr));
448 off += sizeof(struct in6_addr);
455 GNUNET_memcpy (off, &protocol, sizeof(uint8_t));
456 /* off += sizeof (uint8_t); */
461 * Notify the client about the result of its request.
463 * @param client client to notify
464 * @param request_id original request ID to include in response
465 * @param result_af resulting address family
466 * @param addr resulting IP address
469 send_client_reply (struct GNUNET_SERVICE_Client *client,
474 struct GNUNET_MQ_Envelope *env;
475 struct RedirectToIpResponseMessage *res;
481 rlen = sizeof(struct in_addr);
485 rlen = sizeof(struct in6_addr);
496 env = GNUNET_MQ_msg_extra (res, rlen, GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
497 res->result_af = htonl (result_af);
498 res->request_id = request_id;
499 GNUNET_memcpy (&res[1], addr, rlen);
500 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), env);
505 * Free resources associated with a channel state.
507 * @param ts state to free
510 free_channel_state (struct ChannelState *ts)
512 struct GNUNET_HashCode key;
513 struct ChannelMessageQueueEntry *tnq;
514 struct GNUNET_CADET_Channel *channel;
516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up channel state\n");
517 if (NULL != (channel = ts->channel))
520 GNUNET_CADET_channel_destroy (channel);
523 GNUNET_STATISTICS_update (stats,
524 gettext_noop ("# Active channels"),
527 while (NULL != (tnq = ts->tmq_head))
529 GNUNET_CONTAINER_DLL_remove (ts->tmq_head, ts->tmq_tail, tnq);
533 GNUNET_assert (0 == ts->tmq_length);
534 GNUNET_assert (NULL == ts->destination.heap_node);
535 if (NULL != ts->search)
537 GNUNET_REGEX_search_cancel (ts->search);
540 if (NULL != ts->heap_node)
542 GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
543 ts->heap_node = NULL;
544 get_channel_key_from_ips (ts->af,
549 ts->destination_port,
553 GNUNET_CONTAINER_multihashmap_remove (channel_map, &key, ts));
560 * Add the given message to the given channel and trigger the
561 * transmission process.
563 * @param ts channel to queue the message for
564 * @param env message to queue
567 send_to_channel (struct ChannelState *ts, struct GNUNET_MQ_Envelope *env)
569 struct GNUNET_MQ_Handle *mq;
571 GNUNET_assert (NULL != ts->channel);
572 mq = GNUNET_CADET_get_mq (ts->channel);
573 GNUNET_MQ_env_set_options (env,
574 GNUNET_MQ_PRIO_BEST_EFFORT
575 | GNUNET_MQ_PREF_OUT_OF_ORDER);
576 GNUNET_MQ_send (mq, env);
577 if (GNUNET_MQ_get_length (mq) > MAX_MESSAGE_QUEUE_SIZE)
579 env = GNUNET_MQ_unsent_head (mq);
580 GNUNET_assert (NULL != env);
581 GNUNET_STATISTICS_update (stats,
583 "# Messages dropped in cadet queue (overflow)"),
586 GNUNET_MQ_discard (env);
592 * Output destination of a channel for diagnostics.
594 * @param de destination to process
595 * @return diagnostic string describing destination
598 print_channel_destination (const struct DestinationEntry *de)
600 static char dest[256];
604 GNUNET_snprintf (dest,
607 GNUNET_i2s (&de->details.service_destination.target),
609 &de->details.service_destination.service_descriptor));
613 inet_ntop (de->details.exit_destination.af,
614 &de->details.exit_destination.ip,
623 * Function called whenever a channel is destroyed. Should clean up
624 * any associated state.
626 * @param cls our `struct ChannelState`
627 * @param channel connection to the other end (henceforth invalid)
630 channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel)
632 struct ChannelState *ts = cls;
635 NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
637 "CADET notified us about death of channel to `%s'\n",
638 print_channel_destination (&ts->destination));
639 free_channel_state (ts);
644 * Synthesize a plausible ICMP payload for an ICMP error
645 * response on the given channel.
647 * @param ts channel information
648 * @param ipp IPv4 header to fill in (ICMP payload)
649 * @param udp "UDP" header to fill in (ICMP payload); might actually
650 * also be the first 8 bytes of the TCP header
653 make_up_icmpv4_payload (struct ChannelState *ts,
654 struct GNUNET_TUN_IPv4Header *ipp,
655 struct GNUNET_TUN_UdpHeader *udp)
657 GNUNET_TUN_initialize_ipv4_header (ipp,
659 sizeof(struct GNUNET_TUN_TcpHeader),
661 &ts->destination_ip.v4);
662 udp->source_port = htons (ts->source_port);
663 udp->destination_port = htons (ts->destination_port);
664 udp->len = htons (0);
665 udp->crc = htons (0);
670 * Synthesize a plausible ICMP payload for an ICMP error
671 * response on the given channel.
673 * @param ts channel information
674 * @param ipp IPv6 header to fill in (ICMP payload)
675 * @param udp "UDP" header to fill in (ICMP payload); might actually
676 * also be the first 8 bytes of the TCP header
679 make_up_icmpv6_payload (struct ChannelState *ts,
680 struct GNUNET_TUN_IPv6Header *ipp,
681 struct GNUNET_TUN_UdpHeader *udp)
683 GNUNET_TUN_initialize_ipv6_header (ipp,
685 sizeof(struct GNUNET_TUN_TcpHeader),
687 &ts->destination_ip.v6);
688 udp->source_port = htons (ts->source_port);
689 udp->destination_port = htons (ts->destination_port);
690 udp->len = htons (0);
691 udp->crc = htons (0);
696 * We got an ICMP packet back from the CADET channel. Check it is OK.
698 * @param cls our `struct ChannelState *`
699 * @param message the actual message
700 * @return #GNUNET_OK to keep the connection open,
701 * #GNUNET_SYSERR to close it (signal serious error)
704 check_icmp_back (void *cls, const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
706 struct ChannelState *ts = cls;
708 if (NULL == ts->heap_node)
711 return GNUNET_SYSERR;
713 if (AF_UNSPEC == ts->af)
716 return GNUNET_SYSERR;
723 * We got an ICMP packet back from the CADET channel. Pass it on to the
724 * local virtual interface via the helper.
726 * @param cls our `struct ChannelState *`
727 * @param message the actual message
730 handle_icmp_back (void *cls, const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
732 struct ChannelState *ts = cls;
735 GNUNET_STATISTICS_update (stats,
736 gettext_noop ("# ICMP packets received from cadet"),
740 ntohs (i2v->header.size) - sizeof(struct GNUNET_EXIT_IcmpToVPNMessage);
742 char sbuf[INET6_ADDRSTRLEN];
743 char dbuf[INET6_ADDRSTRLEN];
746 GNUNET_ERROR_TYPE_DEBUG,
747 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
749 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof(sbuf)),
750 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof(dbuf)));
755 size_t size = sizeof(struct GNUNET_TUN_IPv4Header)
756 + sizeof(struct GNUNET_TUN_IcmpHeader)
757 + sizeof(struct GNUNET_MessageHeader)
758 + sizeof(struct GNUNET_TUN_Layer2PacketHeader) + mlen;
760 /* reserve some extra space in case we have an ICMP type here where
761 we will need to make up the payload ourselves */
762 char buf[size + sizeof(struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
763 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
764 struct GNUNET_TUN_Layer2PacketHeader *tun =
765 (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
766 struct GNUNET_TUN_IPv4Header *ipv4 =
767 (struct GNUNET_TUN_IPv4Header *) &tun[1];
768 struct GNUNET_TUN_IcmpHeader *icmp =
769 (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
770 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
771 tun->flags = htons (0);
772 tun->proto = htons (ETH_P_IPV4);
773 GNUNET_TUN_initialize_ipv4_header (ipv4,
775 sizeof(struct GNUNET_TUN_IcmpHeader)
777 &ts->destination_ip.v4,
779 *icmp = i2v->icmp_header;
780 GNUNET_memcpy (&icmp[1], &i2v[1], mlen);
781 /* For some ICMP types, we need to adjust (make up) the payload here.
782 Also, depending on the AF used on the other side, we have to
783 do ICMP PT (translate ICMP types) */
784 switch (ntohl (i2v->af))
789 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
790 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
793 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
794 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
795 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: {
796 struct GNUNET_TUN_IPv4Header *ipp =
797 (struct GNUNET_TUN_IPv4Header *) &icmp[1];
798 struct GNUNET_TUN_UdpHeader *udp =
799 (struct GNUNET_TUN_UdpHeader *) &ipp[1];
803 /* sender did not strip ICMP payload? */
807 size += sizeof(struct GNUNET_TUN_IPv4Header) + 8;
808 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
809 make_up_icmpv4_payload (ts, ipp, udp);
815 GNUNET_STATISTICS_update (
817 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
826 /* ICMP PT 6-to-4 and possibly making up payloads */
829 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
830 icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
832 struct GNUNET_TUN_IPv4Header *ipp =
833 (struct GNUNET_TUN_IPv4Header *) &icmp[1];
834 struct GNUNET_TUN_UdpHeader *udp =
835 (struct GNUNET_TUN_UdpHeader *) &ipp[1];
839 /* sender did not strip ICMP payload? */
843 size += sizeof(struct GNUNET_TUN_IPv4Header) + 8;
844 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
845 make_up_icmpv4_payload (ts, ipp, udp);
849 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
850 icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
852 struct GNUNET_TUN_IPv4Header *ipp =
853 (struct GNUNET_TUN_IPv4Header *) &icmp[1];
854 struct GNUNET_TUN_UdpHeader *udp =
855 (struct GNUNET_TUN_UdpHeader *) &ipp[1];
859 /* sender did not strip ICMP payload? */
863 size += sizeof(struct GNUNET_TUN_IPv4Header) + 8;
864 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
865 make_up_icmpv4_payload (ts, ipp, udp);
869 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
870 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
871 GNUNET_STATISTICS_update (
873 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
878 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
879 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
882 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
883 icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
888 GNUNET_STATISTICS_update (
890 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
902 msg->size = htons (size);
903 GNUNET_TUN_calculate_icmp_checksum (icmp, &i2v[1], mlen);
904 (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
910 size_t size = sizeof(struct GNUNET_TUN_IPv6Header)
911 + sizeof(struct GNUNET_TUN_IcmpHeader)
912 + sizeof(struct GNUNET_MessageHeader)
913 + sizeof(struct GNUNET_TUN_Layer2PacketHeader) + mlen;
915 char buf[size + sizeof(struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
916 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
917 struct GNUNET_TUN_Layer2PacketHeader *tun =
918 (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
919 struct GNUNET_TUN_IPv6Header *ipv6 =
920 (struct GNUNET_TUN_IPv6Header *) &tun[1];
921 struct GNUNET_TUN_IcmpHeader *icmp =
922 (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
923 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
924 tun->flags = htons (0);
925 tun->proto = htons (ETH_P_IPV6);
926 GNUNET_TUN_initialize_ipv6_header (ipv6,
928 sizeof(struct GNUNET_TUN_IcmpHeader)
930 &ts->destination_ip.v6,
932 *icmp = i2v->icmp_header;
933 GNUNET_memcpy (&icmp[1], &i2v[1], mlen);
935 /* For some ICMP types, we need to adjust (make up) the payload here.
936 Also, depending on the AF used on the other side, we have to
937 do ICMP PT (translate ICMP types) */
938 switch (ntohl (i2v->af))
941 /* ICMP PT 4-to-6 and possibly making up payloads */
944 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
945 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
948 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
949 icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
952 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
953 icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
955 struct GNUNET_TUN_IPv6Header *ipp =
956 (struct GNUNET_TUN_IPv6Header *) &icmp[1];
957 struct GNUNET_TUN_UdpHeader *udp =
958 (struct GNUNET_TUN_UdpHeader *) &ipp[1];
962 /* sender did not strip ICMP payload? */
966 size += sizeof(struct GNUNET_TUN_IPv6Header) + 8;
967 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
968 make_up_icmpv6_payload (ts, ipp, udp);
972 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
973 icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
975 struct GNUNET_TUN_IPv6Header *ipp =
976 (struct GNUNET_TUN_IPv6Header *) &icmp[1];
977 struct GNUNET_TUN_UdpHeader *udp =
978 (struct GNUNET_TUN_UdpHeader *) &ipp[1];
982 /* sender did not strip ICMP payload? */
986 size += sizeof(struct GNUNET_TUN_IPv6Header) + 8;
987 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
988 make_up_icmpv6_payload (ts, ipp, udp);
992 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
993 GNUNET_STATISTICS_update (
995 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
1001 GNUNET_break_op (0);
1002 GNUNET_STATISTICS_update (
1004 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1015 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1016 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1017 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1018 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: {
1019 struct GNUNET_TUN_IPv6Header *ipp =
1020 (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1021 struct GNUNET_TUN_UdpHeader *udp =
1022 (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1026 /* sender did not strip ICMP payload? */
1027 GNUNET_break_op (0);
1030 size += sizeof(struct GNUNET_TUN_IPv6Header) + 8;
1031 GNUNET_assert (8 == sizeof(struct GNUNET_TUN_UdpHeader));
1032 make_up_icmpv6_payload (ts, ipp, udp);
1036 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1040 GNUNET_break_op (0);
1041 GNUNET_STATISTICS_update (
1043 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1052 GNUNET_break_op (0);
1055 msg->size = htons (size);
1056 GNUNET_TUN_calculate_icmp_checksum (icmp, &i2v[1], mlen);
1057 (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1065 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1066 GNUNET_TIME_absolute_get ().abs_value_us);
1067 GNUNET_CADET_receive_done (ts->channel);
1072 * We got a UDP packet back from the CADET channel. Check that it is OK.
1074 * @param cls our `struct ChannelState *`
1075 * @param reply the actual message
1076 * @return #GNUNET_OK to keep the connection open,
1077 * #GNUNET_SYSERR to close it (signal serious error)
1080 check_udp_back (void *cls, const struct GNUNET_EXIT_UdpReplyMessage *reply)
1082 struct ChannelState *ts = cls;
1084 if (NULL == ts->heap_node)
1086 GNUNET_break_op (0);
1087 return GNUNET_SYSERR;
1089 if (AF_UNSPEC == ts->af)
1091 GNUNET_break_op (0);
1092 return GNUNET_SYSERR;
1099 * We got a UDP packet back from the CADET channel. Pass it on to the
1100 * local virtual interface via the helper.
1102 * @param cls our `struct ChannelState *`
1103 * @param reply the actual message
1106 handle_udp_back (void *cls, const struct GNUNET_EXIT_UdpReplyMessage *reply)
1108 struct ChannelState *ts = cls;
1111 GNUNET_STATISTICS_update (stats,
1112 gettext_noop ("# UDP packets received from cadet"),
1116 ntohs (reply->header.size) - sizeof(struct GNUNET_EXIT_UdpReplyMessage);
1118 char sbuf[INET6_ADDRSTRLEN];
1119 char dbuf[INET6_ADDRSTRLEN];
1122 GNUNET_ERROR_TYPE_DEBUG,
1123 "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1124 (unsigned int) mlen,
1125 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof(sbuf)),
1126 ts->destination_port,
1127 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof(dbuf)),
1133 size_t size = sizeof(struct GNUNET_TUN_IPv4Header)
1134 + sizeof(struct GNUNET_TUN_UdpHeader)
1135 + sizeof(struct GNUNET_MessageHeader)
1136 + sizeof(struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1138 char buf[size] GNUNET_ALIGN;
1139 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1140 struct GNUNET_TUN_Layer2PacketHeader *tun =
1141 (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1142 struct GNUNET_TUN_IPv4Header *ipv4 =
1143 (struct GNUNET_TUN_IPv4Header *) &tun[1];
1144 struct GNUNET_TUN_UdpHeader *udp =
1145 (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1146 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1147 msg->size = htons (size);
1148 tun->flags = htons (0);
1149 tun->proto = htons (ETH_P_IPV4);
1150 GNUNET_TUN_initialize_ipv4_header (ipv4,
1152 sizeof(struct GNUNET_TUN_UdpHeader)
1154 &ts->destination_ip.v4,
1156 if (0 == ntohs (reply->source_port))
1157 udp->source_port = htons (ts->destination_port);
1159 udp->source_port = reply->source_port;
1160 if (0 == ntohs (reply->destination_port))
1161 udp->destination_port = htons (ts->source_port);
1163 udp->destination_port = reply->destination_port;
1164 udp->len = htons (mlen + sizeof(struct GNUNET_TUN_UdpHeader));
1165 GNUNET_TUN_calculate_udp4_checksum (ipv4, udp, &reply[1], mlen);
1166 GNUNET_memcpy (&udp[1], &reply[1], mlen);
1167 (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1173 size_t size = sizeof(struct GNUNET_TUN_IPv6Header)
1174 + sizeof(struct GNUNET_TUN_UdpHeader)
1175 + sizeof(struct GNUNET_MessageHeader)
1176 + sizeof(struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1178 char buf[size] GNUNET_ALIGN;
1179 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1180 struct GNUNET_TUN_Layer2PacketHeader *tun =
1181 (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1182 struct GNUNET_TUN_IPv6Header *ipv6 =
1183 (struct GNUNET_TUN_IPv6Header *) &tun[1];
1184 struct GNUNET_TUN_UdpHeader *udp =
1185 (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1186 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1187 msg->size = htons (size);
1188 tun->flags = htons (0);
1189 tun->proto = htons (ETH_P_IPV6);
1190 GNUNET_TUN_initialize_ipv6_header (ipv6,
1192 sizeof(struct GNUNET_TUN_UdpHeader)
1194 &ts->destination_ip.v6,
1196 if (0 == ntohs (reply->source_port))
1197 udp->source_port = htons (ts->destination_port);
1199 udp->source_port = reply->source_port;
1200 if (0 == ntohs (reply->destination_port))
1201 udp->destination_port = htons (ts->source_port);
1203 udp->destination_port = reply->destination_port;
1204 udp->len = htons (mlen + sizeof(struct GNUNET_TUN_UdpHeader));
1205 GNUNET_TUN_calculate_udp6_checksum (ipv6, udp, &reply[1], mlen);
1206 GNUNET_memcpy (&udp[1], &reply[1], mlen);
1207 (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1215 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1216 GNUNET_TIME_absolute_get ().abs_value_us);
1217 GNUNET_CADET_receive_done (ts->channel);
1222 * We got a TCP packet back from the CADET channel. Check it is OK.
1224 * @param cls our `struct ChannelState *`
1225 * @param data the actual message
1226 * @return #GNUNET_OK to keep the connection open,
1227 * #GNUNET_SYSERR to close it (signal serious error)
1230 check_tcp_back (void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
1232 struct ChannelState *ts = cls;
1234 if (NULL == ts->heap_node)
1236 GNUNET_break_op (0);
1237 return GNUNET_SYSERR;
1239 if (data->tcp_header.off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1241 GNUNET_break_op (0);
1242 return GNUNET_SYSERR;
1249 * We got a TCP packet back from the CADET channel. Pass it on to the
1250 * local virtual interface via the helper.
1252 * @param cls our `struct ChannelState *`
1253 * @param data the actual message
1256 handle_tcp_back (void *cls, const struct GNUNET_EXIT_TcpDataMessage *data)
1258 struct ChannelState *ts = cls;
1261 GNUNET_STATISTICS_update (stats,
1262 gettext_noop ("# TCP packets received from cadet"),
1265 mlen = ntohs (data->header.size) - sizeof(struct GNUNET_EXIT_TcpDataMessage);
1267 char sbuf[INET6_ADDRSTRLEN];
1268 char dbuf[INET6_ADDRSTRLEN];
1271 GNUNET_ERROR_TYPE_DEBUG,
1272 "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1273 (unsigned int) mlen,
1274 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof(sbuf)),
1275 ts->destination_port,
1276 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof(dbuf)),
1282 size_t size = sizeof(struct GNUNET_TUN_IPv4Header)
1283 + sizeof(struct GNUNET_TUN_TcpHeader)
1284 + sizeof(struct GNUNET_MessageHeader)
1285 + sizeof(struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1287 char buf[size] GNUNET_ALIGN;
1288 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1289 struct GNUNET_TUN_Layer2PacketHeader *tun =
1290 (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1291 struct GNUNET_TUN_IPv4Header *ipv4 =
1292 (struct GNUNET_TUN_IPv4Header *) &tun[1];
1293 struct GNUNET_TUN_TcpHeader *tcp =
1294 (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1295 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1296 msg->size = htons (size);
1297 tun->flags = htons (0);
1298 tun->proto = htons (ETH_P_IPV4);
1299 GNUNET_TUN_initialize_ipv4_header (ipv4,
1301 sizeof(struct GNUNET_TUN_TcpHeader)
1303 &ts->destination_ip.v4,
1305 *tcp = data->tcp_header;
1306 tcp->source_port = htons (ts->destination_port);
1307 tcp->destination_port = htons (ts->source_port);
1308 GNUNET_TUN_calculate_tcp4_checksum (ipv4, tcp, &data[1], mlen);
1309 GNUNET_memcpy (&tcp[1], &data[1], mlen);
1310 (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1316 size_t size = sizeof(struct GNUNET_TUN_IPv6Header)
1317 + sizeof(struct GNUNET_TUN_TcpHeader)
1318 + sizeof(struct GNUNET_MessageHeader)
1319 + sizeof(struct GNUNET_TUN_Layer2PacketHeader) + mlen;
1321 char buf[size] GNUNET_ALIGN;
1322 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1323 struct GNUNET_TUN_Layer2PacketHeader *tun =
1324 (struct GNUNET_TUN_Layer2PacketHeader *) &msg[1];
1325 struct GNUNET_TUN_IPv6Header *ipv6 =
1326 (struct GNUNET_TUN_IPv6Header *) &tun[1];
1327 struct GNUNET_TUN_TcpHeader *tcp =
1328 (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1329 msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1330 msg->size = htons (size);
1331 tun->flags = htons (0);
1332 tun->proto = htons (ETH_P_IPV6);
1333 GNUNET_TUN_initialize_ipv6_header (ipv6,
1335 sizeof(struct GNUNET_TUN_TcpHeader)
1337 &ts->destination_ip.v6,
1339 *tcp = data->tcp_header;
1340 tcp->source_port = htons (ts->destination_port);
1341 tcp->destination_port = htons (ts->source_port);
1342 GNUNET_TUN_calculate_tcp6_checksum (ipv6, tcp, &data[1], mlen);
1343 GNUNET_memcpy (&tcp[1], &data[1], mlen);
1344 (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL);
1349 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1350 GNUNET_TIME_absolute_get ().abs_value_us);
1351 GNUNET_CADET_receive_done (ts->channel);
1356 * Create a channel for @a ts to @a target at @a port
1358 * @param ts channel state to create the channel for
1359 * @param target peer to connect to
1360 * @param port destination port
1361 * @return the channel handle
1363 static struct GNUNET_CADET_Channel *
1364 create_channel (struct ChannelState *ts,
1365 const struct GNUNET_PeerIdentity *target,
1366 const struct GNUNET_HashCode *port)
1368 struct GNUNET_MQ_MessageHandler cadet_handlers[] =
1369 { GNUNET_MQ_hd_var_size (udp_back,
1370 GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY,
1371 struct GNUNET_EXIT_UdpReplyMessage,
1373 GNUNET_MQ_hd_var_size (tcp_back,
1374 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN,
1375 struct GNUNET_EXIT_TcpDataMessage,
1377 GNUNET_MQ_hd_var_size (icmp_back,
1378 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN,
1379 struct GNUNET_EXIT_IcmpToVPNMessage,
1381 GNUNET_MQ_handler_end () };
1383 return GNUNET_CADET_channel_create (cadet_handle,
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),
1430 /* these must match the strings used in gnunet-daemon-exit */
1431 GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
1432 strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
1440 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1441 "Creating tunnel to %s for destination %s!\n",
1443 print_channel_destination (&ts->destination));
1444 ts->channel = create_channel (ts, id, &port);
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, int client_af)
1458 struct ChannelState *ts;
1460 GNUNET_STATISTICS_update (stats,
1461 gettext_noop ("# Cadet channels created"),
1464 ts = GNUNET_new (struct ChannelState);
1466 ts->destination = *dt->destination;
1467 ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
1468 ts->destination_port = dt->destination_port;
1469 if (dt->destination->is_service)
1471 struct GNUNET_HashCode cadet_port;
1473 GNUNET_TUN_compute_service_cadet_port (&ts->destination.details
1474 .service_destination
1475 .service_descriptor,
1476 ts->destination_port,
1480 &dt->destination->details.service_destination.target,
1483 if (NULL == ts->channel)
1489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1490 "Creating channel to peer %s offering service %s on port %u\n",
1492 &dt->destination->details.service_destination.target),
1493 GNUNET_h2s (&ts->destination.details.service_destination
1494 .service_descriptor),
1495 (unsigned int) ts->destination_port);
1501 switch (dt->destination->details.exit_destination.af)
1504 char address[GNUNET_TUN_IPV4_REGEXLEN];
1506 GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination
1508 dt->destination_port,
1510 GNUNET_asprintf (&policy,
1512 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1518 char address[GNUNET_TUN_IPV6_REGEXLEN];
1520 GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination
1522 dt->destination_port,
1524 GNUNET_asprintf (&policy,
1526 GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1537 "Requesting connect by string: %s\n",
1539 ts->search = GNUNET_REGEX_search (cfg, policy, &handle_regex_result, ts);
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;
1602 if (payload_length < sizeof(struct GNUNET_TUN_UdpHeader))
1608 tcp = NULL; /* make compiler happy */
1609 icmp = NULL; /* make compiler happy */
1611 if (udp->len < sizeof(struct GNUNET_TUN_UdpHeader))
1613 GNUNET_break_op (0);
1616 source_port = ntohs (udp->source_port);
1617 destination_port = ntohs (udp->destination_port);
1618 get_channel_key_from_ips (af,
1629 if (payload_length < sizeof(struct GNUNET_TUN_TcpHeader))
1635 udp = NULL; /* make compiler happy */
1636 icmp = NULL; /* make compiler happy */
1638 if (tcp->off * 4 < sizeof(struct GNUNET_TUN_TcpHeader))
1640 GNUNET_break_op (0);
1643 source_port = ntohs (tcp->source_port);
1644 destination_port = ntohs (tcp->destination_port);
1645 get_channel_key_from_ips (af,
1656 case IPPROTO_ICMPV6: {
1657 if ((AF_INET == af) ^ (protocol == IPPROTO_ICMP))
1662 if (payload_length < sizeof(struct GNUNET_TUN_IcmpHeader))
1668 tcp = NULL; /* make compiler happy */
1669 udp = NULL; /* make compiler happy */
1672 destination_port = 0;
1673 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);
1699 alen = sizeof(struct in6_addr);
1707 char sbuf[INET6_ADDRSTRLEN];
1708 char dbuf[INET6_ADDRSTRLEN];
1709 char xbuf[INET6_ADDRSTRLEN];
1712 GNUNET_ERROR_TYPE_DEBUG,
1713 "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1714 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1715 inet_ntop (af, source_ip, sbuf, sizeof(sbuf)),
1717 inet_ntop (af, destination_ip, dbuf, sizeof(dbuf)),
1719 inet_ntop (destination->details.exit_destination.af,
1720 &destination->details.exit_destination.ip,
1725 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1726 if (dt->destination_port == destination_port)
1732 char sbuf[INET6_ADDRSTRLEN];
1733 char dbuf[INET6_ADDRSTRLEN];
1736 GNUNET_ERROR_TYPE_DEBUG,
1737 "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1738 (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1739 inet_ntop (af, source_ip, sbuf, sizeof(sbuf)),
1741 inet_ntop (af, destination_ip, dbuf, sizeof(dbuf)),
1744 &destination->details.service_destination.service_descriptor),
1745 GNUNET_i2s (&destination->details.service_destination.target));
1747 for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1748 if (dt->destination_port == destination_port)
1753 dt = GNUNET_new (struct DestinationChannel);
1754 dt->destination = destination;
1755 GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1756 destination->dt_tail,
1758 dt->destination_port = destination_port;
1761 /* see if we have an existing channel for this destination */
1762 ts = GNUNET_CONTAINER_multihashmap_get (channel_map, &key);
1765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1766 "Creating new channel for key %s\n",
1768 /* need to either use the existing channel from the destination (if still
1769 available) or create a fresh one */
1770 ts = create_channel_to_destination (dt, af);
1773 /* now bind existing "unbound" channel to our IP/port tuple */
1774 ts->protocol = protocol;
1778 ts->source_ip.v4 = *(const struct in_addr *) source_ip;
1779 ts->destination_ip.v4 = *(const struct in_addr *) destination_ip;
1783 ts->source_ip.v6 = *(const struct in6_addr *) source_ip;
1784 ts->destination_ip.v6 = *(const struct in6_addr *) destination_ip;
1786 ts->source_port = source_port;
1787 ts->destination_port = destination_port;
1789 GNUNET_CONTAINER_heap_insert (channel_heap,
1791 GNUNET_TIME_absolute_get ().abs_value_us);
1792 GNUNET_assert (GNUNET_YES ==
1793 GNUNET_CONTAINER_multihashmap_put (
1797 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1798 GNUNET_STATISTICS_update (stats,
1799 gettext_noop ("# Active channels"),
1802 while (GNUNET_CONTAINER_multihashmap_size (channel_map) >
1803 max_channel_mappings)
1804 expire_channel (ts);
1808 GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1809 GNUNET_TIME_absolute_get ()
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) ? "EXIT search failed"
1818 : "EXIT search active");
1819 GNUNET_STATISTICS_update (stats,
1821 "# 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) + payload_length
1836 - sizeof(struct GNUNET_TUN_UdpHeader);
1837 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1842 env = GNUNET_MQ_msg_extra (usm,
1844 - sizeof(struct GNUNET_TUN_UdpHeader),
1845 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1846 /* if the source port is below 32000, we assume it has a special
1847 meaning; if not, we pick a random port (this is a heuristic) */
1849 (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1850 usm->destination_port = udp->destination_port;
1851 GNUNET_memcpy (&usm[1],
1853 payload_length - sizeof(struct GNUNET_TUN_UdpHeader));
1857 struct GNUNET_EXIT_UdpInternetMessage *uim;
1858 struct in_addr *ip4dst;
1859 struct in6_addr *ip6dst;
1862 mlen = sizeof(struct GNUNET_EXIT_UdpInternetMessage) + alen
1863 + payload_length - sizeof(struct GNUNET_TUN_UdpHeader);
1864 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1869 env = GNUNET_MQ_msg_extra (uim,
1870 payload_length + alen
1871 - sizeof(struct GNUNET_TUN_UdpHeader),
1872 GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1873 uim->af = htonl (destination->details.exit_destination.af);
1875 (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1876 uim->destination_port = udp->destination_port;
1877 switch (destination->details.exit_destination.af)
1880 ip4dst = (struct in_addr *) &uim[1];
1881 *ip4dst = destination->details.exit_destination.ip.v4;
1882 payload = &ip4dst[1];
1886 ip6dst = (struct in6_addr *) &uim[1];
1887 *ip6dst = destination->details.exit_destination.ip.v6;
1888 payload = &ip6dst[1];
1894 GNUNET_memcpy (payload,
1896 payload_length - sizeof(struct GNUNET_TUN_UdpHeader));
1901 if (GNUNET_NO == ts->is_established)
1903 if (destination->is_service)
1905 struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1907 mlen = sizeof(struct GNUNET_EXIT_TcpServiceStartMessage)
1908 + payload_length - sizeof(struct GNUNET_TUN_TcpHeader);
1909 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1915 GNUNET_MQ_msg_extra (tsm,
1917 - sizeof(struct GNUNET_TUN_TcpHeader),
1918 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1919 tsm->reserved = htonl (0);
1920 tsm->tcp_header = *tcp;
1921 GNUNET_memcpy (&tsm[1],
1923 payload_length - sizeof(struct GNUNET_TUN_TcpHeader));
1927 struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1928 struct in_addr *ip4dst;
1929 struct in6_addr *ip6dst;
1932 mlen = sizeof(struct GNUNET_EXIT_TcpInternetStartMessage) + alen
1933 + payload_length - sizeof(struct GNUNET_TUN_TcpHeader);
1934 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1940 GNUNET_MQ_msg_extra (tim,
1941 payload_length + alen
1942 - sizeof(struct GNUNET_TUN_TcpHeader),
1943 GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1944 tim->af = htonl (destination->details.exit_destination.af);
1945 tim->tcp_header = *tcp;
1946 switch (destination->details.exit_destination.af)
1949 ip4dst = (struct in_addr *) &tim[1];
1950 *ip4dst = destination->details.exit_destination.ip.v4;
1951 payload = &ip4dst[1];
1955 ip6dst = (struct in6_addr *) &tim[1];
1956 *ip6dst = destination->details.exit_destination.ip.v6;
1957 payload = &ip6dst[1];
1963 GNUNET_memcpy (payload,
1965 payload_length - sizeof(struct GNUNET_TUN_TcpHeader));
1970 struct GNUNET_EXIT_TcpDataMessage *tdm;
1972 mlen = sizeof(struct GNUNET_EXIT_TcpDataMessage) + payload_length
1973 - sizeof(struct GNUNET_TUN_TcpHeader);
1974 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
1979 env = GNUNET_MQ_msg_extra (tdm,
1981 - sizeof(struct GNUNET_TUN_TcpHeader),
1982 GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1983 tdm->reserved = htonl (0);
1984 tdm->tcp_header = *tcp;
1985 GNUNET_memcpy (&tdm[1],
1987 payload_length - sizeof(struct GNUNET_TUN_TcpHeader));
1992 case IPPROTO_ICMPV6:
1993 if (destination->is_service)
1995 struct GNUNET_EXIT_IcmpServiceMessage *ism;
1997 /* ICMP protocol translation will be done by the receiver (as we don't know
1998 the target AF); however, we still need to possibly discard the payload
1999 depending on the ICMP type */
2005 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2006 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2009 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2010 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2011 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2012 /* throw away ICMP payload, won't be useful for the other side anyway */
2013 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2017 GNUNET_STATISTICS_update (stats,
2019 "# ICMPv4 packets dropped (not allowed)"),
2024 /* end of AF_INET */
2030 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2031 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2032 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2033 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2034 /* throw away ICMP payload, won't be useful for the other side anyway */
2035 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2038 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2039 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2043 GNUNET_STATISTICS_update (stats,
2045 "# ICMPv6 packets dropped (not allowed)"),
2050 /* end of AF_INET6 */
2058 /* update length calculations, as payload_length may have changed */
2059 mlen = sizeof(struct GNUNET_EXIT_IcmpServiceMessage) + alen
2060 + payload_length - sizeof(struct GNUNET_TUN_IcmpHeader);
2061 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2067 env = GNUNET_MQ_msg_extra (ism,
2069 - sizeof(struct GNUNET_TUN_IcmpHeader),
2070 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
2071 ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
2072 ism->icmp_header = *icmp;
2073 GNUNET_memcpy (&ism[1],
2075 payload_length - sizeof(struct GNUNET_TUN_IcmpHeader));
2079 struct GNUNET_EXIT_IcmpInternetMessage *iim;
2080 struct in_addr *ip4dst;
2081 struct in6_addr *ip6dst;
2085 new_type = icmp->type;
2086 /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2087 and throw away ICMP payload depending on ICMP message type */
2093 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2094 if (destination->details.exit_destination.af == AF_INET6)
2095 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2098 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2099 if (destination->details.exit_destination.af == AF_INET6)
2100 new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2103 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2104 if (destination->details.exit_destination.af == AF_INET6)
2105 new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2106 /* throw away IP-payload, exit will have to make it up anyway */
2107 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2110 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2111 if (destination->details.exit_destination.af == AF_INET6)
2112 new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2113 /* throw away IP-payload, exit will have to make it up anyway */
2114 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2117 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2118 if (destination->details.exit_destination.af == AF_INET6)
2120 GNUNET_STATISTICS_update (
2122 gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2127 /* throw away IP-payload, exit will have to make it up anyway */
2128 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2132 GNUNET_STATISTICS_update (
2134 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2139 /* end of AF_INET */
2145 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2146 if (destination->details.exit_destination.af == AF_INET)
2147 new_type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2148 /* throw away IP-payload, exit will have to make it up anyway */
2149 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2152 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2153 if (destination->details.exit_destination.af == AF_INET)
2154 new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2155 /* throw away IP-payload, exit will have to make it up anyway */
2156 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2159 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2160 if (destination->details.exit_destination.af == AF_INET)
2162 GNUNET_STATISTICS_update (
2164 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2169 /* throw away IP-payload, exit will have to make it up anyway */
2170 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2173 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2174 if (destination->details.exit_destination.af == AF_INET)
2176 GNUNET_STATISTICS_update (
2178 gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2183 /* throw away IP-payload, exit will have to make it up anyway */
2184 payload_length = sizeof(struct GNUNET_TUN_IcmpHeader);
2187 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2188 if (destination->details.exit_destination.af == AF_INET)
2189 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2192 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2193 if (destination->details.exit_destination.af == AF_INET)
2194 new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2198 GNUNET_STATISTICS_update (
2200 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2205 /* end of AF_INET6 */
2212 /* update length calculations, as payload_length may have changed */
2213 mlen = sizeof(struct GNUNET_EXIT_IcmpInternetMessage) + alen
2214 + payload_length - sizeof(struct GNUNET_TUN_IcmpHeader);
2215 if (mlen >= GNUNET_MAX_MESSAGE_SIZE)
2220 env = GNUNET_MQ_msg_extra (iim,
2221 alen + payload_length
2222 - sizeof(struct GNUNET_TUN_IcmpHeader),
2223 GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
2224 iim->icmp_header = *icmp;
2225 iim->icmp_header.type = new_type;
2226 iim->af = htonl (destination->details.exit_destination.af);
2227 switch (destination->details.exit_destination.af)
2230 ip4dst = (struct in_addr *) &iim[1];
2231 *ip4dst = destination->details.exit_destination.ip.v4;
2232 payload = &ip4dst[1];
2236 ip6dst = (struct in6_addr *) &iim[1];
2237 *ip6dst = destination->details.exit_destination.ip.v6;
2238 payload = &ip6dst[1];
2244 GNUNET_memcpy (payload,
2246 payload_length - sizeof(struct GNUNET_TUN_IcmpHeader));
2251 /* not supported above, how can we get here !? */
2255 ts->is_established = GNUNET_YES;
2256 send_to_channel (ts, env);
2261 * Receive packets from the helper-process (someone send to the local
2262 * virtual channel interface). Find the destination mapping, and if it
2263 * exists, identify the correct CADET channel (or possibly create it)
2264 * and forward the packet.
2266 * @param cls closure, NULL
2267 * @param message message we got from the client (VPN channel interface)
2268 * @return #GNUNET_OK on success,
2269 * #GNUNET_NO to stop further processing (no error)
2270 * #GNUNET_SYSERR to stop further processing with error
2273 message_token (void *cls, const struct GNUNET_MessageHeader *message)
2275 const struct GNUNET_TUN_Layer2PacketHeader *tun;
2277 struct GNUNET_HashCode key;
2278 struct DestinationEntry *de;
2280 GNUNET_STATISTICS_update (stats,
2282 "# Packets received from TUN interface"),
2285 mlen = ntohs (message->size);
2286 if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2287 (mlen < sizeof(struct GNUNET_MessageHeader)
2288 + sizeof(struct GNUNET_TUN_Layer2PacketHeader)))
2293 tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2294 mlen -= (sizeof(struct GNUNET_MessageHeader)
2295 + sizeof(struct GNUNET_TUN_Layer2PacketHeader));
2296 switch (ntohs (tun->proto))
2299 const struct GNUNET_TUN_IPv6Header *pkt6;
2301 if (mlen < sizeof(struct GNUNET_TUN_IPv6Header))
2307 pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2308 get_destination_key_from_ip (AF_INET6, &pkt6->destination_address, &key);
2309 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2312 char buf[INET6_ADDRSTRLEN];
2315 GNUNET_ERROR_TYPE_INFO,
2316 _ ("Packet received for unmapped destination `%s' (dropping it)\n"),
2317 inet_ntop (AF_INET6, &pkt6->destination_address, buf, sizeof(buf)));
2323 &pkt6->source_address,
2324 &pkt6->destination_address,
2326 mlen - sizeof(struct GNUNET_TUN_IPv6Header));
2331 struct GNUNET_TUN_IPv4Header *pkt4;
2333 if (mlen < sizeof(struct GNUNET_TUN_IPv4Header))
2339 pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2340 get_destination_key_from_ip (AF_INET, &pkt4->destination_address, &key);
2341 de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2344 char buf[INET_ADDRSTRLEN];
2347 GNUNET_ERROR_TYPE_INFO,
2348 _ ("Packet received for unmapped destination `%s' (dropping it)\n"),
2349 inet_ntop (AF_INET, &pkt4->destination_address, buf, sizeof(buf)));
2352 if (pkt4->header_length * 4 != sizeof(struct GNUNET_TUN_IPv4Header))
2354 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2355 _ ("Received IPv4 packet with options (dropping it)\n"));
2361 &pkt4->source_address,
2362 &pkt4->destination_address,
2364 mlen - sizeof(struct GNUNET_TUN_IPv4Header));
2370 GNUNET_ERROR_TYPE_INFO,
2371 _ ("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2372 (unsigned int) ntohs (tun->proto));
2380 * Allocate an IPv4 address from the range of the channel
2381 * for a new redirection.
2383 * @param v4 where to store the address
2384 * @return #GNUNET_OK on success,
2385 * #GNUNET_SYSERR on error
2388 allocate_v4_address (struct in_addr *v4)
2390 const char *ipv4addr = vpn_argv[4];
2391 const char *ipv4mask = vpn_argv[5];
2392 struct in_addr addr;
2393 struct in_addr mask;
2395 struct GNUNET_HashCode key;
2398 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2399 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2400 /* Given 192.168.0.1/255.255.0.0, we want a mask
2401 of '192.168.255.255', thus: */
2402 mask.s_addr = addr.s_addr | ~mask.s_addr;
2409 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2411 "Failed to find unallocated IPv4 address in VPN's range\n"));
2412 return GNUNET_SYSERR;
2414 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2416 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
2417 v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2418 get_destination_key_from_ip (AF_INET, v4, &key);
2420 while ((GNUNET_YES ==
2421 GNUNET_CONTAINER_multihashmap_contains (destination_map, &key)) ||
2422 (v4->s_addr == addr.s_addr) || (v4->s_addr == mask.s_addr));
2428 * Allocate an IPv6 address from the range of the channel
2429 * for a new redirection.
2431 * @param v6 where to store the address
2432 * @return #GNUNET_OK on success,
2433 * #GNUNET_SYSERR on error
2436 allocate_v6_address (struct in6_addr *v6)
2438 const char *ipv6addr = vpn_argv[2];
2439 struct in6_addr addr;
2440 struct in6_addr mask;
2441 struct in6_addr rnd;
2443 struct GNUNET_HashCode key;
2446 GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2447 GNUNET_assert (ipv6prefix < 128);
2448 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2451 for (i = 127; i >= ipv6prefix; i--)
2452 mask.s6_addr[i / 8] |= (1 << (i % 8));
2454 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2461 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2463 "Failed to find unallocated IPv6 address in VPN's range\n"));
2464 return GNUNET_SYSERR;
2466 for (i = 0; i < 16; i++)
2469 (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2471 v6->s6_addr[i] = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2473 get_destination_key_from_ip (AF_INET6, v6, &key);
2475 while ((GNUNET_YES ==
2476 GNUNET_CONTAINER_multihashmap_contains (destination_map, &key)) ||
2477 (0 == GNUNET_memcmp (v6, &addr)) ||
2478 (0 == GNUNET_memcmp (v6, &mask)));
2484 * Free resources occupied by a destination entry.
2486 * @param de entry to free
2489 free_destination_entry (struct DestinationEntry *de)
2491 struct DestinationChannel *dt;
2493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2494 "Cleaning up destination entry `%s'\n",
2495 print_channel_destination (de));
2496 GNUNET_STATISTICS_update (stats,
2497 gettext_noop ("# Active destinations"),
2500 while (NULL != (dt = de->dt_head))
2502 GNUNET_CONTAINER_DLL_remove (de->dt_head, de->dt_tail, dt);
2505 if (NULL != de->heap_node)
2507 GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2508 de->heap_node = NULL;
2511 GNUNET_CONTAINER_multihashmap_remove (destination_map, &de->key, de));
2518 * We have too many active destinations. Clean up the oldest destination.
2520 * @param except destination that must NOT be cleaned up, even if it is the oldest
2523 expire_destination (struct DestinationEntry *except)
2525 struct DestinationEntry *de;
2527 de = GNUNET_CONTAINER_heap_peek (destination_heap);
2528 GNUNET_assert (NULL != de);
2530 return; /* can't do this */
2531 free_destination_entry (de);
2536 * Allocate an IP address for the response.
2538 * @param result_af desired address family; set to the actual
2539 * address family; can initially be AF_UNSPEC if there
2540 * is no preference; will be set to AF_UNSPEC if the
2542 * @param addr set to either v4 or v6 depending on which
2543 * storage location was used; set to NULL if allocation failed
2544 * @param v4 storage space for an IPv4 address
2545 * @param v6 storage space for an IPv6 address
2546 * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2547 * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2550 allocate_response_ip (int *result_af,
2553 struct in6_addr *v6)
2559 if (GNUNET_OK != allocate_v4_address (v4))
2560 *result_af = AF_UNSPEC;
2566 if (GNUNET_OK != allocate_v6_address (v6))
2567 *result_af = AF_UNSPEC;
2573 if (GNUNET_OK == allocate_v4_address (v4))
2576 *result_af = AF_INET;
2578 else if (GNUNET_OK == allocate_v6_address (v6))
2581 *result_af = AF_INET6;
2587 return GNUNET_SYSERR;
2594 * A client asks us to setup a redirection via some exit node to a
2595 * particular IP. Check if @a msg is well-formed.
2598 * @param cls client requesting client
2599 * @param msg redirection request
2600 * @return #GNUNET_OK if @a msg is well-formed
2603 check_client_redirect_to_ip (void *cls,
2604 const struct RedirectToIpRequestMessage *msg)
2609 alen = ntohs (msg->header.size) - sizeof(struct RedirectToIpRequestMessage);
2610 addr_af = (int) htonl (msg->addr_af);
2614 if (alen != sizeof(struct in_addr))
2617 return GNUNET_SYSERR;
2622 if (alen != sizeof(struct in6_addr))
2625 return GNUNET_SYSERR;
2631 return GNUNET_SYSERR;
2638 * A client asks us to setup a redirection via some exit node to a
2639 * particular IP. Setup the redirection and give the client the
2642 * @param cls client requesting client
2643 * @param msg redirection request
2646 handle_client_redirect_to_ip (void *cls,
2647 const struct RedirectToIpRequestMessage *msg)
2649 struct GNUNET_SERVICE_Client *client = cls;
2656 struct DestinationEntry *de;
2657 struct GNUNET_HashCode key;
2659 alen = ntohs (msg->header.size) - sizeof(struct RedirectToIpRequestMessage);
2660 addr_af = (int) htonl (msg->addr_af);
2661 /* allocate response IP */
2662 result_af = (int) htonl (msg->result_af);
2663 if (GNUNET_OK != allocate_response_ip (&result_af, &addr, &v4, &v6))
2665 GNUNET_SERVICE_client_drop (client);
2668 /* send reply with our IP address */
2669 send_client_reply (client, msg->request_id, result_af, addr);
2670 if (result_af == AF_UNSPEC)
2672 /* failure, we're done */
2673 GNUNET_SERVICE_client_continue (client);
2678 char sbuf[INET6_ADDRSTRLEN];
2679 char dbuf[INET6_ADDRSTRLEN];
2681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2682 "Allocated address %s for redirection via exit to %s\n",
2683 inet_ntop (result_af, addr, sbuf, sizeof(sbuf)),
2684 inet_ntop (addr_af, &msg[1], dbuf, sizeof(dbuf)));
2687 /* setup destination record */
2688 de = GNUNET_new (struct DestinationEntry);
2689 de->is_service = GNUNET_NO;
2690 de->details.exit_destination.af = addr_af;
2691 GNUNET_memcpy (&de->details.exit_destination.ip, &msg[1], alen);
2692 get_destination_key_from_ip (result_af, addr, &key);
2694 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
2698 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2699 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2701 GNUNET_TIME_absolute_ntoh (
2702 msg->expiration_time)
2704 GNUNET_STATISTICS_update (stats,
2705 gettext_noop ("# Active destinations"),
2708 while (GNUNET_CONTAINER_multihashmap_size (destination_map) >
2709 max_destination_mappings)
2710 expire_destination (de);
2711 GNUNET_SERVICE_client_continue (client);
2716 * A client asks us to setup a redirection to a particular peer
2717 * offering a service. Setup the redirection and give the client the
2720 * @param cls requesting client
2721 * @param msg redirection request
2724 handle_client_redirect_to_service (
2726 const struct RedirectToServiceRequestMessage *msg)
2728 struct GNUNET_SERVICE_Client *client = cls;
2733 struct DestinationEntry *de;
2734 struct GNUNET_HashCode key;
2735 struct DestinationChannel *dt;
2737 /* allocate response IP */
2738 result_af = (int) htonl (msg->result_af);
2739 if (GNUNET_OK != allocate_response_ip (&result_af, &addr, &v4, &v6))
2742 GNUNET_SERVICE_client_drop (client);
2745 send_client_reply (client, msg->request_id, result_af, addr);
2746 if (result_af == AF_UNSPEC)
2748 /* failure, we're done */
2749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2750 _ ("Failed to allocate IP address for new destination\n"));
2751 GNUNET_SERVICE_client_continue (client);
2756 char sbuf[INET6_ADDRSTRLEN];
2758 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2759 "Allocated address %s for redirection to service %s on peer %s\n",
2760 inet_ntop (result_af, addr, sbuf, sizeof(sbuf)),
2761 GNUNET_h2s (&msg->service_descriptor),
2762 GNUNET_i2s (&msg->target));
2765 /* setup destination record */
2766 de = GNUNET_new (struct DestinationEntry);
2767 de->is_service = GNUNET_YES;
2768 de->details.service_destination.target = msg->target;
2769 de->details.service_destination.service_descriptor = msg->service_descriptor;
2770 get_destination_key_from_ip (result_af, addr, &key);
2772 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
2776 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2777 de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2779 GNUNET_TIME_absolute_ntoh (
2780 msg->expiration_time)
2782 while (GNUNET_CONTAINER_multihashmap_size (destination_map) >
2783 max_destination_mappings)
2784 expire_destination (de);
2786 dt = GNUNET_new (struct DestinationChannel);
2787 dt->destination = de;
2788 GNUNET_CONTAINER_DLL_insert (de->dt_head, de->dt_tail, dt);
2790 GNUNET_SERVICE_client_continue (client);
2795 * Free memory occupied by an entry in the destination map.
2799 * @param value a `struct DestinationEntry *`
2800 * @return #GNUNET_OK (continue to iterate)
2803 cleanup_destination (void *cls, const struct GNUNET_HashCode *key, void *value)
2805 struct DestinationEntry *de = value;
2807 free_destination_entry (de);
2813 * Free memory occupied by an entry in the channel map.
2817 * @param value a `struct ChannelState *`
2818 * @return #GNUNET_OK (continue to iterate)
2821 cleanup_channel (void *cls, const struct GNUNET_HashCode *key, void *value)
2823 struct ChannelState *ts = value;
2825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2826 "Tearing down channel to `%s' during cleanup\n",
2827 print_channel_destination (&ts->destination));
2828 free_channel_state (ts);
2834 * Function scheduled as very last function, cleans up after us
2843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "VPN is shutting down\n");
2844 if (NULL != destination_map)
2846 GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2847 &cleanup_destination,
2849 GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2850 destination_map = NULL;
2852 if (NULL != destination_heap)
2854 GNUNET_CONTAINER_heap_destroy (destination_heap);
2855 destination_heap = NULL;
2857 if (NULL != channel_map)
2859 GNUNET_CONTAINER_multihashmap_iterate (channel_map, &cleanup_channel, NULL);
2860 GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2863 if (NULL != channel_heap)
2865 GNUNET_CONTAINER_heap_destroy (channel_heap);
2866 channel_heap = NULL;
2868 if (NULL != cadet_handle)
2870 GNUNET_CADET_disconnect (cadet_handle);
2871 cadet_handle = NULL;
2873 if (NULL != helper_handle)
2875 GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2876 GNUNET_HELPER_wait (helper_handle);
2877 helper_handle = NULL;
2881 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2884 for (i = 0; i < 5; i++)
2885 GNUNET_free_non_null (vpn_argv[i]);
2890 * Callback called when a client connects to the service.
2892 * @param cls closure for the service
2893 * @param c the new client that connected to the service
2894 * @param mq the message queue used to send messages to the client
2898 client_connect_cb (void *cls,
2899 struct GNUNET_SERVICE_Client *c,
2900 struct GNUNET_MQ_Handle *mq)
2907 * Callback called when a client disconnected from the service
2909 * @param cls closure for the service
2910 * @param c the client that disconnected
2911 * @param internal_cls should be equal to @a c
2914 client_disconnect_cb (void *cls,
2915 struct GNUNET_SERVICE_Client *c,
2918 GNUNET_assert (c == internal_cls);
2923 * Main function that will be run by the scheduler.
2925 * @param cls closure
2926 * @param cfg_ configuration
2927 * @param service the initialized service
2931 const struct GNUNET_CONFIGURATION_Handle *cfg_,
2932 struct GNUNET_SERVICE_Handle *service)
2944 binary = GNUNET_OS_get_suid_binary_path (cfg, "gnunet-helper-vpn");
2947 GNUNET_OS_check_helper_binary (
2950 "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) // ipv4 only please!
2952 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2953 "`%s' is not SUID or the path is invalid, refusing to run.\n",
2955 GNUNET_free (binary);
2957 /* we won't "really" exit here, as the 'service' is still running;
2958 however, as no handlers are registered, the service won't do
2962 stats = GNUNET_STATISTICS_create ("vpn", cfg);
2964 GNUNET_CONFIGURATION_get_value_number (cfg,
2967 &max_destination_mappings))
2968 max_destination_mappings = 200;
2970 GNUNET_CONFIGURATION_get_value_number (cfg,
2973 &max_channel_mappings))
2974 max_channel_mappings = 200;
2977 GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2,
2980 GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2982 GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2983 channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2986 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2987 if (GNUNET_SYSERR ==
2988 GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2990 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2991 GNUNET_free (binary);
2992 GNUNET_SCHEDULER_shutdown ();
2995 vpn_argv[1] = ifname;
2997 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2999 if (((GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
3003 (1 != inet_pton (AF_INET6, ipv6addr, &v6))))
3005 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3008 _ ("Must specify valid IPv6 address"));
3009 GNUNET_free (binary);
3010 GNUNET_SCHEDULER_shutdown ();
3011 GNUNET_free_non_null (ipv6addr);
3014 vpn_argv[2] = ipv6addr;
3015 ipv6prefix_s = NULL;
3016 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
3021 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3022 GNUNET_SCHEDULER_shutdown ();
3023 GNUNET_free_non_null (ipv6prefix_s);
3026 vpn_argv[3] = ipv6prefix_s;
3027 if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
3031 (ipv6prefix >= 127))
3033 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3036 _ ("Must specify valid IPv6 mask"));
3037 GNUNET_free (binary);
3038 GNUNET_SCHEDULER_shutdown ();
3044 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3046 "IPv6 support disabled as this system does not support IPv6\n"));
3047 vpn_argv[2] = GNUNET_strdup ("-");
3048 vpn_argv[3] = GNUNET_strdup ("-");
3050 if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3053 if (((GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
3057 (1 != inet_pton (AF_INET, ipv4addr, &v4))))
3059 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3062 _ ("Must specify valid IPv4 address"));
3063 GNUNET_free (binary);
3064 GNUNET_SCHEDULER_shutdown ();
3065 GNUNET_free_non_null (ipv4addr);
3068 vpn_argv[4] = ipv4addr;
3070 if (((GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg,
3074 (1 != inet_pton (AF_INET, ipv4mask, &v4))))
3076 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3079 _ ("Must specify valid IPv4 mask"));
3080 GNUNET_free (binary);
3081 GNUNET_SCHEDULER_shutdown ();
3082 GNUNET_free_non_null (ipv4mask);
3085 vpn_argv[5] = ipv4mask;
3089 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3091 "IPv4 support disabled as this system does not support IPv4\n"));
3092 vpn_argv[4] = GNUNET_strdup ("-");
3093 vpn_argv[5] = GNUNET_strdup ("-");
3097 cadet_handle = GNUNET_CADET_connect (cfg_);
3098 // FIXME never opens ports???
3099 helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3105 GNUNET_free (binary);
3106 GNUNET_SCHEDULER_add_shutdown (&cleanup, NULL);
3111 * Define "main" method using service macro.
3113 GNUNET_SERVICE_MAIN (
3115 GNUNET_SERVICE_OPTION_NONE,
3118 &client_disconnect_cb,
3120 GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3121 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP,
3122 struct RedirectToIpRequestMessage,
3124 GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3125 GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3126 struct RedirectToServiceRequestMessage,
3128 GNUNET_MQ_handler_end ());
3131 /* end of gnunet-service-vpn.c */