3d94c9dba798fc7991181365d78907f417f0268b
[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 received.  Ignored.\n"));
1026         return;
1027       }
1028     }
1029     break;
1030   case ETH_P_IPV6:
1031     {
1032       const struct GNUNET_TUN_IPv6Header *pkt6;
1033
1034       if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1035       {
1036         /* Kernel to blame? */
1037         GNUNET_break (0);
1038         return;
1039       }
1040       pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1041       if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
1042       {
1043         /* Kernel to blame? */
1044         GNUNET_break (0);
1045         return;
1046       }
1047       size -= sizeof (struct GNUNET_TUN_IPv6Header);
1048       switch (pkt6->next_header)
1049       {
1050       case IPPROTO_UDP:
1051         udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
1052                          AF_INET6,
1053                          &pkt6->destination_address, 
1054                          &pkt6->source_address);
1055         break;
1056       case IPPROTO_TCP:
1057         tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
1058                          AF_INET6,
1059                          &pkt6->destination_address, 
1060                          &pkt6->source_address);
1061         break;
1062       case IPPROTO_ICMP:
1063         icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1064                           AF_INET6,
1065                           &pkt6->destination_address, 
1066                           &pkt6->source_address);
1067         break;
1068       default:
1069         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1070                     _("IPv6 packet with unsupported next header received.  Ignored.\n"));
1071         return;
1072       }
1073     }
1074     break;
1075   default:
1076     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1077                 _("Packet from unknown protocol %u received.  Ignored.\n"),
1078                 ntohs (pkt_tun->proto));
1079     break;
1080   }
1081 }
1082
1083
1084 /**
1085  * We need to create a (unique) fresh local address (IP+port).
1086  * Fill one in.
1087  *
1088  * @param af desired address family
1089  * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1090  * @param local_address address to initialize
1091  */
1092 static void
1093 setup_fresh_address (int af,
1094                      uint8_t proto,
1095                      struct SocketAddress *local_address)
1096 {
1097   local_address->af = af;
1098   local_address->proto = (uint8_t) proto;
1099   /* default "local" port range is often 32768--61000,
1100      so we pick a random value in that range */  
1101   if (proto == IPPROTO_ICMP)
1102     local_address->port = 0;
1103   else
1104     local_address->port 
1105       = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1106                                                      28232);      
1107   switch (af)
1108   {
1109   case AF_INET:
1110     {
1111       struct in_addr addr;
1112       struct in_addr mask;
1113       struct in_addr rnd;
1114
1115       addr = exit_ipv4addr;
1116       mask = exit_ipv4mask;
1117       if (0 == ~mask.s_addr)
1118       {
1119         /* only one valid IP anyway */
1120         local_address->address.ipv4 = addr;
1121         return;
1122       }
1123       /* Given 192.168.0.1/255.255.0.0, we want a mask 
1124          of '192.168.255.255', thus:  */
1125       mask.s_addr = addr.s_addr | ~mask.s_addr;
1126       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1127       do
1128         {
1129           rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1130                                                  UINT32_MAX);   
1131           local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1132         }
1133       while ( (local_address->address.ipv4.s_addr == addr.s_addr) ||
1134               (local_address->address.ipv4.s_addr == mask.s_addr) );
1135     }
1136     break;
1137   case AF_INET6:
1138     {
1139       struct in6_addr addr;
1140       struct in6_addr mask;
1141       struct in6_addr rnd;
1142       int i;
1143       
1144       addr = exit_ipv6addr;
1145       GNUNET_assert (ipv6prefix < 128);
1146       if (ipv6prefix == 127)
1147       {
1148         /* only one valid IP anyway */
1149         local_address->address.ipv6 = addr;
1150         return;
1151       }
1152       /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1153          thus: */
1154       mask = addr;
1155       for (i=127;i>=ipv6prefix;i--)
1156         mask.s6_addr[i / 8] |= (1 << (i % 8));
1157       
1158       /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1159       do
1160         {
1161           for (i=0;i<16;i++)
1162           {
1163             rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 
1164                                                                        256);
1165             local_address->address.ipv6.s6_addr[i]
1166               = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1167           }
1168         }
1169       while ( (0 == memcmp (&local_address->address.ipv6,
1170                             &addr,
1171                             sizeof (struct in6_addr))) ||
1172               (0 == memcmp (&local_address->address.ipv6,
1173                             &mask,
1174                             sizeof (struct in6_addr))) );
1175     }
1176     break;
1177   default:
1178     GNUNET_assert (0);
1179   }  
1180 }
1181
1182
1183 /**
1184  * We are starting a fresh connection (TCP or UDP) and need
1185  * to pick a source port and IP address (within the correct
1186  * range and address family) to associate replies with the
1187  * connection / correct mesh tunnel.  This function generates
1188  * a "fresh" source IP and source port number for a connection
1189  * After picking a good source address, this function sets up
1190  * the state in the 'connections_map' and 'connections_heap'
1191  * to allow finding the state when needed later.  The function
1192  * also makes sure that we remain within memory limits by
1193  * cleaning up 'old' states.
1194  *
1195  * @param state skeleton state to setup a record for; should
1196  *              'state->ri.remote_address' filled in so that
1197  *              this code can determine which AF/protocol is
1198  *              going to be used (the 'tunnel' should also
1199  *              already be set); after calling this function,
1200  *              heap_node and the local_address will be
1201  *              also initialized (heap_node != NULL can be
1202  *              used to test if a state has been fully setup).
1203  */
1204 static void
1205 setup_state_record (struct TunnelState *state)
1206 {
1207   GNUNET_HashCode key;
1208   struct TunnelState *s;
1209
1210   /* generate fresh, unique address */
1211   do
1212   {
1213     if (NULL == state->serv)
1214       setup_fresh_address (state->ri.remote_address.af,
1215                            state->ri.remote_address.proto,
1216                            &state->ri.local_address);
1217     else
1218       setup_fresh_address (state->serv->address.af,
1219                            state->serv->address.proto,
1220                            &state->ri.local_address);
1221   } while (NULL != get_redirect_state (state->ri.remote_address.af,
1222                                        state->ri.remote_address.proto,
1223                                        &state->ri.remote_address.address,
1224                                        state->ri.remote_address.port,
1225                                        &state->ri.local_address.address,
1226                                        state->ri.local_address.port,
1227                                        &key));
1228   {
1229     char buf[INET6_ADDRSTRLEN];
1230     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1231                 "Picked local address %s:%u for new connection\n",
1232                 inet_ntop (state->ri.local_address.af, 
1233                            &state->ri.local_address.address,
1234                            buf, sizeof (buf)),
1235                 (unsigned int) state->ri.local_address.port);
1236   }
1237   state->state_key = key;
1238   GNUNET_assert (GNUNET_OK ==
1239                  GNUNET_CONTAINER_multihashmap_put (connections_map, 
1240                                                     &key, state,
1241                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1242   state->heap_node = GNUNET_CONTAINER_heap_insert (connections_heap,
1243                                                    state,
1244                                                    GNUNET_TIME_absolute_get ().abs_value);   
1245   while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1246   {
1247     s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1248     GNUNET_assert (state != s);
1249     s->heap_node = NULL;
1250     GNUNET_MESH_tunnel_destroy (s->tunnel);
1251     GNUNET_assert (GNUNET_OK ==
1252                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
1253                                                          &s->state_key, 
1254                                                          s));
1255     GNUNET_free (s);
1256   }
1257 }
1258
1259
1260 /**
1261  * Prepare an IPv4 packet for transmission via the TUN interface.
1262  * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1263  * For UDP, the UDP header will be fully created, whereas for TCP
1264  * only the ports and checksum will be filled in.  So for TCP,
1265  * a skeleton TCP header must be part of the provided payload.
1266  *
1267  * @param payload payload of the packet (starting with UDP payload or
1268  *                TCP header, depending on protocol)
1269  * @param payload_length number of bytes in 'payload'
1270  * @param protocol IPPROTO_UDP or IPPROTO_TCP
1271  * @param tcp_header skeleton of the TCP header, NULL for UDP
1272  * @param src_address source address to use (IP and port)
1273  * @param dst_address destination address to use (IP and port)
1274  * @param pkt4 where to write the assembled packet; must
1275  *        contain enough space for the IP header, UDP/TCP header
1276  *        AND the payload
1277  */
1278 static void
1279 prepare_ipv4_packet (const void *payload, size_t payload_length,
1280                      int protocol,
1281                      const struct GNUNET_TUN_TcpHeader *tcp_header,
1282                      const struct SocketAddress *src_address,
1283                      const struct SocketAddress *dst_address,
1284                      struct GNUNET_TUN_IPv4Header *pkt4)
1285 {
1286   size_t len;
1287
1288   len = payload_length;
1289   switch (protocol)
1290   {
1291   case IPPROTO_UDP:
1292     len += sizeof (struct GNUNET_TUN_UdpHeader);
1293     break;
1294   case IPPROTO_TCP:
1295     len += sizeof (struct GNUNET_TUN_TcpHeader);
1296     GNUNET_assert (NULL != tcp_header);
1297     break;
1298   default:
1299     GNUNET_break (0);
1300     return;
1301   }
1302   if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1303   {
1304     GNUNET_break (0);
1305     return;
1306   }
1307
1308   GNUNET_TUN_initialize_ipv4_header (pkt4,
1309                                      protocol,
1310                                      len,
1311                                      &src_address->address.ipv4,
1312                                      &dst_address->address.ipv4);
1313   switch (protocol)
1314   {
1315   case IPPROTO_UDP:
1316     {
1317       struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1318
1319       pkt4_udp->source_port = htons (src_address->port);
1320       pkt4_udp->destination_port = htons (dst_address->port);
1321       pkt4_udp->len = htons ((uint16_t) payload_length);
1322       GNUNET_TUN_calculate_udp4_checksum (pkt4,
1323                                           pkt4_udp,
1324                                           payload, payload_length);
1325       memcpy (&pkt4_udp[1], payload, payload_length);
1326     }
1327     break;
1328   case IPPROTO_TCP:
1329     {
1330       struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1331       
1332       *pkt4_tcp = *tcp_header;
1333       pkt4_tcp->source_port = htons (src_address->port);
1334       pkt4_tcp->destination_port = htons (dst_address->port);
1335       GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1336                                           pkt4_tcp,
1337                                           payload,
1338                                           payload_length);
1339       memcpy (&pkt4_tcp[1], payload, payload_length);
1340     }
1341     break;
1342   default:
1343     GNUNET_assert (0);
1344   }
1345 }
1346
1347
1348 /**
1349  * Prepare an IPv6 packet for transmission via the TUN interface.
1350  * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1351  * For UDP, the UDP header will be fully created, whereas for TCP
1352  * only the ports and checksum will be filled in.  So for TCP,
1353  * a skeleton TCP header must be part of the provided payload.
1354  *
1355  * @param payload payload of the packet (starting with UDP payload or
1356  *                TCP header, depending on protocol)
1357  * @param payload_length number of bytes in 'payload'
1358  * @param protocol IPPROTO_UDP or IPPROTO_TCP
1359  * @param tcp_header skeleton TCP header data to send, NULL for UDP
1360  * @param src_address source address to use (IP and port)
1361  * @param dst_address destination address to use (IP and port)
1362  * @param pkt6 where to write the assembled packet; must
1363  *        contain enough space for the IP header, UDP/TCP header
1364  *        AND the payload
1365  */
1366 static void
1367 prepare_ipv6_packet (const void *payload, size_t payload_length,
1368                      int protocol,
1369                      const struct GNUNET_TUN_TcpHeader *tcp_header,
1370                      const struct SocketAddress *src_address,
1371                      const struct SocketAddress *dst_address,
1372                      struct GNUNET_TUN_IPv6Header *pkt6)
1373 {
1374   size_t len;
1375
1376   len = payload_length;
1377   switch (protocol)
1378   {
1379   case IPPROTO_UDP:
1380     len += sizeof (struct GNUNET_TUN_UdpHeader);
1381     break;
1382   case IPPROTO_TCP:
1383     len += sizeof (struct GNUNET_TUN_TcpHeader);
1384     break;
1385   default:
1386     GNUNET_break (0);
1387     return;
1388   }
1389   if (len > UINT16_MAX)
1390   {
1391     GNUNET_break (0);
1392     return;
1393   }
1394
1395   GNUNET_TUN_initialize_ipv6_header (pkt6,
1396                                      protocol,
1397                                      len,                                  
1398                                      &src_address->address.ipv6,
1399                                      &dst_address->address.ipv6);
1400
1401   switch (protocol)
1402   {
1403   case IPPROTO_UDP:
1404     {
1405       struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1406
1407       pkt6_udp->source_port = htons (src_address->port);
1408       pkt6_udp->destination_port = htons (dst_address->port);
1409       pkt6_udp->len = htons ((uint16_t) payload_length);
1410       GNUNET_TUN_calculate_udp6_checksum (pkt6,
1411                                           pkt6_udp,
1412                                           payload,
1413                                           payload_length);
1414       memcpy (&pkt6_udp[1], payload, payload_length);
1415     }
1416     break;
1417   case IPPROTO_TCP:
1418     {
1419       struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
1420
1421       /* memcpy first here as some TCP header fields are initialized this way! */
1422       *pkt6_tcp = *tcp_header;
1423       pkt6_tcp->source_port = htons (src_address->port);
1424       pkt6_tcp->destination_port = htons (dst_address->port);
1425       GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1426                                           pkt6_tcp,
1427                                           payload,
1428                                           payload_length);
1429       memcpy (&pkt6_tcp[1], payload, payload_length);
1430     }
1431     break;
1432   default:
1433     GNUNET_assert (0);
1434     break;
1435   }
1436 }
1437
1438
1439 /**
1440  * Send a TCP packet via the TUN interface.
1441  *
1442  * @param destination_address IP and port to use for the TCP packet's destination
1443  * @param source_address IP and port to use for the TCP packet's source
1444  * @param tcp_header header template to use
1445  * @param payload payload of the TCP packet
1446  * @param payload_length number of bytes in 'payload'
1447  */
1448 static void
1449 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1450                          const struct SocketAddress *source_address,
1451                          const struct GNUNET_TUN_TcpHeader *tcp_header,
1452                          const void *payload, size_t payload_length)
1453 {
1454   size_t len;
1455
1456   GNUNET_STATISTICS_update (stats,
1457                             gettext_noop ("# TCP packets sent via TUN"),
1458                             1, GNUNET_NO);
1459   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1460               "Sending packet with %u bytes TCP payload via TUN\n",
1461               (unsigned int) payload_length);
1462   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1463   switch (source_address->af)
1464   {
1465   case AF_INET:
1466     len += sizeof (struct GNUNET_TUN_IPv4Header);
1467     break;
1468   case AF_INET6:
1469     len += sizeof (struct GNUNET_TUN_IPv6Header);
1470     break;
1471   default:
1472     GNUNET_break (0);
1473     return;
1474   }
1475   len += sizeof (struct GNUNET_TUN_TcpHeader);
1476   len += payload_length;
1477   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1478   {
1479     GNUNET_break (0);
1480     return;
1481   }
1482   {
1483     char buf[len];
1484     struct GNUNET_MessageHeader *hdr;
1485     struct GNUNET_TUN_Layer2PacketHeader *tun;
1486     
1487     hdr = (struct GNUNET_MessageHeader *) buf;
1488     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1489     hdr->size = htons (len);
1490     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1491     tun->flags = htons (0);
1492     switch (source_address->af)
1493     {
1494     case AF_INET:
1495       {
1496         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1497         
1498         tun->proto = htons (ETH_P_IPV4);
1499         prepare_ipv4_packet (payload, payload_length,
1500                              IPPROTO_TCP,
1501                              tcp_header, 
1502                              source_address,
1503                              destination_address,
1504                              ipv4);
1505       }
1506       break;
1507     case AF_INET6:
1508       {
1509         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1510         
1511         tun->proto = htons (ETH_P_IPV6);
1512         prepare_ipv6_packet (payload, payload_length, 
1513                              IPPROTO_TCP,
1514                              tcp_header, 
1515                              source_address,
1516                              destination_address,
1517                              ipv6);
1518       }
1519       break;    
1520     default:
1521       GNUNET_assert (0);
1522       break;
1523     }
1524     (void) GNUNET_HELPER_send (helper_handle,
1525                                (const struct GNUNET_MessageHeader*) buf,
1526                                GNUNET_YES,
1527                                NULL, NULL);
1528   }
1529 }
1530
1531
1532 /**
1533  * Process a request via mesh to send a request to a TCP service
1534  * offered by this system.
1535  *
1536  * @param cls closure, NULL
1537  * @param tunnel connection to the other end
1538  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1539  * @param sender who sent the message
1540  * @param message the actual message
1541  * @param atsi performance data for the connection
1542  * @return GNUNET_OK to keep the connection open,
1543  *         GNUNET_SYSERR to close it (signal serious error)
1544  */
1545 static int
1546 receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1547                      void **tunnel_ctx GNUNET_UNUSED,
1548                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1549                      const struct GNUNET_MessageHeader *message,
1550                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1551 {
1552   struct TunnelState *state = *tunnel_ctx;
1553   const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1554   uint16_t pkt_len = ntohs (message->size);
1555
1556   GNUNET_STATISTICS_update (stats,
1557                             gettext_noop ("# TCP service creation requests received via mesh"),
1558                             1, GNUNET_NO);
1559   GNUNET_STATISTICS_update (stats,
1560                             gettext_noop ("# Bytes received from MESH"),
1561                             pkt_len, GNUNET_NO);
1562   /* check that we got at least a valid header */
1563   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1564   {
1565     GNUNET_break_op (0);
1566     return GNUNET_SYSERR;
1567   }
1568   start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1569   pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1570   if ( (NULL == state) ||
1571        (NULL != state->serv) ||
1572        (NULL != state->heap_node) )
1573   {
1574     GNUNET_break_op (0);
1575     return GNUNET_SYSERR;
1576   }
1577   if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1578   {
1579     GNUNET_break_op (0);
1580     return GNUNET_SYSERR;
1581   }
1582   GNUNET_break_op (ntohl (start->reserved) == 0);
1583   /* setup fresh connection */
1584   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1585               "Received data from %s for forwarding to TCP service %s on port %u\n",
1586               GNUNET_i2s (sender),
1587               GNUNET_h2s (&start->service_descriptor),
1588               (unsigned int) ntohs (start->tcp_header.destination_port));  
1589   if (NULL == (state->serv = find_service (tcp_services, &start->service_descriptor, 
1590                                            ntohs (start->tcp_header.destination_port))))
1591   {
1592     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1593                 _("No service found for %s on port %d!\n"),
1594                 "TCP",
1595                 ntohs (start->tcp_header.destination_port));
1596     GNUNET_STATISTICS_update (stats,
1597                               gettext_noop ("# TCP requests dropped (no such service)"),
1598                               1, GNUNET_NO);
1599     return GNUNET_SYSERR;
1600   }
1601   state->ri.remote_address = state->serv->address;    
1602   setup_state_record (state);
1603   send_tcp_packet_via_tun (&state->ri.remote_address,
1604                            &state->ri.local_address,
1605                            &start->tcp_header,
1606                            &start[1], pkt_len);
1607   return GNUNET_YES;
1608 }
1609
1610
1611 /**
1612  * Process a request to forward TCP data to the Internet via this peer.
1613  *
1614  * @param cls closure, NULL
1615  * @param tunnel connection to the other end
1616  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1617  * @param sender who sent the message
1618  * @param message the actual message
1619  * @param atsi performance data for the connection
1620  * @return GNUNET_OK to keep the connection open,
1621  *         GNUNET_SYSERR to close it (signal serious error)
1622  */
1623 static int
1624 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1625                     void **tunnel_ctx GNUNET_UNUSED,
1626                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1627                     const struct GNUNET_MessageHeader *message,
1628                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1629 {
1630   struct TunnelState *state = *tunnel_ctx;
1631   const struct GNUNET_EXIT_TcpInternetStartMessage *start;
1632   uint16_t pkt_len = ntohs (message->size);
1633   const struct in_addr *v4;
1634   const struct in6_addr *v6;
1635   const void *payload;
1636   int af;
1637
1638   GNUNET_STATISTICS_update (stats,
1639                             gettext_noop ("# Bytes received from MESH"),
1640                             pkt_len, GNUNET_NO);
1641   GNUNET_STATISTICS_update (stats,
1642                             gettext_noop ("# TCP IP-exit creation requests received via mesh"),
1643                             1, GNUNET_NO);
1644   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
1645   {
1646     GNUNET_break_op (0);
1647     return GNUNET_SYSERR;
1648   }
1649   start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
1650   pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);  
1651   if ( (NULL == state) ||
1652        (NULL != state->serv) ||
1653        (NULL != state->heap_node) )
1654   {
1655     GNUNET_break_op (0);
1656     return GNUNET_SYSERR;
1657   }
1658   if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1659   {
1660     GNUNET_break_op (0);
1661     return GNUNET_SYSERR;
1662   }
1663   af = (int) ntohl (start->af);
1664   state->ri.remote_address.af = af;
1665   switch (af)
1666   {
1667   case AF_INET:
1668     if (pkt_len < sizeof (struct in_addr))
1669     {
1670       GNUNET_break_op (0);
1671       return GNUNET_SYSERR;
1672     }
1673     if (! ipv4_exit)
1674     {
1675       GNUNET_break_op (0);
1676       return GNUNET_SYSERR;
1677     }
1678     v4 = (const struct in_addr*) &start[1];
1679     payload = &v4[1];
1680     pkt_len -= sizeof (struct in_addr);
1681     state->ri.remote_address.address.ipv4 = *v4;
1682     break;
1683   case AF_INET6:
1684     if (pkt_len < sizeof (struct in6_addr))
1685     {
1686       GNUNET_break_op (0);
1687       return GNUNET_SYSERR;
1688     }
1689     if (! ipv6_exit)
1690     {
1691       GNUNET_break_op (0);
1692       return GNUNET_SYSERR;
1693     }
1694     v6 = (const struct in6_addr*) &start[1];
1695     payload = &v6[1];
1696     pkt_len -= sizeof (struct in6_addr);
1697     state->ri.remote_address.address.ipv6 = *v6;
1698     break;
1699   default:
1700     GNUNET_break_op (0);
1701     return GNUNET_SYSERR;
1702   }
1703   {
1704     char buf[INET6_ADDRSTRLEN];
1705     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1706                 "Received data from %s for starting TCP stream to %s:%u\n",
1707                 GNUNET_i2s (sender),
1708                 inet_ntop (af, 
1709                            &state->ri.remote_address.address,
1710                            buf, sizeof (buf)),
1711                 (unsigned int) ntohs (start->tcp_header.destination_port));  
1712   }
1713   state->ri.remote_address.proto = IPPROTO_TCP;
1714   state->ri.remote_address.port = ntohs (start->tcp_header.destination_port);
1715   setup_state_record (state);
1716   send_tcp_packet_via_tun (&state->ri.remote_address,
1717                            &state->ri.local_address,
1718                            &start->tcp_header,
1719                            payload, pkt_len);
1720   return GNUNET_YES;
1721 }
1722
1723
1724 /**
1725  * Process a request to forward TCP data on an established 
1726  * connection via this peer.
1727  *
1728  * @param cls closure, NULL
1729  * @param tunnel connection to the other end
1730  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1731  * @param sender who sent the message
1732  * @param message the actual message
1733  * @param atsi performance data for the connection
1734  * @return GNUNET_OK to keep the connection open,
1735  *         GNUNET_SYSERR to close it (signal serious error)
1736  */
1737 static int
1738 receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1739                   void **tunnel_ctx GNUNET_UNUSED,
1740                   const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1741                   const struct GNUNET_MessageHeader *message,
1742                   const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1743 {
1744   struct TunnelState *state = *tunnel_ctx;
1745   const struct GNUNET_EXIT_TcpDataMessage *data;
1746   uint16_t pkt_len = ntohs (message->size);
1747
1748   GNUNET_STATISTICS_update (stats,
1749                             gettext_noop ("# Bytes received from MESH"),
1750                             pkt_len, GNUNET_NO);
1751   GNUNET_STATISTICS_update (stats,
1752                             gettext_noop ("# TCP data requests received via mesh"),
1753                             1, GNUNET_NO);
1754   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
1755   {
1756     GNUNET_break_op (0);
1757     return GNUNET_SYSERR;
1758   }
1759   data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
1760   pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);  
1761   if ( (NULL == state) ||
1762        (NULL == state->heap_node) )
1763   {
1764     /* connection should have been up! */
1765     GNUNET_STATISTICS_update (stats,
1766                               gettext_noop ("# TCP DATA requests dropped (no session)"),
1767                               1, GNUNET_NO);
1768     return GNUNET_SYSERR;
1769   }
1770   if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1771   {
1772     GNUNET_break_op (0);
1773     return GNUNET_SYSERR;
1774   }
1775
1776   GNUNET_break_op (ntohl (data->reserved) == 0);
1777   {
1778     char buf[INET6_ADDRSTRLEN];
1779     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1780                 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
1781                 pkt_len,
1782                 GNUNET_i2s (sender),
1783                 inet_ntop (state->ri.remote_address.af, 
1784                            &state->ri.remote_address.address,
1785                            buf, sizeof (buf)),
1786                 (unsigned int) state->ri.remote_address.port);
1787   }
1788
1789   send_tcp_packet_via_tun (&state->ri.remote_address,
1790                            &state->ri.local_address,
1791                            &data->tcp_header,
1792                            &data[1], pkt_len);
1793   return GNUNET_YES;
1794 }
1795
1796
1797 /**
1798  * Send an ICMP packet via the TUN interface.
1799  *
1800  * @param destination_address IP to use for the ICMP packet's destination
1801  * @param source_address IP to use for the ICMP packet's source
1802  * @param icmp_header ICMP header to send
1803  * @param payload payload of the ICMP packet (does NOT include ICMP header)
1804  * @param payload_length number of bytes of data in payload
1805  */
1806 static void
1807 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
1808                           const struct SocketAddress *source_address,
1809                           const struct GNUNET_TUN_IcmpHeader *icmp_header,
1810                           const void *payload, size_t payload_length)
1811 {
1812   size_t len;
1813   struct GNUNET_TUN_IcmpHeader *icmp;
1814
1815   GNUNET_STATISTICS_update (stats,
1816                             gettext_noop ("# ICMP packets sent via TUN"),
1817                             1, GNUNET_NO);
1818   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1819               "Sending packet with %u bytes ICMP payload via TUN\n",
1820               (unsigned int) payload_length);
1821   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1822   switch (destination_address->af)
1823   {
1824   case AF_INET:
1825     len += sizeof (struct GNUNET_TUN_IPv4Header);
1826     break;
1827   case AF_INET6:
1828     len += sizeof (struct GNUNET_TUN_IPv6Header);
1829     break;
1830   default:
1831     GNUNET_break (0);
1832     return;
1833   }
1834   len += sizeof (struct GNUNET_TUN_IcmpHeader);
1835   len += payload_length;
1836   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1837   {
1838     GNUNET_break (0);
1839     return;
1840   }
1841   {
1842     char buf[len];
1843     struct GNUNET_MessageHeader *hdr;
1844     struct GNUNET_TUN_Layer2PacketHeader *tun;
1845     
1846     hdr= (struct GNUNET_MessageHeader *) buf;
1847     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1848     hdr->size = htons (len);
1849     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1850     tun->flags = htons (0);
1851     switch (source_address->af)
1852     {
1853     case AF_INET:
1854       {
1855         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1856         
1857         tun->proto = htons (ETH_P_IPV4);
1858         GNUNET_TUN_initialize_ipv4_header (ipv4,
1859                                            IPPROTO_ICMP,
1860                                            sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1861                                            &source_address->address.ipv4,
1862                                            &destination_address->address.ipv4);
1863         icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
1864       }
1865       break;
1866     case AF_INET6:
1867       {
1868         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1869         
1870         tun->proto = htons (ETH_P_IPV6);
1871         GNUNET_TUN_initialize_ipv6_header (ipv6,
1872                                            IPPROTO_ICMP,
1873                                            sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
1874                                            &source_address->address.ipv6,
1875                                            &destination_address->address.ipv6);
1876         icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
1877       }
1878       break;    
1879     default:
1880       GNUNET_assert (0);
1881       break;
1882     }
1883     *icmp = *icmp_header;
1884     memcpy (&icmp[1],
1885             payload,
1886             payload_length);
1887     GNUNET_TUN_calculate_icmp_checksum (icmp,
1888                                         payload,
1889                                         payload_length);
1890     (void) GNUNET_HELPER_send (helper_handle,
1891                                (const struct GNUNET_MessageHeader*) buf,
1892                                GNUNET_YES,
1893                                NULL, NULL);
1894   }
1895 }
1896
1897
1898 /**
1899  * Synthesize a plausible ICMP payload for an ICMPv4 error
1900  * response on the given tunnel.
1901  *
1902  * @param state tunnel information
1903  * @param ipp IPv6 header to fill in (ICMP payload)
1904  * @param udp "UDP" header to fill in (ICMP payload); might actually
1905  *            also be the first 8 bytes of the TCP header
1906  */
1907 static void
1908 make_up_icmpv4_payload (struct TunnelState *state,
1909                         struct GNUNET_TUN_IPv4Header *ipp,
1910                         struct GNUNET_TUN_UdpHeader *udp)
1911 {
1912   GNUNET_TUN_initialize_ipv4_header (ipp,
1913                                      state->ri.remote_address.proto,
1914                                      sizeof (struct GNUNET_TUN_TcpHeader),
1915                                      &state->ri.remote_address.address.ipv4,
1916                                      &state->ri.local_address.address.ipv4);
1917   udp->source_port = htons (state->ri.remote_address.port);
1918   udp->destination_port = htons (state->ri.local_address.port);
1919   udp->len = htons (0);
1920   udp->crc = htons (0);
1921 }
1922
1923
1924 /**
1925  * Synthesize a plausible ICMP payload for an ICMPv6 error
1926  * response on the given tunnel.
1927  *
1928  * @param state tunnel information
1929  * @param ipp IPv6 header to fill in (ICMP payload)
1930  * @param udp "UDP" header to fill in (ICMP payload); might actually
1931  *            also be the first 8 bytes of the TCP header
1932  */
1933 static void
1934 make_up_icmpv6_payload (struct TunnelState *state,
1935                         struct GNUNET_TUN_IPv6Header *ipp,
1936                         struct GNUNET_TUN_UdpHeader *udp)
1937 {
1938   GNUNET_TUN_initialize_ipv6_header (ipp,
1939                                      state->ri.remote_address.proto,
1940                                      sizeof (struct GNUNET_TUN_TcpHeader),
1941                                      &state->ri.remote_address.address.ipv6,
1942                                      &state->ri.local_address.address.ipv6);
1943   udp->source_port = htons (state->ri.remote_address.port);
1944   udp->destination_port = htons (state->ri.local_address.port);
1945   udp->len = htons (0);
1946   udp->crc = htons (0);
1947 }
1948
1949
1950 /**
1951  * Process a request to forward ICMP data to the Internet via this peer.
1952  *
1953  * @param cls closure, NULL
1954  * @param tunnel connection to the other end
1955  * @param tunnel_ctx pointer to our 'struct TunnelState *'
1956  * @param sender who sent the message
1957  * @param message the actual message
1958  * @param atsi performance data for the connection
1959  * @return GNUNET_OK to keep the connection open,
1960  *         GNUNET_SYSERR to close it (signal serious error)
1961  */
1962 static int
1963 receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1964                      void **tunnel_ctx GNUNET_UNUSED,
1965                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1966                      const struct GNUNET_MessageHeader *message,
1967                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1968 {
1969   struct TunnelState *state = *tunnel_ctx;
1970   const struct GNUNET_EXIT_IcmpInternetMessage *msg;
1971   uint16_t pkt_len = ntohs (message->size);
1972   const struct in_addr *v4;
1973   const struct in6_addr *v6;  
1974   const void *payload;
1975   char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8];
1976   int af;
1977
1978   GNUNET_STATISTICS_update (stats,
1979                             gettext_noop ("# Bytes received from MESH"),
1980                             pkt_len, GNUNET_NO);
1981   GNUNET_STATISTICS_update (stats,
1982                             gettext_noop ("# ICMP IP-exit requests received via mesh"),
1983                             1, GNUNET_NO);
1984   if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
1985   {
1986     GNUNET_break_op (0);
1987     return GNUNET_SYSERR;
1988   }
1989   msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
1990   pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);  
1991
1992   af = (int) ntohl (msg->af);
1993   if ( (NULL != state->heap_node) &&
1994        (af != state->ri.remote_address.af) )
1995   {
1996     /* other peer switched AF on this tunnel; not allowed */
1997     GNUNET_break_op (0);
1998     return GNUNET_SYSERR;
1999   }
2000
2001   switch (af)
2002   {
2003   case AF_INET:
2004     if (pkt_len < sizeof (struct in_addr))
2005     {
2006       GNUNET_break_op (0);
2007       return GNUNET_SYSERR;
2008     }
2009     if (! ipv4_exit)
2010     {
2011       GNUNET_break_op (0);
2012       return GNUNET_SYSERR;
2013     }
2014     v4 = (const struct in_addr*) &msg[1];
2015     payload = &v4[1];
2016     pkt_len -= sizeof (struct in_addr);
2017     state->ri.remote_address.address.ipv4 = *v4;
2018     if (NULL == state->heap_node)
2019     {
2020       state->ri.remote_address.af = af;
2021       state->ri.remote_address.proto = IPPROTO_ICMP;
2022       setup_state_record (state);
2023     }
2024     /* check that ICMP type is something we want to support 
2025        and possibly make up payload! */
2026     switch (msg->icmp_header.type)
2027     {
2028     case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2029     case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2030       break;
2031     case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2032     case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2033     case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2034       if (0 != pkt_len)
2035       {
2036         GNUNET_break_op (0);
2037         return GNUNET_SYSERR;
2038       }
2039       /* make up payload */
2040       {
2041         struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) buf;
2042         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2043
2044         GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2045         pkt_len = sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2046         make_up_icmpv4_payload (state, 
2047                                 ipp,
2048                                 udp);
2049         payload = ipp;
2050       }
2051       break;
2052     default:
2053       GNUNET_break_op (0);
2054       GNUNET_STATISTICS_update (stats,
2055                                 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2056                                 1, GNUNET_NO);
2057       return GNUNET_SYSERR;      
2058     }
2059     /* end AF_INET */
2060     break;
2061   case AF_INET6:
2062     if (pkt_len < sizeof (struct in6_addr))
2063     {
2064       GNUNET_break_op (0);
2065       return GNUNET_SYSERR;
2066     }
2067     if (! ipv6_exit)
2068     {
2069       GNUNET_break_op (0);
2070       return GNUNET_SYSERR;
2071     }
2072     v6 = (const struct in6_addr*) &msg[1];
2073     payload = &v6[1];
2074     pkt_len -= sizeof (struct in6_addr);
2075     state->ri.remote_address.address.ipv6 = *v6;
2076     if (NULL == state->heap_node)
2077     {
2078       state->ri.remote_address.af = af;
2079       state->ri.remote_address.proto = IPPROTO_ICMP;
2080       setup_state_record (state);
2081     }
2082     /* check that ICMP type is something we want to support 
2083        and possibly make up payload! */
2084     switch (msg->icmp_header.type)
2085     {
2086     case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2087     case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2088       break;
2089     case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2090     case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2091     case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2092     case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2093       if (0 != pkt_len)
2094       {
2095         GNUNET_break_op (0);
2096         return GNUNET_SYSERR;
2097       }
2098       /* make up payload */
2099       {
2100         struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) buf;
2101         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2102
2103         GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2104         pkt_len = sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2105         make_up_icmpv6_payload (state, 
2106                                 ipp,
2107                                 udp);
2108         payload = ipp;
2109       }
2110       break;
2111     default:
2112       GNUNET_break_op (0);
2113       GNUNET_STATISTICS_update (stats,
2114                                 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2115                                 1, GNUNET_NO);
2116       return GNUNET_SYSERR;      
2117     }
2118     /* end AF_INET6 */
2119     break;    
2120   default:
2121     /* bad AF */
2122     GNUNET_break_op (0);
2123     return GNUNET_SYSERR;
2124   }
2125  
2126   {
2127     char buf[INET6_ADDRSTRLEN];
2128     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2129                 "Received ICMP data from %s for forwarding to %s\n",
2130                 GNUNET_i2s (sender),
2131                 inet_ntop (af, 
2132                            &state->ri.remote_address.address,
2133                            buf, sizeof (buf)));
2134   }
2135   send_icmp_packet_via_tun (&state->ri.remote_address,
2136                             &state->ri.local_address,
2137                             &msg->icmp_header,
2138                             payload, pkt_len);
2139   return GNUNET_YES;
2140 }
2141
2142
2143 /**
2144  * Setup ICMP payload for ICMP error messages. Called
2145  * for both IPv4 and IPv6 addresses.
2146  *
2147  * @param state context for creating the IP Packet
2148  * @param buf where to create the payload, has at least
2149  *       sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2150  * @return number of bytes of payload we created in buf
2151  */
2152 static uint16_t
2153 make_up_icmp_service_payload (struct TunnelState *state,
2154                               char *buf)
2155 {
2156   switch (state->serv->address.af)
2157   {
2158   case AF_INET:
2159     {
2160       struct GNUNET_TUN_IPv4Header *ipv4;
2161       struct GNUNET_TUN_UdpHeader *udp;
2162       
2163       ipv4 = (struct GNUNET_TUN_IPv4Header *)buf;
2164       udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2165       make_up_icmpv4_payload (state,
2166                               ipv4,
2167                               udp);
2168       GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2169       return sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2170     }
2171     break;
2172   case AF_INET6:
2173     {
2174       struct GNUNET_TUN_IPv6Header *ipv6;
2175       struct GNUNET_TUN_UdpHeader *udp;
2176
2177       ipv6 = (struct GNUNET_TUN_IPv6Header *)buf;
2178       udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2179       make_up_icmpv6_payload (state,
2180                               ipv6,
2181                               udp);
2182       GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2183       return sizeof (struct GNUNET_TUN_IPv6Header) + 8;      
2184     }
2185     break;
2186   default:
2187     GNUNET_break (0);
2188   }
2189   return 0;
2190 }
2191
2192
2193 /**
2194  * Process a request via mesh to send ICMP data to a service
2195  * offered by this system.
2196  *
2197  * @param cls closure, NULL
2198  * @param tunnel connection to the other end
2199  * @param tunnel_ctx pointer to our 'struct TunnelState *'
2200  * @param sender who sent the message
2201  * @param message the actual message
2202  * @param atsi performance data for the connection
2203  * @return GNUNET_OK to keep the connection open,
2204  *         GNUNET_SYSERR to close it (signal serious error)
2205  */
2206 static int
2207 receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2208                       void **tunnel_ctx,
2209                       const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2210                       const struct GNUNET_MessageHeader *message,
2211                       const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2212 {
2213   struct TunnelState *state = *tunnel_ctx;
2214   const struct GNUNET_EXIT_IcmpServiceMessage *msg;
2215   uint16_t pkt_len = ntohs (message->size);
2216   struct GNUNET_TUN_IcmpHeader icmp;
2217   char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8];
2218   const void *payload;
2219
2220   GNUNET_STATISTICS_update (stats,
2221                             gettext_noop ("# Bytes received from MESH"),
2222                             pkt_len, GNUNET_NO);
2223   GNUNET_STATISTICS_update (stats,
2224                             gettext_noop ("# ICMP service requests received via mesh"),
2225                             1, GNUNET_NO);
2226   /* check that we got at least a valid header */
2227   if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
2228   {
2229     GNUNET_break_op (0);
2230     return GNUNET_SYSERR;
2231   }
2232   msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2233   pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2234   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2235               "Received data from %s for forwarding to ICMP service %s\n",
2236               GNUNET_i2s (sender),
2237               GNUNET_h2s (&msg->service_descriptor));
2238   if (NULL == state->serv)
2239   {
2240     /* first packet to service must not be ICMP (cannot determine service!) */
2241     GNUNET_break_op (0);
2242     return GNUNET_SYSERR;
2243   }
2244   icmp = msg->icmp_header;
2245   payload = &msg[1];
2246   state->ri.remote_address = state->serv->address;    
2247   setup_state_record (state);
2248
2249   /* check that ICMP type is something we want to support,
2250      perform ICMP PT if needed ans possibly make up payload */
2251   switch (msg->af)
2252   {
2253   case AF_INET:
2254     switch (msg->icmp_header.type)
2255     {
2256     case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2257       if (state->serv->address.af == AF_INET6)
2258         icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2259       break;
2260     case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2261       if (state->serv->address.af == AF_INET6)
2262         icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2263       break;
2264     case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2265       if (state->serv->address.af == AF_INET6)
2266         icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2267       if (0 != pkt_len)
2268       {
2269         GNUNET_break_op (0);
2270         return GNUNET_SYSERR;
2271       }
2272       payload = buf;
2273       pkt_len = make_up_icmp_service_payload (state, buf);
2274       break;
2275     case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2276       if (state->serv->address.af == AF_INET6)
2277         icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2278       if (0 != pkt_len)
2279       {
2280         GNUNET_break_op (0);
2281         return GNUNET_SYSERR;
2282       }
2283       payload = buf;
2284       pkt_len = make_up_icmp_service_payload (state, buf);
2285       break;
2286     case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2287       if (state->serv->address.af == AF_INET6)
2288       {
2289         GNUNET_STATISTICS_update (stats,
2290                                   gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2291                                   1, GNUNET_NO);
2292         return GNUNET_OK;
2293       }
2294       if (0 != pkt_len)
2295       {
2296         GNUNET_break_op (0);
2297         return GNUNET_SYSERR;
2298       }
2299       payload = buf;
2300       pkt_len = make_up_icmp_service_payload (state, buf);
2301       break;
2302     default:
2303       GNUNET_break_op (0);
2304       GNUNET_STATISTICS_update (stats,
2305                                 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2306                                 1, GNUNET_NO);
2307       return GNUNET_SYSERR;
2308     }
2309     /* end of AF_INET */
2310     break;
2311   case AF_INET6:
2312     switch (msg->icmp_header.type)
2313     {
2314     case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2315       if (state->serv->address.af == AF_INET)
2316         icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2317       break;
2318     case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2319       if (state->serv->address.af == AF_INET)
2320         icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2321       break;
2322     case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2323       if (state->serv->address.af == AF_INET)
2324         icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2325       if (0 != pkt_len)
2326       {
2327         GNUNET_break_op (0);
2328         return GNUNET_SYSERR;
2329       }
2330       payload = buf;
2331       pkt_len = make_up_icmp_service_payload (state, buf);
2332       break;
2333     case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2334       if (state->serv->address.af == AF_INET)
2335         icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2336       if (0 != pkt_len)
2337       {
2338         GNUNET_break_op (0);
2339         return GNUNET_SYSERR;
2340       }
2341       payload = buf;
2342       pkt_len = make_up_icmp_service_payload (state, buf);
2343       break;
2344     case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2345     case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2346       if (state->serv->address.af == AF_INET)
2347       {
2348         GNUNET_STATISTICS_update (stats,
2349                                   gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2350                                   1, GNUNET_NO);
2351         return GNUNET_OK;
2352       }
2353       if (0 != pkt_len)
2354       {
2355         GNUNET_break_op (0);
2356         return GNUNET_SYSERR;
2357       }
2358       payload = buf;
2359       pkt_len = make_up_icmp_service_payload (state, buf);
2360       break;
2361     default:
2362       GNUNET_break_op (0);
2363       GNUNET_STATISTICS_update (stats,
2364                                 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2365                                 1, GNUNET_NO);
2366       return GNUNET_SYSERR;
2367     }
2368     /* end of AF_INET6 */
2369     break;
2370   default:
2371     GNUNET_break_op (0);
2372     return GNUNET_SYSERR;
2373   }
2374
2375   send_icmp_packet_via_tun (&state->ri.remote_address,
2376                             &state->ri.local_address,
2377                             &icmp,
2378                             payload, pkt_len);
2379   return GNUNET_YES;
2380 }
2381
2382
2383 /**
2384  * Send a UDP packet via the TUN interface.
2385  *
2386  * @param destination_address IP and port to use for the UDP packet's destination
2387  * @param source_address IP and port to use for the UDP packet's source
2388  * @param payload payload of the UDP packet (does NOT include UDP header)
2389  * @param payload_length number of bytes of data in payload
2390  */
2391 static void
2392 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
2393                          const struct SocketAddress *source_address,
2394                          const void *payload, size_t payload_length)
2395 {
2396   size_t len;
2397
2398   GNUNET_STATISTICS_update (stats,
2399                             gettext_noop ("# UDP packets sent via TUN"),
2400                             1, GNUNET_NO);
2401   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2402               "Sending packet with %u bytes UDP payload via TUN\n",
2403               (unsigned int) payload_length);
2404   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2405   switch (source_address->af)
2406   {
2407   case AF_INET:
2408     len += sizeof (struct GNUNET_TUN_IPv4Header);
2409     break;
2410   case AF_INET6:
2411     len += sizeof (struct GNUNET_TUN_IPv6Header);
2412     break;
2413   default:
2414     GNUNET_break (0);
2415     return;
2416   }
2417   len += sizeof (struct GNUNET_TUN_UdpHeader);
2418   len += payload_length;
2419   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2420   {
2421     GNUNET_break (0);
2422     return;
2423   }
2424   {
2425     char buf[len];
2426     struct GNUNET_MessageHeader *hdr;
2427     struct GNUNET_TUN_Layer2PacketHeader *tun;
2428     
2429     hdr= (struct GNUNET_MessageHeader *) buf;
2430     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2431     hdr->size = htons (len);
2432     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2433     tun->flags = htons (0);
2434     switch (source_address->af)
2435     {
2436     case AF_INET:
2437       {
2438         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2439         
2440         tun->proto = htons (ETH_P_IPV4);
2441         prepare_ipv4_packet (payload, payload_length,
2442                              IPPROTO_UDP,
2443                              NULL,
2444                              source_address,
2445                              destination_address,
2446                              ipv4);
2447       }
2448       break;
2449     case AF_INET6:
2450       {
2451         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2452         
2453         tun->proto = htons (ETH_P_IPV6);
2454         prepare_ipv6_packet (payload, payload_length, 
2455                              IPPROTO_UDP,
2456                              NULL,
2457                              source_address,
2458                              destination_address,
2459                              ipv6);
2460       }
2461       break;    
2462     default:
2463       GNUNET_assert (0);
2464       break;
2465     }
2466     (void) GNUNET_HELPER_send (helper_handle,
2467                                (const struct GNUNET_MessageHeader*) buf,
2468                                GNUNET_YES,
2469                                NULL, NULL);
2470   }
2471 }
2472
2473
2474 /**
2475  * Process a request to forward UDP data to the Internet via this peer.
2476  *
2477  * @param cls closure, NULL
2478  * @param tunnel connection to the other end
2479  * @param tunnel_ctx pointer to our 'struct TunnelState *'
2480  * @param sender who sent the message
2481  * @param message the actual message
2482  * @param atsi performance data for the connection
2483  * @return GNUNET_OK to keep the connection open,
2484  *         GNUNET_SYSERR to close it (signal serious error)
2485  */
2486 static int
2487 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2488                     void **tunnel_ctx GNUNET_UNUSED,
2489                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2490                     const struct GNUNET_MessageHeader *message,
2491                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2492 {
2493   struct TunnelState *state = *tunnel_ctx;
2494   const struct GNUNET_EXIT_UdpInternetMessage *msg;
2495   uint16_t pkt_len = ntohs (message->size);
2496   const struct in_addr *v4;
2497   const struct in6_addr *v6;
2498   const void *payload;
2499   int af;
2500
2501   GNUNET_STATISTICS_update (stats,
2502                             gettext_noop ("# Bytes received from MESH"),
2503                             pkt_len, GNUNET_NO);
2504   GNUNET_STATISTICS_update (stats,
2505                             gettext_noop ("# UDP IP-exit requests received via mesh"),
2506                             1, GNUNET_NO);
2507   if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2508   {
2509     GNUNET_break_op (0);
2510     return GNUNET_SYSERR;
2511   }
2512   msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message;
2513   pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage);  
2514   af = (int) ntohl (msg->af);
2515   state->ri.remote_address.af = af;
2516   switch (af)
2517   {
2518   case AF_INET:
2519     if (pkt_len < sizeof (struct in_addr))
2520     {
2521       GNUNET_break_op (0);
2522       return GNUNET_SYSERR;
2523     }
2524     if (! ipv4_exit)
2525     {
2526       GNUNET_break_op (0);
2527       return GNUNET_SYSERR;
2528     }
2529     v4 = (const struct in_addr*) &msg[1];
2530     payload = &v4[1];
2531     pkt_len -= sizeof (struct in_addr);
2532     state->ri.remote_address.address.ipv4 = *v4;
2533     break;
2534   case AF_INET6:
2535     if (pkt_len < sizeof (struct in6_addr))
2536     {
2537       GNUNET_break_op (0);
2538       return GNUNET_SYSERR;
2539     }
2540     if (! ipv6_exit)
2541     {
2542       GNUNET_break_op (0);
2543       return GNUNET_SYSERR;
2544     }
2545     v6 = (const struct in6_addr*) &msg[1];
2546     payload = &v6[1];
2547     pkt_len -= sizeof (struct in6_addr);
2548     state->ri.remote_address.address.ipv6 = *v6;
2549     break;
2550   default:
2551     GNUNET_break_op (0);
2552     return GNUNET_SYSERR;
2553   }
2554   {
2555     char buf[INET6_ADDRSTRLEN];
2556     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2557                 "Received data from %s for forwarding to UDP %s:%u\n",
2558                 GNUNET_i2s (sender),
2559                 inet_ntop (af, 
2560                            &state->ri.remote_address.address,
2561                            buf, sizeof (buf)),
2562                 (unsigned int) ntohs (msg->destination_port));  
2563   }
2564   state->ri.remote_address.proto = IPPROTO_UDP;
2565   state->ri.remote_address.port = msg->destination_port;
2566   if (NULL == state->heap_node)
2567     setup_state_record (state);
2568   if (0 != ntohs (msg->source_port))
2569     state->ri.local_address.port = msg->source_port;
2570   send_udp_packet_via_tun (&state->ri.remote_address,
2571                            &state->ri.local_address,
2572                            payload, pkt_len);
2573   return GNUNET_YES;
2574 }
2575
2576
2577 /**
2578  * Process a request via mesh to send a request to a UDP service
2579  * offered by this system.
2580  *
2581  * @param cls closure, NULL
2582  * @param tunnel connection to the other end
2583  * @param tunnel_ctx pointer to our 'struct TunnelState *'
2584  * @param sender who sent the message
2585  * @param message the actual message
2586  * @param atsi performance data for the connection
2587  * @return GNUNET_OK to keep the connection open,
2588  *         GNUNET_SYSERR to close it (signal serious error)
2589  */
2590 static int
2591 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2592                      void **tunnel_ctx,
2593                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
2594                      const struct GNUNET_MessageHeader *message,
2595                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2596 {
2597   struct TunnelState *state = *tunnel_ctx;
2598   const struct GNUNET_EXIT_UdpServiceMessage *msg;
2599   uint16_t pkt_len = ntohs (message->size);
2600
2601   GNUNET_STATISTICS_update (stats,
2602                             gettext_noop ("# Bytes received from MESH"),
2603                             pkt_len, GNUNET_NO);
2604   GNUNET_STATISTICS_update (stats,
2605                             gettext_noop ("# UDP service requests received via mesh"),
2606                             1, GNUNET_NO);
2607   /* check that we got at least a valid header */
2608   if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
2609   {
2610     GNUNET_break_op (0);
2611     return GNUNET_SYSERR;
2612   }
2613   msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message;
2614   pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage);
2615   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2616               "Received data from %s for forwarding to UDP service %s on port %u\n",
2617               GNUNET_i2s (sender),
2618               GNUNET_h2s (&msg->service_descriptor),
2619               (unsigned int) ntohs (msg->destination_port));  
2620   if (NULL == (state->serv = find_service (udp_services, &msg->service_descriptor, 
2621                                            ntohs (msg->destination_port))))
2622   {
2623     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
2624                 _("No service found for %s on port %d!\n"),
2625                 "UDP",
2626                 ntohs (msg->destination_port));
2627     GNUNET_STATISTICS_update (stats,
2628                               gettext_noop ("# UDP requests dropped (no such service)"),
2629                               1, GNUNET_NO);
2630     return GNUNET_SYSERR;
2631   }
2632   state->ri.remote_address = state->serv->address;    
2633   setup_state_record (state);
2634   if (0 != ntohs (msg->source_port))
2635     state->ri.local_address.port = msg->source_port;
2636   send_udp_packet_via_tun (&state->ri.remote_address,
2637                            &state->ri.local_address,
2638                            &msg[1], pkt_len);
2639   return GNUNET_YES;
2640 }
2641
2642
2643 /**
2644  * Callback from GNUNET_MESH for new tunnels.
2645  *
2646  * @param cls closure
2647  * @param tunnel new handle to the tunnel
2648  * @param initiator peer that started the tunnel
2649  * @param atsi performance information for the tunnel
2650  * @return initial tunnel context for the tunnel
2651  */
2652 static void *
2653 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
2654             const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
2655             const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
2656 {
2657   struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState));
2658
2659   GNUNET_STATISTICS_update (stats,
2660                             gettext_noop ("# Inbound MESH tunnels created"),
2661                             1, GNUNET_NO);
2662   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2663               "Received inbound tunnel from `%s'\n",
2664               GNUNET_i2s (initiator));
2665   s->tunnel = tunnel;
2666   return s;
2667 }
2668
2669
2670 /**
2671  * Function called by mesh whenever an inbound tunnel is destroyed.
2672  * Should clean up any associated state.
2673  *
2674  * @param cls closure (set from GNUNET_MESH_connect)
2675  * @param tunnel connection to the other end (henceforth invalid)
2676  * @param tunnel_ctx place where local state associated
2677  *                   with the tunnel is stored
2678  */
2679 static void
2680 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
2681               void *tunnel_ctx)
2682 {
2683   struct TunnelState *s = tunnel_ctx;
2684   struct TunnelMessageQueue *tnq;
2685
2686   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2687               "Tunnel destroyed\n");
2688   while (NULL != (tnq = s->head))
2689   {
2690     GNUNET_CONTAINER_DLL_remove (s->head,
2691                                  s->tail,
2692                                  tnq);
2693     GNUNET_free (tnq);
2694   }
2695   if (s->heap_node != NULL)
2696   {
2697     GNUNET_assert (GNUNET_YES ==
2698                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
2699                                                          &s->state_key,
2700                                                          s));
2701     GNUNET_CONTAINER_heap_remove_node (s->heap_node);
2702     s->heap_node = NULL;
2703   }
2704   if (NULL != s->th)
2705   {
2706     GNUNET_MESH_notify_transmit_ready_cancel (s->th);
2707     s->th = NULL;
2708   }
2709   GNUNET_free (s);
2710 }
2711
2712
2713 /**
2714  * Function that frees everything from a hashmap
2715  *
2716  * @param cls unused
2717  * @param hash key
2718  * @param value value to free
2719  */
2720 static int
2721 free_iterate (void *cls GNUNET_UNUSED,
2722               const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
2723 {
2724   GNUNET_free (value);
2725   return GNUNET_YES;
2726 }
2727
2728
2729 /**
2730  * Function scheduled as very last function, cleans up after us
2731  */
2732 static void
2733 cleanup (void *cls GNUNET_UNUSED,
2734          const struct GNUNET_SCHEDULER_TaskContext *tskctx)
2735 {
2736   unsigned int i;
2737
2738   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2739               "Exit service is shutting down now\n");
2740   if (helper_handle != NULL)
2741   {
2742     GNUNET_HELPER_stop (helper_handle);
2743     helper_handle = NULL;
2744   }
2745   if (mesh_handle != NULL)
2746   {
2747     GNUNET_MESH_disconnect (mesh_handle);
2748     mesh_handle = NULL;
2749   }
2750   if (NULL != connections_map)
2751   {
2752     GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
2753     GNUNET_CONTAINER_multihashmap_destroy (connections_map);
2754     connections_map = NULL;
2755   }
2756   if (NULL != connections_heap)
2757   {
2758     GNUNET_CONTAINER_heap_destroy (connections_heap);
2759     connections_heap = NULL;
2760   }
2761   if (NULL != tcp_services)
2762   {
2763     GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
2764     GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
2765     tcp_services = NULL;
2766   }
2767   if (NULL != udp_services)
2768   {
2769     GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
2770     GNUNET_CONTAINER_multihashmap_destroy (udp_services);
2771     udp_services = NULL;
2772   }
2773   if (stats != NULL)
2774   {
2775     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2776     stats = NULL;
2777   }
2778   for (i=0;i<8;i++)
2779     GNUNET_free_non_null (exit_argv[i]);
2780 }
2781
2782
2783 /**
2784  * Add services to the service map.
2785  *
2786  * @param proto IPPROTO_TCP or IPPROTO_UDP
2787  * @param cpy copy of the service descriptor (can be mutilated)
2788  * @param name DNS name of the service
2789  */
2790 static void
2791 add_services (int proto,
2792               char *cpy,
2793               const char *name)
2794 {
2795   char *redirect;
2796   char *hostname;
2797   char *hostport;
2798   struct LocalService *serv;
2799
2800   for (redirect = strtok (cpy, " "); redirect != NULL;
2801        redirect = strtok (NULL, " "))
2802   {
2803     if (NULL == (hostname = strstr (redirect, ":")))
2804     {
2805       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2806                   "option `%s' for domain `%s' is not formatted correctly!\n",
2807                   redirect,
2808                   name);
2809       continue;
2810     }
2811     hostname[0] = '\0';
2812     hostname++;
2813     if (NULL == (hostport = strstr (hostname, ":")))
2814     {
2815       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2816                   "option `%s' for domain `%s' is not formatted correctly!\n",
2817                   redirect,
2818                   name);
2819       continue;
2820     }
2821     hostport[0] = '\0';
2822     hostport++;
2823     
2824     int local_port = atoi (redirect);
2825     int remote_port = atoi (hostport);
2826     
2827     if (!((local_port > 0) && (local_port < 65536)))
2828     {
2829       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2830                   "`%s' is not a valid port number (for domain `%s')!", redirect,
2831                   name);
2832       continue;
2833     }
2834     if (!((remote_port > 0) && (remote_port < 65536)))
2835     {
2836       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2837                   "`%s' is not a valid port number (for domain `%s')!", hostport,
2838                   name);
2839       continue;
2840     }
2841
2842     serv = GNUNET_malloc (sizeof (struct LocalService));
2843     serv->my_port = (uint16_t) local_port;
2844     serv->address.port = remote_port;
2845     if (0 == strcmp ("localhost4", hostname))
2846     {
2847       const char *ip4addr = exit_argv[4];
2848
2849       serv->address.af = AF_INET;      
2850       GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
2851     }
2852     else if (0 == strcmp ("localhost6", hostname))
2853     {
2854       const char *ip6addr = exit_argv[2];
2855
2856       serv->address.af = AF_INET6;
2857       GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
2858     }
2859     else
2860     {
2861       struct addrinfo *res;      
2862       int ret;
2863
2864       ret = getaddrinfo (hostname, NULL, NULL, &res);      
2865       if ( (ret != 0) || (res == NULL) )
2866       {
2867         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2868                     _("No addresses found for hostname `%s' of service `%s'!\n"),
2869                     hostname,
2870                     name);
2871         GNUNET_free (serv);
2872         continue;
2873       }
2874       
2875       serv->address.af = res->ai_family;
2876       switch (res->ai_family)
2877       {
2878       case AF_INET:
2879         if (! ipv4_enabled)
2880         {
2881           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2882                       _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
2883                       name);
2884           freeaddrinfo (res);
2885           GNUNET_free (serv);
2886           continue;
2887         }
2888         serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
2889         break;
2890       case AF_INET6:
2891         if (! ipv6_enabled)
2892         {
2893           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2894                       _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
2895                       name);
2896           freeaddrinfo (res);
2897           GNUNET_free (serv);
2898           continue;
2899         }       
2900         serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
2901         break;
2902       default:
2903         freeaddrinfo (res);
2904         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2905                     _("No IP addresses found for hostname `%s' of service `%s'!\n"),
2906                     hostname,
2907                     name);
2908         GNUNET_free (serv);
2909         continue;
2910       }
2911       freeaddrinfo (res);
2912     }
2913     store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
2914                    name,
2915                    local_port,
2916                    serv);
2917   }
2918 }
2919
2920
2921 /**
2922  * Reads the configuration servicecfg and populates udp_services
2923  *
2924  * @param cls unused
2925  * @param section name of section in config, equal to hostname
2926  */
2927 static void
2928 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
2929 {
2930   char *cpy;
2931
2932   if ((strlen (section) < 8) ||
2933       (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
2934     return;
2935   if (GNUNET_OK ==
2936       GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
2937                                              &cpy))
2938   {
2939     add_services (IPPROTO_UDP, cpy, section);
2940     GNUNET_free (cpy);
2941   }
2942   if (GNUNET_OK ==
2943       GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
2944                                              &cpy))
2945   {
2946     add_services (IPPROTO_TCP, cpy, section);
2947     GNUNET_free (cpy);
2948   }
2949 }
2950
2951
2952 /**
2953  * Test if the given AF is supported by this system.
2954  * 
2955  * @param af to test
2956  * @return GNUNET_OK if the AF is supported
2957  */
2958 static int
2959 test_af (int af)
2960 {
2961   int s;
2962
2963   s = socket (af, SOCK_STREAM, 0);
2964   if (-1 == s)
2965   {
2966     if (EAFNOSUPPORT == errno)
2967       return GNUNET_NO;
2968     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
2969                          "socket");
2970     return GNUNET_SYSERR;
2971   }
2972   close (s);
2973   return GNUNET_OK;
2974 }
2975
2976
2977 /**
2978  * @brief Main function that will be run by the scheduler.
2979  *
2980  * @param cls closure
2981  * @param args remaining command-line arguments
2982  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
2983  * @param cfg_ configuration
2984  */
2985 static void
2986 run (void *cls, char *const *args GNUNET_UNUSED,
2987      const char *cfgfile GNUNET_UNUSED,
2988      const struct GNUNET_CONFIGURATION_Handle *cfg_)
2989 {
2990   static struct GNUNET_MESH_MessageHandler handlers[] = {
2991     {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0},
2992     {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0},
2993     {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0},
2994     {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0},
2995     {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0},
2996     {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0},
2997     {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0},
2998     {NULL, 0, 0}
2999   };
3000
3001   static GNUNET_MESH_ApplicationType apptypes[] = {
3002     GNUNET_APPLICATION_TYPE_END,
3003     GNUNET_APPLICATION_TYPE_END,
3004     GNUNET_APPLICATION_TYPE_END
3005   };
3006   unsigned int app_idx;
3007   char *exit_ifname;
3008   char *tun_ifname;
3009   char *ipv6addr;
3010   char *ipv6prefix_s;
3011   char *ipv4addr;
3012   char *ipv4mask;
3013
3014   if (GNUNET_YES !=
3015       GNUNET_OS_check_helper_binary ("gnunet-helper-exit"))
3016   {
3017     fprintf (stderr,
3018              "`%s' is not SUID, refusing to run.\n",
3019              "gnunet-helper-exit");
3020     global_ret = 1;
3021     return;
3022   }
3023   cfg = cfg_;
3024   stats = GNUNET_STATISTICS_create ("exit", cfg);
3025   ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4");
3026   ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6"); 
3027   ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4");
3028   ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6"); 
3029
3030   if ( (ipv4_exit || ipv4_enabled) &&
3031        GNUNET_OK != test_af (AF_INET))
3032   {
3033     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3034                 _("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3035     ipv4_exit = GNUNET_NO;
3036     ipv4_enabled = GNUNET_NO;
3037   }
3038   if ( (ipv6_exit || ipv6_enabled) &&
3039        GNUNET_OK != test_af (AF_INET6))
3040   {
3041     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3042                 _("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3043     ipv6_exit = GNUNET_NO;
3044     ipv6_enabled = GNUNET_NO;
3045   }
3046   if (ipv4_exit && (! ipv4_enabled))
3047   {
3048     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3049                 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3050     ipv4_enabled = GNUNET_YES;
3051   }
3052   if (ipv6_exit && (! ipv6_enabled))
3053   {
3054     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3055                 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3056     ipv6_enabled = GNUNET_YES;
3057   }
3058   if (! (ipv4_enabled || ipv6_enabled))
3059   {
3060     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3061                 _("No useful service enabled.  Exiting.\n"));
3062     GNUNET_SCHEDULER_shutdown ();
3063     return;    
3064   }
3065   app_idx = 0;
3066   if (GNUNET_YES == ipv4_exit)    
3067   {
3068     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY;
3069     app_idx++;
3070   }
3071   if (GNUNET_YES == ipv6_exit)    
3072   {
3073     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY;
3074     app_idx++;
3075   }
3076
3077   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
3078
3079   if (GNUNET_OK !=
3080       GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
3081                                              &max_connections))
3082     max_connections = 1024;
3083   exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3084   if (GNUNET_SYSERR ==
3085       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", &tun_ifname))
3086   {
3087     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3088                 "No entry 'TUN_IFNAME' in configuration!\n");
3089     GNUNET_SCHEDULER_shutdown ();
3090     return;
3091   }
3092   exit_argv[1] = tun_ifname;
3093   if (ipv4_enabled)
3094   {
3095     if (GNUNET_SYSERR ==
3096         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", &exit_ifname))
3097     {
3098       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3099                   "No entry 'EXIT_IFNAME' in configuration!\n");
3100       GNUNET_SCHEDULER_shutdown ();
3101       return;
3102     }
3103     exit_argv[2] = exit_ifname;
3104   }
3105   else
3106   {
3107     exit_argv[2] = GNUNET_strdup ("%");
3108   }
3109   
3110
3111   if (GNUNET_YES == ipv6_enabled)
3112   {
3113     if ( (GNUNET_SYSERR ==
3114           GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
3115                                                  &ipv6addr) ||
3116           (1 != inet_pton (AF_INET6, ipv6addr, &exit_ipv6addr))) )
3117     {
3118       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3119                   "No valid entry 'IPV6ADDR' in configuration!\n");
3120       GNUNET_SCHEDULER_shutdown ();
3121       return;
3122     }
3123     exit_argv[3] = ipv6addr;
3124     if (GNUNET_SYSERR ==
3125         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
3126                                                &ipv6prefix_s))
3127     {
3128       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3129                   "No entry 'IPV6PREFIX' in configuration!\n");
3130       GNUNET_SCHEDULER_shutdown ();
3131       return;
3132     }
3133     exit_argv[4] = ipv6prefix_s;
3134     if ( (GNUNET_OK !=
3135           GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
3136                                                  "IPV6PREFIX",
3137                                                  &ipv6prefix)) ||
3138          (ipv6prefix >= 127) )
3139     {
3140       GNUNET_SCHEDULER_shutdown ();
3141       return;
3142     }
3143   } 
3144   else
3145   {
3146     /* IPv6 explicitly disabled */
3147     exit_argv[3] = GNUNET_strdup ("-");
3148     exit_argv[4] = GNUNET_strdup ("-");
3149   }
3150   if (GNUNET_YES == ipv4_enabled)
3151   {
3152     if ( (GNUNET_SYSERR ==
3153           GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
3154                                                  &ipv4addr) ||
3155           (1 != inet_pton (AF_INET, ipv4addr, &exit_ipv4addr))) )
3156       {
3157         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3158                     "No valid entry for 'IPV4ADDR' in configuration!\n");
3159         GNUNET_SCHEDULER_shutdown ();
3160         return;
3161       }
3162     exit_argv[5] = ipv4addr;
3163     if ( (GNUNET_SYSERR ==
3164           GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
3165                                                  &ipv4mask) ||
3166           (1 != inet_pton (AF_INET, ipv4mask, &exit_ipv4mask))) )
3167     {
3168       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3169                   "No valid entry 'IPV4MASK' in configuration!\n");
3170       GNUNET_SCHEDULER_shutdown ();
3171       return;
3172     }
3173     exit_argv[6] = ipv4mask;
3174   }
3175   else
3176   {
3177     /* IPv4 explicitly disabled */
3178     exit_argv[5] = GNUNET_strdup ("-");
3179     exit_argv[6] = GNUNET_strdup ("-");
3180   }
3181   exit_argv[7] = NULL;
3182
3183   udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
3184   tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
3185   GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
3186
3187   connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
3188   connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3189   mesh_handle 
3190     = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL, 
3191                            &new_tunnel, 
3192                            &clean_tunnel, handlers,
3193                            apptypes);
3194   if (NULL == mesh_handle)
3195   {
3196     GNUNET_SCHEDULER_shutdown ();
3197     return;
3198   }
3199   helper_handle = GNUNET_HELPER_start ("gnunet-helper-exit", 
3200                                        exit_argv,
3201                                        &message_token, NULL);
3202 }
3203
3204
3205 /**
3206  * The main function
3207  *
3208  * @param argc number of arguments from the command line
3209  * @param argv command line arguments
3210  * @return 0 ok, 1 on error
3211  */
3212 int
3213 main (int argc, char *const *argv)
3214 {
3215   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
3216     GNUNET_GETOPT_OPTION_END
3217   };
3218
3219   return (GNUNET_OK ==
3220           GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
3221                               gettext_noop
3222                               ("Daemon to run to provide an IP exit node for the VPN"),
3223                               options, &run, NULL)) ? global_ret : 1;
3224 }
3225
3226
3227 /* end of gnunet-daemon-exit.c */