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