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