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 #include <gnunet_common.h>
29 #include <gnunet_program_lib.h>
30 #include <gnunet_protocols.h>
31 #include <gnunet_applications.h>
32 #include <gnunet_mesh_service.h>
33 #include <gnunet_constants.h>
37 /* see http://www.iana.org/assignments/ethernet-numbers */
39 #define ETH_P_IPV4 0x0800
43 #define ETH_P_IPV6 0x86DD
47 GNUNET_NETWORK_STRUCT_BEGIN
49 * Header from Linux TUN interface.
54 * Some flags (unused).
59 * Here we get an ETH_P_-number.
65 * Standard IPv4 header.
69 unsigned header_length:4 GNUNET_PACKED;
70 unsigned version:4 GNUNET_PACKED;
72 uint16_t total_length GNUNET_PACKED;
73 uint16_t identification GNUNET_PACKED;
74 unsigned flags:3 GNUNET_PACKED;
75 unsigned fragmentation_offset:13 GNUNET_PACKED;
78 uint16_t checksum GNUNET_PACKED;
79 struct in_addr source_address GNUNET_PACKED;
80 struct in_addr destination_address GNUNET_PACKED;
84 * Standard IPv6 header.
88 unsigned traffic_class_h:4 GNUNET_PACKED;
89 unsigned version:4 GNUNET_PACKED;
90 unsigned traffic_class_l:4 GNUNET_PACKED;
91 unsigned flow_label:20 GNUNET_PACKED;
92 uint16_t payload_length GNUNET_PACKED;
95 struct in6_addr source_address GNUNET_PACKED;
96 struct in6_addr destination_address GNUNET_PACKED;
99 #define TCP_FLAG_SYN 2
103 unsigned spt:16 GNUNET_PACKED;
104 unsigned dpt:16 GNUNET_PACKED;
105 unsigned seq:32 GNUNET_PACKED;
106 unsigned ack:32 GNUNET_PACKED;
107 unsigned off:4 GNUNET_PACKED;
108 unsigned rsv:4 GNUNET_PACKED;
109 unsigned flg:8 GNUNET_PACKED;
110 unsigned wsz:16 GNUNET_PACKED;
111 unsigned crc:16 GNUNET_PACKED;
112 unsigned urg:16 GNUNET_PACKED;
120 uint16_t spt GNUNET_PACKED;
121 uint16_t dpt GNUNET_PACKED;
122 uint16_t len GNUNET_PACKED;
123 uint16_t crc GNUNET_PACKED;
131 uint16_t id GNUNET_PACKED;
132 uint16_t flags GNUNET_PACKED;
133 uint16_t qdcount GNUNET_PACKED;
134 uint16_t ancount GNUNET_PACKED;
135 uint16_t nscount GNUNET_PACKED;
136 uint16_t arcount GNUNET_PACKED;
138 GNUNET_NETWORK_STRUCT_END
141 * Information about an address.
146 * AF_INET or AF_INET6.
151 * Remote address information.
156 * Address, if af is AF_INET.
161 * Address, if af is AF_INET6.
163 struct in6_addr ipv6;
167 * IPPROTO_TCP or IPPROTO_UDP;
172 * Remote port, in host byte order!
179 * This struct is saved into the services-hashmap to represent
180 * a service this peer is specifically offering an exit for
181 * (for a specific domain name).
187 * Remote address to use for the service.
189 struct SocketAddress address;
192 * DNS name of the service.
197 * Port I am listening on within GNUnet for this service, in host
198 * byte order. (as we may redirect ports).
205 * Information we use to track a connection (the classical 6-tuple of
206 * IP-version, protocol, source-IP, destination-IP, source-port and
209 struct RedirectInformation
213 * Address information for the other party (equivalent of the
214 * arguments one would give to "connect").
216 struct SocketAddress remote_address;
219 * Address information we used locally (AF and proto must match
220 * "remote_address"). Equivalent of the arguments one would give to
223 struct SocketAddress local_address;
226 Note 1: additional information might be added here in the
227 future to support protocols that require special handling,
230 Note 2: we might also sometimes not match on all components
231 of the tuple, to support protocols where things do not always
238 * Queue of messages to a tunnel.
240 struct TunnelMessageQueue
243 * This is a doubly-linked list.
245 struct TunnelMessageQueue *next;
248 * This is a doubly-linked list.
250 struct TunnelMessageQueue *prev;
253 * Payload to send via the tunnel.
258 * Number of bytes in 'payload'.
265 * This struct is saved into connections_map to allow finding the
266 * right tunnel given an IP packet from TUN. It is also associated
267 * with the tunnel's closure so we can find it again for the next
268 * message from the tunnel.
273 * Mesh tunnel that is used for this connection.
275 struct GNUNET_MESH_Tunnel *tunnel;
278 * Heap node for this state in the connections_heap.
280 struct GNUNET_CONTAINER_HeapNode *heap_node;
283 * Key this state has in the connections_map.
285 GNUNET_HashCode state_key;
288 * Associated service record, or NULL for no service.
290 struct LocalService *serv;
293 * Head of DLL of messages for this tunnel.
295 struct TunnelMessageQueue *head;
298 * Tail of DLL of messages for this tunnel.
300 struct TunnelMessageQueue *tail;
303 * Active tunnel transmission request (or NULL).
305 struct GNUNET_MESH_TransmitHandle *th;
308 * Primary redirection information for this connection.
310 struct RedirectInformation ri;
316 * The handle to the configuration used throughout the process
318 static const struct GNUNET_CONFIGURATION_Handle *cfg;
321 * The handle to the helper
323 static struct GNUNET_HELPER_Handle *helper_handle;
326 * Arguments to the exit helper.
328 static char *exit_argv[7];
331 * IPv6 prefix (0..127) from configuration file.
333 static unsigned long long ipv6prefix;
338 static struct GNUNET_MESH_Handle *mesh_handle;
341 * This hashmaps contains the mapping from peer, service-descriptor,
342 * source-port and destination-port to a struct TunnelState
344 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
347 * Heap so we can quickly find "old" connections.
349 static struct GNUNET_CONTAINER_Heap *connections_heap;
352 * If there are at least this many connections, old ones will be removed
354 static long long unsigned int max_connections = 200;
357 * This hashmaps saves interesting things about the configured UDP services
359 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
362 * This hashmaps saves interesting things about the configured TCP services
364 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
368 * Given IP information about a connection, calculate the respective
369 * hash we would use for the 'connections_map'.
371 * @param hash resulting hash
372 * @param ri information about the connection
375 hash_redirect_info (GNUNET_HashCode *hash,
376 const struct RedirectInformation *ri)
380 memset (hash, 0, sizeof (GNUNET_HashCode));
381 /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
382 so we put the IP address in there (and hope for few collisions) */
384 switch (ri->remote_address.af)
387 memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
388 off += sizeof (struct in_addr);
391 memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
392 off += sizeof (struct in_addr);
397 memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
398 off += sizeof (uint16_t);
399 switch (ri->local_address.af)
402 memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr));
403 off += sizeof (struct in_addr);
406 memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr));
407 off += sizeof (struct in_addr);
412 memcpy (off, &ri->local_address.port, sizeof (uint16_t));
413 off += sizeof (uint16_t);
414 memcpy (off, &ri->remote_address.proto, sizeof (uint8_t));
415 off += sizeof (uint8_t);
420 * Get our connection tracking state. Warns if it does not exists,
421 * refreshes the timestamp if it does exist.
423 * @param af address family
424 * @param protocol IPPROTO_UDP or IPPROTO_TCP
425 * @param destination_ip target IP
426 * @param destination_port target port
427 * @param local_ip local IP
428 * @param local_port local port
429 * @param state_key set to hash's state if non-NULL
430 * @return NULL if we have no tracking information for this tuple
432 static struct TunnelState *
433 get_redirect_state (int af,
435 const void *destination_ip,
436 uint16_t destination_port,
437 const void *local_ip,
439 GNUNET_HashCode *state_key)
441 struct RedirectInformation ri;
443 struct TunnelState *state;
445 ri.remote_address.af = af;
447 ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
449 ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
450 ri.remote_address.port = destination_port;
451 ri.remote_address.proto = protocol;
452 ri.local_address.af = af;
454 ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
456 ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
457 ri.local_address.port = local_port;
458 ri.local_address.proto = protocol;
459 hash_redirect_info (&key, &ri);
460 if (NULL != state_key)
462 state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key);
465 /* Mark this connection as freshly used */
466 if (NULL == state_key)
467 GNUNET_CONTAINER_heap_update_cost (connections_heap,
469 GNUNET_TIME_absolute_get ().abs_value);
475 * Given a service descriptor and a destination port, find the
476 * respective service entry.
478 * @param service_map map of services (TCP or UDP)
479 * @param desc service descriptor
480 * @param dpt destination port
481 * @return NULL if we are not aware of such a service
483 static struct LocalService *
484 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
485 const GNUNET_HashCode *desc,
488 char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
490 memcpy (&key[0], &dpt, sizeof (uint16_t));
491 memcpy (&key[sizeof(uint16_t)], desc, sizeof (GNUNET_HashCode));
492 return GNUNET_CONTAINER_multihashmap_get (service_map,
493 (GNUNET_HashCode *) key);
498 * Free memory associated with a service record.
501 * @param key service descriptor
502 * @param value service record to free
506 free_service_record (void *cls,
507 const GNUNET_HashCode *key,
510 struct LocalService *service = value;
512 GNUNET_free_non_null (service->name);
513 GNUNET_free (service);
519 * Given a service descriptor and a destination port, find the
520 * respective service entry.
522 * @param service_map map of services (TCP or UDP)
523 * @param name name of the service
524 * @param dpt destination port
525 * @param service service information record to store (service->name will be set).
528 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
531 struct LocalService *service)
533 char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
534 GNUNET_HashCode desc;
536 GNUNET_CRYPTO_hash (name, strlen (name) + 1, &desc);
537 service->name = GNUNET_strdup (name);
538 memcpy (&key[0], &dpt, sizeof (uint16_t));
539 memcpy (&key[sizeof(uint16_t)], &desc, sizeof (GNUNET_HashCode));
541 GNUNET_CONTAINER_multihashmap_put (service_map,
542 (GNUNET_HashCode *) key,
544 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
546 free_service_record (NULL, (GNUNET_HashCode *) key, service);
547 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
548 _("Got duplicate service records for `%s:%u'\n"),
556 * MESH is ready to receive a message for the tunnel. Transmit it.
558 * @param cls the 'struct TunnelState'.
559 * @param size number of bytes available in buf
560 * @param buf where to copy the message
561 * @return number of bytes copied to buf
564 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
566 struct TunnelState *s = cls;
567 struct GNUNET_MESH_Tunnel *tunnel = s->tunnel;
568 struct TunnelMessageQueue *tnq;
572 GNUNET_assert (size >= tnq->len);
573 memcpy (buf, tnq->payload, tnq->len);
575 GNUNET_CONTAINER_DLL_remove (s->head,
579 if (NULL != (tnq = s->head))
580 s->th = GNUNET_MESH_notify_transmit_ready (tunnel,
581 GNUNET_NO /* corking */,
583 GNUNET_TIME_UNIT_FOREVER_REL,
586 &send_to_peer_notify_callback,
593 * Send the given packet via the mesh tunnel.
595 * @param mesh_tunnel destination
596 * @param payload message to transmit
597 * @param payload_length number of bytes in payload
598 * @param desc descriptor to add before payload (optional)
599 * @param mtype message type to use
602 send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
604 size_t payload_length,
605 const GNUNET_HashCode *desc,
608 struct TunnelState *s;
609 struct TunnelMessageQueue *tnq;
610 struct GNUNET_MessageHeader *msg;
614 len = sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + payload_length;
615 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
620 tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + len);
621 tnq->payload = &tnq[1];
623 msg = (struct GNUNET_MessageHeader *) &tnq[1];
624 msg->size = htons ((uint16_t) len);
625 msg->type = htons (mtype);
628 dp = (GNUNET_HashCode *) &msg[1];
630 memcpy (&dp[1], payload, payload_length);
634 memcpy (&msg[1], payload, payload_length);
636 s = GNUNET_MESH_tunnel_get_data (mesh_tunnel);
637 GNUNET_assert (NULL != s);
638 GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, tnq);
640 s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, 0 /* priority */,
641 GNUNET_TIME_UNIT_FOREVER_REL,
643 &send_to_peer_notify_callback,
649 * @brief Handles an UDP packet received from the helper.
651 * @param udp A pointer to the Packet
652 * @param pktlen number of bytes in 'udp'
653 * @param af address family (AFINET or AF_INET6)
654 * @param destination_ip destination IP-address of the IP packet (should
655 * be our local address)
656 * @param source_ip original source IP-address of the IP packet (should
657 * be the original destination address)
660 udp_from_helper (const struct udp_packet *udp,
663 const void *destination_ip,
664 const void *source_ip)
666 struct TunnelState *state;
668 if (pktlen < sizeof (struct udp_packet))
674 if (pktlen != ntohs (udp->len))
680 state = get_redirect_state (af, IPPROTO_UDP,
688 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
689 _("Packet dropped, have no matching connection information\n"));
692 send_packet_to_mesh_tunnel (state->tunnel,
693 &udp[1], pktlen - sizeof (struct udp_packet),
696 ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK
697 : GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
702 * @brief Handles a TCP packet received from the helper.
704 * @param tcp A pointer to the Packet
705 * @param pktlen the length of the packet, including its header
706 * @param af address family (AFINET or AF_INET6)
707 * @param destination_ip destination IP-address of the IP packet (should
708 * be our local address)
709 * @param source_ip original source IP-address of the IP packet (should
710 * be the original destination address)
713 tcp_from_helper (const struct tcp_packet *tcp,
716 const void *destination_ip,
717 const void *source_ip)
719 struct TunnelState *state;
721 struct tcp_packet *mtcp;
723 if (pktlen < sizeof (struct tcp_packet))
729 state = get_redirect_state (af, IPPROTO_TCP,
737 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
738 _("Packet dropped, have no matching connection information\n"));
742 /* mug port numbers and crc to avoid information leakage;
743 sender will need to lookup the correct values anyway */
744 memcpy (buf, tcp, pktlen);
745 mtcp = (struct tcp_packet *) buf;
749 send_packet_to_mesh_tunnel (state->tunnel,
753 ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK
754 : GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
759 * Receive packets from the helper-process
762 * @param client unsued
763 * @param message message received from helper
766 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
767 const struct GNUNET_MessageHeader *message)
769 const struct tun_header *pkt_tun;
772 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
777 size = ntohs (message->size);
778 if (size < sizeof (struct tun_header) + sizeof (struct GNUNET_MessageHeader))
783 pkt_tun = (const struct tun_header *) &message[1];
784 size -= sizeof (struct tun_header) + sizeof (struct GNUNET_MessageHeader);
785 switch (ntohs (pkt_tun->proto))
789 const struct ip6_header *pkt6;
791 if (size < sizeof (struct ip6_header))
793 /* Kernel to blame? */
797 pkt6 = (struct ip6_header *) &pkt_tun[1];
798 if (size != ntohs (pkt6->payload_length))
800 /* Kernel to blame? */
804 size -= sizeof (struct ip6_header);
805 switch (pkt6->next_header)
808 udp_from_helper ((const struct udp_packet *) &pkt6[1], size,
810 &pkt6->destination_address,
811 &pkt6->source_address);
814 tcp_from_helper ((const struct tcp_packet *) &pkt6[1], size,
816 &pkt6->destination_address,
817 &pkt6->source_address);
820 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
821 _("IPv6 packet with unsupported next header received. Ignored.\n"));
828 const struct ip4_header *pkt4;
830 if (size < sizeof (struct ip4_header))
832 /* Kernel to blame? */
836 pkt4 = (const struct ip4_header *) &pkt_tun[1];
837 if (size != ntohs (pkt4->total_length))
839 /* Kernel to blame? */
843 if (pkt4->header_length * 4 != sizeof (struct ip4_header))
845 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
846 _("IPv4 packet options received. Ignored.\n"));
849 size -= sizeof (struct ip4_header);
850 switch (pkt4->protocol)
853 udp_from_helper ((const struct udp_packet *) &pkt4[1], size,
855 &pkt4->destination_address,
856 &pkt4->source_address);
858 tcp_from_helper ((const struct tcp_packet *) &pkt4[1], size,
860 &pkt4->destination_address,
861 &pkt4->source_address);
864 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
865 _("IPv4 packet with unsupported next header received. Ignored.\n"));
871 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
872 _("Packet from unknown protocol %u received. Ignored.\n"),
873 ntohs (pkt_tun->proto));
880 * We need to create a (unique) fresh local address (IP+port).
883 * @param af desired address family
884 * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
885 * @param local_address address to initialize
888 setup_fresh_address (int af,
890 struct SocketAddress *local_address)
896 const char *ipv4addr = exit_argv[4];
897 const char *ipv4mask = exit_argv[5];
901 GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &tmp));
902 GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &tmp2));
904 /* This should be a noop */
906 tmp |= ntohl (*((uint32_t *) /*tunnel*/ 42)) & (~tmp2);
908 // pkt4->source_address.s_addr = tmp;
913 const char *ipv6addr = exit_argv[2];
914 /* Generate a new src-address
915 * This takes as much from the address of the tunnel as fits into
917 unsigned long long ipv6prefix_r = (ipv6prefix + 7) / 8;
918 inet_pton (AF_INET6, ipv6addr, &local_address->address.ipv6);
919 if (ipv6prefix_r < (16 - sizeof (void *)))
920 ipv6prefix_r = 16 - sizeof (void *);
922 unsigned int offset = ipv6prefix_r - (16 - sizeof (void *));
923 // memcpy ((((char *) &pkt6->source_address)) + ipv6prefix_r, ((char *) &tunnel) + offset, 16 - ipv6prefix_r);
937 setup_state_record (struct TunnelState *state)
940 struct TunnelState *s;
942 /* generate fresh, unique address */
945 setup_fresh_address (state->serv->address.af,
946 state->serv->address.proto,
947 &state->ri.local_address);
948 } while (NULL != get_redirect_state (state->serv->address.af,
950 &state->ri.remote_address.address,
951 state->ri.remote_address.port,
952 &state->ri.local_address.address,
953 state->ri.local_address.port,
955 GNUNET_assert (GNUNET_OK ==
956 GNUNET_CONTAINER_multihashmap_put (connections_map,
958 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
959 state->heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
961 GNUNET_TIME_absolute_get ().abs_value);
962 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
964 s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
965 GNUNET_assert (state != s);
967 GNUNET_MESH_tunnel_destroy (s->tunnel);
968 GNUNET_assert (GNUNET_OK ==
969 GNUNET_CONTAINER_multihashmap_remove (connections_map,
981 prepare_ipv4_packet (const void *payload, size_t payload_length,
983 const struct SocketAddress *src_address,
984 const struct SocketAddress *dst_address,
985 struct ip4_header *pkt4)
989 len = payload_length;
993 len += sizeof (struct udp_packet);
996 /* tcp_header (with port/crc not set) must be part of payload! */
997 if (len < sizeof (struct tcp_packet))
1007 if (len + sizeof (struct ip4_header) > UINT16_MAX)
1014 pkt4->header_length = sizeof (struct ip4_header) / 4;
1015 pkt4->diff_serv = 0;
1016 pkt4->total_length = htons ((uint16_t) (sizeof (struct ip4_header) + len));
1017 pkt4->identification = 0; // FIXME: pick at random!
1019 pkt4->fragmentation_offset = 0;
1021 pkt4->protocol = protocol;
1023 pkt4->destination_address = dst_address->address.ipv4;
1024 pkt4->source_address = src_address->address.ipv4;
1025 pkt4->checksum = GNUNET_CRYPTO_crc16_n (pkt4, sizeof (struct ip4_header));
1031 struct udp_packet *pkt4_udp = (struct udp_packet *) &pkt4[1];
1033 pkt4_udp->spt = htons (src_address->port);
1034 pkt4_udp->dpt = htons (dst_address->port);
1035 pkt4_udp->crc = 0; /* Optional for IPv4 */
1036 pkt4_udp->len = htons ((uint16_t) payload_length);
1037 memcpy (&pkt4_udp[1], payload, payload_length);
1042 struct tcp_packet *pkt4_tcp = (struct tcp_packet *) &pkt4[1];
1044 memcpy (pkt4_tcp, payload, payload_length);
1045 pkt4_tcp->spt = htons (src_address->port);
1046 pkt4_tcp->dpt = htons (dst_address->port);
1049 sum = GNUNET_CRYPTO_crc16_step (sum,
1050 &pkt4->source_address,
1051 sizeof (struct in_addr) * 2);
1052 uint32_t tmp = htonl ((protocol << 16) | (0xffff & len));
1053 sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, sizeof (uint32_t));
1054 sum = GNUNET_CRYPTO_crc16_step (sum, & pkt4_tcp, len);
1055 pkt4_tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1068 prepare_ipv6_packet (const void *payload, size_t payload_length,
1070 const struct SocketAddress *src_address,
1071 const struct SocketAddress *dst_address,
1072 struct ip6_header *pkt6)
1076 len = payload_length;
1080 len += sizeof (struct udp_packet);
1083 /* tcp_header (with port/crc not set) must be part of payload! */
1084 if (len < sizeof (struct tcp_packet))
1094 if (len > UINT16_MAX)
1101 pkt6->next_header = protocol;
1102 pkt6->payload_length = htons ((uint16_t) (len + sizeof (struct ip6_header)));
1103 pkt6->hop_limit = 255;
1104 pkt6->destination_address = dst_address->address.ipv6;
1105 pkt6->source_address = src_address->address.ipv6;
1111 struct udp_packet *pkt6_udp = (struct udp_packet *) &pkt6[1];
1113 memcpy (&pkt6[1], payload, payload_length);
1115 pkt6_udp->spt = htons (src_address->port);
1116 pkt6_udp->dpt = htons (dst_address->port);
1117 pkt6_udp->len = htons ((uint16_t) payload_length);
1120 sum = GNUNET_CRYPTO_crc16_step (sum,
1121 &pkt6->source_address,
1122 sizeof (struct in6_addr) * 2);
1123 uint32_t tmp = htons (len);
1124 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1125 tmp = htonl (pkt6->next_header);
1126 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1127 sum = GNUNET_CRYPTO_crc16_step (sum, pkt6_udp, len);
1128 pkt6_udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1133 struct tcp_packet *pkt6_tcp = (struct tcp_packet *) pkt6;
1135 memcpy (pkt6_tcp, payload, payload_length);
1137 pkt6_tcp->spt = htons (src_address->port);
1138 pkt6_tcp->dpt = htons (dst_address->port);
1141 sum = GNUNET_CRYPTO_crc16_step (sum, &pkt6->source_address,
1142 sizeof (struct in6_addr) * 2);
1143 uint32_t tmp = htonl (len);
1144 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1145 tmp = htonl (pkt6->next_header);
1146 sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
1147 sum = GNUNET_CRYPTO_crc16_step (sum, pkt6_tcp, len);
1148 pkt6_tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1159 * We've just experienced a connection in use. Track it, or if it is
1160 * already tracked, update the tracking.
1162 * @param u_i IP-level connection tracking state
1163 * @param tunnel associated mesh tunnel
1164 * @param desc service descriptor (or NULL)
1165 * @param serv service information
1168 update_state_map (const struct RedirectInformation *ri,
1169 struct GNUNET_MESH_Tunnel *tunnel,
1170 const GNUNET_HashCode *desc,
1171 struct LocalService *serv)
1173 struct TunnelState *state;
1174 GNUNET_HashCode state_key;
1176 hash_redirect_info (&state_key,
1178 state = GNUNET_CONTAINER_multihashmap_get (connections_map, &state_key);
1181 state = GNUNET_malloc (sizeof (struct TunnelState));
1182 state->tunnel = tunnel;
1183 state->state_key = state_key;
1185 // FIXME? if (NULL != desc) state->desc = *desc;
1186 // FIXME? state->redirect_info = *ri;
1187 GNUNET_assert (GNUNET_OK ==
1188 GNUNET_CONTAINER_multihashmap_put (connections_map, &state_key, state,
1189 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1191 GNUNET_CONTAINER_heap_insert (connections_heap,
1193 GNUNET_TIME_absolute_get ().abs_value);
1197 if (state->tunnel != tunnel)
1199 /* Stats / warning: two tunnels got exactly the same connection state!? */
1200 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1201 _("Two different mesh tunnels got the same connection state. Oops.\n"));
1204 GNUNET_CONTAINER_heap_update_cost (connections_heap,
1206 GNUNET_TIME_absolute_get ().abs_value);
1208 while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1210 state = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1211 state->heap_node = NULL;
1212 GNUNET_MESH_tunnel_destroy (state->tunnel);
1213 GNUNET_assert (GNUNET_OK ==
1214 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1217 GNUNET_free (state);
1225 * The messages are one GNUNET_HashCode for the service followed by a struct tcp_packet
1228 receive_tcp_service (void *unused GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1229 void **tunnel_ctx GNUNET_UNUSED,
1230 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1231 const struct GNUNET_MessageHeader *message,
1232 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1235 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1236 const struct tcp_packet *pkt = (const struct tcp_packet *) &desc[1];
1237 uint16_t pkt_len = ntohs (message->size);
1238 struct LocalService *serv;
1239 struct RedirectInformation u_i;
1240 GNUNET_HashCode state_key;
1242 /* check that we got at least a valid header */
1243 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct tcp_packet))
1245 GNUNET_break_op (0);
1248 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1250 if (NULL == (serv = find_service (tcp_services, desc, ntohs (pkt->dpt))))
1252 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1253 _("No service found for %s on port %d!\n"),
1258 pkt->dpt = htons (serv->remote_port);
1260 /* At this point it would be possible to check against some kind of ACL. */
1262 switch (serv->version)
1267 sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header) +
1268 sizeof (struct ip4_header) + pkt_len;
1270 struct tun_header *hdr;
1271 struct GNUNET_MessageHeader *mhdr;
1273 memset (buf, 0, len);
1274 mhdr = (struct GNUNET_MessageHeader*) buf;
1275 hdr = (struct tun_header *) &mhdr[1];
1276 mhdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1277 mhdr->size = htons (len);
1279 hdr->proto = htons (0x0800);
1280 prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v4.ip4address,
1281 tunnel, &u_i, (struct ip4_header *) &hdr[1]);
1282 /* FIXME: here, flow-control with mesh would be nice to have... */
1283 (void) GNUNET_HELPER_send (helper_handle,
1292 sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header) +
1293 sizeof (struct ip6_header) + pkt_len;
1295 struct tun_header *hdr;
1296 struct GNUNET_MessageHeader *mhdr;
1298 memset (buf, 0, len);
1299 mhdr = (struct GNUNET_MessageHeader*) buf;
1300 hdr = (struct tun_header *) &mhdr[1];
1301 mhdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1302 mhdr->size = htons (len);
1304 hdr->proto = htons (0x86dd);
1305 prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v6.ip6address,
1306 tunnel, &u_i, (struct ip6_header *) buf);
1307 /* FIXME: here, flow-control with mesh would be nice to have... */
1308 (void) GNUNET_HELPER_send (helper_handle,
1309 (const struct GNUNET_MessageHeader*) buf,
1321 update_state_map (&u_i, desc, tunnel, serv);
1328 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1329 void **tunnel_ctx GNUNET_UNUSED,
1330 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1331 const struct GNUNET_MessageHeader *message,
1332 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1336 GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
1337 struct tcp_packet *pkt = (struct tcp_packet *) (desc + 1);
1338 struct remote_addr *s = (struct remote_addr *) desc;
1342 ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1343 sizeof (GNUNET_HashCode);
1345 struct TunnelState *state = GNUNET_malloc (sizeof (struct TunnelState));
1347 state->tunnel = tunnel;
1348 state->type = REMOTE;
1349 state->hashmap = tcp_connections;
1350 memcpy (&state->remote, s, sizeof (struct remote_addr));
1352 hash_redirect_info (&state->hash, &state->redirect_info, s->addrlen);
1355 GNUNET_CONTAINER_multihashmap_contains (tcp_connections, &state->hash))
1357 GNUNET_CONTAINER_multihashmap_put (tcp_connections, &state->hash, state,
1358 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1361 GNUNET_CONTAINER_heap_insert (tcp_connections_heap, state,
1362 GNUNET_TIME_absolute_get ().abs_value);
1364 if (GNUNET_CONTAINER_heap_get_size (tcp_connections_heap) >
1365 max_tcp_connections)
1366 GNUNET_SCHEDULER_add_now (collect_connections, tcp_connections_heap);
1369 GNUNET_free (state);
1374 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
1375 sizeof (struct ip6_hdr) + pkt_len;
1378 memset (buf, 0, len);
1383 prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &s->addr, tunnel,
1384 state, (struct ip4_header *) buf);
1387 prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &s->addr, tunnel,
1388 state, (struct ip6_header *) buf);
1391 GNUNET_free (state);
1392 return GNUNET_SYSERR;
1395 /* FIXME: here, flow-control with mesh would be nice to have... */
1396 (void) GNUNET_HELPER_send (helper_handle,
1397 (const struct GNUNET_MessageHeader*) buf,
1412 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1413 const struct SocketAddress *source_address,
1414 const void *payload, size_t payload_length)
1418 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header);
1419 switch (source_address->af)
1422 len += sizeof (struct ip4_header);
1425 len += sizeof (struct ip6_header);
1431 len += sizeof (struct udp_packet);
1432 len += payload_length;
1433 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1440 struct GNUNET_MessageHeader *hdr;
1441 struct tun_header *tun;
1443 hdr= (struct GNUNET_MessageHeader *) buf;
1444 hdr->type = htons (42);
1445 hdr->size = htons (len);
1446 tun = (struct tun_header*) &hdr[1];
1447 tun->flags = htons (0);
1448 switch (source_address->af)
1452 struct ip4_header * ipv4 = (struct ip4_header*) &tun[1];
1454 tun->proto = htons (ETH_P_IPV4);
1455 prepare_ipv4_packet (payload, payload_length, IPPROTO_UDP,
1457 destination_address,
1463 struct ip6_header * ipv6 = (struct ip6_header*) &tun[1];
1465 tun->proto = htons (ETH_P_IPV6);
1466 prepare_ipv6_packet (payload, payload_length, IPPROTO_UDP,
1468 destination_address,
1476 (void) GNUNET_HELPER_send (helper_handle,
1477 (const struct GNUNET_MessageHeader*) buf,
1490 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1491 void **tunnel_ctx GNUNET_UNUSED,
1492 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1493 const struct GNUNET_MessageHeader *message,
1494 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1496 struct TunnelState *state = *tunnel_ctx;
1497 // FIXME: write proper request struct (!)
1498 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1499 const struct udp_packet *pkt = (const struct udp_packet *) &desc[1];
1500 const struct SocketAddress *s = (const struct SocketAddress *) desc;
1501 uint16_t pkt_len = ntohs (message->size);
1503 if (pkt_len != ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) - sizeof (GNUNET_HashCode))
1505 GNUNET_break_op (0);
1508 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1510 if (NULL == state->heap_node)
1512 /* first packet, setup record */
1513 state->ri.remote_address = *s;
1514 setup_state_record (state);
1517 send_udp_packet_via_tun (&state->ri.remote_address,
1518 &state->ri.local_address,
1519 &pkt[1], pkt_len - sizeof (struct udp_packet));
1528 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1530 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1531 const struct GNUNET_MessageHeader *message,
1532 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1534 struct TunnelState *state = *tunnel_ctx;
1535 // FIXME: write proper request struct (we don't need UDP except dpt either!)
1536 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1537 const struct udp_packet *pkt = (const struct udp_packet *) &desc[1];
1538 uint16_t pkt_len = ntohs (message->size);
1541 /* check that we got at least a valid header */
1542 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct udp_packet))
1544 GNUNET_break_op (0);
1547 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1549 GNUNET_assert (ntohs (pkt->len) ==
1550 ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1551 sizeof (GNUNET_HashCode));
1553 if (NULL == state->serv)
1555 /* setup fresh connection */
1556 GNUNET_assert (NULL == state->heap_node);
1557 if (NULL == (state->serv = find_service (udp_services, desc, ntohs (pkt->dpt))))
1559 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1560 _("No service found for %s on port %d!\n"),
1563 GNUNET_MESH_tunnel_destroy (state->tunnel);
1566 state->ri.remote_address = state->serv->address;
1567 setup_state_record (state);
1569 send_udp_packet_via_tun (&state->ri.remote_address,
1570 &state->ri.local_address,
1571 &pkt[1], pkt_len - sizeof (struct udp_packet));
1577 * Callback from GNUNET_MESH for new tunnels.
1579 * @param cls closure
1580 * @param tunnel new handle to the tunnel
1581 * @param initiator peer that started the tunnel
1582 * @param atsi performance information for the tunnel
1583 * @return initial tunnel context for the tunnel
1586 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1587 const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
1588 const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
1590 struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
1598 * Function called by mesh whenever an inbound tunnel is destroyed.
1599 * Should clean up any associated state.
1601 * @param cls closure (set from GNUNET_MESH_connect)
1602 * @param tunnel connection to the other end (henceforth invalid)
1603 * @param tunnel_ctx place where local state associated
1604 * with the tunnel is stored
1607 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
1610 struct TunnelState *s = tunnel_ctx;
1611 struct TunnelMessageQueue *tnq;
1613 while (NULL != (tnq = s->head))
1615 GNUNET_CONTAINER_DLL_remove (s->head,
1620 if (s->heap_node != NULL)
1622 GNUNET_assert (GNUNET_YES ==
1623 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1626 GNUNET_CONTAINER_heap_remove_node (s->heap_node);
1627 s->heap_node = NULL;
1631 GNUNET_MESH_notify_transmit_ready_cancel (s->th);
1639 * Function that frees everything from a hashmap
1643 * @param value value to free
1646 free_iterate (void *cls GNUNET_UNUSED,
1647 const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
1649 GNUNET_free (value);
1655 * Function scheduled as very last function, cleans up after us
1658 cleanup (void *cls GNUNET_UNUSED,
1659 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1663 if (helper_handle != NULL)
1665 GNUNET_HELPER_stop (helper_handle);
1666 helper_handle = NULL;
1668 if (mesh_handle != NULL)
1670 GNUNET_MESH_disconnect (mesh_handle);
1673 if (NULL != connections_map)
1675 GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
1676 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
1677 connections_map = NULL;
1679 if (NULL != connections_heap)
1681 GNUNET_CONTAINER_heap_destroy (connections_heap);
1682 connections_heap = NULL;
1684 if (NULL != tcp_services)
1686 GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
1687 GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
1688 tcp_services = NULL;
1690 if (NULL != udp_services)
1692 GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
1693 GNUNET_CONTAINER_multihashmap_destroy (udp_services);
1694 udp_services = NULL;
1697 GNUNET_free_non_null (exit_argv[i]);
1702 * Add services to the service map.
1704 * @param proto IPPROTO_TCP or IPPROTO_UDP
1705 * @param cpy copy of the service descriptor (can be mutilated)
1706 * @param name DNS name of the service
1709 add_services (int proto,
1716 struct LocalService *serv;
1718 for (redirect = strtok (cpy, " "); redirect != NULL;
1719 redirect = strtok (NULL, " "))
1721 if (NULL == (hostname = strstr (redirect, ":")))
1723 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1724 "option `%s' for domain `%s' is not formatted correctly!\n",
1731 if (NULL == (hostport = strstr (hostname, ":")))
1733 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1734 "option `%s' for domain `%s' is not formatted correctly!\n",
1742 int local_port = atoi (redirect);
1743 int remote_port = atoi (hostport);
1745 if (!((local_port > 0) && (local_port < 65536)))
1747 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1748 "`%s' is not a valid port number (for domain `%s')!", redirect,
1752 if (!((remote_port > 0) && (remote_port < 65536)))
1754 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1755 "`%s' is not a valid port number (for domain `%s')!", hostport,
1760 serv = GNUNET_malloc (sizeof (struct LocalService));
1761 serv->my_port = (uint16_t) local_port;
1762 serv->address.port = remote_port;
1763 if (0 == strcmp ("localhost4", hostname))
1765 const char *ip4addr = exit_argv[4];
1767 serv->address.af = AF_INET;
1768 GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
1770 else if (0 == strcmp ("localhost6", hostname))
1772 const char *ip6addr = exit_argv[2];
1774 serv->address.af = AF_INET6;
1775 GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
1779 struct addrinfo *res;
1782 ret = getaddrinfo (hostname, NULL, NULL, &res);
1783 if ( (ret != 0) || (res == NULL) )
1785 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1786 _("No addresses found for hostname `%s' of service `%s'!\n"),
1793 serv->address.af = res->ai_family;
1794 switch (res->ai_family)
1797 serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
1800 serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
1804 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1805 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
1813 store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
1822 * Reads the configuration servicecfg and populates udp_services
1825 * @param section name of section in config, equal to hostname
1828 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
1832 if ((strlen (section) < 8) ||
1833 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1836 GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1839 add_services (IPPROTO_UDP, cpy, section);
1843 GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1846 add_services (IPPROTO_TCP, cpy, section);
1853 * @brief Main function that will be run by the scheduler.
1855 * @param cls closure
1856 * @param args remaining command-line arguments
1857 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1858 * @param cfg_ configuration
1861 run (void *cls, char *const *args GNUNET_UNUSED,
1862 const char *cfgfile GNUNET_UNUSED,
1863 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1865 static struct GNUNET_MESH_MessageHandler handlers[] = {
1866 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP, 0},
1867 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP, 0},
1873 static GNUNET_MESH_ApplicationType apptypes[] = {
1874 GNUNET_APPLICATION_TYPE_END,
1875 GNUNET_APPLICATION_TYPE_END,
1876 GNUNET_APPLICATION_TYPE_END
1878 unsigned int handler_idx;
1879 unsigned int app_idx;
1891 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1893 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
1895 max_connections = 1024;
1896 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
1897 if (GNUNET_SYSERR ==
1898 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname))
1900 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1901 "No entry 'IFNAME' in configuration!\n");
1902 GNUNET_SCHEDULER_shutdown ();
1905 exit_argv[1] = ifname;
1906 if ( (GNUNET_SYSERR ==
1907 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
1909 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1911 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1912 "No valid entry 'IPV6ADDR' in configuration!\n");
1913 GNUNET_SCHEDULER_shutdown ();
1916 exit_argv[2] = ipv6addr;
1917 if (GNUNET_SYSERR ==
1918 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
1921 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1922 "No entry 'IPV6PREFIX' in configuration!\n");
1923 GNUNET_SCHEDULER_shutdown ();
1926 exit_argv[3] = ipv6prefix_s;
1928 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
1931 (ipv6prefix >= 127) )
1933 GNUNET_SCHEDULER_shutdown ();
1937 if ( (GNUNET_SYSERR ==
1938 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
1940 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1942 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1943 "No valid entry for 'IPV4ADDR' in configuration!\n");
1944 GNUNET_SCHEDULER_shutdown ();
1947 exit_argv[4] = ipv4addr;
1948 if ( (GNUNET_SYSERR ==
1949 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
1951 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1953 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1954 "No valid entry 'IPV4MASK' in configuration!\n");
1955 GNUNET_SCHEDULER_shutdown ();
1958 exit_argv[5] = ipv4mask;
1959 exit_argv[6] = NULL;
1963 udp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_UDP");
1964 tcp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_TCP");
1965 if (GNUNET_YES == udp)
1967 handlers[handler_idx].callback = &receive_udp_remote;
1968 handlers[handler_idx].expected_size = 0;
1969 handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP;
1970 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
1975 if (GNUNET_YES == tcp)
1977 handlers[handler_idx].callback = &receive_tcp_remote;
1978 handlers[handler_idx].expected_size = 0;
1979 handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP;
1980 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
1984 udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1985 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1986 GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
1988 connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
1989 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1991 = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL,
1993 &clean_tunnel, handlers,
1995 if (NULL == mesh_handle)
1997 GNUNET_SCHEDULER_shutdown ();
2000 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn",
2002 &message_token, NULL);
2009 * @param argc number of arguments from the command line
2010 * @param argv command line arguments
2011 * @return 0 ok, 1 on error
2014 main (int argc, char *const *argv)
2016 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
2017 GNUNET_GETOPT_OPTION_END
2020 return (GNUNET_OK ==
2021 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
2023 ("Daemon to run to provide an IP exit node for the VPN"),
2024 options, &run, NULL)) ? 0 : 1;
2028 /* end of gnunet-daemon-exit.c */