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