-fix indent
[oweals/gnunet.git] / src / exit / gnunet-daemon-exit.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010-2013 Christian Grothoff
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file exit/gnunet-daemon-exit.c
23  * @brief tool to allow IP traffic exit from the GNUnet cadet to the Internet
24  * @author Philipp Toelke
25  * @author Christian Grothoff
26  *
27  * TODO:
28  * - test
29  *
30  * Design:
31  * - which code should advertise services? the service model is right
32  *   now a bit odd, especially as this code DOES the exit and knows
33  *   the DNS "name", but OTOH this is clearly NOT the place to advertise
34  *   the service's existence; maybe the daemon should turn into a
35  *   service with an API to add local-exit services dynamically?
36  */
37 #include "platform.h"
38 #include "gnunet_util_lib.h"
39 #include "gnunet_protocols.h"
40 #include "gnunet_applications.h"
41 #include "gnunet_dht_service.h"
42 #include "gnunet_cadet_service.h"
43 #include "gnunet_dnsparser_lib.h"
44 #include "gnunet_dnsstub_lib.h"
45 #include "gnunet_statistics_service.h"
46 #include "gnunet_constants.h"
47 #include "gnunet_signatures.h"
48 #include "gnunet_tun_lib.h"
49 #include "gnunet_regex_service.h"
50 #include "exit.h"
51 #include "block_dns.h"
52
53
54 /**
55  * Maximum path compression length for cadet regex announcing for IPv4 address
56  * based regex.
57  */
58 #define REGEX_MAX_PATH_LEN_IPV4 4
59
60 /**
61  * Maximum path compression length for cadet regex announcing for IPv6 address
62  * based regex.
63  */
64 #define REGEX_MAX_PATH_LEN_IPV6 8
65
66 /**
67  * How frequently do we re-announce the regex for the exit?
68  */
69 #define REGEX_REFRESH_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
70
71 /**
72  * How frequently do we re-announce the DNS exit in the DHT?
73  */
74 #define DHT_PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
75
76 /**
77  * How long do we typically sign the DNS exit advertisement for?
78  */
79 #define DNS_ADVERTISEMENT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 3)
80
81
82 /**
83  * Generic logging shorthand
84  */
85 #define LOG(kind, ...)                          \
86   GNUNET_log_from (kind, "exit", __VA_ARGS__);
87
88
89 /**
90  * Information about an address.
91  */
92 struct SocketAddress
93 {
94   /**
95    * AF_INET or AF_INET6.
96    */
97   int af;
98
99   /**
100    * Remote address information.
101    */
102   union
103   {
104     /**
105      * Address, if af is AF_INET.
106      */
107     struct in_addr ipv4;
108
109     /**
110      * Address, if af is AF_INET6.
111      */
112     struct in6_addr ipv6;
113   } address;
114
115   /**
116    * IPPROTO_TCP or IPPROTO_UDP;
117    */
118   uint8_t proto;
119
120   /**
121    * Remote port, in host byte order!
122    */
123   uint16_t port;
124
125 };
126
127
128 /**
129  * This struct is saved into the services-hashmap to represent
130  * a service this peer is specifically offering an exit for
131  * (for a specific domain name).
132  */
133 struct LocalService
134 {
135
136   /**
137    * Remote address to use for the service.
138    */
139   struct SocketAddress address;
140
141   /**
142    * Descriptor for the service (CADET port).
143    */
144   struct GNUNET_HashCode descriptor;
145
146   /**
147    * DNS name of the service.
148    */
149   char *name;
150
151   /**
152    * Open port with CADET.
153    */
154   struct GNUNET_CADET_Port *port;
155
156   /**
157    * Port I am listening on within GNUnet for this service, in host
158    * byte order.  (as we may redirect ports).
159    */
160   uint16_t my_port;
161
162   /**
163    * #GNUNET_YES if this is a UDP service, otherwise TCP.
164    */
165   int16_t is_udp;
166
167 };
168
169
170 /**
171  * Information we use to track a connection (the classical 6-tuple of
172  * IP-version, protocol, source-IP, destination-IP, source-port and
173  * destinatin-port.
174  */
175 struct RedirectInformation
176 {
177
178   /**
179    * Address information for the other party (equivalent of the
180    * arguments one would give to "connect").
181    */
182   struct SocketAddress remote_address;
183
184   /**
185    * Address information we used locally (AF and proto must match
186    * "remote_address").  Equivalent of the arguments one would give to
187    * "bind".
188    */
189   struct SocketAddress local_address;
190
191   /*
192      Note 1: additional information might be added here in the
193      future to support protocols that require special handling,
194      such as ftp/tftp
195
196      Note 2: we might also sometimes not match on all components
197      of the tuple, to support protocols where things do not always
198      fully map.
199   */
200 };
201
202
203 /**
204  * Queue of messages to a channel.
205  */
206 struct ChannelMessageQueue
207 {
208   /**
209    * This is a doubly-linked list.
210    */
211   struct ChannelMessageQueue *next;
212
213   /**
214    * This is a doubly-linked list.
215    */
216   struct ChannelMessageQueue *prev;
217
218   /**
219    * Payload to send via the channel.
220    */
221   const void *payload;
222
223   /**
224    * Number of bytes in @e payload.
225    */
226   size_t len;
227 };
228
229
230 /**
231  * This struct is saved into #connections_map to allow finding the
232  * right channel given an IP packet from TUN.  It is also associated
233  * with the channel's closure so we can find it again for the next
234  * message from the channel.
235  */
236 struct ChannelState
237 {
238   /**
239    * Cadet channel that is used for this connection.
240    */
241   struct GNUNET_CADET_Channel *channel;
242
243   /**
244    * Who is the other end of this channel.
245    * FIXME is this needed? Only used for debugging messages
246    */
247   struct GNUNET_PeerIdentity peer;
248
249   /**
250    * Active channel transmission request (or NULL).
251    */
252   struct GNUNET_CADET_TransmitHandle *th;
253
254   /**
255    * #GNUNET_NO if this is a channel for TCP/UDP,
256    * #GNUNET_YES if this is a channel for DNS,
257    * #GNUNET_SYSERR if the channel is not yet initialized.
258    */
259   int is_dns;
260
261   union
262   {
263     struct
264     {
265
266       /**
267        * Heap node for this state in the connections_heap.
268        */
269       struct GNUNET_CONTAINER_HeapNode *heap_node;
270
271       /**
272        * Key this state has in the #connections_map.
273        */
274       struct GNUNET_HashCode state_key;
275
276       /**
277        * Associated service record, or NULL for no service.
278        */
279       struct LocalService *serv;
280
281       /**
282        * Head of DLL of messages for this channel.
283        */
284       struct ChannelMessageQueue *head;
285
286       /**
287        * Tail of DLL of messages for this channel.
288        */
289       struct ChannelMessageQueue *tail;
290
291       /**
292        * Primary redirection information for this connection.
293        */
294       struct RedirectInformation ri;
295     } tcp_udp;
296
297     struct
298     {
299
300       /**
301        * DNS reply ready for transmission.
302        */
303       char *reply;
304
305       /**
306        * Socket we are using to transmit this request (must match if we receive
307        * a response).
308        */
309       struct GNUNET_DNSSTUB_RequestSocket *rs;
310
311       /**
312        * Number of bytes in 'reply'.
313        */
314       size_t reply_length;
315
316       /**
317        * Original DNS request ID as used by the client.
318        */
319       uint16_t original_id;
320
321       /**
322        * DNS request ID that we used for forwarding.
323        */
324       uint16_t my_id;
325
326     } dns;
327
328   } specifics;
329
330 };
331
332
333 /**
334  * Return value from 'main'.
335  */
336 static int global_ret;
337
338 /**
339  * Handle to our regex announcement for IPv4.
340  */
341 static struct GNUNET_REGEX_Announcement *regex4;
342
343 /**
344  * Handle to our regex announcement for IPv4.
345  */
346 static struct GNUNET_REGEX_Announcement *regex6;
347
348 /**
349  * The handle to the configuration used throughout the process
350  */
351 static const struct GNUNET_CONFIGURATION_Handle *cfg;
352
353 /**
354  * The handle to the helper
355  */
356 static struct GNUNET_HELPER_Handle *helper_handle;
357
358 /**
359  * Arguments to the exit helper.
360  */
361 static char *exit_argv[8];
362
363 /**
364  * IPv6 address of our TUN interface.
365  */
366 static struct in6_addr exit_ipv6addr;
367
368 /**
369  * IPv6 prefix (0..127) from configuration file.
370  */
371 static unsigned long long ipv6prefix;
372
373 /**
374  * IPv4 address of our TUN interface.
375  */
376 static struct in_addr exit_ipv4addr;
377
378 /**
379  * IPv4 netmask of our TUN interface.
380  */
381 static struct in_addr exit_ipv4mask;
382
383 /**
384  * Statistics.
385  */
386 static struct GNUNET_STATISTICS_Handle *stats;
387
388 /**
389  * The handle to cadet
390  */
391 static struct GNUNET_CADET_Handle *cadet_handle;
392
393 /**
394  * This hashmaps contains the mapping from peer, service-descriptor,
395  * source-port and destination-port to a struct ChannelState
396  */
397 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
398
399 /**
400  * Heap so we can quickly find "old" connections.
401  */
402 static struct GNUNET_CONTAINER_Heap *connections_heap;
403
404 /**
405  * If there are at least this many connections, old ones will be removed
406  */
407 static unsigned long long max_connections;
408
409 /**
410  * This hashmaps saves interesting things about the configured services
411  */
412 static struct GNUNET_CONTAINER_MultiHashMap *services;
413
414 /**
415  * Array of all open DNS requests from channels.
416  */
417 static struct ChannelState *channels[UINT16_MAX + 1];
418
419 /**
420  * Handle to the DNS Stub resolver.
421  */
422 static struct GNUNET_DNSSTUB_Context *dnsstub;
423
424 /**
425  * Handle for ongoing DHT PUT operations to advertise exit service.
426  */
427 static struct GNUNET_DHT_PutHandle *dht_put;
428
429 /**
430  * Handle to the DHT.
431  */
432 static struct GNUNET_DHT_Handle *dht;
433
434 /**
435  * Task for doing DHT PUTs to advertise exit service.
436  */
437 static struct GNUNET_SCHEDULER_Task * dht_task;
438
439 /**
440  * Advertisement message we put into the DHT to advertise us
441  * as a DNS exit.
442  */
443 static struct GNUNET_DNS_Advertisement dns_advertisement;
444
445 /**
446  * Key we store the DNS advertismenet under.
447  */
448 static struct GNUNET_HashCode dht_put_key;
449
450 /**
451  * Private key for this peer.
452  */
453 static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key;
454
455 /**
456  * Are we an IPv4-exit?
457  */
458 static int ipv4_exit;
459
460 /**
461  * Are we an IPv6-exit?
462  */
463 static int ipv6_exit;
464
465 /**
466  * Do we support IPv4 at all on the TUN interface?
467  */
468 static int ipv4_enabled;
469
470 /**
471  * Do we support IPv6 at all on the TUN interface?
472  */
473 static int ipv6_enabled;
474
475
476 /**
477  * We got a reply from DNS for a request of a CADET channel.  Send it
478  * via the channel (after changing the request ID back).
479  *
480  * @param cls the `struct ChannelState`
481  * @param size number of bytes available in @a buf
482  * @param buf where to copy the reply
483  * @return number of bytes written to @a buf
484  */
485 static size_t
486 transmit_reply_to_cadet (void *cls,
487                         size_t size,
488                         void *buf)
489 {
490   struct ChannelState *ts = cls;
491   size_t off;
492   size_t ret;
493   char *cbuf = buf;
494   struct GNUNET_MessageHeader hdr;
495   struct GNUNET_TUN_DnsHeader dns;
496
497   GNUNET_assert (GNUNET_YES == ts->is_dns);
498   ts->th = NULL;
499   GNUNET_assert (ts->specifics.dns.reply != NULL);
500   if (size == 0)
501     return 0;
502   ret = sizeof (struct GNUNET_MessageHeader) + ts->specifics.dns.reply_length;
503   GNUNET_assert (ret <= size);
504   hdr.size = htons (ret);
505   hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET);
506   GNUNET_memcpy (&dns, ts->specifics.dns.reply, sizeof (dns));
507   dns.id = ts->specifics.dns.original_id;
508   off = 0;
509   GNUNET_memcpy (&cbuf[off], &hdr, sizeof (hdr));
510   off += sizeof (hdr);
511   GNUNET_memcpy (&cbuf[off], &dns, sizeof (dns));
512   off += sizeof (dns);
513   GNUNET_memcpy (&cbuf[off], &ts->specifics.dns.reply[sizeof (dns)], ts->specifics.dns.reply_length - sizeof (dns));
514   off += ts->specifics.dns.reply_length - sizeof (dns);
515   GNUNET_free (ts->specifics.dns.reply);
516   ts->specifics.dns.reply = NULL;
517   ts->specifics.dns.reply_length = 0;
518   GNUNET_assert (ret == off);
519   return ret;
520 }
521
522
523 /**
524  * Callback called from DNSSTUB resolver when a resolution
525  * succeeded.
526  *
527  * @param cls NULL
528  * @param rs the socket that received the response
529  * @param dns the response itself
530  * @param r number of bytes in dns
531  */
532 static void
533 process_dns_result (void *cls,
534                     struct GNUNET_DNSSTUB_RequestSocket *rs,
535                     const struct GNUNET_TUN_DnsHeader *dns,
536                     size_t r)
537 {
538   struct ChannelState *ts;
539
540   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
541               "Processing DNS result from stub resolver\n");
542   GNUNET_assert (NULL == cls);
543   /* Handle case that this is a reply to a request from a CADET DNS channel */
544   ts = channels[dns->id];
545   if ( (NULL == ts) ||
546        (ts->specifics.dns.rs != rs) )
547     return;
548   LOG (GNUNET_ERROR_TYPE_DEBUG,
549        "Got a response from the stub resolver for DNS request received via CADET!\n");
550   channels[dns->id] = NULL;
551   GNUNET_free_non_null (ts->specifics.dns.reply);
552   ts->specifics.dns.reply = GNUNET_malloc (r);
553   ts->specifics.dns.reply_length = r;
554   GNUNET_memcpy (ts->specifics.dns.reply, dns, r);
555   if (NULL != ts->th)
556     GNUNET_CADET_notify_transmit_ready_cancel (ts->th);
557   ts->th = GNUNET_CADET_notify_transmit_ready (ts->channel,
558                                               GNUNET_NO,
559                                               GNUNET_TIME_UNIT_FOREVER_REL,
560                                               sizeof (struct GNUNET_MessageHeader) + r,
561                                               &transmit_reply_to_cadet,
562                                               ts);
563 }
564
565
566 /**
567  * Process a request via cadet to perform a DNS query.
568  *
569  * @param cls closure, NULL
570  * @param channel connection to the other end
571  * @param channel_ctx pointer to our `struct ChannelState *`
572  * @param message the actual message
573  *
574  * @return #GNUNET_OK to keep the connection open,
575  *         #GNUNET_SYSERR to close it (signal serious error)
576  */
577 static int
578 receive_dns_request (void *cls GNUNET_UNUSED,
579                      struct GNUNET_CADET_Channel *channel,
580                      void **channel_ctx,
581                      const struct GNUNET_MessageHeader *message)
582 {
583   struct ChannelState *ts = *channel_ctx;
584   const struct GNUNET_TUN_DnsHeader *dns;
585   size_t mlen = ntohs (message->size);
586   size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader);
587   char buf[dlen] GNUNET_ALIGN;
588   struct GNUNET_TUN_DnsHeader *dout;
589
590   if (NULL == dnsstub)
591   {
592     GNUNET_break_op (0);
593     return GNUNET_SYSERR;
594   }
595   if (GNUNET_NO == ts->is_dns)
596   {
597     GNUNET_break_op (0);
598     return GNUNET_SYSERR;
599   }
600   if (GNUNET_SYSERR == ts->is_dns)
601   {
602     /* channel is DNS from now on */
603     ts->is_dns = GNUNET_YES;
604   }
605   if (dlen < sizeof (struct GNUNET_TUN_DnsHeader))
606   {
607     GNUNET_break_op (0);
608     return GNUNET_SYSERR;
609   }
610   dns = (const struct GNUNET_TUN_DnsHeader *) &message[1];
611   ts->specifics.dns.original_id = dns->id;
612   if (channels[ts->specifics.dns.my_id] == ts)
613     channels[ts->specifics.dns.my_id] = NULL;
614   ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
615                                                    UINT16_MAX + 1);
616   channels[ts->specifics.dns.my_id] = ts;
617   GNUNET_memcpy (buf, dns, dlen);
618   dout = (struct GNUNET_TUN_DnsHeader *) buf;
619   dout->id = ts->specifics.dns.my_id;
620   ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub,
621                                                   buf, dlen,
622                                                   &process_dns_result,
623                                                   NULL);
624   if (NULL == ts->specifics.dns.rs)
625     return GNUNET_SYSERR;
626   GNUNET_CADET_receive_done (channel);
627   return GNUNET_OK;
628 }
629
630
631 /**
632  * Given IP information about a connection, calculate the respective
633  * hash we would use for the #connections_map.
634  *
635  * @param hash resulting hash
636  * @param ri information about the connection
637  */
638 static void
639 hash_redirect_info (struct GNUNET_HashCode *hash,
640                     const struct RedirectInformation *ri)
641 {
642   char *off;
643
644   memset (hash,
645           0,
646           sizeof (struct GNUNET_HashCode));
647   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash,
648      so we put the IP address in there (and hope for few collisions) */
649   off = (char*) hash;
650   switch (ri->remote_address.af)
651   {
652   case AF_INET:
653     GNUNET_memcpy (off,
654                    &ri->remote_address.address.ipv4,
655                    sizeof (struct in_addr));
656     off += sizeof (struct in_addr);
657     break;
658   case AF_INET6:
659     GNUNET_memcpy (off,
660                    &ri->remote_address.address.ipv6,
661                    sizeof (struct in6_addr));
662     off += sizeof (struct in_addr);
663     break;
664   default:
665     GNUNET_assert (0);
666   }
667   GNUNET_memcpy (off,
668                  &ri->remote_address.port,
669                  sizeof (uint16_t));
670   off += sizeof (uint16_t);
671   switch (ri->local_address.af)
672   {
673   case AF_INET:
674     GNUNET_memcpy (off,
675                    &ri->local_address.address.ipv4,
676                    sizeof (struct in_addr));
677     off += sizeof (struct in_addr);
678     break;
679   case AF_INET6:
680     GNUNET_memcpy (off,
681                    &ri->local_address.address.ipv6,
682                    sizeof (struct in6_addr));
683     off += sizeof (struct in_addr);
684     break;
685   default:
686     GNUNET_assert (0);
687   }
688   GNUNET_memcpy (off,
689                  &ri->local_address.port,
690                  sizeof (uint16_t));
691   off += sizeof (uint16_t);
692   GNUNET_memcpy (off,
693                  &ri->remote_address.proto,
694                  sizeof (uint8_t));
695   /* off += sizeof (uint8_t); */
696 }
697
698
699 /**
700  * Get our connection tracking state.  Warns if it does not exists,
701  * refreshes the timestamp if it does exist.
702  *
703  * @param af address family
704  * @param protocol IPPROTO_UDP or IPPROTO_TCP
705  * @param destination_ip target IP
706  * @param destination_port target port
707  * @param local_ip local IP
708  * @param local_port local port
709  * @param state_key set to hash's state if non-NULL
710  * @return NULL if we have no tracking information for this tuple
711  */
712 static struct ChannelState *
713 get_redirect_state (int af,
714                     int protocol,
715                     const void *destination_ip,
716                     uint16_t destination_port,
717                     const void *local_ip,
718                     uint16_t local_port,
719                     struct GNUNET_HashCode *state_key)
720 {
721   struct RedirectInformation ri;
722   struct GNUNET_HashCode key;
723   struct ChannelState *state;
724
725   if ( ( (af == AF_INET) && (protocol == IPPROTO_ICMP) ) ||
726        ( (af == AF_INET6) && (protocol == IPPROTO_ICMPV6) ) )
727   {
728     /* ignore ports */
729     destination_port = 0;
730     local_port = 0;
731   }
732   ri.remote_address.af = af;
733   if (af == AF_INET)
734     ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
735   else
736     ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
737   ri.remote_address.port = destination_port;
738   ri.remote_address.proto = protocol;
739   ri.local_address.af = af;
740   if (af == AF_INET)
741     ri.local_address.address.ipv4 = *((struct in_addr*) local_ip);
742   else
743     ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip);
744   ri.local_address.port = local_port;
745   ri.local_address.proto = protocol;
746   hash_redirect_info (&key,
747                       &ri);
748   if (NULL != state_key)
749     *state_key = key;
750   state = GNUNET_CONTAINER_multihashmap_get (connections_map,
751                                              &key);
752   if (NULL == state)
753     return NULL;
754   /* Mark this connection as freshly used */
755   if (NULL == state_key)
756     GNUNET_CONTAINER_heap_update_cost (connections_heap,
757                                        state->specifics.tcp_udp.heap_node,
758                                        GNUNET_TIME_absolute_get ().abs_value_us);
759   return state;
760 }
761
762
763 /**
764  * Free memory associated with a service record.
765  *
766  * @param cls unused
767  * @param key service descriptor
768  * @param value service record to free
769  * @return #GNUNET_OK
770  */
771 static int
772 free_service_record (void *cls,
773                      const struct GNUNET_HashCode *key,
774                      void *value)
775 {
776   struct LocalService *service = value;
777
778   GNUNET_assert (GNUNET_YES ==
779                  GNUNET_CONTAINER_multihashmap_remove (services,
780                                                        key,
781                                                        service));
782   GNUNET_CADET_close_port (service->port);
783   GNUNET_free_non_null (service->name);
784   GNUNET_free (service);
785   return GNUNET_OK;
786 }
787
788
789 /**
790  * Callback from CADET for new channels.
791  *
792  * @param cls closure
793  * @param channel new handle to the channel
794  * @param initiator peer that started the channel
795  * @param port destination port
796  * @param options channel options flags
797  * @return initial channel context for the channel
798  */
799 static void *
800 new_service_channel (void *cls,
801                      struct GNUNET_CADET_Channel *channel,
802                      const struct GNUNET_PeerIdentity *initiator,
803                      const struct GNUNET_HashCode *port,
804                      enum GNUNET_CADET_ChannelOption options)
805 {
806   struct LocalService *ls = cls;
807   struct ChannelState *s = GNUNET_new (struct ChannelState);
808
809   s->peer = *initiator;
810   GNUNET_STATISTICS_update (stats,
811                             gettext_noop ("# Inbound CADET channels created"),
812                             1,
813                             GNUNET_NO);
814   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815               "Received inbound channel from `%s'\n",
816               GNUNET_i2s (initiator));
817   s->channel = channel;
818   s->specifics.tcp_udp.serv = ls;
819   s->specifics.tcp_udp.ri.remote_address = ls->address;
820   return s;
821 }
822
823
824 /**
825  * Given a service descriptor and a destination port, find the
826  * respective service entry.
827  *
828  * @param proto IPPROTO_TCP or IPPROTO_UDP
829  * @param name name of the service
830  * @param destination_port destination port
831  * @param service service information record to store (service->name will be set).
832  */
833 static void
834 store_service (int proto,
835                const char *name,
836                uint16_t destination_port,
837                struct LocalService *service)
838 {
839   char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)];
840
841   GNUNET_TUN_service_name_to_hash (name,
842                                    &service->descriptor);
843   service->name = GNUNET_strdup (name);
844   GNUNET_memcpy (&key[0],
845                  &destination_port,
846                  sizeof (uint16_t));
847   GNUNET_memcpy (&key[sizeof(uint16_t)],
848                  &service->descriptor,
849                  sizeof (struct GNUNET_HashCode));
850   service->port = GNUNET_CADET_open_port (cadet_handle,
851                                           &service->descriptor,
852                                           &new_service_channel,
853                                           service);
854   service->is_udp = (IPPROTO_UDP == proto);
855   if (GNUNET_OK !=
856       GNUNET_CONTAINER_multihashmap_put (services,
857                                          (struct GNUNET_HashCode *) key,
858                                          service,
859                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
860   {
861     free_service_record (NULL,
862                          (struct GNUNET_HashCode *) key,
863                          service);
864     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
865                 _("Got duplicate service records for `%s:%u'\n"),
866                 name,
867                 (unsigned int) destination_port);
868   }
869 }
870
871
872 /**
873  * CADET is ready to receive a message for the channel.  Transmit it.
874  *
875  * @param cls the `struct ChannelState`.
876  * @param size number of bytes available in @a buf
877  * @param buf where to copy the message
878  * @return number of bytes copied to @a buf
879  */
880 static size_t
881 send_to_peer_notify_callback (void *cls,
882                               size_t size,
883                               void *buf)
884 {
885   struct ChannelState *s = cls;
886   struct GNUNET_CADET_Channel *channel = s->channel;
887   struct ChannelMessageQueue *tnq;
888
889   s->th = NULL;
890   tnq = s->specifics.tcp_udp.head;
891   if (NULL == tnq)
892     return 0;
893   if (0 == size)
894   {
895     s->th = GNUNET_CADET_notify_transmit_ready (channel,
896                                                GNUNET_NO /* corking */,
897                                                GNUNET_TIME_UNIT_FOREVER_REL,
898                                                tnq->len,
899                                                &send_to_peer_notify_callback,
900                                                s);
901     return 0;
902   }
903   GNUNET_assert (size >= tnq->len);
904   GNUNET_memcpy (buf, tnq->payload, tnq->len);
905   size = tnq->len;
906   GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
907                                s->specifics.tcp_udp.tail,
908                                tnq);
909   GNUNET_free (tnq);
910   if (NULL != (tnq = s->specifics.tcp_udp.head))
911     s->th = GNUNET_CADET_notify_transmit_ready (channel,
912                                                GNUNET_NO /* corking */,
913                                                GNUNET_TIME_UNIT_FOREVER_REL,
914                                                tnq->len,
915                                                &send_to_peer_notify_callback,
916                                                s);
917   GNUNET_STATISTICS_update (stats,
918                             gettext_noop ("# Bytes transmitted via cadet channels"),
919                             size, GNUNET_NO);
920   return size;
921 }
922
923
924 /**
925  * Send the given packet via the cadet channel.
926  *
927  * @param s channel destination
928  * @param tnq message to queue
929  */
930 static void
931 send_packet_to_cadet_channel (struct ChannelState *s,
932                               struct ChannelMessageQueue *tnq)
933 {
934   struct GNUNET_CADET_Channel *cadet_channel;
935
936   cadet_channel = s->channel;
937   GNUNET_assert (NULL != s);
938   GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head,
939                                     s->specifics.tcp_udp.tail,
940                                     tnq);
941   if (NULL == s->th)
942     s->th = GNUNET_CADET_notify_transmit_ready (cadet_channel,
943                                                 GNUNET_NO /* cork */,
944                                                 GNUNET_TIME_UNIT_FOREVER_REL,
945                                                 tnq->len,
946                                                 &send_to_peer_notify_callback,
947                                                 s);
948 }
949
950
951 /**
952  * @brief Handles an ICMP packet received from the helper.
953  *
954  * @param icmp A pointer to the Packet
955  * @param pktlen number of bytes in @a icmp
956  * @param af address family (AFINET or AF_INET6)
957  * @param destination_ip destination IP-address of the IP packet (should
958  *                       be our local address)
959  * @param source_ip original source IP-address of the IP packet (should
960  *                       be the original destination address)
961  */
962 static void
963 icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp,
964                   size_t pktlen,
965                   int af,
966                   const void *destination_ip,
967                   const void *source_ip)
968 {
969   struct ChannelState *state;
970   struct ChannelMessageQueue *tnq;
971   struct GNUNET_EXIT_IcmpToVPNMessage *i2v;
972   const struct GNUNET_TUN_IPv4Header *ipv4;
973   const struct GNUNET_TUN_IPv6Header *ipv6;
974   const struct GNUNET_TUN_UdpHeader *udp;
975   size_t mlen;
976   uint16_t source_port;
977   uint16_t destination_port;
978   uint8_t protocol;
979
980   {
981     char sbuf[INET6_ADDRSTRLEN];
982     char dbuf[INET6_ADDRSTRLEN];
983     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
984                 "Received ICMP packet going from %s to %s\n",
985                 inet_ntop (af,
986                            source_ip,
987                            sbuf, sizeof (sbuf)),
988                 inet_ntop (af,
989                            destination_ip,
990                            dbuf, sizeof (dbuf)));
991   }
992   if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader))
993   {
994     /* blame kernel */
995     GNUNET_break (0);
996     return;
997   }
998
999   /* Find out if this is an ICMP packet in response to an existing
1000      TCP/UDP packet and if so, figure out ports / protocol of the
1001      existing session from the IP data in the ICMP payload */
1002   source_port = 0;
1003   destination_port = 0;
1004   switch (af)
1005   {
1006   case AF_INET:
1007     protocol = IPPROTO_ICMP;
1008     switch (icmp->type)
1009       {
1010       case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
1011       case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
1012         break;
1013       case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
1014       case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
1015       case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
1016         if (pktlen <
1017             sizeof (struct GNUNET_TUN_IcmpHeader) +
1018             sizeof (struct GNUNET_TUN_IPv4Header) + 8)
1019         {
1020           /* blame kernel */
1021           GNUNET_break (0);
1022           return;
1023         }
1024         ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1];
1025         protocol = ipv4->protocol;
1026         /* could be TCP or UDP, but both have the ports in the right
1027            place, so that doesn't matter here */
1028         udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1];
1029         /* swap ports, as they are from the original message */
1030         destination_port = ntohs (udp->source_port);
1031         source_port = ntohs (udp->destination_port);
1032         /* throw away ICMP payload, won't be useful for the other side anyway */
1033         pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
1034         break;
1035       default:
1036         GNUNET_STATISTICS_update (stats,
1037                                   gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
1038                                   1, GNUNET_NO);
1039         return;
1040       }
1041     break;
1042   case AF_INET6:
1043     protocol = IPPROTO_ICMPV6;
1044     switch (icmp->type)
1045       {
1046       case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
1047       case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
1048       case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
1049       case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
1050         if (pktlen <
1051             sizeof (struct GNUNET_TUN_IcmpHeader) +
1052             sizeof (struct GNUNET_TUN_IPv6Header) + 8)
1053         {
1054           /* blame kernel */
1055           GNUNET_break (0);
1056           return;
1057         }
1058         ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1];
1059         protocol = ipv6->next_header;
1060         /* could be TCP or UDP, but both have the ports in the right
1061            place, so that doesn't matter here */
1062         udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1];
1063         /* swap ports, as they are from the original message */
1064         destination_port = ntohs (udp->source_port);
1065         source_port = ntohs (udp->destination_port);
1066         /* throw away ICMP payload, won't be useful for the other side anyway */
1067         pktlen = sizeof (struct GNUNET_TUN_IcmpHeader);
1068         break;
1069       case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
1070       case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
1071         break;
1072       default:
1073         GNUNET_STATISTICS_update (stats,
1074                                   gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
1075                                   1, GNUNET_NO);
1076         return;
1077       }
1078     break;
1079   default:
1080     GNUNET_assert (0);
1081   }
1082   switch (protocol)
1083   {
1084   case IPPROTO_ICMP:
1085     state = get_redirect_state (af,
1086                                 IPPROTO_ICMP,
1087                                 source_ip,
1088                                 0,
1089                                 destination_ip,
1090                                 0,
1091                                 NULL);
1092     break;
1093   case IPPROTO_ICMPV6:
1094     state = get_redirect_state (af,
1095                                 IPPROTO_ICMPV6,
1096                                 source_ip,
1097                                 0,
1098                                 destination_ip,
1099                                 0,
1100                                 NULL);
1101     break;
1102   case IPPROTO_UDP:
1103     state = get_redirect_state (af,
1104                                 IPPROTO_UDP,
1105                                 source_ip,
1106                                 source_port,
1107                                 destination_ip,
1108                                 destination_port,
1109                                 NULL);
1110     break;
1111   case IPPROTO_TCP:
1112     state = get_redirect_state (af,
1113                                 IPPROTO_TCP,
1114                                 source_ip,
1115                                 source_port,
1116                                 destination_ip,
1117                                 destination_port,
1118                                 NULL);
1119     break;
1120   default:
1121     GNUNET_STATISTICS_update (stats,
1122                               gettext_noop ("# ICMP packets dropped (not allowed)"),
1123                               1,
1124                               GNUNET_NO);
1125     return;
1126   }
1127   if (NULL == state)
1128   {
1129     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1130                 _("ICMP Packet dropped, have no matching connection information\n"));
1131     return;
1132   }
1133   mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader);
1134   tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1135   tnq->payload = &tnq[1];
1136   tnq->len = mlen;
1137   i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1];
1138   i2v->header.size = htons ((uint16_t) mlen);
1139   i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN);
1140   i2v->af = htonl (af);
1141   GNUNET_memcpy (&i2v->icmp_header,
1142           icmp,
1143           pktlen);
1144   send_packet_to_cadet_channel (state, tnq);
1145 }
1146
1147
1148 /**
1149  * @brief Handles an UDP packet received from the helper.
1150  *
1151  * @param udp A pointer to the Packet
1152  * @param pktlen number of bytes in 'udp'
1153  * @param af address family (AFINET or AF_INET6)
1154  * @param destination_ip destination IP-address of the IP packet (should
1155  *                       be our local address)
1156  * @param source_ip original source IP-address of the IP packet (should
1157  *                       be the original destination address)
1158  */
1159 static void
1160 udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp,
1161                  size_t pktlen,
1162                  int af,
1163                  const void *destination_ip,
1164                  const void *source_ip)
1165 {
1166   struct ChannelState *state;
1167   struct ChannelMessageQueue *tnq;
1168   struct GNUNET_EXIT_UdpReplyMessage *urm;
1169   size_t mlen;
1170
1171   {
1172     char sbuf[INET6_ADDRSTRLEN];
1173     char dbuf[INET6_ADDRSTRLEN];
1174     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1175                 "Received UDP packet going from %s:%u to %s:%u\n",
1176                 inet_ntop (af,
1177                            source_ip,
1178                            sbuf, sizeof (sbuf)),
1179                 (unsigned int) ntohs (udp->source_port),
1180                 inet_ntop (af,
1181                            destination_ip,
1182                            dbuf, sizeof (dbuf)),
1183                 (unsigned int) ntohs (udp->destination_port));
1184   }
1185   if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader))
1186   {
1187     /* blame kernel */
1188     GNUNET_break (0);
1189     return;
1190   }
1191   if (pktlen != ntohs (udp->len))
1192   {
1193     /* blame kernel */
1194     GNUNET_break (0);
1195     return;
1196   }
1197   state = get_redirect_state (af,
1198                               IPPROTO_UDP,
1199                               source_ip,
1200                               ntohs (udp->source_port),
1201                               destination_ip,
1202                               ntohs (udp->destination_port),
1203                               NULL);
1204   if (NULL == state)
1205   {
1206     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1207                 _("UDP Packet dropped, have no matching connection information\n"));
1208     return;
1209   }
1210   mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader);
1211   tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1212   tnq->payload = &tnq[1];
1213   tnq->len = mlen;
1214   urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1];
1215   urm->header.size = htons ((uint16_t) mlen);
1216   urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY);
1217   urm->source_port = htons (0);
1218   urm->destination_port = htons (0);
1219   GNUNET_memcpy (&urm[1],
1220           &udp[1],
1221           pktlen - sizeof (struct GNUNET_TUN_UdpHeader));
1222   send_packet_to_cadet_channel (state, tnq);
1223 }
1224
1225
1226 /**
1227  * @brief Handles a TCP packet received from the helper.
1228  *
1229  * @param tcp A pointer to the Packet
1230  * @param pktlen the length of the packet, including its TCP header
1231  * @param af address family (AFINET or AF_INET6)
1232  * @param destination_ip destination IP-address of the IP packet (should
1233  *                       be our local address)
1234  * @param source_ip original source IP-address of the IP packet (should
1235  *                       be the original destination address)
1236  */
1237 static void
1238 tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp,
1239                  size_t pktlen,
1240                  int af,
1241                  const void *destination_ip,
1242                  const void *source_ip)
1243 {
1244   struct ChannelState *state;
1245   char buf[pktlen] GNUNET_ALIGN;
1246   struct GNUNET_TUN_TcpHeader *mtcp;
1247   struct GNUNET_EXIT_TcpDataMessage *tdm;
1248   struct ChannelMessageQueue *tnq;
1249   size_t mlen;
1250
1251   {
1252     char sbuf[INET6_ADDRSTRLEN];
1253     char dbuf[INET6_ADDRSTRLEN];
1254     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1255                 "Received TCP packet with %u bytes going from %s:%u to %s:%u\n",
1256                 (unsigned int) (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)),
1257                 inet_ntop (af,
1258                            source_ip,
1259                            sbuf, sizeof (sbuf)),
1260                 (unsigned int) ntohs (tcp->source_port),
1261                 inet_ntop (af,
1262                            destination_ip,
1263                            dbuf, sizeof (dbuf)),
1264                 (unsigned int) ntohs (tcp->destination_port));
1265   }
1266   if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader))
1267   {
1268     /* blame kernel */
1269     GNUNET_break (0);
1270     return;
1271   }
1272   state = get_redirect_state (af,
1273                               IPPROTO_TCP,
1274                               source_ip,
1275                               ntohs (tcp->source_port),
1276                               destination_ip,
1277                               ntohs (tcp->destination_port),
1278                               NULL);
1279   if (NULL == state)
1280   {
1281     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1282                 _("TCP Packet dropped, have no matching connection information\n"));
1283
1284     return;
1285   }
1286   /* mug port numbers and crc to avoid information leakage;
1287      sender will need to lookup the correct values anyway */
1288   GNUNET_memcpy (buf, tcp, pktlen);
1289   mtcp = (struct GNUNET_TUN_TcpHeader *) buf;
1290   mtcp->source_port = 0;
1291   mtcp->destination_port = 0;
1292   mtcp->crc = 0;
1293
1294   mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader));
1295   if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1296   {
1297     GNUNET_break (0);
1298     return;
1299   }
1300
1301   tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen);
1302   tnq->payload = &tnq[1];
1303   tnq->len = mlen;
1304   tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1];
1305   tdm->header.size = htons ((uint16_t) mlen);
1306   tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN);
1307   tdm->reserved = htonl (0);
1308   GNUNET_memcpy (&tdm->tcp_header,
1309           buf,
1310           pktlen);
1311   send_packet_to_cadet_channel (state, tnq);
1312 }
1313
1314
1315 /**
1316  * Receive packets from the helper-process
1317  *
1318  * @param cls unused
1319  * @param client unsued
1320  * @param message message received from helper
1321  */
1322 static int
1323 message_token (void *cls GNUNET_UNUSED,
1324                void *client GNUNET_UNUSED,
1325                const struct GNUNET_MessageHeader *message)
1326 {
1327   const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun;
1328   size_t size;
1329
1330   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1331               "Got %u-byte message of type %u from gnunet-helper-exit\n",
1332               ntohs (message->size),
1333               ntohs (message->type));
1334   GNUNET_STATISTICS_update (stats,
1335                             gettext_noop ("# Packets received from TUN"),
1336                             1, GNUNET_NO);
1337   if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
1338   {
1339     GNUNET_break (0);
1340     return GNUNET_OK;
1341   }
1342   size = ntohs (message->size);
1343   if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader))
1344   {
1345     GNUNET_break (0);
1346     return GNUNET_OK;
1347   }
1348   GNUNET_STATISTICS_update (stats,
1349                             gettext_noop ("# Bytes received from TUN"),
1350                             size, GNUNET_NO);
1351   pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1];
1352   size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader);
1353   switch (ntohs (pkt_tun->proto))
1354   {
1355   case ETH_P_IPV4:
1356     {
1357       const struct GNUNET_TUN_IPv4Header *pkt4;
1358
1359       if (size < sizeof (struct GNUNET_TUN_IPv4Header))
1360       {
1361         /* Kernel to blame? */
1362         GNUNET_break (0);
1363         return GNUNET_OK;
1364       }
1365       pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1];
1366       if (size != ntohs (pkt4->total_length))
1367       {
1368         /* Kernel to blame? */
1369         GNUNET_break (0);
1370         return GNUNET_OK;
1371       }
1372       if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header))
1373       {
1374         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1375                     _("IPv4 packet options received.  Ignored.\n"));
1376         return GNUNET_OK;
1377       }
1378
1379       size -= sizeof (struct GNUNET_TUN_IPv4Header);
1380       switch (pkt4->protocol)
1381       {
1382       case IPPROTO_UDP:
1383         udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size,
1384                          AF_INET,
1385                          &pkt4->destination_address,
1386                          &pkt4->source_address);
1387         break;
1388       case IPPROTO_TCP:
1389         tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size,
1390                          AF_INET,
1391                          &pkt4->destination_address,
1392                          &pkt4->source_address);
1393         break;
1394       case IPPROTO_ICMP:
1395         icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size,
1396                           AF_INET,
1397                           &pkt4->destination_address,
1398                           &pkt4->source_address);
1399         break;
1400       default:
1401         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1402                     _("IPv4 packet with unsupported next header %u received.  Ignored.\n"),
1403                     (int) pkt4->protocol);
1404         return GNUNET_OK;
1405       }
1406     }
1407     break;
1408   case ETH_P_IPV6:
1409     {
1410       const struct GNUNET_TUN_IPv6Header *pkt6;
1411
1412       if (size < sizeof (struct GNUNET_TUN_IPv6Header))
1413       {
1414         /* Kernel to blame? */
1415         GNUNET_break (0);
1416         return GNUNET_OK;
1417       }
1418       pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1];
1419       if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header))
1420       {
1421         /* Kernel to blame? */
1422         GNUNET_break (0);
1423         return GNUNET_OK;
1424       }
1425       size -= sizeof (struct GNUNET_TUN_IPv6Header);
1426       switch (pkt6->next_header)
1427       {
1428       case IPPROTO_UDP:
1429         udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size,
1430                          AF_INET6,
1431                          &pkt6->destination_address,
1432                          &pkt6->source_address);
1433         break;
1434       case IPPROTO_TCP:
1435         tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size,
1436                          AF_INET6,
1437                          &pkt6->destination_address,
1438                          &pkt6->source_address);
1439         break;
1440       case IPPROTO_ICMPV6:
1441         icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size,
1442                           AF_INET6,
1443                           &pkt6->destination_address,
1444                           &pkt6->source_address);
1445         break;
1446       default:
1447         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1448                     _("IPv6 packet with unsupported next header %d received.  Ignored.\n"),
1449                     pkt6->next_header);
1450         return GNUNET_OK;
1451       }
1452     }
1453     break;
1454   default:
1455     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1456                 _("Packet from unknown protocol %u received.  Ignored.\n"),
1457                 ntohs (pkt_tun->proto));
1458     break;
1459   }
1460   return GNUNET_OK;
1461 }
1462
1463
1464 /**
1465  * We need to create a (unique) fresh local address (IP+port).
1466  * Fill one in.
1467  *
1468  * @param af desired address family
1469  * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP)
1470  * @param local_address address to initialize
1471  */
1472 static void
1473 setup_fresh_address (int af,
1474                      uint8_t proto,
1475                      struct SocketAddress *local_address)
1476 {
1477   local_address->af = af;
1478   local_address->proto = (uint8_t) proto;
1479   /* default "local" port range is often 32768--61000,
1480      so we pick a random value in that range */
1481   if ( ( (af == AF_INET) && (proto == IPPROTO_ICMP) ) ||
1482        ( (af == AF_INET6) && (proto == IPPROTO_ICMPV6) ) )
1483     local_address->port = 0;
1484   else
1485     local_address->port
1486       = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1487                                                      28232);
1488   switch (af)
1489   {
1490   case AF_INET:
1491     {
1492       struct in_addr addr;
1493       struct in_addr mask;
1494       struct in_addr rnd;
1495
1496       addr = exit_ipv4addr;
1497       mask = exit_ipv4mask;
1498       if (0 == ~mask.s_addr)
1499       {
1500         /* only one valid IP anyway */
1501         local_address->address.ipv4 = addr;
1502         return;
1503       }
1504       /* Given 192.168.0.1/255.255.0.0, we want a mask
1505          of '192.168.255.255', thus:  */
1506       mask.s_addr = addr.s_addr | ~mask.s_addr;
1507       /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */
1508       do
1509         {
1510           rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1511                                                  UINT32_MAX);
1512           local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr;
1513         }
1514       while ( (local_address->address.ipv4.s_addr == addr.s_addr) ||
1515               (local_address->address.ipv4.s_addr == mask.s_addr) );
1516     }
1517     break;
1518   case AF_INET6:
1519     {
1520       struct in6_addr addr;
1521       struct in6_addr mask;
1522       struct in6_addr rnd;
1523       int i;
1524
1525       addr = exit_ipv6addr;
1526       GNUNET_assert (ipv6prefix < 128);
1527       if (ipv6prefix == 127)
1528       {
1529         /* only one valid IP anyway */
1530         local_address->address.ipv6 = addr;
1531         return;
1532       }
1533       /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF,
1534          thus: */
1535       mask = addr;
1536       for (i=127;i>=ipv6prefix;i--)
1537         mask.s6_addr[i / 8] |= (1 << (i % 8));
1538
1539       /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */
1540       do
1541         {
1542           for (i=0;i<16;i++)
1543           {
1544             rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1545                                                                        256);
1546             local_address->address.ipv6.s6_addr[i]
1547               = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i];
1548           }
1549         }
1550       while ( (0 == memcmp (&local_address->address.ipv6,
1551                             &addr,
1552                             sizeof (struct in6_addr))) ||
1553               (0 == memcmp (&local_address->address.ipv6,
1554                             &mask,
1555                             sizeof (struct in6_addr))) );
1556     }
1557     break;
1558   default:
1559     GNUNET_assert (0);
1560   }
1561 }
1562
1563
1564 /**
1565  * We are starting a fresh connection (TCP or UDP) and need
1566  * to pick a source port and IP address (within the correct
1567  * range and address family) to associate replies with the
1568  * connection / correct cadet channel.  This function generates
1569  * a "fresh" source IP and source port number for a connection
1570  * After picking a good source address, this function sets up
1571  * the state in the 'connections_map' and 'connections_heap'
1572  * to allow finding the state when needed later.  The function
1573  * also makes sure that we remain within memory limits by
1574  * cleaning up 'old' states.
1575  *
1576  * @param state skeleton state to setup a record for; should
1577  *              'state->specifics.tcp_udp.ri.remote_address' filled in so that
1578  *              this code can determine which AF/protocol is
1579  *              going to be used (the 'channel' should also
1580  *              already be set); after calling this function,
1581  *              heap_node and the local_address will be
1582  *              also initialized (heap_node != NULL can be
1583  *              used to test if a state has been fully setup).
1584  */
1585 static void
1586 setup_state_record (struct ChannelState *state)
1587 {
1588   struct GNUNET_HashCode key;
1589   struct ChannelState *s;
1590
1591   /* generate fresh, unique address */
1592   do
1593   {
1594     if (NULL == state->specifics.tcp_udp.serv)
1595       setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af,
1596                            state->specifics.tcp_udp.ri.remote_address.proto,
1597                            &state->specifics.tcp_udp.ri.local_address);
1598     else
1599       setup_fresh_address (state->specifics.tcp_udp.serv->address.af,
1600                            state->specifics.tcp_udp.serv->address.proto,
1601                            &state->specifics.tcp_udp.ri.local_address);
1602   } while (NULL !=
1603            get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af,
1604                                state->specifics.tcp_udp.ri.remote_address.proto,
1605                                &state->specifics.tcp_udp.ri.remote_address.address,
1606                                state->specifics.tcp_udp.ri.remote_address.port,
1607                                &state->specifics.tcp_udp.ri.local_address.address,
1608                                state->specifics.tcp_udp.ri.local_address.port,
1609                                &key));
1610   {
1611     char buf[INET6_ADDRSTRLEN];
1612     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1613                 "Picked local address %s:%u for new connection\n",
1614                 inet_ntop (state->specifics.tcp_udp.ri.local_address.af,
1615                            &state->specifics.tcp_udp.ri.local_address.address,
1616                            buf,
1617                            sizeof (buf)),
1618                 (unsigned int) state->specifics.tcp_udp.ri.local_address.port);
1619   }
1620   state->specifics.tcp_udp.state_key = key;
1621   GNUNET_assert (GNUNET_OK ==
1622                  GNUNET_CONTAINER_multihashmap_put (connections_map,
1623                                                     &key, state,
1624                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1625   state->specifics.tcp_udp.heap_node
1626     = GNUNET_CONTAINER_heap_insert (connections_heap,
1627                                     state,
1628                                     GNUNET_TIME_absolute_get ().abs_value_us);
1629   while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1630   {
1631     s = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1632     GNUNET_assert (state != s);
1633     s->specifics.tcp_udp.heap_node = NULL;
1634     GNUNET_CADET_channel_destroy (s->channel);
1635     GNUNET_assert (GNUNET_OK ==
1636                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
1637                                                          &s->specifics.tcp_udp.state_key,
1638                                                          s));
1639     GNUNET_free (s);
1640   }
1641 }
1642
1643
1644 /**
1645  * Prepare an IPv4 packet for transmission via the TUN interface.
1646  * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1647  * For UDP, the UDP header will be fully created, whereas for TCP
1648  * only the ports and checksum will be filled in.  So for TCP,
1649  * a skeleton TCP header must be part of the provided payload.
1650  *
1651  * @param payload payload of the packet (starting with UDP payload or
1652  *                TCP header, depending on protocol)
1653  * @param payload_length number of bytes in @a payload
1654  * @param protocol IPPROTO_UDP or IPPROTO_TCP
1655  * @param tcp_header skeleton of the TCP header, NULL for UDP
1656  * @param src_address source address to use (IP and port)
1657  * @param dst_address destination address to use (IP and port)
1658  * @param pkt4 where to write the assembled packet; must
1659  *        contain enough space for the IP header, UDP/TCP header
1660  *        AND the payload
1661  */
1662 static void
1663 prepare_ipv4_packet (const void *payload,
1664                      size_t payload_length,
1665                      int protocol,
1666                      const struct GNUNET_TUN_TcpHeader *tcp_header,
1667                      const struct SocketAddress *src_address,
1668                      const struct SocketAddress *dst_address,
1669                      struct GNUNET_TUN_IPv4Header *pkt4)
1670 {
1671   size_t len;
1672
1673   len = payload_length;
1674   switch (protocol)
1675   {
1676   case IPPROTO_UDP:
1677     len += sizeof (struct GNUNET_TUN_UdpHeader);
1678     break;
1679   case IPPROTO_TCP:
1680     len += sizeof (struct GNUNET_TUN_TcpHeader);
1681     GNUNET_assert (NULL != tcp_header);
1682     break;
1683   default:
1684     GNUNET_break (0);
1685     return;
1686   }
1687   if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX)
1688   {
1689     GNUNET_break (0);
1690     return;
1691   }
1692
1693   GNUNET_TUN_initialize_ipv4_header (pkt4,
1694                                      protocol,
1695                                      len,
1696                                      &src_address->address.ipv4,
1697                                      &dst_address->address.ipv4);
1698   switch (protocol)
1699   {
1700   case IPPROTO_UDP:
1701     {
1702       struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1];
1703
1704       pkt4_udp->source_port = htons (src_address->port);
1705       pkt4_udp->destination_port = htons (dst_address->port);
1706       pkt4_udp->len = htons ((uint16_t) payload_length);
1707       GNUNET_TUN_calculate_udp4_checksum (pkt4,
1708                                           pkt4_udp,
1709                                           payload,
1710                                           payload_length);
1711       GNUNET_memcpy (&pkt4_udp[1],
1712                      payload,
1713                      payload_length);
1714     }
1715     break;
1716   case IPPROTO_TCP:
1717     {
1718       struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1];
1719
1720       *pkt4_tcp = *tcp_header;
1721       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1722                   "Sending TCP packet from port %u to port %u\n",
1723                   src_address->port,
1724                   dst_address->port);
1725       pkt4_tcp->source_port = htons (src_address->port);
1726       pkt4_tcp->destination_port = htons (dst_address->port);
1727       GNUNET_TUN_calculate_tcp4_checksum (pkt4,
1728                                           pkt4_tcp,
1729                                           payload,
1730                                           payload_length);
1731       GNUNET_memcpy (&pkt4_tcp[1],
1732                      payload,
1733                      payload_length);
1734     }
1735     break;
1736   default:
1737     GNUNET_assert (0);
1738   }
1739 }
1740
1741
1742 /**
1743  * Prepare an IPv6 packet for transmission via the TUN interface.
1744  * Initializes the IP header and calculates checksums (IP+UDP/TCP).
1745  * For UDP, the UDP header will be fully created, whereas for TCP
1746  * only the ports and checksum will be filled in.  So for TCP,
1747  * a skeleton TCP header must be part of the provided payload.
1748  *
1749  * @param payload payload of the packet (starting with UDP payload or
1750  *                TCP header, depending on protocol)
1751  * @param payload_length number of bytes in @a payload
1752  * @param protocol IPPROTO_UDP or IPPROTO_TCP
1753  * @param tcp_header skeleton TCP header data to send, NULL for UDP
1754  * @param src_address source address to use (IP and port)
1755  * @param dst_address destination address to use (IP and port)
1756  * @param pkt6 where to write the assembled packet; must
1757  *        contain enough space for the IP header, UDP/TCP header
1758  *        AND the payload
1759  */
1760 static void
1761 prepare_ipv6_packet (const void *payload,
1762                      size_t payload_length,
1763                      int protocol,
1764                      const struct GNUNET_TUN_TcpHeader *tcp_header,
1765                      const struct SocketAddress *src_address,
1766                      const struct SocketAddress *dst_address,
1767                      struct GNUNET_TUN_IPv6Header *pkt6)
1768 {
1769   size_t len;
1770
1771   len = payload_length;
1772   switch (protocol)
1773   {
1774   case IPPROTO_UDP:
1775     len += sizeof (struct GNUNET_TUN_UdpHeader);
1776     break;
1777   case IPPROTO_TCP:
1778     len += sizeof (struct GNUNET_TUN_TcpHeader);
1779     break;
1780   default:
1781     GNUNET_break (0);
1782     return;
1783   }
1784   if (len > UINT16_MAX)
1785   {
1786     GNUNET_break (0);
1787     return;
1788   }
1789
1790   GNUNET_TUN_initialize_ipv6_header (pkt6,
1791                                      protocol,
1792                                      len,
1793                                      &src_address->address.ipv6,
1794                                      &dst_address->address.ipv6);
1795
1796   switch (protocol)
1797   {
1798   case IPPROTO_UDP:
1799     {
1800       struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1];
1801
1802       pkt6_udp->source_port = htons (src_address->port);
1803       pkt6_udp->destination_port = htons (dst_address->port);
1804       pkt6_udp->len = htons ((uint16_t) payload_length);
1805       GNUNET_TUN_calculate_udp6_checksum (pkt6,
1806                                           pkt6_udp,
1807                                           payload,
1808                                           payload_length);
1809       GNUNET_memcpy (&pkt6_udp[1],
1810                      payload,
1811                      payload_length);
1812     }
1813     break;
1814   case IPPROTO_TCP:
1815     {
1816       struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1];
1817
1818       /* GNUNET_memcpy first here as some TCP header fields are initialized this way! */
1819       *pkt6_tcp = *tcp_header;
1820       pkt6_tcp->source_port = htons (src_address->port);
1821       pkt6_tcp->destination_port = htons (dst_address->port);
1822       GNUNET_TUN_calculate_tcp6_checksum (pkt6,
1823                                           pkt6_tcp,
1824                                           payload,
1825                                           payload_length);
1826       GNUNET_memcpy (&pkt6_tcp[1],
1827                      payload,
1828                      payload_length);
1829     }
1830     break;
1831   default:
1832     GNUNET_assert (0);
1833     break;
1834   }
1835 }
1836
1837
1838 /**
1839  * Send a TCP packet via the TUN interface.
1840  *
1841  * @param destination_address IP and port to use for the TCP packet's destination
1842  * @param source_address IP and port to use for the TCP packet's source
1843  * @param tcp_header header template to use
1844  * @param payload payload of the TCP packet
1845  * @param payload_length number of bytes in @a payload
1846  */
1847 static void
1848 send_tcp_packet_via_tun (const struct SocketAddress *destination_address,
1849                          const struct SocketAddress *source_address,
1850                          const struct GNUNET_TUN_TcpHeader *tcp_header,
1851                          const void *payload,
1852                          size_t payload_length)
1853 {
1854   size_t len;
1855
1856   GNUNET_STATISTICS_update (stats,
1857                             gettext_noop ("# TCP packets sent via TUN"),
1858                             1,
1859                             GNUNET_NO);
1860   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1861               "Sending packet with %u bytes TCP payload via TUN\n",
1862               (unsigned int) payload_length);
1863   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
1864   switch (source_address->af)
1865   {
1866   case AF_INET:
1867     len += sizeof (struct GNUNET_TUN_IPv4Header);
1868     break;
1869   case AF_INET6:
1870     len += sizeof (struct GNUNET_TUN_IPv6Header);
1871     break;
1872   default:
1873     GNUNET_break (0);
1874     return;
1875   }
1876   len += sizeof (struct GNUNET_TUN_TcpHeader);
1877   len += payload_length;
1878   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1879   {
1880     GNUNET_break (0);
1881     return;
1882   }
1883   {
1884     char buf[len] GNUNET_ALIGN;
1885     struct GNUNET_MessageHeader *hdr;
1886     struct GNUNET_TUN_Layer2PacketHeader *tun;
1887
1888     hdr = (struct GNUNET_MessageHeader *) buf;
1889     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1890     hdr->size = htons (len);
1891     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
1892     tun->flags = htons (0);
1893     switch (source_address->af)
1894     {
1895     case AF_INET:
1896       {
1897         struct GNUNET_TUN_IPv4Header *ipv4
1898           = (struct GNUNET_TUN_IPv4Header*) &tun[1];
1899
1900         tun->proto = htons (ETH_P_IPV4);
1901         prepare_ipv4_packet (payload,
1902                              payload_length,
1903                              IPPROTO_TCP,
1904                              tcp_header,
1905                              source_address,
1906                              destination_address,
1907                              ipv4);
1908       }
1909       break;
1910     case AF_INET6:
1911       {
1912         struct GNUNET_TUN_IPv6Header *ipv6
1913           = (struct GNUNET_TUN_IPv6Header*) &tun[1];
1914
1915         tun->proto = htons (ETH_P_IPV6);
1916         prepare_ipv6_packet (payload,
1917                              payload_length,
1918                              IPPROTO_TCP,
1919                              tcp_header,
1920                              source_address,
1921                              destination_address,
1922                              ipv6);
1923       }
1924       break;
1925     default:
1926       GNUNET_assert (0);
1927       break;
1928     }
1929     if (NULL != helper_handle)
1930       (void) GNUNET_HELPER_send (helper_handle,
1931                                  (const struct GNUNET_MessageHeader*) buf,
1932                                  GNUNET_YES,
1933                                  NULL,
1934                                  NULL);
1935   }
1936 }
1937
1938
1939 /**
1940  * Process a request via cadet to send a request to a TCP service
1941  * offered by this system.
1942  *
1943  * @param cls closure, NULL
1944  * @param channel connection to the other end
1945  * @param channel_ctx pointer to our `struct ChannelState *`
1946  * @param message the actual message
1947  * @return #GNUNET_OK to keep the connection open,
1948  *         #GNUNET_SYSERR to close it (signal serious error)
1949  */
1950 static int
1951 receive_tcp_service (void *cls,
1952                      struct GNUNET_CADET_Channel *channel,
1953                      void **channel_ctx,
1954                      const struct GNUNET_MessageHeader *message)
1955 {
1956   struct ChannelState *state = *channel_ctx;
1957   const struct GNUNET_EXIT_TcpServiceStartMessage *start;
1958   uint16_t pkt_len = ntohs (message->size);
1959
1960   if (NULL == state)
1961   {
1962     GNUNET_break_op (0);
1963     return GNUNET_SYSERR;
1964   }
1965   if (GNUNET_YES == state->is_dns)
1966   {
1967     GNUNET_break_op (0);
1968     return GNUNET_SYSERR;
1969   }
1970   if (NULL == state->specifics.tcp_udp.serv)
1971   {
1972     GNUNET_break_op (0);
1973     return GNUNET_SYSERR;
1974   }
1975   if (GNUNET_SYSERR == state->is_dns)
1976   {
1977     /* channel is UDP/TCP from now on */
1978     state->is_dns = GNUNET_NO;
1979   }
1980   GNUNET_STATISTICS_update (stats,
1981                             gettext_noop ("# TCP service creation requests received via cadet"),
1982                             1,
1983                             GNUNET_NO);
1984   GNUNET_STATISTICS_update (stats,
1985                             gettext_noop ("# Bytes received from CADET"),
1986                             pkt_len,
1987                             GNUNET_NO);
1988   /* check that we got at least a valid header */
1989   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage))
1990   {
1991     GNUNET_break_op (0);
1992     return GNUNET_SYSERR;
1993   }
1994   start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message;
1995   pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage);
1996   if (NULL != state->specifics.tcp_udp.heap_node)
1997   {
1998     GNUNET_break_op (0);
1999     return GNUNET_SYSERR;
2000   }
2001   if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2002   {
2003     GNUNET_break_op (0);
2004     return GNUNET_SYSERR;
2005   }
2006   GNUNET_break_op (ntohl (start->reserved) == 0);
2007   /* setup fresh connection */
2008   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2009               "Received data from %s for forwarding to TCP service %s on port %u\n",
2010               GNUNET_i2s (&state->peer),
2011               GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
2012               (unsigned int) ntohs (start->tcp_header.destination_port));
2013   setup_state_record (state);
2014   send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2015                            &state->specifics.tcp_udp.ri.local_address,
2016                            &start->tcp_header,
2017                            &start[1],
2018                            pkt_len);
2019   GNUNET_CADET_receive_done (channel);
2020   return GNUNET_YES;
2021 }
2022
2023
2024 /**
2025  * Process a request to forward TCP data to the Internet via this peer.
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_tcp_remote (void *cls GNUNET_UNUSED,
2036                     struct GNUNET_CADET_Channel *channel,
2037                     void **channel_ctx GNUNET_UNUSED,
2038                     const struct GNUNET_MessageHeader *message)
2039 {
2040   struct ChannelState *state = *channel_ctx;
2041   const struct GNUNET_EXIT_TcpInternetStartMessage *start;
2042   uint16_t pkt_len = ntohs (message->size);
2043   const struct in_addr *v4;
2044   const struct in6_addr *v6;
2045   const void *payload;
2046   int af;
2047
2048   if (NULL == state)
2049   {
2050     GNUNET_break_op (0);
2051     return GNUNET_SYSERR;
2052   }
2053   if (GNUNET_YES == state->is_dns)
2054   {
2055     GNUNET_break_op (0);
2056     return GNUNET_SYSERR;
2057   }
2058   if (GNUNET_SYSERR == state->is_dns)
2059   {
2060     /* channel is UDP/TCP from now on */
2061     state->is_dns = GNUNET_NO;
2062   }
2063   GNUNET_STATISTICS_update (stats,
2064                             gettext_noop ("# Bytes received from CADET"),
2065                             pkt_len, GNUNET_NO);
2066   GNUNET_STATISTICS_update (stats,
2067                             gettext_noop ("# TCP IP-exit creation requests received via cadet"),
2068                             1, GNUNET_NO);
2069   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage))
2070   {
2071     GNUNET_break_op (0);
2072     return GNUNET_SYSERR;
2073   }
2074   start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message;
2075   pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage);
2076   if ( (NULL != state->specifics.tcp_udp.serv) ||
2077        (NULL != state->specifics.tcp_udp.heap_node) )
2078   {
2079     GNUNET_break_op (0);
2080     return GNUNET_SYSERR;
2081   }
2082   if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2083   {
2084     GNUNET_break_op (0);
2085     return GNUNET_SYSERR;
2086   }
2087   af = (int) ntohl (start->af);
2088   state->specifics.tcp_udp.ri.remote_address.af = af;
2089   switch (af)
2090   {
2091   case AF_INET:
2092     if (pkt_len < sizeof (struct in_addr))
2093     {
2094       GNUNET_break_op (0);
2095       return GNUNET_SYSERR;
2096     }
2097     if (! ipv4_exit)
2098     {
2099       GNUNET_break_op (0);
2100       return GNUNET_SYSERR;
2101     }
2102     v4 = (const struct in_addr*) &start[1];
2103     payload = &v4[1];
2104     pkt_len -= sizeof (struct in_addr);
2105     state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2106     break;
2107   case AF_INET6:
2108     if (pkt_len < sizeof (struct in6_addr))
2109     {
2110       GNUNET_break_op (0);
2111       return GNUNET_SYSERR;
2112     }
2113     if (! ipv6_exit)
2114     {
2115       GNUNET_break_op (0);
2116       return GNUNET_SYSERR;
2117     }
2118     v6 = (const struct in6_addr*) &start[1];
2119     payload = &v6[1];
2120     pkt_len -= sizeof (struct in6_addr);
2121     state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2122     break;
2123   default:
2124     GNUNET_break_op (0);
2125     return GNUNET_SYSERR;
2126   }
2127   {
2128     char buf[INET6_ADDRSTRLEN];
2129     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2130                 "Received payload from %s for existing TCP stream to %s:%u\n",
2131                 GNUNET_i2s (&state->peer),
2132                 inet_ntop (af,
2133                            &state->specifics.tcp_udp.ri.remote_address.address,
2134                            buf, sizeof (buf)),
2135                 (unsigned int) ntohs (start->tcp_header.destination_port));
2136   }
2137   state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP;
2138   state->specifics.tcp_udp.ri.remote_address.port = ntohs (start->tcp_header.destination_port);
2139   setup_state_record (state);
2140   send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2141                            &state->specifics.tcp_udp.ri.local_address,
2142                            &start->tcp_header,
2143                            payload, pkt_len);
2144   GNUNET_CADET_receive_done (channel);
2145   return GNUNET_YES;
2146 }
2147
2148
2149 /**
2150  * Process a request to forward TCP data on an established
2151  * connection via this peer.
2152  *
2153  * @param cls closure, NULL
2154  * @param channel connection to the other end
2155  * @param channel_ctx pointer to our `struct ChannelState *`
2156  * @param message the actual message
2157  * @return #GNUNET_OK to keep the connection open,
2158  *         #GNUNET_SYSERR to close it (signal serious error)
2159  */
2160 static int
2161 receive_tcp_data (void *cls GNUNET_UNUSED,
2162                   struct GNUNET_CADET_Channel *channel,
2163                   void **channel_ctx GNUNET_UNUSED,
2164                   const struct GNUNET_MessageHeader *message)
2165 {
2166   struct ChannelState *state = *channel_ctx;
2167   const struct GNUNET_EXIT_TcpDataMessage *data;
2168   uint16_t pkt_len = ntohs (message->size);
2169
2170   GNUNET_STATISTICS_update (stats,
2171                             gettext_noop ("# Bytes received from CADET"),
2172                             pkt_len, GNUNET_NO);
2173   GNUNET_STATISTICS_update (stats,
2174                             gettext_noop ("# TCP data requests received via cadet"),
2175                             1, GNUNET_NO);
2176   if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage))
2177   {
2178     GNUNET_break_op (0);
2179     return GNUNET_SYSERR;
2180   }
2181   data = (const struct GNUNET_EXIT_TcpDataMessage*) message;
2182   pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage);
2183   if ( (NULL == state) ||
2184        (NULL == state->specifics.tcp_udp.heap_node) )
2185   {
2186     /* connection should have been up! */
2187     GNUNET_STATISTICS_update (stats,
2188                               gettext_noop ("# TCP DATA requests dropped (no session)"),
2189                               1, GNUNET_NO);
2190     GNUNET_break_op (0);
2191     return GNUNET_SYSERR;
2192   }
2193   if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader))
2194   {
2195     GNUNET_break_op (0);
2196     return GNUNET_SYSERR;
2197   }
2198   if (GNUNET_YES == state->is_dns)
2199   {
2200     GNUNET_break_op (0);
2201     return GNUNET_SYSERR;
2202   }
2203   if (GNUNET_SYSERR == state->is_dns)
2204   {
2205     /* channel is UDP/TCP from now on */
2206     state->is_dns = GNUNET_NO;
2207   }
2208
2209   GNUNET_break_op (ntohl (data->reserved) == 0);
2210   {
2211     char buf[INET6_ADDRSTRLEN];
2212     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2213                 "Received additional %u bytes of data from %s for TCP stream to %s:%u\n",
2214                 pkt_len,
2215                 GNUNET_i2s (&state->peer),
2216                 inet_ntop (state->specifics.tcp_udp.ri.remote_address.af,
2217                            &state->specifics.tcp_udp.ri.remote_address.address,
2218                            buf, sizeof (buf)),
2219                 (unsigned int) state->specifics.tcp_udp.ri.remote_address.port);
2220   }
2221
2222   send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2223                            &state->specifics.tcp_udp.ri.local_address,
2224                            &data->tcp_header,
2225                            &data[1], pkt_len);
2226   GNUNET_CADET_receive_done (channel);
2227   return GNUNET_YES;
2228 }
2229
2230
2231 /**
2232  * Send an ICMP packet via the TUN interface.
2233  *
2234  * @param destination_address IP to use for the ICMP packet's destination
2235  * @param source_address IP to use for the ICMP packet's source
2236  * @param icmp_header ICMP header to send
2237  * @param payload payload of the ICMP packet (does NOT include ICMP header)
2238  * @param payload_length number of bytes of data in @a payload
2239  */
2240 static void
2241 send_icmp_packet_via_tun (const struct SocketAddress *destination_address,
2242                           const struct SocketAddress *source_address,
2243                           const struct GNUNET_TUN_IcmpHeader *icmp_header,
2244                           const void *payload, size_t payload_length)
2245 {
2246   size_t len;
2247   struct GNUNET_TUN_IcmpHeader *icmp;
2248
2249   GNUNET_STATISTICS_update (stats,
2250                             gettext_noop ("# ICMP packets sent via TUN"),
2251                             1, GNUNET_NO);
2252   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2253               "Sending packet with %u bytes ICMP payload via TUN\n",
2254               (unsigned int) payload_length);
2255   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2256   switch (destination_address->af)
2257   {
2258   case AF_INET:
2259     len += sizeof (struct GNUNET_TUN_IPv4Header);
2260     break;
2261   case AF_INET6:
2262     len += sizeof (struct GNUNET_TUN_IPv6Header);
2263     break;
2264   default:
2265     GNUNET_break (0);
2266     return;
2267   }
2268   len += sizeof (struct GNUNET_TUN_IcmpHeader);
2269   len += payload_length;
2270   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2271   {
2272     GNUNET_break (0);
2273     return;
2274   }
2275   {
2276     char buf[len] GNUNET_ALIGN;
2277     struct GNUNET_MessageHeader *hdr;
2278     struct GNUNET_TUN_Layer2PacketHeader *tun;
2279
2280     hdr= (struct GNUNET_MessageHeader *) buf;
2281     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2282     hdr->size = htons (len);
2283     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2284     tun->flags = htons (0);
2285     switch (source_address->af)
2286     {
2287     case AF_INET:
2288       {
2289         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2290
2291         tun->proto = htons (ETH_P_IPV4);
2292         GNUNET_TUN_initialize_ipv4_header (ipv4,
2293                                            IPPROTO_ICMP,
2294                                            sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2295                                            &source_address->address.ipv4,
2296                                            &destination_address->address.ipv4);
2297         icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1];
2298       }
2299       break;
2300     case AF_INET6:
2301       {
2302         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2303
2304         tun->proto = htons (ETH_P_IPV6);
2305         GNUNET_TUN_initialize_ipv6_header (ipv6,
2306                                            IPPROTO_ICMPV6,
2307                                            sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length,
2308                                            &source_address->address.ipv6,
2309                                            &destination_address->address.ipv6);
2310         icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1];
2311       }
2312       break;
2313     default:
2314       GNUNET_assert (0);
2315       break;
2316     }
2317     *icmp = *icmp_header;
2318     GNUNET_memcpy (&icmp[1],
2319             payload,
2320             payload_length);
2321     GNUNET_TUN_calculate_icmp_checksum (icmp,
2322                                         payload,
2323                                         payload_length);
2324     if (NULL != helper_handle)
2325       (void) GNUNET_HELPER_send (helper_handle,
2326                                  (const struct GNUNET_MessageHeader*) buf,
2327                                  GNUNET_YES,
2328                                  NULL, NULL);
2329   }
2330 }
2331
2332
2333 /**
2334  * Synthesize a plausible ICMP payload for an ICMPv4 error
2335  * response on the given channel.
2336  *
2337  * @param state channel information
2338  * @param ipp IPv6 header to fill in (ICMP payload)
2339  * @param udp "UDP" header to fill in (ICMP payload); might actually
2340  *            also be the first 8 bytes of the TCP header
2341  */
2342 static void
2343 make_up_icmpv4_payload (struct ChannelState *state,
2344                         struct GNUNET_TUN_IPv4Header *ipp,
2345                         struct GNUNET_TUN_UdpHeader *udp)
2346 {
2347   GNUNET_TUN_initialize_ipv4_header (ipp,
2348                                      state->specifics.tcp_udp.ri.remote_address.proto,
2349                                      sizeof (struct GNUNET_TUN_TcpHeader),
2350                                      &state->specifics.tcp_udp.ri.remote_address.address.ipv4,
2351                                      &state->specifics.tcp_udp.ri.local_address.address.ipv4);
2352   udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
2353   udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
2354   udp->len = htons (0);
2355   udp->crc = htons (0);
2356 }
2357
2358
2359 /**
2360  * Synthesize a plausible ICMP payload for an ICMPv6 error
2361  * response on the given channel.
2362  *
2363  * @param state channel information
2364  * @param ipp IPv6 header to fill in (ICMP payload)
2365  * @param udp "UDP" header to fill in (ICMP payload); might actually
2366  *            also be the first 8 bytes of the TCP header
2367  */
2368 static void
2369 make_up_icmpv6_payload (struct ChannelState *state,
2370                         struct GNUNET_TUN_IPv6Header *ipp,
2371                         struct GNUNET_TUN_UdpHeader *udp)
2372 {
2373   GNUNET_TUN_initialize_ipv6_header (ipp,
2374                                      state->specifics.tcp_udp.ri.remote_address.proto,
2375                                      sizeof (struct GNUNET_TUN_TcpHeader),
2376                                      &state->specifics.tcp_udp.ri.remote_address.address.ipv6,
2377                                      &state->specifics.tcp_udp.ri.local_address.address.ipv6);
2378   udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port);
2379   udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port);
2380   udp->len = htons (0);
2381   udp->crc = htons (0);
2382 }
2383
2384
2385 /**
2386  * Process a request to forward ICMP data to the Internet via this peer.
2387  *
2388  * @param cls closure, NULL
2389  * @param channel connection to the other end
2390  * @param channel_ctx pointer to our 'struct ChannelState *'
2391  * @param message the actual message
2392  * @return #GNUNET_OK to keep the connection open,
2393  *         #GNUNET_SYSERR to close it (signal serious error)
2394  */
2395 static int
2396 receive_icmp_remote (void *cls,
2397                      struct GNUNET_CADET_Channel *channel,
2398                      void **channel_ctx,
2399                      const struct GNUNET_MessageHeader *message)
2400 {
2401   struct ChannelState *state = *channel_ctx;
2402   const struct GNUNET_EXIT_IcmpInternetMessage *msg;
2403   uint16_t pkt_len = ntohs (message->size);
2404   const struct in_addr *v4;
2405   const struct in6_addr *v6;
2406   const void *payload;
2407   char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2408   int af;
2409
2410   if (GNUNET_YES == state->is_dns)
2411   {
2412     GNUNET_break_op (0);
2413     return GNUNET_SYSERR;
2414   }
2415   if (GNUNET_SYSERR == state->is_dns)
2416   {
2417     /* channel is UDP/TCP from now on */
2418     state->is_dns = GNUNET_NO;
2419   }
2420   GNUNET_STATISTICS_update (stats,
2421                             gettext_noop ("# Bytes received from CADET"),
2422                             pkt_len, GNUNET_NO);
2423   GNUNET_STATISTICS_update (stats,
2424                             gettext_noop ("# ICMP IP-exit requests received via cadet"),
2425                             1, GNUNET_NO);
2426   if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage))
2427   {
2428     GNUNET_break_op (0);
2429     return GNUNET_SYSERR;
2430   }
2431   msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message;
2432   pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage);
2433
2434   af = (int) ntohl (msg->af);
2435   if ( (NULL != state->specifics.tcp_udp.heap_node) &&
2436        (af != state->specifics.tcp_udp.ri.remote_address.af) )
2437   {
2438     /* other peer switched AF on this channel; not allowed */
2439     GNUNET_break_op (0);
2440     return GNUNET_SYSERR;
2441   }
2442
2443   switch (af)
2444   {
2445   case AF_INET:
2446     if (pkt_len < sizeof (struct in_addr))
2447     {
2448       GNUNET_break_op (0);
2449       return GNUNET_SYSERR;
2450     }
2451     if (! ipv4_exit)
2452     {
2453       GNUNET_break_op (0);
2454       return GNUNET_SYSERR;
2455     }
2456     v4 = (const struct in_addr*) &msg[1];
2457     payload = &v4[1];
2458     pkt_len -= sizeof (struct in_addr);
2459     state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2460     if (NULL == state->specifics.tcp_udp.heap_node)
2461     {
2462       state->specifics.tcp_udp.ri.remote_address.af = af;
2463       state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP;
2464       setup_state_record (state);
2465     }
2466     /* check that ICMP type is something we want to support
2467        and possibly make up payload! */
2468     switch (msg->icmp_header.type)
2469     {
2470     case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2471     case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2472       break;
2473     case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2474     case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2475     case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2476       if (0 != pkt_len)
2477       {
2478         GNUNET_break_op (0);
2479         return GNUNET_SYSERR;
2480       }
2481       /* make up payload */
2482       {
2483         struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) buf;
2484         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2485
2486         GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2487         pkt_len = sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2488         make_up_icmpv4_payload (state,
2489                                 ipp,
2490                                 udp);
2491         payload = ipp;
2492       }
2493       break;
2494     default:
2495       GNUNET_break_op (0);
2496       GNUNET_STATISTICS_update (stats,
2497                                 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2498                                 1, GNUNET_NO);
2499       return GNUNET_SYSERR;
2500     }
2501     /* end AF_INET */
2502     break;
2503   case AF_INET6:
2504     if (pkt_len < sizeof (struct in6_addr))
2505     {
2506       GNUNET_break_op (0);
2507       return GNUNET_SYSERR;
2508     }
2509     if (! ipv6_exit)
2510     {
2511       GNUNET_break_op (0);
2512       return GNUNET_SYSERR;
2513     }
2514     v6 = (const struct in6_addr*) &msg[1];
2515     payload = &v6[1];
2516     pkt_len -= sizeof (struct in6_addr);
2517     state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
2518     if (NULL == state->specifics.tcp_udp.heap_node)
2519     {
2520       state->specifics.tcp_udp.ri.remote_address.af = af;
2521       state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6;
2522       setup_state_record (state);
2523     }
2524     /* check that ICMP type is something we want to support
2525        and possibly make up payload! */
2526     switch (msg->icmp_header.type)
2527     {
2528     case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2529     case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2530       break;
2531     case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2532     case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2533     case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2534     case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2535       if (0 != pkt_len)
2536       {
2537         GNUNET_break_op (0);
2538         return GNUNET_SYSERR;
2539       }
2540       /* make up payload */
2541       {
2542         struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) buf;
2543         struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1];
2544
2545         GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2546         pkt_len = sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2547         make_up_icmpv6_payload (state,
2548                                 ipp,
2549                                 udp);
2550         payload = ipp;
2551       }
2552       break;
2553     default:
2554       GNUNET_break_op (0);
2555       GNUNET_STATISTICS_update (stats,
2556                                 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2557                                 1, GNUNET_NO);
2558       return GNUNET_SYSERR;
2559     }
2560     /* end AF_INET6 */
2561     break;
2562   default:
2563     /* bad AF */
2564     GNUNET_break_op (0);
2565     return GNUNET_SYSERR;
2566   }
2567
2568   {
2569     char buf[INET6_ADDRSTRLEN];
2570     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2571                 "Received ICMP data from %s for forwarding to %s\n",
2572                 GNUNET_i2s (&state->peer),
2573                 inet_ntop (af,
2574                            &state->specifics.tcp_udp.ri.remote_address.address,
2575                            buf, sizeof (buf)));
2576   }
2577   send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2578                             &state->specifics.tcp_udp.ri.local_address,
2579                             &msg->icmp_header,
2580                             payload, pkt_len);
2581   GNUNET_CADET_receive_done (channel);
2582   return GNUNET_YES;
2583 }
2584
2585
2586 /**
2587  * Setup ICMP payload for ICMP error messages. Called
2588  * for both IPv4 and IPv6 addresses.
2589  *
2590  * @param state context for creating the IP Packet
2591  * @param buf where to create the payload, has at least
2592  *       sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes
2593  * @return number of bytes of payload we created in buf
2594  */
2595 static uint16_t
2596 make_up_icmp_service_payload (struct ChannelState *state,
2597                               char *buf)
2598 {
2599   switch (state->specifics.tcp_udp.serv->address.af)
2600   {
2601   case AF_INET:
2602     {
2603       struct GNUNET_TUN_IPv4Header *ipv4;
2604       struct GNUNET_TUN_UdpHeader *udp;
2605
2606       ipv4 = (struct GNUNET_TUN_IPv4Header *)buf;
2607       udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1];
2608       make_up_icmpv4_payload (state,
2609                               ipv4,
2610                               udp);
2611       GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2612       return sizeof (struct GNUNET_TUN_IPv4Header) + 8;
2613     }
2614     break;
2615   case AF_INET6:
2616     {
2617       struct GNUNET_TUN_IPv6Header *ipv6;
2618       struct GNUNET_TUN_UdpHeader *udp;
2619
2620       ipv6 = (struct GNUNET_TUN_IPv6Header *)buf;
2621       udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1];
2622       make_up_icmpv6_payload (state,
2623                               ipv6,
2624                               udp);
2625       GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
2626       return sizeof (struct GNUNET_TUN_IPv6Header) + 8;
2627     }
2628     break;
2629   default:
2630     GNUNET_break (0);
2631   }
2632   return 0;
2633 }
2634
2635
2636 /**
2637  * Process a request via cadet to send ICMP data to a service
2638  * offered by this system.
2639  *
2640  * @param cls closure, NULL
2641  * @param channel connection to the other end
2642  * @param channel_ctx pointer to our 'struct ChannelState *'
2643  * @param message the actual message
2644  * @return #GNUNET_OK to keep the connection open,
2645  *         #GNUNET_SYSERR to close it (signal serious error)
2646  */
2647 static int
2648 receive_icmp_service (void *cls,
2649                       struct GNUNET_CADET_Channel *channel,
2650                       void **channel_ctx,
2651                       const struct GNUNET_MessageHeader *message)
2652 {
2653   struct ChannelState *state = *channel_ctx;
2654   const struct GNUNET_EXIT_IcmpServiceMessage *msg;
2655   uint16_t pkt_len = ntohs (message->size);
2656   struct GNUNET_TUN_IcmpHeader icmp;
2657   char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN;
2658   const void *payload;
2659
2660   if (GNUNET_YES == state->is_dns)
2661   {
2662     GNUNET_break_op (0);
2663     return GNUNET_SYSERR;
2664   }
2665   if (NULL == state->specifics.tcp_udp.serv)
2666   {
2667     GNUNET_break_op (0);
2668     return GNUNET_SYSERR;
2669   }
2670   GNUNET_STATISTICS_update (stats,
2671                             gettext_noop ("# Bytes received from CADET"),
2672                             pkt_len, GNUNET_NO);
2673   GNUNET_STATISTICS_update (stats,
2674                             gettext_noop ("# ICMP service requests received via cadet"),
2675                             1, GNUNET_NO);
2676   /* check that we got at least a valid header */
2677   if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage))
2678   {
2679     GNUNET_break_op (0);
2680     return GNUNET_SYSERR;
2681   }
2682   msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message;
2683   pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage);
2684   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2685               "Received data from %s for forwarding to ICMP service %s\n",
2686               GNUNET_i2s (&state->peer),
2687               GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor));
2688   icmp = msg->icmp_header;
2689   payload = &msg[1];
2690   state->specifics.tcp_udp.ri.remote_address
2691     = state->specifics.tcp_udp.serv->address;
2692   setup_state_record (state);
2693
2694   /* check that ICMP type is something we want to support,
2695      perform ICMP PT if needed ans possibly make up payload */
2696   switch (msg->af)
2697   {
2698   case AF_INET:
2699     switch (msg->icmp_header.type)
2700     {
2701     case GNUNET_TUN_ICMPTYPE_ECHO_REPLY:
2702       if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2703         icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY;
2704       break;
2705     case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST:
2706       if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2707         icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST;
2708       break;
2709     case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE:
2710       if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2711         icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE;
2712       if (0 != pkt_len)
2713       {
2714         GNUNET_break_op (0);
2715         return GNUNET_SYSERR;
2716       }
2717       payload = buf;
2718       pkt_len = make_up_icmp_service_payload (state, buf);
2719       break;
2720     case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED:
2721       if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2722         icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED;
2723       if (0 != pkt_len)
2724       {
2725         GNUNET_break_op (0);
2726         return GNUNET_SYSERR;
2727       }
2728       payload = buf;
2729       pkt_len = make_up_icmp_service_payload (state, buf);
2730       break;
2731     case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH:
2732       if (state->specifics.tcp_udp.serv->address.af == AF_INET6)
2733       {
2734         GNUNET_STATISTICS_update (stats,
2735                                   gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"),
2736                                   1, GNUNET_NO);
2737         return GNUNET_OK;
2738       }
2739       if (0 != pkt_len)
2740       {
2741         GNUNET_break_op (0);
2742         return GNUNET_SYSERR;
2743       }
2744       payload = buf;
2745       pkt_len = make_up_icmp_service_payload (state, buf);
2746       break;
2747     default:
2748       GNUNET_break_op (0);
2749       GNUNET_STATISTICS_update (stats,
2750                                 gettext_noop ("# ICMPv4 packets dropped (type not allowed)"),
2751                                 1, GNUNET_NO);
2752       return GNUNET_SYSERR;
2753     }
2754     /* end of AF_INET */
2755     break;
2756   case AF_INET6:
2757     switch (msg->icmp_header.type)
2758     {
2759     case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY:
2760       if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2761         icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY;
2762       break;
2763     case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST:
2764       if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2765         icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST;
2766       break;
2767     case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE:
2768       if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2769         icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE;
2770       if (0 != pkt_len)
2771       {
2772         GNUNET_break_op (0);
2773         return GNUNET_SYSERR;
2774       }
2775       payload = buf;
2776       pkt_len = make_up_icmp_service_payload (state, buf);
2777       break;
2778     case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED:
2779       if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2780         icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED;
2781       if (0 != pkt_len)
2782       {
2783         GNUNET_break_op (0);
2784         return GNUNET_SYSERR;
2785       }
2786       payload = buf;
2787       pkt_len = make_up_icmp_service_payload (state, buf);
2788       break;
2789     case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG:
2790     case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM:
2791       if (state->specifics.tcp_udp.serv->address.af == AF_INET)
2792       {
2793         GNUNET_STATISTICS_update (stats,
2794                                   gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"),
2795                                   1, GNUNET_NO);
2796         return GNUNET_OK;
2797       }
2798       if (0 != pkt_len)
2799       {
2800         GNUNET_break_op (0);
2801         return GNUNET_SYSERR;
2802       }
2803       payload = buf;
2804       pkt_len = make_up_icmp_service_payload (state, buf);
2805       break;
2806     default:
2807       GNUNET_break_op (0);
2808       GNUNET_STATISTICS_update (stats,
2809                                 gettext_noop ("# ICMPv6 packets dropped (type not allowed)"),
2810                                 1, GNUNET_NO);
2811       return GNUNET_SYSERR;
2812     }
2813     /* end of AF_INET6 */
2814     break;
2815   default:
2816     GNUNET_break_op (0);
2817     return GNUNET_SYSERR;
2818   }
2819
2820   send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
2821                             &state->specifics.tcp_udp.ri.local_address,
2822                             &icmp,
2823                             payload, pkt_len);
2824   GNUNET_CADET_receive_done (channel);
2825   return GNUNET_YES;
2826 }
2827
2828
2829 /**
2830  * Send a UDP packet via the TUN interface.
2831  *
2832  * @param destination_address IP and port to use for the UDP packet's destination
2833  * @param source_address IP and port to use for the UDP packet's source
2834  * @param payload payload of the UDP packet (does NOT include UDP header)
2835  * @param payload_length number of bytes of data in @a payload
2836  */
2837 static void
2838 send_udp_packet_via_tun (const struct SocketAddress *destination_address,
2839                          const struct SocketAddress *source_address,
2840                          const void *payload, size_t payload_length)
2841 {
2842   size_t len;
2843
2844   GNUNET_STATISTICS_update (stats,
2845                             gettext_noop ("# UDP packets sent via TUN"),
2846                             1, GNUNET_NO);
2847   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2848               "Sending packet with %u bytes UDP payload via TUN\n",
2849               (unsigned int) payload_length);
2850   len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader);
2851   switch (source_address->af)
2852   {
2853   case AF_INET:
2854     len += sizeof (struct GNUNET_TUN_IPv4Header);
2855     break;
2856   case AF_INET6:
2857     len += sizeof (struct GNUNET_TUN_IPv6Header);
2858     break;
2859   default:
2860     GNUNET_break (0);
2861     return;
2862   }
2863   len += sizeof (struct GNUNET_TUN_UdpHeader);
2864   len += payload_length;
2865   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
2866   {
2867     GNUNET_break (0);
2868     return;
2869   }
2870   {
2871     char buf[len] GNUNET_ALIGN;
2872     struct GNUNET_MessageHeader *hdr;
2873     struct GNUNET_TUN_Layer2PacketHeader *tun;
2874
2875     hdr= (struct GNUNET_MessageHeader *) buf;
2876     hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
2877     hdr->size = htons (len);
2878     tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1];
2879     tun->flags = htons (0);
2880     switch (source_address->af)
2881     {
2882     case AF_INET:
2883       {
2884         struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1];
2885
2886         tun->proto = htons (ETH_P_IPV4);
2887         prepare_ipv4_packet (payload,
2888                              payload_length,
2889                              IPPROTO_UDP,
2890                              NULL,
2891                              source_address,
2892                              destination_address,
2893                              ipv4);
2894       }
2895       break;
2896     case AF_INET6:
2897       {
2898         struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1];
2899
2900         tun->proto = htons (ETH_P_IPV6);
2901         prepare_ipv6_packet (payload,
2902                              payload_length,
2903                              IPPROTO_UDP,
2904                              NULL,
2905                              source_address,
2906                              destination_address,
2907                              ipv6);
2908       }
2909       break;
2910     default:
2911       GNUNET_assert (0);
2912       break;
2913     }
2914     if (NULL != helper_handle)
2915       (void) GNUNET_HELPER_send (helper_handle,
2916                                  (const struct GNUNET_MessageHeader*) buf,
2917                                  GNUNET_YES,
2918                                  NULL, NULL);
2919   }
2920 }
2921
2922
2923 /**
2924  * Process a request to forward UDP data to the Internet via this peer.
2925  *
2926  * @param cls closure, NULL
2927  * @param channel connection to the other end
2928  * @param channel_ctx pointer to our 'struct ChannelState *'
2929  * @param message the actual message
2930  * @return #GNUNET_OK to keep the connection open,
2931  *         #GNUNET_SYSERR to close it (signal serious error)
2932  */
2933 static int
2934 receive_udp_remote (void *cls,
2935                     struct GNUNET_CADET_Channel *channel,
2936                     void **channel_ctx,
2937                     const struct GNUNET_MessageHeader *message)
2938 {
2939   struct ChannelState *state = *channel_ctx;
2940   const struct GNUNET_EXIT_UdpInternetMessage *msg;
2941   uint16_t pkt_len = ntohs (message->size);
2942   const struct in_addr *v4;
2943   const struct in6_addr *v6;
2944   const void *payload;
2945   int af;
2946
2947   if (GNUNET_YES == state->is_dns)
2948   {
2949     GNUNET_break_op (0);
2950     return GNUNET_SYSERR;
2951   }
2952   if (GNUNET_SYSERR == state->is_dns)
2953   {
2954     /* channel is UDP/TCP from now on */
2955     state->is_dns = GNUNET_NO;
2956   }
2957   GNUNET_STATISTICS_update (stats,
2958                             gettext_noop ("# Bytes received from CADET"),
2959                             pkt_len, GNUNET_NO);
2960   GNUNET_STATISTICS_update (stats,
2961                             gettext_noop ("# UDP IP-exit requests received via cadet"),
2962                             1, GNUNET_NO);
2963   if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage))
2964   {
2965     GNUNET_break_op (0);
2966     return GNUNET_SYSERR;
2967   }
2968   msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message;
2969   pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage);
2970   af = (int) ntohl (msg->af);
2971   state->specifics.tcp_udp.ri.remote_address.af = af;
2972   switch (af)
2973   {
2974   case AF_INET:
2975     if (pkt_len < sizeof (struct in_addr))
2976     {
2977       GNUNET_break_op (0);
2978       return GNUNET_SYSERR;
2979     }
2980     if (! ipv4_exit)
2981     {
2982       GNUNET_break_op (0);
2983       return GNUNET_SYSERR;
2984     }
2985     v4 = (const struct in_addr*) &msg[1];
2986     payload = &v4[1];
2987     pkt_len -= sizeof (struct in_addr);
2988     state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4;
2989     break;
2990   case AF_INET6:
2991     if (pkt_len < sizeof (struct in6_addr))
2992     {
2993       GNUNET_break_op (0);
2994       return GNUNET_SYSERR;
2995     }
2996     if (! ipv6_exit)
2997     {
2998       GNUNET_break_op (0);
2999       return GNUNET_SYSERR;
3000     }
3001     v6 = (const struct in6_addr*) &msg[1];
3002     payload = &v6[1];
3003     pkt_len -= sizeof (struct in6_addr);
3004     state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6;
3005     break;
3006   default:
3007     GNUNET_break_op (0);
3008     return GNUNET_SYSERR;
3009   }
3010   {
3011     char buf[INET6_ADDRSTRLEN];
3012     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3013                 "Received data from %s for forwarding to UDP %s:%u\n",
3014                 GNUNET_i2s (&state->peer),
3015                 inet_ntop (af,
3016                            &state->specifics.tcp_udp.ri.remote_address.address,
3017                            buf, sizeof (buf)),
3018                 (unsigned int) ntohs (msg->destination_port));
3019   }
3020   state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP;
3021   state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port;
3022   if (NULL == state->specifics.tcp_udp.heap_node)
3023     setup_state_record (state);
3024   if (0 != ntohs (msg->source_port))
3025     state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
3026   send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
3027                            &state->specifics.tcp_udp.ri.local_address,
3028                            payload, pkt_len);
3029   GNUNET_CADET_receive_done (channel);
3030   return GNUNET_YES;
3031 }
3032
3033
3034 /**
3035  * Process a request via cadet to send a request to a UDP service
3036  * offered by this system.
3037  *
3038  * @param cls closure, NULL
3039  * @param channel connection to the other end
3040  * @param channel_ctx pointer to our 'struct ChannelState *'
3041  * @param message the actual message
3042  * @return #GNUNET_OK to keep the connection open,
3043  *         #GNUNET_SYSERR to close it (signal serious error)
3044  */
3045 static int
3046 receive_udp_service (void *cls,
3047                      struct GNUNET_CADET_Channel *channel,
3048                      void **channel_ctx,
3049                      const struct GNUNET_MessageHeader *message)
3050 {
3051   struct ChannelState *state = *channel_ctx;
3052   const struct GNUNET_EXIT_UdpServiceMessage *msg;
3053   uint16_t pkt_len = ntohs (message->size);
3054
3055   if (NULL == state->specifics.tcp_udp.serv)
3056   {
3057     GNUNET_break_op (0);
3058     return GNUNET_SYSERR;
3059   }
3060   GNUNET_STATISTICS_update (stats,
3061                             gettext_noop ("# Bytes received from CADET"),
3062                             pkt_len, GNUNET_NO);
3063   GNUNET_STATISTICS_update (stats,
3064                             gettext_noop ("# UDP service requests received via cadet"),
3065                             1, GNUNET_NO);
3066   /* check that we got at least a valid header */
3067   if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage))
3068   {
3069     GNUNET_break_op (0);
3070     return GNUNET_SYSERR;
3071   }
3072   msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message;
3073   pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage);
3074   LOG (GNUNET_ERROR_TYPE_DEBUG,
3075        "Received data from %s for forwarding to UDP service %s on port %u\n",
3076        GNUNET_i2s (&state->peer),
3077        GNUNET_h2s (&state->specifics.tcp_udp.serv->descriptor),
3078        (unsigned int) ntohs (msg->destination_port));
3079   setup_state_record (state);
3080   if (0 != ntohs (msg->source_port))
3081     state->specifics.tcp_udp.ri.local_address.port = msg->source_port;
3082   send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address,
3083                            &state->specifics.tcp_udp.ri.local_address,
3084                            &msg[1],
3085                            pkt_len);
3086   GNUNET_CADET_receive_done (channel);
3087   return GNUNET_YES;
3088 }
3089
3090
3091 /**
3092  * Callback from CADET for new channels.
3093  *
3094  * @param cls closure
3095  * @param channel new handle to the channel
3096  * @param initiator peer that started the channel
3097  * @param port destination port
3098  * @param options channel options flags
3099  * @return initial channel context for the channel
3100  */
3101 static void *
3102 new_channel (void *cls,
3103              struct GNUNET_CADET_Channel *channel,
3104              const struct GNUNET_PeerIdentity *initiator,
3105              const struct GNUNET_HashCode *port,
3106              enum GNUNET_CADET_ChannelOption options)
3107 {
3108   struct ChannelState *s = GNUNET_new (struct ChannelState);
3109
3110   s->is_dns = GNUNET_SYSERR;
3111   s->peer = *initiator;
3112   GNUNET_STATISTICS_update (stats,
3113                             gettext_noop ("# Inbound CADET channels created"),
3114                             1, GNUNET_NO);
3115   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3116               "Received inbound channel from `%s'\n",
3117               GNUNET_i2s (initiator));
3118   s->channel = channel;
3119   return s;
3120 }
3121
3122
3123 /**
3124  * Function called by cadet whenever an inbound channel is destroyed.
3125  * Should clean up any associated state.
3126  *
3127  * @param cls closure (set from #GNUNET_CADET_connect)
3128  * @param channel connection to the other end (henceforth invalid)
3129  * @param channel_ctx place where local state associated
3130  *                   with the channel is stored
3131  */
3132 static void
3133 clean_channel (void *cls,
3134                const struct GNUNET_CADET_Channel *channel,
3135                void *channel_ctx)
3136 {
3137   struct ChannelState *s = channel_ctx;
3138   struct ChannelMessageQueue *tnq;
3139
3140   LOG (GNUNET_ERROR_TYPE_DEBUG,
3141        "Channel destroyed\n");
3142   if (GNUNET_SYSERR == s->is_dns)
3143   {
3144     GNUNET_free (s);
3145     return;
3146   }
3147   if (GNUNET_YES == s->is_dns)
3148   {
3149     if (channels[s->specifics.dns.my_id] == s)
3150       channels[s->specifics.dns.my_id] = NULL;
3151     GNUNET_free_non_null (s->specifics.dns.reply);
3152   }
3153   else
3154   {
3155     while (NULL != (tnq = s->specifics.tcp_udp.head))
3156     {
3157       GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head,
3158                                    s->specifics.tcp_udp.tail,
3159                                    tnq);
3160       GNUNET_free (tnq);
3161     }
3162     if (NULL != s->specifics.tcp_udp.heap_node)
3163     {
3164       GNUNET_assert (GNUNET_YES ==
3165                      GNUNET_CONTAINER_multihashmap_remove (connections_map,
3166                                                            &s->specifics.tcp_udp.state_key,
3167                                                            s));
3168       GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node);
3169       s->specifics.tcp_udp.heap_node = NULL;
3170     }
3171   }
3172   if (NULL != s->th)
3173   {
3174     GNUNET_CADET_notify_transmit_ready_cancel (s->th);
3175     s->th = NULL;
3176   }
3177   GNUNET_free (s);
3178 }
3179
3180
3181 /**
3182  * Function that frees everything from a hashmap
3183  *
3184  * @param cls unused
3185  * @param hash key
3186  * @param value value to free
3187  */
3188 static int
3189 free_iterate (void *cls,
3190               const struct GNUNET_HashCode * hash,
3191               void *value)
3192 {
3193   GNUNET_free (value);
3194   return GNUNET_YES;
3195 }
3196
3197
3198 /**
3199  * Function scheduled as very last function if the service
3200  * disabled itself because the helper is not installed
3201  * properly.  Does nothing, except for keeping the
3202  * service process alive by virtue of being scheduled.
3203  *
3204  * @param cls NULL
3205  * @param tc scheduler context
3206  */
3207 static void
3208 dummy_task (void *cls)
3209 {
3210   /* just terminate */
3211 }
3212
3213
3214 /**
3215  * Function scheduled as very last function, cleans up after us
3216  *
3217  * @param cls NULL
3218  */
3219 static void
3220 cleanup (void *cls)
3221 {
3222   unsigned int i;
3223
3224   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3225               "Exit service is shutting down now\n");
3226
3227   if (NULL != helper_handle)
3228   {
3229     GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
3230     helper_handle = NULL;
3231   }
3232   if (NULL != regex4)
3233   {
3234     GNUNET_REGEX_announce_cancel (regex4);
3235     regex4 = NULL;
3236   }
3237   if (NULL != regex6)
3238   {
3239     GNUNET_REGEX_announce_cancel (regex6);
3240     regex6 = NULL;
3241   }
3242   if (NULL != services)
3243   {
3244     GNUNET_CONTAINER_multihashmap_iterate (services,
3245                                            &free_service_record,
3246                                            NULL);
3247     GNUNET_CONTAINER_multihashmap_destroy (services);
3248   }
3249   if (NULL != cadet_handle)
3250   {
3251     GNUNET_CADET_disconnect (cadet_handle);
3252     cadet_handle = NULL;
3253   }
3254   if (NULL != connections_map)
3255   {
3256     GNUNET_CONTAINER_multihashmap_iterate (connections_map,
3257                                            &free_iterate,
3258                                            NULL);
3259     GNUNET_CONTAINER_multihashmap_destroy (connections_map);
3260     connections_map = NULL;
3261   }
3262   if (NULL != connections_heap)
3263   {
3264     GNUNET_CONTAINER_heap_destroy (connections_heap);
3265     connections_heap = NULL;
3266   }
3267   if (NULL != dnsstub)
3268   {
3269     GNUNET_DNSSTUB_stop (dnsstub);
3270     dnsstub = NULL;
3271   }
3272   if (NULL != peer_key)
3273   {
3274     GNUNET_free (peer_key);
3275     peer_key = NULL;
3276   }
3277   if (NULL != dht_task)
3278   {
3279     GNUNET_SCHEDULER_cancel (dht_task);
3280     dht_task = NULL;
3281   }
3282   if (NULL != dht_put)
3283   {
3284     GNUNET_DHT_put_cancel (dht_put);
3285     dht_put = NULL;
3286   }
3287   if (NULL != dht)
3288   {
3289     GNUNET_DHT_disconnect (dht);
3290     dht = NULL;
3291   }
3292   if (NULL != stats)
3293   {
3294     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
3295     stats = NULL;
3296   }
3297   for (i=0;i<8;i++)
3298     GNUNET_free_non_null (exit_argv[i]);
3299 }
3300
3301
3302 /**
3303  * Add services to the service map.
3304  *
3305  * @param proto IPPROTO_TCP or IPPROTO_UDP
3306  * @param cpy copy of the service descriptor (can be mutilated)
3307  * @param name DNS name of the service
3308  */
3309 static void
3310 add_services (int proto,
3311               char *cpy,
3312               const char *name)
3313 {
3314   char *redirect;
3315   char *hostname;
3316   char *hostport;
3317   struct LocalService *serv;
3318   char *n;
3319   size_t slen;
3320
3321   slen = strlen (name);
3322   GNUNET_assert (slen >= 8);
3323   n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */);
3324
3325   for (redirect = strtok (cpy, " "); redirect != NULL;
3326        redirect = strtok (NULL, " "))
3327   {
3328     if (NULL == (hostname = strstr (redirect, ":")))
3329     {
3330       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3331                   _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3332                   redirect,
3333                   name);
3334       continue;
3335     }
3336     hostname[0] = '\0';
3337     hostname++;
3338     if (NULL == (hostport = strstr (hostname, ":")))
3339     {
3340       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3341                   _("Option `%s' for domain `%s' is not formatted correctly!\n"),
3342                   redirect,
3343                   name);
3344       continue;
3345     }
3346     hostport[0] = '\0';
3347     hostport++;
3348
3349     int local_port = atoi (redirect);
3350     int remote_port = atoi (hostport);
3351
3352     if (! ((local_port > 0) && (local_port < 65536)))
3353     {
3354       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3355                   _("`%s' is not a valid port number (for domain `%s')!"),
3356                   redirect,
3357                   name);
3358       continue;
3359     }
3360     if (! ((remote_port > 0) && (remote_port < 65536)))
3361     {
3362       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3363                   _("`%s' is not a valid port number (for domain `%s')!"),
3364                   hostport,
3365                   name);
3366       continue;
3367     }
3368
3369     serv = GNUNET_new (struct LocalService);
3370     serv->address.proto = proto;
3371     serv->my_port = (uint16_t) local_port;
3372     serv->address.port = remote_port;
3373     if (0 == strcmp ("localhost4",
3374                      hostname))
3375     {
3376       const char *ip4addr = exit_argv[5];
3377
3378       serv->address.af = AF_INET;
3379       GNUNET_assert (1 == inet_pton (AF_INET,
3380                                      ip4addr,
3381                                      &serv->address.address.ipv4));
3382     }
3383     else if (0 == strcmp ("localhost6",
3384                           hostname))
3385     {
3386       const char *ip6addr = exit_argv[3];
3387
3388       serv->address.af = AF_INET6;
3389       GNUNET_assert (1 == inet_pton (AF_INET6,
3390                                      ip6addr,
3391                                      &serv->address.address.ipv6));
3392     }
3393     else
3394     {
3395       struct addrinfo *res;
3396       int ret;
3397
3398       ret = getaddrinfo (hostname,
3399                          NULL,
3400                          NULL,
3401                          &res);
3402       if ( (0 != ret) || (NULL == res) )
3403       {
3404         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3405                     _("No addresses found for hostname `%s' of service `%s'!\n"),
3406                     hostname,
3407                     n);
3408         GNUNET_free (serv);
3409         continue;
3410       }
3411
3412       serv->address.af = res->ai_family;
3413       switch (res->ai_family)
3414       {
3415       case AF_INET:
3416         if (! ipv4_enabled)
3417         {
3418           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3419                       _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3420                       n);
3421           freeaddrinfo (res);
3422           GNUNET_free (serv);
3423           continue;
3424         }
3425         serv->address.address.ipv4
3426           = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
3427         break;
3428       case AF_INET6:
3429         if (! ipv6_enabled)
3430         {
3431           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3432                       _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"),
3433                       n);
3434           freeaddrinfo (res);
3435           GNUNET_free (serv);
3436           continue;
3437         }
3438         serv->address.address.ipv6
3439           = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
3440         break;
3441       default:
3442         freeaddrinfo (res);
3443         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3444                     _("No IP addresses found for hostname `%s' of service `%s'!\n"),
3445                     hostname,
3446                     n);
3447         GNUNET_free (serv);
3448         continue;
3449       }
3450       freeaddrinfo (res);
3451     }
3452     store_service (proto,
3453                    n,
3454                    local_port,
3455                    serv);
3456   }
3457   GNUNET_free (n);
3458 }
3459
3460
3461 /**
3462  * Reads the configuration servicecfg and populates udp_services
3463  *
3464  * @param cls unused
3465  * @param section name of section in config, equal to hostname
3466  */
3467 static void
3468 read_service_conf (void *cls,
3469                    const char *section)
3470 {
3471   char *cpy;
3472
3473   if ((strlen (section) < 8) ||
3474       (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
3475     return;
3476   if (GNUNET_OK ==
3477       GNUNET_CONFIGURATION_get_value_string (cfg,
3478                                              section,
3479                                              "UDP_REDIRECTS",
3480                                              &cpy))
3481   {
3482     add_services (IPPROTO_UDP,
3483                   cpy,
3484                   section);
3485     GNUNET_free (cpy);
3486   }
3487   if (GNUNET_OK ==
3488       GNUNET_CONFIGURATION_get_value_string (cfg,
3489                                              section,
3490                                              "TCP_REDIRECTS",
3491                                              &cpy))
3492   {
3493     add_services (IPPROTO_TCP,
3494                   cpy,
3495                   section);
3496     GNUNET_free (cpy);
3497   }
3498 }
3499
3500
3501 /**
3502  * We are running a DNS exit service, advertise it in the
3503  * DHT.  This task is run periodically to do the DHT PUT.
3504  *
3505  * @param cls closure
3506  */
3507 static void
3508 do_dht_put (void *cls);
3509
3510
3511 /**
3512  * Function called when the DHT PUT operation is complete.
3513  * Schedules the next PUT.
3514  *
3515  * @param cls closure, NULL
3516  * @param success #GNUNET_OK if the operation worked (unused)
3517  */
3518 static void
3519 dht_put_cont (void *cls,
3520               int success)
3521 {
3522   dht_put = NULL;
3523   dht_task = GNUNET_SCHEDULER_add_delayed (DHT_PUT_FREQUENCY,
3524                                            &do_dht_put,
3525                                            NULL);
3526 }
3527
3528
3529 /**
3530  * We are running a DNS exit service, advertise it in the
3531  * DHT.  This task is run periodically to do the DHT PUT.
3532  *
3533  * @param cls closure
3534  */
3535 static void
3536 do_dht_put (void *cls)
3537 {
3538   struct GNUNET_TIME_Absolute expiration;
3539
3540   dht_task = NULL;
3541   expiration = GNUNET_TIME_absolute_ntoh (dns_advertisement.expiration_time);
3542   if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us <
3543       GNUNET_TIME_UNIT_HOURS.rel_value_us)
3544   {
3545     /* refresh advertisement */
3546     expiration = GNUNET_TIME_relative_to_absolute (DNS_ADVERTISEMENT_TIMEOUT);
3547     dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton (expiration);
3548     GNUNET_assert (GNUNET_OK ==
3549                    GNUNET_CRYPTO_eddsa_sign (peer_key,
3550                                            &dns_advertisement.purpose,
3551                                            &dns_advertisement.signature));
3552   }
3553   dht_put = GNUNET_DHT_put (dht,
3554                             &dht_put_key,
3555                             1 /* replication */,
3556                             GNUNET_DHT_RO_NONE,
3557                             GNUNET_BLOCK_TYPE_DNS,
3558                             sizeof (struct GNUNET_DNS_Advertisement),
3559                             &dns_advertisement,
3560                             expiration,
3561                             &dht_put_cont,
3562                             NULL);
3563 }
3564
3565
3566 /**
3567  * Figure out which IP versions we should support (and which
3568  * are supported by the OS) according to our configuration.
3569  */
3570 static void
3571 parse_ip_options ()
3572 {
3573   ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3574                                                     "exit",
3575                                                     "EXIT_IPV4");
3576   ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3577                                                     "exit",
3578                                                     "EXIT_IPV6");
3579   ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3580                                                        "exit",
3581                                                        "ENABLE_IPV4");
3582   ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg,
3583                                                        "exit",
3584                                                        "ENABLE_IPV6");
3585   if ( (ipv4_exit || ipv4_enabled) &&
3586        GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET))
3587   {
3588     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3589                 _("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n"));
3590     ipv4_exit = GNUNET_NO;
3591     ipv4_enabled = GNUNET_NO;
3592   }
3593   if ( (ipv6_exit || ipv6_enabled) &&
3594        GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6))
3595   {
3596     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3597                 _("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n"));
3598     ipv6_exit = GNUNET_NO;
3599     ipv6_enabled = GNUNET_NO;
3600   }
3601   if (ipv4_exit && (! ipv4_enabled))
3602   {
3603     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3604                 _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n"));
3605     ipv4_enabled = GNUNET_YES;
3606   }
3607   if (ipv6_exit && (! ipv6_enabled))
3608   {
3609     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3610                 _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n"));
3611     ipv6_enabled = GNUNET_YES;
3612   }
3613 }
3614
3615
3616 /**
3617  * Helper function to open the CADET port for DNS exits and to
3618  * advertise the DNS exit (if applicable).
3619  */
3620 static void
3621 advertise_dns_exit ()
3622 {
3623   char *dns_exit;
3624   struct GNUNET_HashCode port;
3625   struct in_addr dns_exit4;
3626   struct in6_addr dns_exit6;
3627
3628   if (GNUNET_YES !=
3629       GNUNET_CONFIGURATION_get_value_yesno (cfg,
3630                                             "exit",
3631                                             "EXIT_DNS"))
3632     return;
3633   if ( (GNUNET_OK !=
3634         GNUNET_CONFIGURATION_get_value_string (cfg,
3635                                                "exit",
3636                                                "DNS_RESOLVER",
3637                                                &dns_exit)) ||
3638        ( (1 != inet_pton (AF_INET,
3639                           dns_exit,
3640                           &dns_exit4)) &&
3641          (1 != inet_pton (AF_INET6,
3642                           dns_exit,
3643                           &dns_exit6)) ) )
3644   {
3645     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3646                                "dns",
3647                                "DNS_RESOLVER",
3648                                _("need a valid IPv4 or IPv6 address\n"));
3649     return;
3650   }
3651   /* open port */
3652   GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER,
3653                       strlen (GNUNET_APPLICATION_PORT_INTERNET_RESOLVER),
3654                       &port);
3655   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3656               "Opening CADET port %s for DNS exit service\n",
3657               GNUNET_h2s (&port));
3658   GNUNET_CADET_open_port (cadet_handle,
3659                           &port,
3660                           &new_channel,
3661                           NULL);
3662   /* advertise exit */
3663   dht = GNUNET_DHT_connect (cfg,
3664                             1);
3665   peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
3666   GNUNET_CRYPTO_eddsa_key_get_public (peer_key,
3667                                       &dns_advertisement.peer.public_key);
3668   dns_advertisement.purpose.size = htonl (sizeof (struct GNUNET_DNS_Advertisement) -
3669                                           sizeof (struct GNUNET_CRYPTO_EddsaSignature));
3670   dns_advertisement.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD);
3671   GNUNET_CRYPTO_hash ("dns",
3672                       strlen ("dns"),
3673                       &dht_put_key);
3674   dht_task = GNUNET_SCHEDULER_add_now (&do_dht_put,
3675                                        NULL);
3676   GNUNET_free (dns_exit);
3677 }
3678
3679
3680 /**
3681  * Initialize #exit_argv.
3682  *
3683  * @return #GNUNET_OK on success, #GNUNET_SYSERR if we should shutdown
3684  */
3685 static int
3686 setup_exit_helper_args ()
3687 {
3688   char *exit_ifname;
3689   char *tun_ifname;
3690   char *ipv6addr;
3691   char *ipv6prefix_s;
3692   char *ipv4addr;
3693   char *ipv4mask;
3694
3695   exit_argv[0] = GNUNET_strdup ("exit-gnunet");
3696   if (GNUNET_SYSERR ==
3697       GNUNET_CONFIGURATION_get_value_string (cfg,
3698                                              "exit",
3699                                              "TUN_IFNAME",
3700                                              &tun_ifname))
3701   {
3702     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3703                                "EXIT",
3704                                "TUN_IFNAME");
3705     return GNUNET_SYSERR;
3706   }
3707   exit_argv[1] = tun_ifname;
3708   if (ipv4_enabled)
3709   {
3710     if (GNUNET_SYSERR ==
3711         GNUNET_CONFIGURATION_get_value_string (cfg,
3712                                                "exit",
3713                                                "EXIT_IFNAME",
3714                                                &exit_ifname))
3715     {
3716       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3717                                  "EXIT",
3718                                  "EXIT_IFNAME");
3719       return GNUNET_SYSERR;
3720     }
3721     exit_argv[2] = exit_ifname;
3722   }
3723   else
3724   {
3725     exit_argv[2] = GNUNET_strdup ("-");
3726   }
3727
3728   if (GNUNET_YES == ipv6_enabled)
3729   {
3730     ipv6addr = NULL;
3731     if ( (GNUNET_SYSERR ==
3732           GNUNET_CONFIGURATION_get_value_string (cfg,
3733                                                  "exit",
3734                                                  "IPV6ADDR",
3735                                                  &ipv6addr) ||
3736           (1 != inet_pton (AF_INET6,
3737                            ipv6addr,
3738                            &exit_ipv6addr))) )
3739     {
3740       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3741                                  "EXIT",
3742                                  "IPV6ADDR");
3743       GNUNET_free_non_null (ipv6addr);
3744       return GNUNET_SYSERR;
3745     }
3746     exit_argv[3] = ipv6addr;
3747     if (GNUNET_SYSERR ==
3748         GNUNET_CONFIGURATION_get_value_string (cfg,
3749                                                "exit",
3750                                                "IPV6PREFIX",
3751                                                &ipv6prefix_s))
3752     {
3753       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3754                                  "EXIT",
3755                                  "IPV6PREFIX");
3756       return GNUNET_SYSERR;
3757     }
3758     exit_argv[4] = ipv6prefix_s;
3759     if ( (GNUNET_OK !=
3760           GNUNET_CONFIGURATION_get_value_number (cfg,
3761                                                  "exit",
3762                                                  "IPV6PREFIX",
3763                                                  &ipv6prefix)) ||
3764          (ipv6prefix >= 127) )
3765     {
3766       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3767                                  "EXIT",
3768                                  "IPV6PREFIX",
3769                                  _("Must be a number"));
3770       return GNUNET_SYSERR;
3771     }
3772   }
3773   else
3774   {
3775     /* IPv6 explicitly disabled */
3776     exit_argv[3] = GNUNET_strdup ("-");
3777     exit_argv[4] = GNUNET_strdup ("-");
3778   }
3779   if (GNUNET_YES == ipv4_enabled)
3780   {
3781     ipv4addr = NULL;
3782     if ( (GNUNET_SYSERR ==
3783           GNUNET_CONFIGURATION_get_value_string (cfg,
3784                                                  "exit",
3785                                                  "IPV4ADDR",
3786                                                  &ipv4addr) ||
3787           (1 != inet_pton (AF_INET,
3788                            ipv4addr,
3789                            &exit_ipv4addr))) )
3790       {
3791         GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3792                                    "EXIT",
3793                                    "IPV4ADDR");
3794         GNUNET_free_non_null (ipv4addr);
3795         return GNUNET_SYSERR;
3796       }
3797     exit_argv[5] = ipv4addr;
3798     ipv4mask = NULL;
3799     if ( (GNUNET_SYSERR ==
3800           GNUNET_CONFIGURATION_get_value_string (cfg,
3801                                                  "exit",
3802                                                  "IPV4MASK",
3803                                                  &ipv4mask) ||
3804           (1 != inet_pton (AF_INET,
3805                            ipv4mask,
3806                            &exit_ipv4mask))) )
3807     {
3808       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
3809                                  "EXIT",
3810                                  "IPV4MASK");
3811       GNUNET_free_non_null (ipv4mask);
3812       return GNUNET_SYSERR;
3813     }
3814     exit_argv[6] = ipv4mask;
3815   }
3816   else
3817   {
3818     /* IPv4 explicitly disabled */
3819     exit_argv[5] = GNUNET_strdup ("-");
3820     exit_argv[6] = GNUNET_strdup ("-");
3821   }
3822   exit_argv[7] = NULL;
3823   return GNUNET_OK;
3824 }
3825
3826
3827 /**
3828  * @brief Main function that will be run by the scheduler.
3829  *
3830  * @param cls closure
3831  * @param args remaining command-line arguments
3832  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
3833  * @param cfg_ configuration
3834  */
3835 static void
3836 run (void *cls,
3837      char *const *args,
3838      const char *cfgfile,
3839      const struct GNUNET_CONFIGURATION_Handle *cfg_)
3840 {
3841   static struct GNUNET_CADET_MessageHandler handlers[] = {
3842     {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0},
3843     {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0},
3844     {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0},
3845     {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0},
3846     {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0},
3847     {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0},
3848     {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0},
3849     {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0},
3850     {NULL, 0, 0}
3851   };
3852   struct GNUNET_HashCode port;
3853   char *policy;
3854   char *binary;
3855   char *regex;
3856   char *prefixed_regex;
3857
3858   cfg = cfg_;
3859   if (GNUNET_OK !=
3860       GNUNET_CONFIGURATION_get_value_number (cfg,
3861                                              "exit",
3862                                              "MAX_CONNECTIONS",
3863                                              &max_connections))
3864     max_connections = 1024;
3865   parse_ip_options ();
3866   if ( (ipv4_exit) || (ipv6_exit) )
3867   {
3868     binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit");
3869     if (GNUNET_YES !=
3870         GNUNET_OS_check_helper_binary (binary,
3871                                        GNUNET_YES,
3872                                        "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only
3873     {
3874       GNUNET_free (binary);
3875       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3876                   _("`%s' must be installed SUID, EXIT will not work\n"),
3877                   "gnunet-helper-exit");
3878       GNUNET_SCHEDULER_add_shutdown (&dummy_task,
3879                                      NULL);
3880       global_ret = 1;
3881       return;
3882     }
3883     GNUNET_free (binary);
3884   }
3885   if (! (ipv4_enabled || ipv6_enabled))
3886   {
3887     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3888                 _("No useful service enabled.  Exiting.\n"));
3889     GNUNET_SCHEDULER_shutdown ();
3890     return;
3891   }
3892
3893   GNUNET_SCHEDULER_add_shutdown (&cleanup,
3894                                  NULL);
3895   stats = GNUNET_STATISTICS_create ("exit",
3896                                     cfg);
3897   cadet_handle = GNUNET_CADET_connect (cfg,
3898                                        NULL,
3899                                        &clean_channel,
3900                                        handlers);
3901   if (NULL == cadet_handle)
3902   {
3903     GNUNET_SCHEDULER_shutdown ();
3904     return;
3905   }
3906   advertise_dns_exit ();
3907   if (GNUNET_OK !=
3908       setup_exit_helper_args ())
3909   {
3910     GNUNET_SCHEDULER_shutdown ();
3911     return;
3912   }
3913
3914   services = GNUNET_CONTAINER_multihashmap_create (65536,
3915                                                    GNUNET_NO);
3916   connections_map = GNUNET_CONTAINER_multihashmap_create (65536,
3917                                                           GNUNET_NO);
3918   connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
3919   GNUNET_CONFIGURATION_iterate_sections (cfg,
3920                                          &read_service_conf,
3921                                          NULL);
3922
3923   /* Cadet handle acquired, now open ports and announce regular
3924      expressions matching our exit */
3925   if ( (GNUNET_YES == ipv4_enabled) && (GNUNET_YES == ipv4_exit) )
3926   {
3927     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV4_GATEWAY,
3928                         strlen (GNUNET_APPLICATION_PORT_IPV4_GATEWAY),
3929                         &port);
3930     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3931                 "Opening CADET port %s for IPv4 gateway service\n",
3932                 GNUNET_h2s (&port));
3933     GNUNET_CADET_open_port (cadet_handle,
3934                             &port,
3935                             &new_channel,
3936                             NULL);
3937     policy = NULL;
3938     if (GNUNET_OK !=
3939         GNUNET_CONFIGURATION_get_value_string (cfg,
3940                                                "exit",
3941                                                "EXIT_RANGE_IPV4_POLICY",
3942                                                &policy))
3943       regex = NULL;
3944     else
3945       regex = GNUNET_TUN_ipv4policy2regex (policy);
3946     GNUNET_free_non_null (policy);
3947     if (NULL != regex)
3948     {
3949       (void) GNUNET_asprintf (&prefixed_regex,
3950                               "%s%s",
3951                               GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3952                               regex);
3953       regex4 = GNUNET_REGEX_announce (cfg,
3954                                       prefixed_regex,
3955                                       REGEX_REFRESH_FREQUENCY,
3956                                       REGEX_MAX_PATH_LEN_IPV4);
3957       GNUNET_free (regex);
3958       GNUNET_free (prefixed_regex);
3959     }
3960   }
3961
3962   if ( (GNUNET_YES == ipv6_enabled) && (GNUNET_YES == ipv6_exit) )
3963   {
3964     GNUNET_CRYPTO_hash (GNUNET_APPLICATION_PORT_IPV6_GATEWAY,
3965                         strlen (GNUNET_APPLICATION_PORT_IPV6_GATEWAY),
3966                         &port);
3967     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3968                 "Opening CADET port %s for IPv6 gateway service\n",
3969                 GNUNET_h2s (&port));
3970     GNUNET_CADET_open_port (cadet_handle,
3971                             &port,
3972                             &new_channel,
3973                             NULL);
3974     policy = NULL;
3975     if (GNUNET_OK !=
3976         GNUNET_CONFIGURATION_get_value_string (cfg,
3977                                                "exit",
3978                                                "EXIT_RANGE_IPV6_POLICY",
3979                                                &policy))
3980       regex = NULL;
3981     else
3982       regex = GNUNET_TUN_ipv6policy2regex (policy);
3983     GNUNET_free_non_null (policy);
3984     if (NULL != regex)
3985     {
3986       (void) GNUNET_asprintf (&prefixed_regex,
3987                               "%s%s",
3988                               GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
3989                               regex);
3990       regex6 = GNUNET_REGEX_announce (cfg,
3991                                       prefixed_regex,
3992                                       REGEX_REFRESH_FREQUENCY,
3993                                       REGEX_MAX_PATH_LEN_IPV6);
3994       GNUNET_free (regex);
3995       GNUNET_free (prefixed_regex);
3996     }
3997   }
3998   if ((ipv4_exit) || (ipv6_exit))
3999     helper_handle = GNUNET_HELPER_start (GNUNET_NO,
4000                                          "gnunet-helper-exit",
4001                                          exit_argv,
4002                                          &message_token,
4003                                          NULL, NULL);
4004 }
4005
4006
4007 /**
4008  * The main function
4009  *
4010  * @param argc number of arguments from the command line
4011  * @param argv command line arguments
4012  * @return 0 ok, 1 on error
4013  */
4014 int
4015 main (int argc,
4016       char *const *argv)
4017 {
4018   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
4019     GNUNET_GETOPT_OPTION_END
4020   };
4021
4022   if (GNUNET_OK !=
4023       GNUNET_STRINGS_get_utf8_args (argc,
4024                                     argv,
4025                                     &argc,
4026                                     &argv))
4027     return 2;
4028
4029   return (GNUNET_OK ==
4030           GNUNET_PROGRAM_run (argc,
4031                               argv,
4032                               "gnunet-daemon-exit",
4033                               gettext_noop ("Daemon to run to provide an IP exit node for the VPN"),
4034                               options,
4035                               &run,
4036                               NULL)) ? global_ret : 1;
4037 }
4038
4039
4040 /* end of gnunet-daemon-exit.c */