e6730ccdb9739f1504ca7f8283b0b2a312a2d3e4
[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 #include <platform.h>
28 #include <gnunet_common.h>
29 #include <gnunet_program_lib.h>
30 #include <gnunet_protocols.h>
31 #include <gnunet_applications.h>
32 #include <gnunet_mesh_service.h>
33 #include <gnunet_constants.h>
34 #include <string.h>
35
36
37 /* see http://www.iana.org/assignments/ethernet-numbers */
38 #ifndef ETH_P_IPV4
39 #define ETH_P_IPV4 0x0800
40 #endif
41
42 #ifndef ETH_P_IPV6
43 #define ETH_P_IPV6 0x86DD
44 #endif
45
46
47 GNUNET_NETWORK_STRUCT_BEGIN
48 /**
49  * Header from Linux TUN interface.
50  */ 
51 struct tun_header
52 {
53   /**
54    * Some flags (unused).
55    */ 
56   uint16_t flags;
57
58   /**
59    * Here we get an ETH_P_-number.
60    */
61   uint16_t proto;
62 };
63
64 /**
65  * Standard IPv4 header.
66  */
67 struct ip4_header
68 {
69   unsigned header_length:4 GNUNET_PACKED;
70   unsigned version:4 GNUNET_PACKED;
71   uint8_t diff_serv;
72   uint16_t total_length GNUNET_PACKED;
73   uint16_t identification GNUNET_PACKED;
74   unsigned flags:3 GNUNET_PACKED;
75   unsigned fragmentation_offset:13 GNUNET_PACKED;
76   uint8_t ttl;
77   uint8_t protocol;
78   uint16_t checksum GNUNET_PACKED;
79   struct in_addr source_address GNUNET_PACKED;
80   struct in_addr destination_address GNUNET_PACKED;
81 };
82
83 /**
84  * Standard IPv6 header.
85  */
86 struct ip6_header
87 {
88   unsigned traffic_class_h:4 GNUNET_PACKED;
89   unsigned version:4 GNUNET_PACKED;
90   unsigned traffic_class_l:4 GNUNET_PACKED;
91   unsigned flow_label:20 GNUNET_PACKED;
92   uint16_t payload_length GNUNET_PACKED;
93   uint8_t next_header;
94   uint8_t hop_limit;
95   struct in6_addr source_address GNUNET_PACKED;
96   struct in6_addr destination_address GNUNET_PACKED;
97 };
98
99 #define TCP_FLAG_SYN 2
100
101 struct tcp_packet
102 {
103   unsigned spt:16 GNUNET_PACKED;
104   unsigned dpt:16 GNUNET_PACKED;
105   unsigned seq:32 GNUNET_PACKED;
106   unsigned ack:32 GNUNET_PACKED;
107   unsigned off:4 GNUNET_PACKED;
108   unsigned rsv:4 GNUNET_PACKED;
109   unsigned flg:8 GNUNET_PACKED;
110   unsigned wsz:16 GNUNET_PACKED;
111   unsigned crc:16 GNUNET_PACKED;
112   unsigned urg:16 GNUNET_PACKED;
113 };
114
115 /**
116  * UDP packet header.
117  */
118 struct udp_packet
119 {
120   uint16_t spt GNUNET_PACKED;
121   uint16_t dpt GNUNET_PACKED;
122   uint16_t len GNUNET_PACKED;
123   uint16_t crc GNUNET_PACKED;
124 };
125
126 /**
127  * DNS header.
128  */
129 struct dns_header
130 {
131   uint16_t id GNUNET_PACKED;
132   uint16_t flags GNUNET_PACKED;
133   uint16_t qdcount GNUNET_PACKED;
134   uint16_t ancount GNUNET_PACKED;
135   uint16_t nscount GNUNET_PACKED;
136   uint16_t arcount GNUNET_PACKED;
137 };
138 GNUNET_NETWORK_STRUCT_END
139
140 /**
141  * Information about a remote address.
142  */
143 struct remote_addr
144 {
145   /**
146    * AF_INET or AF_INET6.
147    */
148   int af;
149
150   /**
151    * Remote address information.
152    */
153   union
154   {
155     /**
156      * Address, if af is AF_INET.
157      */
158     struct in_addr ipv4;
159
160     /**
161      * Address, if af is AF_INET6.
162      */
163     struct in6_addr ipv6;
164   } address;
165
166   /**
167    * Remote port, in host byte order!
168    */
169   uint16_t port;
170   
171   /**
172    * IPPROTO_TCP or IPPROTO_UDP;
173    */
174   uint8_t proto;
175
176 };
177
178 /**
179  * This struct is saved into the services-hashmap
180  */
181 struct redirect_service
182 {
183
184   /**
185    * Remote address to use for the service.
186    */
187   struct remote_addr address;
188
189   /**
190    * Descriptor for this service (also key of this entry in the service hash map).
191    */
192   GNUNET_HashCode desc;
193
194   /**
195    * Port I am listening on within GNUnet for this service, in host byte order.
196    */
197   uint16_t my_port;
198
199 };
200
201 /**
202  * Information we use to track a connection.
203  */
204 struct redirect_info 
205 {
206
207   /**
208    * Address information for the other party.
209    */
210   struct remote_addr remote_address;
211
212   /**
213    * The source-port of this connection, in host byte order
214    */
215   uint16_t source_port;
216
217 };
218
219 /**
220  * This struct is saved into {tcp,udp}_connections;
221  */
222 struct redirect_state
223 {
224   /**
225    * Mesh tunnel that is used for this connection.
226    */
227   struct GNUNET_MESH_Tunnel *tunnel;
228
229   /**
230    * Heap node for this state in the connections_heap.
231    */
232   struct GNUNET_CONTAINER_HeapNode *heap_node;
233
234   /**
235    * Key this state has in the connections_map.
236    */
237   GNUNET_HashCode state_key;
238
239   /**
240    * Associated service record, or NULL for no service.
241    */
242   struct redirect_service *serv;
243
244   /**
245    * Source port we use for this connection.  FIXME: needed? used?
246    */
247   uint16_t source_port__;
248
249 };
250
251 /**
252  * Queue of messages to a tunnel.
253  */
254 struct tunnel_notify_queue
255 {
256   /**
257    * This is a doubly-linked list.
258    */
259   struct tunnel_notify_queue *next;
260
261   /**
262    * This is a doubly-linked list.
263    */
264   struct tunnel_notify_queue *prev;
265
266   /**
267    * Payload to send via the tunnel.
268    */
269   const void *payload;
270
271   /**
272    * Number of bytes in 'cls'.
273    */
274   size_t len;
275 };
276
277
278 /**
279  * Information we track per mesh tunnel.
280  */
281 struct tunnel_state
282 {
283   struct tunnel_notify_queue *head;
284   struct tunnel_notify_queue *tail;
285   struct GNUNET_MESH_TransmitHandle *th;
286   struct GNUNET_MESH_Tunnel *tunnel;
287 };
288
289
290 /**
291  * The handle to the configuration used throughout the process
292  */
293 static const struct GNUNET_CONFIGURATION_Handle *cfg;
294
295 /**
296  * The handle to the helper
297  */
298 static struct GNUNET_HELPER_Handle *helper_handle;
299
300 /**
301  * Arguments to the exit helper.
302  */
303 static char *exit_argv[7];
304
305 /**
306  * IPv6 prefix (0..127) from configuration file.
307  */
308 static unsigned long long ipv6prefix;
309
310 /**
311  * Final status code.
312  */
313 static int ret;
314
315 /**
316  * The handle to mesh
317  */
318 static struct GNUNET_MESH_Handle *mesh_handle;
319
320 /**
321  * This hashmaps contains the mapping from peer, service-descriptor,
322  * source-port and destination-port to a struct redirect_state
323  */
324 static struct GNUNET_CONTAINER_MultiHashMap *connections_map;
325
326 /**
327  * Heap so we can quickly find "old" connections.
328  */
329 static struct GNUNET_CONTAINER_Heap *connections_heap;
330
331 /**
332  * If there are at least this many connections, old ones will be removed
333  */
334 static long long unsigned int max_connections = 200;
335
336 /**
337  * This hashmaps saves interesting things about the configured UDP services
338  */
339 static struct GNUNET_CONTAINER_MultiHashMap *udp_services;
340
341 /**
342  * This hashmaps saves interesting things about the configured TCP services
343  */
344 static struct GNUNET_CONTAINER_MultiHashMap *tcp_services;
345
346
347 /**
348  * Given IP information about a connection, calculate the respective
349  * hash we would use for the 'connections_map'.
350  *
351  * @param hash resulting hash
352  * @param ri information about the connection
353  */
354 static void
355 hash_redirect_info (GNUNET_HashCode * hash, 
356                     const struct redirect_info *ri)
357 {
358   char *off;
359
360   memset (hash, 0, sizeof (GNUNET_HashCode));
361   /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash */
362   off = (char*) hash;
363   switch (ri->remote_address.af)
364   {
365   case AF_INET:
366     memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr));
367     off += sizeof (struct in_addr);
368     break;
369   case AF_INET6:
370     memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr));
371     off += sizeof (struct in_addr);
372     break;
373   default:
374     GNUNET_assert (0);
375   }
376   memcpy (off, &ri->remote_address.port, sizeof (uint16_t));
377   memcpy (off, &ri->remote_address.proto, sizeof (uint8_t));
378   memcpy (off, &ri->source_port, sizeof (uint8_t));
379 }
380
381
382 /**
383  * Given a service descriptor and a destination port, find the
384  * respective service entry.
385  *
386  * @param service_map map of services (TCP or UDP)
387  * @param desc service descriptor
388  * @param dpt destination port
389  * @return NULL if we are not aware of such a service
390  */
391 struct redirect_service *
392 find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
393               const GNUNET_HashCode *desc,
394               uint16_t dpt)
395 {
396   char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
397
398   memcpy (&key[0], &dpt, sizeof (uint16_t));
399   memcpy (&key[sizeof(uint16_t)], desc, sizeof (GNUNET_HashCode));
400   return GNUNET_CONTAINER_multihashmap_get (service_map,
401                                             (GNUNET_HashCode *) key);
402 }
403
404
405 /**
406  * Free memory associated with a service record.
407  *
408  * @param cls unused
409  * @param key service descriptor
410  * @param value service record to free
411  * @return GNUNET_OK
412  */
413 static int
414 free_service_record (void *cls,
415                      const GNUNET_HashCode *key,
416                      void *value)
417 {
418   struct redirect_service *service = value;
419
420   GNUNET_free (service);
421   return GNUNET_OK;
422 }
423
424
425 /**
426  * Given a service descriptor and a destination port, find the
427  * respective service entry.
428  *
429  * @param service_map map of services (TCP or UDP)
430  * @param name name of the service 
431  * @param dpt destination port
432  * @param service service information record to store (service->desc will be set).
433  */
434 static void
435 store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map,
436                const char *name,
437                uint16_t dpt,
438                struct redirect_service *service)
439 {
440   char key[sizeof (GNUNET_HashCode) + sizeof (uint16_t)];
441   GNUNET_HashCode desc;
442
443   GNUNET_CRYPTO_hash (name, strlen (name) + 1, &desc);
444   service->desc = desc;
445   memcpy (&key[0], &dpt, sizeof (uint16_t));
446   memcpy (&key[sizeof(uint16_t)], &desc, sizeof (GNUNET_HashCode));
447   if (GNUNET_OK !=
448       GNUNET_CONTAINER_multihashmap_put (service_map,
449                                          (GNUNET_HashCode *) key,
450                                          service,
451                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
452   {
453     free_service_record (NULL, (GNUNET_HashCode *) key, service);
454     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
455                 _("Got duplicate service records for `%s:%u'\n"),
456                 name,
457                 (unsigned int) dpt);
458   }
459 }
460
461
462 /**
463  * MESH is ready to receive a message for the tunnel.  Transmit it.
464  *
465  * @param cls the 'struct tunnel_state'.
466  * @param size number of bytes available in buf
467  * @param buf where to copy the message
468  * @return number of bytes copied to buf
469  */
470 static size_t
471 send_to_peer_notify_callback (void *cls, size_t size, void *buf)
472 {
473   struct tunnel_state *s = cls;
474   struct GNUNET_MESH_Tunnel *tunnel = s->tunnel;
475   struct tunnel_notify_queue *tnq;
476
477   s->th = NULL;
478   tnq = s->head;
479   GNUNET_assert (size >= tnq->len);
480   memcpy (buf, tnq->payload, tnq->len);
481   size = tnq->len;
482   GNUNET_CONTAINER_DLL_remove (s->head, 
483                                s->tail,
484                                tnq);  
485   GNUNET_free (tnq);
486   if (NULL != (tnq = s->head))
487     s->th = GNUNET_MESH_notify_transmit_ready (tunnel, 
488                                                GNUNET_NO /* corking */, 
489                                                0 /* priority */,
490                                                GNUNET_TIME_UNIT_FOREVER_REL,
491                                                NULL,
492                                                tnq->len,
493                                                &send_to_peer_notify_callback,
494                                                s);
495   return size;
496 }
497
498
499 /**
500  * Send the given packet via the mesh tunnel.
501  *
502  * @param mesh_tunnel destination
503  * @param payload message to transmit
504  * @param payload_length number of bytes in payload
505  * @param desc descriptor to add 
506  * @param mtype message type to use
507  */
508 static void
509 send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel,
510                             const void *payload,
511                             size_t payload_length,
512                             const GNUNET_HashCode *desc,
513                             uint16_t mtype)
514 {
515   struct tunnel_state *s;
516   struct tunnel_notify_queue *tnq;
517   struct GNUNET_MessageHeader *msg;
518   size_t len;
519   GNUNET_HashCode *dp;
520
521   len = sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + payload_length;
522   if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
523   {
524     GNUNET_break (0);
525     return;
526   }
527   tnq = GNUNET_malloc (sizeof (struct tunnel_notify_queue) + len);
528   tnq->payload = &tnq[1];
529   tnq->len = len;
530   msg = (struct GNUNET_MessageHeader *) &tnq[1];
531   msg->size = htons ((uint16_t) len);
532   msg->type = htons (mtype);
533   dp = (GNUNET_HashCode *) &msg[1];
534   *dp = *desc;
535   memcpy (&dp[1], payload, payload_length);
536   s = GNUNET_MESH_tunnel_get_data (mesh_tunnel);
537   GNUNET_assert (NULL != s);
538   GNUNET_CONTAINER_DLL_insert_tail (s->head, s->tail, tnq);
539   if (NULL == s->th)
540     s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, 0 /* priority */,
541                                                GNUNET_TIME_UNIT_FOREVER_REL,
542                                                NULL, len,
543                                                &send_to_peer_notify_callback,
544                                                s);
545 }
546
547
548 /**
549  * Get our connection tracking state.  Warns if it does not exists,
550  * refreshes the timestamp if it does exist.
551  *
552  * @param af address family
553  * @param protocol IPPROTO_UDP or IPPROTO_TCP
554  * @param destination_ip target IP
555  * @param destination_port target port
556  * @param source_port source port
557  * @return NULL if we have no tracking information for this tuple
558  */
559 static struct redirect_state *
560 get_redirect_state (int af,
561                     int protocol,
562                     const void *destination_ip,
563                     uint16_t destination_port,
564                     uint16_t source_port)
565 {
566   struct redirect_info ri;
567   GNUNET_HashCode state_key;
568   struct redirect_state *state;
569
570   ri.remote_address.af = af;
571   if (af == AF_INET)
572     ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip);
573   else
574     ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip);
575   ri.remote_address.port = destination_port;
576   ri.remote_address.proto = IPPROTO_UDP;
577   ri.source_port = source_port;
578
579   hash_redirect_info (&state_key, &ri);
580   state = GNUNET_CONTAINER_multihashmap_get (connections_map, &state_key);
581   if (NULL == state)
582   {
583     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
584                 _("Packet dropped, have no matching connection information\n"));
585     return NULL;
586   }
587   /* Mark this connection as freshly used */
588   GNUNET_CONTAINER_heap_update_cost (connections_heap, 
589                                      state->heap_node,
590                                      GNUNET_TIME_absolute_get ().abs_value);
591   return state;
592 }
593
594
595 /**
596  * @brief Handles an UDP packet received from the helper.
597  *
598  * @param udp A pointer to the Packet
599  * @param pktlen number of bytes in 'udp'
600  * @param destination_ip destination IP-address
601  * @param af address family (AFINET or AF_INET6)
602  */
603 static void
604 udp_from_helper (const struct udp_packet *udp, 
605                  size_t pktlen,
606                  const void *destination_ip, int af)
607 {
608   struct redirect_state *state;
609   struct GNUNET_MESH_Tunnel *tunnel;
610   GNUNET_HashCode desc;
611
612   if (pktlen < sizeof (struct udp_packet))
613   {
614     /* blame kernel */
615     GNUNET_break (0);
616     return;
617   }
618   if (pktlen != ntohs (udp->len))
619   {
620     /* blame kernel */
621     GNUNET_break (0);
622     return;
623   }
624   state = get_redirect_state (af, IPPROTO_UDP,
625                               destination_ip,
626                               ntohs (udp->dpt), 
627                               ntohs (udp->spt));
628   if (NULL == state)
629     return;
630   tunnel = state->tunnel;
631
632   // FIXME...
633 #if 0
634   if (state->type == SERVICE)
635   {
636     /* check if spt == serv.remote if yes: set spt = serv.myport ("nat") */
637     if (ntohs (udp->spt) == state->serv->remote_port)
638     {
639       udp->spt = htons (state->serv->my_port);
640     }
641     else
642     {
643       /* otherwise the answer came from a different port (tftp does this)
644        * add this new port to the list of all services, so that the packets
645        * coming back from the client to this new port will be routed correctly
646        */
647       struct redirect_service *serv =
648           GNUNET_malloc (sizeof (struct redirect_service));
649       memcpy (serv, state->serv, sizeof (struct redirect_service));
650       serv->my_port = ntohs (udp->spt);
651       serv->remote_port = ntohs (udp->spt);
652       uint16_t *desc = alloca (sizeof (GNUNET_HashCode) + 2);
653
654       memcpy ((GNUNET_HashCode *) (desc + 1), &state->desc,
655               sizeof (GNUNET_HashCode));
656       *desc = ntohs (udp->spt);
657       GNUNET_assert (GNUNET_OK ==
658                      GNUNET_CONTAINER_multihashmap_put (udp_services,
659                                                         (GNUNET_HashCode *)
660                                                         desc, serv,
661                                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
662
663       state->serv = serv;
664     }
665   }
666   
667   if (state->type == SERVICE)
668     memcpy (&desc, &state->desc, sizeof (GNUNET_HashCode));
669   else
670     memcpy (&desc, &state->remote, sizeof (struct remote_addr));
671 #else
672   memset (&desc, 0, sizeof (desc));
673 #endif
674
675   /* send udp-packet back */
676   send_packet_to_mesh_tunnel (tunnel,
677                               udp, pktlen,
678                               &desc,
679                               state->serv != NULL
680                               ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK 
681                               : GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK);
682 }
683
684
685 /**
686  * @brief Handles a TCP packet received from the helper.
687  *
688  * @param tcp A pointer to the Packet
689  * @param pktlen the length of the packet, including its header
690  * @param destination_ip destination IP-address
691  * @param af address family (AFINET or AF_INET6)
692  */
693 static void
694 tcp_from_helper (const struct tcp_packet *tcp, 
695                  size_t pktlen,
696                  const void *destination_ip, int af)
697 {
698   struct redirect_state *state;
699   struct GNUNET_MESH_Tunnel *tunnel;
700   GNUNET_HashCode desc;
701
702   if (pktlen < sizeof (struct tcp_packet))
703   {
704     /* blame kernel */
705     GNUNET_break (0);
706     return;
707   }
708   state = get_redirect_state (af, IPPROTO_TCP,
709                               destination_ip, 
710                               ntohs (tcp->dpt),
711                               ntohs (tcp->spt));
712   if (NULL == state)
713     return;
714   tunnel = state->tunnel;
715
716   // FIXME...
717 #if 0
718   if (state->type == SERVICE)
719   {
720     /* check if spt == serv.remote if yes: set spt = serv.myport ("nat") */
721     if (ntohs (tcp->spt) == state->serv->remote_port)
722     {
723       tcp->spt = htons (state->serv->my_port);
724     }
725     else
726     {
727       // This is an illegal packet.
728       return;
729     }
730   }
731
732   /* send tcp-packet back */
733   if (state->type == SERVICE)
734     memcpy (&desc, &state->desc, sizeof (GNUNET_HashCode));
735   else
736     memcpy (&desc, &state->remote, sizeof (struct remote_addr));
737 #else
738   memset (&desc, 0, sizeof (desc));
739 #endif
740   
741
742   send_packet_to_mesh_tunnel (tunnel,
743                               tcp, pktlen,
744                               &desc,
745                               state->serv != NULL
746                               ? GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK 
747                               : GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK);
748 }
749
750
751 /**
752  * Receive packets from the helper-process
753  *
754  * @param cls unused
755  * @param client unsued
756  * @param message message received from helper
757  */
758 static void
759 message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
760                const struct GNUNET_MessageHeader *message)
761 {
762   const struct tun_header *pkt_tun;
763   size_t size;
764
765   if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
766   {
767     GNUNET_break (0);
768     return;
769   }
770   size = ntohs (message->size);
771   if (size < sizeof (struct tun_header) + sizeof (struct GNUNET_MessageHeader))
772   {
773     GNUNET_break (0);
774     return;
775   }
776   pkt_tun = (const struct tun_header *) &message[1];
777   size -= sizeof (struct tun_header) + sizeof (struct GNUNET_MessageHeader);
778   switch (ntohs (pkt_tun->proto))
779   {
780   case ETH_P_IPV6:
781     {
782       const struct ip6_header *pkt6;
783
784       if (size < sizeof (struct ip6_header))
785       {
786         /* Kernel to blame? */
787         GNUNET_break (0);
788         return;
789       }
790       pkt6 = (struct ip6_header *) &pkt_tun[1];
791       if (size != ntohs (pkt6->payload_length))
792       {
793         /* Kernel to blame? */
794         GNUNET_break (0);
795         return;
796       }
797       size -= sizeof (struct ip6_header);
798       switch (pkt6->next_header)
799       {
800       case IPPROTO_UDP:
801         udp_from_helper ( (const struct udp_packet *) &pkt6[1], size,
802                           &pkt6->destination_address, 
803                           AF_INET6);
804         break;
805       case IPPROTO_TCP:
806         tcp_from_helper ((const struct tcp_packet *) &pkt6[1], size,
807                          &pkt6->destination_address, 
808                          AF_INET6);
809         break;
810       default:
811         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
812                     _("IPv6 packet with unsupported next header received.  Ignored.\n"));
813         return;
814       }
815     }
816     break;
817   case ETH_P_IPV4:
818     {
819       const struct ip4_header *pkt4;
820
821       if (size < sizeof (struct ip4_header))
822       {
823         /* Kernel to blame? */
824         GNUNET_break (0);
825         return;
826       }
827       pkt4 = (const struct ip4_header *) &pkt_tun[1];
828       if (size != ntohs (pkt4->total_length))
829       {
830         /* Kernel to blame? */
831         GNUNET_break (0);
832         return;
833       }
834       if (pkt4->header_length * 4 != sizeof (struct ip4_header))
835       {
836         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
837                     _("IPv4 packet options received.  Ignored.\n"));
838         return;
839       }
840       size -= sizeof (struct ip4_header);
841       switch (pkt4->protocol)
842       {
843       case IPPROTO_UDP:
844         udp_from_helper ((const struct udp_packet *) &pkt4[1], size,
845                          &pkt4->destination_address, AF_INET);
846         break;
847       case IPPROTO_TCP:
848         tcp_from_helper ((const struct tcp_packet *) &pkt4[1], size,
849                          &pkt4->destination_address, AF_INET);
850         break;
851       default:
852         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
853                     _("IPv4 packet with unsupported next header received.  Ignored.\n"));
854         return;
855       }
856     }
857     break;
858   default:
859     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
860                 _("Packet from unknown protocol %u received.  Ignored.\n"),
861                 ntohs (pkt_tun->proto));
862     break;
863   }
864 }
865
866
867
868
869 void
870 prepare_ipv4_packet (size_t len, uint16_t pktlen, void *payload,
871                      uint8_t protocol, void *ipaddress, void *tunnel,
872                      struct redirect_info *state, struct ip4_header *pkt4)
873 {
874   const char *ipv4addr = exit_argv[4];
875   const char *ipv4mask = exit_argv[5];
876   uint32_t tmp;
877   uint32_t tmp2;
878
879   GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &tmp));
880   GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &tmp2));
881   memcpy (&pkt4[1], payload, pktlen);
882   pkt4->version = 4;
883   pkt4->header_length = sizeof (struct ip4_header) / 4;
884   pkt4->diff_serv = 0;
885   pkt4->total_length = htons (sizeof (struct ip4_header) + pktlen);
886   pkt4->identification = 0; // FIXME!
887   pkt4->flags = 0;
888   pkt4->fragmentation_offset = 0;
889   pkt4->ttl = 255;
890   pkt4->protocol = protocol;
891   pkt4->checksum = 0;        /* Will be calculated later */
892
893   memcpy (&pkt4->destination_address, ipaddress, sizeof (struct in_addr));
894
895   /* Generate a new src-address  -- FIXME: not always, right!? */
896
897   /* This should be a noop */
898   tmp = tmp & tmp2;
899   tmp |= ntohl (*((uint32_t *) tunnel)) & (~tmp2);
900
901   pkt4->source_address.s_addr = tmp;
902   pkt4->checksum = GNUNET_CRYPTO_crc16_n (pkt4, sizeof (struct ip4_header));
903
904   // FIXME:  memcpy (&state->addr, &tmp, 4);
905
906   switch (protocol)
907   {
908   case IPPROTO_UDP:
909     {
910       struct udp_packet *pkt4_udp = (struct udp_packet *) &pkt4[1];
911       // FIXME: state->pt = pkt4_udp->spt;
912       pkt4_udp->crc = 0;  /* Optional for IPv4 */
913     }
914     break;
915   case IPPROTO_TCP:
916     {
917       struct tcp_packet *pkt4_tcp = (struct tcp_packet *) &pkt4[1];
918       
919       // FIXME: state->pt = pkt4_tcp->spt;
920       pkt4_tcp->crc = 0;
921       uint32_t sum = 0;
922       sum = GNUNET_CRYPTO_crc16_step (sum, 
923                                       &pkt4->source_address,
924                                       sizeof (struct in_addr) * 2);
925       tmp = (protocol << 16) | (0xffff & pktlen);
926       tmp = htonl (tmp);
927       sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, 4);
928       sum = GNUNET_CRYPTO_crc16_step (sum, & pkt4_tcp, pktlen);
929       pkt4_tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
930     }
931     break;
932   default:
933     GNUNET_assert (0);
934   }
935 }
936
937
938 void
939 prepare_ipv6_packet (size_t len, uint16_t pktlen, void *payload,
940                      uint16_t protocol, void *ipaddress, void *tunnel,
941                      struct redirect_info *state, struct ip6_header *pkt6)
942 {
943   const char *ipv6addr = exit_argv[2];
944   uint32_t tmp;
945
946
947   memcpy (&pkt6[1], payload, pktlen);
948
949   pkt6->version = 6;
950   pkt6->next_header = protocol;
951   pkt6->payload_length = htons (pktlen);
952   pkt6->hop_limit = 64;
953
954   memcpy (&pkt6->destination_address, ipaddress, sizeof (struct in6_addr));
955
956   /* Generate a new src-address
957    * This takes as much from the address of the tunnel as fits into
958    * the host-mask*/
959
960   unsigned long long ipv6prefix_r = (ipv6prefix + 7) / 8;
961
962   inet_pton (AF_INET6, ipv6addr, &pkt6->source_address);
963
964   if (ipv6prefix_r < (16 - sizeof (void *)))
965     ipv6prefix_r = 16 - sizeof (void *);
966
967   unsigned int offset = ipv6prefix_r - (16 - sizeof (void *));
968
969   memcpy ((((char *) &pkt6->source_address)) + ipv6prefix_r,
970           ((char *) &tunnel) + offset, 16 - ipv6prefix_r);
971
972   /* copy the needed information into the state */
973   // FIXME: memcpy (&state->addr, &pkt6->source_address, 16);
974
975   switch (protocol)
976   {
977   case IPPROTO_UDP:
978     {
979       struct udp_packet *pkt6_udp = (struct udp_packet *) &pkt6[1];
980       
981       // FIXME: state->pt = pkt6_udp->spt;      
982       pkt6_udp->crc = 0;
983       uint32_t sum = 0;
984       sum =
985         GNUNET_CRYPTO_crc16_step (sum, & pkt6->source_address,
986                                   16 * 2);
987       tmp = (htons (pktlen) & 0xffff);
988       sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, 4);
989       tmp = htons (pkt6->next_header & 0x00ff);
990       sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, 4);
991       sum =
992         GNUNET_CRYPTO_crc16_step (sum, pkt6_udp,
993                                   ntohs (pkt6_udp->len));
994       pkt6_udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
995     }
996     break;
997   case IPPROTO_TCP:
998     {
999       struct tcp_packet *pkt6_tcp = (struct tcp_packet *) pkt6;
1000       
1001       // FIXME: state->pt = pkt6_tcp->spt;
1002       pkt6_tcp->crc = 0;
1003       uint32_t sum = 0;
1004       
1005       sum =
1006         GNUNET_CRYPTO_crc16_step (sum, & pkt6->source_address, 16 * 2);
1007       tmp = htonl (pktlen);
1008       sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, 4);
1009       tmp = htonl (((pkt6->next_header & 0x000000ff)));
1010       sum = GNUNET_CRYPTO_crc16_step (sum, & tmp, 4);
1011       
1012       sum =
1013         GNUNET_CRYPTO_crc16_step (sum,  pkt6_tcp,
1014                                   ntohs (pkt6->payload_length));
1015       pkt6_tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
1016     }
1017     break;
1018   default:
1019     GNUNET_assert (0);
1020     break;
1021   }
1022 }
1023
1024
1025 /**
1026  * We've just experienced a connection in use.  Track it, or if it is
1027  * already tracked, update the tracking.
1028  *
1029  * @param u_i IP-level connection tracking state
1030  * @param tunnel associated mesh tunnel
1031  * @param desc service descriptor (or NULL)
1032  * @param serv service information
1033  */
1034 void
1035 update_state_map (const struct redirect_info *ri,
1036                   struct GNUNET_MESH_Tunnel *tunnel,
1037                   const GNUNET_HashCode *desc,
1038                   struct redirect_service *serv)
1039 {
1040   struct redirect_state *state;
1041   GNUNET_HashCode state_key;
1042
1043   hash_redirect_info (&state_key,
1044                       ri);
1045   state = GNUNET_CONTAINER_multihashmap_get (connections_map, &state_key);
1046   if (NULL == state)
1047   {
1048     state = GNUNET_malloc (sizeof (struct redirect_state));
1049     state->tunnel = tunnel;
1050     state->state_key = state_key;
1051     state->serv = serv;
1052     // FIXME? if (NULL != desc) state->desc = *desc;
1053     // FIXME? state->redirect_info = *ri;
1054     GNUNET_assert (GNUNET_OK ==
1055                    GNUNET_CONTAINER_multihashmap_put (connections_map, &state_key, state,
1056                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1057     state->heap_node =
1058       GNUNET_CONTAINER_heap_insert (connections_heap,
1059                                     state,
1060                                     GNUNET_TIME_absolute_get ().abs_value);
1061   }
1062   else
1063   {
1064     if (state->tunnel != tunnel) 
1065     {
1066       /* Stats / warning: two tunnels got exactly the same connection state!? */
1067       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1068                   _("Two different mesh tunnels got the same connection state. Oops.\n"));
1069       return;
1070     }
1071     GNUNET_CONTAINER_heap_update_cost (connections_heap,
1072                                        state->heap_node,
1073                                        GNUNET_TIME_absolute_get ().abs_value);
1074   }
1075   while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections)
1076   {
1077     state = GNUNET_CONTAINER_heap_remove_root (connections_heap);
1078     state->heap_node = NULL;
1079     GNUNET_MESH_tunnel_destroy (state->tunnel);
1080     GNUNET_assert (GNUNET_OK ==
1081                    GNUNET_CONTAINER_multihashmap_remove (connections_map,
1082                                                          &state->state_key, 
1083                                                          state));
1084     GNUNET_free (state);
1085   }
1086 }
1087
1088                   
1089
1090
1091 /**
1092  * The messages are one GNUNET_HashCode for the service followed by a struct tcp_packet
1093  */
1094 static int
1095 receive_tcp_service (void *unused GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1096                      void **tunnel_ctx GNUNET_UNUSED,
1097                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1098                      const struct GNUNET_MessageHeader *message,
1099                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1100 {
1101 #if 0
1102   const GNUNET_HashCode *desc = (const GNUNET_HashCode *) &message[1];
1103   const struct tcp_packet *pkt = (const struct tcp_packet *) &desc[1];
1104   uint16_t pkt_len = ntohs (message->size);
1105   struct redirect_service *serv;
1106   struct redirect_info u_i;
1107   GNUNET_HashCode state_key;
1108
1109   /* check that we got at least a valid header */
1110   if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct tcp_packet))
1111   {
1112     GNUNET_break_op (0);
1113     return GNUNET_YES;
1114   }
1115   pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1116
1117   if (NULL == (serv = find_service (tcp_services, desc, ntohs (pkt->dpt))))
1118   {
1119     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1120                 _("No service found for %s on port %d!\n"),
1121                 "TCP",
1122                 ntohs (pkt->dpt));
1123     return GNUNET_YES;
1124   }
1125   pkt->dpt = htons (serv->remote_port);
1126
1127   /* At this point it would be possible to check against some kind of ACL. */
1128
1129   switch (serv->version)
1130     {
1131     case 4:
1132       {
1133         size_t len =
1134           sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header) +
1135           sizeof (struct ip4_header) + pkt_len;       
1136         char buf[len];
1137         struct tun_header *hdr;
1138         struct GNUNET_MessageHeader *mhdr;
1139         
1140         memset (buf, 0, len);
1141         mhdr = (struct GNUNET_MessageHeader*) buf;
1142         hdr = (struct tun_header *) &mhdr[1];
1143         mhdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1144         mhdr->size = htons (len);
1145         hdr->flags = 0;
1146         hdr->proto = htons (0x0800);
1147         prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v4.ip4address,
1148                              tunnel, &u_i, (struct ip4_header *) &hdr[1]);
1149         /* FIXME: here, flow-control with mesh would be nice to have... */
1150         (void) GNUNET_HELPER_send (helper_handle,
1151                                    mhdr,
1152                                    GNUNET_YES,
1153                                    NULL, NULL);
1154         break;
1155       }
1156     case 6:
1157       {
1158         size_t len =
1159           sizeof (struct GNUNET_MessageHeader) + sizeof (struct tun_header) +
1160           sizeof (struct ip6_header) + pkt_len;
1161         char buf[len];
1162         struct tun_header *hdr;
1163         struct GNUNET_MessageHeader *mhdr;
1164         
1165         memset (buf, 0, len);
1166         mhdr = (struct GNUNET_MessageHeader*) buf;
1167         hdr = (struct tun_header *) &mhdr[1];
1168         mhdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
1169         mhdr->size = htons (len);
1170         hdr->flags = 0;
1171         hdr->proto = htons (0x86dd);
1172         prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &serv->v6.ip6address,
1173                              tunnel, &u_i, (struct ip6_header *) buf);
1174             /* FIXME: here, flow-control with mesh would be nice to have... */
1175         (void) GNUNET_HELPER_send (helper_handle,
1176                                    (const struct GNUNET_MessageHeader*) buf,
1177                                    GNUNET_YES,
1178                                    NULL, NULL);
1179
1180         break;
1181       }
1182     default:
1183       GNUNET_assert (0);
1184       break;
1185     }
1186
1187
1188   update_state_map (&u_i, desc, tunnel, serv);
1189 #endif
1190   return GNUNET_YES;
1191 }
1192
1193
1194 static int
1195 receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1196                     void **tunnel_ctx GNUNET_UNUSED,
1197                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1198                     const struct GNUNET_MessageHeader *message,
1199                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1200 {
1201   // FIXME
1202 #if 0
1203   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
1204   struct tcp_packet *pkt = (struct tcp_packet *) (desc + 1);
1205   struct remote_addr *s = (struct remote_addr *) desc;
1206   char *buf;
1207   size_t len;
1208   uint16_t pkt_len =
1209       ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1210       sizeof (GNUNET_HashCode);
1211
1212   struct redirect_state *state = GNUNET_malloc (sizeof (struct redirect_state));
1213
1214   state->tunnel = tunnel;
1215   state->type = REMOTE;
1216   state->hashmap = tcp_connections;
1217   memcpy (&state->remote, s, sizeof (struct remote_addr));
1218
1219   hash_redirect_info (&state->hash, &state->redirect_info, s->addrlen);
1220
1221   if (GNUNET_NO ==
1222       GNUNET_CONTAINER_multihashmap_contains (tcp_connections, &state->hash))
1223   {
1224     GNUNET_CONTAINER_multihashmap_put (tcp_connections, &state->hash, state,
1225                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1226
1227     state->heap_node =
1228         GNUNET_CONTAINER_heap_insert (tcp_connections_heap, state,
1229                                       GNUNET_TIME_absolute_get ().abs_value);
1230
1231     if (GNUNET_CONTAINER_heap_get_size (tcp_connections_heap) >
1232         max_tcp_connections)
1233       GNUNET_SCHEDULER_add_now (collect_connections, tcp_connections_heap);
1234   }
1235   else
1236     GNUNET_free (state);
1237
1238
1239
1240   len =
1241       sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
1242       sizeof (struct ip6_hdr) + pkt_len;
1243   buf = alloca (len);
1244
1245   memset (buf, 0, len);
1246
1247   switch (s->addrlen)
1248   {
1249   case 4:
1250     prepare_ipv4_packet (len, pkt_len, pkt, IPPROTO_TCP, &s->addr, tunnel,
1251                          state, (struct ip4_header *) buf);
1252     break;
1253   case 16:
1254     prepare_ipv6_packet (len, pkt_len, pkt, IPPROTO_TCP, &s->addr, tunnel,
1255                          state, (struct ip6_header *) buf);
1256     break;
1257   default:
1258     GNUNET_free (state);
1259     return GNUNET_SYSERR;
1260   }
1261
1262   /* FIXME: here, flow-control with mesh would be nice to have... */
1263   (void) GNUNET_HELPER_send (helper_handle,
1264                              (const struct GNUNET_MessageHeader*) buf,
1265                              GNUNET_YES,
1266                              NULL, NULL);
1267
1268 #endif
1269   return GNUNET_YES;
1270 }
1271
1272 static int
1273 receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1274                     void **tunnel_ctx GNUNET_UNUSED,
1275                     const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1276                     const struct GNUNET_MessageHeader *message,
1277                     const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1278 {
1279   // FIXME
1280 #if 0
1281   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
1282   struct udp_packet *pkt = (struct udp_packet *) (desc + 1);
1283   struct remote_addr *s = (struct remote_addr *) desc;
1284   char *buf;
1285   size_t len;
1286
1287   GNUNET_assert (ntohs (pkt->len) ==
1288                  ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1289                  sizeof (GNUNET_HashCode));
1290
1291   /* Prepare the state.
1292    * This will be saved in the hashmap, so that the receiving procedure knows
1293    * through which tunnel this connection has to be routed.
1294    */
1295   struct redirect_state *state = GNUNET_malloc (sizeof (struct redirect_state));
1296
1297   state->tunnel = tunnel;
1298   state->hashmap = udp_connections;
1299   state->type = REMOTE;
1300   memcpy (&state->remote, s, sizeof (struct remote_addr));
1301
1302   len =
1303       sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
1304       sizeof (struct ip6_hdr) + ntohs (pkt->len);
1305   buf = alloca (len);
1306
1307   memset (buf, 0, len);
1308
1309   switch (s->addrlen)
1310   {
1311   case 4:
1312     prepare_ipv4_packet (len, ntohs (pkt->len), pkt, IPPROTO_UDP, &s->addr,
1313                          tunnel, state, (struct ip4_header *) buf);
1314     break;
1315   case 16:
1316     prepare_ipv6_packet (len, ntohs (pkt->len), pkt, IPPROTO_UDP, &s->addr,
1317                          tunnel, state, (struct ip6_header *) buf);
1318     break;
1319   default:
1320     GNUNET_assert (0);
1321     break;
1322   }
1323
1324   hash_redirect_info (&state->hash, &state->redirect_info, s->addrlen);
1325
1326   (void) GNUNET_HELPER_send (helper_handle,
1327                              (const struct GNUNET_MessageHeader*) buf,
1328                              GNUNET_YES,
1329                              NULL, NULL);
1330
1331
1332   if (GNUNET_NO ==
1333       GNUNET_CONTAINER_multihashmap_contains (udp_connections, &state->hash))
1334   {
1335     GNUNET_CONTAINER_multihashmap_put (udp_connections, &state->hash, state,
1336                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1337
1338     state->heap_node =
1339         GNUNET_CONTAINER_heap_insert (udp_connections_heap, state,
1340                                       GNUNET_TIME_absolute_get ().abs_value);
1341
1342     if (GNUNET_CONTAINER_heap_get_size (udp_connections_heap) >
1343         max_udp_connections)
1344       GNUNET_SCHEDULER_add_now (collect_connections, udp_connections_heap);
1345   }
1346   else
1347     GNUNET_free (state);
1348 #endif
1349   return GNUNET_YES;
1350 }
1351
1352 /**
1353  * The messages are one GNUNET_HashCode for the service, followed by a struct udp_packet
1354  */
1355 static int
1356 receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1357                      void **tunnel_ctx,
1358                      const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED,
1359                      const struct GNUNET_MessageHeader *message,
1360                      const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED)
1361 {
1362   // FIXME
1363 #if 0
1364   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
1365   struct udp_packet *pkt = (struct udp_packet *) (desc + 1);
1366   uint16_t pkt_len = ntohs (message->size);
1367   struct redirect_service *serv;
1368
1369   /* check that we got at least a valid header */
1370   if (pkt_len < sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + sizeof (struct udp_packet))
1371   {
1372     GNUNET_break_op (0);
1373     return GNUNET_YES;
1374   }
1375   pkt_len -= (sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode));
1376
1377   GNUNET_assert (ntohs (pkt->len) ==
1378                  ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) -
1379                  sizeof (GNUNET_HashCode));
1380
1381   if (NULL == (serv = find_service (udp_services, desc, ntohs (pkt->dpt))))
1382   {
1383     GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
1384                 _("No service found for %s on port %d!\n"),
1385                 "UDP",
1386                 ntohs (pkt->dpt));
1387     return GNUNET_YES;
1388   }
1389   pkt->dpt = htons (serv->remote_port);
1390
1391   /*
1392    * At this point it would be possible to check against some kind of ACL.
1393    */
1394
1395   char *buf;
1396   size_t len;
1397
1398   /* Prepare the state.
1399    * This will be saved in the hashmap, so that the receiving procedure knows
1400    * through which tunnel this connection has to be routed.
1401    */
1402   struct redirect_state *state = GNUNET_malloc (sizeof (struct redirect_state));
1403
1404   state->tunnel = tunnel;
1405   state->serv = serv;
1406   state->type = SERVICE;
1407   state->hashmap = udp_connections;
1408   memcpy (&state->desc, desc, sizeof (GNUNET_HashCode));
1409
1410   len =
1411       sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
1412       sizeof (struct ip6_hdr) + ntohs (pkt->len);
1413   buf = alloca (len);
1414
1415   memset (buf, 0, len);
1416
1417   switch (serv->version)
1418   {
1419   case 4:
1420     prepare_ipv4_packet (len, ntohs (pkt->len), pkt, IPPROTO_UDP,
1421                          &serv->v4.ip4address, tunnel, state,
1422                          (struct ip4_header *) buf);
1423     break;
1424   case 6:
1425     prepare_ipv6_packet (len, ntohs (pkt->len), pkt, IPPROTO_UDP,
1426                          &serv->v6.ip6address, tunnel, state,
1427                          (struct ip6_header *) buf);
1428
1429     break;
1430   default:
1431     GNUNET_assert (0);
1432     break;
1433   }
1434
1435   hash_redirect_info (&state->hash, &state->redirect_info,
1436                       serv->version == 4 ? 4 : 16);
1437
1438   if (GNUNET_NO ==
1439       GNUNET_CONTAINER_multihashmap_contains (udp_connections, &state->hash))
1440   {
1441     GNUNET_CONTAINER_multihashmap_put (udp_connections, &state->hash, state,
1442                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1443
1444     state->heap_node =
1445         GNUNET_CONTAINER_heap_insert (udp_connections_heap, state,
1446                                       GNUNET_TIME_absolute_get ().abs_value);
1447
1448     if (GNUNET_CONTAINER_heap_get_size (udp_connections_heap) >
1449         max_udp_connections)
1450       GNUNET_SCHEDULER_add_now (collect_connections, udp_connections_heap);
1451   }
1452   else
1453     GNUNET_free (state);
1454
1455   (void) GNUNET_HELPER_send (helper_handle,
1456                              (const struct GNUNET_MessageHeader*) buf,
1457                              GNUNET_YES,
1458                              NULL, NULL);
1459 #endif
1460   return GNUNET_YES;
1461 }
1462
1463
1464
1465
1466
1467
1468
1469 /**
1470  * Callback from GNUNET_MESH for new tunnels.
1471  *
1472  * @param cls closure
1473  * @param tunnel new handle to the tunnel
1474  * @param initiator peer that started the tunnel
1475  * @param atsi performance information for the tunnel
1476  * @return initial tunnel context for the tunnel
1477  */
1478 static void *
1479 new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1480             const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED,
1481             const struct GNUNET_ATS_Information *ats GNUNET_UNUSED)
1482 {
1483   struct tunnel_state *s = GNUNET_malloc (sizeof (struct tunnel_state));
1484   
1485   s->tunnel = tunnel;
1486   return s;
1487 }
1488
1489
1490 /**
1491  * Function called by mesh whenever an inbound tunnel is destroyed.
1492  * Should clean up any associated state.
1493  *
1494  * @param cls closure (set from GNUNET_MESH_connect)
1495  * @param tunnel connection to the other end (henceforth invalid)
1496  * @param tunnel_ctx place where local state associated
1497  *                   with the tunnel is stored
1498  */
1499 static void
1500 clean_tunnel (void *cls GNUNET_UNUSED, const struct GNUNET_MESH_Tunnel *tunnel,
1501               void *tunnel_ctx)
1502 {
1503   struct tunnel_state *s = tunnel_ctx;
1504   struct tunnel_notify_queue *tnq;
1505
1506   while (NULL != (tnq = s->head))
1507   {
1508     GNUNET_CONTAINER_DLL_remove (s->head,
1509                                  s->tail,
1510                                  tnq);
1511     GNUNET_free (tnq);
1512   }
1513   if (NULL != s->th)
1514   {
1515     GNUNET_MESH_notify_transmit_ready_cancel (s->th);
1516     s->th = NULL;
1517   }
1518   GNUNET_free (s);
1519 }
1520
1521
1522 /**
1523  * Function that frees everything from a hashmap
1524  *
1525  * @param cls unused
1526  * @param hash key
1527  * @param value value to free
1528  */
1529 static int
1530 free_iterate (void *cls GNUNET_UNUSED,
1531               const GNUNET_HashCode * hash GNUNET_UNUSED, void *value)
1532 {
1533   GNUNET_free (value);
1534   return GNUNET_YES;
1535 }
1536
1537
1538 /**
1539  * Function scheduled as very last function, cleans up after us
1540  */
1541 static void
1542 cleanup (void *cls GNUNET_UNUSED,
1543          const struct GNUNET_SCHEDULER_TaskContext *tskctx)
1544 {
1545   unsigned int i;
1546
1547   if (helper_handle != NULL)
1548   {
1549     GNUNET_HELPER_stop (helper_handle);
1550     helper_handle = NULL;
1551   }
1552   if (mesh_handle != NULL)
1553   {
1554     GNUNET_MESH_disconnect (mesh_handle);
1555     mesh_handle = NULL;
1556   }
1557   if (NULL != connections_map)
1558   {
1559     GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL);
1560     GNUNET_CONTAINER_multihashmap_destroy (connections_map);
1561     connections_map = NULL;
1562   }
1563   if (NULL != connections_heap)
1564   {
1565     GNUNET_CONTAINER_heap_destroy (connections_heap);
1566     connections_heap = NULL;
1567   }
1568   if (NULL != tcp_services)
1569   {
1570     GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL);
1571     GNUNET_CONTAINER_multihashmap_destroy (tcp_services);
1572     tcp_services = NULL;
1573   }
1574   if (NULL != udp_services)
1575   {
1576     GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL);
1577     GNUNET_CONTAINER_multihashmap_destroy (udp_services);
1578     udp_services = NULL;
1579   }
1580   for (i=0;i<5;i++)
1581     GNUNET_free_non_null (exit_argv[i]);
1582 }
1583
1584
1585 /**
1586  * Add services to the service map.
1587  *
1588  * @param proto IPPROTO_TCP or IPPROTO_UDP
1589  * @param cpy copy of the service descriptor (can be mutilated)
1590  * @param name DNS name of the service
1591  */
1592 static void
1593 add_services (int proto,
1594               char *cpy,
1595               const char *name)
1596 {
1597   char *redirect;
1598   char *hostname;
1599   char *hostport;
1600   struct redirect_service *serv;
1601
1602   for (redirect = strtok (cpy, " "); redirect != NULL;
1603        redirect = strtok (NULL, " "))
1604   {
1605     if (NULL == (hostname = strstr (redirect, ":")))
1606     {
1607       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1608                   "option `%s' for domain `%s' is not formatted correctly!\n",
1609                   redirect,
1610                   name);
1611       continue;
1612     }
1613     hostname[0] = '\0';
1614     hostname++;
1615     if (NULL == (hostport = strstr (hostname, ":")))
1616     {
1617       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1618                   "option `%s' for domain `%s' is not formatted correctly!\n",
1619                   redirect,
1620                   name);
1621       continue;
1622     }
1623     hostport[0] = '\0';
1624     hostport++;
1625     
1626     int local_port = atoi (redirect);
1627     int remote_port = atoi (hostport);
1628     
1629     if (!((local_port > 0) && (local_port < 65536)))
1630     {
1631       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1632                   "`%s' is not a valid port number (for domain `%s')!", redirect,
1633                   name);
1634       continue;
1635     }
1636     if (!((remote_port > 0) && (remote_port < 65536)))
1637     {
1638       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1639                   "`%s' is not a valid port number (for domain `%s')!", hostport,
1640                   name);
1641       continue;
1642     }
1643
1644     serv = GNUNET_malloc (sizeof (struct redirect_service));
1645     serv->my_port = (uint16_t) local_port;
1646     serv->address.port = remote_port;
1647     if (0 == strcmp ("localhost4", hostname))
1648     {
1649       const char *ip4addr = exit_argv[4];
1650
1651       serv->address.af = AF_INET;      
1652       GNUNET_assert (1 != inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4));
1653     }
1654     else if (0 == strcmp ("localhost6", hostname))
1655     {
1656       const char *ip6addr = exit_argv[2];
1657
1658       serv->address.af = AF_INET6;
1659       GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6));
1660     }
1661     else
1662     {
1663       struct addrinfo *res;      
1664       int ret;
1665
1666       ret = getaddrinfo (hostname, NULL, NULL, &res);      
1667       if ( (ret != 0) || (res == NULL) )
1668       {
1669         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1670                     _("No addresses found for hostname `%s' of service `%s'!\n"),
1671                     hostname,
1672                     name);
1673         GNUNET_free (serv);
1674         continue;
1675       }
1676       
1677       serv->address.af = res->ai_family;
1678       switch (res->ai_family)
1679       {
1680         case AF_INET:
1681           serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr;
1682           break;
1683         case AF_INET6:
1684           serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
1685           break;
1686       default:
1687         freeaddrinfo (res);
1688         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1689                     _("No IP addresses found for hostname `%s' of service `%s'!\n"),
1690                     hostname,
1691                     name);
1692         GNUNET_free (serv);
1693         continue;
1694       }
1695       freeaddrinfo (res);
1696     }
1697     store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services,
1698                    name,
1699                    local_port,
1700                    serv);
1701   }
1702 }
1703
1704
1705 /**
1706  * Reads the configuration servicecfg and populates udp_services
1707  *
1708  * @param cls unused
1709  * @param section name of section in config, equal to hostname
1710  */
1711 static void
1712 read_service_conf (void *cls GNUNET_UNUSED, const char *section)
1713 {
1714   char *cpy;
1715
1716   if ((strlen (section) < 8) ||
1717       (0 != strcmp (".gnunet.", section + (strlen (section) - 8))))
1718     return;
1719   if (GNUNET_OK ==
1720       GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS",
1721                                              &cpy))
1722   {
1723     add_services (IPPROTO_UDP, cpy, section);
1724     GNUNET_free (cpy);
1725   }
1726   if (GNUNET_OK ==
1727       GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS",
1728                                              &cpy))
1729   {
1730     add_services (IPPROTO_TCP, cpy, section);
1731     GNUNET_free (cpy);
1732   }
1733 }
1734
1735
1736 /**
1737  * @brief Main function that will be run by the scheduler.
1738  *
1739  * @param cls closure
1740  * @param args remaining command-line arguments
1741  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1742  * @param cfg_ configuration
1743  */
1744 static void
1745 run (void *cls, char *const *args GNUNET_UNUSED,
1746      const char *cfgfile GNUNET_UNUSED,
1747      const struct GNUNET_CONFIGURATION_Handle *cfg_)
1748 {
1749   static struct GNUNET_MESH_MessageHandler handlers[] = {
1750     {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP, 0},
1751     {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP, 0},
1752     {NULL, 0, 0},
1753     {NULL, 0, 0},
1754     {NULL, 0, 0}
1755   };
1756
1757   static GNUNET_MESH_ApplicationType apptypes[] = {
1758     GNUNET_APPLICATION_TYPE_END,
1759     GNUNET_APPLICATION_TYPE_END,
1760     GNUNET_APPLICATION_TYPE_END
1761   };
1762   unsigned int handler_idx;
1763   unsigned int app_idx;
1764   int udp;
1765   int tcp;
1766   char *ifname;
1767   char *ipv6addr;
1768   char *ipv6prefix_s;
1769   char *ipv4addr;
1770   char *ipv4mask;
1771   struct in_addr v4;
1772   struct in6_addr v6;
1773
1774   cfg = cfg_;
1775   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1776   if (GNUNET_OK !=
1777       GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS",
1778                                              &max_connections))
1779     max_connections = 1024;
1780   exit_argv[0] = GNUNET_strdup ("exit-gnunet");
1781   if (GNUNET_SYSERR ==
1782       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IFNAME", &ifname))
1783   {
1784     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1785                 "No entry 'IFNAME' in configuration!\n");
1786     GNUNET_SCHEDULER_shutdown ();
1787     return;
1788   }
1789   exit_argv[1] = ifname;
1790   if ( (GNUNET_SYSERR ==
1791         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR",
1792                                                &ipv6addr) ||
1793         (1 != inet_pton (AF_INET6, ipv6addr, &v6))) )
1794   {
1795     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1796                 "No valid entry 'IPV6ADDR' in configuration!\n");
1797     GNUNET_SCHEDULER_shutdown ();
1798     return;
1799   }
1800   exit_argv[2] = ipv6addr;
1801   if (GNUNET_SYSERR ==
1802       GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX",
1803                                              &ipv6prefix_s))
1804   {
1805     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1806                 "No entry 'IPV6PREFIX' in configuration!\n");
1807     GNUNET_SCHEDULER_shutdown ();
1808     return;
1809   }
1810   exit_argv[3] = ipv6prefix_s;
1811   if ( (GNUNET_OK !=
1812         GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
1813                                                "IPV6PREFIX",
1814                                                &ipv6prefix)) ||
1815        (ipv6prefix >= 127) )
1816   {
1817     GNUNET_SCHEDULER_shutdown ();
1818     return;
1819   }
1820
1821   if ( (GNUNET_SYSERR ==
1822         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR",
1823                                                &ipv4addr) ||
1824         (1 != inet_pton (AF_INET, ipv4addr, &v4))) )
1825   {
1826     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1827                 "No valid entry for 'IPV4ADDR' in configuration!\n");
1828     GNUNET_SCHEDULER_shutdown ();
1829     return;
1830   }
1831   exit_argv[4] = ipv4addr;
1832   if ( (GNUNET_SYSERR ==
1833         GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK",
1834                                                &ipv4mask) ||
1835         (1 != inet_pton (AF_INET, ipv4mask, &v4))) )
1836   {
1837     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1838                 "No valid entry 'IPV4MASK' in configuration!\n");
1839     GNUNET_SCHEDULER_shutdown ();
1840     return;
1841   }
1842   exit_argv[5] = ipv4mask;
1843   exit_argv[6] = NULL;
1844
1845   app_idx = 0;
1846   handler_idx = 2;
1847   udp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_UDP");
1848   tcp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_TCP");
1849   if (GNUNET_YES == udp)
1850   {
1851     handlers[handler_idx].callback = &receive_udp_remote;
1852     handlers[handler_idx].expected_size = 0;
1853     handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP;
1854     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
1855     handler_idx++;
1856     app_idx++;
1857   }
1858
1859   if (GNUNET_YES == tcp)
1860   {
1861     handlers[handler_idx].callback = &receive_tcp_remote;
1862     handlers[handler_idx].expected_size = 0;
1863     handlers[handler_idx].type = GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP;
1864     apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
1865     handler_idx++;
1866     app_idx++;
1867   }
1868   udp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1869   tcp_services = GNUNET_CONTAINER_multihashmap_create (65536);
1870   GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL);
1871
1872   connections_map = GNUNET_CONTAINER_multihashmap_create (65536);
1873   connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1874   mesh_handle 
1875     = GNUNET_MESH_connect (cfg, 42 /* queue size */, NULL, 
1876                            &new_tunnel, 
1877                            &clean_tunnel, handlers,
1878                            apptypes);
1879   if (NULL == mesh_handle)
1880   {
1881     GNUNET_SCHEDULER_shutdown ();
1882     return;
1883   }
1884   helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", 
1885                                        exit_argv,
1886                                        &message_token, NULL);
1887 }
1888
1889
1890 /**
1891  * The main function
1892  *
1893  * @param argc number of arguments from the command line
1894  * @param argv command line arguments
1895  * @return 0 ok, 1 on error
1896  */
1897 int
1898 main (int argc, char *const *argv)
1899 {
1900   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
1901     GNUNET_GETOPT_OPTION_END
1902   };
1903
1904   return (GNUNET_OK ==
1905           GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit",
1906                               gettext_noop
1907                               ("Daemon to run to provide an IP exit node for the VPN"),
1908                               options, &run, NULL)) ? ret : 1;
1909 }
1910
1911
1912 /* end of gnunet-daemon-exit.c */