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