7097d71a0ce90c152506b0230bb999d02f1448e9
[oweals/gnunet.git] / src / exit / gnunet-daemon-exit.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010, 2012 Christian Grothoff
4
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.
9
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.
14
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.
19 */
20
21 /**
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
26  *
27  * TODO:
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
32  */
33 #include <platform.h>
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>
40 #include <string.h>
41
42
43 /* see http://www.iana.org/assignments/ethernet-numbers */
44 #ifndef ETH_P_IPV4
45 #define ETH_P_IPV4 0x0800
46 #endif
47
48 #ifndef ETH_P_IPV6
49 #define ETH_P_IPV6 0x86DD
50 #endif
51
52
53 GNUNET_NETWORK_STRUCT_BEGIN
54 /**
55  * Header from Linux TUN interface.
56  */ 
57 struct tun_header
58 {
59   /**
60    * Some flags (unused).
61    */ 
62   uint16_t flags;
63
64   /**
65    * Here we get an ETH_P_-number.
66    */
67   uint16_t proto;
68 };
69
70 /**
71  * Standard IPv4 header.
72  */
73 struct ip4_header
74 {
75   unsigned header_length:4 GNUNET_PACKED;
76   unsigned version:4 GNUNET_PACKED;
77   uint8_t diff_serv;
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;
82   uint8_t ttl;
83   uint8_t protocol;
84   uint16_t checksum GNUNET_PACKED;
85   struct in_addr source_address GNUNET_PACKED;
86   struct in_addr destination_address GNUNET_PACKED;
87 };
88
89 /**
90  * Standard IPv6 header.
91  */
92 struct ip6_header
93 {
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;
99   uint8_t next_header;
100   uint8_t hop_limit;
101   struct in6_addr source_address GNUNET_PACKED;
102   struct in6_addr destination_address GNUNET_PACKED;
103 };
104
105 #define TCP_FLAG_SYN 2
106
107 struct tcp_packet
108 {
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;
119 };
120
121 /**
122  * UDP packet header.
123  */
124 struct udp_packet
125 {
126   uint16_t spt GNUNET_PACKED;
127   uint16_t dpt GNUNET_PACKED;
128   uint16_t len GNUNET_PACKED;
129   uint16_t crc GNUNET_PACKED;
130 };
131
132 /**
133  * DNS header.
134  */
135 struct dns_header
136 {
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;
143 };
144 GNUNET_NETWORK_STRUCT_END
145
146 /**
147  * Information about an address.
148  */
149 struct SocketAddress
150 {
151   /**
152    * AF_INET or AF_INET6.
153    */
154   int af;
155
156   /**
157    * Remote address information.
158    */
159   union
160   {
161     /**
162      * Address, if af is AF_INET.
163      */
164     struct in_addr ipv4;
165
166     /**
167      * Address, if af is AF_INET6.
168      */
169     struct in6_addr ipv6;
170   } address;
171   
172   /**
173    * IPPROTO_TCP or IPPROTO_UDP;
174    */
175   uint8_t proto;
176
177   /**
178    * Remote port, in host byte order!
179    */
180   uint16_t port;
181
182 };
183
184 /**
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).
188  */
189 struct LocalService
190 {
191
192   /**
193    * Remote address to use for the service.
194    */
195   struct SocketAddress address;
196
197   /**
198    * DNS name of the service.
199    */
200   char *name;
201
202   /**
203    * Port I am listening on within GNUnet for this service, in host
204    * byte order.  (as we may redirect ports).
205    */
206   uint16_t my_port;
207
208 };
209
210 /**
211  * Information we use to track a connection (the classical 6-tuple of
212  * IP-version, protocol, source-IP, destination-IP, source-port and
213  * destinatin-port.
214  */
215 struct RedirectInformation 
216 {
217
218   /**
219    * Address information for the other party (equivalent of the
220    * arguments one would give to "connect").
221    */
222   struct SocketAddress remote_address;
223
224   /**
225    * Address information we used locally (AF and proto must match
226    * "remote_address").  Equivalent of the arguments one would give to
227    * "bind".
228    */
229   struct SocketAddress local_address;
230
231   /* 
232      Note 1: additional information might be added here in the
233      future to support protocols that require special handling,
234      such as ftp/tftp 
235
236      Note 2: we might also sometimes not match on all components
237      of the tuple, to support protocols where things do not always
238      fully map.
239   */
240 };
241
242
243 /**
244  * Queue of messages to a tunnel.
245  */
246 struct TunnelMessageQueue
247 {
248   /**
249    * This is a doubly-linked list.
250    */
251   struct TunnelMessageQueue *next;
252
253   /**
254    * This is a doubly-linked list.
255    */
256   struct TunnelMessageQueue *prev;
257
258   /**
259    * Payload to send via the tunnel.
260    */
261   const void *payload;
262
263   /**
264    * Number of bytes in 'payload'.
265    */
266   size_t len;
267 };
268
269
270 /**
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.
275  */
276 struct TunnelState
277 {
278   /**
279    * Mesh tunnel that is used for this connection.
280    */
281   struct GNUNET_MESH_Tunnel *tunnel;
282
283   /**
284    * Heap node for this state in the connections_heap.
285    */
286   struct GNUNET_CONTAINER_HeapNode *heap_node;
287
288   /**
289    * Key this state has in the connections_map.
290    */
291   GNUNET_HashCode state_key;
292
293   /**
294    * Associated service record, or NULL for no service.
295    */
296   struct LocalService *serv;
297
298   /**
299    * Head of DLL of messages for this tunnel.
300    */
301   struct TunnelMessageQueue *head;
302
303   /**
304    * Tail of DLL of messages for this tunnel.
305    */
306   struct TunnelMessageQueue *tail;
307
308   /**
309    * Active tunnel transmission request (or NULL).
310    */
311   struct GNUNET_MESH_TransmitHandle *th;
312
313   /**
314    * Primary redirection information for this connection.
315    */
316   struct RedirectInformation ri;
317
318 };
319
320
321 /**
322  * The handle to the configuration used throughout the process
323  */
324 static const struct GNUNET_CONFIGURATION_Handle *cfg;
325
326 /**
327  * The handle to the helper
328  */
329 static struct GNUNET_HELPER_Handle *helper_handle;
330
331 /**
332  * Arguments to the exit helper.
333  */
334 static char *exit_argv[7];
335
336 /**
337  * IPv6 prefix (0..127) from configuration file.
338  */
339 static unsigned long long ipv6prefix;
340
341 /**
342  * The handle to mesh
343  */
344 static struct GNUNET_MESH_Handle *mesh_handle;
345
346 /**
347  * This hashmaps contains the mapping from peer, service-descriptor,
348  * source-port and destination-port to a struct TunnelState
349  */
350 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
351
352 /**
353  * Heap so we can quickly find "old" connections.
354  */
355 static struct GNUNET_CONTAINER_Heap *connections_heap;
356
357 /**
358  * If there are at least this many connections, old ones will be removed
359  */
360 static long long unsigned int max_connections = 200;
361
362 /**
363  * This hashmaps saves interesting things about the configured UDP services
364  */
365 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
366
367 /**
368  * This hashmaps saves interesting things about the configured TCP services
369  */
370 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
371
372
373 /**
374  * Given IP information about a connection, calculate the respective
375  * hash we would use for the 'connections_map'.
376  *
377  * @param hash resulting hash
378  * @param ri information about the connection
379  */
380 static void
381 hash_redirect_info (GNUNET_HashCode *hash, 
382                     const struct RedirectInformation *ri)
383 {
384   char *off;
385
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) */
389   off = (char*) hash;
390   switch (ri->remote_address.af)
391   {
392   case AF_INET:
393     memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
394     off += sizeof (struct in_addr);
395     break;
396   case AF_INET6:
397     memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
398     off += sizeof (struct in_addr);
399     break;
400   default:
401     GNUNET_assert (0);
402   }
403   memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
404   off += sizeof (uint16_t);
405   switch (ri->local_address.af)
406   {
407   case AF_INET:
408     memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr));
409     off += sizeof (struct in_addr);
410     break;
411   case AF_INET6:
412     memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr));
413     off += sizeof (struct in_addr);
414     break;
415   default:
416     GNUNET_assert (0);
417   }
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);
422 }
423
424
425 /**
426  * Get our connection tracking state.  Warns if it does not exists,
427  * refreshes the timestamp if it does exist.
428  *
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
437  */
438 static struct TunnelState *
439 get_redirect_state (int af,
440                     int protocol,                   
441                     const void *destination_ip,
442                     uint16_t destination_port,
443                     const void *local_ip,
444                     uint16_t local_port,
445                     GNUNET_HashCode *state_key)
446 {
447   struct RedirectInformation ri;
448   GNUNET_HashCode key;
449   struct TunnelState *state;
450
451   ri.remote_address.af = af;
452   if (af == AF_INET)
453     ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
454   else
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;
459   if (af == AF_INET)
460     ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
461   else
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)
467     *state_key = key;
468   state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key);
469   if (NULL == state)
470     return NULL;
471   /* Mark this connection as freshly used */
472   if (NULL == state_key)
473     GNUNET_CONTAINER_heap_update_cost (connections_heap, 
474                                        state->heap_node,
475                                        GNUNET_TIME_absolute_get ().abs_value);
476   return state;
477 }
478
479
480 /**
481  * Given a service descriptor and a destination port, find the
482  * respective service entry.
483  *
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
488  */
489 static struct LocalService *
490 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
491               const GNUNET_HashCode *desc,
492               uint16_t dpt)
493 {
494   char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
495
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);
500 }
501
502
503 /**
504  * Free memory associated with a service record.
505  *
506  * @param cls unused
507  * @param key service descriptor
508  * @param value service record to free
509  * @return GNUNET_OK
510  */
511 static int
512 free_service_record (void *cls,
513                      const GNUNET_HashCode *key,
514                      void *value)
515 {
516   struct LocalService *service = value;
517
518   GNUNET_free_non_null (service->name);
519   GNUNET_free (service);
520   return GNUNET_OK;
521 }
522
523
524 /**
525  * Given a service descriptor and a destination port, find the
526  * respective service entry.
527  *
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).
532  */
533 static void
534 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
535                const char *name,
536                uint16_t dpt,
537                struct LocalService *service)
538 {
539   char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
540   GNUNET_HashCode desc;
541
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));
546   if (GNUNET_OK !=
547       GNUNET_CONTAINER_multihashmap_put (service_map,
548                                          (GNUNET_HashCode *) key,
549                                          service,
550                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
551   {
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"),
555                 name,
556                 (unsigned int) dpt);
557   }
558 }
559
560
561 /**
562  * MESH is ready to receive a message for the tunnel.  Transmit it.
563  *
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
568  */
569 static size_t
570 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
571 {
572   struct TunnelState *s = cls;
573   struct GNUNET_MESH_Tunnel *tunnel = s->tunnel;
574   struct TunnelMessageQueue *tnq;
575
576   s->th = NULL;
577   tnq = s->head;
578   GNUNET_assert (size >= tnq->len);
579   memcpy (buf, tnq->payload, tnq->len);
580   size = tnq->len;
581   GNUNET_CONTAINER_DLL_remove (s->head, 
582                                s->tail,
583                                tnq);  
584   GNUNET_free (tnq);
585   if (NULL != (tnq = s->head))
586     s->th = GNUNET_MESH_notify_transmit_ready (tunnel, 
587                                                GNUNET_NO /* corking */, 
588                                                0 /* priority */,
589                                                GNUNET_TIME_UNIT_FOREVER_REL,
590                                                NULL,
591                                                tnq->len,
592                                                &send_to_peer_notify_callback,
593                                                s);
594   return size;
595 }
596
597
598 /**
599  * Send the given packet via the mesh tunnel.
600  *
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
606  */
607 static void
608 send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
609                             const void *payload,
610                             size_t payload_length,
611                             const GNUNET_HashCode *desc,
612                             uint16_t mtype)
613 {
614   struct TunnelState *s;
615   struct TunnelMessageQueue *tnq;
616   struct GNUNET_MessageHeader *msg;
617   size_t len;
618   GNUNET_HashCode *dp;
619
620   len = sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + payload_length;
621   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
622   {
623     GNUNET_break (0);
624     return;
625   }
626   tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + len);
627   tnq->payload = &tnq[1];
628   tnq->len = len;
629   msg = (struct GNUNET_MessageHeader *) &tnq[1];
630   msg->size = htons ((uint16_t) len);
631   msg->type = htons (mtype);
632   if (NULL != desc)
633   {
634     dp = (GNUNET_HashCode *) &msg[1];
635     *dp = *desc;  
636     memcpy (&dp[1], payload, payload_length);
637   }
638   else
639   {
640     memcpy (&msg[1], payload, payload_length);
641   }
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);
645   if (NULL == s->th)
646     s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, 0 /* priority */,
647                                                GNUNET_TIME_UNIT_FOREVER_REL,
648                                                NULL, len,
649                                                &send_to_peer_notify_callback,
650                                                s);
651 }
652
653
654 /**
655  * @brief Handles an UDP packet received from the helper.
656  *
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)
664  */
665 static void
666 udp_from_helper (const struct udp_packet *udp, 
667                  size_t pktlen,
668                  int af,
669                  const void *destination_ip, 
670                  const void *source_ip)
671 {
672   struct TunnelState *state;
673
674   if (pktlen < sizeof (struct udp_packet))
675   {
676     /* blame kernel */
677     GNUNET_break (0);
678     return;
679   }
680   if (pktlen != ntohs (udp->len))
681   {
682     /* blame kernel */
683     GNUNET_break (0);
684     return;
685   }
686   state = get_redirect_state (af, IPPROTO_UDP,
687                               source_ip,
688                               ntohs (udp->spt),
689                               destination_ip,
690                               ntohs (udp->dpt),
691                               NULL);
692   if (NULL == state)
693   {
694     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
695                 _("Packet dropped, have no matching connection information\n"));
696     return;
697   }
698   send_packet_to_mesh_tunnel (state->tunnel,
699                               &udp[1], pktlen - sizeof (struct udp_packet),
700                               NULL,
701                               state->serv != NULL
702                               ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK 
703                               : GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
704 }
705
706
707 /**
708  * @brief Handles a TCP packet received from the helper.
709  *
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)
717  */
718 static void
719 tcp_from_helper (const struct tcp_packet *tcp, 
720                  size_t pktlen,
721                  int af,
722                  const void *destination_ip,
723                  const void *source_ip)
724 {
725   struct TunnelState *state;
726   char buf[pktlen];
727   struct tcp_packet *mtcp;
728
729   if (pktlen < sizeof (struct tcp_packet))
730   {
731     /* blame kernel */
732     GNUNET_break (0);
733     return;
734   }
735   state = get_redirect_state (af, IPPROTO_TCP,
736                               source_ip, 
737                               ntohs (tcp->spt),
738                               destination_ip,
739                               ntohs (tcp->dpt),
740                               NULL);
741   if (NULL == state)
742   {
743     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
744                 _("Packet dropped, have no matching connection information\n"));
745     
746     return;
747   }
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;
752   mtcp->spt = 0;
753   mtcp->dpt = 0;
754   mtcp->crc = 0;
755   send_packet_to_mesh_tunnel (state->tunnel,
756                               mtcp, pktlen,
757                               NULL,
758                               state->serv != NULL
759                               ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK 
760                               : GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
761 }
762
763
764 /**
765  * Receive packets from the helper-process
766  *
767  * @param cls unused
768  * @param client unsued
769  * @param message message received from helper
770  */
771 static void
772 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
773                const struct GNUNET_MessageHeader *message)
774 {
775   const struct tun_header *pkt_tun;
776   size_t size;
777
778   if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
779   {
780     GNUNET_break (0);
781     return;
782   }
783   size = ntohs (message->size);
784   if (size < sizeof (struct tun_header) + sizeof (struct GNUNET_MessageHeader))
785   {
786     GNUNET_break (0);
787     return;
788   }
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))
792   {
793   case ETH_P_IPV6:
794     {
795       const struct ip6_header *pkt6;
796
797       if (size < sizeof (struct ip6_header))
798       {
799         /* Kernel to blame? */
800         GNUNET_break (0);
801         return;
802       }
803       pkt6 = (struct ip6_header *) &pkt_tun[1];
804       if (size != ntohs (pkt6->payload_length))
805       {
806         /* Kernel to blame? */
807         GNUNET_break (0);
808         return;
809       }
810       size -= sizeof (struct ip6_header);
811       switch (pkt6->next_header)
812       {
813       case IPPROTO_UDP:
814         udp_from_helper ((const struct udp_packet *) &pkt6[1], size,
815                          AF_INET6,
816                          &pkt6->destination_address, 
817                          &pkt6->source_address);
818         break;
819       case IPPROTO_TCP:
820         tcp_from_helper ((const struct tcp_packet *) &pkt6[1], size,
821                          AF_INET6,
822                          &pkt6->destination_address, 
823                          &pkt6->source_address);
824         break;
825       default:
826         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
827                     _("IPv6 packet with unsupported next header received.  Ignored.\n"));
828         return;
829       }
830     }
831     break;
832   case ETH_P_IPV4:
833     {
834       const struct ip4_header *pkt4;
835
836       if (size < sizeof (struct ip4_header))
837       {
838         /* Kernel to blame? */
839         GNUNET_break (0);
840         return;
841       }
842       pkt4 = (const struct ip4_header *) &pkt_tun[1];
843       if (size != ntohs (pkt4->total_length))
844       {
845         /* Kernel to blame? */
846         GNUNET_break (0);
847         return;
848       }
849       if (pkt4->header_length * 4 != sizeof (struct ip4_header))
850       {
851         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
852                     _("IPv4 packet options received.  Ignored.\n"));
853         return;
854       }
855       size -= sizeof (struct ip4_header);
856       switch (pkt4->protocol)
857       {
858       case IPPROTO_UDP:
859         udp_from_helper ((const struct udp_packet *) &pkt4[1], size,
860                          AF_INET,
861                          &pkt4->destination_address, 
862                          &pkt4->source_address);
863       case IPPROTO_TCP:
864         tcp_from_helper ((const struct tcp_packet *) &pkt4[1], size,
865                          AF_INET,
866                          &pkt4->destination_address, 
867                          &pkt4->source_address);
868         break;
869       default:
870         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
871                     _("IPv4 packet with unsupported next header received.  Ignored.\n"));
872         return;
873       }
874     }
875     break;
876   default:
877     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
878                 _("Packet from unknown protocol %u received.  Ignored.\n"),
879                 ntohs (pkt_tun->proto));
880     break;
881   }
882 }
883
884
885 /**
886  * We need to create a (unique) fresh local address (IP+port).
887  * Fill one in.
888  *
889  * @param af desired address family
890  * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
891  * @param local_address address to initialize
892  */
893 static void
894 setup_fresh_address (int af,
895                      int proto,
896                      struct SocketAddress *local_address)
897 {
898   switch (af)
899   {
900   case AF_INET:
901     {
902       const char *ipv4addr = exit_argv[4];
903       const char *ipv4mask = exit_argv[5];
904       uint32_t tmp;
905       uint32_t tmp2;
906       
907       GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &tmp));
908       GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &tmp2));
909       // FIXME
910       /* This should be a noop */
911       tmp = tmp & tmp2;
912       tmp |= ntohl (*((uint32_t *) /*tunnel*/ 42)) & (~tmp2);
913       
914       // pkt4->source_address.s_addr = tmp;
915     }
916     break;
917   case AF_INET6:
918     {
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
922        * the host-mask*/
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 *);
927       
928       unsigned int offset = ipv6prefix_r - (16 - sizeof (void *));
929       // memcpy ((((char *) &pkt6->source_address)) + ipv6prefix_r, ((char *) &tunnel) + offset, 16 - ipv6prefix_r);
930       offset++;
931     }
932     break;
933   default:
934     GNUNET_assert (0);
935   }  
936 }
937
938
939 /**
940  * FIXME: document!
941  */
942 static void
943 setup_state_record (struct TunnelState *state)
944 {
945   GNUNET_HashCode key;
946   struct TunnelState *s;
947
948   /* generate fresh, unique address */
949   do
950   {
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,
955                                        IPPROTO_UDP,
956                                        &state->ri.remote_address.address,
957                                        state->ri.remote_address.port,
958                                        &state->ri.local_address.address,
959                                        state->ri.local_address.port,
960                                        &key));
961   GNUNET_assert (GNUNET_OK ==
962                  GNUNET_CONTAINER_multihashmap_put (connections_map, 
963                                                     &key, state,
964                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
965   state->heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
966                                                    state,
967                                                    GNUNET_TIME_absolute_get ().abs_value);   
968   while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
969   {
970     s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
971     GNUNET_assert (state != s);
972     s->heap_node = NULL;
973     GNUNET_MESH_tunnel_destroy (s->tunnel);
974     GNUNET_assert (GNUNET_OK ==
975                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
976                                                          &s->state_key, 
977                                                          s));
978     GNUNET_free (s);
979   }
980 }
981
982
983 /**
984  * FIXME: document
985  */
986 static void
987 prepare_ipv4_packet (const void *payload, size_t payload_length,
988                      int protocol,
989                      const struct SocketAddress *src_address,
990                      const struct SocketAddress *dst_address,
991                      struct ip4_header *pkt4)
992 {
993   size_t len;
994
995   len = payload_length;
996   switch (protocol)
997   {
998   case IPPROTO_UDP:
999     len += sizeof (struct udp_packet);
1000     break;
1001   case IPPROTO_TCP:
1002     /* tcp_header (with port/crc not set) must be part of payload! */
1003     if (len < sizeof (struct tcp_packet))
1004     {
1005       GNUNET_break (0);
1006       return;
1007     }
1008     break;
1009   default:
1010     GNUNET_break (0);
1011     return;
1012   }
1013   if (len + sizeof (struct ip4_header) > UINT16_MAX)
1014   {
1015     GNUNET_break (0);
1016     return;
1017   }
1018
1019   pkt4->version = 4;
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, 
1024                                                               65536);
1025   pkt4->flags = 0;
1026   pkt4->fragmentation_offset = 0;
1027   pkt4->ttl = 255;
1028   pkt4->protocol = protocol;
1029   pkt4->checksum = 0;
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));
1033
1034   switch (protocol)
1035   {
1036   case IPPROTO_UDP:
1037     {
1038       struct udp_packet *pkt4_udp = (struct udp_packet *) &pkt4[1];
1039
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);
1045     }
1046     break;
1047   case IPPROTO_TCP:
1048     {
1049       struct tcp_packet *pkt4_tcp = (struct tcp_packet *) &pkt4[1];
1050       
1051       memcpy (pkt4_tcp, payload, payload_length);
1052       pkt4_tcp->spt = htons (src_address->port);
1053       pkt4_tcp->dpt = htons (dst_address->port);
1054       pkt4_tcp->crc = 0;
1055       uint32_t sum = 0;
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);
1063     }
1064     break;
1065   default:
1066     GNUNET_assert (0);
1067   }
1068 }
1069
1070
1071 /**
1072  * FIXME: document
1073  */
1074 static void
1075 prepare_ipv6_packet (const void *payload, size_t payload_length,
1076                      int protocol,
1077                      const struct SocketAddress *src_address,
1078                      const struct SocketAddress *dst_address,
1079                      struct ip6_header *pkt6)
1080 {
1081   size_t len;
1082
1083   len = payload_length;
1084   switch (protocol)
1085   {
1086   case IPPROTO_UDP:
1087     len += sizeof (struct udp_packet);
1088     break;
1089   case IPPROTO_TCP:
1090     /* tcp_header (with port/crc not set) must be part of payload! */
1091     if (len < sizeof (struct tcp_packet))
1092     {
1093       GNUNET_break (0);
1094       return;
1095     }
1096     break;
1097   default:
1098     GNUNET_break (0);
1099     return;
1100   }
1101   if (len > UINT16_MAX)
1102   {
1103     GNUNET_break (0);
1104     return;
1105   }
1106
1107   pkt6->version = 6;
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;
1113
1114   switch (protocol)
1115   {
1116   case IPPROTO_UDP:
1117     {
1118       struct udp_packet *pkt6_udp = (struct udp_packet *) &pkt6[1];
1119
1120       memcpy (&pkt6[1], payload, payload_length);
1121       pkt6_udp->crc = 0;
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);
1125
1126       uint32_t sum = 0;
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);
1136     }
1137     break;
1138   case IPPROTO_TCP:
1139     {
1140       struct tcp_packet *pkt6_tcp = (struct tcp_packet *) pkt6;
1141       
1142       memcpy (pkt6_tcp, payload, payload_length);
1143       pkt6_tcp->crc = 0;
1144       pkt6_tcp->spt = htons (src_address->port);
1145       pkt6_tcp->dpt = htons (dst_address->port);
1146
1147       uint32_t sum = 0;
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);
1156     }
1157     break;
1158   default:
1159     GNUNET_assert (0);
1160     break;
1161   }
1162 }
1163
1164
1165 /**
1166  * We've just experienced a connection in use.  Track it, or if it is
1167  * already tracked, update the tracking.
1168  *
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
1173  */
1174 void
1175 update_state_map (const struct RedirectInformation *ri,
1176                   struct GNUNET_MESH_Tunnel *tunnel,
1177                   const GNUNET_HashCode *desc,
1178                   struct LocalService *serv)
1179 {
1180   struct TunnelState *state;
1181   GNUNET_HashCode state_key;
1182
1183   hash_redirect_info (&state_key,
1184                       ri);
1185   state = GNUNET_CONTAINER_multihashmap_get (connections_map, &state_key);
1186   if (NULL == state)
1187   {
1188     state = GNUNET_malloc (sizeof (struct TunnelState));
1189     state->tunnel = tunnel;
1190     state->state_key = state_key;
1191     state->serv = serv;
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));
1197     state->heap_node =
1198       GNUNET_CONTAINER_heap_insert (connections_heap,
1199                                     state,
1200                                     GNUNET_TIME_absolute_get ().abs_value);
1201   }
1202   else
1203   {
1204     if (state->tunnel != tunnel) 
1205     {
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"));
1209       return;
1210     }
1211     GNUNET_CONTAINER_heap_update_cost (connections_heap,
1212                                        state->heap_node,
1213                                        GNUNET_TIME_absolute_get ().abs_value);
1214   }
1215   while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1216   {
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,
1222                                                          &state->state_key, 
1223                                                          state));
1224     GNUNET_free (state);
1225   }
1226 }
1227
1228
1229 /**
1230  * FIXME: document!
1231  *
1232  * @param payload payload of the IP header (includes TCP header)
1233  */
1234 static void
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)
1238 {
1239   size_t len;
1240
1241   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header);
1242   switch (source_address->af)
1243   {
1244   case AF_INET:
1245     len += sizeof (struct ip4_header);
1246     break;
1247   case AF_INET6:
1248     len += sizeof (struct ip6_header);
1249     break;
1250   default:
1251     GNUNET_break (0);
1252     return;
1253   }
1254   len += payload_length;
1255   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1256   {
1257     GNUNET_break (0);
1258     return;
1259   }
1260   {
1261     char buf[len];
1262     struct GNUNET_MessageHeader *hdr;
1263     struct tun_header *tun;
1264     
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)
1271     {
1272     case AF_INET:
1273       {
1274         struct ip4_header * ipv4 = (struct ip4_header*) &tun[1];
1275         
1276         tun->proto = htons (ETH_P_IPV4);
1277         prepare_ipv4_packet (payload, payload_length, IPPROTO_TCP,
1278                              source_address,
1279                              destination_address,
1280                              ipv4);
1281       }
1282       break;
1283     case AF_INET6:
1284       {
1285         struct ip6_header * ipv6 = (struct ip6_header*) &tun[1];
1286         
1287         tun->proto = htons (ETH_P_IPV6);
1288         prepare_ipv6_packet (payload, payload_length, IPPROTO_TCP,
1289                              source_address,
1290                              destination_address,
1291                              ipv6);
1292       }
1293       break;    
1294     default:
1295       GNUNET_assert (0);
1296       break;
1297     }
1298     (void) GNUNET_HELPER_send (helper_handle,
1299                                (const struct GNUNET_MessageHeader*) buf,
1300                                GNUNET_YES,
1301                                NULL, NULL);
1302   }
1303 }
1304
1305
1306 /**
1307  * The messages are one GNUNET_HashCode for the service followed by a struct tcp_packet
1308  * FIXME: document!
1309  */
1310 static int
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)
1316 {
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);
1322
1323
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))
1326   {
1327     GNUNET_break_op (0);
1328     return GNUNET_YES;
1329   }
1330   pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1331
1332   if (NULL == state->serv) 
1333   {
1334     /* setup fresh connection */
1335     GNUNET_assert (NULL == state->heap_node);
1336     if (NULL == (state->serv = find_service (tcp_services, desc, ntohs (pkt->dpt))))
1337     {
1338       GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1339                   _("No service found for %s on port %d!\n"),
1340                   "TCP",
1341                   ntohs (pkt->dpt));
1342       GNUNET_MESH_tunnel_destroy (state->tunnel);
1343       return GNUNET_YES;
1344     }
1345     state->ri.remote_address = state->serv->address;    
1346     setup_state_record (state);
1347   }
1348   send_tcp_packet_via_tun (&state->ri.remote_address,
1349                            &state->ri.local_address,
1350                            pkt, pkt_len);
1351   return GNUNET_YES;
1352 }
1353
1354
1355 /**
1356  * FIXME: document!
1357  */
1358 static int
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)
1364 {
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);
1371
1372   if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct tcp_packet))
1373   {
1374     GNUNET_break_op (0);
1375     return GNUNET_YES;
1376   }
1377   pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1378
1379   if (NULL == state->heap_node)
1380   {
1381     /* first packet, setup record */
1382     state->ri.remote_address = *s;
1383     setup_state_record (state);
1384   }
1385
1386   send_tcp_packet_via_tun (&state->ri.remote_address,
1387                            &state->ri.local_address,
1388                            pkt, pkt_len);
1389   return GNUNET_YES;
1390 }
1391
1392
1393 /**
1394  * FIXME: document!
1395  * @param payload payload of the UDP packet (does NOT include UDP header)
1396  */
1397 static void
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)
1401 {
1402   size_t len;
1403
1404   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header);
1405   switch (source_address->af)
1406   {
1407   case AF_INET:
1408     len += sizeof (struct ip4_header);
1409     break;
1410   case AF_INET6:
1411     len += sizeof (struct ip6_header);
1412     break;
1413   default:
1414     GNUNET_break (0);
1415     return;
1416   }
1417   len += sizeof (struct udp_packet);
1418   len += payload_length;
1419   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1420   {
1421     GNUNET_break (0);
1422     return;
1423   }
1424   {
1425     char buf[len];
1426     struct GNUNET_MessageHeader *hdr;
1427     struct tun_header *tun;
1428     
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)
1435     {
1436     case AF_INET:
1437       {
1438         struct ip4_header * ipv4 = (struct ip4_header*) &tun[1];
1439         
1440         tun->proto = htons (ETH_P_IPV4);
1441         prepare_ipv4_packet (payload, payload_length, IPPROTO_UDP,
1442                              source_address,
1443                              destination_address,
1444                              ipv4);
1445       }
1446       break;
1447     case AF_INET6:
1448       {
1449         struct ip6_header * ipv6 = (struct ip6_header*) &tun[1];
1450         
1451         tun->proto = htons (ETH_P_IPV6);
1452         prepare_ipv6_packet (payload, payload_length, IPPROTO_UDP,
1453                              source_address,
1454                              destination_address,
1455                              ipv6);
1456       }
1457       break;    
1458     default:
1459       GNUNET_assert (0);
1460       break;
1461     }
1462     (void) GNUNET_HELPER_send (helper_handle,
1463                                (const struct GNUNET_MessageHeader*) buf,
1464                                GNUNET_YES,
1465                                NULL, NULL);
1466   }
1467 }
1468
1469
1470 /**
1471  * FIXME: document!
1472  */
1473 static int
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)
1479 {
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);
1486
1487   if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct udp_packet))
1488   {
1489     GNUNET_break_op (0);
1490     return GNUNET_YES;
1491   }
1492   pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1493
1494   if (NULL == state->heap_node)
1495   {
1496     /* first packet, setup record */
1497     state->ri.remote_address = *s;
1498     setup_state_record (state);
1499   }
1500
1501   send_udp_packet_via_tun (&state->ri.remote_address,
1502                            &state->ri.local_address,
1503                            &pkt[1], pkt_len - sizeof (struct udp_packet));
1504   return GNUNET_YES;
1505 }
1506
1507
1508 /**
1509  * FIXME: document!
1510  */
1511 static int
1512 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1513                      void **tunnel_ctx,
1514                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1515                      const struct GNUNET_MessageHeader *message,
1516                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1517 {
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);
1523
1524
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))
1527   {
1528     GNUNET_break_op (0);
1529     return GNUNET_YES;
1530   }
1531   pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1532
1533   GNUNET_assert (ntohs (pkt->len) ==
1534                  ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1535                  sizeof (GNUNET_HashCode));
1536
1537   if (NULL == state->serv) 
1538   {
1539     /* setup fresh connection */
1540     GNUNET_assert (NULL == state->heap_node);
1541     if (NULL == (state->serv = find_service (udp_services, desc, ntohs (pkt->dpt))))
1542     {
1543       GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1544                   _("No service found for %s on port %d!\n"),
1545                   "UDP",
1546                   ntohs (pkt->dpt));
1547       GNUNET_MESH_tunnel_destroy (state->tunnel);
1548       return GNUNET_YES;
1549     }
1550     state->ri.remote_address = state->serv->address;    
1551     setup_state_record (state);
1552   }
1553   send_udp_packet_via_tun (&state->ri.remote_address,
1554                            &state->ri.local_address,
1555                            &pkt[1], pkt_len - sizeof (struct udp_packet));
1556   return GNUNET_YES;
1557 }
1558
1559
1560 /**
1561  * Callback from GNUNET_MESH for new tunnels.
1562  *
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
1568  */
1569 static void *
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)
1573 {
1574   struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
1575   
1576   s->tunnel = tunnel;
1577   return s;
1578 }
1579
1580
1581 /**
1582  * Function called by mesh whenever an inbound tunnel is destroyed.
1583  * Should clean up any associated state.
1584  *
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
1589  */
1590 static void
1591 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
1592               void *tunnel_ctx)
1593 {
1594   struct TunnelState *s = tunnel_ctx;
1595   struct TunnelMessageQueue *tnq;
1596
1597   while (NULL != (tnq = s->head))
1598   {
1599     GNUNET_CONTAINER_DLL_remove (s->head,
1600                                  s->tail,
1601                                  tnq);
1602     GNUNET_free (tnq);
1603   }
1604   if (s->heap_node != NULL)
1605   {
1606     GNUNET_assert (GNUNET_YES ==
1607                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
1608                                                          &s->state_key,
1609                                                          s));
1610     GNUNET_CONTAINER_heap_remove_node (s->heap_node);
1611     s->heap_node = NULL;
1612   }
1613   if (NULL != s->th)
1614   {
1615     GNUNET_MESH_notify_transmit_ready_cancel (s->th);
1616     s->th = NULL;
1617   }
1618   GNUNET_free (s);
1619 }
1620
1621
1622 /**
1623  * Function that frees everything from a hashmap
1624  *
1625  * @param cls unused
1626  * @param hash key
1627  * @param value value to free
1628  */
1629 static int
1630 free_iterate (void *cls GNUNET_UNUSED,
1631               const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
1632 {
1633   GNUNET_free (value);
1634   return GNUNET_YES;
1635 }
1636
1637
1638 /**
1639  * Function scheduled as very last function, cleans up after us
1640  */
1641 static void
1642 cleanup (void *cls GNUNET_UNUSED,
1643          const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1644 {
1645   unsigned int i;
1646
1647   if (helper_handle != NULL)
1648   {
1649     GNUNET_HELPER_stop (helper_handle);
1650     helper_handle = NULL;
1651   }
1652   if (mesh_handle != NULL)
1653   {
1654     GNUNET_MESH_disconnect (mesh_handle);
1655     mesh_handle = NULL;
1656   }
1657   if (NULL != connections_map)
1658   {
1659     GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
1660     GNUNET_CONTAINER_multihashmap_destroy (connections_map);
1661     connections_map = NULL;
1662   }
1663   if (NULL != connections_heap)
1664   {
1665     GNUNET_CONTAINER_heap_destroy (connections_heap);
1666     connections_heap = NULL;
1667   }
1668   if (NULL != tcp_services)
1669   {
1670     GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
1671     GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
1672     tcp_services = NULL;
1673   }
1674   if (NULL != udp_services)
1675   {
1676     GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
1677     GNUNET_CONTAINER_multihashmap_destroy (udp_services);
1678     udp_services = NULL;
1679   }
1680   for (i=0;i<5;i++)
1681     GNUNET_free_non_null (exit_argv[i]);
1682 }
1683
1684
1685 /**
1686  * Add services to the service map.
1687  *
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
1691  */
1692 static void
1693 add_services (int proto,
1694               char *cpy,
1695               const char *name)
1696 {
1697   char *redirect;
1698   char *hostname;
1699   char *hostport;
1700   struct LocalService *serv;
1701
1702   for (redirect = strtok (cpy, " "); redirect != NULL;
1703        redirect = strtok (NULL, " "))
1704   {
1705     if (NULL == (hostname = strstr (redirect, ":")))
1706     {
1707       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1708                   "option `%s' for domain `%s' is not formatted correctly!\n",
1709                   redirect,
1710                   name);
1711       continue;
1712     }
1713     hostname[0] = '\0';
1714     hostname++;
1715     if (NULL == (hostport = strstr (hostname, ":")))
1716     {
1717       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1718                   "option `%s' for domain `%s' is not formatted correctly!\n",
1719                   redirect,
1720                   name);
1721       continue;
1722     }
1723     hostport[0] = '\0';
1724     hostport++;
1725     
1726     int local_port = atoi (redirect);
1727     int remote_port = atoi (hostport);
1728     
1729     if (!((local_port > 0) && (local_port < 65536)))
1730     {
1731       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1732                   "`%s' is not a valid port number (for domain `%s')!", redirect,
1733                   name);
1734       continue;
1735     }
1736     if (!((remote_port > 0) && (remote_port < 65536)))
1737     {
1738       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1739                   "`%s' is not a valid port number (for domain `%s')!", hostport,
1740                   name);
1741       continue;
1742     }
1743
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))
1748     {
1749       const char *ip4addr = exit_argv[4];
1750
1751       serv->address.af = AF_INET;      
1752       GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
1753     }
1754     else if (0 == strcmp ("localhost6", hostname))
1755     {
1756       const char *ip6addr = exit_argv[2];
1757
1758       serv->address.af = AF_INET6;
1759       GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
1760     }
1761     else
1762     {
1763       struct addrinfo *res;      
1764       int ret;
1765
1766       ret = getaddrinfo (hostname, NULL, NULL, &res);      
1767       if ( (ret != 0) || (res == NULL) )
1768       {
1769         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1770                     _("No addresses found for hostname `%s' of service `%s'!\n"),
1771                     hostname,
1772                     name);
1773         GNUNET_free (serv);
1774         continue;
1775       }
1776       
1777       serv->address.af = res->ai_family;
1778       switch (res->ai_family)
1779       {
1780         case AF_INET:
1781           serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
1782           break;
1783         case AF_INET6:
1784           serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
1785           break;
1786       default:
1787         freeaddrinfo (res);
1788         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1789                     _("No IP addresses found for hostname `%s' of service `%s'!\n"),
1790                     hostname,
1791                     name);
1792         GNUNET_free (serv);
1793         continue;
1794       }
1795       freeaddrinfo (res);
1796     }
1797     store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
1798                    name,
1799                    local_port,
1800                    serv);
1801   }
1802 }
1803
1804
1805 /**
1806  * Reads the configuration servicecfg and populates udp_services
1807  *
1808  * @param cls unused
1809  * @param section name of section in config, equal to hostname
1810  */
1811 static void
1812 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
1813 {
1814   char *cpy;
1815
1816   if ((strlen (section) < 8) ||
1817       (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1818     return;
1819   if (GNUNET_OK ==
1820       GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1821                                              &cpy))
1822   {
1823     add_services (IPPROTO_UDP, cpy, section);
1824     GNUNET_free (cpy);
1825   }
1826   if (GNUNET_OK ==
1827       GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1828                                              &cpy))
1829   {
1830     add_services (IPPROTO_TCP, cpy, section);
1831     GNUNET_free (cpy);
1832   }
1833 }
1834
1835
1836 /**
1837  * @brief Main function that will be run by the scheduler.
1838  *
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
1843  */
1844 static void
1845 run (void *cls, char *const *args GNUNET_UNUSED,
1846      const char *cfgfile GNUNET_UNUSED,
1847      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1848 {
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},
1852     {NULL, 0, 0},
1853     {NULL, 0, 0},
1854     {NULL, 0, 0}
1855   };
1856
1857   static GNUNET_MESH_ApplicationType apptypes[] = {
1858     GNUNET_APPLICATION_TYPE_END,
1859     GNUNET_APPLICATION_TYPE_END,
1860     GNUNET_APPLICATION_TYPE_END
1861   };
1862   unsigned int handler_idx;
1863   unsigned int app_idx;
1864   int udp;
1865   int tcp;
1866   char *ifname;
1867   char *ipv6addr;
1868   char *ipv6prefix_s;
1869   char *ipv4addr;
1870   char *ipv4mask;
1871   struct in_addr v4;
1872   struct in6_addr v6;
1873
1874   cfg = cfg_;
1875   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1876   if (GNUNET_OK !=
1877       GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
1878                                              &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))
1883   {
1884     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1885                 "No entry 'IFNAME' in configuration!\n");
1886     GNUNET_SCHEDULER_shutdown ();
1887     return;
1888   }
1889   exit_argv[1] = ifname;
1890   if ( (GNUNET_SYSERR ==
1891         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
1892                                                &ipv6addr) ||
1893         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1894   {
1895     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1896                 "No valid entry 'IPV6ADDR' in configuration!\n");
1897     GNUNET_SCHEDULER_shutdown ();
1898     return;
1899   }
1900   exit_argv[2] = ipv6addr;
1901   if (GNUNET_SYSERR ==
1902       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
1903                                              &ipv6prefix_s))
1904   {
1905     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1906                 "No entry 'IPV6PREFIX' in configuration!\n");
1907     GNUNET_SCHEDULER_shutdown ();
1908     return;
1909   }
1910   exit_argv[3] = ipv6prefix_s;
1911   if ( (GNUNET_OK !=
1912         GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
1913                                                "IPV6PREFIX",
1914                                                &ipv6prefix)) ||
1915        (ipv6prefix >= 127) )
1916   {
1917     GNUNET_SCHEDULER_shutdown ();
1918     return;
1919   }
1920
1921   if ( (GNUNET_SYSERR ==
1922         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
1923                                                &ipv4addr) ||
1924         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1925   {
1926     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1927                 "No valid entry for 'IPV4ADDR' in configuration!\n");
1928     GNUNET_SCHEDULER_shutdown ();
1929     return;
1930   }
1931   exit_argv[4] = ipv4addr;
1932   if ( (GNUNET_SYSERR ==
1933         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
1934                                                &ipv4mask) ||
1935         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1936   {
1937     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1938                 "No valid entry 'IPV4MASK' in configuration!\n");
1939     GNUNET_SCHEDULER_shutdown ();
1940     return;
1941   }
1942   exit_argv[5] = ipv4mask;
1943   exit_argv[6] = NULL;
1944
1945   app_idx = 0;
1946   handler_idx = 2;
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)
1950   {
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;
1955     handler_idx++;
1956     app_idx++;
1957   }
1958
1959   if (GNUNET_YES == tcp)
1960   {
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;
1965     handler_idx++;
1966     app_idx++;
1967   }
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);
1971
1972   connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
1973   connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1974   mesh_handle 
1975     = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL, 
1976                            &new_tunnel, 
1977                            &clean_tunnel, handlers,
1978                            apptypes);
1979   if (NULL == mesh_handle)
1980   {
1981     GNUNET_SCHEDULER_shutdown ();
1982     return;
1983   }
1984   helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", 
1985                                        exit_argv,
1986                                        &message_token, NULL);
1987 }
1988
1989
1990 /**
1991  * The main function
1992  *
1993  * @param argc number of arguments from the command line
1994  * @param argv command line arguments
1995  * @return 0 ok, 1 on error
1996  */
1997 int
1998 main (int argc, char *const *argv)
1999 {
2000   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
2001     GNUNET_GETOPT_OPTION_END
2002   };
2003
2004   return (GNUNET_OK ==
2005           GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
2006                               gettext_noop
2007                               ("Daemon to run to provide an IP exit node for the VPN"),
2008                               options, &run, NULL)) ? 0 : 1;
2009 }
2010
2011
2012 /* end of gnunet-daemon-exit.c */