Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / vpn / gnunet-service-vpn.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010, 2011, 2012, 2016, 2017 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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, 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    * Destination port this channel state is used for.
88    */
89   uint16_t destination_port;
90
91 };
92
93
94 /**
95  * Information we track for each IP address to determine which channel
96  * to send the traffic over to the destination.
97  */
98 struct DestinationEntry
99 {
100
101   /**
102    * Key under which this entry is in the 'destination_map' (only valid
103    * if 'heap_node != NULL').
104    */
105   struct GNUNET_HashCode key;
106
107   /**
108    * Head of DLL of channels associated with this destination.
109    */
110   struct DestinationChannel *dt_head;
111
112   /**
113    * Tail of DLL of channels associated with this destination.
114    */
115   struct DestinationChannel *dt_tail;
116
117   /**
118    * Entry for this entry in the destination_heap.
119    */
120   struct GNUNET_CONTAINER_HeapNode *heap_node;
121
122   /**
123    * #GNUNET_NO if this is a channel to an Internet-exit,
124    * #GNUNET_YES if this channel is to a service.
125    */
126   int is_service;
127
128   /**
129    * Details about the connection (depending on is_service).
130    */
131   union
132   {
133
134     struct
135     {
136       /**
137        * The description of the service (only used for service channels).
138        */
139       struct GNUNET_HashCode service_descriptor;
140
141       /**
142        * Peer offering the service.
143        */
144       struct GNUNET_PeerIdentity target;
145
146     } service_destination;
147
148     struct
149     {
150
151       /**
152        * Address family used (AF_INET or AF_INET6).
153        */
154       int af;
155
156       /**
157        * IP address of the ultimate destination (only used for exit channels).
158        */
159       union
160       {
161         /**
162          * Address if af is AF_INET.
163          */
164         struct in_addr v4;
165
166         /**
167          * Address if af is AF_INET6.
168          */
169         struct in6_addr v6;
170       } ip;
171
172     } exit_destination;
173
174   } details;
175
176 };
177
178
179 /**
180  * A messages we have in queue for a particular channel.
181  */
182 struct ChannelMessageQueueEntry
183 {
184   /**
185    * This is a doubly-linked list.
186    */
187   struct ChannelMessageQueueEntry *next;
188
189   /**
190    * This is a doubly-linked list.
191    */
192   struct ChannelMessageQueueEntry *prev;
193
194   /**
195    * Number of bytes in @e msg.
196    */
197   size_t len;
198
199   /**
200    * Message to transmit, allocated at the end of this struct.
201    */
202   const void *msg;
203 };
204
205
206 /**
207  * State we keep for each of our channels.
208  */
209 struct ChannelState
210 {
211
212   /**
213    * Information about the channel to use, NULL if no channel
214    * is available right now.
215    */
216   struct GNUNET_CADET_Channel *channel;
217
218   /**
219    * Active query with REGEX to locate exit.
220    */
221   struct GNUNET_REGEX_Search *search;
222
223   /**
224    * Entry for this entry in the channel_heap, NULL as long as this
225    * channel state is not fully bound.
226    */
227   struct GNUNET_CONTAINER_HeapNode *heap_node;
228
229   /**
230    * Head of list of messages scheduled for transmission.
231    */
232   struct ChannelMessageQueueEntry *tmq_head;
233
234   /**
235    * Tail of list of messages scheduled for transmission.
236    */
237   struct ChannelMessageQueueEntry *tmq_tail;
238
239   /**
240    * Destination to which this channel leads.  Note that
241    * this struct is NOT in the destination_map (but a
242    * local copy) and that the 'heap_node' should always
243    * be NULL.
244    */
245   struct DestinationEntry destination;
246
247   /**
248    * Addess family used for this channel on the local TUN interface.
249    */
250   int af;
251
252   /**
253    * Is this channel new (#GNUNET_NO), or did we exchange messages with the
254    * other side already (#GNUNET_YES)?
255    */
256   int is_established;
257
258   /**
259    * Length of the doubly linked 'tmq_head/tmq_tail' list.
260    */
261   unsigned int tmq_length;
262
263   /**
264    * IPPROTO_TCP or IPPROTO_UDP once bound.
265    */
266   uint8_t protocol;
267
268   /**
269    * IP address of the source on our end, initially uninitialized.
270    */
271   union
272   {
273     /**
274      * Address if af is AF_INET.
275      */
276     struct in_addr v4;
277
278     /**
279      * Address if af is AF_INET6.
280      */
281     struct in6_addr v6;
282
283   } source_ip;
284
285   /**
286    * Destination IP address used by the source on our end (this is the IP
287    * that we pick freely within the VPN's channel IP range).
288    */
289   union
290   {
291     /**
292      * Address if af is AF_INET.
293      */
294     struct in_addr v4;
295
296     /**
297      * Address if af is AF_INET6.
298      */
299     struct in6_addr v6;
300
301   } destination_ip;
302
303   /**
304    * Source port used by the sender on our end; 0 for uninitialized.
305    */
306   uint16_t source_port;
307
308   /**
309    * Destination port used by the sender on our end; 0 for uninitialized.
310    */
311   uint16_t destination_port;
312
313 };
314
315
316 /**
317  * Return value from #main().
318  */
319 static int global_ret;
320
321 /**
322  * Configuration we use.
323  */
324 static const struct GNUNET_CONFIGURATION_Handle *cfg;
325
326 /**
327  * Handle to the cadet service.
328  */
329 static struct GNUNET_CADET_Handle *cadet_handle;
330
331 /**
332  * Map from IP address to destination information (possibly with a
333  * CADET channel handle for fast setup).
334  */
335 static struct GNUNET_CONTAINER_MultiHashMap *destination_map;
336
337 /**
338  * Min-Heap sorted by activity time to expire old mappings.
339  */
340 static struct GNUNET_CONTAINER_Heap *destination_heap;
341
342 /**
343  * Map from source and destination address (IP+port) to connection
344  * information (mostly with the respective CADET channel handle).
345  */
346 static struct GNUNET_CONTAINER_MultiHashMap *channel_map;
347
348 /**
349  * Min-Heap sorted by activity time to expire old mappings; values are
350  * of type 'struct ChannelState'.
351  */
352 static struct GNUNET_CONTAINER_Heap *channel_heap;
353
354 /**
355  * Statistics.
356  */
357 static struct GNUNET_STATISTICS_Handle *stats;
358
359 /**
360  * The handle to the VPN helper process "gnunet-helper-vpn".
361  */
362 static struct GNUNET_HELPER_Handle *helper_handle;
363
364 /**
365  * Arguments to the vpn helper.
366  */
367 static char *vpn_argv[7];
368
369 /**
370  * Length of the prefix of the VPN's IPv6 network.
371  */
372 static unsigned long long ipv6prefix;
373
374 /**
375  * If there are more than this number of address-mappings, old ones
376  * will be removed
377  */
378 static unsigned long long max_destination_mappings;
379
380 /**
381  * If there are more than this number of open channels, old ones
382  * will be removed
383  */
384 static unsigned long long max_channel_mappings;
385
386
387 /**
388  * Compute the key under which we would store an entry in the
389  * #destination_map for the given IP address.
390  *
391  * @param af address family (AF_INET or AF_INET6)
392  * @param address IP address, struct in_addr or struct in6_addr
393  * @param key where to store the key
394  */
395 static void
396 get_destination_key_from_ip (int af,
397                              const void *address,
398                              struct GNUNET_HashCode *key)
399 {
400   switch (af)
401   {
402   case AF_INET:
403     GNUNET_CRYPTO_hash (address,
404                         sizeof (struct in_addr),
405                         key);
406     break;
407   case AF_INET6:
408     GNUNET_CRYPTO_hash (address,
409                         sizeof (struct in6_addr),
410                         key);
411     break;
412   default:
413     GNUNET_assert (0);
414     break;
415   }
416 }
417
418
419 /**
420  * Compute the key under which we would store an entry in the
421  * channel_map for the given socket address pair.
422  *
423  * @param af address family (AF_INET or AF_INET6)
424  * @param protocol IPPROTO_TCP or IPPROTO_UDP
425  * @param source_ip sender's source IP, struct in_addr or struct in6_addr
426  * @param source_port sender's source port
427  * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr
428  * @param destination_port sender's destination port
429  * @param key where to store the key
430  */
431 static void
432 get_channel_key_from_ips (int af,
433                           uint8_t protocol,
434                           const void *source_ip,
435                           uint16_t source_port,
436                           const void *destination_ip,
437                           uint16_t destination_port,
438                           struct GNUNET_HashCode *key)
439 {
440   char *off;
441
442   memset (key, 0, sizeof (struct GNUNET_HashCode));
443   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
444      so we put the ports in there (and hope for few collisions) */
445   off = (char*) key;
446   GNUNET_memcpy (off, &source_port, sizeof (uint16_t));
447   off += sizeof (uint16_t);
448   GNUNET_memcpy (off, &destination_port, sizeof (uint16_t));
449   off += sizeof (uint16_t);
450   switch (af)
451   {
452   case AF_INET:
453     GNUNET_memcpy (off, source_ip, sizeof (struct in_addr));
454     off += sizeof (struct in_addr);
455     GNUNET_memcpy (off, destination_ip, sizeof (struct in_addr));
456     off += sizeof (struct in_addr);
457     break;
458   case AF_INET6:
459     GNUNET_memcpy (off, source_ip, sizeof (struct in6_addr));
460     off += sizeof (struct in6_addr);
461     GNUNET_memcpy (off, destination_ip, sizeof (struct in6_addr));
462     off += sizeof (struct in6_addr);
463     break;
464   default:
465     GNUNET_assert (0);
466     break;
467   }
468   GNUNET_memcpy (off, &protocol, sizeof (uint8_t));
469   /* off += sizeof (uint8_t);  */
470 }
471
472
473 /**
474  * Notify the client about the result of its request.
475  *
476  * @param client client to notify
477  * @param request_id original request ID to include in response
478  * @param result_af resulting address family
479  * @param addr resulting IP address
480  */
481 static void
482 send_client_reply (struct GNUNET_SERVICE_Client *client,
483                    uint64_t request_id,
484                    int result_af,
485                    const void *addr)
486 {
487   struct GNUNET_MQ_Envelope *env;
488   struct RedirectToIpResponseMessage *res;
489   size_t rlen;
490
491   switch (result_af)
492   {
493   case AF_INET:
494     rlen = sizeof (struct in_addr);
495     break;
496   case AF_INET6:
497     rlen = sizeof (struct in6_addr);
498     break;
499   case AF_UNSPEC:
500     rlen = 0;
501     break;
502   default:
503     GNUNET_assert (0);
504     return;
505   }
506   env = GNUNET_MQ_msg_extra (res,
507                              rlen,
508                              GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP);
509   res->result_af = htonl (result_af);
510   res->request_id = request_id;
511   GNUNET_memcpy (&res[1],
512                  addr,
513                  rlen);
514   GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
515                   env);
516 }
517
518
519 /**
520  * Free resources associated with a channel state.
521  *
522  * @param ts state to free
523  */
524 static void
525 free_channel_state (struct ChannelState *ts)
526 {
527   struct GNUNET_HashCode key;
528   struct ChannelMessageQueueEntry *tnq;
529   struct GNUNET_CADET_Channel *channel;
530
531   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
532               "Cleaning up channel state\n");
533   if (NULL != (channel = ts->channel))
534   {
535     ts->channel = NULL;
536     GNUNET_CADET_channel_destroy (channel);
537     return;
538   }
539   GNUNET_STATISTICS_update (stats,
540                             gettext_noop ("# Active channels"),
541                             -1, GNUNET_NO);
542   while (NULL != (tnq = ts->tmq_head))
543   {
544     GNUNET_CONTAINER_DLL_remove (ts->tmq_head,
545                                  ts->tmq_tail,
546                                  tnq);
547     ts->tmq_length--;
548     GNUNET_free (tnq);
549   }
550   GNUNET_assert (0 == ts->tmq_length);
551   GNUNET_assert (NULL == ts->destination.heap_node);
552   if (NULL != ts->search)
553   {
554     GNUNET_REGEX_search_cancel (ts->search);
555     ts->search = NULL;
556   }
557   if (NULL != ts->heap_node)
558   {
559     GNUNET_CONTAINER_heap_remove_node (ts->heap_node);
560     ts->heap_node = NULL;
561     get_channel_key_from_ips (ts->af,
562                              ts->protocol,
563                              &ts->source_ip,
564                              ts->source_port,
565                              &ts->destination_ip,
566                              ts->destination_port,
567                              &key);
568     GNUNET_assert (GNUNET_YES ==
569                    GNUNET_CONTAINER_multihashmap_remove (channel_map,
570                                                          &key,
571                                                          ts));
572   }
573   GNUNET_free (ts);
574 }
575
576
577 /**
578  * Add the given message to the given channel and trigger the
579  * transmission process.
580  *
581  * @param ts channel to queue the message for
582  * @param env message to queue
583  */
584 static void
585 send_to_channel (struct ChannelState *ts,
586                  struct GNUNET_MQ_Envelope *env)
587 {
588   struct GNUNET_MQ_Handle *mq;
589
590   GNUNET_assert (NULL != ts->channel);
591   mq = GNUNET_CADET_get_mq (ts->channel);
592   GNUNET_MQ_send (mq,
593                   env);
594   if (GNUNET_MQ_get_length (mq) > MAX_MESSAGE_QUEUE_SIZE)
595   {
596     env = GNUNET_MQ_unsent_head (mq);
597     GNUNET_assert (NULL != env);
598     GNUNET_STATISTICS_update (stats,
599                               gettext_noop ("# Messages dropped in cadet queue (overflow)"),
600                               1,
601                               GNUNET_NO);
602     GNUNET_MQ_discard (env);
603   }
604 }
605
606
607 /**
608  * Output destination of a channel for diagnostics.
609  *
610  * @param de destination to process
611  * @return diagnostic string describing destination
612  */
613 static const char *
614 print_channel_destination (const struct DestinationEntry *de)
615 {
616   static char dest[256];
617
618   if (de->is_service)
619   {
620     GNUNET_snprintf (dest,
621                      sizeof (dest),
622                      "HS: %s-%s",
623                      GNUNET_i2s (&de->details.service_destination.target),
624                      GNUNET_h2s (&de->details.service_destination.service_descriptor));
625   }
626   else
627   {
628     inet_ntop (de->details.exit_destination.af,
629                &de->details.exit_destination.ip,
630                dest,
631                sizeof (dest));
632   }
633   return dest;
634 }
635
636
637 /**
638  * Function called whenever a channel is destroyed.  Should clean up
639  * any associated state.
640  *
641  * @param cls our `struct ChannelState`
642  * @param channel connection to the other end (henceforth invalid)
643  */
644 static void
645 channel_cleaner (void *cls,
646                  const struct GNUNET_CADET_Channel *channel)
647 {
648   struct ChannelState *ts = cls;
649
650   ts->channel = NULL; /* we must not call GNUNET_CADET_channel_destroy() anymore */
651   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
652               "CADET notified us about death of channel to `%s'\n",
653               print_channel_destination (&ts->destination));
654   free_channel_state (ts);
655 }
656
657
658 /**
659  * Synthesize a plausible ICMP payload for an ICMP error
660  * response on the given channel.
661  *
662  * @param ts channel information
663  * @param ipp IPv4 header to fill in (ICMP payload)
664  * @param udp "UDP" header to fill in (ICMP payload); might actually
665  *            also be the first 8 bytes of the TCP header
666  */
667 static void
668 make_up_icmpv4_payload (struct ChannelState *ts,
669                         struct GNUNET_TUN_IPv4Header *ipp,
670                         struct GNUNET_TUN_UdpHeader *udp)
671 {
672   GNUNET_TUN_initialize_ipv4_header (ipp,
673                                      ts->protocol,
674                                      sizeof (struct GNUNET_TUN_TcpHeader),
675                                      &ts->source_ip.v4,
676                                      &ts->destination_ip.v4);
677   udp->source_port = htons (ts->source_port);
678   udp->destination_port = htons (ts->destination_port);
679   udp->len = htons (0);
680   udp->crc = htons (0);
681 }
682
683
684 /**
685  * Synthesize a plausible ICMP payload for an ICMP error
686  * response on the given channel.
687  *
688  * @param ts channel information
689  * @param ipp IPv6 header to fill in (ICMP payload)
690  * @param udp "UDP" header to fill in (ICMP payload); might actually
691  *            also be the first 8 bytes of the TCP header
692  */
693 static void
694 make_up_icmpv6_payload (struct ChannelState *ts,
695                         struct GNUNET_TUN_IPv6Header *ipp,
696                         struct GNUNET_TUN_UdpHeader *udp)
697 {
698   GNUNET_TUN_initialize_ipv6_header (ipp,
699                                      ts->protocol,
700                                      sizeof (struct GNUNET_TUN_TcpHeader),
701                                      &ts->source_ip.v6,
702                                      &ts->destination_ip.v6);
703   udp->source_port = htons (ts->source_port);
704   udp->destination_port = htons (ts->destination_port);
705   udp->len = htons (0);
706   udp->crc = htons (0);
707 }
708
709
710 /**
711  * We got an ICMP packet back from the CADET channel.  Check it is OK.
712  *
713  * @param cls our `struct ChannelState *`
714  * @param message the actual message
715  * @return #GNUNET_OK to keep the connection open,
716  *         #GNUNET_SYSERR to close it (signal serious error)
717  */
718 static int
719 check_icmp_back (void *cls,
720                  const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
721 {
722   struct ChannelState *ts = cls;
723
724   if (NULL == ts->heap_node)
725   {
726     GNUNET_break_op (0);
727     return GNUNET_SYSERR;
728   }
729   if (AF_UNSPEC == ts->af)
730   {
731     GNUNET_break_op (0);
732     return GNUNET_SYSERR;
733   }
734   return GNUNET_OK;
735 }
736
737
738 /**
739  * We got an ICMP packet back from the CADET channel.  Pass it on to the
740  * local virtual interface via the helper.
741  *
742  * @param cls our `struct ChannelState *`
743  * @param message the actual message
744  */
745 static void
746 handle_icmp_back (void *cls,
747                   const struct GNUNET_EXIT_IcmpToVPNMessage *i2v)
748 {
749   struct ChannelState *ts = cls;
750   size_t mlen;
751
752   GNUNET_STATISTICS_update (stats,
753                             gettext_noop ("# ICMP packets received from cadet"),
754                             1,
755                             GNUNET_NO);
756   mlen = ntohs (i2v->header.size) - sizeof (struct GNUNET_EXIT_IcmpToVPNMessage);
757   {
758     char sbuf[INET6_ADDRSTRLEN];
759     char dbuf[INET6_ADDRSTRLEN];
760
761     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762                 "Received ICMP packet from cadet, sending %u bytes from %s -> %s via TUN\n",
763                 (unsigned int) mlen,
764                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
765                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)));
766   }
767   switch (ts->af)
768   {
769   case AF_INET:
770     {
771       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
772         + sizeof (struct GNUNET_TUN_IcmpHeader)
773         + sizeof (struct GNUNET_MessageHeader) +
774         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
775         mlen;
776       {
777         /* reserve some extra space in case we have an ICMP type here where
778            we will need to make up the payload ourselves */
779         char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN;
780         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
781         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
782         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
783         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1];
784         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
785         tun->flags = htons (0);
786         tun->proto = htons (ETH_P_IPV4);
787         GNUNET_TUN_initialize_ipv4_header (ipv4,
788                                            IPPROTO_ICMP,
789                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
790                                            &ts->destination_ip.v4,
791                                            &ts->source_ip.v4);
792         *icmp = i2v->icmp_header;
793         GNUNET_memcpy (&icmp[1],
794                        &i2v[1],
795                        mlen);
796         /* For some ICMP types, we need to adjust (make up) the payload here.
797            Also, depending on the AF used on the other side, we have to
798            do ICMP PT (translate ICMP types) */
799         switch (ntohl (i2v->af))
800         {
801         case AF_INET:
802           switch (icmp->type)
803           {
804           case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
805           case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
806             break;
807           case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
808           case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
809           case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
810             {
811               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
812               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
813
814               if (mlen != 0)
815                 {
816                   /* sender did not strip ICMP payload? */
817                   GNUNET_break_op (0);
818                   return;
819                 }
820               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
821               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
822               make_up_icmpv4_payload (ts, ipp, udp);
823             }
824             break;
825           default:
826             GNUNET_break_op (0);
827             GNUNET_STATISTICS_update (stats,
828                                       gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
829                                       1, GNUNET_NO);
830             return;
831           }
832           /* end AF_INET */
833           break;
834         case AF_INET6:
835           /* ICMP PT 6-to-4 and possibly making up payloads */
836           switch (icmp->type)
837           {
838           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
839             icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
840             {
841               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
842               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
843
844               if (mlen != 0)
845                 {
846                   /* sender did not strip ICMP payload? */
847                   GNUNET_break_op (0);
848                   return;
849                 }
850               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
851               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
852               make_up_icmpv4_payload (ts, ipp, udp);
853             }
854             break;
855           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
856             icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
857             {
858               struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1];
859               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
860
861               if (mlen != 0)
862                 {
863                   /* sender did not strip ICMP payload? */
864                   GNUNET_break_op (0);
865                   return;
866                 }
867               size += sizeof (struct GNUNET_TUN_IPv4Header) + 8;
868               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
869               make_up_icmpv4_payload (ts, ipp, udp);
870             }
871             break;
872           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
873           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
874             GNUNET_STATISTICS_update (stats,
875                                       gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
876                                       1, GNUNET_NO);
877             return;
878           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
879             icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
880             break;
881           case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
882             icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
883             break;
884           default:
885             GNUNET_break_op (0);
886             GNUNET_STATISTICS_update (stats,
887                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
888                                       1, GNUNET_NO);
889             return;
890           }
891           /* end AF_INET6 */
892           break;
893         default:
894           GNUNET_break_op (0);
895           return;
896         }
897         msg->size = htons (size);
898         GNUNET_TUN_calculate_icmp_checksum (icmp,
899                                             &i2v[1],
900                                             mlen);
901         (void) GNUNET_HELPER_send (helper_handle,
902                                    msg,
903                                    GNUNET_YES,
904                                    NULL, NULL);
905       }
906     }
907     break;
908   case AF_INET6:
909     {
910       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
911         + sizeof (struct GNUNET_TUN_IcmpHeader)
912         + sizeof (struct GNUNET_MessageHeader) +
913         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
914         mlen;
915       {
916         char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
917         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
918         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
919         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
920         struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1];
921         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
922         tun->flags = htons (0);
923         tun->proto = htons (ETH_P_IPV6);
924         GNUNET_TUN_initialize_ipv6_header (ipv6,
925                                            IPPROTO_ICMPV6,
926                                            sizeof (struct GNUNET_TUN_IcmpHeader) + mlen,
927                                            &ts->destination_ip.v6,
928                                            &ts->source_ip.v6);
929         *icmp = i2v->icmp_header;
930         GNUNET_memcpy (&icmp[1],
931                 &i2v[1],
932                 mlen);
933
934         /* For some ICMP types, we need to adjust (make up) the payload here.
935            Also, depending on the AF used on the other side, we have to
936            do ICMP PT (translate ICMP types) */
937         switch (ntohl (i2v->af))
938         {
939         case AF_INET:
940           /* ICMP PT 4-to-6 and possibly making up payloads */
941           switch (icmp->type)
942           {
943           case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
944             icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
945             break;
946           case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
947             icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
948             break;
949           case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
950             icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
951             {
952               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
953               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
954
955               if (mlen != 0)
956                 {
957                   /* sender did not strip ICMP payload? */
958                   GNUNET_break_op (0);
959                   return;
960                 }
961               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
962               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
963               make_up_icmpv6_payload (ts, ipp, udp);
964             }
965             break;
966           case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
967             icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
968             {
969               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
970               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
971
972               if (mlen != 0)
973                 {
974                   /* sender did not strip ICMP payload? */
975                   GNUNET_break_op (0);
976                   return;
977                 }
978               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
979               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
980               make_up_icmpv6_payload (ts, ipp, udp);
981             }
982             break;
983           case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
984             GNUNET_STATISTICS_update (stats,
985                                       gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
986                                       1, GNUNET_NO);
987             return;
988           default:
989             GNUNET_break_op (0);
990             GNUNET_STATISTICS_update (stats,
991                                       gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
992                                       1, GNUNET_NO);
993             return;
994           }
995           /* end AF_INET */
996           break;
997         case AF_INET6:
998           switch (icmp->type)
999           {
1000           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1001           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1002           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1003           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1004             {
1005               struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1];
1006               struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
1007
1008               if (mlen != 0)
1009                 {
1010                   /* sender did not strip ICMP payload? */
1011                   GNUNET_break_op (0);
1012                   return;
1013                 }
1014               size += sizeof (struct GNUNET_TUN_IPv6Header) + 8;
1015               GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
1016               make_up_icmpv6_payload (ts, ipp, udp);
1017             }
1018             break;
1019           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1020             break;
1021           default:
1022             GNUNET_break_op (0);
1023             GNUNET_STATISTICS_update (stats,
1024                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1025                                       1, GNUNET_NO);
1026             return;
1027           }
1028           /* end AF_INET6 */
1029           break;
1030         default:
1031           GNUNET_break_op (0);
1032           return;
1033         }
1034         msg->size = htons (size);
1035         GNUNET_TUN_calculate_icmp_checksum (icmp,
1036                                             &i2v[1], mlen);
1037         (void) GNUNET_HELPER_send (helper_handle,
1038                                    msg,
1039                                    GNUNET_YES,
1040                                    NULL, NULL);
1041       }
1042     }
1043     break;
1044   default:
1045     GNUNET_assert (0);
1046   }
1047   GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1048                                      GNUNET_TIME_absolute_get ().abs_value_us);
1049   GNUNET_CADET_receive_done (ts->channel);
1050 }
1051
1052
1053 /**
1054  * We got a UDP packet back from the CADET channel.  Check that it is OK.
1055  *
1056  * @param cls our `struct ChannelState *`
1057  * @param reply the actual message
1058  * @return #GNUNET_OK to keep the connection open,
1059  *         #GNUNET_SYSERR to close it (signal serious error)
1060  */
1061 static int
1062 check_udp_back (void *cls,
1063                   const struct GNUNET_EXIT_UdpReplyMessage *reply)
1064 {
1065   struct ChannelState *ts = cls;
1066
1067   if (NULL == ts->heap_node)
1068   {
1069     GNUNET_break_op (0);
1070     return GNUNET_SYSERR;
1071   }
1072   if (AF_UNSPEC == ts->af)
1073   {
1074     GNUNET_break_op (0);
1075     return GNUNET_SYSERR;
1076   }
1077   return GNUNET_OK;
1078 }
1079
1080
1081 /**
1082  * We got a UDP packet back from the CADET channel.  Pass it on to the
1083  * local virtual interface via the helper.
1084  *
1085  * @param cls our `struct ChannelState *`
1086  * @param reply the actual message
1087  */
1088 static void
1089 handle_udp_back (void *cls,
1090                  const struct GNUNET_EXIT_UdpReplyMessage *reply)
1091 {
1092   struct ChannelState *ts = cls;
1093   size_t mlen;
1094
1095   GNUNET_STATISTICS_update (stats,
1096                             gettext_noop ("# UDP packets received from cadet"),
1097                             1,
1098                             GNUNET_NO);
1099   mlen = ntohs (reply->header.size) - sizeof (struct GNUNET_EXIT_UdpReplyMessage);
1100   {
1101     char sbuf[INET6_ADDRSTRLEN];
1102     char dbuf[INET6_ADDRSTRLEN];
1103
1104     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1105                 "Received UDP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1106                 (unsigned int) mlen,
1107                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1108                 ts->destination_port,
1109                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1110                 ts->source_port);
1111   }
1112   switch (ts->af)
1113   {
1114   case AF_INET:
1115     {
1116       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1117         + sizeof (struct GNUNET_TUN_UdpHeader)
1118         + sizeof (struct GNUNET_MessageHeader) +
1119         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1120         mlen;
1121       {
1122         char buf[size] GNUNET_ALIGN;
1123         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1124         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1125         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1126         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1127         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1128         msg->size = htons (size);
1129         tun->flags = htons (0);
1130         tun->proto = htons (ETH_P_IPV4);
1131         GNUNET_TUN_initialize_ipv4_header (ipv4,
1132                                            IPPROTO_UDP,
1133                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1134                                            &ts->destination_ip.v4,
1135                                            &ts->source_ip.v4);
1136         if (0 == ntohs (reply->source_port))
1137           udp->source_port = htons (ts->destination_port);
1138         else
1139           udp->source_port = reply->source_port;
1140         if (0 == ntohs (reply->destination_port))
1141           udp->destination_port = htons (ts->source_port);
1142         else
1143           udp->destination_port = reply->destination_port;
1144         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1145         GNUNET_TUN_calculate_udp4_checksum (ipv4,
1146                                             udp,
1147                                             &reply[1],
1148                                             mlen);
1149         GNUNET_memcpy (&udp[1],
1150                 &reply[1],
1151                 mlen);
1152         (void) GNUNET_HELPER_send (helper_handle,
1153                                    msg,
1154                                    GNUNET_YES,
1155                                    NULL, NULL);
1156       }
1157     }
1158     break;
1159   case AF_INET6:
1160     {
1161       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1162         + sizeof (struct GNUNET_TUN_UdpHeader)
1163         + sizeof (struct GNUNET_MessageHeader) +
1164         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1165         mlen;
1166       {
1167         char buf[size] GNUNET_ALIGN;
1168         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1169         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1170         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1171         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1172         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1173         msg->size = htons (size);
1174         tun->flags = htons (0);
1175         tun->proto = htons (ETH_P_IPV6);
1176         GNUNET_TUN_initialize_ipv6_header (ipv6,
1177                                            IPPROTO_UDP,
1178                                            sizeof (struct GNUNET_TUN_UdpHeader) + mlen,
1179                                            &ts->destination_ip.v6,
1180                                            &ts->source_ip.v6);
1181         if (0 == ntohs (reply->source_port))
1182           udp->source_port = htons (ts->destination_port);
1183         else
1184           udp->source_port = reply->source_port;
1185         if (0 == ntohs (reply->destination_port))
1186           udp->destination_port = htons (ts->source_port);
1187         else
1188           udp->destination_port = reply->destination_port;
1189         udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader));
1190         GNUNET_TUN_calculate_udp6_checksum (ipv6,
1191                                             udp,
1192                                             &reply[1], mlen);
1193         GNUNET_memcpy (&udp[1],
1194                 &reply[1],
1195                 mlen);
1196         (void) GNUNET_HELPER_send (helper_handle,
1197                                    msg,
1198                                    GNUNET_YES,
1199                                    NULL, NULL);
1200       }
1201     }
1202     break;
1203   default:
1204     GNUNET_assert (0);
1205   }
1206   GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1207                                      GNUNET_TIME_absolute_get ().abs_value_us);
1208   GNUNET_CADET_receive_done (ts->channel);
1209 }
1210
1211
1212 /**
1213  * We got a TCP packet back from the CADET channel.  Check it is OK.
1214  *
1215  * @param cls our `struct ChannelState *`
1216  * @param data the actual message
1217  * @return #GNUNET_OK to keep the connection open,
1218  *         #GNUNET_SYSERR to close it (signal serious error)
1219  */
1220 static int
1221 check_tcp_back (void *cls,
1222                   const struct GNUNET_EXIT_TcpDataMessage *data)
1223 {
1224   struct ChannelState *ts = cls;
1225
1226   if (NULL == ts->heap_node)
1227   {
1228     GNUNET_break_op (0);
1229     return GNUNET_SYSERR;
1230   }
1231   if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1232   {
1233     GNUNET_break_op (0);
1234     return GNUNET_SYSERR;
1235   }
1236   return GNUNET_OK;
1237 }
1238
1239
1240 /**
1241  * We got a TCP packet back from the CADET channel.  Pass it on to the
1242  * local virtual interface via the helper.
1243  *
1244  * @param cls our `struct ChannelState *`
1245  * @param data the actual message
1246  */
1247 static void
1248 handle_tcp_back (void *cls,
1249                  const struct GNUNET_EXIT_TcpDataMessage *data)
1250 {
1251   struct ChannelState *ts = cls;
1252   size_t mlen;
1253
1254   GNUNET_STATISTICS_update (stats,
1255                             gettext_noop ("# TCP packets received from cadet"),
1256                             1,
1257                             GNUNET_NO);
1258   mlen = ntohs (data->header.size) - sizeof (struct GNUNET_EXIT_TcpDataMessage);
1259   {
1260     char sbuf[INET6_ADDRSTRLEN];
1261     char dbuf[INET6_ADDRSTRLEN];
1262
1263     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1264                 "Received TCP reply from cadet, sending %u bytes from [%s]:%u -> [%s]:%u via TUN\n",
1265                 (unsigned int) mlen,
1266                 inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)),
1267                 ts->destination_port,
1268                 inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)),
1269                 ts->source_port);
1270   }
1271   switch (ts->af)
1272   {
1273   case AF_INET:
1274     {
1275       size_t size = sizeof (struct GNUNET_TUN_IPv4Header)
1276         + sizeof (struct GNUNET_TUN_TcpHeader)
1277         + sizeof (struct GNUNET_MessageHeader) +
1278         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1279         mlen;
1280       {
1281         char buf[size] GNUNET_ALIGN;
1282         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1283         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1284         struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
1285         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1];
1286         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1287         msg->size = htons (size);
1288         tun->flags = htons (0);
1289         tun->proto = htons (ETH_P_IPV4);
1290         GNUNET_TUN_initialize_ipv4_header (ipv4,
1291                                            IPPROTO_TCP,
1292                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1293                                            &ts->destination_ip.v4,
1294                                            &ts->source_ip.v4);
1295         *tcp = data->tcp_header;
1296         tcp->source_port = htons (ts->destination_port);
1297         tcp->destination_port = htons (ts->source_port);
1298         GNUNET_TUN_calculate_tcp4_checksum (ipv4,
1299                                             tcp,
1300                                             &data[1],
1301                                             mlen);
1302         GNUNET_memcpy (&tcp[1],
1303                        &data[1],
1304                        mlen);
1305         (void) GNUNET_HELPER_send (helper_handle,
1306                                    msg,
1307                                    GNUNET_YES,
1308                                    NULL, NULL);
1309       }
1310     }
1311     break;
1312   case AF_INET6:
1313     {
1314       size_t size = sizeof (struct GNUNET_TUN_IPv6Header)
1315         + sizeof (struct GNUNET_TUN_TcpHeader)
1316         + sizeof (struct GNUNET_MessageHeader) +
1317         sizeof (struct GNUNET_TUN_Layer2PacketHeader) +
1318         mlen;
1319       {
1320         char buf[size] GNUNET_ALIGN;
1321         struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf;
1322         struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1];
1323         struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1];
1324         struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1];
1325         msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1326         msg->size = htons (size);
1327         tun->flags = htons (0);
1328         tun->proto = htons (ETH_P_IPV6);
1329         GNUNET_TUN_initialize_ipv6_header (ipv6,
1330                                            IPPROTO_TCP,
1331                                            sizeof (struct GNUNET_TUN_TcpHeader) + mlen,
1332                                            &ts->destination_ip.v6,
1333                                            &ts->source_ip.v6);
1334         *tcp = data->tcp_header;
1335         tcp->source_port = htons (ts->destination_port);
1336         tcp->destination_port = htons (ts->source_port);
1337         GNUNET_TUN_calculate_tcp6_checksum (ipv6,
1338                                             tcp,
1339                                             &data[1],
1340                                             mlen);
1341         GNUNET_memcpy (&tcp[1],
1342                        &data[1],
1343                        mlen);
1344         (void) GNUNET_HELPER_send (helper_handle,
1345                                    msg,
1346                                    GNUNET_YES,
1347                                    NULL, NULL);
1348       }
1349     }
1350     break;
1351   }
1352   GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1353                                      GNUNET_TIME_absolute_get ().abs_value_us);
1354   GNUNET_CADET_receive_done (ts->channel);
1355 }
1356
1357
1358 /**
1359  * Create a channel for @a ts to @a target at @a port
1360  *
1361  * @param ts channel state to create the channel for
1362  * @param target peer to connect to
1363  * @param port destination port
1364  * @return the channel handle
1365  */
1366 static struct GNUNET_CADET_Channel *
1367 create_channel (struct ChannelState *ts,
1368                 const struct GNUNET_PeerIdentity *target,
1369                 const struct GNUNET_HashCode *port)
1370 {
1371   struct GNUNET_MQ_MessageHandler cadet_handlers[] = {
1372     GNUNET_MQ_hd_var_size (udp_back,
1373                            GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY,
1374                            struct GNUNET_EXIT_UdpReplyMessage,
1375                            ts),
1376     GNUNET_MQ_hd_var_size (tcp_back,
1377                            GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN,
1378                            struct GNUNET_EXIT_TcpDataMessage,
1379                            ts),
1380     GNUNET_MQ_hd_var_size (icmp_back,
1381                            GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN,
1382                            struct GNUNET_EXIT_IcmpToVPNMessage,
1383                            ts),
1384     GNUNET_MQ_handler_end()
1385   };
1386
1387   return GNUNET_CADET_channel_creatE (cadet_handle,
1388                                       ts,
1389                                       target,
1390                                       port,
1391                                       GNUNET_CADET_OPTION_DEFAULT,
1392                                       NULL,
1393                                       &channel_cleaner,
1394                                       cadet_handlers);
1395 }
1396
1397
1398 /**
1399  * Regex has found a potential exit peer for us; consider using it.
1400  *
1401  * @param cls the `struct ChannelState`
1402  * @param id Peer providing a regex that matches the string.
1403  * @param get_path Path of the get request.
1404  * @param get_path_length Lenght of @a get_path.
1405  * @param put_path Path of the put request.
1406  * @param put_path_length Length of the @a put_path.
1407  */
1408 static void
1409 handle_regex_result (void *cls,
1410                      const struct GNUNET_PeerIdentity *id,
1411                      const struct GNUNET_PeerIdentity *get_path,
1412                      unsigned int get_path_length,
1413                      const struct GNUNET_PeerIdentity *put_path,
1414                      unsigned int put_path_length)
1415 {
1416   struct ChannelState *ts = cls;
1417   struct GNUNET_HashCode port;
1418
1419   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1420               "Exit %s found for destination %s!\n",
1421               GNUNET_i2s (id),
1422               print_channel_destination (&ts->destination));
1423   GNUNET_REGEX_search_cancel (ts->search);
1424   ts->search = NULL;
1425   switch (ts->af)
1426   {
1427   case AF_INET:
1428     /* these must match the strings used in gnunet-daemon-exit */
1429     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
1430                         strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
1431                         &port);
1432     break;
1433   case AF_INET6:
1434     /* these must match the strings used in gnunet-daemon-exit */
1435     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
1436                         strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
1437                         &port);
1438     break;
1439   default:
1440     GNUNET_break (0);
1441     return;
1442   }
1443   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1444               "Creating tunnel to %s for destination %s!\n",
1445               GNUNET_i2s (id),
1446               print_channel_destination (&ts->destination));
1447   ts->channel = create_channel (ts,
1448                                 id,
1449                                 &port);
1450 }
1451
1452
1453 /**
1454  * Initialize the given destination entry's cadet channel.
1455  *
1456  * @param dt destination channel for which we need to setup a channel
1457  * @param client_af address family of the address returned to the client
1458  * @return channel state of the channel that was created
1459  */
1460 static struct ChannelState *
1461 create_channel_to_destination (struct DestinationChannel *dt,
1462                                int client_af)
1463 {
1464   struct ChannelState *ts;
1465
1466   GNUNET_STATISTICS_update (stats,
1467                             gettext_noop ("# Cadet channels created"),
1468                             1,
1469                             GNUNET_NO);
1470   ts = GNUNET_new (struct ChannelState);
1471   ts->af = client_af;
1472   ts->destination = *dt->destination;
1473   ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
1474   ts->destination_port = dt->destination_port;
1475   if (dt->destination->is_service)
1476   {
1477     struct GNUNET_HashCode cadet_port;
1478
1479     GNUNET_TUN_compute_service_cadet_port (&ts->destination.details.service_destination.service_descriptor,
1480                                            ts->destination_port,
1481                                            &cadet_port);
1482     ts->channel = create_channel (ts,
1483                                   &dt->destination->details.service_destination.target,
1484                                   &cadet_port);
1485
1486     if (NULL == ts->channel)
1487     {
1488       GNUNET_break (0);
1489       GNUNET_free (ts);
1490       return NULL;
1491     }
1492     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1493                 "Creating channel to peer %s offering service %s on port %u\n",
1494                 GNUNET_i2s (&dt->destination->details.service_destination.target),
1495                 GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor),
1496                 (unsigned int) ts->destination_port);
1497   }
1498   else
1499   {
1500     char *policy;
1501
1502     switch (dt->destination->details.exit_destination.af)
1503     {
1504     case AF_INET:
1505     {
1506       char address[GNUNET_TUN_IPV4_REGEXLEN];
1507
1508       GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4,
1509                                     dt->destination_port,
1510                                     address);
1511       GNUNET_asprintf (&policy,
1512                        "%s%s",
1513                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1514                        address);
1515       break;
1516     }
1517     case AF_INET6:
1518     {
1519       char address[GNUNET_TUN_IPV6_REGEXLEN];
1520
1521       GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6,
1522                                     dt->destination_port,
1523                                     address);
1524       GNUNET_asprintf (&policy,
1525                        "%s%s",
1526                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
1527                        address);
1528       break;
1529     }
1530     default:
1531       GNUNET_assert (0);
1532       break;
1533     }
1534
1535     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1536                 "Requesting connect by string: %s\n",
1537                 policy);
1538     ts->search = GNUNET_REGEX_search (cfg,
1539                                       policy,
1540                                       &handle_regex_result,
1541                                       ts);
1542     GNUNET_free (policy);
1543   }
1544   return ts;
1545 }
1546
1547
1548 /**
1549  * We have too many active channels.  Clean up the oldest channel.
1550  *
1551  * @param except channel that must NOT be cleaned up, even if it is the oldest
1552  */
1553 static void
1554 expire_channel (struct ChannelState *except)
1555 {
1556   struct ChannelState *ts;
1557
1558   ts = GNUNET_CONTAINER_heap_peek (channel_heap);
1559   GNUNET_assert (NULL != ts);
1560   if (except == ts)
1561     return; /* can't do this */
1562   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1563               "Tearing down expired channel to %s\n",
1564               print_channel_destination (&except->destination));
1565   free_channel_state (ts);
1566 }
1567
1568
1569 /**
1570  * Route a packet via cadet to the given destination.
1571  *
1572  * @param destination description of the destination
1573  * @param af address family on this end (AF_INET or AF_INET6)
1574  * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6
1575  * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr)
1576  * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr)
1577  * @param payload payload of the packet after the IP header
1578  * @param payload_length number of bytes in @a payload
1579  */
1580 static void
1581 route_packet (struct DestinationEntry *destination,
1582               int af,
1583               uint8_t protocol,
1584               const void *source_ip,
1585               const void *destination_ip,
1586               const void *payload,
1587               size_t payload_length)
1588 {
1589   struct GNUNET_HashCode key;
1590   struct ChannelState *ts;
1591   size_t alen;
1592   size_t mlen;
1593   struct GNUNET_MQ_Envelope *env;
1594   const struct GNUNET_TUN_UdpHeader *udp;
1595   const struct GNUNET_TUN_TcpHeader *tcp;
1596   const struct GNUNET_TUN_IcmpHeader *icmp;
1597   struct DestinationChannel *dt;
1598   uint16_t source_port;
1599   uint16_t destination_port;
1600
1601   switch (protocol)
1602   {
1603   case IPPROTO_UDP:
1604     {
1605       if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader))
1606       {
1607         /* blame kernel? */
1608         GNUNET_break (0);
1609         return;
1610       }
1611       tcp = NULL; /* make compiler happy */
1612       icmp = NULL;  /* make compiler happy */
1613       udp = payload;
1614       if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader))
1615       {
1616         GNUNET_break_op (0);
1617         return;
1618       }
1619       source_port = ntohs (udp->source_port);
1620       destination_port = ntohs (udp->destination_port);
1621       get_channel_key_from_ips (af,
1622                                 IPPROTO_UDP,
1623                                 source_ip,
1624                                 source_port,
1625                                 destination_ip,
1626                                 destination_port,
1627                                 &key);
1628     }
1629     break;
1630   case IPPROTO_TCP:
1631     {
1632       if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader))
1633       {
1634         /* blame kernel? */
1635         GNUNET_break (0);
1636         return;
1637       }
1638       udp = NULL; /* make compiler happy */
1639       icmp = NULL;  /* make compiler happy */
1640       tcp = payload;
1641       if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
1642       {
1643         GNUNET_break_op (0);
1644         return;
1645       }
1646       source_port = ntohs (tcp->source_port);
1647       destination_port = ntohs (tcp->destination_port);
1648       get_channel_key_from_ips (af,
1649                                 IPPROTO_TCP,
1650                                 source_ip,
1651                                 source_port,
1652                                 destination_ip,
1653                                 destination_port,
1654                                 &key);
1655     }
1656     break;
1657   case IPPROTO_ICMP:
1658   case IPPROTO_ICMPV6:
1659     {
1660       if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) )
1661       {
1662         GNUNET_break (0);
1663         return;
1664       }
1665       if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader))
1666       {
1667         /* blame kernel? */
1668         GNUNET_break (0);
1669         return;
1670       }
1671       tcp = NULL; /* make compiler happy */
1672       udp = NULL;  /* make compiler happy */
1673       icmp = payload;
1674       source_port = 0;
1675       destination_port = 0;
1676       get_channel_key_from_ips (af,
1677                                 protocol,
1678                                 source_ip,
1679                                 0,
1680                                 destination_ip,
1681                                 0,
1682                                 &key);
1683     }
1684     break;
1685   default:
1686     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1687                 _("Protocol %u not supported, dropping\n"),
1688                 (unsigned int) protocol);
1689     return;
1690   }
1691   alen = 0;
1692   if (! destination->is_service)
1693   {
1694     switch (destination->details.exit_destination.af)
1695     {
1696     case AF_INET:
1697       alen = sizeof (struct in_addr);
1698      break;
1699     case AF_INET6:
1700       alen = sizeof (struct in6_addr);
1701       break;
1702     default:
1703       GNUNET_assert (0);
1704     }
1705
1706     {
1707       char sbuf[INET6_ADDRSTRLEN];
1708       char dbuf[INET6_ADDRSTRLEN];
1709       char xbuf[INET6_ADDRSTRLEN];
1710
1711       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1712                   "Routing %s packet from [%s]:%u -> [%s]:%u to destination [%s]:%u\n",
1713                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1714                   inet_ntop (af,
1715                              source_ip,
1716                              sbuf,
1717                              sizeof (sbuf)),
1718                   source_port,
1719                   inet_ntop (af,
1720                              destination_ip,
1721                              dbuf,
1722                              sizeof (dbuf)),
1723                   destination_port,
1724                   inet_ntop (destination->details.exit_destination.af,
1725                              &destination->details.exit_destination.ip,
1726                              xbuf, sizeof (xbuf)),
1727                   destination_port);
1728     }
1729     for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1730       if (dt->destination_port == destination_port)
1731         break;
1732   }
1733   else
1734   {
1735     {
1736       char sbuf[INET6_ADDRSTRLEN];
1737       char dbuf[INET6_ADDRSTRLEN];
1738
1739       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1740                   "Routing %s packet from [%s]:%u -> [%s]:%u to service %s at peer %s\n",
1741                   (protocol == IPPROTO_TCP) ? "TCP" : "UDP",
1742                   inet_ntop (af,
1743                              source_ip,
1744                              sbuf,
1745                              sizeof (sbuf)),
1746                   source_port,
1747                   inet_ntop (af,
1748                              destination_ip,
1749                              dbuf,
1750                              sizeof (dbuf)),
1751                   destination_port,
1752                   GNUNET_h2s (&destination->details.service_destination.service_descriptor),
1753                   GNUNET_i2s (&destination->details.service_destination.target));
1754     }
1755     for (dt = destination->dt_head; NULL != dt; dt = dt->next)
1756       if (dt->destination_port == destination_port)
1757         break;
1758   }
1759   if (NULL == dt)
1760   {
1761     dt = GNUNET_new (struct DestinationChannel);
1762     dt->destination = destination;
1763     GNUNET_CONTAINER_DLL_insert (destination->dt_head,
1764                                  destination->dt_tail,
1765                                  dt);
1766     dt->destination_port = destination_port;
1767   }
1768
1769   /* see if we have an existing channel for this destination */
1770   ts = GNUNET_CONTAINER_multihashmap_get (channel_map,
1771                                           &key);
1772   if (NULL == ts)
1773   {
1774     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1775                 "Creating new channel for key %s\n",
1776                 GNUNET_h2s (&key));
1777     /* need to either use the existing channel from the destination (if still
1778        available) or create a fresh one */
1779     ts = create_channel_to_destination (dt,
1780                                         af);
1781     if (NULL == ts)
1782       return;
1783     /* now bind existing "unbound" channel to our IP/port tuple */
1784     ts->protocol = protocol;
1785     ts->af = af;
1786     if (AF_INET == af)
1787     {
1788       ts->source_ip.v4 = * (const struct in_addr *) source_ip;
1789       ts->destination_ip.v4 = * (const struct in_addr *) destination_ip;
1790     }
1791     else
1792     {
1793       ts->source_ip.v6 = * (const struct in6_addr *) source_ip;
1794       ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip;
1795     }
1796     ts->source_port = source_port;
1797     ts->destination_port = destination_port;
1798     ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap,
1799                                                   ts,
1800                                                   GNUNET_TIME_absolute_get ().abs_value_us);
1801     GNUNET_assert (GNUNET_YES ==
1802                    GNUNET_CONTAINER_multihashmap_put (channel_map,
1803                                                       &key,
1804                                                       ts,
1805                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1806     GNUNET_STATISTICS_update (stats,
1807                               gettext_noop ("# Active channels"),
1808                               1, GNUNET_NO);
1809     while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings)
1810       expire_channel (ts);
1811   }
1812   else
1813   {
1814     GNUNET_CONTAINER_heap_update_cost (ts->heap_node,
1815                                        GNUNET_TIME_absolute_get ().abs_value_us);
1816   }
1817   if (NULL == ts->channel)
1818   {
1819     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1820                 "Packet dropped, channel to %s not yet ready (%s)\n",
1821                 print_channel_destination (&ts->destination),
1822                 (NULL == ts->search)
1823                 ? "EXIT search failed"
1824                 : "EXIT search active");
1825     GNUNET_STATISTICS_update (stats,
1826                               gettext_noop ("# Packets dropped (channel not yet online)"),
1827                               1,
1828                               GNUNET_NO);
1829     return;
1830   }
1831
1832   /* send via channel */
1833   switch (protocol)
1834   {
1835   case IPPROTO_UDP:
1836     if (destination->is_service)
1837     {
1838       struct GNUNET_EXIT_UdpServiceMessage *usm;
1839
1840       mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) +
1841         payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1842       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1843       {
1844         GNUNET_break (0);
1845         return;
1846       }
1847       env = GNUNET_MQ_msg_extra (usm,
1848                                  payload_length - sizeof (struct GNUNET_TUN_UdpHeader),
1849                                  GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE);
1850       /* if the source port is below 32000, we assume it has a special
1851          meaning; if not, we pick a random port (this is a heuristic) */
1852       usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1853       usm->destination_port = udp->destination_port;
1854       GNUNET_memcpy (&usm[1],
1855                      &udp[1],
1856                      payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1857     }
1858     else
1859     {
1860       struct GNUNET_EXIT_UdpInternetMessage *uim;
1861       struct in_addr *ip4dst;
1862       struct in6_addr *ip6dst;
1863       void *payload;
1864
1865       mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) +
1866         alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader);
1867       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1868       {
1869         GNUNET_break (0);
1870         return;
1871       }
1872       env = GNUNET_MQ_msg_extra (uim,
1873                                  payload_length + alen - sizeof (struct GNUNET_TUN_UdpHeader),
1874                                  GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET);
1875       uim->af = htonl (destination->details.exit_destination.af);
1876       uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0;
1877       uim->destination_port = udp->destination_port;
1878       switch (destination->details.exit_destination.af)
1879       {
1880       case AF_INET:
1881         ip4dst = (struct in_addr *) &uim[1];
1882         *ip4dst = destination->details.exit_destination.ip.v4;
1883         payload = &ip4dst[1];
1884         break;
1885       case AF_INET6:
1886         ip6dst = (struct in6_addr *) &uim[1];
1887         *ip6dst = destination->details.exit_destination.ip.v6;
1888         payload = &ip6dst[1];
1889         break;
1890       default:
1891         GNUNET_assert (0);
1892       }
1893       GNUNET_memcpy (payload,
1894                      &udp[1],
1895                      payload_length - sizeof (struct GNUNET_TUN_UdpHeader));
1896     }
1897     break;
1898   case IPPROTO_TCP:
1899     if (GNUNET_NO == ts->is_established)
1900     {
1901       if (destination->is_service)
1902       {
1903         struct GNUNET_EXIT_TcpServiceStartMessage *tsm;
1904
1905         mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) +
1906           payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1907         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1908         {
1909           GNUNET_break (0);
1910           return;
1911         }
1912         env = GNUNET_MQ_msg_extra (tsm,
1913                                    payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1914                                    GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START);
1915         tsm->reserved = htonl (0);
1916         tsm->tcp_header = *tcp;
1917         GNUNET_memcpy (&tsm[1],
1918                        &tcp[1],
1919                        payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1920       }
1921       else
1922       {
1923         struct GNUNET_EXIT_TcpInternetStartMessage *tim;
1924         struct in_addr *ip4dst;
1925         struct in6_addr *ip6dst;
1926         void *payload;
1927
1928         mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) +
1929           alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1930         if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1931         {
1932           GNUNET_break (0);
1933           return;
1934         }
1935         env = GNUNET_MQ_msg_extra (tim,
1936                                    payload_length + alen - sizeof (struct GNUNET_TUN_TcpHeader),
1937                                    GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START);
1938         tim->af = htonl (destination->details.exit_destination.af);
1939         tim->tcp_header = *tcp;
1940         switch (destination->details.exit_destination.af)
1941         {
1942         case AF_INET:
1943           ip4dst = (struct in_addr *) &tim[1];
1944           *ip4dst = destination->details.exit_destination.ip.v4;
1945           payload = &ip4dst[1];
1946           break;
1947         case AF_INET6:
1948           ip6dst = (struct in6_addr *) &tim[1];
1949           *ip6dst = destination->details.exit_destination.ip.v6;
1950           payload = &ip6dst[1];
1951           break;
1952         default:
1953           GNUNET_assert (0);
1954         }
1955         GNUNET_memcpy (payload,
1956                        &tcp[1],
1957                        payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1958       }
1959     }
1960     else
1961     {
1962       struct GNUNET_EXIT_TcpDataMessage *tdm;
1963
1964       mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) +
1965         payload_length - sizeof (struct GNUNET_TUN_TcpHeader);
1966       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1967       {
1968         GNUNET_break (0);
1969         return;
1970       }
1971       env = GNUNET_MQ_msg_extra (tdm,
1972                                  payload_length - sizeof (struct GNUNET_TUN_TcpHeader),
1973                                  GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT);
1974       tdm->reserved = htonl (0);
1975       tdm->tcp_header = *tcp;
1976       GNUNET_memcpy (&tdm[1],
1977                      &tcp[1],
1978                      payload_length - sizeof (struct GNUNET_TUN_TcpHeader));
1979      }
1980     break;
1981   case IPPROTO_ICMP:
1982   case IPPROTO_ICMPV6:
1983     if (destination->is_service)
1984     {
1985       struct GNUNET_EXIT_IcmpServiceMessage *ism;
1986
1987       /* ICMP protocol translation will be done by the receiver (as we don't know
1988          the target AF); however, we still need to possibly discard the payload
1989          depending on the ICMP type */
1990       switch (af)
1991       {
1992       case AF_INET:
1993         switch (icmp->type)
1994         {
1995         case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1996         case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1997           break;
1998         case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1999         case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2000         case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2001           /* throw away ICMP payload, won't be useful for the other side anyway */
2002           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2003           break;
2004         default:
2005           GNUNET_STATISTICS_update (stats,
2006                                     gettext_noop ("# ICMPv4 packets dropped (not allowed)"),
2007                                     1, GNUNET_NO);
2008           return;
2009         }
2010         /* end of AF_INET */
2011         break;
2012       case AF_INET6:
2013         switch (icmp->type)
2014         {
2015         case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2016         case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2017         case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2018         case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2019           /* throw away ICMP payload, won't be useful for the other side anyway */
2020           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2021           break;
2022         case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2023         case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2024           break;
2025         default:
2026           GNUNET_STATISTICS_update (stats,
2027                                     gettext_noop ("# ICMPv6 packets dropped (not allowed)"),
2028                                     1, GNUNET_NO);
2029           return;
2030         }
2031         /* end of AF_INET6 */
2032         break;
2033       default:
2034         GNUNET_assert (0);
2035         break;
2036       }
2037
2038       /* update length calculations, as payload_length may have changed */
2039       mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) +
2040         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2041       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2042       {
2043         GNUNET_break (0);
2044         return;
2045       }
2046
2047       env = GNUNET_MQ_msg_extra (ism,
2048                                  payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2049                                  GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE);
2050       ism->af = htonl (af); /* need to tell destination ICMP protocol family! */
2051       ism->icmp_header = *icmp;
2052       GNUNET_memcpy (&ism[1],
2053                      &icmp[1],
2054                      payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2055     }
2056     else
2057     {
2058       struct GNUNET_EXIT_IcmpInternetMessage *iim;
2059       struct in_addr *ip4dst;
2060       struct in6_addr *ip6dst;
2061       void *payload;
2062       uint8_t new_type;
2063
2064       /* Perform ICMP protocol-translation (depending on destination AF and source AF)
2065          and throw away ICMP payload depending on ICMP message type */
2066       switch (af)
2067       {
2068       case AF_INET:
2069         switch (icmp->type)
2070         {
2071         case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2072           if (destination->details.exit_destination.af == AF_INET6)
2073             new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2074           break;
2075         case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2076           if (destination->details.exit_destination.af == AF_INET6)
2077             new_type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2078           break;
2079         case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2080           if (destination->details.exit_destination.af == AF_INET6)
2081             new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2082           /* throw away IP-payload, exit will have to make it up anyway */
2083           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2084           break;
2085         case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2086           if (destination->details.exit_destination.af == AF_INET6)
2087             new_type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2088           /* throw away IP-payload, exit will have to make it up anyway */
2089           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2090           break;
2091         case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2092           if (destination->details.exit_destination.af == AF_INET6)
2093             {
2094               GNUNET_STATISTICS_update (stats,
2095                                         gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2096                                         1, GNUNET_NO);
2097               return;
2098             }
2099           /* throw away IP-payload, exit will have to make it up anyway */
2100           payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2101           break;
2102         default:
2103           GNUNET_STATISTICS_update (stats,
2104                                     gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2105                                     1, GNUNET_NO);
2106           return;
2107         }
2108         /* end of AF_INET */
2109         break;
2110       case AF_INET6:
2111         switch (icmp->type)
2112           {
2113           case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2114             if (destination->details.exit_destination.af == AF_INET6)
2115               new_type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2116             /* throw away IP-payload, exit will have to make it up anyway */
2117             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2118             break;
2119           case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2120             if (destination->details.exit_destination.af == AF_INET)
2121               new_type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2122             /* throw away IP-payload, exit will have to make it up anyway */
2123             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2124             break;
2125           case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2126             if (destination->details.exit_destination.af == AF_INET)
2127             {
2128               GNUNET_STATISTICS_update (stats,
2129                                         gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2130                                         1, GNUNET_NO);
2131               return;
2132             }
2133             /* throw away IP-payload, exit will have to make it up anyway */
2134             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2135             break;
2136           case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2137             if (destination->details.exit_destination.af == AF_INET)
2138             {
2139               GNUNET_STATISTICS_update (stats,
2140                                         gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2141                                         1, GNUNET_NO);
2142               return;
2143             }
2144             /* throw away IP-payload, exit will have to make it up anyway */
2145             payload_length = sizeof (struct GNUNET_TUN_IcmpHeader);
2146             break;
2147           case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2148             if (destination->details.exit_destination.af == AF_INET)
2149               new_type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2150             break;
2151           case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2152             if (destination->details.exit_destination.af == AF_INET)
2153               new_type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2154             break;
2155           default:
2156             GNUNET_STATISTICS_update (stats,
2157                                       gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2158                                       1, GNUNET_NO);
2159             return;
2160           }
2161         /* end of AF_INET6 */
2162         break;
2163       default:
2164         GNUNET_assert (0);
2165       }
2166
2167       /* update length calculations, as payload_length may have changed */
2168       mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) +
2169         alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader);
2170       if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2171       {
2172         GNUNET_break (0);
2173         return;
2174       }
2175       env = GNUNET_MQ_msg_extra (iim,
2176                                  alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader),
2177                                  GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET);
2178       iim->icmp_header = *icmp;
2179       iim->icmp_header.type = new_type;
2180       iim->af = htonl (destination->details.exit_destination.af);
2181       switch (destination->details.exit_destination.af)
2182       {
2183       case AF_INET:
2184         ip4dst = (struct in_addr *) &iim[1];
2185         *ip4dst = destination->details.exit_destination.ip.v4;
2186         payload = &ip4dst[1];
2187         break;
2188       case AF_INET6:
2189         ip6dst = (struct in6_addr *) &iim[1];
2190         *ip6dst = destination->details.exit_destination.ip.v6;
2191         payload = &ip6dst[1];
2192         break;
2193       default:
2194         GNUNET_assert (0);
2195       }
2196       GNUNET_memcpy (payload,
2197                      &icmp[1],
2198                      payload_length - sizeof (struct GNUNET_TUN_IcmpHeader));
2199     }
2200     break;
2201   default:
2202     /* not supported above, how can we get here !? */
2203     GNUNET_assert (0);
2204     break;
2205   }
2206   ts->is_established = GNUNET_YES;
2207   send_to_channel (ts,
2208                    env);
2209 }
2210
2211
2212 /**
2213  * Receive packets from the helper-process (someone send to the local
2214  * virtual channel interface).  Find the destination mapping, and if it
2215  * exists, identify the correct CADET channel (or possibly create it)
2216  * and forward the packet.
2217  *
2218  * @param cls closure, NULL
2219  * @param client NULL
2220  * @param message message we got from the client (VPN channel interface)
2221  */
2222 static int
2223 message_token (void *cls,
2224                void *client,
2225                const struct GNUNET_MessageHeader *message)
2226 {
2227   const struct GNUNET_TUN_Layer2PacketHeader *tun;
2228   size_t mlen;
2229   struct GNUNET_HashCode key;
2230   struct DestinationEntry *de;
2231
2232   GNUNET_STATISTICS_update (stats,
2233                             gettext_noop ("# Packets received from TUN interface"),
2234                             1, GNUNET_NO);
2235   mlen = ntohs (message->size);
2236   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) ||
2237        (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) )
2238   {
2239     GNUNET_break (0);
2240     return GNUNET_OK;
2241   }
2242   tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
2243   mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader));
2244   switch (ntohs (tun->proto))
2245   {
2246   case ETH_P_IPV6:
2247     {
2248       const struct GNUNET_TUN_IPv6Header *pkt6;
2249
2250       if (mlen < sizeof (struct GNUNET_TUN_IPv6Header))
2251       {
2252         /* blame kernel */
2253         GNUNET_break (0);
2254         return GNUNET_OK;
2255       }
2256       pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1];
2257       get_destination_key_from_ip (AF_INET6,
2258                                    &pkt6->destination_address,
2259                                    &key);
2260       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2261       if (NULL == de)
2262       {
2263         char buf[INET6_ADDRSTRLEN];
2264
2265         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2266                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
2267                     inet_ntop (AF_INET6,
2268                                &pkt6->destination_address,
2269                                buf,
2270                                sizeof (buf)));
2271         return GNUNET_OK;
2272       }
2273       route_packet (de,
2274                     AF_INET6,
2275                     pkt6->next_header,
2276                     &pkt6->source_address,
2277                     &pkt6->destination_address,
2278                     &pkt6[1],
2279                     mlen - sizeof (struct GNUNET_TUN_IPv6Header));
2280     }
2281     break;
2282   case ETH_P_IPV4:
2283     {
2284       struct GNUNET_TUN_IPv4Header *pkt4;
2285
2286       if (mlen < sizeof (struct GNUNET_TUN_IPv4Header))
2287       {
2288         /* blame kernel */
2289         GNUNET_break (0);
2290         return GNUNET_OK;
2291       }
2292       pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1];
2293       get_destination_key_from_ip (AF_INET,
2294                                    &pkt4->destination_address,
2295                                    &key);
2296       de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key);
2297       if (NULL == de)
2298       {
2299         char buf[INET_ADDRSTRLEN];
2300
2301         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2302                     _("Packet received for unmapped destination `%s' (dropping it)\n"),
2303                     inet_ntop (AF_INET,
2304                                &pkt4->destination_address,
2305                                buf,
2306                                sizeof (buf)));
2307         return GNUNET_OK;
2308       }
2309       if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
2310       {
2311         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2312                     _("Received IPv4 packet with options (dropping it)\n"));
2313         return GNUNET_OK;
2314       }
2315       route_packet (de,
2316                     AF_INET,
2317                     pkt4->protocol,
2318                     &pkt4->source_address,
2319                     &pkt4->destination_address,
2320                     &pkt4[1],
2321                     mlen - sizeof (struct GNUNET_TUN_IPv4Header));
2322     }
2323     break;
2324   default:
2325     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2326                 _("Received packet of unknown protocol %d from TUN (dropping it)\n"),
2327                 (unsigned int) ntohs (tun->proto));
2328     break;
2329   }
2330   return GNUNET_OK;
2331 }
2332
2333
2334 /**
2335  * Allocate an IPv4 address from the range of the channel
2336  * for a new redirection.
2337  *
2338  * @param v4 where to store the address
2339  * @return #GNUNET_OK on success,
2340  *         #GNUNET_SYSERR on error
2341  */
2342 static int
2343 allocate_v4_address (struct in_addr *v4)
2344 {
2345   const char *ipv4addr = vpn_argv[4];
2346   const char *ipv4mask = vpn_argv[5];
2347   struct in_addr addr;
2348   struct in_addr mask;
2349   struct in_addr rnd;
2350   struct GNUNET_HashCode key;
2351   unsigned int tries;
2352
2353   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr));
2354   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask));
2355   /* Given 192.168.0.1/255.255.0.0, we want a mask
2356      of '192.168.255.255', thus:  */
2357   mask.s_addr = addr.s_addr | ~mask.s_addr;
2358   tries = 0;
2359   do
2360     {
2361       tries++;
2362       if (tries > 16)
2363       {
2364         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2365                     _("Failed to find unallocated IPv4 address in VPN's range\n"));
2366         return GNUNET_SYSERR;
2367       }
2368       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
2369       rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2370                                              UINT32_MAX);
2371       v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
2372       get_destination_key_from_ip (AF_INET,
2373                                    v4,
2374                                    &key);
2375     }
2376   while ( (GNUNET_YES ==
2377            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2378                                                    &key)) ||
2379           (v4->s_addr == addr.s_addr) ||
2380           (v4->s_addr == mask.s_addr) );
2381   return GNUNET_OK;
2382 }
2383
2384
2385 /**
2386  * Allocate an IPv6 address from the range of the channel
2387  * for a new redirection.
2388  *
2389  * @param v6 where to store the address
2390  * @return #GNUNET_OK on success,
2391  *         #GNUNET_SYSERR on error
2392  */
2393 static int
2394 allocate_v6_address (struct in6_addr *v6)
2395 {
2396   const char *ipv6addr = vpn_argv[2];
2397   struct in6_addr addr;
2398   struct in6_addr mask;
2399   struct in6_addr rnd;
2400   int i;
2401   struct GNUNET_HashCode key;
2402   unsigned int tries;
2403
2404   GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr));
2405   GNUNET_assert (ipv6prefix < 128);
2406   /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
2407      thus: */
2408   mask = addr;
2409   for (i=127;i>=ipv6prefix;i--)
2410     mask.s6_addr[i / 8] |= (1 << (i % 8));
2411
2412   /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
2413   tries = 0;
2414   do
2415     {
2416       tries++;
2417       if (tries > 16)
2418         {
2419           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2420                       _("Failed to find unallocated IPv6 address in VPN's range\n"));
2421           return GNUNET_SYSERR;
2422
2423         }
2424       for (i=0;i<16;i++)
2425         {
2426           rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
2427                                                                      256);
2428           v6->s6_addr[i]
2429             = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
2430         }
2431       get_destination_key_from_ip (AF_INET6,
2432                                    v6,
2433                                    &key);
2434     }
2435   while ( (GNUNET_YES ==
2436            GNUNET_CONTAINER_multihashmap_contains (destination_map,
2437                                                    &key)) ||
2438           (0 == memcmp (v6,
2439                         &addr,
2440                         sizeof (struct in6_addr))) ||
2441           (0 == memcmp (v6,
2442                         &mask,
2443                         sizeof (struct in6_addr))) );
2444   return GNUNET_OK;
2445 }
2446
2447
2448 /**
2449  * Free resources occupied by a destination entry.
2450  *
2451  * @param de entry to free
2452  */
2453 static void
2454 free_destination_entry (struct DestinationEntry *de)
2455 {
2456   struct DestinationChannel *dt;
2457
2458   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2459               "Cleaning up destination entry `%s'\n",
2460               print_channel_destination (de));
2461   GNUNET_STATISTICS_update (stats,
2462                             gettext_noop ("# Active destinations"),
2463                             -1, GNUNET_NO);
2464   while (NULL != (dt = de->dt_head))
2465   {
2466     GNUNET_CONTAINER_DLL_remove (de->dt_head,
2467                                  de->dt_tail,
2468                                  dt);
2469     GNUNET_free (dt);
2470   }
2471   if (NULL != de->heap_node)
2472   {
2473     GNUNET_CONTAINER_heap_remove_node (de->heap_node);
2474     de->heap_node = NULL;
2475     GNUNET_assert (GNUNET_YES ==
2476                    GNUNET_CONTAINER_multihashmap_remove (destination_map,
2477                                                          &de->key,
2478                                                          de));
2479   }
2480   GNUNET_free (de);
2481 }
2482
2483
2484 /**
2485  * We have too many active destinations.  Clean up the oldest destination.
2486  *
2487  * @param except destination that must NOT be cleaned up, even if it is the oldest
2488  */
2489 static void
2490 expire_destination (struct DestinationEntry *except)
2491 {
2492   struct DestinationEntry *de;
2493
2494   de = GNUNET_CONTAINER_heap_peek (destination_heap);
2495   GNUNET_assert (NULL != de);
2496   if (except == de)
2497     return; /* can't do this */
2498   free_destination_entry (de);
2499 }
2500
2501
2502 /**
2503  * Allocate an IP address for the response.
2504  *
2505  * @param result_af desired address family; set to the actual
2506  *        address family; can initially be AF_UNSPEC if there
2507  *        is no preference; will be set to AF_UNSPEC if the
2508  *        allocation failed
2509  * @param addr set to either v4 or v6 depending on which
2510  *         storage location was used; set to NULL if allocation failed
2511  * @param v4 storage space for an IPv4 address
2512  * @param v6 storage space for an IPv6 address
2513  * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was
2514  *         an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC)
2515  */
2516 static int
2517 allocate_response_ip (int *result_af,
2518                       void **addr,
2519                       struct in_addr *v4,
2520                       struct in6_addr *v6)
2521 {
2522   *addr = NULL;
2523   switch (*result_af)
2524   {
2525   case AF_INET:
2526     if (GNUNET_OK !=
2527         allocate_v4_address (v4))
2528       *result_af = AF_UNSPEC;
2529     else
2530       *addr = v4;
2531     break;
2532   case AF_INET6:
2533     if (GNUNET_OK !=
2534         allocate_v6_address (v6))
2535       *result_af = AF_UNSPEC;
2536     else
2537       *addr = v6;
2538     break;
2539   case AF_UNSPEC:
2540     if (GNUNET_OK ==
2541         allocate_v4_address (v4))
2542     {
2543       *addr = v4;
2544       *result_af = AF_INET;
2545     }
2546     else if (GNUNET_OK ==
2547         allocate_v6_address (v6))
2548     {
2549       *addr = v6;
2550       *result_af = AF_INET6;
2551     }
2552     break;
2553   default:
2554     GNUNET_break (0);
2555     return GNUNET_SYSERR;
2556   }
2557   return GNUNET_OK;
2558 }
2559
2560
2561 /**
2562  * A client asks us to setup a redirection via some exit node to a
2563  * particular IP.  Check if @a msg is well-formed.
2564  * allocated IP.
2565  *
2566  * @param cls client requesting client
2567  * @param msg redirection request
2568  * @return #GNUNET_OK if @a msg is well-formed
2569  */
2570 static int
2571 check_client_redirect_to_ip (void *cls,
2572                              const struct RedirectToIpRequestMessage *msg)
2573 {
2574   size_t alen;
2575   int addr_af;
2576
2577   alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2578   addr_af = (int) htonl (msg->addr_af);
2579   switch (addr_af)
2580   {
2581   case AF_INET:
2582     if (alen != sizeof (struct in_addr))
2583     {
2584       GNUNET_break (0);
2585       return GNUNET_SYSERR;
2586     }
2587     break;
2588   case AF_INET6:
2589     if (alen != sizeof (struct in6_addr))
2590     {
2591       GNUNET_break (0);
2592       return GNUNET_SYSERR;
2593     }
2594     break;
2595   default:
2596     GNUNET_break (0);
2597     return GNUNET_SYSERR;
2598   }
2599   return GNUNET_OK;
2600 }
2601
2602
2603 /**
2604  * A client asks us to setup a redirection via some exit node to a
2605  * particular IP.  Setup the redirection and give the client the
2606  * allocated IP.
2607  *
2608  * @param cls client requesting client
2609  * @param msg redirection request
2610  */
2611 static void
2612 handle_client_redirect_to_ip (void *cls,
2613                               const struct RedirectToIpRequestMessage *msg)
2614 {
2615   struct GNUNET_SERVICE_Client *client = cls;
2616   size_t alen;
2617   int addr_af;
2618   int result_af;
2619   struct in_addr v4;
2620   struct in6_addr v6;
2621   void *addr;
2622   struct DestinationEntry *de;
2623   struct GNUNET_HashCode key;
2624
2625   alen = ntohs (msg->header.size) - sizeof (struct RedirectToIpRequestMessage);
2626   addr_af = (int) htonl (msg->addr_af);
2627   /* allocate response IP */
2628   result_af = (int) htonl (msg->result_af);
2629   if (GNUNET_OK != allocate_response_ip (&result_af,
2630                                          &addr,
2631                                          &v4, &v6))
2632   {
2633     GNUNET_SERVICE_client_drop (client);
2634     return;
2635   }
2636   /* send reply with our IP address */
2637   send_client_reply (client,
2638                      msg->request_id,
2639                      result_af,
2640                      addr);
2641   if (result_af == AF_UNSPEC)
2642   {
2643     /* failure, we're done */
2644     GNUNET_SERVICE_client_continue (client);
2645     return;
2646   }
2647
2648   {
2649     char sbuf[INET6_ADDRSTRLEN];
2650     char dbuf[INET6_ADDRSTRLEN];
2651
2652     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2653                 "Allocated address %s for redirection via exit to %s\n",
2654                 inet_ntop (result_af,
2655                            addr,
2656                            sbuf,
2657                            sizeof (sbuf)),
2658                 inet_ntop (addr_af,
2659                            &msg[1],
2660                            dbuf,
2661                            sizeof (dbuf)));
2662   }
2663
2664   /* setup destination record */
2665   de = GNUNET_new (struct DestinationEntry);
2666   de->is_service = GNUNET_NO;
2667   de->details.exit_destination.af = addr_af;
2668   GNUNET_memcpy (&de->details.exit_destination.ip,
2669                  &msg[1],
2670                  alen);
2671   get_destination_key_from_ip (result_af,
2672                                addr,
2673                                &key);
2674   de->key = key;
2675   GNUNET_assert (GNUNET_OK ==
2676                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2677                                                     &key,
2678                                                     de,
2679                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2680   de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap,
2681                                                 de,
2682                                                 GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2683   GNUNET_STATISTICS_update (stats,
2684                             gettext_noop ("# Active destinations"),
2685                             1, GNUNET_NO);
2686   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2687     expire_destination (de);
2688   GNUNET_SERVICE_client_continue (client);
2689 }
2690
2691
2692 /**
2693  * A client asks us to setup a redirection to a particular peer
2694  * offering a service.  Setup the redirection and give the client the
2695  * allocated IP.
2696  *
2697  * @param cls requesting client
2698  * @param msg redirection request
2699  */
2700 static void
2701 handle_client_redirect_to_service (void *cls,
2702                                    const struct RedirectToServiceRequestMessage *msg)
2703 {
2704   struct GNUNET_SERVICE_Client *client = cls;
2705   int result_af;
2706   struct in_addr v4;
2707   struct in6_addr v6;
2708   void *addr;
2709   struct DestinationEntry *de;
2710   struct GNUNET_HashCode key;
2711   struct DestinationChannel *dt;
2712
2713   /* allocate response IP */
2714   result_af = (int) htonl (msg->result_af);
2715   if (GNUNET_OK !=
2716       allocate_response_ip (&result_af,
2717                             &addr,
2718                             &v4,
2719                             &v6))
2720   {
2721     GNUNET_break (0);
2722     GNUNET_SERVICE_client_drop (client);
2723     return;
2724   }
2725   send_client_reply (client,
2726                      msg->request_id,
2727                      result_af,
2728                      addr);
2729   if (result_af == AF_UNSPEC)
2730   {
2731     /* failure, we're done */
2732     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2733                 _("Failed to allocate IP address for new destination\n"));
2734     GNUNET_SERVICE_client_continue (client);
2735     return;
2736   }
2737
2738   {
2739     char sbuf[INET6_ADDRSTRLEN];
2740
2741     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2742                 "Allocated address %s for redirection to service %s on peer %s\n",
2743                 inet_ntop (result_af,
2744                            addr,
2745                            sbuf,
2746                            sizeof (sbuf)),
2747                 GNUNET_h2s (&msg->service_descriptor),
2748                 GNUNET_i2s (&msg->target));
2749   }
2750
2751   /* setup destination record */
2752   de = GNUNET_new (struct DestinationEntry);
2753   de->is_service = GNUNET_YES;
2754   de->details.service_destination.target = msg->target;
2755   de->details.service_destination.service_descriptor = msg->service_descriptor;
2756   get_destination_key_from_ip (result_af,
2757                                addr,
2758                                &key);
2759   de->key = key;
2760   GNUNET_assert (GNUNET_OK ==
2761                  GNUNET_CONTAINER_multihashmap_put (destination_map,
2762                                                     &key,
2763                                                     de,
2764                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
2765   de->heap_node
2766     = GNUNET_CONTAINER_heap_insert (destination_heap,
2767                                     de,
2768                                     GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us);
2769   while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings)
2770     expire_destination (de);
2771
2772   dt = GNUNET_new (struct DestinationChannel);
2773   dt->destination = de;
2774   GNUNET_CONTAINER_DLL_insert (de->dt_head,
2775                                de->dt_tail,
2776                                dt);
2777   /* we're done */
2778   GNUNET_SERVICE_client_continue (client);
2779 }
2780
2781
2782
2783 /**
2784  * Free memory occupied by an entry in the destination map.
2785  *
2786  * @param cls unused
2787  * @param key unused
2788  * @param value a `struct DestinationEntry *`
2789  * @return #GNUNET_OK (continue to iterate)
2790  */
2791 static int
2792 cleanup_destination (void *cls,
2793                      const struct GNUNET_HashCode *key,
2794                      void *value)
2795 {
2796   struct DestinationEntry *de = value;
2797
2798   free_destination_entry (de);
2799   return GNUNET_OK;
2800 }
2801
2802
2803 /**
2804  * Free memory occupied by an entry in the channel map.
2805  *
2806  * @param cls unused
2807  * @param key unused
2808  * @param value a `struct ChannelState *`
2809  * @return #GNUNET_OK (continue to iterate)
2810  */
2811 static int
2812 cleanup_channel (void *cls,
2813                  const struct GNUNET_HashCode *key,
2814                  void *value)
2815 {
2816   struct ChannelState *ts = value;
2817
2818   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2819               "Tearing down channel to `%s' during cleanup\n",
2820               print_channel_destination (&ts->destination));
2821   free_channel_state (ts);
2822   return GNUNET_OK;
2823 }
2824
2825
2826 /**
2827  * Function scheduled as very last function, cleans up after us
2828  *
2829  * @param cls unused
2830  */
2831 static void
2832 cleanup (void *cls)
2833 {
2834   unsigned int i;
2835
2836   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2837               "VPN is shutting down\n");
2838   if (NULL != destination_map)
2839   {
2840     GNUNET_CONTAINER_multihashmap_iterate (destination_map,
2841                                            &cleanup_destination,
2842                                            NULL);
2843     GNUNET_CONTAINER_multihashmap_destroy (destination_map);
2844     destination_map = NULL;
2845   }
2846   if (NULL != destination_heap)
2847   {
2848     GNUNET_CONTAINER_heap_destroy (destination_heap);
2849     destination_heap = NULL;
2850   }
2851   if (NULL != channel_map)
2852   {
2853     GNUNET_CONTAINER_multihashmap_iterate (channel_map,
2854                                            &cleanup_channel,
2855                                            NULL);
2856     GNUNET_CONTAINER_multihashmap_destroy (channel_map);
2857     channel_map = NULL;
2858   }
2859   if (NULL != channel_heap)
2860   {
2861     GNUNET_CONTAINER_heap_destroy (channel_heap);
2862     channel_heap = NULL;
2863   }
2864   if (NULL != cadet_handle)
2865   {
2866     GNUNET_CADET_disconnect (cadet_handle);
2867     cadet_handle = NULL;
2868   }
2869   if (NULL != helper_handle)
2870   {
2871     GNUNET_HELPER_kill (helper_handle, GNUNET_NO);
2872     GNUNET_HELPER_wait (helper_handle);
2873     helper_handle = NULL;
2874   }
2875   if (NULL != stats)
2876   {
2877     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
2878     stats = NULL;
2879   }
2880   for (i=0;i<5;i++)
2881     GNUNET_free_non_null (vpn_argv[i]);
2882 }
2883
2884
2885 /**
2886  * Callback called when a client connects to the service.
2887  *
2888  * @param cls closure for the service
2889  * @param c the new client that connected to the service
2890  * @param mq the message queue used to send messages to the client
2891  * @return @a c
2892  */
2893 static void *
2894 client_connect_cb (void *cls,
2895                    struct GNUNET_SERVICE_Client *c,
2896                    struct GNUNET_MQ_Handle *mq)
2897 {
2898   return c;
2899 }
2900
2901
2902 /**
2903  * Callback called when a client disconnected from the service
2904  *
2905  * @param cls closure for the service
2906  * @param c the client that disconnected
2907  * @param internal_cls should be equal to @a c
2908  */
2909 static void
2910 client_disconnect_cb (void *cls,
2911                       struct GNUNET_SERVICE_Client *c,
2912                       void *internal_cls)
2913 {
2914   GNUNET_assert (c == internal_cls);
2915 }
2916
2917
2918 /**
2919  * Main function that will be run by the scheduler.
2920  *
2921  * @param cls closure
2922  * @param cfg_ configuration
2923  * @param service the initialized service
2924  */
2925 static void
2926 run (void *cls,
2927      const struct GNUNET_CONFIGURATION_Handle *cfg_,
2928      struct GNUNET_SERVICE_Handle *service)
2929 {
2930   char *ifname;
2931   char *ipv6addr;
2932   char *ipv6prefix_s;
2933   char *ipv4addr;
2934   char *ipv4mask;
2935   struct in_addr v4;
2936   struct in6_addr v6;
2937   char *binary;
2938
2939   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
2940
2941   if (GNUNET_YES !=
2942       GNUNET_OS_check_helper_binary (binary,
2943                                      GNUNET_YES,
2944                                      "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
2945   {
2946     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2947                 "`%s' is not SUID, refusing to run.\n",
2948                 "gnunet-helper-vpn");
2949     GNUNET_free (binary);
2950     global_ret = 1;
2951     /* we won't "really" exit here, as the 'service' is still running;
2952        however, as no handlers are registered, the service won't do
2953        anything either */
2954     return;
2955   }
2956   GNUNET_free (binary);
2957   cfg = cfg_;
2958   stats = GNUNET_STATISTICS_create ("vpn", cfg);
2959   if (GNUNET_OK !=
2960       GNUNET_CONFIGURATION_get_value_number (cfg,
2961                                              "VPN",
2962                                              "MAX_MAPPING",
2963                                              &max_destination_mappings))
2964     max_destination_mappings = 200;
2965   if (GNUNET_OK !=
2966       GNUNET_CONFIGURATION_get_value_number (cfg,
2967                                              "VPN",
2968                                              "MAX_TUNNELS",
2969                                              &max_channel_mappings))
2970     max_channel_mappings = 200;
2971
2972   destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO);
2973   destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2974   channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO);
2975   channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2976
2977
2978   vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
2979   if (GNUNET_SYSERR ==
2980       GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname))
2981   {
2982     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME");
2983     GNUNET_SCHEDULER_shutdown ();
2984     return;
2985   }
2986   vpn_argv[1] = ifname;
2987   ipv6addr = NULL;
2988   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6))
2989   {
2990     if ( (GNUNET_SYSERR ==
2991           GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR",
2992                                                  &ipv6addr) ||
2993           (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
2994     {
2995       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR",
2996                                  _("Must specify valid IPv6 address"));
2997       GNUNET_SCHEDULER_shutdown ();
2998       GNUNET_free_non_null (ipv6addr);
2999       return;
3000     }
3001     vpn_argv[2] = ipv6addr;
3002     ipv6prefix_s = NULL;
3003     if (GNUNET_SYSERR ==
3004         GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX",
3005                                                &ipv6prefix_s))
3006     {
3007       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX");
3008       GNUNET_SCHEDULER_shutdown ();
3009       GNUNET_free_non_null (ipv6prefix_s);
3010       return;
3011     }
3012     vpn_argv[3] = ipv6prefix_s;
3013     if ( (GNUNET_OK !=
3014           GNUNET_CONFIGURATION_get_value_number (cfg, "VPN",
3015                                                  "IPV6PREFIX",
3016                                                  &ipv6prefix)) ||
3017          (ipv6prefix >= 127) )
3018     {
3019       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3020                                  _("Must specify valid IPv6 mask"));
3021       GNUNET_SCHEDULER_shutdown ();
3022       return;
3023     }
3024   }
3025   else
3026   {
3027     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3028                 _("IPv6 support disabled as this system does not support IPv6\n"));
3029     vpn_argv[2] = GNUNET_strdup ("-");
3030     vpn_argv[3] = GNUNET_strdup ("-");
3031   }
3032   if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET))
3033   {
3034     ipv4addr = NULL;
3035     if ( (GNUNET_SYSERR ==
3036           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR",
3037                                                  &ipv4addr) ||
3038           (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
3039     {
3040       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR",
3041                                  _("Must specify valid IPv4 address"));
3042       GNUNET_SCHEDULER_shutdown ();
3043       GNUNET_free_non_null (ipv4addr);
3044       return;
3045     }
3046     vpn_argv[4] = ipv4addr;
3047     ipv4mask = NULL;
3048     if ( (GNUNET_SYSERR ==
3049           GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK",
3050                                                  &ipv4mask) ||
3051           (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
3052     {
3053       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK",
3054                                  _("Must specify valid IPv4 mask"));
3055       GNUNET_SCHEDULER_shutdown ();
3056       GNUNET_free_non_null (ipv4mask);
3057       return;
3058     }
3059     vpn_argv[5] = ipv4mask;
3060   }
3061   else
3062   {
3063     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3064                 _("IPv4 support disabled as this system does not support IPv4\n"));
3065     vpn_argv[4] = GNUNET_strdup ("-");
3066     vpn_argv[5] = GNUNET_strdup ("-");
3067   }
3068   vpn_argv[6] = NULL;
3069
3070   cadet_handle = GNUNET_CADET_connecT (cfg_);
3071     // FIXME never opens ports???
3072   helper_handle = GNUNET_HELPER_start (GNUNET_NO,
3073                                        "gnunet-helper-vpn", vpn_argv,
3074                                        &message_token, NULL, NULL);
3075   GNUNET_SCHEDULER_add_shutdown (&cleanup,
3076                                  NULL);
3077 }
3078
3079
3080 /**
3081  * Define "main" method using service macro.
3082  */
3083 GNUNET_SERVICE_MAIN
3084 ("vpn",
3085  GNUNET_SERVICE_OPTION_NONE,
3086  &run,
3087  &client_connect_cb,
3088  &client_disconnect_cb,
3089  NULL,
3090  GNUNET_MQ_hd_var_size (client_redirect_to_ip,
3091                         GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP,
3092                         struct RedirectToIpRequestMessage,
3093                         NULL),
3094  GNUNET_MQ_hd_fixed_size (client_redirect_to_service,
3095                           GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE,
3096                           struct RedirectToServiceRequestMessage,
3097                           NULL),
3098  GNUNET_MQ_handler_end ());
3099
3100
3101 /* end of gnunet-service-vpn.c */