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