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