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