make the log output shorter
[oweals/gnunet.git] / src / vpn / gnunet-daemon-vpn.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 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 vpn/gnunet-daemon-vpn.c
23  * @brief
24  * @author Philipp Toelke
25  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_program_lib.h"
29 #include "gnunet-vpn-packet.h"
30 #include "gnunet_common.h"
31 #include "gnunet_protocols.h"
32 #include "gnunet_applications.h"
33 #include <gnunet_mesh_service.h>
34 #include "gnunet_client_lib.h"
35 #include "gnunet_container_lib.h"
36 #include "gnunet_constants.h"
37 #include <block_dns.h>
38 #include "gnunet-daemon-vpn-helper.h"
39 #include "gnunet-daemon-vpn-dns.h"
40 #include "gnunet-daemon-vpn.h"
41 #include "gnunet-vpn-checksum.h"
42
43 const struct GNUNET_CONFIGURATION_Handle *cfg;
44 struct GNUNET_MESH_Handle *mesh_handle;
45 struct GNUNET_CONTAINER_MultiHashMap* hashmap;
46 static struct GNUNET_CONTAINER_Heap *heap;
47
48 /**
49  * If there are at least this many address-mappings, old ones will be removed
50  */
51 static long long unsigned int max_mappings = 200;
52
53 /**
54  * Final status code.
55  */
56 static int ret;
57
58 /**
59  * This hashmap contains the mapping from peer, service-descriptor,
60  * source-port and destination-port to a socket
61  */
62 static struct GNUNET_CONTAINER_MultiHashMap *udp_connections;
63
64 /**
65  * Function scheduled as very last function, cleans up after us
66  *{{{
67  */
68 static void
69 cleanup(void* cls __attribute__((unused)), const struct GNUNET_SCHEDULER_TaskContext* tskctx) {
70     GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
71
72     /* stop the helper */
73     cleanup_helper(helper_handle);
74
75     /* close the connection to the service-dns */
76     if (dns_connection != NULL)
77       {
78         GNUNET_CLIENT_disconnect (dns_connection, GNUNET_NO);
79         dns_connection = NULL;
80       }
81
82     if (mesh_handle != NULL)
83       {
84         GNUNET_MESH_disconnect(mesh_handle);
85         mesh_handle = NULL;
86       }
87 }
88 /*}}}*/
89
90 /**
91  * @return the hash of the IP-Address if a mapping exists, NULL otherwise
92  */
93 GNUNET_HashCode*
94 address_mapping_exists(unsigned char addr[]) {
95     GNUNET_HashCode* key = GNUNET_malloc(sizeof(GNUNET_HashCode));
96     unsigned char* k = (unsigned char*)key;
97     memset(key, 0, sizeof(GNUNET_HashCode));
98     unsigned int i;
99     for (i = 0; i < 16; i++)
100         k[15-i] = addr[i];
101
102     if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(hashmap, key))
103       return key;
104     else
105       {
106         GNUNET_free(key);
107         return NULL;
108       }
109 }
110
111 static void
112 collect_mappings(void* cls __attribute__((unused)), const struct GNUNET_SCHEDULER_TaskContext* tc) {
113     if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
114       return;
115
116     struct map_entry* me = GNUNET_CONTAINER_heap_remove_root(heap);
117
118     /* This is free()ed memory! */
119     me->heap_node = NULL;
120
121     /* FIXME! GNUNET_MESH_close_tunnel(me->tunnel); */
122
123     GNUNET_CONTAINER_multihashmap_remove(hashmap, &me->hash, me);
124
125     GNUNET_free(me);
126 }
127
128 void
129 send_icmp_response(void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) {
130     if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
131       return;
132
133     struct ip6_icmp* request = cls;
134
135     struct ip6_icmp* response = alloca(ntohs(request->shdr.size));
136     GNUNET_assert(response != NULL);
137     memset(response, 0, ntohs(request->shdr.size));
138
139     response->shdr.size = request->shdr.size;
140     response->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
141
142     response->tun.flags = 0;
143     response->tun.type = htons(0x86dd);
144
145     response->ip6_hdr.hoplmt = 255;
146     response->ip6_hdr.paylgth = request->ip6_hdr.paylgth;
147     response->ip6_hdr.nxthdr = 0x3a;
148     response->ip6_hdr.version = 6;
149     memcpy(&response->ip6_hdr.sadr, &request->ip6_hdr.dadr, 16);
150     memcpy(&response->ip6_hdr.dadr, &request->ip6_hdr.sadr, 16);
151
152     response->icmp_hdr.code = 0;
153     response->icmp_hdr.type = 0x81;
154
155     /* Magic, more Magic! */
156     response->icmp_hdr.chks = request->icmp_hdr.chks - 0x1;
157
158     /* Copy the rest of the packet */
159     memcpy(response+1, request+1, ntohs(request->shdr.size) - sizeof(struct ip6_icmp));
160
161     write_to_helper(response, ntohs(response->shdr.size));
162
163     GNUNET_free(request);
164 }
165
166 /**
167  * cls is the pointer to a GNUNET_MessageHeader that is
168  * followed by the service-descriptor and the packet that should be sent;
169  */
170 static size_t
171 send_pkt_to_peer_notify_callback (void *cls, size_t size, void *buf)
172 {
173   struct GNUNET_MESH_Tunnel **tunnel = cls;
174   struct GNUNET_MessageHeader *hdr =
175     (struct GNUNET_MessageHeader *) (tunnel + 1);
176   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "send_pkt_to_peer_notify_callback: buf = %x; size = %u;\n", buf, size);
177   GNUNET_assert (size >= ntohs (hdr->size));
178   memcpy (buf, hdr, ntohs (hdr->size));
179   size = ntohs(hdr->size);
180   GNUNET_free (cls);
181   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent!\n");
182   return size;
183 }
184
185 unsigned int
186 port_in_ports (uint64_t ports, uint16_t port)
187 {
188   uint16_t *ps = (uint16_t *) & ports;
189   return ps[0] == port || ps[1] == port || ps[2] == port || ps[3] == port;
190 }
191
192 void
193 send_pkt_to_peer (void *cls, 
194                   const struct GNUNET_PeerIdentity *peer,
195                   const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused)))
196 {
197   /* peer == NULL means that all peers in this request are connected */
198   if (peer == NULL) return;
199   struct GNUNET_MESH_Tunnel **tunnel = cls;
200   struct GNUNET_MessageHeader *hdr =
201     (struct GNUNET_MessageHeader *) (tunnel + 1);
202
203   GNUNET_assert(NULL != tunnel);
204   GNUNET_assert(NULL != *tunnel);
205
206   GNUNET_MESH_notify_transmit_ready (*tunnel,
207                                      GNUNET_NO,
208                                      42,
209                                      GNUNET_TIME_relative_divide(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2),
210                                      (const struct GNUNET_PeerIdentity *)NULL,
211                                      ntohs(hdr->size),
212                                      send_pkt_to_peer_notify_callback,
213                                      cls);
214 }
215
216 /**
217  * Create a new Address from an answer-packet
218  */
219 void
220 new_ip6addr(unsigned char* buf, const GNUNET_HashCode *peer, const GNUNET_HashCode *service_desc) { /* {{{ */
221     char* ipv6addr;
222     unsigned long long ipv6prefix;
223     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr));
224     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "vpn", "IPV6PREFIX", &ipv6prefix));
225     GNUNET_assert(ipv6prefix < 127);
226     ipv6prefix = (ipv6prefix + 7)/8;
227
228     inet_pton (AF_INET6, ipv6addr, buf);
229     GNUNET_free(ipv6addr);
230
231     int peer_length = 16 - ipv6prefix - 6;
232     if (peer_length <= 0)
233       peer_length = 0;
234
235     int service_length = 16 - ipv6prefix - peer_length;
236     if (service_length <= 0)
237       service_length = 0;
238
239     memcpy(buf+ipv6prefix, service_desc, service_length);
240     memcpy(buf+ipv6prefix+service_length, peer, peer_length);
241 }
242 /*}}}*/
243
244
245 /**
246  * Create a new Address from an answer-packet
247  */
248 void
249 new_ip6addr_remote (unsigned char *buf, unsigned char *addr, char addrlen)
250 {                               /* {{{ */
251   char *ipv6addr;
252   unsigned long long ipv6prefix;
253   GNUNET_assert (GNUNET_OK ==
254                  GNUNET_CONFIGURATION_get_value_string (cfg, "vpn",
255                                                         "IPV6ADDR",
256                                                         &ipv6addr));
257   GNUNET_assert (GNUNET_OK ==
258                  GNUNET_CONFIGURATION_get_value_number (cfg, "vpn",
259                                                         "IPV6PREFIX",
260                                                         &ipv6prefix));
261   GNUNET_assert (ipv6prefix < 127);
262   ipv6prefix = (ipv6prefix + 7) / 8;
263
264   inet_pton (AF_INET6, ipv6addr, buf);
265   GNUNET_free (ipv6addr);
266
267   int local_length = 16 - ipv6prefix;
268
269   memcpy (buf + ipv6prefix, addr, GNUNET_MAX (addrlen, local_length));
270 }
271 /*}}}*/
272
273 /**
274  * This gets scheduled with cls pointing to an answer_packet and does everything
275  * needed in order to send it to the helper.
276  *
277  * At the moment this means "inventing" and IPv6-Address for .gnunet-services and
278  * doing nothing for "real" services.
279  */
280 void
281 process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) {
282     if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
283       return;
284
285     struct answer_packet* pkt = cls;
286     struct answer_packet_list* list;
287
288     /* This answer is about a .gnunet-service
289      *
290      * It contains an almost complete DNS-Response, we have to fill in the ip
291      * at the offset pkt->addroffset
292      */
293     if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_SERVICE)
294       {
295         pkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP;
296
297         GNUNET_HashCode key;
298         memset(&key, 0, sizeof(GNUNET_HashCode));
299
300         unsigned char* c = ((unsigned char*)pkt)+ntohs(pkt->addroffset);
301         unsigned char* k = (unsigned char*)&key;
302         new_ip6addr(c, &pkt->service_descr.peer, &pkt->service_descr.service_descriptor);
303         /*
304          * Copy the newly generated ip-address to the key backwarts (as only the first part is hashed)
305          */
306         unsigned int i;
307         for (i = 0; i < 16; i++)
308             k[15-i] = c[i];
309
310         uint16_t namelen = strlen((char*)pkt->data+12)+1;
311
312         struct map_entry* value = GNUNET_malloc(sizeof(struct map_entry) + namelen);
313         char* name = (char*)(value +1);
314
315         value->namelen = namelen;
316         memcpy(name, pkt->data+12, namelen);
317
318         memcpy(&value->desc, &pkt->service_descr, sizeof(struct GNUNET_vpn_service_descriptor));
319
320         memset(value->additional_ports, 0, 8192);
321
322         memcpy(&value->hash, &key, sizeof(GNUNET_HashCode));
323
324         if (GNUNET_NO ==
325             GNUNET_CONTAINER_multihashmap_contains (hashmap, &key))
326           {
327             GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value,
328                                                GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
329
330             value->heap_node = GNUNET_CONTAINER_heap_insert (heap, value,
331                                                              GNUNET_TIME_absolute_get ().abs_value);
332             if (GNUNET_CONTAINER_heap_get_size(heap) > max_mappings)
333               GNUNET_SCHEDULER_add_now(collect_mappings, NULL);
334           }
335         else
336           GNUNET_free(value);
337
338
339         list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*));
340
341         memcpy(&list->pkt, pkt, htons(pkt->hdr.size));
342
343       }
344     else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_REV)
345       {
346         GNUNET_HashCode key;
347         memset(&key, 0, sizeof key);
348         unsigned char* k = (unsigned char*)&key;
349         unsigned char* s = pkt->data+12;
350         int i = 0;
351         /* Whoever designed the reverse IPv6-lookup is batshit insane */
352         for (i = 0; i < 16; i++)
353           {
354             unsigned char c1 = s[(4*i)+1];
355             unsigned char c2 = s[(4*i)+3];
356             if (c1 <= '9')
357               k[i] = c1 - '0';
358             else
359               k[i] = c1 - 87; /* 87 is the difference between 'a' and 10 */
360             if (c2 <= '9')
361               k[i] += 16*(c2 - '0');
362             else
363               k[i] += 16*(c2 - 87);
364           }
365
366         struct map_entry* map_entry = GNUNET_CONTAINER_multihashmap_get(hashmap, &key);
367         uint16_t offset = ntohs(pkt->addroffset);
368
369         if (map_entry == NULL)
370           {
371             GNUNET_free(pkt);
372             return;
373           }
374
375         GNUNET_CONTAINER_heap_update_cost (heap, map_entry->heap_node,
376                                            GNUNET_TIME_absolute_get ().abs_value);
377
378
379         unsigned short namelen = htons(map_entry->namelen);
380         char* name = (char*)(map_entry + 1);
381
382         list = GNUNET_malloc(2*sizeof(struct answer_packet_list*) + offset + 2 + ntohs(namelen));
383
384         struct answer_packet* rpkt = &list->pkt;
385
386         /* The offset points to the first byte belonging to the address */
387         memcpy(rpkt, pkt, offset - 1);
388
389         rpkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP;
390         rpkt->hdr.size = ntohs(offset + 2 + ntohs(namelen));
391
392         memcpy(((char*)rpkt)+offset, &namelen, 2);
393         memcpy(((char*)rpkt)+offset+2, name, ntohs(namelen));
394
395       }
396     else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_IP)
397       {
398         list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*));
399         memcpy(&list->pkt, pkt, htons(pkt->hdr.size));
400       }
401     else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_REMOTE)
402       {
403         pkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP;
404
405         GNUNET_HashCode key;
406         memset(&key, 0, sizeof(GNUNET_HashCode));
407
408         unsigned char* c = ((unsigned char*)pkt)+ntohs(pkt->addroffset);
409         new_ip6addr_remote(c, pkt->addr, pkt->addrsize);
410         unsigned char* k = (unsigned char*)&key;
411         /*
412          * Copy the newly generated ip-address to the key backwards (as only the first part is used in the hash-table)
413          */
414         unsigned int i;
415         for (i = 0; i < 16; i++)
416             k[15-i] = c[i];
417
418         uint16_t namelen = strlen((char*)pkt->data+12)+1;
419
420         struct map_entry* value = GNUNET_malloc(sizeof(struct map_entry) + namelen);
421         char* name = (char*)(value +1);
422
423         value->namelen = namelen;
424         memcpy(name, pkt->data+12, namelen);
425
426         value->addrlen = pkt->addrsize;
427         memcpy(&value->addr, &pkt->addr, pkt->addrsize);
428         memset(value->additional_ports, 0, 8192);
429
430         memcpy(&value->hash, &key, sizeof(GNUNET_HashCode));
431
432         if (GNUNET_NO ==
433             GNUNET_CONTAINER_multihashmap_contains (hashmap, &key))
434           {
435             GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value,
436                                                GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
437             value->heap_node = GNUNET_CONTAINER_heap_insert (heap, value,
438                                                              GNUNET_TIME_absolute_get ().abs_value);
439             if (GNUNET_CONTAINER_heap_get_size(heap) > max_mappings)
440               GNUNET_SCHEDULER_add_now(collect_mappings, NULL);
441           }
442         else
443           GNUNET_free(value);
444
445         list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*));
446
447         memcpy(&list->pkt, pkt, htons(pkt->hdr.size));
448       }
449     else
450       {
451         GNUNET_break(0);
452         GNUNET_free(pkt);
453         return;
454       }
455
456     GNUNET_free(pkt);
457
458     GNUNET_CONTAINER_DLL_insert_after(answer_proc_head, answer_proc_tail, answer_proc_tail, list);
459
460     schedule_helper_write(GNUNET_TIME_UNIT_FOREVER_REL, NULL);
461
462     return;
463 }
464
465 /**
466  * Sets a bit active in a bitArray.
467  *
468  * @param bitArray memory area to set the bit in
469  * @param bitIdx which bit to set
470  */
471 void
472 setBit (char *bitArray, unsigned int bitIdx)
473 {
474   size_t arraySlot;
475   unsigned int targetBit;
476
477   arraySlot = bitIdx / 8;
478   targetBit = (1L << (bitIdx % 8));
479   bitArray[arraySlot] |= targetBit;
480 }
481
482 /**
483  * Clears a bit from bitArray.
484  *
485  * @param bitArray memory area to set the bit in
486  * @param bitIdx which bit to unset
487  */
488 void
489 clearBit (char *bitArray, unsigned int bitIdx)
490 {
491   size_t slot;
492   unsigned int targetBit;
493
494   slot = bitIdx / 8;
495   targetBit = (1L << (bitIdx % 8));
496   bitArray[slot] = bitArray[slot] & (~targetBit);
497 }
498
499 /**
500  * Checks if a bit is active in the bitArray
501  *
502  * @param bitArray memory area to set the bit in
503  * @param bitIdx which bit to test
504  * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
505  */
506 int
507 testBit (char *bitArray, unsigned int bitIdx)
508 {
509   size_t slot;
510   unsigned int targetBit;
511
512   slot = bitIdx / 8;
513   targetBit = (1L << (bitIdx % 8));
514   if (bitArray[slot] & targetBit)
515     return GNUNET_YES;
516   else
517     return GNUNET_NO;
518 }
519
520 /**
521  * @brief Add the port to the list of additional ports in the map_entry
522  *
523  * @param me the map_entry
524  * @param port the port in host-byte-order
525  */
526 static void
527 add_additional_port (struct map_entry *me, uint16_t port)
528 {
529   setBit(me->additional_ports, port);
530 }
531
532 static int
533 receive_udp_back (void *cls __attribute__((unused)), struct GNUNET_MESH_Tunnel* tunnel,
534                   void **tunnel_ctx __attribute__((unused)),
535                   const struct GNUNET_PeerIdentity *sender __attribute__((unused)),
536                   const struct GNUNET_MessageHeader *message,
537                   const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused)))
538 {
539   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
540   struct remote_addr* s = (struct remote_addr*)desc;
541   struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
542   const struct GNUNET_PeerIdentity* other = GNUNET_MESH_get_peer(tunnel);
543
544   size_t size = sizeof(struct ip6_udp) + ntohs(pkt->len) - 1 - sizeof(struct udp_pkt);
545
546   struct ip6_udp* pkt6 = alloca(size);
547
548   GNUNET_assert(pkt6 != NULL);
549
550   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK)
551     new_ip6addr(pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
552   else
553     new_ip6addr_remote(pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
554
555   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Relaying calc:%d gnu:%d udp:%d bytes!\n", size, ntohs(message->size), ntohs(pkt->len));
556
557   pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
558   pkt6->shdr.size = htons(size);
559
560   pkt6->tun.flags = 0;
561   pkt6->tun.type = htons(0x86dd);
562
563   pkt6->ip6_hdr.version = 6;
564   pkt6->ip6_hdr.tclass_h = 0;
565   pkt6->ip6_hdr.tclass_l = 0;
566   pkt6->ip6_hdr.flowlbl = 0;
567   pkt6->ip6_hdr.paylgth = pkt->len;
568   pkt6->ip6_hdr.nxthdr = 0x11;
569   pkt6->ip6_hdr.hoplmt = 0xff;
570
571   {
572     char* ipv6addr;
573     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr));
574     inet_pton (AF_INET6, ipv6addr, pkt6->ip6_hdr.dadr);
575     GNUNET_free(ipv6addr);
576   }
577   memcpy(&pkt6->udp_hdr, pkt, ntohs(pkt->len));
578
579   GNUNET_HashCode* key = address_mapping_exists(pkt6->ip6_hdr.sadr);
580   GNUNET_assert (key != NULL);
581
582   struct map_entry *me = GNUNET_CONTAINER_multihashmap_get(hashmap, key);
583   GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
584                                      GNUNET_TIME_absolute_get ().abs_value);
585
586   GNUNET_free(key);
587
588   GNUNET_assert (me != NULL);
589   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK)
590     {
591       GNUNET_assert (me->desc.service_type & htonl(GNUNET_DNS_SERVICE_TYPE_UDP));
592       if (!port_in_ports(me->desc.ports, pkt6->udp_hdr.spt) &&
593           !testBit(me->additional_ports, ntohs(pkt6->udp_hdr.spt))) {
594           add_additional_port(me, ntohs(pkt6->udp_hdr.spt));
595       }
596     }
597
598   pkt6->udp_hdr.crc = 0;
599   uint32_t sum = 0;
600   sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.sadr, 16);
601   sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.dadr, 16);
602   uint32_t tmp = (pkt6->udp_hdr.len & 0xffff);
603   sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4);
604   tmp = htons(((pkt6->ip6_hdr.nxthdr & 0x00ff)));
605   sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4);
606
607   sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->udp_hdr, ntohs(pkt->len));
608   pkt6->udp_hdr.crc = calculate_checksum_end(sum);
609
610   write_to_helper(pkt6, size);
611
612   return GNUNET_OK;
613 }
614
615 static int
616 receive_tcp_back (void *cls __attribute__((unused)), struct GNUNET_MESH_Tunnel* tunnel,
617                   void **tunnel_ctx __attribute__((unused)),
618                   const struct GNUNET_PeerIdentity *sender __attribute__((unused)),
619                   const struct GNUNET_MessageHeader *message,
620                   const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused)))
621 {
622   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
623   struct remote_addr* s = (struct remote_addr*)desc;
624   struct tcp_pkt *pkt = (struct tcp_pkt *) (desc + 1);
625   const struct GNUNET_PeerIdentity* other = GNUNET_MESH_get_peer(tunnel);
626
627   size_t pktlen = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader) - sizeof(GNUNET_HashCode);
628   size_t size = pktlen + sizeof(struct ip6_tcp) - 1;
629
630   struct ip6_tcp* pkt6 = alloca(size);
631   memset(pkt6, 0, size);
632
633   GNUNET_assert(pkt6 != NULL);
634
635   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK)
636     new_ip6addr(pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
637   else
638     new_ip6addr_remote(pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
639
640   pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
641   pkt6->shdr.size = htons(size);
642
643   pkt6->tun.flags = 0;
644   pkt6->tun.type = htons(0x86dd);
645
646   pkt6->ip6_hdr.version = 6;
647   pkt6->ip6_hdr.tclass_h = 0;
648   pkt6->ip6_hdr.tclass_l = 0;
649   pkt6->ip6_hdr.flowlbl = 0;
650   pkt6->ip6_hdr.paylgth = htons(pktlen);
651   pkt6->ip6_hdr.nxthdr = 0x06;
652   pkt6->ip6_hdr.hoplmt = 0xff;
653
654   {
655     char* ipv6addr;
656     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr));
657     inet_pton (AF_INET6, ipv6addr, pkt6->ip6_hdr.dadr);
658     GNUNET_free(ipv6addr);
659   }
660   memcpy(&pkt6->tcp_hdr, pkt, pktlen);
661
662   GNUNET_HashCode* key = address_mapping_exists(pkt6->ip6_hdr.sadr);
663   GNUNET_assert (key != NULL);
664
665   struct map_entry *me = GNUNET_CONTAINER_multihashmap_get(hashmap, key);
666   GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
667                                      GNUNET_TIME_absolute_get ().abs_value);
668
669   GNUNET_free(key);
670
671   GNUNET_assert (me != NULL);
672   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK)
673     GNUNET_assert (me->desc.service_type & htonl(GNUNET_DNS_SERVICE_TYPE_TCP));
674
675   pkt6->tcp_hdr.crc = 0;
676   uint32_t sum = 0;
677   uint32_t tmp;
678   sum =
679     calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
680   sum =
681     calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
682   tmp = htonl(pktlen);
683   sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
684   tmp = htonl (((pkt6->ip6_hdr.nxthdr & 0x000000ff)));
685   sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
686
687   sum =
688     calculate_checksum_update (sum, (uint16_t *) & pkt6->tcp_hdr,
689                                ntohs (pkt6->ip6_hdr.paylgth));
690   pkt6->tcp_hdr.crc = calculate_checksum_end (sum);
691
692   write_to_helper(pkt6, size);
693
694   return GNUNET_OK;
695 }
696
697 /**
698  * Main function that will be run by the scheduler.
699  *
700  * @param cls closure
701  * @param args remaining command-line arguments
702  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
703  * @param cfg_ configuration
704  */
705 static void
706 run (void *cls,
707      char *const *args __attribute__((unused)),
708      const char *cfgfilep __attribute__((unused)),
709      const struct GNUNET_CONFIGURATION_Handle *cfg_)
710 {
711     static const struct GNUNET_MESH_MessageHandler handlers[] = {
712           {receive_udp_back, GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK, 0},
713           {receive_tcp_back, GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK, 0},
714           {receive_udp_back, GNUNET_MESSAGE_TYPE_REMOTE_UDP_BACK, 0},
715           {receive_tcp_back, GNUNET_MESSAGE_TYPE_REMOTE_TCP_BACK, 0},
716           {NULL, 0, 0}
717     };
718
719     static const GNUNET_MESH_ApplicationType types[] = {
720         GNUNET_APPLICATION_TYPE_END
721     };
722
723     mesh_handle = GNUNET_MESH_connect(cfg_,
724                                       NULL,
725                                       NULL,
726                                       handlers,
727                                       types);
728     cfg = cfg_;
729     restart_hijack = 0;
730     hashmap = GNUNET_CONTAINER_multihashmap_create(65536);
731     heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
732     GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPINGg",
733                                            &max_mappings);
734     udp_connections = GNUNET_CONTAINER_multihashmap_create(65536);
735     GNUNET_SCHEDULER_TaskIdentifier conn_task = GNUNET_SCHEDULER_add_now (connect_to_service_dns, NULL);
736     GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL);
737     GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
738 }
739
740 /**
741  * The main function to obtain template from gnunetd.
742  *
743  * @param argc number of arguments from the command line
744  * @param argv command line arguments
745  * @return 0 ok, 1 on error
746  */
747 int
748 main (int argc, char *const *argv) {
749     static const struct GNUNET_GETOPT_CommandLineOption options[] = {
750         GNUNET_GETOPT_OPTION_END
751     };
752
753     return (GNUNET_OK ==
754             GNUNET_PROGRAM_run (argc,
755                                 argv,
756                                 "vpn",
757                                 gettext_noop ("help text"),
758                                 options, &run, NULL)) ? ret : 1;
759 }
760
761 /* end of gnunet-daemon-vpn.c */
762