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