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