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