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