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