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