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