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