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