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