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