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