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