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