2 This file is part of GNUnet.
3 (C) 2010, 2012 Christian Grothoff
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file exit/gnunet-daemon-exit.c
23 * @brief tool to allow IP traffic exit from the GNUnet mesh to the Internet
24 * @author Philipp Toelke
25 * @author Christian Grothoff
31 * - which code should advertise services? the service model is right
32 * now a bit odd, especially as this code DOES the exit and knows
33 * the DNS "name", but OTOH this is clearly NOT the place to advertise
34 * the service's existence; maybe the daemon should turn into a
35 * service with an API to add local-exit services dynamically?
38 #include "gnunet_util_lib.h"
39 #include "gnunet_protocols.h"
40 #include "gnunet_applications.h"
41 #include "gnunet_mesh_service.h"
42 #include "gnunet_statistics_service.h"
43 #include "gnunet_constants.h"
44 #include "gnunet_tun_lib.h"
48 * Information about an address.
53 * AF_INET or AF_INET6.
58 * Remote address information.
63 * Address, if af is AF_INET.
68 * Address, if af is AF_INET6.
74 * IPPROTO_TCP or IPPROTO_UDP;
79 * Remote port, in host byte order!
86 * This struct is saved into the services-hashmap to represent
87 * a service this peer is specifically offering an exit for
88 * (for a specific domain name).
94 * Remote address to use for the service.
96 struct SocketAddress address;
99 * DNS name of the service.
104 * Port I am listening on within GNUnet for this service, in host
105 * byte order. (as we may redirect ports).
112 * Information we use to track a connection (the classical 6-tuple of
113 * IP-version, protocol, source-IP, destination-IP, source-port and
116 struct RedirectInformation
120 * Address information for the other party (equivalent of the
121 * arguments one would give to "connect").
123 struct SocketAddress remote_address;
126 * Address information we used locally (AF and proto must match
127 * "remote_address"). Equivalent of the arguments one would give to
130 struct SocketAddress local_address;
133 Note 1: additional information might be added here in the
134 future to support protocols that require special handling,
137 Note 2: we might also sometimes not match on all components
138 of the tuple, to support protocols where things do not always
145 * Queue of messages to a tunnel.
147 struct TunnelMessageQueue
150 * This is a doubly-linked list.
152 struct TunnelMessageQueue *next;
155 * This is a doubly-linked list.
157 struct TunnelMessageQueue *prev;
160 * Payload to send via the tunnel.
165 * Number of bytes in 'payload'.
172 * This struct is saved into connections_map to allow finding the
173 * right tunnel given an IP packet from TUN. It is also associated
174 * with the tunnel's closure so we can find it again for the next
175 * message from the tunnel.
180 * Mesh tunnel that is used for this connection.
182 struct GNUNET_MESH_Tunnel *tunnel;
185 * Heap node for this state in the connections_heap.
187 struct GNUNET_CONTAINER_HeapNode *heap_node;
190 * Key this state has in the connections_map.
192 GNUNET_HashCode state_key;
195 * Associated service record, or NULL for no service.
197 struct LocalService *serv;
200 * Head of DLL of messages for this tunnel.
202 struct TunnelMessageQueue *head;
205 * Tail of DLL of messages for this tunnel.
207 struct TunnelMessageQueue *tail;
210 * Active tunnel transmission request (or NULL).
212 struct GNUNET_MESH_TransmitHandle *th;
215 * Primary redirection information for this connection.
217 struct RedirectInformation ri;
223 * The handle to the configuration used throughout the process
225 static const struct GNUNET_CONFIGURATION_Handle *cfg;
228 * The handle to the helper
230 static struct GNUNET_HELPER_Handle *helper_handle;
233 * Arguments to the exit helper.
235 static char *exit_argv[7];
238 * IPv6 address of our TUN interface.
240 static struct in6_addr exit_ipv6addr;
243 * IPv6 prefix (0..127) from configuration file.
245 static unsigned long long ipv6prefix;
248 * IPv4 address of our TUN interface.
250 static struct in_addr exit_ipv4addr;
253 * IPv4 netmask of our TUN interface.
255 static struct in_addr exit_ipv4mask;
261 static struct GNUNET_STATISTICS_Handle *stats;
266 static struct GNUNET_MESH_Handle *mesh_handle;
269 * This hashmaps contains the mapping from peer, service-descriptor,
270 * source-port and destination-port to a struct TunnelState
272 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
275 * Heap so we can quickly find "old" connections.
277 static struct GNUNET_CONTAINER_Heap *connections_heap;
280 * If there are at least this many connections, old ones will be removed
282 static long long unsigned int max_connections;
285 * This hashmaps saves interesting things about the configured UDP services
287 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
290 * This hashmaps saves interesting things about the configured TCP services
292 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
295 * Are we an IPv4-exit?
297 static int ipv4_exit;
300 * Are we an IPv6-exit?
302 static int ipv6_exit;
305 * Do we support IPv4 at all on the TUN interface?
307 static int ipv4_enabled;
310 * Do we support IPv6 at all on the TUN interface?
312 static int ipv6_enabled;
316 * Given IP information about a connection, calculate the respective
317 * hash we would use for the 'connections_map'.
319 * @param hash resulting hash
320 * @param ri information about the connection
323 hash_redirect_info (GNUNET_HashCode *hash,
324 const struct RedirectInformation *ri)
328 memset (hash, 0, sizeof (GNUNET_HashCode));
329 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
330 so we put the IP address in there (and hope for few collisions) */
332 switch (ri->remote_address.af)
335 memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
336 off += sizeof (struct in_addr);
339 memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
340 off += sizeof (struct in_addr);
345 memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
346 off += sizeof (uint16_t);
347 switch (ri->local_address.af)
350 memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr));
351 off += sizeof (struct in_addr);
354 memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr));
355 off += sizeof (struct in_addr);
360 memcpy (off, &ri->local_address.port, sizeof (uint16_t));
361 off += sizeof (uint16_t);
362 memcpy (off, &ri->remote_address.proto, sizeof (uint8_t));
363 off += sizeof (uint8_t);
368 * Get our connection tracking state. Warns if it does not exists,
369 * refreshes the timestamp if it does exist.
371 * @param af address family
372 * @param protocol IPPROTO_UDP or IPPROTO_TCP
373 * @param destination_ip target IP
374 * @param destination_port target port
375 * @param local_ip local IP
376 * @param local_port local port
377 * @param state_key set to hash's state if non-NULL
378 * @return NULL if we have no tracking information for this tuple
380 static struct TunnelState *
381 get_redirect_state (int af,
383 const void *destination_ip,
384 uint16_t destination_port,
385 const void *local_ip,
387 GNUNET_HashCode *state_key)
389 struct RedirectInformation ri;
391 struct TunnelState *state;
393 ri.remote_address.af = af;
395 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
397 ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
398 ri.remote_address.port = destination_port;
399 ri.remote_address.proto = protocol;
400 ri.local_address.af = af;
402 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
404 ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
405 ri.local_address.port = local_port;
406 ri.local_address.proto = protocol;
407 hash_redirect_info (&key, &ri);
408 if (NULL != state_key)
410 state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key);
413 /* Mark this connection as freshly used */
414 if (NULL == state_key)
415 GNUNET_CONTAINER_heap_update_cost (connections_heap,
417 GNUNET_TIME_absolute_get ().abs_value);
423 * Given a service descriptor and a destination port, find the
424 * respective service entry.
426 * @param service_map map of services (TCP or UDP)
427 * @param desc service descriptor
428 * @param dpt destination port
429 * @return NULL if we are not aware of such a service
431 static struct LocalService *
432 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
433 const GNUNET_HashCode *desc,
436 char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
438 memcpy (&key[0], &dpt, sizeof (uint16_t));
439 memcpy (&key[sizeof(uint16_t)], desc, sizeof (GNUNET_HashCode));
440 return GNUNET_CONTAINER_multihashmap_get (service_map,
441 (GNUNET_HashCode *) key);
446 * Free memory associated with a service record.
449 * @param key service descriptor
450 * @param value service record to free
454 free_service_record (void *cls,
455 const GNUNET_HashCode *key,
458 struct LocalService *service = value;
460 GNUNET_free_non_null (service->name);
461 GNUNET_free (service);
467 * Given a service descriptor and a destination port, find the
468 * respective service entry.
470 * @param service_map map of services (TCP or UDP)
471 * @param name name of the service
472 * @param dpt destination port
473 * @param service service information record to store (service->name will be set).
476 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
479 struct LocalService *service)
481 char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
482 GNUNET_HashCode desc;
484 GNUNET_CRYPTO_hash (name, strlen (name) + 1, &desc);
485 service->name = GNUNET_strdup (name);
486 memcpy (&key[0], &dpt, sizeof (uint16_t));
487 memcpy (&key[sizeof(uint16_t)], &desc, sizeof (GNUNET_HashCode));
489 GNUNET_CONTAINER_multihashmap_put (service_map,
490 (GNUNET_HashCode *) key,
492 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
494 free_service_record (NULL, (GNUNET_HashCode *) key, service);
495 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
496 _("Got duplicate service records for `%s:%u'\n"),
504 * MESH is ready to receive a message for the tunnel. Transmit it.
506 * @param cls the 'struct TunnelState'.
507 * @param size number of bytes available in buf
508 * @param buf where to copy the message
509 * @return number of bytes copied to buf
512 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
514 struct TunnelState *s = cls;
515 struct GNUNET_MESH_Tunnel *tunnel = s->tunnel;
516 struct TunnelMessageQueue *tnq;
520 GNUNET_assert (size >= tnq->len);
521 memcpy (buf, tnq->payload, tnq->len);
523 GNUNET_CONTAINER_DLL_remove (s->head,
527 if (NULL != (tnq = s->head))
528 s->th = GNUNET_MESH_notify_transmit_ready (tunnel,
529 GNUNET_NO /* corking */,
531 GNUNET_TIME_UNIT_FOREVER_REL,
534 &send_to_peer_notify_callback,
536 GNUNET_STATISTICS_update (stats,
537 gettext_noop ("# Bytes transmitted via mesh tunnels"),
544 * Send the given packet via the mesh tunnel.
546 * @param mesh_tunnel destination
547 * @param tnq message to queue
550 send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
551 struct TunnelMessageQueue *tnq)
553 struct TunnelState *s;
555 s = GNUNET_MESH_tunnel_get_data (mesh_tunnel);
556 GNUNET_assert (NULL != s);
557 GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, tnq);
559 s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, 0 /* priority */,
560 GNUNET_TIME_UNIT_FOREVER_REL,
562 &send_to_peer_notify_callback,
568 * @brief Handles an ICMP packet received from the helper.
570 * @param icmp A pointer to the Packet
571 * @param pktlen number of bytes in 'icmp'
572 * @param af address family (AFINET or AF_INET6)
573 * @param destination_ip destination IP-address of the IP packet (should
574 * be our local address)
575 * @param source_ip original source IP-address of the IP packet (should
576 * be the original destination address)
579 icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
582 const void *destination_ip,
583 const void *source_ip)
585 struct TunnelState *state;
586 struct TunnelMessageQueue *tnq;
587 struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
588 const struct GNUNET_TUN_IPv4Header *ipv4;
589 const struct GNUNET_TUN_IPv6Header *ipv6;
590 const struct GNUNET_TUN_UdpHeader *udp;
597 char sbuf[INET6_ADDRSTRLEN];
598 char dbuf[INET6_ADDRSTRLEN];
599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
600 "Received ICMP packet going from %s to %s\n",
603 sbuf, sizeof (sbuf)),
606 dbuf, sizeof (dbuf)));
608 if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
615 /* Find out if this is an ICMP packet in response to an existing
616 TCP/UDP packet and if so, figure out ports / protocol of the
617 existing session from the IP data in the ICMP payload */
620 protocol = IPPROTO_ICMP;
626 case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
627 case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
629 case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
630 case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
631 case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
633 sizeof (struct GNUNET_TUN_IcmpHeader) +
634 sizeof (struct GNUNET_TUN_IPv4Header) + 8)
640 ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
641 protocol = ipv4->protocol;
642 /* could be TCP or UDP, but both have the ports in the right
643 place, so that doesn't matter here */
644 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
645 spt = ntohs (udp->spt);
646 dpt = ntohs (udp->dpt);
649 GNUNET_STATISTICS_update (stats,
650 gettext_noop ("# ICMP packets dropped (not allowed)"),
658 case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
659 case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
660 case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
661 case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
663 sizeof (struct GNUNET_TUN_IcmpHeader) +
664 sizeof (struct GNUNET_TUN_IPv6Header) + 8)
670 ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
671 protocol = ipv6->next_header;
672 /* could be TCP or UDP, but both have the ports in the right
673 place, so that doesn't matter here */
674 udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
675 spt = ntohs (udp->spt);
676 dpt = ntohs (udp->dpt);
678 case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
679 case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
682 GNUNET_STATISTICS_update (stats,
683 gettext_noop ("# ICMP packets dropped (not allowed)"),
694 state = get_redirect_state (af, IPPROTO_ICMP,
700 state = get_redirect_state (af, IPPROTO_UDP,
708 state = get_redirect_state (af, IPPROTO_TCP,
716 GNUNET_STATISTICS_update (stats,
717 gettext_noop ("# ICMP packets dropped (not allowed)"),
723 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
724 _("Packet dropped, have no matching connection information\n"));
727 mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader);
728 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);
729 tnq->payload = &tnq[1];
731 i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1];
732 i2v->header.size = htons ((uint16_t) mlen);
733 i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
734 i2v->af = htonl (af);
735 memcpy (&i2v->icmp_header,
738 /* FIXME: should we sanitize the host-specific payload here? On the
739 one hand, quite a bit of what we send is meaningless on the other
740 side (our IPs, ports, etc.); on the other hand, trying to compact
741 the packet would be very messy, and blanking fields out is also
742 hardly productive as they seem to contain nothing remotely
744 send_packet_to_mesh_tunnel (state->tunnel,
750 * @brief Handles an UDP packet received from the helper.
752 * @param udp A pointer to the Packet
753 * @param pktlen number of bytes in 'udp'
754 * @param af address family (AFINET or AF_INET6)
755 * @param destination_ip destination IP-address of the IP packet (should
756 * be our local address)
757 * @param source_ip original source IP-address of the IP packet (should
758 * be the original destination address)
761 udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
764 const void *destination_ip,
765 const void *source_ip)
767 struct TunnelState *state;
768 struct TunnelMessageQueue *tnq;
769 struct GNUNET_EXIT_UdpReplyMessage *urm;
773 char sbuf[INET6_ADDRSTRLEN];
774 char dbuf[INET6_ADDRSTRLEN];
775 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
776 "Received UDP packet going from %s:%u to %s:%u\n",
779 sbuf, sizeof (sbuf)),
780 (unsigned int) ntohs (udp->spt),
783 dbuf, sizeof (dbuf)),
784 (unsigned int) ntohs (udp->dpt));
786 if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
792 if (pktlen != ntohs (udp->len))
798 state = get_redirect_state (af, IPPROTO_UDP,
806 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
807 _("Packet dropped, have no matching connection information\n"));
810 mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader);
811 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);
812 tnq->payload = &tnq[1];
814 urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1];
815 urm->header.size = htons ((uint16_t) mlen);
816 urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
817 urm->source_port = htons (0);
818 urm->destination_port = htons (0);
821 pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
822 send_packet_to_mesh_tunnel (state->tunnel,
828 * @brief Handles a TCP packet received from the helper.
830 * @param tcp A pointer to the Packet
831 * @param pktlen the length of the packet, including its TCP header
832 * @param af address family (AFINET or AF_INET6)
833 * @param destination_ip destination IP-address of the IP packet (should
834 * be our local address)
835 * @param source_ip original source IP-address of the IP packet (should
836 * be the original destination address)
839 tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
842 const void *destination_ip,
843 const void *source_ip)
845 struct TunnelState *state;
847 struct GNUNET_TUN_TcpHeader *mtcp;
848 struct GNUNET_EXIT_TcpDataMessage *tdm;
849 struct TunnelMessageQueue *tnq;
853 char sbuf[INET6_ADDRSTRLEN];
854 char dbuf[INET6_ADDRSTRLEN];
855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
856 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
857 pktlen - sizeof (struct GNUNET_TUN_TcpHeader),
860 sbuf, sizeof (sbuf)),
861 (unsigned int) ntohs (tcp->spt),
864 dbuf, sizeof (dbuf)),
865 (unsigned int) ntohs (tcp->dpt));
867 if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
873 state = get_redirect_state (af, IPPROTO_TCP,
881 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
882 _("Packet dropped, have no matching connection information\n"));
886 /* mug port numbers and crc to avoid information leakage;
887 sender will need to lookup the correct values anyway */
888 memcpy (buf, tcp, pktlen);
889 mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
894 mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
895 if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
901 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);
902 tnq->payload = &tnq[1];
904 tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
905 tdm->header.size = htons ((uint16_t) mlen);
906 tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
907 tdm->reserved = htonl (0);
908 memcpy (&tdm->tcp_header,
911 send_packet_to_mesh_tunnel (state->tunnel,
917 * Receive packets from the helper-process
920 * @param client unsued
921 * @param message message received from helper
924 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
925 const struct GNUNET_MessageHeader *message)
927 const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
930 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931 "Got %u-byte message of type %u from gnunet-helper-exit\n",
932 ntohs (message->size),
933 ntohs (message->type));
934 GNUNET_STATISTICS_update (stats,
935 gettext_noop ("# Packets received from TUN"),
937 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
942 size = ntohs (message->size);
943 if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
948 GNUNET_STATISTICS_update (stats,
949 gettext_noop ("# Bytes received from TUN"),
951 pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
952 size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
953 switch (ntohs (pkt_tun->proto))
957 const struct GNUNET_TUN_IPv4Header *pkt4;
959 if (size < sizeof (struct GNUNET_TUN_IPv4Header))
961 /* Kernel to blame? */
965 pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
966 if (size != ntohs (pkt4->total_length))
968 /* Kernel to blame? */
972 if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
974 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
975 _("IPv4 packet options received. Ignored.\n"));
979 size -= sizeof (struct GNUNET_TUN_IPv4Header);
980 switch (pkt4->protocol)
983 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
985 &pkt4->destination_address,
986 &pkt4->source_address);
988 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
990 &pkt4->destination_address,
991 &pkt4->source_address);
994 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
996 &pkt4->destination_address,
997 &pkt4->source_address);
1000 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1001 _("IPv4 packet with unsupported next header received. Ignored.\n"));
1008 const struct GNUNET_TUN_IPv6Header *pkt6;
1010 if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1012 /* Kernel to blame? */
1016 pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1017 if (size != ntohs (pkt6->payload_length))
1019 /* Kernel to blame? */
1023 size -= sizeof (struct GNUNET_TUN_IPv6Header);
1024 switch (pkt6->next_header)
1027 udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
1029 &pkt6->destination_address,
1030 &pkt6->source_address);
1033 tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
1035 &pkt6->destination_address,
1036 &pkt6->source_address);
1039 icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1041 &pkt6->destination_address,
1042 &pkt6->source_address);
1045 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1046 _("IPv6 packet with unsupported next header received. Ignored.\n"));
1052 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1053 _("Packet from unknown protocol %u received. Ignored.\n"),
1054 ntohs (pkt_tun->proto));
1061 * We need to create a (unique) fresh local address (IP+port).
1064 * @param af desired address family
1065 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1066 * @param local_address address to initialize
1069 setup_fresh_address (int af,
1071 struct SocketAddress *local_address)
1073 local_address->af = af;
1074 local_address->proto = (uint8_t) proto;
1075 /* default "local" port range is often 32768--61000,
1076 so we pick a random value in that range */
1078 = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1084 struct in_addr addr;
1085 struct in_addr mask;
1088 addr = exit_ipv4addr;
1089 mask = exit_ipv4mask;
1090 if (0 == ~mask.s_addr)
1092 /* only one valid IP anyway */
1093 local_address->address.ipv4 = addr;
1096 /* Given 192.168.0.1/255.255.0.0, we want a mask
1097 of '192.168.255.255', thus: */
1098 mask.s_addr = addr.s_addr | ~mask.s_addr;
1099 /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1102 rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1104 local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1106 while ( (local_address->address.ipv4.s_addr == addr.s_addr) ||
1107 (local_address->address.ipv4.s_addr == mask.s_addr) );
1112 struct in6_addr addr;
1113 struct in6_addr mask;
1114 struct in6_addr rnd;
1117 addr = exit_ipv6addr;
1118 GNUNET_assert (ipv6prefix < 128);
1119 if (ipv6prefix == 127)
1121 /* only one valid IP anyway */
1122 local_address->address.ipv6 = addr;
1125 /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1128 for (i=127;i>=128-ipv6prefix;i--)
1129 mask.s6_addr[i / 8] |= (1 << (i % 8));
1131 /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1136 rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1138 local_address->address.ipv6.s6_addr[i]
1139 = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1142 while ( (0 == memcmp (&local_address->address.ipv6,
1144 sizeof (struct in6_addr))) ||
1145 (0 == memcmp (&local_address->address.ipv6,
1147 sizeof (struct in6_addr))) );
1157 * We are starting a fresh connection (TCP or UDP) and need
1158 * to pick a source port and IP address (within the correct
1159 * range and address family) to associate replies with the
1160 * connection / correct mesh tunnel. This function generates
1161 * a "fresh" source IP and source port number for a connection
1162 * After picking a good source address, this function sets up
1163 * the state in the 'connections_map' and 'connections_heap'
1164 * to allow finding the state when needed later. The function
1165 * also makes sure that we remain within memory limits by
1166 * cleaning up 'old' states.
1168 * @param state skeleton state to setup a record for; should
1169 * 'state->ri.remote_address' filled in so that
1170 * this code can determine which AF/protocol is
1171 * going to be used (the 'tunnel' should also
1172 * already be set); after calling this function,
1173 * heap_node and the local_address will be
1174 * also initialized (heap_node != NULL can be
1175 * used to test if a state has been fully setup).
1178 setup_state_record (struct TunnelState *state)
1180 GNUNET_HashCode key;
1181 struct TunnelState *s;
1183 /* generate fresh, unique address */
1186 if (NULL == state->serv)
1187 setup_fresh_address (state->ri.remote_address.af,
1188 state->ri.remote_address.proto,
1189 &state->ri.local_address);
1191 setup_fresh_address (state->serv->address.af,
1192 state->serv->address.proto,
1193 &state->ri.local_address);
1194 } while (NULL != get_redirect_state (state->ri.remote_address.af,
1195 state->ri.remote_address.proto,
1196 &state->ri.remote_address.address,
1197 state->ri.remote_address.port,
1198 &state->ri.local_address.address,
1199 state->ri.local_address.port,
1202 char buf[INET6_ADDRSTRLEN];
1203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1204 "Picked local address %s:%u for new connection\n",
1205 inet_ntop (state->ri.local_address.af,
1206 &state->ri.local_address.address,
1208 (unsigned int) state->ri.local_address.port);
1210 state->state_key = key;
1211 GNUNET_assert (GNUNET_OK ==
1212 GNUNET_CONTAINER_multihashmap_put (connections_map,
1214 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1215 state->heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
1217 GNUNET_TIME_absolute_get ().abs_value);
1218 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1220 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1221 GNUNET_assert (state != s);
1222 s->heap_node = NULL;
1223 GNUNET_MESH_tunnel_destroy (s->tunnel);
1224 GNUNET_assert (GNUNET_OK ==
1225 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1234 * Prepare an IPv4 packet for transmission via the TUN interface.
1235 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1236 * For UDP, the UDP header will be fully created, whereas for TCP
1237 * only the ports and checksum will be filled in. So for TCP,
1238 * a skeleton TCP header must be part of the provided payload.
1240 * @param payload payload of the packet (starting with UDP payload or
1241 * TCP header, depending on protocol)
1242 * @param payload_length number of bytes in 'payload'
1243 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1244 * @param src_address source address to use (IP and port)
1245 * @param dst_address destination address to use (IP and port)
1246 * @param pkt6 where to write the assembled packet; must
1247 * contain enough space for the IP header, UDP/TCP header
1251 prepare_ipv4_packet (const void *payload, size_t payload_length,
1253 const struct GNUNET_TUN_TcpHeader *tcp_header,
1254 const struct SocketAddress *src_address,
1255 const struct SocketAddress *dst_address,
1256 struct GNUNET_TUN_IPv4Header *pkt4)
1260 len = payload_length;
1264 len += sizeof (struct GNUNET_TUN_UdpHeader);
1267 len += sizeof (struct GNUNET_TUN_TcpHeader);
1268 GNUNET_assert (NULL != tcp_header);
1274 if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1280 GNUNET_TUN_initialize_ipv4_header (pkt4,
1283 &src_address->address.ipv4,
1284 &dst_address->address.ipv4);
1289 struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1291 pkt4_udp->spt = htons (src_address->port);
1292 pkt4_udp->dpt = htons (dst_address->port);
1293 pkt4_udp->len = htons ((uint16_t) payload_length);
1294 GNUNET_TUN_calculate_udp4_checksum (pkt4,
1296 payload, payload_length);
1297 memcpy (&pkt4_udp[1], payload, payload_length);
1302 struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1304 memcpy (pkt4_tcp, tcp_header, sizeof (struct GNUNET_TUN_TcpHeader));
1305 pkt4_tcp->spt = htons (src_address->port);
1306 pkt4_tcp->dpt = htons (dst_address->port);
1307 GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1311 memcpy (&pkt4_tcp[1], payload, payload_length);
1321 * Prepare an IPv6 packet for transmission via the TUN interface.
1322 * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1323 * For UDP, the UDP header will be fully created, whereas for TCP
1324 * only the ports and checksum will be filled in. So for TCP,
1325 * a skeleton TCP header must be part of the provided payload.
1327 * @param payload payload of the packet (starting with UDP payload or
1328 * TCP header, depending on protocol)
1329 * @param payload_length number of bytes in 'payload'
1330 * @param protocol IPPROTO_UDP or IPPROTO_TCP
1331 * @param src_address source address to use (IP and port)
1332 * @param dst_address destination address to use (IP and port)
1333 * @param pkt6 where to write the assembled packet; must
1334 * contain enough space for the IP header, UDP/TCP header
1338 prepare_ipv6_packet (const void *payload, size_t payload_length,
1340 const struct GNUNET_TUN_TcpHeader *tcp_header,
1341 const struct SocketAddress *src_address,
1342 const struct SocketAddress *dst_address,
1343 struct GNUNET_TUN_IPv6Header *pkt6)
1347 len = payload_length;
1351 len += sizeof (struct GNUNET_TUN_UdpHeader);
1354 /* tcp_header (with port/crc not set) must be part of payload! */
1355 if (len < sizeof (struct GNUNET_TUN_TcpHeader))
1365 if (len > UINT16_MAX)
1371 GNUNET_TUN_initialize_ipv6_header (pkt6,
1374 &dst_address->address.ipv6,
1375 &src_address->address.ipv6);
1381 struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1383 pkt6_udp->spt = htons (src_address->port);
1384 pkt6_udp->dpt = htons (dst_address->port);
1385 pkt6_udp->len = htons ((uint16_t) payload_length);
1387 GNUNET_TUN_calculate_udp6_checksum (pkt6,
1391 memcpy (&pkt6[1], payload, payload_length);
1396 struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) pkt6;
1398 /* memcpy first here as some TCP header fields are initialized this way! */
1399 memcpy (pkt6_tcp, payload, payload_length);
1400 pkt6_tcp->spt = htons (src_address->port);
1401 pkt6_tcp->dpt = htons (dst_address->port);
1402 GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1416 * Send a TCP packet via the TUN interface.
1418 * @param destination_address IP and port to use for the TCP packet's destination
1419 * @param source_address IP and port to use for the TCP packet's source
1420 * @param tcp header template to use
1421 * @param payload payload of the TCP packet
1422 * @param payload_length number of bytes in 'payload'
1425 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1426 const struct SocketAddress *source_address,
1427 const struct GNUNET_TUN_TcpHeader *tcp_header,
1428 const void *payload, size_t payload_length)
1432 GNUNET_STATISTICS_update (stats,
1433 gettext_noop ("# TCP packets sent via TUN"),
1435 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1436 "Sending packet with %u bytes TCP payload via TUN\n",
1437 (unsigned int) payload_length);
1438 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1439 switch (source_address->af)
1442 len += sizeof (struct GNUNET_TUN_IPv4Header);
1445 len += sizeof (struct GNUNET_TUN_IPv6Header);
1451 len += sizeof (struct GNUNET_TUN_TcpHeader);
1452 len += payload_length;
1453 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1460 struct GNUNET_MessageHeader *hdr;
1461 struct GNUNET_TUN_Layer2PacketHeader *tun;
1463 hdr = (struct GNUNET_MessageHeader *) buf;
1464 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1465 hdr->size = htons (len);
1466 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1467 tun->flags = htons (0);
1468 switch (source_address->af)
1472 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1474 tun->proto = htons (ETH_P_IPV4);
1475 prepare_ipv4_packet (payload, payload_length,
1479 destination_address,
1485 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1487 tun->proto = htons (ETH_P_IPV6);
1488 prepare_ipv6_packet (payload, payload_length,
1492 destination_address,
1500 (void) GNUNET_HELPER_send (helper_handle,
1501 (const struct GNUNET_MessageHeader*) buf,
1509 * Process a request via mesh to send a request to a TCP service
1510 * offered by this system.
1512 * @param cls closure, NULL
1513 * @param tunnel connection to the other end
1514 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1515 * @param sender who sent the message
1516 * @param message the actual message
1517 * @param atsi performance data for the connection
1518 * @return GNUNET_OK to keep the connection open,
1519 * GNUNET_SYSERR to close it (signal serious error)
1522 receive_tcp_service (void *unused GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1523 void **tunnel_ctx GNUNET_UNUSED,
1524 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1525 const struct GNUNET_MessageHeader *message,
1526 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1528 struct TunnelState *state = *tunnel_ctx;
1529 const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1530 uint16_t pkt_len = ntohs (message->size);
1532 GNUNET_STATISTICS_update (stats,
1533 gettext_noop ("# TCP service creation requests received via mesh"),
1535 GNUNET_STATISTICS_update (stats,
1536 gettext_noop ("# Bytes received from MESH"),
1537 pkt_len, GNUNET_NO);
1538 /* check that we got at least a valid header */
1539 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1541 GNUNET_break_op (0);
1542 return GNUNET_SYSERR;
1544 start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1545 pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1546 if ( (NULL == state) ||
1547 (NULL != state->serv) ||
1548 (NULL != state->heap_node) )
1550 GNUNET_break_op (0);
1551 return GNUNET_SYSERR;
1553 GNUNET_break_op (ntohl (start->reserved) == 0);
1554 /* setup fresh connection */
1555 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1556 "Received data from %s for forwarding to TCP service %s on port %u\n",
1557 GNUNET_i2s (sender),
1558 GNUNET_h2s (&start->service_descriptor),
1559 (unsigned int) ntohs (start->tcp_header.dpt));
1560 if (NULL == (state->serv = find_service (tcp_services, &start->service_descriptor,
1561 ntohs (start->tcp_header.dpt))))
1563 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1564 _("No service found for %s on port %d!\n"),
1566 ntohs (start->tcp_header.dpt));
1567 GNUNET_STATISTICS_update (stats,
1568 gettext_noop ("# TCP requests dropped (no such service)"),
1570 return GNUNET_SYSERR;
1572 state->ri.remote_address = state->serv->address;
1573 setup_state_record (state);
1574 send_tcp_packet_via_tun (&state->ri.remote_address,
1575 &state->ri.local_address,
1577 &start[1], pkt_len);
1583 * Process a request to forward TCP data to the Internet via this peer.
1585 * @param cls closure, NULL
1586 * @param tunnel connection to the other end
1587 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1588 * @param sender who sent the message
1589 * @param message the actual message
1590 * @param atsi performance data for the connection
1591 * @return GNUNET_OK to keep the connection open,
1592 * GNUNET_SYSERR to close it (signal serious error)
1595 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1596 void **tunnel_ctx GNUNET_UNUSED,
1597 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1598 const struct GNUNET_MessageHeader *message,
1599 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1601 struct TunnelState *state = *tunnel_ctx;
1602 const struct GNUNET_EXIT_TcpInternetStartMessage *start;
1603 uint16_t pkt_len = ntohs (message->size);
1604 const struct in_addr *v4;
1605 const struct in6_addr *v6;
1606 const void *payload;
1609 GNUNET_STATISTICS_update (stats,
1610 gettext_noop ("# Bytes received from MESH"),
1611 pkt_len, GNUNET_NO);
1612 GNUNET_STATISTICS_update (stats,
1613 gettext_noop ("# TCP IP-exit creation requests received via mesh"),
1615 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
1617 GNUNET_break_op (0);
1618 return GNUNET_SYSERR;
1620 start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
1621 pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
1622 if ( (NULL == state) ||
1623 (NULL != state->serv) ||
1624 (NULL != state->heap_node) )
1626 GNUNET_break_op (0);
1627 return GNUNET_SYSERR;
1629 af = (int) ntohl (start->af);
1630 state->ri.remote_address.af = af;
1634 if (pkt_len < sizeof (struct in_addr))
1636 GNUNET_break_op (0);
1637 return GNUNET_SYSERR;
1641 GNUNET_break_op (0);
1642 return GNUNET_SYSERR;
1644 v4 = (const struct in_addr*) &start[1];
1646 pkt_len -= sizeof (struct in_addr);
1647 state->ri.remote_address.address.ipv4 = *v4;
1650 if (pkt_len < sizeof (struct in6_addr))
1652 GNUNET_break_op (0);
1653 return GNUNET_SYSERR;
1657 GNUNET_break_op (0);
1658 return GNUNET_SYSERR;
1660 v6 = (const struct in6_addr*) &start[1];
1662 pkt_len -= sizeof (struct in6_addr);
1663 state->ri.remote_address.address.ipv6 = *v6;
1666 GNUNET_break_op (0);
1667 return GNUNET_SYSERR;
1670 char buf[INET6_ADDRSTRLEN];
1671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1672 "Received data from %s for starting TCP stream to %s:%u\n",
1673 GNUNET_i2s (sender),
1675 &state->ri.remote_address.address,
1677 (unsigned int) ntohs (start->tcp_header.dpt));
1680 state->ri.remote_address.proto = IPPROTO_TCP;
1681 state->ri.remote_address.port = ntohs (start->tcp_header.dpt);
1682 setup_state_record (state);
1683 send_tcp_packet_via_tun (&state->ri.remote_address,
1684 &state->ri.local_address,
1692 * Process a request to forward TCP data on an established
1693 * connection via this peer.
1695 * @param cls closure, NULL
1696 * @param tunnel connection to the other end
1697 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1698 * @param sender who sent the message
1699 * @param message the actual message
1700 * @param atsi performance data for the connection
1701 * @return GNUNET_OK to keep the connection open,
1702 * GNUNET_SYSERR to close it (signal serious error)
1705 receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1706 void **tunnel_ctx GNUNET_UNUSED,
1707 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1708 const struct GNUNET_MessageHeader *message,
1709 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1711 struct TunnelState *state = *tunnel_ctx;
1712 const struct GNUNET_EXIT_TcpDataMessage *data;
1713 uint16_t pkt_len = ntohs (message->size);
1715 GNUNET_STATISTICS_update (stats,
1716 gettext_noop ("# Bytes received from MESH"),
1717 pkt_len, GNUNET_NO);
1718 GNUNET_STATISTICS_update (stats,
1719 gettext_noop ("# TCP data requests received via mesh"),
1721 if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1723 GNUNET_break_op (0);
1724 return GNUNET_SYSERR;
1726 data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
1727 pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
1728 if ( (NULL == state) ||
1729 (NULL == state->heap_node) )
1731 /* connection should have been up! */
1732 GNUNET_STATISTICS_update (stats,
1733 gettext_noop ("# TCP DATA requests dropped (no session)"),
1735 return GNUNET_SYSERR;
1737 GNUNET_break_op (ntohl (data->reserved) == 0);
1739 char buf[INET6_ADDRSTRLEN];
1740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1741 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1743 GNUNET_i2s (sender),
1744 inet_ntop (state->ri.remote_address.af,
1745 &state->ri.remote_address.address,
1747 (unsigned int) state->ri.remote_address.port);
1750 send_tcp_packet_via_tun (&state->ri.remote_address,
1751 &state->ri.local_address,
1759 * Send an ICMP packet via the TUN interface.
1761 * @param destination_address IP to use for the ICMP packet's destination
1762 * @param source_address IP to use for the ICMP packet's source
1763 * @param icmp_header ICMP header to send
1764 * @param payload payload of the ICMP packet (does NOT include ICMP header)
1765 * @param payload_length number of bytes of data in payload
1768 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1769 const struct SocketAddress *source_address,
1770 const struct GNUNET_TUN_IcmpHeader *icmp_header,
1771 const void *payload, size_t payload_length)
1774 struct GNUNET_TUN_IcmpHeader *icmp;
1776 GNUNET_STATISTICS_update (stats,
1777 gettext_noop ("# ICMP packets sent via TUN"),
1779 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1780 "Sending packet with %u bytes ICMP payload via TUN\n",
1781 (unsigned int) payload_length);
1782 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1783 switch (destination_address->af)
1786 len += sizeof (struct GNUNET_TUN_IPv4Header);
1789 len += sizeof (struct GNUNET_TUN_IPv6Header);
1795 len += sizeof (struct GNUNET_TUN_IcmpHeader);
1796 len += payload_length;
1797 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1804 struct GNUNET_MessageHeader *hdr;
1805 struct GNUNET_TUN_Layer2PacketHeader *tun;
1807 hdr= (struct GNUNET_MessageHeader *) buf;
1808 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1809 hdr->size = htons (len);
1810 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1811 tun->flags = htons (0);
1812 switch (source_address->af)
1816 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1818 tun->proto = htons (ETH_P_IPV4);
1819 GNUNET_TUN_initialize_ipv4_header (ipv4,
1821 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1822 &source_address->address.ipv4,
1823 &destination_address->address.ipv4);
1824 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1829 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1831 tun->proto = htons (ETH_P_IPV6);
1832 GNUNET_TUN_initialize_ipv6_header (ipv6,
1834 sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1835 &source_address->address.ipv6,
1836 &destination_address->address.ipv6);
1837 icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1844 *icmp = *icmp_header;
1848 GNUNET_TUN_calculate_icmp_checksum (icmp,
1851 (void) GNUNET_HELPER_send (helper_handle,
1852 (const struct GNUNET_MessageHeader*) buf,
1860 * Process a request to forward ICMP data to the Internet via this peer.
1862 * @param cls closure, NULL
1863 * @param tunnel connection to the other end
1864 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1865 * @param sender who sent the message
1866 * @param message the actual message
1867 * @param atsi performance data for the connection
1868 * @return GNUNET_OK to keep the connection open,
1869 * GNUNET_SYSERR to close it (signal serious error)
1872 receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1873 void **tunnel_ctx GNUNET_UNUSED,
1874 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1875 const struct GNUNET_MessageHeader *message,
1876 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1878 struct TunnelState *state = *tunnel_ctx;
1879 const struct GNUNET_EXIT_IcmpInternetMessage *msg;
1880 uint16_t pkt_len = ntohs (message->size);
1881 const struct in_addr *v4;
1882 const struct in6_addr *v6;
1883 const void *payload;
1886 GNUNET_STATISTICS_update (stats,
1887 gettext_noop ("# Bytes received from MESH"),
1888 pkt_len, GNUNET_NO);
1889 GNUNET_STATISTICS_update (stats,
1890 gettext_noop ("# ICMP IP-exit requests received via mesh"),
1892 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
1894 GNUNET_break_op (0);
1895 return GNUNET_SYSERR;
1897 msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
1898 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
1900 af = (int) ntohl (msg->af);
1901 state->ri.remote_address.af = af;
1905 if (pkt_len < sizeof (struct in_addr))
1907 GNUNET_break_op (0);
1908 return GNUNET_SYSERR;
1912 GNUNET_break_op (0);
1913 return GNUNET_SYSERR;
1915 v4 = (const struct in_addr*) &msg[1];
1917 pkt_len -= sizeof (struct in_addr);
1918 state->ri.remote_address.address.ipv4 = *v4;
1921 if (pkt_len < sizeof (struct in6_addr))
1923 GNUNET_break_op (0);
1924 return GNUNET_SYSERR;
1928 GNUNET_break_op (0);
1929 return GNUNET_SYSERR;
1931 v6 = (const struct in6_addr*) &msg[1];
1933 pkt_len -= sizeof (struct in6_addr);
1934 state->ri.remote_address.address.ipv6 = *v6;
1937 GNUNET_break_op (0);
1938 return GNUNET_SYSERR;
1942 char buf[INET6_ADDRSTRLEN];
1943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1944 "Received ICMP data from %s for forwarding to %s\n",
1945 GNUNET_i2s (sender),
1947 &state->ri.remote_address.address,
1948 buf, sizeof (buf)));
1951 /* FIXME: check that ICMP type is something we want to support */
1953 state->ri.remote_address.proto = IPPROTO_ICMP;
1954 state->ri.remote_address.port = 0;
1955 state->ri.local_address.port = 0;
1956 if (NULL == state->heap_node)
1957 setup_state_record (state);
1959 send_icmp_packet_via_tun (&state->ri.remote_address,
1960 &state->ri.local_address,
1968 * Process a request via mesh to send ICMP data to a service
1969 * offered by this system.
1971 * @param cls closure, NULL
1972 * @param tunnel connection to the other end
1973 * @param tunnel_ctx pointer to our 'struct TunnelState *'
1974 * @param sender who sent the message
1975 * @param message the actual message
1976 * @param atsi performance data for the connection
1977 * @return GNUNET_OK to keep the connection open,
1978 * GNUNET_SYSERR to close it (signal serious error)
1981 receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1983 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1984 const struct GNUNET_MessageHeader *message,
1985 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1987 struct TunnelState *state = *tunnel_ctx;
1988 const struct GNUNET_EXIT_IcmpServiceMessage *msg;
1989 uint16_t pkt_len = ntohs (message->size);
1991 GNUNET_STATISTICS_update (stats,
1992 gettext_noop ("# Bytes received from MESH"),
1993 pkt_len, GNUNET_NO);
1994 GNUNET_STATISTICS_update (stats,
1995 gettext_noop ("# ICMP service requests received via mesh"),
1997 /* check that we got at least a valid header */
1998 if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
2000 GNUNET_break_op (0);
2001 return GNUNET_SYSERR;
2003 msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2004 pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2006 "Received data from %s for forwarding to ICMP service %s\n",
2007 GNUNET_i2s (sender),
2008 GNUNET_h2s (&msg->service_descriptor));
2009 if (NULL == state->serv)
2011 /* first packet to service must not be ICMP (cannot determine service!) */
2012 GNUNET_break_op (0);
2013 return GNUNET_SYSERR;
2015 if (state->serv->address.af != ntohl (msg->af))
2017 GNUNET_STATISTICS_update (stats,
2018 gettext_noop ("# ICMP service requests discarded (incompatible af)"),
2020 return GNUNET_SYSERR;
2023 /* FIXME: check that ICMP type is something we want to support */
2025 state->ri.remote_address = state->serv->address;
2026 setup_state_record (state);
2028 send_icmp_packet_via_tun (&state->ri.remote_address,
2029 &state->ri.local_address,
2037 * Send a UDP packet via the TUN interface.
2039 * @param destination_address IP and port to use for the UDP packet's destination
2040 * @param source_address IP and port to use for the UDP packet's source
2041 * @param payload payload of the UDP packet (does NOT include UDP header)
2042 * @param payload_length number of bytes of data in payload
2045 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
2046 const struct SocketAddress *source_address,
2047 const void *payload, size_t payload_length)
2051 GNUNET_STATISTICS_update (stats,
2052 gettext_noop ("# UDP packets sent via TUN"),
2054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2055 "Sending packet with %u bytes UDP payload via TUN\n",
2056 (unsigned int) payload_length);
2057 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2058 switch (source_address->af)
2061 len += sizeof (struct GNUNET_TUN_IPv4Header);
2064 len += sizeof (struct GNUNET_TUN_IPv6Header);
2070 len += sizeof (struct GNUNET_TUN_UdpHeader);
2071 len += payload_length;
2072 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2079 struct GNUNET_MessageHeader *hdr;
2080 struct GNUNET_TUN_Layer2PacketHeader *tun;
2082 hdr= (struct GNUNET_MessageHeader *) buf;
2083 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2084 hdr->size = htons (len);
2085 tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2086 tun->flags = htons (0);
2087 switch (source_address->af)
2091 struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2093 tun->proto = htons (ETH_P_IPV4);
2094 prepare_ipv4_packet (payload, payload_length,
2098 destination_address,
2104 struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2106 tun->proto = htons (ETH_P_IPV6);
2107 prepare_ipv6_packet (payload, payload_length,
2111 destination_address,
2119 (void) GNUNET_HELPER_send (helper_handle,
2120 (const struct GNUNET_MessageHeader*) buf,
2128 * Process a request to forward UDP data to the Internet via this peer.
2130 * @param cls closure, NULL
2131 * @param tunnel connection to the other end
2132 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2133 * @param sender who sent the message
2134 * @param message the actual message
2135 * @param atsi performance data for the connection
2136 * @return GNUNET_OK to keep the connection open,
2137 * GNUNET_SYSERR to close it (signal serious error)
2140 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2141 void **tunnel_ctx GNUNET_UNUSED,
2142 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2143 const struct GNUNET_MessageHeader *message,
2144 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2146 struct TunnelState *state = *tunnel_ctx;
2147 const struct GNUNET_EXIT_UdpInternetMessage *msg;
2148 uint16_t pkt_len = ntohs (message->size);
2149 const struct in_addr *v4;
2150 const struct in6_addr *v6;
2151 const void *payload;
2154 GNUNET_STATISTICS_update (stats,
2155 gettext_noop ("# Bytes received from MESH"),
2156 pkt_len, GNUNET_NO);
2157 GNUNET_STATISTICS_update (stats,
2158 gettext_noop ("# UDP IP-exit requests received via mesh"),
2160 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2162 GNUNET_break_op (0);
2163 return GNUNET_SYSERR;
2165 msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message;
2166 pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage);
2167 af = (int) ntohl (msg->af);
2168 state->ri.remote_address.af = af;
2172 if (pkt_len < sizeof (struct in_addr))
2174 GNUNET_break_op (0);
2175 return GNUNET_SYSERR;
2179 GNUNET_break_op (0);
2180 return GNUNET_SYSERR;
2182 v4 = (const struct in_addr*) &msg[1];
2184 pkt_len -= sizeof (struct in_addr);
2185 state->ri.remote_address.address.ipv4 = *v4;
2188 if (pkt_len < sizeof (struct in6_addr))
2190 GNUNET_break_op (0);
2191 return GNUNET_SYSERR;
2195 GNUNET_break_op (0);
2196 return GNUNET_SYSERR;
2198 v6 = (const struct in6_addr*) &msg[1];
2200 pkt_len -= sizeof (struct in6_addr);
2201 state->ri.remote_address.address.ipv6 = *v6;
2204 GNUNET_break_op (0);
2205 return GNUNET_SYSERR;
2208 char buf[INET6_ADDRSTRLEN];
2209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2210 "Received data from %s for forwarding to UDP %s:%u\n",
2211 GNUNET_i2s (sender),
2213 &state->ri.remote_address.address,
2215 (unsigned int) ntohs (msg->destination_port));
2217 state->ri.remote_address.proto = IPPROTO_UDP;
2218 state->ri.remote_address.port = msg->destination_port;
2219 if (NULL == state->heap_node)
2220 setup_state_record (state);
2221 if (0 != ntohs (msg->source_port))
2222 state->ri.local_address.port = msg->source_port;
2223 send_udp_packet_via_tun (&state->ri.remote_address,
2224 &state->ri.local_address,
2231 * Process a request via mesh to send a request to a UDP service
2232 * offered by this system.
2234 * @param cls closure, NULL
2235 * @param tunnel connection to the other end
2236 * @param tunnel_ctx pointer to our 'struct TunnelState *'
2237 * @param sender who sent the message
2238 * @param message the actual message
2239 * @param atsi performance data for the connection
2240 * @return GNUNET_OK to keep the connection open,
2241 * GNUNET_SYSERR to close it (signal serious error)
2244 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2246 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2247 const struct GNUNET_MessageHeader *message,
2248 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2250 struct TunnelState *state = *tunnel_ctx;
2251 const struct GNUNET_EXIT_UdpServiceMessage *msg;
2252 uint16_t pkt_len = ntohs (message->size);
2254 GNUNET_STATISTICS_update (stats,
2255 gettext_noop ("# Bytes received from MESH"),
2256 pkt_len, GNUNET_NO);
2257 GNUNET_STATISTICS_update (stats,
2258 gettext_noop ("# UDP service requests received via mesh"),
2260 /* check that we got at least a valid header */
2261 if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
2263 GNUNET_break_op (0);
2264 return GNUNET_SYSERR;
2266 msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message;
2267 pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage);
2268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2269 "Received data from %s for forwarding to UDP service %s on port %u\n",
2270 GNUNET_i2s (sender),
2271 GNUNET_h2s (&msg->service_descriptor),
2272 (unsigned int) ntohs (msg->destination_port));
2273 if (NULL == (state->serv = find_service (udp_services, &msg->service_descriptor,
2274 ntohs (msg->destination_port))))
2276 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2277 _("No service found for %s on port %d!\n"),
2279 ntohs (msg->destination_port));
2280 GNUNET_STATISTICS_update (stats,
2281 gettext_noop ("# UDP requests dropped (no such service)"),
2283 return GNUNET_SYSERR;
2285 state->ri.remote_address = state->serv->address;
2286 setup_state_record (state);
2287 if (0 != ntohs (msg->source_port))
2288 state->ri.local_address.port = msg->source_port;
2289 send_udp_packet_via_tun (&state->ri.remote_address,
2290 &state->ri.local_address,
2297 * Callback from GNUNET_MESH for new tunnels.
2299 * @param cls closure
2300 * @param tunnel new handle to the tunnel
2301 * @param initiator peer that started the tunnel
2302 * @param atsi performance information for the tunnel
2303 * @return initial tunnel context for the tunnel
2306 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2307 const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
2308 const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
2310 struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
2312 GNUNET_STATISTICS_update (stats,
2313 gettext_noop ("# Inbound MESH tunnels created"),
2315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2316 "Received inbound tunnel from `%s'\n",
2317 GNUNET_i2s (initiator));
2324 * Function called by mesh whenever an inbound tunnel is destroyed.
2325 * Should clean up any associated state.
2327 * @param cls closure (set from GNUNET_MESH_connect)
2328 * @param tunnel connection to the other end (henceforth invalid)
2329 * @param tunnel_ctx place where local state associated
2330 * with the tunnel is stored
2333 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
2336 struct TunnelState *s = tunnel_ctx;
2337 struct TunnelMessageQueue *tnq;
2339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2340 "Tunnel destroyed\n");
2341 while (NULL != (tnq = s->head))
2343 GNUNET_CONTAINER_DLL_remove (s->head,
2348 if (s->heap_node != NULL)
2350 GNUNET_assert (GNUNET_YES ==
2351 GNUNET_CONTAINER_multihashmap_remove (connections_map,
2354 GNUNET_CONTAINER_heap_remove_node (s->heap_node);
2355 s->heap_node = NULL;
2359 GNUNET_MESH_notify_transmit_ready_cancel (s->th);
2367 * Function that frees everything from a hashmap
2371 * @param value value to free
2374 free_iterate (void *cls GNUNET_UNUSED,
2375 const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
2377 GNUNET_free (value);
2383 * Function scheduled as very last function, cleans up after us
2386 cleanup (void *cls GNUNET_UNUSED,
2387 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
2391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2392 "Exit service is shutting down now\n");
2393 if (helper_handle != NULL)
2395 GNUNET_HELPER_stop (helper_handle);
2396 helper_handle = NULL;
2398 if (mesh_handle != NULL)
2400 GNUNET_MESH_disconnect (mesh_handle);
2403 if (NULL != connections_map)
2405 GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
2406 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
2407 connections_map = NULL;
2409 if (NULL != connections_heap)
2411 GNUNET_CONTAINER_heap_destroy (connections_heap);
2412 connections_heap = NULL;
2414 if (NULL != tcp_services)
2416 GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
2417 GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
2418 tcp_services = NULL;
2420 if (NULL != udp_services)
2422 GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
2423 GNUNET_CONTAINER_multihashmap_destroy (udp_services);
2424 udp_services = NULL;
2428 GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
2432 GNUNET_free_non_null (exit_argv[i]);
2437 * Add services to the service map.
2439 * @param proto IPPROTO_TCP or IPPROTO_UDP
2440 * @param cpy copy of the service descriptor (can be mutilated)
2441 * @param name DNS name of the service
2444 add_services (int proto,
2451 struct LocalService *serv;
2453 for (redirect = strtok (cpy, " "); redirect != NULL;
2454 redirect = strtok (NULL, " "))
2456 if (NULL == (hostname = strstr (redirect, ":")))
2458 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2459 "option `%s' for domain `%s' is not formatted correctly!\n",
2466 if (NULL == (hostport = strstr (hostname, ":")))
2468 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2469 "option `%s' for domain `%s' is not formatted correctly!\n",
2477 int local_port = atoi (redirect);
2478 int remote_port = atoi (hostport);
2480 if (!((local_port > 0) && (local_port < 65536)))
2482 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2483 "`%s' is not a valid port number (for domain `%s')!", redirect,
2487 if (!((remote_port > 0) && (remote_port < 65536)))
2489 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2490 "`%s' is not a valid port number (for domain `%s')!", hostport,
2495 serv = GNUNET_malloc (sizeof (struct LocalService));
2496 serv->my_port = (uint16_t) local_port;
2497 serv->address.port = remote_port;
2498 if (0 == strcmp ("localhost4", hostname))
2500 const char *ip4addr = exit_argv[4];
2502 serv->address.af = AF_INET;
2503 GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
2505 else if (0 == strcmp ("localhost6", hostname))
2507 const char *ip6addr = exit_argv[2];
2509 serv->address.af = AF_INET6;
2510 GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
2514 struct addrinfo *res;
2517 ret = getaddrinfo (hostname, NULL, NULL, &res);
2518 if ( (ret != 0) || (res == NULL) )
2520 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2521 _("No addresses found for hostname `%s' of service `%s'!\n"),
2528 serv->address.af = res->ai_family;
2529 switch (res->ai_family)
2534 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2535 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
2541 serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
2546 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2547 _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
2553 serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
2557 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2558 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
2566 store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
2575 * Reads the configuration servicecfg and populates udp_services
2578 * @param section name of section in config, equal to hostname
2581 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
2585 if ((strlen (section) < 8) ||
2586 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
2589 GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
2592 add_services (IPPROTO_UDP, cpy, section);
2596 GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
2599 add_services (IPPROTO_TCP, cpy, section);
2606 * @brief Main function that will be run by the scheduler.
2608 * @param cls closure
2609 * @param args remaining command-line arguments
2610 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
2611 * @param cfg_ configuration
2614 run (void *cls, char *const *args GNUNET_UNUSED,
2615 const char *cfgfile GNUNET_UNUSED,
2616 const struct GNUNET_CONFIGURATION_Handle *cfg_)
2618 static struct GNUNET_MESH_MessageHandler handlers[] = {
2619 {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0},
2620 {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0},
2621 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0},
2622 {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0},
2623 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0},
2624 {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0},
2625 {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0},
2629 static GNUNET_MESH_ApplicationType apptypes[] = {
2630 GNUNET_APPLICATION_TYPE_END,
2631 GNUNET_APPLICATION_TYPE_END,
2632 GNUNET_APPLICATION_TYPE_END
2634 unsigned int app_idx;
2643 stats = GNUNET_STATISTICS_create ("exit", cfg);
2644 ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
2645 ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6");
2646 ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4");
2647 ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6");
2648 if (ipv4_exit && (! ipv4_enabled))
2650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2651 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
2652 ipv4_enabled = GNUNET_YES;
2654 if (ipv6_exit && (! ipv6_enabled))
2656 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2657 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
2658 ipv6_enabled = GNUNET_YES;
2660 if (! (ipv4_enabled || ipv6_enabled))
2662 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2663 _("No useful service enabled. Exiting.\n"));
2664 GNUNET_SCHEDULER_shutdown ();
2668 if (GNUNET_YES == ipv4_exit)
2670 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
2673 if (GNUNET_YES == ipv6_exit)
2675 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
2679 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
2682 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
2684 max_connections = 1024;
2685 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
2686 if (GNUNET_SYSERR ==
2687 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", &tun_ifname))
2689 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2690 "No entry 'TUN_IFNAME' in configuration!\n");
2691 GNUNET_SCHEDULER_shutdown ();
2694 exit_argv[1] = tun_ifname;
2697 if (GNUNET_SYSERR ==
2698 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", &exit_ifname))
2700 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2701 "No entry 'EXIT_IFNAME' in configuration!\n");
2702 GNUNET_SCHEDULER_shutdown ();
2705 exit_argv[2] = exit_ifname;
2709 exit_argv[2] = GNUNET_strdup ("%");
2711 if (GNUNET_YES == ipv6_enabled)
2713 if ( (GNUNET_SYSERR ==
2714 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
2716 (1 != inet_pton (AF_INET6, ipv6addr, &exit_ipv6addr))) )
2718 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2719 "No valid entry 'IPV6ADDR' in configuration!\n");
2720 GNUNET_SCHEDULER_shutdown ();
2723 exit_argv[3] = ipv6addr;
2724 if (GNUNET_SYSERR ==
2725 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
2728 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2729 "No entry 'IPV6PREFIX' in configuration!\n");
2730 GNUNET_SCHEDULER_shutdown ();
2733 exit_argv[4] = ipv6prefix_s;
2735 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
2738 (ipv6prefix >= 127) )
2740 GNUNET_SCHEDULER_shutdown ();
2746 /* IPv6 explicitly disabled */
2747 exit_argv[3] = GNUNET_strdup ("-");
2748 exit_argv[4] = GNUNET_strdup ("-");
2750 if (GNUNET_YES == ipv4_enabled)
2752 if ( (GNUNET_SYSERR ==
2753 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
2755 (1 != inet_pton (AF_INET, ipv4addr, &exit_ipv4addr))) )
2757 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2758 "No valid entry for 'IPV4ADDR' in configuration!\n");
2759 GNUNET_SCHEDULER_shutdown ();
2762 exit_argv[5] = ipv4addr;
2763 if ( (GNUNET_SYSERR ==
2764 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
2766 (1 != inet_pton (AF_INET, ipv4mask, &exit_ipv4mask))) )
2768 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2769 "No valid entry 'IPV4MASK' in configuration!\n");
2770 GNUNET_SCHEDULER_shutdown ();
2773 exit_argv[6] = ipv4mask;
2777 /* IPv4 explicitly disabled */
2778 exit_argv[5] = GNUNET_strdup ("-");
2779 exit_argv[6] = GNUNET_strdup ("-");
2781 exit_argv[7] = NULL;
2783 udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
2784 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
2785 GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
2787 connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
2788 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2790 = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL,
2792 &clean_tunnel, handlers,
2794 if (NULL == mesh_handle)
2796 GNUNET_SCHEDULER_shutdown ();
2799 helper_handle = GNUNET_HELPER_start ("gnunet-helper-exit",
2801 &message_token, NULL);
2808 * @param argc number of arguments from the command line
2809 * @param argv command line arguments
2810 * @return 0 ok, 1 on error
2813 main (int argc, char *const *argv)
2815 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
2816 GNUNET_GETOPT_OPTION_END
2819 return (GNUNET_OK ==
2820 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
2822 ("Daemon to run to provide an IP exit node for the VPN"),
2823 options, &run, NULL)) ? 0 : 1;
2827 /* end of gnunet-daemon-exit.c */