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 * @param payload payload of the IP header (includes TCP header)
1228 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1229 const struct SocketAddress *source_address,
1230 const void *payload, size_t payload_length)
1234 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header);
1235 switch (source_address->af)
1238 len += sizeof (struct ip4_header);
1241 len += sizeof (struct ip6_header);
1247 len += payload_length;
1248 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1255 struct GNUNET_MessageHeader *hdr;
1256 struct tun_header *tun;
1258 hdr= (struct GNUNET_MessageHeader *) buf;
1259 hdr->type = htons (42);
1260 hdr->size = htons (len);
1261 tun = (struct tun_header*) &hdr[1];
1262 tun->flags = htons (0);
1263 switch (source_address->af)
1267 struct ip4_header * ipv4 = (struct ip4_header*) &tun[1];
1269 tun->proto = htons (ETH_P_IPV4);
1270 prepare_ipv4_packet (payload, payload_length, IPPROTO_TCP,
1272 destination_address,
1278 struct ip6_header * ipv6 = (struct ip6_header*) &tun[1];
1280 tun->proto = htons (ETH_P_IPV6);
1281 prepare_ipv6_packet (payload, payload_length, IPPROTO_TCP,
1283 destination_address,
1291 (void) GNUNET_HELPER_send (helper_handle,
1292 (const struct GNUNET_MessageHeader*) buf,
1300 * The messages are one GNUNET_HashCode for the service followed by a struct tcp_packet
1304 receive_tcp_service (void *unused GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1305 void **tunnel_ctx GNUNET_UNUSED,
1306 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1307 const struct GNUNET_MessageHeader *message,
1308 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1310 struct TunnelState *state = *tunnel_ctx;
1311 // FIXME: write proper request struct (we don't need the descriptor EACH time here!)
1312 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1313 const struct tcp_packet *pkt = (const struct tcp_packet *) &desc[1];
1314 uint16_t pkt_len = ntohs (message->size);
1317 /* check that we got at least a valid header */
1318 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct tcp_packet))
1320 GNUNET_break_op (0);
1323 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1325 if (NULL == state->serv)
1327 /* setup fresh connection */
1328 GNUNET_assert (NULL == state->heap_node);
1329 if (NULL == (state->serv = find_service (tcp_services, desc, ntohs (pkt->dpt))))
1331 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1332 _("No service found for %s on port %d!\n"),
1335 GNUNET_MESH_tunnel_destroy (state->tunnel);
1338 state->ri.remote_address = state->serv->address;
1339 setup_state_record (state);
1341 send_tcp_packet_via_tun (&state->ri.remote_address,
1342 &state->ri.local_address,
1352 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1353 void **tunnel_ctx GNUNET_UNUSED,
1354 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1355 const struct GNUNET_MessageHeader *message,
1356 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1358 struct TunnelState *state = *tunnel_ctx;
1359 // FIXME: write proper request struct (!)
1360 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1361 const struct tcp_packet *pkt = (const struct tcp_packet *) &desc[1];
1362 const struct SocketAddress *s = (const struct SocketAddress *) desc;
1363 uint16_t pkt_len = ntohs (message->size);
1365 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct tcp_packet))
1367 GNUNET_break_op (0);
1370 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1372 if (NULL == state->heap_node)
1374 /* first packet, setup record */
1375 state->ri.remote_address = *s;
1376 setup_state_record (state);
1379 send_tcp_packet_via_tun (&state->ri.remote_address,
1380 &state->ri.local_address,
1388 * @param payload payload of the UDP packet (does NOT include UDP header)
1391 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
1392 const struct SocketAddress *source_address,
1393 const void *payload, size_t payload_length)
1397 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header);
1398 switch (source_address->af)
1401 len += sizeof (struct ip4_header);
1404 len += sizeof (struct ip6_header);
1410 len += sizeof (struct udp_packet);
1411 len += payload_length;
1412 if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1419 struct GNUNET_MessageHeader *hdr;
1420 struct tun_header *tun;
1422 hdr= (struct GNUNET_MessageHeader *) buf;
1423 hdr->type = htons (42);
1424 hdr->size = htons (len);
1425 tun = (struct tun_header*) &hdr[1];
1426 tun->flags = htons (0);
1427 switch (source_address->af)
1431 struct ip4_header * ipv4 = (struct ip4_header*) &tun[1];
1433 tun->proto = htons (ETH_P_IPV4);
1434 prepare_ipv4_packet (payload, payload_length, IPPROTO_UDP,
1436 destination_address,
1442 struct ip6_header * ipv6 = (struct ip6_header*) &tun[1];
1444 tun->proto = htons (ETH_P_IPV6);
1445 prepare_ipv6_packet (payload, payload_length, IPPROTO_UDP,
1447 destination_address,
1455 (void) GNUNET_HELPER_send (helper_handle,
1456 (const struct GNUNET_MessageHeader*) buf,
1467 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1468 void **tunnel_ctx GNUNET_UNUSED,
1469 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1470 const struct GNUNET_MessageHeader *message,
1471 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1473 struct TunnelState *state = *tunnel_ctx;
1474 // FIXME: write proper request struct (!)
1475 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1476 const struct udp_packet *pkt = (const struct udp_packet *) &desc[1];
1477 const struct SocketAddress *s = (const struct SocketAddress *) desc;
1478 uint16_t pkt_len = ntohs (message->size);
1480 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct udp_packet))
1482 GNUNET_break_op (0);
1485 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1487 if (NULL == state->heap_node)
1489 /* first packet, setup record */
1490 state->ri.remote_address = *s;
1491 setup_state_record (state);
1494 send_udp_packet_via_tun (&state->ri.remote_address,
1495 &state->ri.local_address,
1496 &pkt[1], pkt_len - sizeof (struct udp_packet));
1505 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1507 const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1508 const struct GNUNET_MessageHeader *message,
1509 const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1511 struct TunnelState *state = *tunnel_ctx;
1512 // FIXME: write proper request struct (we don't need UDP except dpt either!)
1513 const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1514 const struct udp_packet *pkt = (const struct udp_packet *) &desc[1];
1515 uint16_t pkt_len = ntohs (message->size);
1518 /* check that we got at least a valid header */
1519 if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct udp_packet))
1521 GNUNET_break_op (0);
1524 pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1526 GNUNET_assert (ntohs (pkt->len) ==
1527 ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1528 sizeof (GNUNET_HashCode));
1530 if (NULL == state->serv)
1532 /* setup fresh connection */
1533 GNUNET_assert (NULL == state->heap_node);
1534 if (NULL == (state->serv = find_service (udp_services, desc, ntohs (pkt->dpt))))
1536 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1537 _("No service found for %s on port %d!\n"),
1540 GNUNET_MESH_tunnel_destroy (state->tunnel);
1543 state->ri.remote_address = state->serv->address;
1544 setup_state_record (state);
1546 send_udp_packet_via_tun (&state->ri.remote_address,
1547 &state->ri.local_address,
1548 &pkt[1], pkt_len - sizeof (struct udp_packet));
1554 * Callback from GNUNET_MESH for new tunnels.
1556 * @param cls closure
1557 * @param tunnel new handle to the tunnel
1558 * @param initiator peer that started the tunnel
1559 * @param atsi performance information for the tunnel
1560 * @return initial tunnel context for the tunnel
1563 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1564 const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
1565 const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
1567 struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
1575 * Function called by mesh whenever an inbound tunnel is destroyed.
1576 * Should clean up any associated state.
1578 * @param cls closure (set from GNUNET_MESH_connect)
1579 * @param tunnel connection to the other end (henceforth invalid)
1580 * @param tunnel_ctx place where local state associated
1581 * with the tunnel is stored
1584 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
1587 struct TunnelState *s = tunnel_ctx;
1588 struct TunnelMessageQueue *tnq;
1590 while (NULL != (tnq = s->head))
1592 GNUNET_CONTAINER_DLL_remove (s->head,
1597 if (s->heap_node != NULL)
1599 GNUNET_assert (GNUNET_YES ==
1600 GNUNET_CONTAINER_multihashmap_remove (connections_map,
1603 GNUNET_CONTAINER_heap_remove_node (s->heap_node);
1604 s->heap_node = NULL;
1608 GNUNET_MESH_notify_transmit_ready_cancel (s->th);
1616 * Function that frees everything from a hashmap
1620 * @param value value to free
1623 free_iterate (void *cls GNUNET_UNUSED,
1624 const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
1626 GNUNET_free (value);
1632 * Function scheduled as very last function, cleans up after us
1635 cleanup (void *cls GNUNET_UNUSED,
1636 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1640 if (helper_handle != NULL)
1642 GNUNET_HELPER_stop (helper_handle);
1643 helper_handle = NULL;
1645 if (mesh_handle != NULL)
1647 GNUNET_MESH_disconnect (mesh_handle);
1650 if (NULL != connections_map)
1652 GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
1653 GNUNET_CONTAINER_multihashmap_destroy (connections_map);
1654 connections_map = NULL;
1656 if (NULL != connections_heap)
1658 GNUNET_CONTAINER_heap_destroy (connections_heap);
1659 connections_heap = NULL;
1661 if (NULL != tcp_services)
1663 GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
1664 GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
1665 tcp_services = NULL;
1667 if (NULL != udp_services)
1669 GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
1670 GNUNET_CONTAINER_multihashmap_destroy (udp_services);
1671 udp_services = NULL;
1674 GNUNET_free_non_null (exit_argv[i]);
1679 * Add services to the service map.
1681 * @param proto IPPROTO_TCP or IPPROTO_UDP
1682 * @param cpy copy of the service descriptor (can be mutilated)
1683 * @param name DNS name of the service
1686 add_services (int proto,
1693 struct LocalService *serv;
1695 for (redirect = strtok (cpy, " "); redirect != NULL;
1696 redirect = strtok (NULL, " "))
1698 if (NULL == (hostname = strstr (redirect, ":")))
1700 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1701 "option `%s' for domain `%s' is not formatted correctly!\n",
1708 if (NULL == (hostport = strstr (hostname, ":")))
1710 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1711 "option `%s' for domain `%s' is not formatted correctly!\n",
1719 int local_port = atoi (redirect);
1720 int remote_port = atoi (hostport);
1722 if (!((local_port > 0) && (local_port < 65536)))
1724 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1725 "`%s' is not a valid port number (for domain `%s')!", redirect,
1729 if (!((remote_port > 0) && (remote_port < 65536)))
1731 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1732 "`%s' is not a valid port number (for domain `%s')!", hostport,
1737 serv = GNUNET_malloc (sizeof (struct LocalService));
1738 serv->my_port = (uint16_t) local_port;
1739 serv->address.port = remote_port;
1740 if (0 == strcmp ("localhost4", hostname))
1742 const char *ip4addr = exit_argv[4];
1744 serv->address.af = AF_INET;
1745 GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
1747 else if (0 == strcmp ("localhost6", hostname))
1749 const char *ip6addr = exit_argv[2];
1751 serv->address.af = AF_INET6;
1752 GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
1756 struct addrinfo *res;
1759 ret = getaddrinfo (hostname, NULL, NULL, &res);
1760 if ( (ret != 0) || (res == NULL) )
1762 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1763 _("No addresses found for hostname `%s' of service `%s'!\n"),
1770 serv->address.af = res->ai_family;
1771 switch (res->ai_family)
1774 serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
1777 serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
1781 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1782 _("No IP addresses found for hostname `%s' of service `%s'!\n"),
1790 store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
1799 * Reads the configuration servicecfg and populates udp_services
1802 * @param section name of section in config, equal to hostname
1805 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
1809 if ((strlen (section) < 8) ||
1810 (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1813 GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1816 add_services (IPPROTO_UDP, cpy, section);
1820 GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1823 add_services (IPPROTO_TCP, cpy, section);
1830 * @brief Main function that will be run by the scheduler.
1832 * @param cls closure
1833 * @param args remaining command-line arguments
1834 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1835 * @param cfg_ configuration
1838 run (void *cls, char *const *args GNUNET_UNUSED,
1839 const char *cfgfile GNUNET_UNUSED,
1840 const struct GNUNET_CONFIGURATION_Handle *cfg_)
1842 static struct GNUNET_MESH_MessageHandler handlers[] = {
1843 {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP, 0},
1844 {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP, 0},
1850 static GNUNET_MESH_ApplicationType apptypes[] = {
1851 GNUNET_APPLICATION_TYPE_END,
1852 GNUNET_APPLICATION_TYPE_END,
1853 GNUNET_APPLICATION_TYPE_END
1855 unsigned int handler_idx;
1856 unsigned int app_idx;
1868 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1870 GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
1872 max_connections = 1024;
1873 exit_argv[0] = GNUNET_strdup ("exit-gnunet");
1874 if (GNUNET_SYSERR ==
1875 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname))
1877 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1878 "No entry 'IFNAME' in configuration!\n");
1879 GNUNET_SCHEDULER_shutdown ();
1882 exit_argv[1] = ifname;
1883 if ( (GNUNET_SYSERR ==
1884 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
1886 (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1888 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1889 "No valid entry 'IPV6ADDR' in configuration!\n");
1890 GNUNET_SCHEDULER_shutdown ();
1893 exit_argv[2] = ipv6addr;
1894 if (GNUNET_SYSERR ==
1895 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
1898 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1899 "No entry 'IPV6PREFIX' in configuration!\n");
1900 GNUNET_SCHEDULER_shutdown ();
1903 exit_argv[3] = ipv6prefix_s;
1905 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
1908 (ipv6prefix >= 127) )
1910 GNUNET_SCHEDULER_shutdown ();
1914 if ( (GNUNET_SYSERR ==
1915 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
1917 (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1919 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1920 "No valid entry for 'IPV4ADDR' in configuration!\n");
1921 GNUNET_SCHEDULER_shutdown ();
1924 exit_argv[4] = ipv4addr;
1925 if ( (GNUNET_SYSERR ==
1926 GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
1928 (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1930 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1931 "No valid entry 'IPV4MASK' in configuration!\n");
1932 GNUNET_SCHEDULER_shutdown ();
1935 exit_argv[5] = ipv4mask;
1936 exit_argv[6] = NULL;
1940 udp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_UDP");
1941 tcp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_TCP");
1942 if (GNUNET_YES == udp)
1944 handlers[handler_idx].callback = &receive_udp_remote;
1945 handlers[handler_idx].expected_size = 0;
1946 handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP;
1947 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
1952 if (GNUNET_YES == tcp)
1954 handlers[handler_idx].callback = &receive_tcp_remote;
1955 handlers[handler_idx].expected_size = 0;
1956 handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP;
1957 apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
1961 udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1962 tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1963 GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
1965 connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
1966 connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1968 = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL,
1970 &clean_tunnel, handlers,
1972 if (NULL == mesh_handle)
1974 GNUNET_SCHEDULER_shutdown ();
1977 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn",
1979 &message_token, NULL);
1986 * @param argc number of arguments from the command line
1987 * @param argv command line arguments
1988 * @return 0 ok, 1 on error
1991 main (int argc, char *const *argv)
1993 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1994 GNUNET_GETOPT_OPTION_END
1997 return (GNUNET_OK ==
1998 GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
2000 ("Daemon to run to provide an IP exit node for the VPN"),
2001 options, &run, NULL)) ? 0 : 1;
2005 /* end of gnunet-daemon-exit.c */