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