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