diff options
author | Philipp Tölke <toelke@in.tum.de> | 2011-03-14 15:16:29 +0000 |
---|---|---|
committer | Philipp Tölke <toelke@in.tum.de> | 2011-03-14 15:16:29 +0000 |
commit | f934fdb1b54cc25c3524f76460937a65fd43edeb (patch) | |
tree | e39061f806c0dca475019ba98acce56213b94810 /src/vpn | |
parent | 236b945be1ccdbaa06792e87e622ead0b2770920 (diff) | |
download | gnunet-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.c | 280 |
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 | ||
445 | static void | ||
446 | prepare_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 | |||
505 | static void | ||
506 | prepare_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 | ||