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