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