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