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