aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorPhilipp Tölke <toelke@in.tum.de>2011-03-14 15:16:29 +0000
committerPhilipp Tölke <toelke@in.tum.de>2011-03-14 15:16:29 +0000
commitf934fdb1b54cc25c3524f76460937a65fd43edeb (patch)
treee39061f806c0dca475019ba98acce56213b94810 /src/vpn
parent236b945be1ccdbaa06792e87e622ead0b2770920 (diff)
downloadgnunet-f934fdb1b54cc25c3524f76460937a65fd43edeb.tar.gz
gnunet-f934fdb1b54cc25c3524f76460937a65fd43edeb.zip
refactor to ease the handling of tcp
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/gnunet-daemon-exit.c280
1 files changed, 157 insertions, 123 deletions
diff --git a/src/vpn/gnunet-daemon-exit.c b/src/vpn/gnunet-daemon-exit.c
index 1c53a83d1..e76c8c32c 100644
--- a/src/vpn/gnunet-daemon-exit.c
+++ b/src/vpn/gnunet-daemon-exit.c
@@ -442,6 +442,135 @@ start_helper_and_schedule(void *cls,
442 GNUNET_free(ifname); 442 GNUNET_free(ifname);
443} 443}
444 444
445static void
446prepare_ipv4_packet (ssize_t len, ssize_t pktlen, void *payload,
447 uint16_t protocol, void *ipaddress, void *tunnel,
448 struct udp_state *state, struct ip_udp *pkt4)
449{
450 uint32_t tmp, tmp2;
451
452 pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
453 pkt4->shdr.size = htons (len);
454 pkt4->tun.flags = 0;
455 pkt4->tun.type = htons (0x0800);
456
457 memcpy (&pkt4->udp_hdr, payload, pktlen);
458
459 pkt4->ip_hdr.version = 4;
460 pkt4->ip_hdr.hdr_lngth = 5;
461 pkt4->ip_hdr.diff_serv = 0;
462 pkt4->ip_hdr.tot_lngth = htons (20 + pktlen);
463 pkt4->ip_hdr.ident = 0;
464 pkt4->ip_hdr.flags = 0;
465 pkt4->ip_hdr.frag_off = 0;
466 pkt4->ip_hdr.ttl = 255;
467 pkt4->ip_hdr.proto = protocol;
468 pkt4->ip_hdr.chks = 0; /* Will be calculated later */
469
470 memcpy (&tmp, ipaddress, 4);
471 pkt4->ip_hdr.dadr = tmp;
472
473 /* Generate a new src-address */
474 char *ipv4addr;
475 char *ipv4mask;
476 GNUNET_assert (GNUNET_OK ==
477 GNUNET_CONFIGURATION_get_value_string (cfg, "exit",
478 "IPV4ADDR",
479 &ipv4addr));
480 GNUNET_assert (GNUNET_OK ==
481 GNUNET_CONFIGURATION_get_value_string (cfg, "exit",
482 "IPV4MASK",
483 &ipv4mask));
484 inet_pton (AF_INET, ipv4addr, &tmp);
485 inet_pton (AF_INET, ipv4mask, &tmp2);
486 GNUNET_free (ipv4addr);
487 GNUNET_free (ipv4mask);
488
489 /* This should be a noop */
490 tmp = tmp & tmp2;
491
492 tmp |= ntohl (*((uint32_t *) tunnel)) & (~tmp2);
493
494 pkt4->ip_hdr.sadr = tmp;
495
496 memcpy (&state->udp_info.addr, &tmp, 4);
497 state->udp_info.pt = pkt4->udp_hdr.spt;
498
499 pkt4->udp_hdr.crc = 0; /* Optional for IPv4 */
500
501 pkt4->ip_hdr.chks =
502 calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4);
503}
504
505static void
506prepare_ipv6_packet (ssize_t len, ssize_t pktlen, void *payload,
507 uint16_t protocol, void *ipaddress, void *tunnel,
508 struct udp_state *state, struct ip6_udp *pkt6)
509{
510 uint32_t tmp;
511
512 pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
513 pkt6->shdr.size = htons (len);
514 pkt6->tun.flags = 0;
515
516 pkt6->tun.type = htons (0x86dd);
517
518 memcpy (&pkt6->udp_hdr, payload, pktlen);
519
520 pkt6->ip6_hdr.version = 6;
521 pkt6->ip6_hdr.nxthdr = protocol;
522 pkt6->ip6_hdr.paylgth = htons (pktlen);
523 pkt6->ip6_hdr.hoplmt = 64;
524
525 memcpy (pkt6->ip6_hdr.dadr, ipaddress, 16);
526
527 /* Generate a new src-address
528 * This takes as much from the address of the tunnel as fits into
529 * the host-mask*/
530 char *ipv6addr;
531 unsigned long long ipv6prefix;
532 GNUNET_assert (GNUNET_OK ==
533 GNUNET_CONFIGURATION_get_value_string (cfg, "exit",
534 "IPV6ADDR",
535 &ipv6addr));
536 GNUNET_assert (GNUNET_OK ==
537 GNUNET_CONFIGURATION_get_value_number (cfg, "exit",
538 "IPV6PREFIX",
539 &ipv6prefix));
540 GNUNET_assert (ipv6prefix < 127);
541 ipv6prefix = (ipv6prefix + 7) / 8;
542
543 inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.sadr);
544 GNUNET_free (ipv6addr);
545
546 if (ipv6prefix < (16 - sizeof (void *)))
547 ipv6prefix = 16 - sizeof (void *);
548
549 unsigned int offset = ipv6prefix - (16 - sizeof (void *));
550 memcpy ((((char *) &pkt6->ip6_hdr.sadr)) + ipv6prefix,
551 ((char *) &tunnel) + offset, 16 - ipv6prefix);
552
553 /* copy the needed information into the state */
554 memcpy (&state->udp_info.addr, &pkt6->ip6_hdr.sadr, 16);
555 state->udp_info.pt = pkt6->udp_hdr.spt;
556
557 pkt6->udp_hdr.crc = 0;
558 uint32_t sum = 0;
559 sum =
560 calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16);
561 sum =
562 calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16);
563 tmp = (htons (pktlen) & 0xffff);
564 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
565 tmp = htons (((pkt6->ip6_hdr.nxthdr & 0x00ff)));
566 sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4);
567
568 sum =
569 calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr,
570 ntohs (pkt6->udp_hdr.len));
571 pkt6->udp_hdr.crc = calculate_checksum_end (sum);
572}
573
445/** 574/**
446 * The messages are one GNUNET_HashCode for the service, followed by a struct udp_pkt 575 * The messages are one GNUNET_HashCode for the service, followed by a struct udp_pkt
447 */ 576 */
@@ -456,8 +585,6 @@ receive_udp_service (void *cls,
456 GNUNET_HashCode hash; 585 GNUNET_HashCode hash;
457 GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1); 586 GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1);
458 struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1); 587 struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1);
459 struct ip6_udp *pkt6;
460 struct ip_udp *pkt4;
461 588
462 GNUNET_assert (ntohs (pkt->len) == 589 GNUNET_assert (ntohs (pkt->len) ==
463 ntohs (message->size) - 590 ntohs (message->size) -
@@ -465,162 +592,69 @@ receive_udp_service (void *cls,
465 sizeof (GNUNET_HashCode)); 592 sizeof (GNUNET_HashCode));
466 593
467 /* Get the configuration from the hashmap */ 594 /* Get the configuration from the hashmap */
468 uint16_t *udp_desc = alloca(sizeof(GNUNET_HashCode)+2); 595 uint16_t *udp_desc = alloca (sizeof (GNUNET_HashCode) + 2);
469 memcpy(udp_desc + 1, desc, sizeof(GNUNET_HashCode)); 596 memcpy (udp_desc + 1, desc, sizeof (GNUNET_HashCode));
470 *udp_desc = ntohs(pkt->dpt); 597 *udp_desc = ntohs (pkt->dpt);
471 GNUNET_CRYPTO_hash(udp_desc, sizeof(GNUNET_HashCode)+2, &hash); 598 GNUNET_CRYPTO_hash (udp_desc, sizeof (GNUNET_HashCode) + 2, &hash);
472 struct udp_service *serv = GNUNET_CONTAINER_multihashmap_get(udp_services, &hash); 599 struct udp_service *serv =
600 GNUNET_CONTAINER_multihashmap_get (udp_services, &hash);
473 if (NULL == serv) 601 if (NULL == serv)
474 { 602 {
475 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "No service found for dpt %d!\n", *udp_desc); 603 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "No service found for dpt %d!\n",
604 *udp_desc);
476 return GNUNET_YES; 605 return GNUNET_YES;
477 } 606 }
478 607
479 pkt->dpt = htons(serv->remote_port); 608 pkt->dpt = htons (serv->remote_port);
480 /* FIXME -> check acl etc */ 609 /* FIXME -> check acl etc */
481 610
482 char* buf; 611 char *buf;
483 size_t len; 612 size_t len;
484 uint32_t tmp, tmp2;
485 613
486 /* Prepare the state. 614 /* Prepare the state.
487 * This will be saved in the hashmap, so that the receiving procedure knows 615 * This will be saved in the hashmap, so that the receiving procedure knows
488 * through which tunnel this connection has to be routed. 616 * through which tunnel this connection has to be routed.
489 */ 617 */
490 struct udp_state *state = GNUNET_malloc (sizeof (struct udp_state)); 618 struct udp_state *state = GNUNET_malloc (sizeof (struct udp_state));
491 memset(state, 0, sizeof(struct udp_state)); 619 memset (state, 0, sizeof (struct udp_state));
492 state->tunnel = tunnel; 620 state->tunnel = tunnel;
493 state->serv = serv; 621 state->serv = serv;
494 memcpy(&state->desc, desc, sizeof(GNUNET_HashCode)); 622 memcpy (&state->desc, desc, sizeof (GNUNET_HashCode));
623
624 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) +
625 sizeof (struct ip6_hdr) + ntohs (pkt->len);
626 buf = alloca (len);
627
628 memset (buf, 0, len);
495 629
496 switch (serv->version) 630 switch (serv->version)
497 { 631 {
498 case 4: 632 case 4:
499 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + 633 prepare_ipv4_packet (len, ntohs (pkt->len), pkt, 0x11, /* UDP */
500 sizeof (struct ip_hdr) + ntohs (pkt->len); 634 &serv->v4.ip4address,
501 pkt4 = alloca(len); 635 tunnel, state, (struct ip_udp *) buf);
502 memset (pkt4, 0, len);
503 buf = (char*)pkt4;
504
505 pkt4->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
506 pkt4->shdr.size = htons(len);
507 pkt4->tun.flags = 0;
508 pkt4->tun.type = htons(0x0800);
509
510 memcpy(&pkt4->udp_hdr, pkt, ntohs(pkt->len));
511
512 pkt4->ip_hdr.version = 4;
513 pkt4->ip_hdr.hdr_lngth = 5;
514 pkt4->ip_hdr.diff_serv = 0;
515 pkt4->ip_hdr.tot_lngth = htons(20 + ntohs(pkt->len));
516 pkt4->ip_hdr.ident = 0;
517 pkt4->ip_hdr.flags = 0;
518 pkt4->ip_hdr.frag_off = 0;
519 pkt4->ip_hdr.ttl = 255;
520 pkt4->ip_hdr.proto = 0x11; /* UDP */
521 pkt4->ip_hdr.chks = 0; /* Will be calculated later*/
522
523 memcpy(&tmp, &serv->v4.ip4address, 4);
524 pkt4->ip_hdr.dadr = tmp;
525
526 /* Generate a new src-address */
527 char* ipv4addr;
528 char* ipv4mask;
529 GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "exit", "IPV4ADDR", &ipv4addr));
530 GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "exit", "IPV4MASK", &ipv4mask));
531 inet_pton(AF_INET, ipv4addr, &tmp);
532 inet_pton(AF_INET, ipv4mask, &tmp2);
533 GNUNET_free(ipv4addr);
534 GNUNET_free(ipv4mask);
535
536 /* This should be a noop */
537 tmp = tmp & tmp2;
538
539 tmp |= ntohl(*((uint32_t*)tunnel)) & (~tmp2);
540
541 pkt4->ip_hdr.sadr = tmp;
542
543 memcpy(&state->udp_info.addr, &tmp, 4);
544 state->udp_info.pt = pkt4->udp_hdr.spt;
545
546 pkt4->udp_hdr.crc = 0; /* Optional for IPv4 */
547
548 pkt4->ip_hdr.chks = calculate_ip_checksum((uint16_t*)&pkt4->ip_hdr, 5*4);
549
550 break; 636 break;
551 case 6: 637 case 6:
552 len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + 638 prepare_ipv6_packet (len, ntohs (pkt->len), pkt, 0x11, /* UDP */
553 sizeof (struct ip6_hdr) + ntohs (pkt->len); 639 &serv->v6.ip6address,
554 pkt6 = 640 tunnel, state, (struct ip6_udp *) buf);
555 alloca (len);
556 memset (pkt6, 0, len);
557 buf =(char*) pkt6;
558
559 pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER);
560 pkt6->shdr.size = htons(len);
561 pkt6->tun.flags = 0;
562 pkt6->tun.type = htons(0x86dd);
563
564 memcpy (&pkt6->udp_hdr, pkt, ntohs (pkt->len));
565
566 pkt6->ip6_hdr.version = 6;
567 pkt6->ip6_hdr.nxthdr = 0x11; //UDP
568 pkt6->ip6_hdr.paylgth = pkt->len;
569 pkt6->ip6_hdr.hoplmt = 64;
570
571 memcpy(pkt6->ip6_hdr.dadr, &serv->v6.ip6address, 16);
572
573 /* Generate a new src-address
574 * This takes as much from the address of the tunnel as fits into
575 * the host-mask*/
576 char* ipv6addr;
577 unsigned long long ipv6prefix;
578 GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "exit", "IPV6ADDR", &ipv6addr));
579 GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "exit", "IPV6PREFIX", &ipv6prefix));
580 GNUNET_assert(ipv6prefix < 127);
581 ipv6prefix = (ipv6prefix + 7)/8;
582
583 inet_pton (AF_INET6, ipv6addr, &pkt6->ip6_hdr.sadr);
584 GNUNET_free(ipv6addr);
585
586 if (ipv6prefix < (16 - sizeof(void*)))
587 ipv6prefix = 16 - sizeof(void*);
588
589 unsigned int offset = ipv6prefix - (16-sizeof(void*));
590 memcpy((((char*)&pkt6->ip6_hdr.sadr))+ipv6prefix, ((char*)&tunnel)+offset, 16 - ipv6prefix);
591
592 /* copy the needed information into the state */
593 memcpy(&state->udp_info.addr, &pkt6->ip6_hdr.sadr, 16);
594 state->udp_info.pt = pkt6->udp_hdr.spt;
595
596 pkt6->udp_hdr.crc = 0;
597 uint32_t sum = 0;
598 sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.sadr, 16);
599 sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.dadr, 16);
600 tmp = (pkt6->udp_hdr.len & 0xffff);
601 sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4);
602 tmp = htons(((pkt6->ip6_hdr.nxthdr & 0x00ff)));
603 sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4);
604
605 sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->udp_hdr, ntohs(pkt6->udp_hdr.len));
606 pkt6->udp_hdr.crc = calculate_checksum_end(sum);
607 641
608 break; 642 break;
609 default: 643 default:
610 GNUNET_assert(0); 644 GNUNET_assert (0);
611 break; 645 break;
612 } 646 }
613 647
614 GNUNET_CRYPTO_hash (&state->udp_info, sizeof(struct udp_info), &hash); 648 GNUNET_CRYPTO_hash (&state->udp_info, sizeof (struct udp_info), &hash);
615 649
616 if (GNUNET_NO == 650 if (GNUNET_NO ==
617 GNUNET_CONTAINER_multihashmap_contains (udp_connections, &hash)) 651 GNUNET_CONTAINER_multihashmap_contains (udp_connections, &hash))
618 GNUNET_CONTAINER_multihashmap_put (udp_connections, &hash, state, 652 GNUNET_CONTAINER_multihashmap_put (udp_connections, &hash, state,
619 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); 653 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
620 else 654 else
621 GNUNET_free(state); 655 GNUNET_free (state);
622 656
623 (void)GNUNET_DISK_file_write(helper_handle->fh_to_helper, buf, len); 657 (void) GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, len);
624 return GNUNET_YES; 658 return GNUNET_YES;
625} 659}
626 660