aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-daemon-vpn.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-02 09:57:25 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-02 09:57:25 +0000
commit2b152f749e6274ab97baa09b9d1522803c76027f (patch)
treeea5e4857b6de87cb3ad79da334c6d61e213cd54a /src/vpn/gnunet-daemon-vpn.c
parenta0f00b8f5726eccb6eab9bcf974c3e45ab572220 (diff)
downloadgnunet-2b152f749e6274ab97baa09b9d1522803c76027f.tar.gz
gnunet-2b152f749e6274ab97baa09b9d1522803c76027f.zip
-using new GNUNET_HELPER_ API inside of VPN, also eliminating bugs with partial writes as part of this
Diffstat (limited to 'src/vpn/gnunet-daemon-vpn.c')
-rw-r--r--src/vpn/gnunet-daemon-vpn.c656
1 files changed, 636 insertions, 20 deletions
diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c
index 7d303ecd5..35db8af7b 100644
--- a/src/vpn/gnunet-daemon-vpn.c
+++ b/src/vpn/gnunet-daemon-vpn.c
@@ -35,7 +35,6 @@
35#include "gnunet_container_lib.h" 35#include "gnunet_container_lib.h"
36#include "gnunet_constants.h" 36#include "gnunet_constants.h"
37#include <block_dns.h> 37#include <block_dns.h>
38#include "gnunet-daemon-vpn-helper.h"
39#include "gnunet_dns_service.h" 38#include "gnunet_dns_service.h"
40#include "gnunet-daemon-vpn.h" 39#include "gnunet-daemon-vpn.h"
41#include "gnunet-vpn-checksum.h" 40#include "gnunet-vpn-checksum.h"
@@ -45,6 +44,16 @@ struct GNUNET_MESH_Handle *mesh_handle;
45struct GNUNET_CONTAINER_MultiHashMap *hashmap; 44struct GNUNET_CONTAINER_MultiHashMap *hashmap;
46static struct GNUNET_CONTAINER_Heap *heap; 45static struct GNUNET_CONTAINER_Heap *heap;
47 46
47/**
48 * The handle to the helper
49 */
50static struct GNUNET_HELPER_Handle *helper_handle;
51
52/**
53 * Arguments to the exit helper.
54 */
55static char *vpn_argv[7];
56
48struct GNUNET_DNS_Handle *dns_handle; 57struct GNUNET_DNS_Handle *dns_handle;
49 58
50struct answer_packet_list *answer_proc_head; 59struct answer_packet_list *answer_proc_head;
@@ -82,6 +91,14 @@ GNUNET_SCHEDULER_TaskIdentifier shs_task;
82 91
83 92
84/** 93/**
94 * The tunnels that will be used to send tcp- and udp-packets
95 */
96static struct GNUNET_MESH_Tunnel *tcp_tunnel;
97static struct GNUNET_MESH_Tunnel *udp_tunnel;
98
99
100
101/**
85 * Sets a bit active in a bitArray. 102 * Sets a bit active in a bitArray.
86 * 103 *
87 * @param bitArray memory area to set the bit in 104 * @param bitArray memory area to set the bit in
@@ -129,11 +146,9 @@ static void
129cleanup (void *cls GNUNET_UNUSED, 146cleanup (void *cls GNUNET_UNUSED,
130 const struct GNUNET_SCHEDULER_TaskContext *tskctx) 147 const struct GNUNET_SCHEDULER_TaskContext *tskctx)
131{ 148{
132 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); 149 unsigned int i;
133
134 /* stop the helper */
135 cleanup_helper (helper_handle);
136 150
151 GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN));
137 /* close the connection to the service-dns */ 152 /* close the connection to the service-dns */
138 GNUNET_DNS_disconnect (dns_handle); 153 GNUNET_DNS_disconnect (dns_handle);
139 if (mesh_handle != NULL) 154 if (mesh_handle != NULL)
@@ -141,6 +156,11 @@ cleanup (void *cls GNUNET_UNUSED,
141 GNUNET_MESH_disconnect (mesh_handle); 156 GNUNET_MESH_disconnect (mesh_handle);
142 mesh_handle = NULL; 157 mesh_handle = NULL;
143 } 158 }
159 if (helper_handle != NULL)
160 {
161 GNUNET_HELPER_stop (helper_handle);
162 helper_handle = NULL;
163 }
144 if (GNUNET_SCHEDULER_NO_TASK != shs_task) 164 if (GNUNET_SCHEDULER_NO_TASK != shs_task)
145 { 165 {
146 GNUNET_SCHEDULER_cancel (shs_task); 166 GNUNET_SCHEDULER_cancel (shs_task);
@@ -151,6 +171,8 @@ cleanup (void *cls GNUNET_UNUSED,
151 GNUNET_SCHEDULER_cancel (conn_task); 171 GNUNET_SCHEDULER_cancel (conn_task);
152 conn_task = GNUNET_SCHEDULER_NO_TASK; 172 conn_task = GNUNET_SCHEDULER_NO_TASK;
153 } 173 }
174 for (i=0;i<5;i++)
175 GNUNET_free_non_null (vpn_argv[i]);
154} 176}
155 177
156/*}}}*/ 178/*}}}*/
@@ -210,6 +232,532 @@ address4_mapping_exists (uint32_t addr)
210 } 232 }
211} 233}
212 234
235
236static void *
237initialize_tunnel_state (int addrlen, struct GNUNET_MESH_TransmitHandle *th)
238{
239 struct tunnel_state *ts = GNUNET_malloc (sizeof *ts);
240
241 ts->addrlen = addrlen;
242 ts->th = th;
243 return ts;
244}
245
246/**
247 * Send an dns-answer-packet to the helper
248 */
249void
250helper_write (void *cls GNUNET_UNUSED,
251 int status)
252{
253 struct answer_packet_list *ans = answer_proc_head;
254
255 if (NULL == ans)
256 return;
257 if (GNUNET_SYSERR == status)
258 return;
259
260 size_t len = ntohs (ans->pkt.hdr.size);
261
262 GNUNET_assert (ans->pkt.subtype == GNUNET_DNS_ANSWER_TYPE_IP);
263
264 GNUNET_assert (20 == sizeof (struct ip_hdr));
265 GNUNET_assert (8 == sizeof (struct udp_pkt));
266
267 size_t data_len = len - sizeof (struct answer_packet) + 1;
268
269 size_t pkt_len;
270
271 if (ans->pkt.addrlen == 16)
272 {
273 size_t net_len =
274 sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len;
275 pkt_len =
276 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
277 net_len;
278
279 struct ip6_udp_dns *pkt = alloca (pkt_len);
280
281 GNUNET_assert (pkt != NULL);
282 memset (pkt, 0, pkt_len);
283
284 /* set the gnunet-header */
285 pkt->shdr.size = htons (pkt_len);
286 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
287
288 /* set the tun-header (no flags and ethertype of IPv4) */
289 pkt->tun.flags = 0;
290 pkt->tun.type = htons (0x86dd);
291
292 memcpy (&pkt->ip6_hdr.sadr, ans->pkt.from, 16);
293 memcpy (&pkt->ip6_hdr.dadr, ans->pkt.to, 16);
294
295 /* set the udp-header */
296 pkt->udp_dns.udp_hdr.spt = htons (53);
297 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
298 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr));
299 pkt->udp_dns.udp_hdr.crc = 0;
300 uint32_t sum = 0;
301
302 sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16);
303 sum = calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16);
304 uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff);
305
306 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
307 tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff)));
308 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
309
310 sum =
311 calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr,
312 ntohs (net_len - sizeof (struct ip6_hdr)));
313 pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum);
314
315 pkt->ip6_hdr.version = 6;
316 pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr);
317 pkt->ip6_hdr.nxthdr = IPPROTO_UDP;
318 pkt->ip6_hdr.hoplmt = 0xff;
319
320 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
321 (void) GNUNET_HELPER_send (helper_handle,
322 &pkt->shdr,
323 GNUNET_YES,
324 &helper_write, NULL);
325 }
326 else if (ans->pkt.addrlen == 4)
327 {
328 size_t net_len =
329 sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len;
330 pkt_len =
331 sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
332 net_len;
333
334 struct ip_udp_dns *pkt = alloca (pkt_len);
335
336 GNUNET_assert (pkt != NULL);
337 memset (pkt, 0, pkt_len);
338
339 /* set the gnunet-header */
340 pkt->shdr.size = htons (pkt_len);
341 pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
342
343 /* set the tun-header (no flags and ethertype of IPv4) */
344 pkt->tun.flags = 0;
345 pkt->tun.type = htons (0x0800);
346
347 /* set the ip-header */
348 pkt->ip_hdr.version = 4;
349 pkt->ip_hdr.hdr_lngth = 5;
350 pkt->ip_hdr.diff_serv = 0;
351 pkt->ip_hdr.tot_lngth = htons (net_len);
352 pkt->ip_hdr.ident = 0;
353 pkt->ip_hdr.flags = 0;
354 pkt->ip_hdr.frag_off = 0;
355 pkt->ip_hdr.ttl = 255;
356 pkt->ip_hdr.proto = IPPROTO_UDP;
357 pkt->ip_hdr.chks = 0; /* Will be calculated later */
358
359 memcpy (&pkt->ip_hdr.sadr, ans->pkt.from, 4);
360 memcpy (&pkt->ip_hdr.dadr, ans->pkt.to, 4);
361
362 pkt->ip_hdr.chks =
363 calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4);
364
365 /* set the udp-header */
366 pkt->udp_dns.udp_hdr.spt = htons (53);
367 pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port;
368 pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr));
369 pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */
370
371 memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len);
372 (void) GNUNET_HELPER_send (helper_handle,
373 &pkt->shdr,
374 GNUNET_YES,
375 &helper_write, NULL);
376
377 }
378 else
379 {
380 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong addrlen = %d\n",
381 ans->pkt.addrlen);
382 GNUNET_assert (0);
383 return; /* convince compiler that we're done here */
384 }
385
386 GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans);
387 GNUNET_free (ans);
388
389}
390
391/**
392 * Receive packets from the helper-process
393 */
394void
395message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED,
396 const struct GNUNET_MessageHeader *message)
397{
398 GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER);
399
400 struct tun_pkt *pkt_tun = (struct tun_pkt *) message;
401 GNUNET_HashCode *key;
402
403 /* ethertype is ipv6 */
404 if (ntohs (pkt_tun->tun.type) == 0x86dd)
405 {
406 struct ip6_pkt *pkt6 = (struct ip6_pkt *) message;
407
408 GNUNET_assert (pkt6->ip6_hdr.version == 6);
409 struct ip6_tcp *pkt6_tcp;
410 struct ip6_udp *pkt6_udp;
411 struct ip6_icmp *pkt6_icmp;
412
413 pkt6_udp = NULL; /* make compiler happy */
414 switch (pkt6->ip6_hdr.nxthdr)
415 {
416 case IPPROTO_UDP:
417 pkt6_udp = (struct ip6_udp *) pkt6;
418 /* Send dns-packets to the service-dns */
419 if (ntohs (pkt6_udp->udp_hdr.dpt) == 53)
420 {
421 /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */
422 GNUNET_DNS_queue_request_v6 (dns_handle,
423 &pkt6->ip6_hdr.dadr,
424 &pkt6->ip6_hdr.sadr,
425 ntohs (pkt6_udp->udp_hdr.spt),
426 ntohs (pkt6_udp->udp_hdr.len) - 8,
427 (const void*) pkt6_udp->data);
428
429 break;
430 }
431 /* fall through */
432 case IPPROTO_TCP:
433 pkt6_tcp = (struct ip6_tcp *) pkt6;
434
435 if ((key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
436 {
437 struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key);
438
439 GNUNET_assert (me != NULL);
440 GNUNET_free (key);
441
442 size_t size =
443 sizeof (struct GNUNET_MESH_Tunnel *) +
444 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
445 ntohs (pkt6->ip6_hdr.paylgth);
446
447 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
448 struct GNUNET_MessageHeader *hdr =
449 (struct GNUNET_MessageHeader *) (cls + 1);
450 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
451
452 hdr->size =
453 htons (sizeof (struct GNUNET_MessageHeader) +
454 sizeof (GNUNET_HashCode) + ntohs (pkt6->ip6_hdr.paylgth));
455
456 GNUNET_MESH_ApplicationType app_type = 0; /* fix compiler uninitialized warning... */
457
458 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
459 me->addrlen);
460 if (me->addrlen == 0)
461 {
462 /* This is a mapping to a gnunet-service */
463 memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode));
464
465 if (IPPROTO_UDP == pkt6->ip6_hdr.nxthdr &&
466 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) &&
467 (port_in_ports (me->desc.ports, pkt6_udp->udp_hdr.dpt) ||
468 testBit (me->additional_ports, ntohs (pkt6_udp->udp_hdr.dpt))))
469 {
470 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP);
471
472 memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
473
474 }
475 else if (IPPROTO_TCP == pkt6->ip6_hdr.nxthdr &&
476 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP))
477 && (port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt)))
478 {
479 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP);
480
481 memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
482
483 }
484 else
485 {
486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pip: %d\n",
487 port_in_ports (me->desc.ports, pkt6_tcp->tcp_hdr.dpt));
488 GNUNET_assert (0);
489 }
490 if (me->tunnel == NULL && NULL != cls)
491 {
492 *cls =
493 GNUNET_MESH_tunnel_create (mesh_handle,
494 initialize_tunnel_state (16, NULL),
495 &send_pkt_to_peer, NULL, cls);
496
497 GNUNET_MESH_peer_request_connect_add (*cls,
498 (struct GNUNET_PeerIdentity *)
499 &me->desc.peer);
500 me->tunnel = *cls;
501 }
502 else if (NULL != cls)
503 {
504 *cls = me->tunnel;
505 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
507 "Queued to send IPv6 to peer %x, type %d\n",
508 *((unsigned int *) &me->desc.peer), ntohs (hdr->type));
509 }
510 }
511 else
512 {
513 /* This is a mapping to a "real" address */
514 struct remote_addr *s = (struct remote_addr *) hc;
515
516 s->addrlen = me->addrlen;
517 memcpy (s->addr, me->addr, me->addrlen);
518 s->proto = pkt6->ip6_hdr.nxthdr;
519 if (s->proto == IPPROTO_UDP)
520 {
521 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
522 memcpy (hc + 1, &pkt6_udp->udp_hdr, ntohs (pkt6_udp->udp_hdr.len));
523 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
524 if (NULL != udp_tunnel)
525 me->tunnel = udp_tunnel;
526 }
527 else if (s->proto == IPPROTO_TCP)
528 {
529 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
530 memcpy (hc + 1, &pkt6_tcp->tcp_hdr, ntohs (pkt6->ip6_hdr.paylgth));
531 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
532 if (NULL != tcp_tunnel)
533 me->tunnel = tcp_tunnel;
534 }
535 else
536 {
537 GNUNET_assert (0);
538 }
539 if (me->tunnel == NULL && NULL != cls)
540 {
541 *cls =
542 GNUNET_MESH_tunnel_create (mesh_handle,
543 initialize_tunnel_state (16, NULL),
544 &send_pkt_to_peer, NULL, cls);
545
546 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
547 me->tunnel = *cls;
548 if (GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY == app_type)
549 udp_tunnel = *cls;
550 else if (GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY == app_type)
551 tcp_tunnel = *cls;
552 }
553 else if (NULL != cls)
554 {
555 *cls = me->tunnel;
556 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
557 }
558 }
559 }
560 else
561 {
562 char pbuf[INET6_ADDRSTRLEN];
563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564 "Packet to %s, which has no mapping\n",
565 inet_ntop (AF_INET6,
566 &pkt6->ip6_hdr.dadr,
567 pbuf,
568 sizeof (pbuf)));
569 }
570 break;
571 case 0x3a:
572 /* ICMPv6 */
573 pkt6_icmp = (struct ip6_icmp *) pkt6;
574 /* If this packet is an icmp-echo-request and a mapping exists, answer */
575 if (pkt6_icmp->icmp_hdr.type == 0x80 &&
576 (key = address6_mapping_exists (&pkt6->ip6_hdr.dadr)) != NULL)
577 {
578 GNUNET_free (key);
579 pkt6_icmp = GNUNET_malloc (ntohs (pkt6->shdr.size));
580 memcpy (pkt6_icmp, pkt6, ntohs (pkt6->shdr.size));
581 GNUNET_SCHEDULER_add_now (&send_icmp6_response, pkt6_icmp);
582 }
583 break;
584 }
585 }
586 /* ethertype is ipv4 */
587 else if (ntohs (pkt_tun->tun.type) == 0x0800)
588 {
589 struct ip_pkt *pkt = (struct ip_pkt *) message;
590 struct ip_udp *udp = (struct ip_udp *) message;
591 struct ip_tcp *pkt_tcp;
592 struct ip_udp *pkt_udp;
593 struct ip_icmp *pkt_icmp;
594
595 GNUNET_assert (pkt->ip_hdr.version == 4);
596
597 /* Send dns-packets to the service-dns */
598 if (pkt->ip_hdr.proto == IPPROTO_UDP && ntohs (udp->udp_hdr.dpt) == 53)
599 {
600 GNUNET_DNS_queue_request_v4 (dns_handle,
601 &pkt->ip_hdr.dadr,
602 &pkt->ip_hdr.sadr,
603 ntohs (udp->udp_hdr.spt),
604 ntohs (udp->udp_hdr.len) - 8,
605 (const void*) udp->data);
606 }
607 else
608 {
609 uint32_t dadr = pkt->ip_hdr.dadr.s_addr;
610 unsigned char *c = (unsigned char *) &dadr;
611
612 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Packet to %d.%d.%d.%d, proto %x\n",
613 c[0], c[1], c[2], c[3], pkt->ip_hdr.proto);
614 switch (pkt->ip_hdr.proto)
615 {
616 case IPPROTO_TCP:
617 case IPPROTO_UDP:
618 pkt_tcp = (struct ip_tcp *) pkt;
619 pkt_udp = (struct ip_udp *) pkt;
620
621 if ((key = address4_mapping_exists (dadr)) != NULL)
622 {
623 struct map_entry *me =
624 GNUNET_CONTAINER_multihashmap_get (hashmap, key);
625 GNUNET_assert (me != NULL);
626 GNUNET_free (key);
627
628 size_t size =
629 sizeof (struct GNUNET_MESH_Tunnel *) +
630 sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) +
631 ntohs (pkt->ip_hdr.tot_lngth) - 4 * pkt->ip_hdr.hdr_lngth;
632
633 struct GNUNET_MESH_Tunnel **cls = GNUNET_malloc (size);
634 struct GNUNET_MessageHeader *hdr =
635 (struct GNUNET_MessageHeader *) (cls + 1);
636 GNUNET_HashCode *hc = (GNUNET_HashCode *) (hdr + 1);
637
638 hdr->size =
639 htons (sizeof (struct GNUNET_MessageHeader) +
640 sizeof (GNUNET_HashCode) + ntohs (pkt->ip_hdr.tot_lngth) -
641 4 * pkt->ip_hdr.hdr_lngth);
642
643 GNUNET_MESH_ApplicationType app_type = 0; /* make compiler happy */
644
645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "me->addrlen is %d\n",
646 me->addrlen);
647 if (me->addrlen == 0)
648 {
649 /* This is a mapping to a gnunet-service */
650 memcpy (hc, &me->desc.service_descriptor, sizeof (GNUNET_HashCode));
651
652 if ((IPPROTO_UDP == pkt->ip_hdr.proto) &&
653 (me->desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)) &&
654 (port_in_ports (me->desc.ports, pkt_udp->udp_hdr.dpt) ||
655 testBit (me->additional_ports, ntohs (pkt_udp->udp_hdr.dpt))))
656 {
657 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP);
658
659 memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
660
661 }
662 else if ((IPPROTO_TCP == pkt->ip_hdr.proto) &&
663 (me->
664 desc.service_type & htonl (GNUNET_DNS_SERVICE_TYPE_TCP))
665 && (port_in_ports (me->desc.ports, pkt_tcp->tcp_hdr.dpt)))
666 {
667 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP);
668
669 memcpy (hc + 1, &pkt_tcp->tcp_hdr,
670 ntohs (pkt->ip_hdr.tot_lngth) -
671 4 * pkt->ip_hdr.hdr_lngth);
672
673 }
674 if (me->tunnel == NULL && NULL != cls)
675 {
676 *cls =
677 GNUNET_MESH_tunnel_create (mesh_handle,
678 initialize_tunnel_state (4, NULL),
679 send_pkt_to_peer, NULL, cls);
680 GNUNET_MESH_peer_request_connect_add (*cls,
681 (struct GNUNET_PeerIdentity
682 *) &me->desc.peer);
683 me->tunnel = *cls;
684 }
685 else if (NULL != cls)
686 {
687 *cls = me->tunnel;
688 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
690 "Queued to send IPv4 to peer %x, type %d\n",
691 *((unsigned int *) &me->desc.peer),
692 ntohs (hdr->type));
693 }
694 }
695 else
696 {
697 /* This is a mapping to a "real" address */
698 struct remote_addr *s = (struct remote_addr *) hc;
699
700 s->addrlen = me->addrlen;
701 memcpy (s->addr, me->addr, me->addrlen);
702 s->proto = pkt->ip_hdr.proto;
703 if (s->proto == IPPROTO_UDP)
704 {
705 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP);
706 memcpy (hc + 1, &pkt_udp->udp_hdr, ntohs (pkt_udp->udp_hdr.len));
707 app_type = GNUNET_APPLICATION_TYPE_INTERNET_UDP_GATEWAY;
708 }
709 else if (s->proto == IPPROTO_TCP)
710 {
711 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP);
712 memcpy (hc + 1, &pkt_tcp->tcp_hdr,
713 ntohs (pkt->ip_hdr.tot_lngth) -
714 4 * pkt->ip_hdr.hdr_lngth);
715 app_type = GNUNET_APPLICATION_TYPE_INTERNET_TCP_GATEWAY;
716 }
717 else
718 GNUNET_assert (0);
719 if (me->tunnel == NULL && NULL != cls)
720 {
721 *cls =
722 GNUNET_MESH_tunnel_create (mesh_handle,
723 initialize_tunnel_state (4, NULL),
724 send_pkt_to_peer, NULL, cls);
725
726 GNUNET_MESH_peer_request_connect_by_type (*cls, app_type);
727 me->tunnel = *cls;
728 }
729 else if (NULL != cls)
730 {
731 *cls = me->tunnel;
732 send_pkt_to_peer (cls, (struct GNUNET_PeerIdentity *) 1, NULL);
733 }
734 }
735 }
736 else
737 {
738 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
739 "Packet to %x which has no mapping\n", dadr);
740 }
741 break;
742 case 0x01:
743 /* ICMP */
744 pkt_icmp = (struct ip_icmp *) pkt;
745 if (pkt_icmp->icmp_hdr.type == 0x8 &&
746 (key = address4_mapping_exists (dadr)) != NULL)
747 {
748 GNUNET_free (key);
749 pkt_icmp = GNUNET_malloc (ntohs (pkt->shdr.size));
750 memcpy (pkt_icmp, pkt, ntohs (pkt->shdr.size));
751 GNUNET_SCHEDULER_add_now (&send_icmp4_response, pkt_icmp);
752 }
753 break;
754 }
755 }
756 }
757}
758
759
760
213static void 761static void
214collect_mappings (void *cls GNUNET_UNUSED, 762collect_mappings (void *cls GNUNET_UNUSED,
215 const struct GNUNET_SCHEDULER_TaskContext *tc) 763 const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -269,8 +817,10 @@ send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
269 memcpy (response + 1, request + 1, 817 memcpy (response + 1, request + 1,
270 ntohs (request->shdr.size) - sizeof (struct ip_icmp)); 818 ntohs (request->shdr.size) - sizeof (struct ip_icmp));
271 819
272 write_to_helper (response, ntohs (response->shdr.size)); 820 (void) GNUNET_HELPER_send (helper_handle,
273 821 &response->shdr,
822 GNUNET_YES,
823 NULL, NULL);
274 GNUNET_free (request); 824 GNUNET_free (request);
275} 825}
276 826
@@ -310,8 +860,10 @@ send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
310 memcpy (response + 1, request + 1, 860 memcpy (response + 1, request + 1,
311 ntohs (request->shdr.size) - sizeof (struct ip6_icmp)); 861 ntohs (request->shdr.size) - sizeof (struct ip6_icmp));
312 862
313 write_to_helper (response, ntohs (response->shdr.size)); 863 (void) GNUNET_HELPER_send (helper_handle,
314 864 &response->shdr,
865 GNUNET_YES,
866 NULL, NULL);
315 GNUNET_free (request); 867 GNUNET_free (request);
316} 868}
317 869
@@ -824,9 +1376,6 @@ process_answer (void *cls,
824 GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail, 1376 GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail,
825 answer_proc_tail, list); 1377 answer_proc_tail, list);
826 1378
827 schedule_helper_write (GNUNET_TIME_UNIT_FOREVER_REL, NULL);
828
829 return;
830} 1379}
831 1380
832 1381
@@ -939,8 +1488,11 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
939 calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr, 1488 calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr,
940 ntohs (pkt->len)); 1489 ntohs (pkt->len));
941 pkt6->udp_hdr.crc = calculate_checksum_end (sum); 1490 pkt6->udp_hdr.crc = calculate_checksum_end (sum);
942 1491
943 write_to_helper (pkt6, size); 1492 (void) GNUNET_HELPER_send (helper_handle,
1493 &pkt6->shdr,
1494 GNUNET_YES,
1495 NULL, NULL);
944 } 1496 }
945 else 1497 else
946 { 1498 {
@@ -1011,7 +1563,10 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1011 pkt4->ip_hdr.chks = 1563 pkt4->ip_hdr.chks =
1012 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); 1564 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1013 1565
1014 write_to_helper (pkt4, size); 1566 (void) GNUNET_HELPER_send (helper_handle,
1567 &pkt4->shdr,
1568 GNUNET_YES,
1569 NULL, NULL);
1015 } 1570 }
1016 1571
1017 return GNUNET_OK; 1572 return GNUNET_OK;
@@ -1113,7 +1668,10 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1113 ntohs (pkt6->ip6_hdr.paylgth)); 1668 ntohs (pkt6->ip6_hdr.paylgth));
1114 pkt6->tcp_hdr.crc = calculate_checksum_end (sum); 1669 pkt6->tcp_hdr.crc = calculate_checksum_end (sum);
1115 1670
1116 write_to_helper (pkt6, size); 1671 (void) GNUNET_HELPER_send (helper_handle,
1672 &pkt6->shdr,
1673 GNUNET_YES,
1674 NULL, NULL);
1117 } 1675 }
1118 else 1676 else
1119 { 1677 {
@@ -1194,7 +1752,11 @@ receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel,
1194 pkt4->ip_hdr.chks = 1752 pkt4->ip_hdr.chks =
1195 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); 1753 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
1196 1754
1197 write_to_helper (pkt4, size); 1755 (void) GNUNET_HELPER_send (helper_handle,
1756 &pkt4->shdr,
1757 GNUNET_YES,
1758 NULL, NULL);
1759
1198 } 1760 }
1199 1761
1200 return GNUNET_OK; 1762 return GNUNET_OK;
@@ -1237,10 +1799,14 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1237 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0}, 1799 {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0},
1238 {NULL, 0, 0} 1800 {NULL, 0, 0}
1239 }; 1801 };
1240
1241 static const GNUNET_MESH_ApplicationType types[] = { 1802 static const GNUNET_MESH_ApplicationType types[] = {
1242 GNUNET_APPLICATION_TYPE_END 1803 GNUNET_APPLICATION_TYPE_END
1243 }; 1804 };
1805 char *ifname;
1806 char *ipv6addr;
1807 char *ipv6prefix;
1808 char *ipv4addr;
1809 char *ipv4mask;
1244 1810
1245 mesh_handle = 1811 mesh_handle =
1246 GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers, 1812 GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers,
@@ -1254,8 +1820,58 @@ run (void *cls, char *const *args GNUNET_UNUSED,
1254 dns_handle = GNUNET_DNS_connect (cfg, 1820 dns_handle = GNUNET_DNS_connect (cfg,
1255 &process_answer, 1821 &process_answer,
1256 NULL); 1822 NULL);
1257 shs_task = 1823 if (GNUNET_SYSERR ==
1258 GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL); 1824 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IFNAME", &ifname))
1825 {
1826 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1827 "No entry 'IFNAME' in configuration!\n");
1828 exit (1);
1829 }
1830
1831 if (GNUNET_SYSERR ==
1832 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr))
1833 {
1834 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1835 "No entry 'IPV6ADDR' in configuration!\n");
1836 exit (1);
1837 }
1838
1839 if (GNUNET_SYSERR ==
1840 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6PREFIX",
1841 &ipv6prefix))
1842 {
1843 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1844 "No entry 'IPV6PREFIX' in configuration!\n");
1845 exit (1);
1846 }
1847
1848 if (GNUNET_SYSERR ==
1849 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr))
1850 {
1851 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1852 "No entry 'IPV4ADDR' in configuration!\n");
1853 exit (1);
1854 }
1855
1856 if (GNUNET_SYSERR ==
1857 GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask))
1858 {
1859 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1860 "No entry 'IPV4MASK' in configuration!\n");
1861 exit (1);
1862 }
1863
1864 vpn_argv[0] = GNUNET_strdup ("vpn-gnunet");
1865 vpn_argv[1] = ifname;
1866 vpn_argv[2] = ipv6addr;
1867 vpn_argv[3] = ipv6prefix;
1868 vpn_argv[4] = ipv4addr;
1869 vpn_argv[5] = ipv4mask;
1870 vpn_argv[6] = NULL;
1871
1872 helper_handle = GNUNET_HELPER_start ("gnunet-helper-vpn", vpn_argv,
1873 &message_token, NULL);
1874 GNUNET_DNS_restart_hijack (dns_handle);
1259 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); 1875 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls);
1260} 1876}
1261 1877