remove send on connect
[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         unsigned char* k = (unsigned char*)&key;
425         /*
426          * Copy the newly generated ip-address to the key backwards (as only the first part is used in the hash-table)
427          */
428         unsigned int i;
429         for (i = 0; i < 16; i++)
430             k[15-i] = c[i];
431
432         uint16_t namelen = strlen((char*)pkt->data+12)+1;
433
434         struct map_entry* value = GNUNET_malloc(sizeof(struct map_entry) + namelen);
435         char* name = (char*)(value +1);
436
437         value->namelen = namelen;
438         memcpy(name, pkt->data+12, namelen);
439
440         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting addrlen to %d\n", pkt->addrsize);
441         value->addrlen = pkt->addrsize;
442         memcpy(&value->addr, &pkt->addr, pkt->addrsize);
443         memset(value->additional_ports, 0, 8192);
444
445         memcpy(&value->hash, &key, sizeof(GNUNET_HashCode));
446
447         if (GNUNET_NO ==
448             GNUNET_CONTAINER_multihashmap_contains (hashmap, &key))
449           {
450             GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value,
451                                                GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
452             value->heap_node = GNUNET_CONTAINER_heap_insert (heap, value,
453                                                              GNUNET_TIME_absolute_get ().abs_value);
454             if (GNUNET_CONTAINER_heap_get_size(heap) > max_mappings)
455               GNUNET_SCHEDULER_add_now(collect_mappings, NULL);
456           }
457         else
458           GNUNET_free(value);
459
460         list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*));
461
462         memcpy(&list->pkt, pkt, htons(pkt->hdr.size));
463       }
464     else
465       {
466         GNUNET_break(0);
467         GNUNET_free(pkt);
468         return;
469       }
470
471     GNUNET_free(pkt);
472
473     GNUNET_CONTAINER_DLL_insert_after(answer_proc_head, answer_proc_tail, answer_proc_tail, list);
474
475     schedule_helper_write(GNUNET_TIME_UNIT_FOREVER_REL, NULL);
476
477     return;
478 }
479
480 /**
481  * Sets a bit active in a bitArray.
482  *
483  * @param bitArray memory area to set the bit in
484  * @param bitIdx which bit to set
485  */
486 void
487 setBit (char *bitArray, unsigned int bitIdx)
488 {
489   size_t arraySlot;
490   unsigned int targetBit;
491
492   arraySlot = bitIdx / 8;
493   targetBit = (1L << (bitIdx % 8));
494   bitArray[arraySlot] |= targetBit;
495 }
496
497 /**
498  * Clears a bit from bitArray.
499  *
500  * @param bitArray memory area to set the bit in
501  * @param bitIdx which bit to unset
502  */
503 void
504 clearBit (char *bitArray, unsigned int bitIdx)
505 {
506   size_t slot;
507   unsigned int targetBit;
508
509   slot = bitIdx / 8;
510   targetBit = (1L << (bitIdx % 8));
511   bitArray[slot] = bitArray[slot] & (~targetBit);
512 }
513
514 /**
515  * Checks if a bit is active in the bitArray
516  *
517  * @param bitArray memory area to set the bit in
518  * @param bitIdx which bit to test
519  * @return GNUNET_YES if the bit is set, GNUNET_NO if not.
520  */
521 int
522 testBit (char *bitArray, unsigned int bitIdx)
523 {
524   size_t slot;
525   unsigned int targetBit;
526
527   slot = bitIdx / 8;
528   targetBit = (1L << (bitIdx % 8));
529   if (bitArray[slot] & targetBit)
530     return GNUNET_YES;
531   else
532     return GNUNET_NO;
533 }
534
535 /**
536  * @brief Add the port to the list of additional ports in the map_entry
537  *
538  * @param me the map_entry
539  * @param port the port in host-byte-order
540  */
541 static void
542 add_additional_port (struct map_entry *me, uint16_t port)
543 {
544   setBit(me->additional_ports, port);
545 }
546
547 static int
548 receive_udp_back (void *cls __attribute__((unused)), struct GNUNET_MESH_Tunnel* tunnel,
549                   void **tunnel_ctx __attribute__((unused)),
550                   const struct GNUNET_PeerIdentity *sender __attribute__((unused)),
551                   const struct GNUNET_MessageHeader *message,
552                   const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused)))
553 {
554   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
555   struct remote_addr* s = (struct remote_addr*)desc;
556   struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
557   const struct GNUNET_PeerIdentity* other = GNUNET_MESH_get_peer(tunnel);
558
559   size_t size = sizeof(struct ip6_udp) + ntohs(pkt->len) - 1 - sizeof(struct udp_pkt);
560
561   struct ip6_udp* pkt6 = alloca(size);
562
563   GNUNET_assert(pkt6 != NULL);
564
565   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK)
566     new_ip6addr(pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
567   else
568     new_ip6addr_remote(pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
569
570   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Relaying calc:%d gnu:%d udp:%d bytes!\n", size, ntohs(message->size), ntohs(pkt->len));
571
572   pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
573   pkt6->shdr.size = htons(size);
574
575   pkt6->tun.flags = 0;
576   pkt6->tun.type = htons(0x86dd);
577
578   pkt6->ip6_hdr.version = 6;
579   pkt6->ip6_hdr.tclass_h = 0;
580   pkt6->ip6_hdr.tclass_l = 0;
581   pkt6->ip6_hdr.flowlbl = 0;
582   pkt6->ip6_hdr.paylgth = pkt->len;
583   pkt6->ip6_hdr.nxthdr = 0x11;
584   pkt6->ip6_hdr.hoplmt = 0xff;
585
586   {
587     char* ipv6addr;
588     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr));
589     inet_pton (AF_INET6, ipv6addr, pkt6->ip6_hdr.dadr);
590     GNUNET_free(ipv6addr);
591   }
592   memcpy(&pkt6->udp_hdr, pkt, ntohs(pkt->len));
593
594   GNUNET_HashCode* key = address_mapping_exists(pkt6->ip6_hdr.sadr);
595   GNUNET_assert (key != NULL);
596
597   struct map_entry *me = GNUNET_CONTAINER_multihashmap_get(hashmap, key);
598   GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
599                                      GNUNET_TIME_absolute_get ().abs_value);
600
601   GNUNET_free(key);
602
603   GNUNET_assert (me != NULL);
604   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK)
605     {
606       GNUNET_assert (me->desc.service_type & htonl(GNUNET_DNS_SERVICE_TYPE_UDP));
607       if (!port_in_ports(me->desc.ports, pkt6->udp_hdr.spt) &&
608           !testBit(me->additional_ports, ntohs(pkt6->udp_hdr.spt))) {
609           add_additional_port(me, ntohs(pkt6->udp_hdr.spt));
610       }
611     }
612
613   pkt6->udp_hdr.crc = 0;
614   uint32_t sum = 0;
615   sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.sadr, 16);
616   sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.dadr, 16);
617   uint32_t tmp = (pkt6->udp_hdr.len & 0xffff);
618   sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4);
619   tmp = htons(((pkt6->ip6_hdr.nxthdr & 0x00ff)));
620   sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4);
621
622   sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->udp_hdr, ntohs(pkt->len));
623   pkt6->udp_hdr.crc = calculate_checksum_end(sum);
624
625   write_to_helper(pkt6, size);
626
627   return GNUNET_OK;
628 }
629
630 static int
631 receive_tcp_back (void *cls __attribute__((unused)), struct GNUNET_MESH_Tunnel* tunnel,
632                   void **tunnel_ctx __attribute__((unused)),
633                   const struct GNUNET_PeerIdentity *sender __attribute__((unused)),
634                   const struct GNUNET_MessageHeader *message,
635                   const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused)))
636 {
637   GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
638   struct remote_addr* s = (struct remote_addr*)desc;
639   struct tcp_pkt *pkt = (struct tcp_pkt *) (desc + 1);
640   const struct GNUNET_PeerIdentity* other = GNUNET_MESH_get_peer(tunnel);
641
642   size_t pktlen = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader) - sizeof(GNUNET_HashCode);
643   size_t size = pktlen + sizeof(struct ip6_tcp) - 1;
644
645   struct ip6_tcp* pkt6 = alloca(size);
646   memset(pkt6, 0, size);
647
648   GNUNET_assert(pkt6 != NULL);
649
650   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK)
651     new_ip6addr(pkt6->ip6_hdr.sadr, &other->hashPubKey, desc);
652   else
653     new_ip6addr_remote(pkt6->ip6_hdr.sadr, s->addr, s->addrlen);
654
655   pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
656   pkt6->shdr.size = htons(size);
657
658   pkt6->tun.flags = 0;
659   pkt6->tun.type = htons(0x86dd);
660
661   pkt6->ip6_hdr.version = 6;
662   pkt6->ip6_hdr.tclass_h = 0;
663   pkt6->ip6_hdr.tclass_l = 0;
664   pkt6->ip6_hdr.flowlbl = 0;
665   pkt6->ip6_hdr.paylgth = htons(pktlen);
666   pkt6->ip6_hdr.nxthdr = 0x06;
667   pkt6->ip6_hdr.hoplmt = 0xff;
668
669   {
670     char* ipv6addr;
671     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr));
672     inet_pton (AF_INET6, ipv6addr, pkt6->ip6_hdr.dadr);
673     GNUNET_free(ipv6addr);
674   }
675   memcpy(&pkt6->tcp_hdr, pkt, pktlen);
676
677   GNUNET_HashCode* key = address_mapping_exists(pkt6->ip6_hdr.sadr);
678   GNUNET_assert (key != NULL);
679
680   struct map_entry *me = GNUNET_CONTAINER_multihashmap_get(hashmap, key);
681   GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node,
682                                      GNUNET_TIME_absolute_get ().abs_value);
683
684   GNUNET_free(key);
685
686   GNUNET_assert (me != NULL);
687   if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK)
688     GNUNET_assert (me->desc.service_type & htonl(GNUNET_DNS_SERVICE_TYPE_TCP));
689
690   pkt6->tcp_hdr.crc = 0;
691   uint32_t sum = 0;
692   uint32_t tmp;
693   sum =
694     calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
695   sum =
696     calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
697   tmp = htonl(pktlen);
698   sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
699   tmp = htonl (((pkt6->ip6_hdr.nxthdr & 0x000000ff)));
700   sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
701
702   sum =
703     calculate_checksum_update (sum, (uint16_t *) & pkt6->tcp_hdr,
704                                ntohs (pkt6->ip6_hdr.paylgth));
705   pkt6->tcp_hdr.crc = calculate_checksum_end (sum);
706
707   write_to_helper(pkt6, size);
708
709   return GNUNET_OK;
710 }
711
712 /**
713  * Main function that will be run by the scheduler.
714  *
715  * @param cls closure
716  * @param args remaining command-line arguments
717  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
718  * @param cfg_ configuration
719  */
720 static void
721 run (void *cls,
722      char *const *args __attribute__((unused)),
723      const char *cfgfilep __attribute__((unused)),
724      const struct GNUNET_CONFIGURATION_Handle *cfg_)
725 {
726     static const struct GNUNET_MESH_MessageHandler handlers[] = {
727           {receive_udp_back, GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK, 0},
728           {receive_tcp_back, GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK, 0},
729           {receive_udp_back, GNUNET_MESSAGE_TYPE_REMOTE_UDP_BACK, 0},
730           {receive_tcp_back, GNUNET_MESSAGE_TYPE_REMOTE_TCP_BACK, 0},
731           {NULL, 0, 0}
732     };
733
734     static const GNUNET_MESH_ApplicationType types[] = {
735         GNUNET_APPLICATION_TYPE_END
736     };
737
738     mesh_handle = GNUNET_MESH_connect(cfg_,
739                                       NULL,
740                                       NULL,
741                                       handlers,
742                                       types);
743     cfg = cfg_;
744     restart_hijack = 0;
745     hashmap = GNUNET_CONTAINER_multihashmap_create(65536);
746     heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
747     GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPINGg",
748                                            &max_mappings);
749     udp_connections = GNUNET_CONTAINER_multihashmap_create(65536);
750     conn_task = GNUNET_SCHEDULER_add_now (connect_to_service_dns, NULL);
751     shs_task = GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL);
752     GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
753 }
754
755 /**
756  * The main function to obtain template from gnunetd.
757  *
758  * @param argc number of arguments from the command line
759  * @param argv command line arguments
760  * @return 0 ok, 1 on error
761  */
762 int
763 main (int argc, char *const *argv) {
764     static const struct GNUNET_GETOPT_CommandLineOption options[] = {
765         GNUNET_GETOPT_OPTION_END
766     };
767
768     return (GNUNET_OK ==
769             GNUNET_PROGRAM_run (argc,
770                                 argv,
771                                 "vpn",
772                                 gettext_noop ("help text"),
773                                 options, &run, NULL)) ? ret : 1;
774 }
775
776 /* end of gnunet-daemon-vpn.c */
777