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