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