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