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