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