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