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
28 * - setup_fresh_address is not implemented
29 * - various functions are not documented
30 * - update_state_map is dead, do we need something like it still?
31 * - need proper message headers for mesh P2P messages
34 #include <gnunet_common.h>
35 #include <gnunet_program_lib.h>
36 #include <gnunet_protocols.h>
37 #include <gnunet_applications.h>
38 #include <gnunet_mesh_service.h>
39 #include <gnunet_constants.h>
43 /* see http://www.iana.org/assignments/ethernet-numbers */
45 #define ETH_P_IPV4 0x0800
49 #define ETH_P_IPV6 0x86DD
53 GNUNET_NETWORK_STRUCT_BEGIN
55 * Header from Linux TUN interface.
60 * Some flags (unused).
65 * Here we get an ETH_P_-number.
71 * Standard IPv4 header.
75 unsigned header_length:4 GNUNET_PACKED;
76 unsigned version:4 GNUNET_PACKED;
78 uint16_t total_length GNUNET_PACKED;
79 uint16_t identification GNUNET_PACKED;
80 unsigned flags:3 GNUNET_PACKED;
81 unsigned fragmentation_offset:13 GNUNET_PACKED;
84 uint16_t checksum GNUNET_PACKED;
85 struct in_addr source_address GNUNET_PACKED;
86 struct in_addr destination_address GNUNET_PACKED;
90 * Standard IPv6 header.
94 unsigned traffic_class_h:4 GNUNET_PACKED;
95 unsigned version:4 GNUNET_PACKED;
96 unsigned traffic_class_l:4 GNUNET_PACKED;
97 unsigned flow_label:20 GNUNET_PACKED;
98 uint16_t payload_length GNUNET_PACKED;
101 struct in6_addr source_address GNUNET_PACKED;
102 struct in6_addr destination_address GNUNET_PACKED;
105 #define TCP_FLAG_SYN 2
109 unsigned spt:16 GNUNET_PACKED;
110 unsigned dpt:16 GNUNET_PACKED;
111 unsigned seq:32 GNUNET_PACKED;
112 unsigned ack:32 GNUNET_PACKED;
113 unsigned off:4 GNUNET_PACKED;
114 unsigned rsv:4 GNUNET_PACKED;
115 unsigned flg:8 GNUNET_PACKED;
116 unsigned wsz:16 GNUNET_PACKED;
117 unsigned crc:16 GNUNET_PACKED;
118 unsigned urg:16 GNUNET_PACKED;
126 uint16_t spt GNUNET_PACKED;
127 uint16_t dpt GNUNET_PACKED;
128 uint16_t len GNUNET_PACKED;
129 uint16_t crc GNUNET_PACKED;
137 uint16_t id GNUNET_PACKED;
138 uint16_t flags GNUNET_PACKED;
139 uint16_t qdcount GNUNET_PACKED;
140 uint16_t ancount GNUNET_PACKED;
141 uint16_t nscount GNUNET_PACKED;
142 uint16_t arcount GNUNET_PACKED;
144 GNUNET_NETWORK_STRUCT_END
147 * Information about an address.
152 * AF_INET or AF_INET6.
157 * Remote address information.
162 * Address, if af is AF_INET.
167 * Address, if af is AF_INET6.
169 struct in6_addr ipv6;
173 * IPPROTO_TCP or IPPROTO_UDP;
178 * Remote port, in host byte order!
185 * This struct is saved into the services-hashmap to represent
186 * a service this peer is specifically offering an exit for
187 * (for a specific domain name).
193 * Remote address to use for the service.
195 struct SocketAddress address;
198 * DNS name of the service.
203 * Port I am listening on within GNUnet for this service, in host
204 * byte order. (as we may redirect ports).
211 * Information we use to track a connection (the classical 6-tuple of
212 * IP-version, protocol, source-IP, destination-IP, source-port and
215 struct RedirectInformation
219 * Address information for the other party (equivalent of the
220 * arguments one would give to "connect").
222 struct SocketAddress remote_address;
225 * Address information we used locally (AF and proto must match
226 * "remote_address"). Equivalent of the arguments one would give to
229 struct SocketAddress local_address;
232 Note 1: additional information might be added here in the
233 future to support protocols that require special handling,
236 Note 2: we might also sometimes not match on all components
237 of the tuple, to support protocols where things do not always
244 * Queue of messages to a tunnel.
246 struct TunnelMessageQueue
249 * This is a doubly-linked list.
251 struct TunnelMessageQueue *next;
254 * This is a doubly-linked list.
256 struct TunnelMessageQueue *prev;
259 * Payload to send via the tunnel.
264 * Number of bytes in 'payload'.
271 * This struct is saved into connections_map to allow finding the
272 * right tunnel given an IP packet from TUN. It is also associated
273 * with the tunnel's closure so we can find it again for the next
274 * message from the tunnel.
279 * Mesh tunnel that is used for this connection.
281 struct GNUNET_MESH_Tunnel *tunnel;
284 * Heap node for this state in the connections_heap.
286 struct GNUNET_CONTAINER_HeapNode *heap_node;
289 * Key this state has in the connections_map.
291 GNUNET_HashCode state_key;
294 * Associated service record, or NULL for no service.
296 struct LocalService *serv;
299 * Head of DLL of messages for this tunnel.
301 struct TunnelMessageQueue *head;
304 * Tail of DLL of messages for this tunnel.
306 struct TunnelMessageQueue *tail;
309 * Active tunnel transmission request (or NULL).
311 struct GNUNET_MESH_TransmitHandle *th;
314 * Primary redirection information for this connection.
316 struct RedirectInformation ri;
322 * The handle to the configuration used throughout the process
324 static const struct GNUNET_CONFIGURATION_Handle *cfg;
327 * The handle to the helper
329 static struct GNUNET_HELPER_Handle *helper_handle;
332 * Arguments to the exit helper.
334 static char *exit_argv[7];
337 * IPv6 prefix (0..127) from configuration file.
339 static unsigned long long ipv6prefix;
344 static struct GNUNET_MESH_Handle *mesh_handle;
347 * This hashmaps contains the mapping from peer, service-descriptor,
348 * source-port and destination-port to a struct TunnelState
350 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
353 * Heap so we can quickly find "old" connections.
355 static struct GNUNET_CONTAINER_Heap *connections_heap;
358 * If there are at least this many connections, old ones will be removed
360 static long long unsigned int max_connections = 200;
363 * This hashmaps saves interesting things about the configured UDP services
365 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
368 * This hashmaps saves interesting things about the configured TCP services
370 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
374 * Given IP information about a connection, calculate the respective
375 * hash we would use for the 'connections_map'.
377 * @param hash resulting hash
378 * @param ri information about the connection
381 hash_redirect_info (GNUNET_HashCode *hash,
382 const struct RedirectInformation *ri)
386 memset (hash, 0, sizeof (GNUNET_HashCode));
387 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
388 so we put the IP address in there (and hope for few collisions) */
390 switch (ri->remote_address.af)
393 memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
394 off += sizeof (struct in_addr);
397 memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
398 off += sizeof (struct in_addr);
403 memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
404 off += sizeof (uint16_t);
405 switch (ri->local_address.af)
408 memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr));
409 off += sizeof (struct in_addr);
412 memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr));
413 off += sizeof (struct in_addr);
418 memcpy (off, &ri->local_address.port, sizeof (uint16_t));
419 off += sizeof (uint16_t);
420 memcpy (off, &ri->remote_address.proto, sizeof (uint8_t));
421 off += sizeof (uint8_t);
426 * Get our connection tracking state. Warns if it does not exists,
427 * refreshes the timestamp if it does exist.
429 * @param af address family
430 * @param protocol IPPROTO_UDP or IPPROTO_TCP
431 * @param destination_ip target IP
432 * @param destination_port target port
433 * @param local_ip local IP
434 * @param local_port local port
435 * @param state_key set to hash's state if non-NULL
436 * @return NULL if we have no tracking information for this tuple
438 static struct TunnelState *
439 get_redirect_state (int af,
441 const void *destination_ip,
442 uint16_t destination_port,
443 const void *local_ip,
445 GNUNET_HashCode *state_key)
447 struct RedirectInformation ri;
449 struct TunnelState *state;
451 ri.remote_address.af = af;
453 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
455 ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
456 ri.remote_address.port = destination_port;
457 ri.remote_address.proto = protocol;
458 ri.local_address.af = af;
460 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
462 ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
463 ri.local_address.port = local_port;
464 ri.local_address.proto = protocol;
465 hash_redirect_info (&key, &ri);
466 if (NULL != state_key)
468 state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key);
471 /* Mark this connection as freshly used */
472 if (NULL == state_key)
473 GNUNET_CONTAINER_heap_update_cost (connections_heap,
475 GNUNET_TIME_absolute_get ().abs_value);
481 * Given a service descriptor and a destination port, find the
482 * respective service entry.
484 * @param service_map map of services (TCP or UDP)
485 * @param desc service descriptor
486 * @param dpt destination port
487 * @return NULL if we are not aware of such a service
489 static struct LocalService *
490 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
491 const GNUNET_HashCode *desc,
494 char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
496 memcpy (&key[0], &dpt, sizeof (uint16_t));
497 memcpy (&key[sizeof(uint16_t)], desc, sizeof (GNUNET_HashCode));
498 return GNUNET_CONTAINER_multihashmap_get (service_map,
499 (GNUNET_HashCode *) key);
504 * Free memory associated with a service record.
507 * @param key service descriptor
508 * @param value service record to free
512 free_service_record (void *cls,
513 const GNUNET_HashCode *key,
516 struct LocalService *service = value;
518 GNUNET_free_non_null (service->name);
519 GNUNET_free (service);
525 * Given a service descriptor and a destination port, find the
526 * respective service entry.
528 * @param service_map map of services (TCP or UDP)
529 * @param name name of the service
530 * @param dpt destination port
531 * @param service service information record to store (service->name will be set).
534 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
537 struct LocalService *service)
539 char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
540 GNUNET_HashCode desc;
542 GNUNET_CRYPTO_hash (name, strlen (name) + 1, &desc);
543 service->name = GNUNET_strdup (name);
544 memcpy (&key[0], &dpt, sizeof (uint16_t));
545 memcpy (&key[sizeof(uint16_t)], &desc, sizeof (GNUNET_HashCode));
547 GNUNET_CONTAINER_multihashmap_put (service_map,
548 (GNUNET_HashCode *) key,
550 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
552 free_service_record (NULL, (GNUNET_HashCode *) key, service);
553 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
554 _("Got duplicate service records for `%s:%u'\n"),
562 * MESH is ready to receive a message for the tunnel. Transmit it.
564 * @param cls the 'struct TunnelState'.
565 * @param size number of bytes available in buf
566 * @param buf where to copy the message
567 * @return number of bytes copied to buf
570 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
572 struct TunnelState *s = cls;
573 struct GNUNET_MESH_Tunnel *tunnel = s->tunnel;
574 struct TunnelMessageQueue *tnq;
578 GNUNET_assert (size >= tnq->len);
579 memcpy (buf, tnq->payload, tnq->len);
581 GNUNET_CONTAINER_DLL_remove (s->head,
585 if (NULL != (tnq = s->head))
586 s->th = GNUNET_MESH_notify_transmit_ready (tunnel,
587 GNUNET_NO /* corking */,
589 GNUNET_TIME_UNIT_FOREVER_REL,
592 &send_to_peer_notify_callback,
599 * Send the given packet via the mesh tunnel.
601 * @param mesh_tunnel destination
602 * @param payload message to transmit
603 * @param payload_length number of bytes in payload
604 * @param desc descriptor to add before payload (optional)
605 * @param mtype message type to use
608 send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
610 size_t payload_length,
611 const GNUNET_HashCode *desc,
614 struct TunnelState *s;
615 struct TunnelMessageQueue *tnq;
616 struct GNUNET_MessageHeader *msg;
620 len = sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + payload_length;
621 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
626 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + len);
627 tnq->payload = &tnq[1];
629 msg = (struct GNUNET_MessageHeader *) &tnq[1];
630 msg->size = htons ((uint16_t) len);
631 msg->type = htons (mtype);
634 dp = (GNUNET_HashCode *) &msg[1];
636 memcpy (&dp[1], payload, payload_length);
640 memcpy (&msg[1], payload, payload_length);
642 s = GNUNET_MESH_tunnel_get_data (mesh_tunnel);
643 GNUNET_assert (NULL != s);
644 GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, tnq);
646 s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, 0 /* priority */,
647 GNUNET_TIME_UNIT_FOREVER_REL,
649 &send_to_peer_notify_callback,
655 * @brief Handles an UDP packet received from the helper.
657 * @param udp A pointer to the Packet
658 * @param pktlen number of bytes in 'udp'
659 * @param af address family (AFINET or AF_INET6)
660 * @param destination_ip destination IP-address of the IP packet (should
661 * be our local address)
662 * @param source_ip original source IP-address of the IP packet (should
663 * be the original destination address)
666 udp_from_helper (const struct udp_packet *udp,
669 const void *destination_ip,
670 const void *source_ip)
672 struct TunnelState *state;
674 if (pktlen < sizeof (struct udp_packet))
680 if (pktlen != ntohs (udp->len))
686 state = get_redirect_state (af, IPPROTO_UDP,
694 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
695 _("Packet dropped, have no matching connection information\n"));
698 send_packet_to_mesh_tunnel (state->tunnel,
699 &udp[1], pktlen - sizeof (struct udp_packet),
702 ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK
703 : GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
708 * @brief Handles a TCP packet received from the helper.
710 * @param tcp A pointer to the Packet
711 * @param pktlen the length of the packet, including its header
712 * @param af address family (AFINET or AF_INET6)
713 * @param destination_ip destination IP-address of the IP packet (should
714 * be our local address)
715 * @param source_ip original source IP-address of the IP packet (should
716 * be the original destination address)
719 tcp_from_helper (const struct tcp_packet *tcp,
722 const void *destination_ip,
723 const void *source_ip)
725 struct TunnelState *state;
727 struct tcp_packet *mtcp;
729 if (pktlen < sizeof (struct tcp_packet))
735 state = get_redirect_state (af, IPPROTO_TCP,
743 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
744 _("Packet dropped, have no matching connection information\n"));
748 /* mug port numbers and crc to avoid information leakage;
749 sender will need to lookup the correct values anyway */
750 memcpy (buf, tcp, pktlen);
751 mtcp = (struct tcp_packet *) buf;
755 send_packet_to_mesh_tunnel (state->tunnel,
759 ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK
760 : GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
765 * Receive packets from the helper-process
768 * @param client unsued
769 * @param message message received from helper
772 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
773 const struct GNUNET_MessageHeader *message)
775 const struct tun_header *pkt_tun;
778 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
783 size = ntohs (message->size);
784 if (size < sizeof (struct tun_header) + sizeof (struct GNUNET_MessageHeader))
789 pkt_tun = (const struct tun_header *) &message[1];
790 size -= sizeof (struct tun_header) + sizeof (struct GNUNET_MessageHeader);
791 switch (ntohs (pkt_tun->proto))
795 const struct ip6_header *pkt6;
797 if (size < sizeof (struct ip6_header))
799 /* Kernel to blame? */
803 pkt6 = (struct ip6_header *) &pkt_tun[1];
804 if (size != ntohs (pkt6->payload_length))
806 /* Kernel to blame? */
810 size -= sizeof (struct ip6_header);
811 switch (pkt6->next_header)
814 udp_from_helper ((const struct udp_packet *) &pkt6[1], size,
816 &pkt6->destination_address,
817 &pkt6->source_address);
820 tcp_from_helper ((const struct tcp_packet *) &pkt6[1], size,
822 &pkt6->destination_address,
823 &pkt6->source_address);
826 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
827 _("IPv6 packet with unsupported next header received. Ignored.\n"));
834 const struct ip4_header *pkt4;
836 if (size < sizeof (struct ip4_header))
838 /* Kernel to blame? */
842 pkt4 = (const struct ip4_header *) &pkt_tun[1];
843 if (size != ntohs (pkt4->total_length))
845 /* Kernel to blame? */
849 if (pkt4->header_length * 4 != sizeof (struct ip4_header))
851 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
852 _("IPv4 packet options received. Ignored.\n"));
855 size -= sizeof (struct ip4_header);
856 switch (pkt4->protocol)
859 udp_from_helper ((const struct udp_packet *) &pkt4[1], size,
861 &pkt4->destination_address,
862 &pkt4->source_address);
864 tcp_from_helper ((const struct tcp_packet *) &pkt4[1], size,
866 &pkt4->destination_address,
867 &pkt4->source_address);
870 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
871 _("IPv4 packet with unsupported next header received. Ignored.\n"));
877 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
878 _("Packet from unknown protocol %u received. Ignored.\n"),
879 ntohs (pkt_tun->proto));
886 * We need to create a (unique) fresh local address (IP+port).
889 * @param af desired address family
890 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
891 * @param local_address address to initialize
894 setup_fresh_address (int af,
896 struct SocketAddress *local_address)
902 const char *ipv4addr = exit_argv[4];
903 const char *ipv4mask = exit_argv[5];
907 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &tmp));
908 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &tmp2));
910 /* This should be a noop */
912 tmp |= ntohl (*((uint32_t *) /*tunnel*/ 42)) & (~tmp2);
914 // pkt4->source_address.s_addr = tmp;
919 const char *ipv6addr = exit_argv[2];
920 /* Generate a new src-address
921 * This takes as much from the address of the tunnel as fits into
923 unsigned long long ipv6prefix_r = (ipv6prefix + 7) / 8;
924 inet_pton (AF_INET6, ipv6addr, &local_address->address.ipv6);
925 if (ipv6prefix_r < (16 - sizeof (void *)))
926 ipv6prefix_r = 16 - sizeof (void *);
928 unsigned int offset = ipv6prefix_r - (16 - sizeof (void *));
929 // memcpy ((((char *) &pkt6->source_address)) + ipv6prefix_r, ((char *) &tunnel) + offset, 16 - ipv6prefix_r);
943 setup_state_record (struct TunnelState *state)
946 struct TunnelState *s;
948 /* generate fresh, unique address */
951 setup_fresh_address (state->serv->address.af,
952 state->serv->address.proto,
953 &state->ri.local_address);
954 } while (NULL != get_redirect_state (state->serv->address.af,
956 &state->ri.remote_address.address,
957 state->ri.remote_address.port,
958 &state->ri.local_address.address,
959 state->ri.local_address.port,
961 GNUNET_assert (GNUNET_OK ==
962 GNUNET_CONTAINER_multihashmap_put (connections_map,
964 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
965 state->heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
967 GNUNET_TIME_absolute_get ().abs_value);
968 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
970 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
971 GNUNET_assert (state != s);
973 GNUNET_MESH_tunnel_destroy (s->tunnel);
974 GNUNET_assert (GNUNET_OK ==
975 GNUNET_CONTAINER_multihashmap_remove (connections_map,
987 prepare_ipv4_packet (const void *payload, size_t payload_length,
989 const struct SocketAddress *src_address,
990 const struct SocketAddress *dst_address,
991 struct ip4_header *pkt4)
995 len = payload_length;
999 len += sizeof (struct udp_packet);
1002 /* tcp_header (with port/crc not set) must be part of payload! */
1003 if (len < sizeof (struct tcp_packet))
1013 if (len + sizeof (struct ip4_header) > UINT16_MAX)
1020 pkt4->header_length = sizeof (struct ip4_header) / 4;
1021 pkt4->diff_serv = 0;
1022 pkt4->total_length = htons ((uint16_t) (sizeof (struct ip4_header) + len));
1023 pkt4->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1026 pkt4->fragmentation_offset = 0;
1028 pkt4->protocol = protocol;
1030 pkt4->destination_address = dst_address->address.ipv4;
1031 pkt4->source_address = src_address->address.ipv4;
1032 pkt4->checksum = GNUNET_CRYPTO_crc16_n (pkt4, sizeof (struct ip4_header));
1038 struct udp_packet *pkt4_udp = (struct udp_packet *) &pkt4[1];
1040 pkt4_udp->spt = htons (src_address->port);
1041 pkt4_udp->dpt = htons (dst_address->port);
1042 pkt4_udp->crc = 0; /* Optional for IPv4 */
1043 pkt4_udp->len = htons ((uint16_t) payload_length);
1044 memcpy (&pkt4_udp[1], payload, payload_length);
1049 struct tcp_packet *pkt4_tcp = (struct tcp_packet *) &pkt4[1];
1051 memcpy (pkt4_tcp, payload, payload_length);
1052 pkt4_tcp->spt = htons (src_address->port);
1053 pkt4_tcp->dpt = htons (dst_address->port);
1056 sum = GNUNET_CRYPTO_crc16_step (sum,
1057 &pkt4->source_address,
1058 sizeof (struct in_addr) * 2);
1059 uint32_t tmp = htonl ((protocol << 16) | (0xffff & len));
1060 sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, sizeof (uint32_t));
1061 sum = GNUNET_CRYPTO_crc16_step (sum, & pkt4_tcp, len);
1062 pkt4_tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1075 prepare_ipv6_packet (const void *payload, size_t payload_length,
1077 const struct SocketAddress *src_address,
1078 const struct SocketAddress *dst_address,
1079 struct ip6_header *pkt6)
1083 len = payload_length;
1087 len += sizeof (struct udp_packet);
1090 /* tcp_header (with port/crc not set) must be part of payload! */
1091 if (len < sizeof (struct tcp_packet))
1101 if (len > UINT16_MAX)
1108 pkt6->next_header = protocol;
1109 pkt6->payload_length = htons ((uint16_t) (len + sizeof (struct ip6_header)));
1110 pkt6->hop_limit = 255;
1111 pkt6->destination_address = dst_address->address.ipv6;
1112 pkt6->source_address = src_address->address.ipv6;
1118 struct udp_packet *pkt6_udp = (struct udp_packet *) &pkt6[1];
1120 memcpy (&pkt6[1], payload, payload_length);
1122 pkt6_udp->spt = htons (src_address->port);
1123 pkt6_udp->dpt = htons (dst_address->port);
1124 pkt6_udp->len = htons ((uint16_t) payload_length);
1127 sum = GNUNET_CRYPTO_crc16_step (sum,
1128 &pkt6->source_address,
1129 sizeof (struct in6_addr) * 2);
1130 uint32_t tmp = htons (len);
1131 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1132 tmp = htonl (pkt6->next_header);
1133 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1134 sum = GNUNET_CRYPTO_crc16_step (sum, pkt6_udp, len);
1135 pkt6_udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1140 struct tcp_packet *pkt6_tcp = (struct tcp_packet *) pkt6;
1142 memcpy (pkt6_tcp, payload, payload_length);
1144 pkt6_tcp->spt = htons (src_address->port);
1145 pkt6_tcp->dpt = htons (dst_address->port);
1148 sum = GNUNET_CRYPTO_crc16_step (sum, &pkt6->source_address,
1149 sizeof (struct in6_addr) * 2);
1150 uint32_t tmp = htonl (len);
1151 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1152 tmp = htonl (pkt6->next_header);
1153 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1154 sum = GNUNET_CRYPTO_crc16_step (sum, pkt6_tcp, len);
1155 pkt6_tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1166 * We've just experienced a connection in use. Track it, or if it is
1167 * already tracked, update the tracking.
1169 * @param u_i IP-level connection tracking state
1170 * @param tunnel associated mesh tunnel
1171 * @param desc service descriptor (or NULL)
1172 * @param serv service information
1175 update_state_map (const struct RedirectInformation *ri,
1176 struct GNUNET_MESH_Tunnel *tunnel,
1177 const GNUNET_HashCode *desc,
1178 struct LocalService *serv)
1180 struct TunnelState *state;
1181 GNUNET_HashCode state_key;
1183 hash_redirect_info (&state_key,
1185 state = GNUNET_CONTAINER_multihashmap_get (connections_map, &state_key);
1188 state = GNUNET_malloc (sizeof (struct TunnelState));
1189 state->tunnel = tunnel;
1190 state->state_key = state_key;
1192 // FIXME? if (NULL != desc) state->desc = *desc;
1193 // FIXME? state->redirect_info = *ri;
1194 GNUNET_assert (GNUNET_OK ==
1195 GNUNET_CONTAINER_multihashmap_put (connections_map, &state_key, state,
1196 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1198 GNUNET_CONTAINER_heap_insert (connections_heap,
1200 GNUNET_TIME_absolute_get ().abs_value);
1204 if (state->tunnel != tunnel)
1206 /* Stats / warning: two tunnels got exactly the same connection state!? */
1207 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1208 _("Two different mesh tunnels got the same connection state. Oops.\n"));
1211 GNUNET_CONTAINER_heap_update_cost (connections_heap,
1213 GNUNET_TIME_absolute_get ().abs_value);
1215 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1217 state = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1218 state->heap_node = NULL;
1219 GNUNET_MESH_tunnel_destroy (state->tunnel);
1220 GNUNET_assert (GNUNET_OK ==
1221 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1224 GNUNET_free (state);
1232 * @param payload payload of the IP header (includes TCP header)
1235 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1236 const struct SocketAddress *source_address,
1237 const void *payload, size_t payload_length)
1241 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header);
1242 switch (source_address->af)
1245 len += sizeof (struct ip4_header);
1248 len += sizeof (struct ip6_header);
1254 len += payload_length;
1255 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1262 struct GNUNET_MessageHeader *hdr;
1263 struct tun_header *tun;
1265 hdr= (struct GNUNET_MessageHeader *) buf;
1266 hdr->type = htons (42);
1267 hdr->size = htons (len);
1268 tun = (struct tun_header*) &hdr[1];
1269 tun->flags = htons (0);
1270 switch (source_address->af)
1274 struct ip4_header * ipv4 = (struct ip4_header*) &tun[1];
1276 tun->proto = htons (ETH_P_IPV4);
1277 prepare_ipv4_packet (payload, payload_length, IPPROTO_TCP,
1279 destination_address,
1285 struct ip6_header * ipv6 = (struct ip6_header*) &tun[1];
1287 tun->proto = htons (ETH_P_IPV6);
1288 prepare_ipv6_packet (payload, payload_length, IPPROTO_TCP,
1290 destination_address,
1298 (void) GNUNET_HELPER_send (helper_handle,
1299 (const struct GNUNET_MessageHeader*) buf,
1307 * The messages are one GNUNET_HashCode for the service followed by a struct tcp_packet
1311 receive_tcp_service (void *unused GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1312 void **tunnel_ctx GNUNET_UNUSED,
1313 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1314 const struct GNUNET_MessageHeader *message,
1315 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1317 struct TunnelState *state = *tunnel_ctx;
1318 // FIXME: write proper request struct (we don't need the descriptor EACH time here!)
1319 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1320 const struct tcp_packet *pkt = (const struct tcp_packet *) &desc[1];
1321 uint16_t pkt_len = ntohs (message->size);
1324 /* check that we got at least a valid header */
1325 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct tcp_packet))
1327 GNUNET_break_op (0);
1330 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1332 if (NULL == state->serv)
1334 /* setup fresh connection */
1335 GNUNET_assert (NULL == state->heap_node);
1336 if (NULL == (state->serv = find_service (tcp_services, desc, ntohs (pkt->dpt))))
1338 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1339 _("No service found for %s on port %d!\n"),
1342 GNUNET_MESH_tunnel_destroy (state->tunnel);
1345 state->ri.remote_address = state->serv->address;
1346 setup_state_record (state);
1348 send_tcp_packet_via_tun (&state->ri.remote_address,
1349 &state->ri.local_address,
1359 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1360 void **tunnel_ctx GNUNET_UNUSED,
1361 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1362 const struct GNUNET_MessageHeader *message,
1363 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1365 struct TunnelState *state = *tunnel_ctx;
1366 // FIXME: write proper request struct (!)
1367 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1368 const struct tcp_packet *pkt = (const struct tcp_packet *) &desc[1];
1369 const struct SocketAddress *s = (const struct SocketAddress *) desc;
1370 uint16_t pkt_len = ntohs (message->size);
1372 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct tcp_packet))
1374 GNUNET_break_op (0);
1377 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1379 if (NULL == state->heap_node)
1381 /* first packet, setup record */
1382 state->ri.remote_address = *s;
1383 setup_state_record (state);
1386 send_tcp_packet_via_tun (&state->ri.remote_address,
1387 &state->ri.local_address,
1395 * @param payload payload of the UDP packet (does NOT include UDP header)
1398 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1399 const struct SocketAddress *source_address,
1400 const void *payload, size_t payload_length)
1404 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header);
1405 switch (source_address->af)
1408 len += sizeof (struct ip4_header);
1411 len += sizeof (struct ip6_header);
1417 len += sizeof (struct udp_packet);
1418 len += payload_length;
1419 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1426 struct GNUNET_MessageHeader *hdr;
1427 struct tun_header *tun;
1429 hdr= (struct GNUNET_MessageHeader *) buf;
1430 hdr->type = htons (42);
1431 hdr->size = htons (len);
1432 tun = (struct tun_header*) &hdr[1];
1433 tun->flags = htons (0);
1434 switch (source_address->af)
1438 struct ip4_header * ipv4 = (struct ip4_header*) &tun[1];
1440 tun->proto = htons (ETH_P_IPV4);
1441 prepare_ipv4_packet (payload, payload_length, IPPROTO_UDP,
1443 destination_address,
1449 struct ip6_header * ipv6 = (struct ip6_header*) &tun[1];
1451 tun->proto = htons (ETH_P_IPV6);
1452 prepare_ipv6_packet (payload, payload_length, IPPROTO_UDP,
1454 destination_address,
1462 (void) GNUNET_HELPER_send (helper_handle,
1463 (const struct GNUNET_MessageHeader*) buf,
1474 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1475 void **tunnel_ctx GNUNET_UNUSED,
1476 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1477 const struct GNUNET_MessageHeader *message,
1478 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1480 struct TunnelState *state = *tunnel_ctx;
1481 // FIXME: write proper request struct (!)
1482 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1483 const struct udp_packet *pkt = (const struct udp_packet *) &desc[1];
1484 const struct SocketAddress *s = (const struct SocketAddress *) desc;
1485 uint16_t pkt_len = ntohs (message->size);
1487 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct udp_packet))
1489 GNUNET_break_op (0);
1492 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1494 if (NULL == state->heap_node)
1496 /* first packet, setup record */
1497 state->ri.remote_address = *s;
1498 setup_state_record (state);
1501 send_udp_packet_via_tun (&state->ri.remote_address,
1502 &state->ri.local_address,
1503 &pkt[1], pkt_len - sizeof (struct udp_packet));
1512 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1514 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1515 const struct GNUNET_MessageHeader *message,
1516 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1518 struct TunnelState *state = *tunnel_ctx;
1519 // FIXME: write proper request struct (we don't need UDP except dpt either!)
1520 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1521 const struct udp_packet *pkt = (const struct udp_packet *) &desc[1];
1522 uint16_t pkt_len = ntohs (message->size);
1525 /* check that we got at least a valid header */
1526 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct udp_packet))
1528 GNUNET_break_op (0);
1531 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1533 GNUNET_assert (ntohs (pkt->len) ==
1534 ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1535 sizeof (GNUNET_HashCode));
1537 if (NULL == state->serv)
1539 /* setup fresh connection */
1540 GNUNET_assert (NULL == state->heap_node);
1541 if (NULL == (state->serv = find_service (udp_services, desc, ntohs (pkt->dpt))))
1543 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1544 _("No service found for %s on port %d!\n"),
1547 GNUNET_MESH_tunnel_destroy (state->tunnel);
1550 state->ri.remote_address = state->serv->address;
1551 setup_state_record (state);
1553 send_udp_packet_via_tun (&state->ri.remote_address,
1554 &state->ri.local_address,
1555 &pkt[1], pkt_len - sizeof (struct udp_packet));
1561 * Callback from GNUNET_MESH for new tunnels.
1563 * @param cls closure
1564 * @param tunnel new handle to the tunnel
1565 * @param initiator peer that started the tunnel
1566 * @param atsi performance information for the tunnel
1567 * @return initial tunnel context for the tunnel
1570 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1571 const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
1572 const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
1574 struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
1582 * Function called by mesh whenever an inbound tunnel is destroyed.
1583 * Should clean up any associated state.
1585 * @param cls closure (set from GNUNET_MESH_connect)
1586 * @param tunnel connection to the other end (henceforth invalid)
1587 * @param tunnel_ctx place where local state associated
1588 * with the tunnel is stored
1591 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
1594 struct TunnelState *s = tunnel_ctx;
1595 struct TunnelMessageQueue *tnq;
1597 while (NULL != (tnq = s->head))
1599 GNUNET_CONTAINER_DLL_remove (s->head,
1604 if (s->heap_node != NULL)
1606 GNUNET_assert (GNUNET_YES ==
1607 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1610 GNUNET_CONTAINER_heap_remove_node (s->heap_node);
1611 s->heap_node = NULL;
1615 GNUNET_MESH_notify_transmit_ready_cancel (s->th);
1623 * Function that frees everything from a hashmap
1627 * @param value value to free
1630 free_iterate (void *cls GNUNET_UNUSED,
1631 const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
1633 GNUNET_free (value);
1639 * Function scheduled as very last function, cleans up after us
1642 cleanup (void *cls GNUNET_UNUSED,
1643 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1647 if (helper_handle != NULL)
1649 GNUNET_HELPER_stop (helper_handle);
1650 helper_handle = NULL;
1652 if (mesh_handle != NULL)
1654 GNUNET_MESH_disconnect (mesh_handle);
1657 if (NULL != connections_map)
1659 GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
1660 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
1661 connections_map = NULL;
1663 if (NULL != connections_heap)
1665 GNUNET_CONTAINER_heap_destroy (connections_heap);
1666 connections_heap = NULL;
1668 if (NULL != tcp_services)
1670 GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
1671 GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
1672 tcp_services = NULL;
1674 if (NULL != udp_services)
1676 GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
1677 GNUNET_CONTAINER_multihashmap_destroy (udp_services);
1678 udp_services = NULL;
1681 GNUNET_free_non_null (exit_argv[i]);
1686 * Add services to the service map.
1688 * @param proto IPPROTO_TCP or IPPROTO_UDP
1689 * @param cpy copy of the service descriptor (can be mutilated)
1690 * @param name DNS name of the service
1693 add_services (int proto,
1700 struct LocalService *serv;
1702 for (redirect = strtok (cpy, " "); redirect != NULL;
1703 redirect = strtok (NULL, " "))
1705 if (NULL == (hostname = strstr (redirect, ":")))
1707 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1708 "option `%s' for domain `%s' is not formatted correctly!\n",
1715 if (NULL == (hostport = strstr (hostname, ":")))
1717 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1718 "option `%s' for domain `%s' is not formatted correctly!\n",
1726 int local_port = atoi (redirect);
1727 int remote_port = atoi (hostport);
1729 if (!((local_port > 0) && (local_port < 65536)))
1731 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1732 "`%s' is not a valid port number (for domain `%s')!", redirect,
1736 if (!((remote_port > 0) && (remote_port < 65536)))
1738 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1739 "`%s' is not a valid port number (for domain `%s')!", hostport,
1744 serv = GNUNET_malloc (sizeof (struct LocalService));
1745 serv->my_port = (uint16_t) local_port;
1746 serv->address.port = remote_port;
1747 if (0 == strcmp ("localhost4", hostname))
1749 const char *ip4addr = exit_argv[4];
1751 serv->address.af = AF_INET;
1752 GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
1754 else if (0 == strcmp ("localhost6", hostname))
1756 const char *ip6addr = exit_argv[2];
1758 serv->address.af = AF_INET6;
1759 GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
1763 struct addrinfo *res;
1766 ret = getaddrinfo (hostname, NULL, NULL, &res);
1767 if ( (ret != 0) || (res == NULL) )
1769 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1770 _("No addresses found for hostname `%s' of service `%s'!\n"),
1777 serv->address.af = res->ai_family;
1778 switch (res->ai_family)
1781 serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
1784 serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
1788 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1789 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
1797 store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
1806 * Reads the configuration servicecfg and populates udp_services
1809 * @param section name of section in config, equal to hostname
1812 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
1816 if ((strlen (section) < 8) ||
1817 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1820 GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1823 add_services (IPPROTO_UDP, cpy, section);
1827 GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1830 add_services (IPPROTO_TCP, cpy, section);
1837 * @brief Main function that will be run by the scheduler.
1839 * @param cls closure
1840 * @param args remaining command-line arguments
1841 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1842 * @param cfg_ configuration
1845 run (void *cls, char *const *args GNUNET_UNUSED,
1846 const char *cfgfile GNUNET_UNUSED,
1847 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1849 static struct GNUNET_MESH_MessageHandler handlers[] = {
1850 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP, 0},
1851 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP, 0},
1857 static GNUNET_MESH_ApplicationType apptypes[] = {
1858 GNUNET_APPLICATION_TYPE_END,
1859 GNUNET_APPLICATION_TYPE_END,
1860 GNUNET_APPLICATION_TYPE_END
1862 unsigned int handler_idx;
1863 unsigned int app_idx;
1875 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1877 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
1879 max_connections = 1024;
1880 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
1881 if (GNUNET_SYSERR ==
1882 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname))
1884 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1885 "No entry 'IFNAME' in configuration!\n");
1886 GNUNET_SCHEDULER_shutdown ();
1889 exit_argv[1] = ifname;
1890 if ( (GNUNET_SYSERR ==
1891 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
1893 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1895 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1896 "No valid entry 'IPV6ADDR' in configuration!\n");
1897 GNUNET_SCHEDULER_shutdown ();
1900 exit_argv[2] = ipv6addr;
1901 if (GNUNET_SYSERR ==
1902 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
1905 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1906 "No entry 'IPV6PREFIX' in configuration!\n");
1907 GNUNET_SCHEDULER_shutdown ();
1910 exit_argv[3] = ipv6prefix_s;
1912 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
1915 (ipv6prefix >= 127) )
1917 GNUNET_SCHEDULER_shutdown ();
1921 if ( (GNUNET_SYSERR ==
1922 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
1924 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1926 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1927 "No valid entry for 'IPV4ADDR' in configuration!\n");
1928 GNUNET_SCHEDULER_shutdown ();
1931 exit_argv[4] = ipv4addr;
1932 if ( (GNUNET_SYSERR ==
1933 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
1935 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1937 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1938 "No valid entry 'IPV4MASK' in configuration!\n");
1939 GNUNET_SCHEDULER_shutdown ();
1942 exit_argv[5] = ipv4mask;
1943 exit_argv[6] = NULL;
1947 udp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_UDP");
1948 tcp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_TCP");
1949 if (GNUNET_YES == udp)
1951 handlers[handler_idx].callback = &receive_udp_remote;
1952 handlers[handler_idx].expected_size = 0;
1953 handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP;
1954 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
1959 if (GNUNET_YES == tcp)
1961 handlers[handler_idx].callback = &receive_tcp_remote;
1962 handlers[handler_idx].expected_size = 0;
1963 handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP;
1964 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
1968 udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1969 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1970 GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
1972 connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
1973 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1975 = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL,
1977 &clean_tunnel, handlers,
1979 if (NULL == mesh_handle)
1981 GNUNET_SCHEDULER_shutdown ();
1984 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn",
1986 &message_token, NULL);
1993 * @param argc number of arguments from the command line
1994 * @param argv command line arguments
1995 * @return 0 ok, 1 on error
1998 main (int argc, char *const *argv)
2000 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
2001 GNUNET_GETOPT_OPTION_END
2004 return (GNUNET_OK ==
2005 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
2007 ("Daemon to run to provide an IP exit node for the VPN"),
2008 options, &run, NULL)) ? 0 : 1;
2012 /* end of gnunet-daemon-exit.c */