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