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