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