From: Philipp Tölke Date: Mon, 14 Mar 2011 15:16:31 +0000 (+0000) Subject: Send TCP in both directions: X-Git-Tag: initial-import-from-subversion-38251~18985 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=2ebe944c1ef77807610668fefd716e2adf9a2e9a;p=oweals%2Fgnunet.git Send TCP in both directions: me@harga ~$ time scp philipptoelke.gnunet:tmp/file tmp/d/ file 100% 100MB 4.8MB/s 00:21 real 0m30.588s user 0m1.484s sys 0m0.386s --- diff --git a/src/vpn/gnunet-daemon-exit.c b/src/vpn/gnunet-daemon-exit.c index b6b86cfc8..c30a74e85 100644 --- a/src/vpn/gnunet-daemon-exit.c +++ b/src/vpn/gnunet-daemon-exit.c @@ -174,100 +174,188 @@ send_udp_to_peer_notify_callback (void *cls, size_t size, void *buf) } /** - * Receive packets from the helper-process + * @brief Handles an UDP-Packet received from the helper. + * + * @param udp A pointer to the Packet + * @param dadr The IP-Destination-address + * @param addrlen The length of the address + * @param version 4 or 6 */ static void -message_token (void *cls, - void *client, const struct GNUNET_MessageHeader *message) +udp_from_helper (struct udp_pkt *udp, unsigned char *dadr, size_t addrlen, + unsigned int version) { - GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER); - - struct tun_pkt *pkt_tun = (struct tun_pkt *) message; - - struct GNUNET_MessageHeader *msg; + struct redirect_info u_i; struct GNUNET_MESH_Tunnel *tunnel; uint32_t len; + struct GNUNET_MessageHeader *msg; - struct udp_pkt *udp; - struct redirect_info u_i; - memset(&u_i, 0, sizeof(struct redirect_info)); + memset (&u_i, 0, sizeof (struct redirect_info)); - unsigned int version; - - /* ethertype is ipv6 */ - if (ntohs (pkt_tun->tun.type) == 0x86dd) - { - struct ip6_udp *pkt6 = (struct ip6_udp*)pkt_tun; - if (pkt6->ip6_hdr.nxthdr != 0x11) return; - /* lookup in udp_connections for dpt/dadr*/ - memcpy(&u_i.addr, pkt6->ip6_hdr.dadr, 16); - udp = &pkt6->udp_hdr; - version = 6; - } - else if (ntohs(pkt_tun->tun.type) == 0x0800) - { - struct ip_udp *pkt4 = (struct ip_udp*)pkt_tun; - if (pkt4->ip_hdr.proto != 0x11) return; - uint32_t tmp = pkt4->ip_hdr.dadr; - memcpy(&u_i.addr, &tmp, 4); - udp = &pkt4->udp_hdr; - version = 4; - } - else - { - return; - } + memcpy (&u_i.addr, dadr, addrlen); u_i.pt = udp->dpt; - /* get tunnel and service-descriptor from this*/ + /* get tunnel and service-descriptor from this */ GNUNET_HashCode hash; - GNUNET_CRYPTO_hash(&u_i, sizeof(struct redirect_info), &hash); - struct redirect_state *state = GNUNET_CONTAINER_multihashmap_get(udp_connections, &hash); + GNUNET_CRYPTO_hash (&u_i, sizeof (struct redirect_info), &hash); + struct redirect_state *state = + GNUNET_CONTAINER_multihashmap_get (udp_connections, &hash); tunnel = state->tunnel; - /* check if spt == serv.remote if yes: set spt = serv.myport*/ - if (ntohs(udp->spt) == state->serv->remote_port) + /* check if spt == serv.remote if yes: set spt = serv.myport ("nat") */ + if (ntohs (udp->spt) == state->serv->remote_port) { - udp->spt = htons(state->serv->my_port); + udp->spt = htons (state->serv->my_port); } else { - struct redirect_service *serv = GNUNET_malloc(sizeof(struct redirect_service)); - memcpy(serv, state->serv, sizeof(struct redirect_service)); - serv->my_port = ntohs(udp->spt); - serv->remote_port = ntohs(udp->spt); + struct redirect_service *serv = + GNUNET_malloc (sizeof (struct redirect_service)); + memcpy (serv, state->serv, sizeof (struct redirect_service)); + serv->my_port = ntohs (udp->spt); + serv->remote_port = ntohs (udp->spt); uint16_t *desc = alloca (sizeof (GNUNET_HashCode) + 2); - memcpy((GNUNET_HashCode *) (desc + 1), &state->desc, sizeof(GNUNET_HashCode)); - *desc = ntohs(udp->spt); + memcpy ((GNUNET_HashCode *) (desc + 1), &state->desc, + sizeof (GNUNET_HashCode)); + *desc = ntohs (udp->spt); GNUNET_HashCode hash; GNUNET_CRYPTO_hash (desc, sizeof (GNUNET_HashCode) + 2, &hash); GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (udp_services, - &hash, serv, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + GNUNET_CONTAINER_multihashmap_put (udp_services, + &hash, serv, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); state->serv = serv; } - /* send udp-packet back */ - len = sizeof(struct GNUNET_MessageHeader) + sizeof(GNUNET_HashCode) + ntohs(udp->len); - msg = GNUNET_malloc(len); - msg->size = htons(len); - msg->type = htons(GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK); - GNUNET_HashCode *desc = (GNUNET_HashCode*)(msg+1); - memcpy(desc, &state->desc, sizeof(GNUNET_HashCode)); - void* _udp = desc+1; - memcpy(_udp, udp, ntohs(udp->len)); + /* send udp-packet back */ + len = + sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + + ntohs (udp->len); + msg = GNUNET_malloc (len); + msg->size = htons (len); + msg->type = htons (GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK); + GNUNET_HashCode *desc = (GNUNET_HashCode *) (msg + 1); + memcpy (desc, &state->desc, sizeof (GNUNET_HashCode)); + void *_udp = desc + 1; + memcpy (_udp, udp, ntohs (udp->len)); GNUNET_MESH_notify_transmit_ready (tunnel, - GNUNET_NO, - 42, - GNUNET_TIME_relative_divide(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2), - len, - send_udp_to_peer_notify_callback, - msg); + GNUNET_NO, + 42, + GNUNET_TIME_relative_divide + (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2), + len, send_udp_to_peer_notify_callback, + msg); } +/** + * @brief Handles a TCP-Packet received from the helper. + * + * @param tcp A pointer to the Packet + * @param dadr The IP-Destination-address + * @param addrlen The length of the address + * @param version 4 or 6 + */ +static void +tcp_from_helper (struct tcp_pkt *tcp, unsigned char *dadr, size_t addrlen, + unsigned int version, size_t pktlen) +{ + struct redirect_info u_i; + struct GNUNET_MESH_Tunnel *tunnel; + uint32_t len; + struct GNUNET_MessageHeader *msg; + + memset (&u_i, 0, sizeof (struct redirect_info)); + + memcpy (&u_i.addr, dadr, addrlen); + u_i.pt = tcp->dpt; + + /* get tunnel and service-descriptor from this */ + GNUNET_HashCode hash; + GNUNET_CRYPTO_hash (&u_i, sizeof (struct redirect_info), &hash); + struct redirect_state *state = + GNUNET_CONTAINER_multihashmap_get (tcp_connections, &hash); + + tunnel = state->tunnel; + + /* check if spt == serv.remote if yes: set spt = serv.myport ("nat") */ + if (ntohs (tcp->spt) == state->serv->remote_port) + { + tcp->spt = htons (state->serv->my_port); + } + else + { + // This is an illegal packet. + GNUNET_assert (0); + } + /* send udp-packet back */ + len = + sizeof (struct GNUNET_MessageHeader) + sizeof (GNUNET_HashCode) + pktlen; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "len: %d\n", pktlen); + msg = GNUNET_malloc (len); + msg->size = htons (len); + msg->type = htons (GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK); + GNUNET_HashCode *desc = (GNUNET_HashCode *) (msg + 1); + memcpy (desc, &state->desc, sizeof (GNUNET_HashCode)); + void *_tcp = desc + 1; + memcpy (_tcp, tcp, pktlen); + + GNUNET_MESH_notify_transmit_ready (tunnel, + GNUNET_NO, + 42, + GNUNET_TIME_relative_divide + (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2), + len, send_udp_to_peer_notify_callback, + msg); +} + + +/** + * Receive packets from the helper-process + */ +static void +message_token (void *cls, + void *client, const struct GNUNET_MessageHeader *message) +{ + GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_HELPER); + + struct tun_pkt *pkt_tun = (struct tun_pkt *) message; + + /* ethertype is ipv6 */ + if (ntohs (pkt_tun->tun.type) == 0x86dd) + { + struct ip6_pkt *pkt6 = (struct ip6_pkt *) pkt_tun; + if (0x11 == pkt6->ip6_hdr.nxthdr) + udp_from_helper (&((struct ip6_udp *) pkt6)->udp_hdr, + (unsigned char *) &pkt6->ip6_hdr.dadr, 16, 6); + else if (0x06 == pkt6->ip6_hdr.nxthdr) + tcp_from_helper (&((struct ip6_tcp *) pkt6)->tcp_hdr, + (unsigned char *) &pkt6->ip6_hdr.dadr, 16, 6, + ntohs (pkt6->ip6_hdr.paylgth)); + } + else if (ntohs (pkt_tun->tun.type) == 0x0800) + { + struct ip_pkt *pkt4 = (struct ip_pkt *) pkt_tun; + uint32_t tmp = pkt4->ip_hdr.dadr; + if (0x11 == pkt4->ip_hdr.proto) + udp_from_helper (&((struct ip_udp *) pkt4)->udp_hdr, + (unsigned char *) &tmp, 4, 4); + else if (0x06 == pkt4->ip_hdr.proto) + { + size_t pktlen = ntohs(pkt4->ip_hdr.tot_lngth); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "tot: %d\n", pktlen); + pktlen -= 4*pkt4->ip_hdr.hdr_lngth; + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "-hdr: %d\n", pktlen); + tcp_from_helper (&((struct ip_tcp *) pkt4)->tcp_hdr, + (unsigned char *) &tmp, 4, 4, pktlen); + } + } + else + { + return; + } +} /** * Reads the configuration servicecfg and populates udp_services diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c index 40cf96826..b5f83f9db 100644 --- a/src/vpn/gnunet-daemon-vpn-helper.c +++ b/src/vpn/gnunet-daemon-vpn-helper.c @@ -274,6 +274,9 @@ message_token (void *cls, } else { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Dropping packet. nxthdr=%d, type=%d, dpt=%x, flg=%d, ports=%x\n", + pkt6->ip6_hdr.nxthdr, ntohl(me->desc.service_type), + ntohs(pkt6_tcp->tcp_hdr.dpt), pkt6_tcp->tcp_hdr.flg, me->desc.ports); GNUNET_free (cls); cls = NULL; } diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c index 86a616109..e57a5bf23 100644 --- a/src/vpn/gnunet-daemon-vpn.c +++ b/src/vpn/gnunet-daemon-vpn.c @@ -479,6 +479,80 @@ receive_udp_back (void *cls, struct GNUNET_MESH_Tunnel* tunnel, return GNUNET_OK; } +static int +receive_tcp_back (void *cls, struct GNUNET_MESH_Tunnel* tunnel, + void **tunnel_ctx, + const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) +{ + GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1); + struct tcp_pkt *pkt = (struct tcp_pkt *) (desc + 1); + const struct GNUNET_PeerIdentity* other = GNUNET_MESH_get_peer(tunnel); + + size_t pktlen = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader) - sizeof(GNUNET_HashCode); + size_t size = pktlen + sizeof(struct ip6_tcp) - 1; + + struct ip6_tcp* pkt6 = alloca(size); + + GNUNET_assert(pkt6 != NULL); + + new_ip6addr(pkt6->ip6_hdr.sadr, &other->hashPubKey, desc); + + pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER); + pkt6->shdr.size = htons(size); + + pkt6->tun.flags = 0; + pkt6->tun.type = htons(0x86dd); + + pkt6->ip6_hdr.version = 6; + pkt6->ip6_hdr.tclass_h = 0; + pkt6->ip6_hdr.tclass_l = 0; + pkt6->ip6_hdr.flowlbl = 0; + pkt6->ip6_hdr.paylgth = htons(pktlen); + pkt6->ip6_hdr.nxthdr = 0x06; + pkt6->ip6_hdr.hoplmt = 0xff; + + { + char* ipv6addr; + GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr)); + inet_pton (AF_INET6, ipv6addr, pkt6->ip6_hdr.dadr); + GNUNET_free(ipv6addr); + } + memcpy(&pkt6->tcp_hdr, pkt, pktlen); + + GNUNET_HashCode* key = address_mapping_exists(pkt6->ip6_hdr.sadr); + GNUNET_assert (key != NULL); + + struct map_entry *me = GNUNET_CONTAINER_multihashmap_get(hashmap, key); + + GNUNET_free(key); + + GNUNET_assert (me != NULL); + GNUNET_assert (me->desc.service_type & htonl(GNUNET_DNS_SERVICE_TYPE_TCP)); + + pkt6->tcp_hdr.crc = 0; + uint32_t sum = 0; + uint32_t tmp; + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16); + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16); + tmp = htonl(pktlen); + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + tmp = htonl (((pkt6->ip6_hdr.nxthdr & 0x000000ff))); + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt6->tcp_hdr, + ntohs (pkt6->ip6_hdr.paylgth)); + pkt6->tcp_hdr.crc = calculate_checksum_end (sum); + + write_to_helper(pkt6, size); + + return GNUNET_OK; +} + void init_mesh (void* cls, struct GNUNET_MESH_Handle* server, const struct GNUNET_PeerIdentity* my_identity, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected to MESH, I am %x\n", *((unsigned long*)my_identity)); } @@ -503,6 +577,7 @@ run (void *cls, { const static struct GNUNET_MESH_MessageHandler handlers[] = { {receive_udp_back, GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK, 0}, + {receive_tcp_back, GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK, 0}, {NULL, 0, 0} }; mesh_handle = GNUNET_MESH_connect(cfg_,