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