7201c61ccbfa2b7c450bcc62a8fc9523d18b6344
[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  * - test
29  *
30  * Design:
31  * - which code should advertise services? the service model is right
32  *   now a bit odd, especially as this code DOES the exit and knows
33  *   the DNS "name", but OTOH this is clearly NOT the place to advertise
34  *   the service's existence; maybe the daemon should turn into a 
35  *   service with an API to add local-exit services dynamically?
36  */
37 #include "platform.h"
38 #include "gnunet_util_lib.h"
39 #include "gnunet_protocols.h"
40 #include "gnunet_applications.h"
41 #include "gnunet_mesh_service.h"
42 #include "gnunet_statistics_service.h"
43 #include "gnunet_constants.h"
44 #include "gnunet_tun_lib.h"
45 #include "exit.h"
46
47 /**
48  * Information about an address.
49  */
50 struct SocketAddress
51 {
52   /**
53    * AF_INET or AF_INET6.
54    */
55   int af;
56
57   /**
58    * Remote address information.
59    */
60   union
61   {
62     /**
63      * Address, if af is AF_INET.
64      */
65     struct in_addr ipv4;
66
67     /**
68      * Address, if af is AF_INET6.
69      */
70     struct in6_addr ipv6;
71   } address;
72   
73   /**
74    * IPPROTO_TCP or IPPROTO_UDP;
75    */
76   uint8_t proto;
77
78   /**
79    * Remote port, in host byte order!
80    */
81   uint16_t port;
82
83 };
84
85 /**
86  * This struct is saved into the services-hashmap to represent
87  * a service this peer is specifically offering an exit for
88  * (for a specific domain name).
89  */
90 struct LocalService
91 {
92
93   /**
94    * Remote address to use for the service.
95    */
96   struct SocketAddress address;
97
98   /**
99    * DNS name of the service.
100    */
101   char *name;
102
103   /**
104    * Port I am listening on within GNUnet for this service, in host
105    * byte order.  (as we may redirect ports).
106    */
107   uint16_t my_port;
108
109 };
110
111 /**
112  * Information we use to track a connection (the classical 6-tuple of
113  * IP-version, protocol, source-IP, destination-IP, source-port and
114  * destinatin-port.
115  */
116 struct RedirectInformation 
117 {
118
119   /**
120    * Address information for the other party (equivalent of the
121    * arguments one would give to "connect").
122    */
123   struct SocketAddress remote_address;
124
125   /**
126    * Address information we used locally (AF and proto must match
127    * "remote_address").  Equivalent of the arguments one would give to
128    * "bind".
129    */
130   struct SocketAddress local_address;
131
132   /* 
133      Note 1: additional information might be added here in the
134      future to support protocols that require special handling,
135      such as ftp/tftp 
136
137      Note 2: we might also sometimes not match on all components
138      of the tuple, to support protocols where things do not always
139      fully map.
140   */
141 };
142
143
144 /**
145  * Queue of messages to a tunnel.
146  */
147 struct TunnelMessageQueue
148 {
149   /**
150    * This is a doubly-linked list.
151    */
152   struct TunnelMessageQueue *next;
153
154   /**
155    * This is a doubly-linked list.
156    */
157   struct TunnelMessageQueue *prev;
158
159   /**
160    * Payload to send via the tunnel.
161    */
162   const void *payload;
163
164   /**
165    * Number of bytes in 'payload'.
166    */
167   size_t len;
168 };
169
170
171 /**
172  * This struct is saved into connections_map to allow finding the
173  * right tunnel given an IP packet from TUN.  It is also associated
174  * with the tunnel's closure so we can find it again for the next
175  * message from the tunnel.
176  */
177 struct TunnelState
178 {
179   /**
180    * Mesh tunnel that is used for this connection.
181    */
182   struct GNUNET_MESH_Tunnel *tunnel;
183
184   /**
185    * Heap node for this state in the connections_heap.
186    */
187   struct GNUNET_CONTAINER_HeapNode *heap_node;
188
189   /**
190    * Key this state has in the connections_map.
191    */
192   GNUNET_HashCode state_key;
193
194   /**
195    * Associated service record, or NULL for no service.
196    */
197   struct LocalService *serv;
198
199   /**
200    * Head of DLL of messages for this tunnel.
201    */
202   struct TunnelMessageQueue *head;
203
204   /**
205    * Tail of DLL of messages for this tunnel.
206    */
207   struct TunnelMessageQueue *tail;
208
209   /**
210    * Active tunnel transmission request (or NULL).
211    */
212   struct GNUNET_MESH_TransmitHandle *th;
213
214   /**
215    * Primary redirection information for this connection.
216    */
217   struct RedirectInformation ri;
218
219 };
220
221
222 /**
223  * The handle to the configuration used throughout the process
224  */
225 static const struct GNUNET_CONFIGURATION_Handle *cfg;
226
227 /**
228  * The handle to the helper
229  */
230 static struct GNUNET_HELPER_Handle *helper_handle;
231
232 /**
233  * Arguments to the exit helper.
234  */
235 static char *exit_argv[7];
236
237 /**
238  * IPv6 address of our TUN interface.
239  */
240 static struct in6_addr exit_ipv6addr;
241
242 /**
243  * IPv6 prefix (0..127) from configuration file.
244  */
245 static unsigned long long ipv6prefix;
246
247 /**
248  * IPv4 address of our TUN interface.
249  */
250 static struct in_addr exit_ipv4addr;
251
252 /**
253  * IPv4 netmask of our TUN interface.
254  */
255 static struct in_addr exit_ipv4mask;
256
257
258 /**
259  * Statistics.
260  */
261 static struct GNUNET_STATISTICS_Handle *stats;
262
263 /**
264  * The handle to mesh
265  */
266 static struct GNUNET_MESH_Handle *mesh_handle;
267
268 /**
269  * This hashmaps contains the mapping from peer, service-descriptor,
270  * source-port and destination-port to a struct TunnelState
271  */
272 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
273
274 /**
275  * Heap so we can quickly find "old" connections.
276  */
277 static struct GNUNET_CONTAINER_Heap *connections_heap;
278
279 /**
280  * If there are at least this many connections, old ones will be removed
281  */
282 static long long unsigned int max_connections;
283
284 /**
285  * This hashmaps saves interesting things about the configured UDP services
286  */
287 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
288
289 /**
290  * This hashmaps saves interesting things about the configured TCP services
291  */
292 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
293
294 /**
295  * Are we an IPv4-exit?
296  */
297 static int ipv4_exit;
298
299 /**
300  * Are we an IPv6-exit?
301  */
302 static int ipv6_exit;
303
304 /**
305  * Do we support IPv4 at all on the TUN interface?
306  */
307 static int ipv4_enabled;
308
309 /**
310  * Do we support IPv6 at all on the TUN interface?
311  */
312 static int ipv6_enabled;
313
314
315 /**
316  * Given IP information about a connection, calculate the respective
317  * hash we would use for the 'connections_map'.
318  *
319  * @param hash resulting hash
320  * @param ri information about the connection
321  */
322 static void
323 hash_redirect_info (GNUNET_HashCode *hash, 
324                     const struct RedirectInformation *ri)
325 {
326   char *off;
327
328   memset (hash, 0, sizeof (GNUNET_HashCode));
329   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
330      so we put the IP address in there (and hope for few collisions) */
331   off = (char*) hash;
332   switch (ri->remote_address.af)
333   {
334   case AF_INET:
335     memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
336     off += sizeof (struct in_addr);
337     break;
338   case AF_INET6:
339     memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
340     off += sizeof (struct in_addr);
341     break;
342   default:
343     GNUNET_assert (0);
344   }
345   memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
346   off += sizeof (uint16_t);
347   switch (ri->local_address.af)
348   {
349   case AF_INET:
350     memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr));
351     off += sizeof (struct in_addr);
352     break;
353   case AF_INET6:
354     memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr));
355     off += sizeof (struct in_addr);
356     break;
357   default:
358     GNUNET_assert (0);
359   }
360   memcpy (off, &ri->local_address.port, sizeof (uint16_t));
361   off += sizeof (uint16_t);
362   memcpy (off, &ri->remote_address.proto, sizeof (uint8_t));
363   off += sizeof (uint8_t);
364 }
365
366
367 /**
368  * Get our connection tracking state.  Warns if it does not exists,
369  * refreshes the timestamp if it does exist.
370  *
371  * @param af address family
372  * @param protocol IPPROTO_UDP or IPPROTO_TCP
373  * @param destination_ip target IP
374  * @param destination_port target port
375  * @param local_ip local IP
376  * @param local_port local port
377  * @param state_key set to hash's state if non-NULL
378  * @return NULL if we have no tracking information for this tuple
379  */
380 static struct TunnelState *
381 get_redirect_state (int af,
382                     int protocol,                   
383                     const void *destination_ip,
384                     uint16_t destination_port,
385                     const void *local_ip,
386                     uint16_t local_port,
387                     GNUNET_HashCode *state_key)
388 {
389   struct RedirectInformation ri;
390   GNUNET_HashCode key;
391   struct TunnelState *state;
392
393   ri.remote_address.af = af;
394   if (af == AF_INET)
395     ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
396   else
397     ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
398   ri.remote_address.port = destination_port;
399   ri.remote_address.proto = protocol;
400   ri.local_address.af = af;
401   if (af == AF_INET)
402     ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
403   else
404     ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
405   ri.local_address.port = local_port;
406   ri.local_address.proto = protocol;
407   hash_redirect_info (&key, &ri);
408   if (NULL != state_key)
409     *state_key = key;
410   state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key);
411   if (NULL == state)
412     return NULL;
413   /* Mark this connection as freshly used */
414   if (NULL == state_key)
415     GNUNET_CONTAINER_heap_update_cost (connections_heap, 
416                                        state->heap_node,
417                                        GNUNET_TIME_absolute_get ().abs_value);
418   return state;
419 }
420
421
422 /**
423  * Given a service descriptor and a destination port, find the
424  * respective service entry.
425  *
426  * @param service_map map of services (TCP or UDP)
427  * @param desc service descriptor
428  * @param dpt destination port
429  * @return NULL if we are not aware of such a service
430  */
431 static struct LocalService *
432 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
433               const GNUNET_HashCode *desc,
434               uint16_t dpt)
435 {
436   char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
437
438   memcpy (&key[0], &dpt, sizeof (uint16_t));
439   memcpy (&key[sizeof(uint16_t)], desc, sizeof (GNUNET_HashCode));
440   return GNUNET_CONTAINER_multihashmap_get (service_map,
441                                             (GNUNET_HashCode *) key);
442 }
443
444
445 /**
446  * Free memory associated with a service record.
447  *
448  * @param cls unused
449  * @param key service descriptor
450  * @param value service record to free
451  * @return GNUNET_OK
452  */
453 static int
454 free_service_record (void *cls,
455                      const GNUNET_HashCode *key,
456                      void *value)
457 {
458   struct LocalService *service = value;
459
460   GNUNET_free_non_null (service->name);
461   GNUNET_free (service);
462   return GNUNET_OK;
463 }
464
465
466 /**
467  * Given a service descriptor and a destination port, find the
468  * respective service entry.
469  *
470  * @param service_map map of services (TCP or UDP)
471  * @param name name of the service 
472  * @param dpt destination port
473  * @param service service information record to store (service->name will be set).
474  */
475 static void
476 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
477                const char *name,
478                uint16_t dpt,
479                struct LocalService *service)
480 {
481   char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
482   GNUNET_HashCode desc;
483
484   GNUNET_CRYPTO_hash (name, strlen (name) + 1, &desc);
485   service->name = GNUNET_strdup (name);
486   memcpy (&key[0], &dpt, sizeof (uint16_t));
487   memcpy (&key[sizeof(uint16_t)], &desc, sizeof (GNUNET_HashCode));
488   if (GNUNET_OK !=
489       GNUNET_CONTAINER_multihashmap_put (service_map,
490                                          (GNUNET_HashCode *) key,
491                                          service,
492                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
493   {
494     free_service_record (NULL, (GNUNET_HashCode *) key, service);
495     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
496                 _("Got duplicate service records for `%s:%u'\n"),
497                 name,
498                 (unsigned int) dpt);
499   }
500 }
501
502
503 /**
504  * MESH is ready to receive a message for the tunnel.  Transmit it.
505  *
506  * @param cls the 'struct TunnelState'.
507  * @param size number of bytes available in buf
508  * @param buf where to copy the message
509  * @return number of bytes copied to buf
510  */
511 static size_t
512 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
513 {
514   struct TunnelState *s = cls;
515   struct GNUNET_MESH_Tunnel *tunnel = s->tunnel;
516   struct TunnelMessageQueue *tnq;
517
518   s->th = NULL;
519   tnq = s->head;
520   GNUNET_assert (size >= tnq->len);
521   memcpy (buf, tnq->payload, tnq->len);
522   size = tnq->len;
523   GNUNET_CONTAINER_DLL_remove (s->head, 
524                                s->tail,
525                                tnq);  
526   GNUNET_free (tnq);
527   if (NULL != (tnq = s->head))
528     s->th = GNUNET_MESH_notify_transmit_ready (tunnel, 
529                                                GNUNET_NO /* corking */, 
530                                                0 /* priority */,
531                                                GNUNET_TIME_UNIT_FOREVER_REL,
532                                                NULL,
533                                                tnq->len,
534                                                &send_to_peer_notify_callback,
535                                                s);
536   GNUNET_STATISTICS_update (stats,
537                             gettext_noop ("# Bytes transmitted via mesh tunnels"),
538                             size, GNUNET_NO);
539   return size;
540 }
541
542
543 /**
544  * Send the given packet via the mesh tunnel.
545  *
546  * @param mesh_tunnel destination
547  * @param tnq message to queue
548  */
549 static void
550 send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
551                             struct TunnelMessageQueue *tnq)
552 {
553   struct TunnelState *s;
554
555   s = GNUNET_MESH_tunnel_get_data (mesh_tunnel);
556   GNUNET_assert (NULL != s);
557   GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, tnq);
558   if (NULL == s->th)
559     s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, 0 /* priority */,
560                                                GNUNET_TIME_UNIT_FOREVER_REL,
561                                                NULL, tnq->len,
562                                                &send_to_peer_notify_callback,
563                                                s);
564 }
565
566
567 /**
568  * @brief Handles an ICMP packet received from the helper.
569  *
570  * @param icmp A pointer to the Packet
571  * @param pktlen number of bytes in 'icmp'
572  * @param af address family (AFINET or AF_INET6)
573  * @param destination_ip destination IP-address of the IP packet (should 
574  *                       be our local address)
575  * @param source_ip original source IP-address of the IP packet (should
576  *                       be the original destination address)
577  */
578 static void
579 icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp, 
580                   size_t pktlen,
581                   int af,
582                   const void *destination_ip, 
583                   const void *source_ip)
584 {
585   struct TunnelState *state;
586   struct TunnelMessageQueue *tnq;
587   struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
588   const struct GNUNET_TUN_IPv4Header *ipv4;
589   const struct GNUNET_TUN_IPv6Header *ipv6;
590   const struct GNUNET_TUN_UdpHeader *udp;
591   size_t mlen;
592   uint16_t spt;
593   uint16_t dpt;
594   uint8_t protocol;
595
596   {
597     char sbuf[INET6_ADDRSTRLEN];
598     char dbuf[INET6_ADDRSTRLEN];
599     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
600                 "Received ICMP packet going from %s to %s\n",
601                 inet_ntop (af,
602                            source_ip,
603                            sbuf, sizeof (sbuf)),
604                 inet_ntop (af,
605                            source_ip,
606                            dbuf, sizeof (dbuf)));    
607   }
608   if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
609   {
610     /* blame kernel */
611     GNUNET_break (0);
612     return;
613   }
614
615   /* Find out if this is an ICMP packet in response to an existing
616      TCP/UDP packet and if so, figure out ports / protocol of the
617      existing session from the IP data in the ICMP payload */
618   spt = 0;
619   dpt = 0;
620   protocol = IPPROTO_ICMP;
621   switch (af)
622   {
623   case AF_INET:
624     switch (icmp->type)
625       {
626       case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
627       case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
628         break;
629       case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
630       case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
631       case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
632         if (pktlen < 
633             sizeof (struct GNUNET_TUN_IcmpHeader) +
634             sizeof (struct GNUNET_TUN_IPv4Header) + 8)
635         {
636           /* blame kernel */
637           GNUNET_break (0);
638           return;
639         }
640         ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
641         protocol = ipv4->protocol;
642         /* could be TCP or UDP, but both have the ports in the right
643            place, so that doesn't matter here */
644         udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
645         spt = ntohs (udp->spt);
646         dpt = ntohs (udp->dpt);
647         break;
648       default:
649         GNUNET_STATISTICS_update (stats,
650                                   gettext_noop ("# ICMP packets dropped (not allowed)"),
651                                   1, GNUNET_NO);
652         return;
653       }
654     break;
655   case AF_INET6:
656     switch (icmp->type)
657       {
658       case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
659       case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
660       case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
661       case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
662         if (pktlen < 
663             sizeof (struct GNUNET_TUN_IcmpHeader) +
664             sizeof (struct GNUNET_TUN_IPv6Header) + 8)
665         {
666           /* blame kernel */
667           GNUNET_break (0);
668           return;
669         }
670         ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
671         protocol = ipv6->next_header;
672         /* could be TCP or UDP, but both have the ports in the right
673            place, so that doesn't matter here */
674         udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
675         spt = ntohs (udp->spt);
676         dpt = ntohs (udp->dpt);
677         break;
678       case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
679       case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
680         break;
681       default:
682         GNUNET_STATISTICS_update (stats,
683                                   gettext_noop ("# ICMP packets dropped (not allowed)"),
684                                   1, GNUNET_NO);
685         return;
686       }
687     break;
688   default:
689     GNUNET_assert (0);
690   }
691   switch (protocol)
692   {
693   case IPPROTO_ICMP:
694     state = get_redirect_state (af, IPPROTO_ICMP,
695                                 source_ip, 0,
696                                 destination_ip, 0,
697                                 NULL);
698     break;
699   case IPPROTO_UDP:
700     state = get_redirect_state (af, IPPROTO_UDP,
701                                 source_ip,
702                                 spt,
703                                 destination_ip,
704                                 dpt,
705                                 NULL);
706     break;
707   case IPPROTO_TCP:
708     state = get_redirect_state (af, IPPROTO_TCP,
709                                 source_ip,
710                                 spt,
711                                 destination_ip,
712                                 dpt,
713                                 NULL);
714     break;
715   default:
716     GNUNET_STATISTICS_update (stats,
717                               gettext_noop ("# ICMP packets dropped (not allowed)"),
718                               1, GNUNET_NO);
719     return;
720   }
721   if (NULL == state)
722   {
723     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
724                 _("Packet dropped, have no matching connection information\n"));
725     return;
726   }
727   mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader);
728   tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);  
729   tnq->payload = &tnq[1];
730   tnq->len = mlen;
731   i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1];
732   i2v->header.size = htons ((uint16_t) mlen);
733   i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
734   i2v->af = htonl (af);
735   memcpy (&i2v->icmp_header,
736           icmp,
737           pktlen);
738   /* FIXME: should we sanitize the host-specific payload here?  On the
739      one hand, quite a bit of what we send is meaningless on the other
740      side (our IPs, ports, etc.); on the other hand, trying to compact
741      the packet would be very messy, and blanking fields out is also
742      hardly productive as they seem to contain nothing remotely
743      sensitive. */  
744   send_packet_to_mesh_tunnel (state->tunnel,
745                               tnq);
746 }
747
748
749 /**
750  * @brief Handles an UDP packet received from the helper.
751  *
752  * @param udp A pointer to the Packet
753  * @param pktlen number of bytes in 'udp'
754  * @param af address family (AFINET or AF_INET6)
755  * @param destination_ip destination IP-address of the IP packet (should 
756  *                       be our local address)
757  * @param source_ip original source IP-address of the IP packet (should
758  *                       be the original destination address)
759  */
760 static void
761 udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp, 
762                  size_t pktlen,
763                  int af,
764                  const void *destination_ip, 
765                  const void *source_ip)
766 {
767   struct TunnelState *state;
768   struct TunnelMessageQueue *tnq;
769   struct GNUNET_EXIT_UdpReplyMessage *urm;
770   size_t mlen;
771
772   {
773     char sbuf[INET6_ADDRSTRLEN];
774     char dbuf[INET6_ADDRSTRLEN];
775     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
776                 "Received UDP packet going from %s:%u to %s:%u\n",
777                 inet_ntop (af,
778                            source_ip,
779                            sbuf, sizeof (sbuf)),
780                 (unsigned int) ntohs (udp->spt),
781                 inet_ntop (af,
782                            source_ip,
783                            dbuf, sizeof (dbuf)),
784                 (unsigned int) ntohs (udp->dpt));
785   }
786   if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
787   {
788     /* blame kernel */
789     GNUNET_break (0);
790     return;
791   }
792   if (pktlen != ntohs (udp->len))
793   {
794     /* blame kernel */
795     GNUNET_break (0);
796     return;
797   }
798   state = get_redirect_state (af, IPPROTO_UDP,
799                               source_ip,
800                               ntohs (udp->spt),
801                               destination_ip,
802                               ntohs (udp->dpt),
803                               NULL);
804   if (NULL == state)
805   {
806     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
807                 _("Packet dropped, have no matching connection information\n"));
808     return;
809   }
810   mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader);
811   tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);  
812   tnq->payload = &tnq[1];
813   tnq->len = mlen;
814   urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1];
815   urm->header.size = htons ((uint16_t) mlen);
816   urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
817   urm->source_port = htons (0);
818   urm->destination_port = htons (0);
819   memcpy (&urm[1],
820           &udp[1],
821           pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
822   send_packet_to_mesh_tunnel (state->tunnel,
823                               tnq);
824 }
825
826
827 /**
828  * @brief Handles a TCP packet received from the helper.
829  *
830  * @param tcp A pointer to the Packet
831  * @param pktlen the length of the packet, including its TCP header
832  * @param af address family (AFINET or AF_INET6)
833  * @param destination_ip destination IP-address of the IP packet (should 
834  *                       be our local address)
835  * @param source_ip original source IP-address of the IP packet (should
836  *                       be the original destination address)
837  */
838 static void
839 tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp, 
840                  size_t pktlen,
841                  int af,
842                  const void *destination_ip,
843                  const void *source_ip)
844 {
845   struct TunnelState *state;
846   char buf[pktlen];
847   struct GNUNET_TUN_TcpHeader *mtcp;
848   struct GNUNET_EXIT_TcpDataMessage *tdm;
849   struct TunnelMessageQueue *tnq;
850   size_t mlen;
851
852   {
853     char sbuf[INET6_ADDRSTRLEN];
854     char dbuf[INET6_ADDRSTRLEN];
855     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
856                 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
857                 pktlen - sizeof (struct GNUNET_TUN_TcpHeader),
858                 inet_ntop (af,
859                            source_ip,
860                            sbuf, sizeof (sbuf)),
861                 (unsigned int) ntohs (tcp->spt),
862                 inet_ntop (af,
863                            destination_ip,
864                            dbuf, sizeof (dbuf)),
865                 (unsigned int) ntohs (tcp->dpt));
866   }
867   if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
868   {
869     /* blame kernel */
870     GNUNET_break (0);
871     return;
872   }
873   state = get_redirect_state (af, IPPROTO_TCP,
874                               source_ip, 
875                               ntohs (tcp->spt),
876                               destination_ip,
877                               ntohs (tcp->dpt),
878                               NULL);
879   if (NULL == state)
880   {
881     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
882                 _("Packet dropped, have no matching connection information\n"));
883     
884     return;
885   }
886   /* mug port numbers and crc to avoid information leakage;
887      sender will need to lookup the correct values anyway */
888   memcpy (buf, tcp, pktlen);  
889   mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
890   mtcp->spt = 0;
891   mtcp->dpt = 0;
892   mtcp->crc = 0;
893
894   mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
895   if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
896   {
897     GNUNET_break (0);
898     return;
899   }
900
901   tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen);
902   tnq->payload = &tnq[1];
903   tnq->len = mlen;
904   tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
905   tdm->header.size = htons ((uint16_t) mlen);
906   tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
907   tdm->reserved = htonl (0);
908   memcpy (&tdm->tcp_header,
909           buf, 
910           pktlen);
911   send_packet_to_mesh_tunnel (state->tunnel,
912                               tnq);
913 }
914
915
916 /**
917  * Receive packets from the helper-process
918  *
919  * @param cls unused
920  * @param client unsued
921  * @param message message received from helper
922  */
923 static void
924 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
925                const struct GNUNET_MessageHeader *message)
926 {
927   const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
928   size_t size;
929
930   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
931               "Got %u-byte message of type %u from gnunet-helper-exit\n",
932               ntohs (message->size),
933               ntohs (message->type));
934   GNUNET_STATISTICS_update (stats,
935                             gettext_noop ("# Packets received from TUN"),
936                             1, GNUNET_NO);
937   if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
938   {
939     GNUNET_break (0);
940     return;
941   }
942   size = ntohs (message->size);
943   if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
944   {
945     GNUNET_break (0);
946     return;
947   }
948   GNUNET_STATISTICS_update (stats,
949                             gettext_noop ("# Bytes received from TUN"),
950                             size, GNUNET_NO);
951   pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
952   size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
953   switch (ntohs (pkt_tun->proto))
954   {
955   case ETH_P_IPV4:
956     {
957       const struct GNUNET_TUN_IPv4Header *pkt4;
958
959       if (size < sizeof (struct GNUNET_TUN_IPv4Header))
960       {
961         /* Kernel to blame? */
962         GNUNET_break (0);
963         return;
964       }
965       pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
966       if (size != ntohs (pkt4->total_length))
967       {
968         /* Kernel to blame? */
969         GNUNET_break (0);
970         return;
971       }
972       if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
973       {
974         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
975                     _("IPv4 packet options received.  Ignored.\n"));
976         return;
977       }
978       
979       size -= sizeof (struct GNUNET_TUN_IPv4Header);
980       switch (pkt4->protocol)
981       {
982       case IPPROTO_UDP:
983         udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
984                          AF_INET,
985                          &pkt4->destination_address, 
986                          &pkt4->source_address);
987       case IPPROTO_TCP:
988         tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
989                          AF_INET,
990                          &pkt4->destination_address, 
991                          &pkt4->source_address);
992         break;
993       case IPPROTO_ICMP:
994         icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
995                           AF_INET,
996                           &pkt4->destination_address, 
997                           &pkt4->source_address);
998         break;
999       default:
1000         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1001                     _("IPv4 packet with unsupported next header received.  Ignored.\n"));
1002         return;
1003       }
1004     }
1005     break;
1006   case ETH_P_IPV6:
1007     {
1008       const struct GNUNET_TUN_IPv6Header *pkt6;
1009
1010       if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1011       {
1012         /* Kernel to blame? */
1013         GNUNET_break (0);
1014         return;
1015       }
1016       pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1017       if (size != ntohs (pkt6->payload_length))
1018       {
1019         /* Kernel to blame? */
1020         GNUNET_break (0);
1021         return;
1022       }
1023       size -= sizeof (struct GNUNET_TUN_IPv6Header);
1024       switch (pkt6->next_header)
1025       {
1026       case IPPROTO_UDP:
1027         udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
1028                          AF_INET6,
1029                          &pkt6->destination_address, 
1030                          &pkt6->source_address);
1031         break;
1032       case IPPROTO_TCP:
1033         tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
1034                          AF_INET6,
1035                          &pkt6->destination_address, 
1036                          &pkt6->source_address);
1037         break;
1038       case IPPROTO_ICMP:
1039         icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1040                           AF_INET6,
1041                           &pkt6->destination_address, 
1042                           &pkt6->source_address);
1043         break;
1044       default:
1045         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1046                     _("IPv6 packet with unsupported next header received.  Ignored.\n"));
1047         return;
1048       }
1049     }
1050     break;
1051   default:
1052     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1053                 _("Packet from unknown protocol %u received.  Ignored.\n"),
1054                 ntohs (pkt_tun->proto));
1055     break;
1056   }
1057 }
1058
1059
1060 /**
1061  * We need to create a (unique) fresh local address (IP+port).
1062  * Fill one in.
1063  *
1064  * @param af desired address family
1065  * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1066  * @param local_address address to initialize
1067  */
1068 static void
1069 setup_fresh_address (int af,
1070                      uint8_t proto,
1071                      struct SocketAddress *local_address)
1072 {
1073   local_address->af = af;
1074   local_address->proto = (uint8_t) proto;
1075   /* default "local" port range is often 32768--61000,
1076      so we pick a random value in that range */  
1077   local_address->port 
1078     = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1079                                                    28232);      
1080   switch (af)
1081   {
1082   case AF_INET:
1083     {
1084       struct in_addr addr;
1085       struct in_addr mask;
1086       struct in_addr rnd;
1087
1088       addr = exit_ipv4addr;
1089       mask = exit_ipv4mask;
1090       if (0 == ~mask.s_addr)
1091       {
1092         /* only one valid IP anyway */
1093         local_address->address.ipv4 = addr;
1094         return;
1095       }
1096       /* Given 192.168.0.1/255.255.0.0, we want a mask 
1097          of '192.168.255.255', thus:  */
1098       mask.s_addr = addr.s_addr | ~mask.s_addr;
1099       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1100       do
1101         {
1102           rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1103                                                  UINT32_MAX);   
1104           local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1105         }
1106       while ( (local_address->address.ipv4.s_addr == addr.s_addr) ||
1107               (local_address->address.ipv4.s_addr == mask.s_addr) );
1108     }
1109     break;
1110   case AF_INET6:
1111     {
1112       struct in6_addr addr;
1113       struct in6_addr mask;
1114       struct in6_addr rnd;
1115       int i;
1116       
1117       addr = exit_ipv6addr;
1118       GNUNET_assert (ipv6prefix < 128);
1119       if (ipv6prefix == 127)
1120       {
1121         /* only one valid IP anyway */
1122         local_address->address.ipv6 = addr;
1123         return;
1124       }
1125       /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1126          thus: */
1127       mask = addr;
1128       for (i=127;i>=128-ipv6prefix;i--)
1129         mask.s6_addr[i / 8] |= (1 << (i % 8));
1130       
1131       /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1132       do
1133         {
1134           for (i=0;i<16;i++)
1135           {
1136             rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1137                                                                        256);
1138             local_address->address.ipv6.s6_addr[i]
1139               = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1140           }
1141         }
1142       while ( (0 == memcmp (&local_address->address.ipv6,
1143                             &addr,
1144                             sizeof (struct in6_addr))) ||
1145               (0 == memcmp (&local_address->address.ipv6,
1146                             &mask,
1147                             sizeof (struct in6_addr))) );
1148     }
1149     break;
1150   default:
1151     GNUNET_assert (0);
1152   }  
1153 }
1154
1155
1156 /**
1157  * We are starting a fresh connection (TCP or UDP) and need
1158  * to pick a source port and IP address (within the correct
1159  * range and address family) to associate replies with the
1160  * connection / correct mesh tunnel.  This function generates
1161  * a "fresh" source IP and source port number for a connection
1162  * After picking a good source address, this function sets up
1163  * the state in the 'connections_map' and 'connections_heap'
1164  * to allow finding the state when needed later.  The function
1165  * also makes sure that we remain within memory limits by
1166  * cleaning up 'old' states.
1167  *
1168  * @param state skeleton state to setup a record for; should
1169  *              'state->ri.remote_address' filled in so that
1170  *              this code can determine which AF/protocol is
1171  *              going to be used (the 'tunnel' should also
1172  *              already be set); after calling this function,
1173  *              heap_node and the local_address will be
1174  *              also initialized (heap_node != NULL can be
1175  *              used to test if a state has been fully setup).
1176  */
1177 static void
1178 setup_state_record (struct TunnelState *state)
1179 {
1180   GNUNET_HashCode key;
1181   struct TunnelState *s;
1182
1183   /* generate fresh, unique address */
1184   do
1185   {
1186     if (NULL == state->serv)
1187       setup_fresh_address (state->ri.remote_address.af,
1188                            state->ri.remote_address.proto,
1189                            &state->ri.local_address);
1190     else
1191       setup_fresh_address (state->serv->address.af,
1192                            state->serv->address.proto,
1193                            &state->ri.local_address);
1194   } while (NULL != get_redirect_state (state->ri.remote_address.af,
1195                                        state->ri.remote_address.proto,
1196                                        &state->ri.remote_address.address,
1197                                        state->ri.remote_address.port,
1198                                        &state->ri.local_address.address,
1199                                        state->ri.local_address.port,
1200                                        &key));
1201   {
1202     char buf[INET6_ADDRSTRLEN];
1203     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1204                 "Picked local address %s:%u for new connection\n",
1205                 inet_ntop (state->ri.local_address.af, 
1206                            &state->ri.local_address.address,
1207                            buf, sizeof (buf)),
1208                 (unsigned int) state->ri.local_address.port);  
1209   }
1210   state->state_key = key;
1211   GNUNET_assert (GNUNET_OK ==
1212                  GNUNET_CONTAINER_multihashmap_put (connections_map, 
1213                                                     &key, state,
1214                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1215   state->heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
1216                                                    state,
1217                                                    GNUNET_TIME_absolute_get ().abs_value);   
1218   while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1219   {
1220     s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1221     GNUNET_assert (state != s);
1222     s->heap_node = NULL;
1223     GNUNET_MESH_tunnel_destroy (s->tunnel);
1224     GNUNET_assert (GNUNET_OK ==
1225                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
1226                                                          &s->state_key, 
1227                                                          s));
1228     GNUNET_free (s);
1229   }
1230 }
1231
1232
1233 /**
1234  * Prepare an IPv4 packet for transmission via the TUN interface.
1235  * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1236  * For UDP, the UDP header will be fully created, whereas for TCP
1237  * only the ports and checksum will be filled in.  So for TCP,
1238  * a skeleton TCP header must be part of the provided payload.
1239  *
1240  * @param payload payload of the packet (starting with UDP payload or
1241  *                TCP header, depending on protocol)
1242  * @param payload_length number of bytes in 'payload'
1243  * @param protocol IPPROTO_UDP or IPPROTO_TCP
1244  * @param src_address source address to use (IP and port)
1245  * @param dst_address destination address to use (IP and port)
1246  * @param pkt6 where to write the assembled packet; must
1247  *        contain enough space for the IP header, UDP/TCP header
1248  *        AND the payload
1249  */
1250 static void
1251 prepare_ipv4_packet (const void *payload, size_t payload_length,
1252                      int protocol,
1253                      const struct GNUNET_TUN_TcpHeader *tcp_header,
1254                      const struct SocketAddress *src_address,
1255                      const struct SocketAddress *dst_address,
1256                      struct GNUNET_TUN_IPv4Header *pkt4)
1257 {
1258   size_t len;
1259
1260   len = payload_length;
1261   switch (protocol)
1262   {
1263   case IPPROTO_UDP:
1264     len += sizeof (struct GNUNET_TUN_UdpHeader);
1265     break;
1266   case IPPROTO_TCP:
1267     len += sizeof (struct GNUNET_TUN_TcpHeader);
1268     GNUNET_assert (NULL != tcp_header);
1269     break;
1270   default:
1271     GNUNET_break (0);
1272     return;
1273   }
1274   if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1275   {
1276     GNUNET_break (0);
1277     return;
1278   }
1279
1280   GNUNET_TUN_initialize_ipv4_header (pkt4,
1281                                      protocol,
1282                                      len,
1283                                      &src_address->address.ipv4,
1284                                      &dst_address->address.ipv4);
1285   switch (protocol)
1286   {
1287   case IPPROTO_UDP:
1288     {
1289       struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1290
1291       pkt4_udp->spt = htons (src_address->port);
1292       pkt4_udp->dpt = htons (dst_address->port);
1293       pkt4_udp->len = htons ((uint16_t) payload_length);
1294       GNUNET_TUN_calculate_udp4_checksum (pkt4,
1295                                           pkt4_udp,
1296                                           payload, payload_length);
1297       memcpy (&pkt4_udp[1], payload, payload_length);
1298     }
1299     break;
1300   case IPPROTO_TCP:
1301     {
1302       struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1303       
1304       memcpy (pkt4_tcp, tcp_header, sizeof (struct GNUNET_TUN_TcpHeader));
1305       pkt4_tcp->spt = htons (src_address->port);
1306       pkt4_tcp->dpt = htons (dst_address->port);
1307       GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1308                                           pkt4_tcp,
1309                                           payload,
1310                                           payload_length);
1311       memcpy (&pkt4_tcp[1], payload, payload_length);
1312     }
1313     break;
1314   default:
1315     GNUNET_assert (0);
1316   }
1317 }
1318
1319
1320 /**
1321  * Prepare an IPv6 packet for transmission via the TUN interface.
1322  * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1323  * For UDP, the UDP header will be fully created, whereas for TCP
1324  * only the ports and checksum will be filled in.  So for TCP,
1325  * a skeleton TCP header must be part of the provided payload.
1326  *
1327  * @param payload payload of the packet (starting with UDP payload or
1328  *                TCP header, depending on protocol)
1329  * @param payload_length number of bytes in 'payload'
1330  * @param protocol IPPROTO_UDP or IPPROTO_TCP
1331  * @param src_address source address to use (IP and port)
1332  * @param dst_address destination address to use (IP and port)
1333  * @param pkt6 where to write the assembled packet; must
1334  *        contain enough space for the IP header, UDP/TCP header
1335  *        AND the payload
1336  */
1337 static void
1338 prepare_ipv6_packet (const void *payload, size_t payload_length,
1339                      int protocol,
1340                      const struct GNUNET_TUN_TcpHeader *tcp_header,
1341                      const struct SocketAddress *src_address,
1342                      const struct SocketAddress *dst_address,
1343                      struct GNUNET_TUN_IPv6Header *pkt6)
1344 {
1345   size_t len;
1346
1347   len = payload_length;
1348   switch (protocol)
1349   {
1350   case IPPROTO_UDP:
1351     len += sizeof (struct GNUNET_TUN_UdpHeader);
1352     break;
1353   case IPPROTO_TCP:
1354     /* tcp_header (with port/crc not set) must be part of payload! */
1355     if (len < sizeof (struct GNUNET_TUN_TcpHeader))
1356     {
1357       GNUNET_break (0);
1358       return;
1359     }
1360     break;
1361   default:
1362     GNUNET_break (0);
1363     return;
1364   }
1365   if (len > UINT16_MAX)
1366   {
1367     GNUNET_break (0);
1368     return;
1369   }
1370
1371   GNUNET_TUN_initialize_ipv6_header (pkt6,
1372                                      protocol,
1373                                      len,
1374                                      &dst_address->address.ipv6,
1375                                      &src_address->address.ipv6);
1376
1377   switch (protocol)
1378   {
1379   case IPPROTO_UDP:
1380     {
1381       struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1382
1383       pkt6_udp->spt = htons (src_address->port);
1384       pkt6_udp->dpt = htons (dst_address->port);
1385       pkt6_udp->len = htons ((uint16_t) payload_length);
1386       pkt6_udp->crc = 0;
1387       GNUNET_TUN_calculate_udp6_checksum (pkt6,
1388                                           pkt6_udp,
1389                                           payload,
1390                                           payload_length);
1391       memcpy (&pkt6[1], payload, payload_length);
1392     }
1393     break;
1394   case IPPROTO_TCP:
1395     {
1396       struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) pkt6;
1397
1398       /* memcpy first here as some TCP header fields are initialized this way! */
1399       memcpy (pkt6_tcp, payload, payload_length);
1400       pkt6_tcp->spt = htons (src_address->port);
1401       pkt6_tcp->dpt = htons (dst_address->port);
1402       GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1403                                           pkt6_tcp,
1404                                           payload,
1405                                           payload_length);
1406     }
1407     break;
1408   default:
1409     GNUNET_assert (0);
1410     break;
1411   }
1412 }
1413
1414
1415 /**
1416  * Send a TCP packet via the TUN interface.
1417  *
1418  * @param destination_address IP and port to use for the TCP packet's destination
1419  * @param source_address IP and port to use for the TCP packet's source
1420  * @param tcp header template to use
1421  * @param payload payload of the TCP packet
1422  * @param payload_length number of bytes in 'payload'
1423  */
1424 static void
1425 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1426                          const struct SocketAddress *source_address,
1427                          const struct GNUNET_TUN_TcpHeader *tcp_header,
1428                          const void *payload, size_t payload_length)
1429 {
1430   size_t len;
1431
1432   GNUNET_STATISTICS_update (stats,
1433                             gettext_noop ("# TCP packets sent via TUN"),
1434                             1, GNUNET_NO);
1435   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1436               "Sending packet with %u bytes TCP payload via TUN\n",
1437               (unsigned int) payload_length);
1438   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1439   switch (source_address->af)
1440   {
1441   case AF_INET:
1442     len += sizeof (struct GNUNET_TUN_IPv4Header);
1443     break;
1444   case AF_INET6:
1445     len += sizeof (struct GNUNET_TUN_IPv6Header);
1446     break;
1447   default:
1448     GNUNET_break (0);
1449     return;
1450   }
1451   len += sizeof (struct GNUNET_TUN_TcpHeader);
1452   len += payload_length;
1453   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1454   {
1455     GNUNET_break (0);
1456     return;
1457   }
1458   {
1459     char buf[len];
1460     struct GNUNET_MessageHeader *hdr;
1461     struct GNUNET_TUN_Layer2PacketHeader *tun;
1462     
1463     hdr = (struct GNUNET_MessageHeader *) buf;
1464     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1465     hdr->size = htons (len);
1466     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1467     tun->flags = htons (0);
1468     switch (source_address->af)
1469     {
1470     case AF_INET:
1471       {
1472         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1473         
1474         tun->proto = htons (ETH_P_IPV4);
1475         prepare_ipv4_packet (payload, payload_length,
1476                              IPPROTO_TCP,
1477                              tcp_header, 
1478                              source_address,
1479                              destination_address,
1480                              ipv4);
1481       }
1482       break;
1483     case AF_INET6:
1484       {
1485         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1486         
1487         tun->proto = htons (ETH_P_IPV6);
1488         prepare_ipv6_packet (payload, payload_length, 
1489                              IPPROTO_TCP,
1490                              tcp_header, 
1491                              source_address,
1492                              destination_address,
1493                              ipv6);
1494       }
1495       break;    
1496     default:
1497       GNUNET_assert (0);
1498       break;
1499     }
1500     (void) GNUNET_HELPER_send (helper_handle,
1501                                (const struct GNUNET_MessageHeader*) buf,
1502                                GNUNET_YES,
1503                                NULL, NULL);
1504   }
1505 }
1506
1507
1508 /**
1509  * Process a request via mesh to send a request to a TCP service
1510  * offered by this system.
1511  *
1512  * @param cls closure, NULL
1513  * @param tunnel connection to the other end
1514  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1515  * @param sender who sent the message
1516  * @param message the actual message
1517  * @param atsi performance data for the connection
1518  * @return GNUNET_OK to keep the connection open,
1519  *         GNUNET_SYSERR to close it (signal serious error)
1520  */
1521 static int
1522 receive_tcp_service (void *unused GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1523                      void **tunnel_ctx GNUNET_UNUSED,
1524                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1525                      const struct GNUNET_MessageHeader *message,
1526                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1527 {
1528   struct TunnelState *state = *tunnel_ctx;
1529   const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1530   uint16_t pkt_len = ntohs (message->size);
1531
1532   GNUNET_STATISTICS_update (stats,
1533                             gettext_noop ("# TCP service creation requests received via mesh"),
1534                             1, GNUNET_NO);
1535   GNUNET_STATISTICS_update (stats,
1536                             gettext_noop ("# Bytes received from MESH"),
1537                             pkt_len, GNUNET_NO);
1538   /* check that we got at least a valid header */
1539   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1540   {
1541     GNUNET_break_op (0);
1542     return GNUNET_SYSERR;
1543   }
1544   start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1545   pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1546   if ( (NULL == state) ||
1547        (NULL != state->serv) ||
1548        (NULL != state->heap_node) )
1549   {
1550     GNUNET_break_op (0);
1551     return GNUNET_SYSERR;
1552   }
1553   GNUNET_break_op (ntohl (start->reserved) == 0);
1554   /* setup fresh connection */
1555   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1556               "Received data from %s for forwarding to TCP service %s on port %u\n",
1557               GNUNET_i2s (sender),
1558               GNUNET_h2s (&start->service_descriptor),
1559               (unsigned int) ntohs (start->tcp_header.dpt));  
1560   if (NULL == (state->serv = find_service (tcp_services, &start->service_descriptor, 
1561                                            ntohs (start->tcp_header.dpt))))
1562   {
1563     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1564                 _("No service found for %s on port %d!\n"),
1565                 "TCP",
1566                 ntohs (start->tcp_header.dpt));
1567     GNUNET_STATISTICS_update (stats,
1568                               gettext_noop ("# TCP requests dropped (no such service)"),
1569                               1, GNUNET_NO);
1570     return GNUNET_SYSERR;
1571   }
1572   state->ri.remote_address = state->serv->address;    
1573   setup_state_record (state);
1574   send_tcp_packet_via_tun (&state->ri.remote_address,
1575                            &state->ri.local_address,
1576                            &start->tcp_header,
1577                            &start[1], pkt_len);
1578   return GNUNET_YES;
1579 }
1580
1581
1582 /**
1583  * Process a request to forward TCP data to the Internet via this peer.
1584  *
1585  * @param cls closure, NULL
1586  * @param tunnel connection to the other end
1587  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1588  * @param sender who sent the message
1589  * @param message the actual message
1590  * @param atsi performance data for the connection
1591  * @return GNUNET_OK to keep the connection open,
1592  *         GNUNET_SYSERR to close it (signal serious error)
1593  */
1594 static int
1595 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1596                     void **tunnel_ctx GNUNET_UNUSED,
1597                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1598                     const struct GNUNET_MessageHeader *message,
1599                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1600 {
1601   struct TunnelState *state = *tunnel_ctx;
1602   const struct GNUNET_EXIT_TcpInternetStartMessage *start;
1603   uint16_t pkt_len = ntohs (message->size);
1604   const struct in_addr *v4;
1605   const struct in6_addr *v6;
1606   const void *payload;
1607   int af;
1608
1609   GNUNET_STATISTICS_update (stats,
1610                             gettext_noop ("# Bytes received from MESH"),
1611                             pkt_len, GNUNET_NO);
1612   GNUNET_STATISTICS_update (stats,
1613                             gettext_noop ("# TCP IP-exit creation requests received via mesh"),
1614                             1, GNUNET_NO);
1615   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
1616   {
1617     GNUNET_break_op (0);
1618     return GNUNET_SYSERR;
1619   }
1620   start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
1621   pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);  
1622   if ( (NULL == state) ||
1623        (NULL != state->serv) ||
1624        (NULL != state->heap_node) )
1625   {
1626     GNUNET_break_op (0);
1627     return GNUNET_SYSERR;
1628   }
1629   af = (int) ntohl (start->af);
1630   state->ri.remote_address.af = af;
1631   switch (af)
1632   {
1633   case AF_INET:
1634     if (pkt_len < sizeof (struct in_addr))
1635     {
1636       GNUNET_break_op (0);
1637       return GNUNET_SYSERR;
1638     }
1639     if (! ipv4_exit)
1640     {
1641       GNUNET_break_op (0);
1642       return GNUNET_SYSERR;
1643     }
1644     v4 = (const struct in_addr*) &start[1];
1645     payload = &v4[1];
1646     pkt_len -= sizeof (struct in_addr);
1647     state->ri.remote_address.address.ipv4 = *v4;
1648     break;
1649   case AF_INET6:
1650     if (pkt_len < sizeof (struct in6_addr))
1651     {
1652       GNUNET_break_op (0);
1653       return GNUNET_SYSERR;
1654     }
1655     if (! ipv6_exit)
1656     {
1657       GNUNET_break_op (0);
1658       return GNUNET_SYSERR;
1659     }
1660     v6 = (const struct in6_addr*) &start[1];
1661     payload = &v6[1];
1662     pkt_len -= sizeof (struct in6_addr);
1663     state->ri.remote_address.address.ipv6 = *v6;
1664     break;
1665   default:
1666     GNUNET_break_op (0);
1667     return GNUNET_SYSERR;
1668   }
1669   {
1670     char buf[INET6_ADDRSTRLEN];
1671     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1672                 "Received data from %s for starting TCP stream to %s:%u\n",
1673                 GNUNET_i2s (sender),
1674                 inet_ntop (af, 
1675                            &state->ri.remote_address.address,
1676                            buf, sizeof (buf)),
1677                 (unsigned int) ntohs (start->tcp_header.dpt));  
1678   }
1679
1680   state->ri.remote_address.proto = IPPROTO_TCP;
1681   state->ri.remote_address.port = ntohs (start->tcp_header.dpt);
1682   setup_state_record (state);
1683   send_tcp_packet_via_tun (&state->ri.remote_address,
1684                            &state->ri.local_address,
1685                            &start->tcp_header,
1686                            payload, pkt_len);
1687   return GNUNET_YES;
1688 }
1689
1690
1691 /**
1692  * Process a request to forward TCP data on an established 
1693  * connection via this peer.
1694  *
1695  * @param cls closure, NULL
1696  * @param tunnel connection to the other end
1697  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1698  * @param sender who sent the message
1699  * @param message the actual message
1700  * @param atsi performance data for the connection
1701  * @return GNUNET_OK to keep the connection open,
1702  *         GNUNET_SYSERR to close it (signal serious error)
1703  */
1704 static int
1705 receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1706                   void **tunnel_ctx GNUNET_UNUSED,
1707                   const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1708                   const struct GNUNET_MessageHeader *message,
1709                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1710 {
1711   struct TunnelState *state = *tunnel_ctx;
1712   const struct GNUNET_EXIT_TcpDataMessage *data;
1713   uint16_t pkt_len = ntohs (message->size);
1714
1715   GNUNET_STATISTICS_update (stats,
1716                             gettext_noop ("# Bytes received from MESH"),
1717                             pkt_len, GNUNET_NO);
1718   GNUNET_STATISTICS_update (stats,
1719                             gettext_noop ("# TCP data requests received via mesh"),
1720                             1, GNUNET_NO);
1721   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1722   {
1723     GNUNET_break_op (0);
1724     return GNUNET_SYSERR;
1725   }
1726   data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
1727   pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);  
1728   if ( (NULL == state) ||
1729        (NULL == state->heap_node) )
1730   {
1731     /* connection should have been up! */
1732     GNUNET_STATISTICS_update (stats,
1733                               gettext_noop ("# TCP DATA requests dropped (no session)"),
1734                               1, GNUNET_NO);
1735     return GNUNET_SYSERR;
1736   }
1737   GNUNET_break_op (ntohl (data->reserved) == 0);
1738   {
1739     char buf[INET6_ADDRSTRLEN];
1740     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1741                 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1742                 pkt_len,
1743                 GNUNET_i2s (sender),
1744                 inet_ntop (state->ri.remote_address.af, 
1745                            &state->ri.remote_address.address,
1746                            buf, sizeof (buf)),
1747                 (unsigned int) state->ri.remote_address.port);
1748   }
1749
1750   send_tcp_packet_via_tun (&state->ri.remote_address,
1751                            &state->ri.local_address,
1752                            &data->tcp_header,
1753                            &data[1], pkt_len);
1754   return GNUNET_YES;
1755 }
1756
1757
1758 /**
1759  * Send an ICMP packet via the TUN interface.
1760  *
1761  * @param destination_address IP to use for the ICMP packet's destination
1762  * @param source_address IP to use for the ICMP packet's source
1763  * @param icmp_header ICMP header to send
1764  * @param payload payload of the ICMP packet (does NOT include ICMP header)
1765  * @param payload_length number of bytes of data in payload
1766  */
1767 static void
1768 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1769                           const struct SocketAddress *source_address,
1770                           const struct GNUNET_TUN_IcmpHeader *icmp_header,
1771                           const void *payload, size_t payload_length)
1772 {
1773   size_t len;
1774   struct GNUNET_TUN_IcmpHeader *icmp;
1775
1776   GNUNET_STATISTICS_update (stats,
1777                             gettext_noop ("# ICMP packets sent via TUN"),
1778                             1, GNUNET_NO);
1779   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1780               "Sending packet with %u bytes ICMP payload via TUN\n",
1781               (unsigned int) payload_length);
1782   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1783   switch (destination_address->af)
1784   {
1785   case AF_INET:
1786     len += sizeof (struct GNUNET_TUN_IPv4Header);
1787     break;
1788   case AF_INET6:
1789     len += sizeof (struct GNUNET_TUN_IPv6Header);
1790     break;
1791   default:
1792     GNUNET_break (0);
1793     return;
1794   }
1795   len += sizeof (struct GNUNET_TUN_IcmpHeader);
1796   len += payload_length;
1797   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1798   {
1799     GNUNET_break (0);
1800     return;
1801   }
1802   {
1803     char buf[len];
1804     struct GNUNET_MessageHeader *hdr;
1805     struct GNUNET_TUN_Layer2PacketHeader *tun;
1806     
1807     hdr= (struct GNUNET_MessageHeader *) buf;
1808     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1809     hdr->size = htons (len);
1810     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1811     tun->flags = htons (0);
1812     switch (source_address->af)
1813     {
1814     case AF_INET:
1815       {
1816         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1817         
1818         tun->proto = htons (ETH_P_IPV4);
1819         GNUNET_TUN_initialize_ipv4_header (ipv4,
1820                                            IPPROTO_ICMP,
1821                                            sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1822                                            &source_address->address.ipv4,
1823                                            &destination_address->address.ipv4);
1824         icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1825       }
1826       break;
1827     case AF_INET6:
1828       {
1829         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1830         
1831         tun->proto = htons (ETH_P_IPV6);
1832         GNUNET_TUN_initialize_ipv6_header (ipv6,
1833                                            IPPROTO_ICMP,
1834                                            sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1835                                            &source_address->address.ipv6,
1836                                            &destination_address->address.ipv6);
1837         icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1838       }
1839       break;    
1840     default:
1841       GNUNET_assert (0);
1842       break;
1843     }
1844     *icmp = *icmp_header;
1845     memcpy (&icmp[1],
1846             payload,
1847             payload_length);
1848     GNUNET_TUN_calculate_icmp_checksum (icmp,
1849                                         payload,
1850                                         payload_length);
1851     (void) GNUNET_HELPER_send (helper_handle,
1852                                (const struct GNUNET_MessageHeader*) buf,
1853                                GNUNET_YES,
1854                                NULL, NULL);
1855   }
1856 }
1857
1858
1859 /**
1860  * Process a request to forward ICMP data to the Internet via this peer.
1861  *
1862  * @param cls closure, NULL
1863  * @param tunnel connection to the other end
1864  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1865  * @param sender who sent the message
1866  * @param message the actual message
1867  * @param atsi performance data for the connection
1868  * @return GNUNET_OK to keep the connection open,
1869  *         GNUNET_SYSERR to close it (signal serious error)
1870  */
1871 static int
1872 receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1873                      void **tunnel_ctx GNUNET_UNUSED,
1874                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1875                      const struct GNUNET_MessageHeader *message,
1876                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1877 {
1878   struct TunnelState *state = *tunnel_ctx;
1879   const struct GNUNET_EXIT_IcmpInternetMessage *msg;
1880   uint16_t pkt_len = ntohs (message->size);
1881   const struct in_addr *v4;
1882   const struct in6_addr *v6;  
1883   const void *payload;
1884   int af;
1885
1886   GNUNET_STATISTICS_update (stats,
1887                             gettext_noop ("# Bytes received from MESH"),
1888                             pkt_len, GNUNET_NO);
1889   GNUNET_STATISTICS_update (stats,
1890                             gettext_noop ("# ICMP IP-exit requests received via mesh"),
1891                             1, GNUNET_NO);
1892   if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
1893   {
1894     GNUNET_break_op (0);
1895     return GNUNET_SYSERR;
1896   }
1897   msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
1898   pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);  
1899
1900   af = (int) ntohl (msg->af);
1901   state->ri.remote_address.af = af;
1902   switch (af)
1903   {
1904   case AF_INET:
1905     if (pkt_len < sizeof (struct in_addr))
1906     {
1907       GNUNET_break_op (0);
1908       return GNUNET_SYSERR;
1909     }
1910     if (! ipv4_exit)
1911     {
1912       GNUNET_break_op (0);
1913       return GNUNET_SYSERR;
1914     }
1915     v4 = (const struct in_addr*) &msg[1];
1916     payload = &v4[1];
1917     pkt_len -= sizeof (struct in_addr);
1918     state->ri.remote_address.address.ipv4 = *v4;
1919     break;
1920   case AF_INET6:
1921     if (pkt_len < sizeof (struct in6_addr))
1922     {
1923       GNUNET_break_op (0);
1924       return GNUNET_SYSERR;
1925     }
1926     if (! ipv6_exit)
1927     {
1928       GNUNET_break_op (0);
1929       return GNUNET_SYSERR;
1930     }
1931     v6 = (const struct in6_addr*) &msg[1];
1932     payload = &v6[1];
1933     pkt_len -= sizeof (struct in6_addr);
1934     state->ri.remote_address.address.ipv6 = *v6;
1935     break;
1936   default:
1937     GNUNET_break_op (0);
1938     return GNUNET_SYSERR;
1939   }
1940  
1941   {
1942     char buf[INET6_ADDRSTRLEN];
1943     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1944                 "Received ICMP data from %s for forwarding to %s\n",
1945                 GNUNET_i2s (sender),
1946                 inet_ntop (af, 
1947                            &state->ri.remote_address.address,
1948                            buf, sizeof (buf)));
1949   }
1950
1951   /* FIXME: check that ICMP type is something we want to support */
1952
1953   state->ri.remote_address.proto = IPPROTO_ICMP;
1954   state->ri.remote_address.port = 0;
1955   state->ri.local_address.port = 0;
1956   if (NULL == state->heap_node)
1957     setup_state_record (state);
1958
1959   send_icmp_packet_via_tun (&state->ri.remote_address,
1960                             &state->ri.local_address,
1961                             &msg->icmp_header,
1962                             payload, pkt_len);
1963   return GNUNET_YES;
1964 }
1965
1966
1967 /**
1968  * Process a request via mesh to send ICMP data to a service
1969  * offered by this system.
1970  *
1971  * @param cls closure, NULL
1972  * @param tunnel connection to the other end
1973  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1974  * @param sender who sent the message
1975  * @param message the actual message
1976  * @param atsi performance data for the connection
1977  * @return GNUNET_OK to keep the connection open,
1978  *         GNUNET_SYSERR to close it (signal serious error)
1979  */
1980 static int
1981 receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1982                       void **tunnel_ctx,
1983                       const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1984                       const struct GNUNET_MessageHeader *message,
1985                       const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1986 {
1987   struct TunnelState *state = *tunnel_ctx;
1988   const struct GNUNET_EXIT_IcmpServiceMessage *msg;
1989   uint16_t pkt_len = ntohs (message->size);
1990
1991   GNUNET_STATISTICS_update (stats,
1992                             gettext_noop ("# Bytes received from MESH"),
1993                             pkt_len, GNUNET_NO);
1994   GNUNET_STATISTICS_update (stats,
1995                             gettext_noop ("# ICMP service requests received via mesh"),
1996                             1, GNUNET_NO);
1997   /* check that we got at least a valid header */
1998   if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
1999   {
2000     GNUNET_break_op (0);
2001     return GNUNET_SYSERR;
2002   }
2003   msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2004   pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2005   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2006               "Received data from %s for forwarding to ICMP service %s\n",
2007               GNUNET_i2s (sender),
2008               GNUNET_h2s (&msg->service_descriptor));
2009   if (NULL == state->serv)
2010   {
2011     /* first packet to service must not be ICMP (cannot determine service!) */
2012     GNUNET_break_op (0);
2013     return GNUNET_SYSERR;
2014   }
2015   if (state->serv->address.af != ntohl (msg->af))
2016   {
2017     GNUNET_STATISTICS_update (stats,
2018                               gettext_noop ("# ICMP service requests discarded (incompatible af)"),
2019                               1, GNUNET_NO);
2020     return GNUNET_SYSERR;
2021   }
2022
2023   /* FIXME: check that ICMP type is something we want to support */
2024
2025   state->ri.remote_address = state->serv->address;    
2026   setup_state_record (state);
2027
2028   send_icmp_packet_via_tun (&state->ri.remote_address,
2029                             &state->ri.local_address,
2030                             &msg->icmp_header,
2031                             &msg[1], pkt_len);
2032   return GNUNET_YES;
2033 }
2034
2035
2036 /**
2037  * Send a UDP packet via the TUN interface.
2038  *
2039  * @param destination_address IP and port to use for the UDP packet's destination
2040  * @param source_address IP and port to use for the UDP packet's source
2041  * @param payload payload of the UDP packet (does NOT include UDP header)
2042  * @param payload_length number of bytes of data in payload
2043  */
2044 static void
2045 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
2046                          const struct SocketAddress *source_address,
2047                          const void *payload, size_t payload_length)
2048 {
2049   size_t len;
2050
2051   GNUNET_STATISTICS_update (stats,
2052                             gettext_noop ("# UDP packets sent via TUN"),
2053                             1, GNUNET_NO);
2054   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2055               "Sending packet with %u bytes UDP payload via TUN\n",
2056               (unsigned int) payload_length);
2057   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2058   switch (source_address->af)
2059   {
2060   case AF_INET:
2061     len += sizeof (struct GNUNET_TUN_IPv4Header);
2062     break;
2063   case AF_INET6:
2064     len += sizeof (struct GNUNET_TUN_IPv6Header);
2065     break;
2066   default:
2067     GNUNET_break (0);
2068     return;
2069   }
2070   len += sizeof (struct GNUNET_TUN_UdpHeader);
2071   len += payload_length;
2072   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2073   {
2074     GNUNET_break (0);
2075     return;
2076   }
2077   {
2078     char buf[len];
2079     struct GNUNET_MessageHeader *hdr;
2080     struct GNUNET_TUN_Layer2PacketHeader *tun;
2081     
2082     hdr= (struct GNUNET_MessageHeader *) buf;
2083     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2084     hdr->size = htons (len);
2085     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2086     tun->flags = htons (0);
2087     switch (source_address->af)
2088     {
2089     case AF_INET:
2090       {
2091         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2092         
2093         tun->proto = htons (ETH_P_IPV4);
2094         prepare_ipv4_packet (payload, payload_length,
2095                              IPPROTO_UDP,
2096                              NULL,
2097                              source_address,
2098                              destination_address,
2099                              ipv4);
2100       }
2101       break;
2102     case AF_INET6:
2103       {
2104         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2105         
2106         tun->proto = htons (ETH_P_IPV6);
2107         prepare_ipv6_packet (payload, payload_length, 
2108                              IPPROTO_UDP,
2109                              NULL,
2110                              source_address,
2111                              destination_address,
2112                              ipv6);
2113       }
2114       break;    
2115     default:
2116       GNUNET_assert (0);
2117       break;
2118     }
2119     (void) GNUNET_HELPER_send (helper_handle,
2120                                (const struct GNUNET_MessageHeader*) buf,
2121                                GNUNET_YES,
2122                                NULL, NULL);
2123   }
2124 }
2125
2126
2127 /**
2128  * Process a request to forward UDP data to the Internet via this peer.
2129  *
2130  * @param cls closure, NULL
2131  * @param tunnel connection to the other end
2132  * @param tunnel_ctx pointer to our 'struct TunnelState *'
2133  * @param sender who sent the message
2134  * @param message the actual message
2135  * @param atsi performance data for the connection
2136  * @return GNUNET_OK to keep the connection open,
2137  *         GNUNET_SYSERR to close it (signal serious error)
2138  */
2139 static int
2140 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2141                     void **tunnel_ctx GNUNET_UNUSED,
2142                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2143                     const struct GNUNET_MessageHeader *message,
2144                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2145 {
2146   struct TunnelState *state = *tunnel_ctx;
2147   const struct GNUNET_EXIT_UdpInternetMessage *msg;
2148   uint16_t pkt_len = ntohs (message->size);
2149   const struct in_addr *v4;
2150   const struct in6_addr *v6;
2151   const void *payload;
2152   int af;
2153
2154   GNUNET_STATISTICS_update (stats,
2155                             gettext_noop ("# Bytes received from MESH"),
2156                             pkt_len, GNUNET_NO);
2157   GNUNET_STATISTICS_update (stats,
2158                             gettext_noop ("# UDP IP-exit requests received via mesh"),
2159                             1, GNUNET_NO);
2160   if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2161   {
2162     GNUNET_break_op (0);
2163     return GNUNET_SYSERR;
2164   }
2165   msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message;
2166   pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage);  
2167   af = (int) ntohl (msg->af);
2168   state->ri.remote_address.af = af;
2169   switch (af)
2170   {
2171   case AF_INET:
2172     if (pkt_len < sizeof (struct in_addr))
2173     {
2174       GNUNET_break_op (0);
2175       return GNUNET_SYSERR;
2176     }
2177     if (! ipv4_exit)
2178     {
2179       GNUNET_break_op (0);
2180       return GNUNET_SYSERR;
2181     }
2182     v4 = (const struct in_addr*) &msg[1];
2183     payload = &v4[1];
2184     pkt_len -= sizeof (struct in_addr);
2185     state->ri.remote_address.address.ipv4 = *v4;
2186     break;
2187   case AF_INET6:
2188     if (pkt_len < sizeof (struct in6_addr))
2189     {
2190       GNUNET_break_op (0);
2191       return GNUNET_SYSERR;
2192     }
2193     if (! ipv6_exit)
2194     {
2195       GNUNET_break_op (0);
2196       return GNUNET_SYSERR;
2197     }
2198     v6 = (const struct in6_addr*) &msg[1];
2199     payload = &v6[1];
2200     pkt_len -= sizeof (struct in6_addr);
2201     state->ri.remote_address.address.ipv6 = *v6;
2202     break;
2203   default:
2204     GNUNET_break_op (0);
2205     return GNUNET_SYSERR;
2206   }
2207   {
2208     char buf[INET6_ADDRSTRLEN];
2209     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2210                 "Received data from %s for forwarding to UDP %s:%u\n",
2211                 GNUNET_i2s (sender),
2212                 inet_ntop (af, 
2213                            &state->ri.remote_address.address,
2214                            buf, sizeof (buf)),
2215                 (unsigned int) ntohs (msg->destination_port));  
2216   }
2217   state->ri.remote_address.proto = IPPROTO_UDP;
2218   state->ri.remote_address.port = msg->destination_port;
2219   if (NULL == state->heap_node)
2220     setup_state_record (state);
2221   if (0 != ntohs (msg->source_port))
2222     state->ri.local_address.port = msg->source_port;
2223   send_udp_packet_via_tun (&state->ri.remote_address,
2224                            &state->ri.local_address,
2225                            payload, pkt_len);
2226   return GNUNET_YES;
2227 }
2228
2229
2230 /**
2231  * Process a request via mesh to send a request to a UDP service
2232  * offered by this system.
2233  *
2234  * @param cls closure, NULL
2235  * @param tunnel connection to the other end
2236  * @param tunnel_ctx pointer to our 'struct TunnelState *'
2237  * @param sender who sent the message
2238  * @param message the actual message
2239  * @param atsi performance data for the connection
2240  * @return GNUNET_OK to keep the connection open,
2241  *         GNUNET_SYSERR to close it (signal serious error)
2242  */
2243 static int
2244 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2245                      void **tunnel_ctx,
2246                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2247                      const struct GNUNET_MessageHeader *message,
2248                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2249 {
2250   struct TunnelState *state = *tunnel_ctx;
2251   const struct GNUNET_EXIT_UdpServiceMessage *msg;
2252   uint16_t pkt_len = ntohs (message->size);
2253
2254   GNUNET_STATISTICS_update (stats,
2255                             gettext_noop ("# Bytes received from MESH"),
2256                             pkt_len, GNUNET_NO);
2257   GNUNET_STATISTICS_update (stats,
2258                             gettext_noop ("# UDP service requests received via mesh"),
2259                             1, GNUNET_NO);
2260   /* check that we got at least a valid header */
2261   if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
2262   {
2263     GNUNET_break_op (0);
2264     return GNUNET_SYSERR;
2265   }
2266   msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message;
2267   pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage);
2268   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2269               "Received data from %s for forwarding to UDP service %s on port %u\n",
2270               GNUNET_i2s (sender),
2271               GNUNET_h2s (&msg->service_descriptor),
2272               (unsigned int) ntohs (msg->destination_port));  
2273   if (NULL == (state->serv = find_service (udp_services, &msg->service_descriptor, 
2274                                            ntohs (msg->destination_port))))
2275   {
2276     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
2277                 _("No service found for %s on port %d!\n"),
2278                 "UDP",
2279                 ntohs (msg->destination_port));
2280     GNUNET_STATISTICS_update (stats,
2281                               gettext_noop ("# UDP requests dropped (no such service)"),
2282                               1, GNUNET_NO);
2283     return GNUNET_SYSERR;
2284   }
2285   state->ri.remote_address = state->serv->address;    
2286   setup_state_record (state);
2287   if (0 != ntohs (msg->source_port))
2288     state->ri.local_address.port = msg->source_port;
2289   send_udp_packet_via_tun (&state->ri.remote_address,
2290                            &state->ri.local_address,
2291                            &msg[1], pkt_len);
2292   return GNUNET_YES;
2293 }
2294
2295
2296 /**
2297  * Callback from GNUNET_MESH for new tunnels.
2298  *
2299  * @param cls closure
2300  * @param tunnel new handle to the tunnel
2301  * @param initiator peer that started the tunnel
2302  * @param atsi performance information for the tunnel
2303  * @return initial tunnel context for the tunnel
2304  */
2305 static void *
2306 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2307             const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
2308             const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
2309 {
2310   struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
2311
2312   GNUNET_STATISTICS_update (stats,
2313                             gettext_noop ("# Inbound MESH tunnels created"),
2314                             1, GNUNET_NO);
2315   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2316               "Received inbound tunnel from `%s'\n",
2317               GNUNET_i2s (initiator));
2318   s->tunnel = tunnel;
2319   return s;
2320 }
2321
2322
2323 /**
2324  * Function called by mesh whenever an inbound tunnel is destroyed.
2325  * Should clean up any associated state.
2326  *
2327  * @param cls closure (set from GNUNET_MESH_connect)
2328  * @param tunnel connection to the other end (henceforth invalid)
2329  * @param tunnel_ctx place where local state associated
2330  *                   with the tunnel is stored
2331  */
2332 static void
2333 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
2334               void *tunnel_ctx)
2335 {
2336   struct TunnelState *s = tunnel_ctx;
2337   struct TunnelMessageQueue *tnq;
2338
2339   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2340               "Tunnel destroyed\n");
2341   while (NULL != (tnq = s->head))
2342   {
2343     GNUNET_CONTAINER_DLL_remove (s->head,
2344                                  s->tail,
2345                                  tnq);
2346     GNUNET_free (tnq);
2347   }
2348   if (s->heap_node != NULL)
2349   {
2350     GNUNET_assert (GNUNET_YES ==
2351                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
2352                                                          &s->state_key,
2353                                                          s));
2354     GNUNET_CONTAINER_heap_remove_node (s->heap_node);
2355     s->heap_node = NULL;
2356   }
2357   if (NULL != s->th)
2358   {
2359     GNUNET_MESH_notify_transmit_ready_cancel (s->th);
2360     s->th = NULL;
2361   }
2362   GNUNET_free (s);
2363 }
2364
2365
2366 /**
2367  * Function that frees everything from a hashmap
2368  *
2369  * @param cls unused
2370  * @param hash key
2371  * @param value value to free
2372  */
2373 static int
2374 free_iterate (void *cls GNUNET_UNUSED,
2375               const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
2376 {
2377   GNUNET_free (value);
2378   return GNUNET_YES;
2379 }
2380
2381
2382 /**
2383  * Function scheduled as very last function, cleans up after us
2384  */
2385 static void
2386 cleanup (void *cls GNUNET_UNUSED,
2387          const struct GNUNET_SCHEDULER_TaskContext *tskctx)
2388 {
2389   unsigned int i;
2390
2391   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2392               "Exit service is shutting down now\n");
2393   if (helper_handle != NULL)
2394   {
2395     GNUNET_HELPER_stop (helper_handle);
2396     helper_handle = NULL;
2397   }
2398   if (mesh_handle != NULL)
2399   {
2400     GNUNET_MESH_disconnect (mesh_handle);
2401     mesh_handle = NULL;
2402   }
2403   if (NULL != connections_map)
2404   {
2405     GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
2406     GNUNET_CONTAINER_multihashmap_destroy (connections_map);
2407     connections_map = NULL;
2408   }
2409   if (NULL != connections_heap)
2410   {
2411     GNUNET_CONTAINER_heap_destroy (connections_heap);
2412     connections_heap = NULL;
2413   }
2414   if (NULL != tcp_services)
2415   {
2416     GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
2417     GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
2418     tcp_services = NULL;
2419   }
2420   if (NULL != udp_services)
2421   {
2422     GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
2423     GNUNET_CONTAINER_multihashmap_destroy (udp_services);
2424     udp_services = NULL;
2425   }
2426   if (stats != NULL)
2427   {
2428     GNUNET_STATISTICS_destroy (stats, GNUNET_YES);
2429     stats = NULL;
2430   }
2431   for (i=0;i<5;i++)
2432     GNUNET_free_non_null (exit_argv[i]);
2433 }
2434
2435
2436 /**
2437  * Add services to the service map.
2438  *
2439  * @param proto IPPROTO_TCP or IPPROTO_UDP
2440  * @param cpy copy of the service descriptor (can be mutilated)
2441  * @param name DNS name of the service
2442  */
2443 static void
2444 add_services (int proto,
2445               char *cpy,
2446               const char *name)
2447 {
2448   char *redirect;
2449   char *hostname;
2450   char *hostport;
2451   struct LocalService *serv;
2452
2453   for (redirect = strtok (cpy, " "); redirect != NULL;
2454        redirect = strtok (NULL, " "))
2455   {
2456     if (NULL == (hostname = strstr (redirect, ":")))
2457     {
2458       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2459                   "option `%s' for domain `%s' is not formatted correctly!\n",
2460                   redirect,
2461                   name);
2462       continue;
2463     }
2464     hostname[0] = '\0';
2465     hostname++;
2466     if (NULL == (hostport = strstr (hostname, ":")))
2467     {
2468       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2469                   "option `%s' for domain `%s' is not formatted correctly!\n",
2470                   redirect,
2471                   name);
2472       continue;
2473     }
2474     hostport[0] = '\0';
2475     hostport++;
2476     
2477     int local_port = atoi (redirect);
2478     int remote_port = atoi (hostport);
2479     
2480     if (!((local_port > 0) && (local_port < 65536)))
2481     {
2482       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2483                   "`%s' is not a valid port number (for domain `%s')!", redirect,
2484                   name);
2485       continue;
2486     }
2487     if (!((remote_port > 0) && (remote_port < 65536)))
2488     {
2489       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2490                   "`%s' is not a valid port number (for domain `%s')!", hostport,
2491                   name);
2492       continue;
2493     }
2494
2495     serv = GNUNET_malloc (sizeof (struct LocalService));
2496     serv->my_port = (uint16_t) local_port;
2497     serv->address.port = remote_port;
2498     if (0 == strcmp ("localhost4", hostname))
2499     {
2500       const char *ip4addr = exit_argv[4];
2501
2502       serv->address.af = AF_INET;      
2503       GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
2504     }
2505     else if (0 == strcmp ("localhost6", hostname))
2506     {
2507       const char *ip6addr = exit_argv[2];
2508
2509       serv->address.af = AF_INET6;
2510       GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
2511     }
2512     else
2513     {
2514       struct addrinfo *res;      
2515       int ret;
2516
2517       ret = getaddrinfo (hostname, NULL, NULL, &res);      
2518       if ( (ret != 0) || (res == NULL) )
2519       {
2520         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2521                     _("No addresses found for hostname `%s' of service `%s'!\n"),
2522                     hostname,
2523                     name);
2524         GNUNET_free (serv);
2525         continue;
2526       }
2527       
2528       serv->address.af = res->ai_family;
2529       switch (res->ai_family)
2530       {
2531       case AF_INET:
2532         if (! ipv4_enabled)
2533         {
2534           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2535                       _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
2536                       name);
2537           freeaddrinfo (res);
2538           GNUNET_free (serv);
2539           continue;
2540         }
2541         serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
2542         break;
2543       case AF_INET6:
2544         if (! ipv6_enabled)
2545         {
2546           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2547                       _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
2548                       name);
2549           freeaddrinfo (res);
2550           GNUNET_free (serv);
2551           continue;
2552         }       
2553         serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
2554         break;
2555       default:
2556         freeaddrinfo (res);
2557         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2558                     _("No IP addresses found for hostname `%s' of service `%s'!\n"),
2559                     hostname,
2560                     name);
2561         GNUNET_free (serv);
2562         continue;
2563       }
2564       freeaddrinfo (res);
2565     }
2566     store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
2567                    name,
2568                    local_port,
2569                    serv);
2570   }
2571 }
2572
2573
2574 /**
2575  * Reads the configuration servicecfg and populates udp_services
2576  *
2577  * @param cls unused
2578  * @param section name of section in config, equal to hostname
2579  */
2580 static void
2581 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
2582 {
2583   char *cpy;
2584
2585   if ((strlen (section) < 8) ||
2586       (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
2587     return;
2588   if (GNUNET_OK ==
2589       GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
2590                                              &cpy))
2591   {
2592     add_services (IPPROTO_UDP, cpy, section);
2593     GNUNET_free (cpy);
2594   }
2595   if (GNUNET_OK ==
2596       GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
2597                                              &cpy))
2598   {
2599     add_services (IPPROTO_TCP, cpy, section);
2600     GNUNET_free (cpy);
2601   }
2602 }
2603
2604
2605 /**
2606  * @brief Main function that will be run by the scheduler.
2607  *
2608  * @param cls closure
2609  * @param args remaining command-line arguments
2610  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
2611  * @param cfg_ configuration
2612  */
2613 static void
2614 run (void *cls, char *const *args GNUNET_UNUSED,
2615      const char *cfgfile GNUNET_UNUSED,
2616      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2617 {
2618   static struct GNUNET_MESH_MessageHandler handlers[] = {
2619     {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0},
2620     {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0},
2621     {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0},
2622     {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0},
2623     {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0},
2624     {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0},
2625     {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0},
2626     {NULL, 0, 0}
2627   };
2628
2629   static GNUNET_MESH_ApplicationType apptypes[] = {
2630     GNUNET_APPLICATION_TYPE_END,
2631     GNUNET_APPLICATION_TYPE_END,
2632     GNUNET_APPLICATION_TYPE_END
2633   };
2634   unsigned int app_idx;
2635   char *exit_ifname;
2636   char *tun_ifname;
2637   char *ipv6addr;
2638   char *ipv6prefix_s;
2639   char *ipv4addr;
2640   char *ipv4mask;
2641
2642   cfg = cfg_;
2643   stats = GNUNET_STATISTICS_create ("exit", cfg);
2644   ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
2645   ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6"); 
2646   ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4");
2647   ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6"); 
2648   if (ipv4_exit && (! ipv4_enabled))
2649   {
2650     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2651                 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
2652     ipv4_enabled = GNUNET_YES;
2653   }
2654   if (ipv6_exit && (! ipv6_enabled))
2655   {
2656     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2657                 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
2658     ipv6_enabled = GNUNET_YES;
2659   }
2660   if (! (ipv4_enabled || ipv6_enabled))
2661   {
2662     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2663                 _("No useful service enabled.  Exiting.\n"));
2664     GNUNET_SCHEDULER_shutdown ();
2665     return;    
2666   }
2667   app_idx = 0;
2668   if (GNUNET_YES == ipv4_exit)    
2669   {
2670     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
2671     app_idx++;
2672   }
2673   if (GNUNET_YES == ipv6_exit)    
2674   {
2675     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
2676     app_idx++;
2677   }
2678
2679   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
2680
2681   if (GNUNET_OK !=
2682       GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
2683                                              &max_connections))
2684     max_connections = 1024;
2685   exit_argv[0] = GNUNET_strdup ("exit-gnunet");
2686   if (GNUNET_SYSERR ==
2687       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", &tun_ifname))
2688   {
2689     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2690                 "No entry 'TUN_IFNAME' in configuration!\n");
2691     GNUNET_SCHEDULER_shutdown ();
2692     return;
2693   }
2694   exit_argv[1] = tun_ifname;
2695   if (ipv4_enabled)
2696   {
2697     if (GNUNET_SYSERR ==
2698         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", &exit_ifname))
2699     {
2700       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2701                   "No entry 'EXIT_IFNAME' in configuration!\n");
2702       GNUNET_SCHEDULER_shutdown ();
2703       return;
2704     }
2705     exit_argv[2] = exit_ifname;
2706   }
2707   else
2708   {
2709     exit_argv[2] = GNUNET_strdup ("%");
2710   }
2711   if (GNUNET_YES == ipv6_enabled)
2712   {
2713     if ( (GNUNET_SYSERR ==
2714           GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
2715                                                  &ipv6addr) ||
2716           (1 != inet_pton (AF_INET6, ipv6addr, &exit_ipv6addr))) )
2717     {
2718       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2719                   "No valid entry 'IPV6ADDR' in configuration!\n");
2720       GNUNET_SCHEDULER_shutdown ();
2721       return;
2722     }
2723     exit_argv[3] = ipv6addr;
2724     if (GNUNET_SYSERR ==
2725         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
2726                                                &ipv6prefix_s))
2727     {
2728       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2729                   "No entry 'IPV6PREFIX' in configuration!\n");
2730       GNUNET_SCHEDULER_shutdown ();
2731       return;
2732     }
2733     exit_argv[4] = ipv6prefix_s;
2734     if ( (GNUNET_OK !=
2735           GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
2736                                                  "IPV6PREFIX",
2737                                                  &ipv6prefix)) ||
2738          (ipv6prefix >= 127) )
2739     {
2740       GNUNET_SCHEDULER_shutdown ();
2741       return;
2742     }
2743   } 
2744   else
2745   {
2746     /* IPv6 explicitly disabled */
2747     exit_argv[3] = GNUNET_strdup ("-");
2748     exit_argv[4] = GNUNET_strdup ("-");
2749   }
2750   if (GNUNET_YES == ipv4_enabled)
2751   {
2752     if ( (GNUNET_SYSERR ==
2753           GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
2754                                                  &ipv4addr) ||
2755           (1 != inet_pton (AF_INET, ipv4addr, &exit_ipv4addr))) )
2756       {
2757         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2758                     "No valid entry for 'IPV4ADDR' in configuration!\n");
2759         GNUNET_SCHEDULER_shutdown ();
2760         return;
2761       }
2762     exit_argv[5] = ipv4addr;
2763     if ( (GNUNET_SYSERR ==
2764           GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
2765                                                  &ipv4mask) ||
2766           (1 != inet_pton (AF_INET, ipv4mask, &exit_ipv4mask))) )
2767     {
2768       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2769                   "No valid entry 'IPV4MASK' in configuration!\n");
2770       GNUNET_SCHEDULER_shutdown ();
2771       return;
2772     }
2773     exit_argv[6] = ipv4mask;
2774   }
2775   else
2776   {
2777     /* IPv4 explicitly disabled */
2778     exit_argv[5] = GNUNET_strdup ("-");
2779     exit_argv[6] = GNUNET_strdup ("-");
2780   }
2781   exit_argv[7] = NULL;
2782
2783   udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
2784   tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
2785   GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
2786
2787   connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
2788   connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2789   mesh_handle 
2790     = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL, 
2791                            &new_tunnel, 
2792                            &clean_tunnel, handlers,
2793                            apptypes);
2794   if (NULL == mesh_handle)
2795   {
2796     GNUNET_SCHEDULER_shutdown ();
2797     return;
2798   }
2799   helper_handle = GNUNET_HELPER_start ("gnunet-helper-exit", 
2800                                        exit_argv,
2801                                        &message_token, NULL);
2802 }
2803
2804
2805 /**
2806  * The main function
2807  *
2808  * @param argc number of arguments from the command line
2809  * @param argv command line arguments
2810  * @return 0 ok, 1 on error
2811  */
2812 int
2813 main (int argc, char *const *argv)
2814 {
2815   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
2816     GNUNET_GETOPT_OPTION_END
2817   };
2818
2819   return (GNUNET_OK ==
2820           GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
2821                               gettext_noop
2822                               ("Daemon to run to provide an IP exit node for the VPN"),
2823                               options, &run, NULL)) ? 0 : 1;
2824 }
2825
2826
2827 /* end of gnunet-daemon-exit.c */