X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fvpn%2Fgnunet-daemon-vpn.c;h=cc8001eae412119f28ab7389e5e26f443e17b2b4;hb=83b19539f4d322b43683f5838b72e9ec2c8e6073;hp=8f78073dd2a962c57e57e4d449d2226dc843858e;hpb=32836e0a1ea37c794f740eba5e713c00d44e149c;p=oweals%2Fgnunet.git diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c index 8f78073dd..cc8001eae 100644 --- a/src/vpn/gnunet-daemon-vpn.c +++ b/src/vpn/gnunet-daemon-vpn.c @@ -42,9 +42,17 @@ const struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_MESH_Handle *mesh_handle; -struct GNUNET_CONTAINER_MultiHashMap* hashmap; +struct GNUNET_CONTAINER_MultiHashMap *hashmap; static struct GNUNET_CONTAINER_Heap *heap; +struct tunnel_notify_queue +{ + struct tunnel_notify_queue *next; + struct tunnel_notify_queue *prev; + size_t len; + void *cls; +}; + /** * If there are at least this many address-mappings, old ones will be removed */ @@ -61,106 +69,208 @@ static int ret; */ static struct GNUNET_CONTAINER_MultiHashMap *udp_connections; +GNUNET_SCHEDULER_TaskIdentifier conn_task; + +GNUNET_SCHEDULER_TaskIdentifier shs_task; + /** * Function scheduled as very last function, cleans up after us *{{{ */ static void -cleanup(void* cls __attribute__((unused)), const struct GNUNET_SCHEDULER_TaskContext* tskctx) { - GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); +cleanup (void *cls + __attribute__ ((unused)), + const struct GNUNET_SCHEDULER_TaskContext *tskctx) +{ + GNUNET_assert (0 != (tskctx->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)); - /* stop the helper */ - cleanup_helper(helper_handle); + /* stop the helper */ + cleanup_helper (helper_handle); - /* close the connection to the service-dns */ - if (dns_connection != NULL) - { - GNUNET_CLIENT_disconnect (dns_connection, GNUNET_NO); - dns_connection = NULL; - } + /* close the connection to the service-dns */ + if (dns_connection != NULL) + { + GNUNET_CLIENT_disconnect (dns_connection, GNUNET_NO); + dns_connection = NULL; + } - if (mesh_handle != NULL) - { - GNUNET_MESH_disconnect(mesh_handle); - mesh_handle = NULL; - } + if (mesh_handle != NULL) + { + GNUNET_MESH_disconnect (mesh_handle); + mesh_handle = NULL; + } + if (GNUNET_SCHEDULER_NO_TASK != shs_task) + { + GNUNET_SCHEDULER_cancel (shs_task); + shs_task = GNUNET_SCHEDULER_NO_TASK; + } + if (GNUNET_SCHEDULER_NO_TASK != conn_task) + { + GNUNET_SCHEDULER_cancel (conn_task); + conn_task = GNUNET_SCHEDULER_NO_TASK; + } } + /*}}}*/ /** * @return the hash of the IP-Address if a mapping exists, NULL otherwise */ -GNUNET_HashCode* -address_mapping_exists(unsigned char addr[]) { - GNUNET_HashCode* key = GNUNET_malloc(sizeof(GNUNET_HashCode)); - unsigned char* k = (unsigned char*)key; - memset(key, 0, sizeof(GNUNET_HashCode)); - unsigned int i; - for (i = 0; i < 16; i++) - k[15-i] = addr[i]; +GNUNET_HashCode * +address6_mapping_exists (unsigned char addr[]) +{ + GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode)); + unsigned char *k = (unsigned char *) key; - if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(hashmap, key)) - return key; - else - { - GNUNET_free(key); - return NULL; - } + memset (key, 0, sizeof (GNUNET_HashCode)); + unsigned int i; + + for (i = 0; i < 16; i++) + k[15 - i] = addr[i]; + + if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key)) + return key; + else + { + GNUNET_free (key); + return NULL; + } +} + +/** + * @return the hash of the IP-Address if a mapping exists, NULL otherwise + */ +GNUNET_HashCode * +address4_mapping_exists (uint32_t addr) +{ + GNUNET_HashCode *key = GNUNET_malloc (sizeof (GNUNET_HashCode)); + + memset (key, 0, sizeof (GNUNET_HashCode)); + unsigned char *c = (unsigned char *) &addr; + unsigned char *k = (unsigned char *) key; + unsigned int i; + + for (i = 0; i < 4; i++) + k[3 - i] = c[i]; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "a4_m_e: getting with key %08x, addr is %08x, %d.%d.%d.%d\n", + *((uint32_t *) (key)), addr, c[0], c[1], c[2], c[3]); + + if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (hashmap, key)) + return key; + else + { + GNUNET_free (key); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mapping not found!\n"); + return NULL; + } } static void -collect_mappings(void* cls __attribute__((unused)), const struct GNUNET_SCHEDULER_TaskContext* tc) { - if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; +collect_mappings (void *cls + __attribute__ ((unused)), + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) + return; - struct map_entry* me = GNUNET_CONTAINER_heap_remove_root(heap); + struct map_entry *me = GNUNET_CONTAINER_heap_remove_root (heap); - /* This is free()ed memory! */ - me->heap_node = NULL; + /* This is free()ed memory! */ + me->heap_node = NULL; - /* FIXME! GNUNET_MESH_close_tunnel(me->tunnel); */ + /* FIXME! GNUNET_MESH_close_tunnel(me->tunnel); */ - GNUNET_CONTAINER_multihashmap_remove(hashmap, &me->hash, me); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove (hashmap, &me->hash, me)); - GNUNET_free(me); + GNUNET_free (me); } void -send_icmp_response(void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; +send_icmp4_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) + return; + + struct ip_icmp *request = cls; + + struct ip_icmp *response = alloca (ntohs (request->shdr.size)); + + GNUNET_assert (response != NULL); + memset (response, 0, ntohs (request->shdr.size)); + + response->shdr.size = request->shdr.size; + response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + + response->tun.flags = 0; + response->tun.type = htons (0x0800); + + response->ip_hdr.hdr_lngth = 5; + response->ip_hdr.version = 4; + response->ip_hdr.proto = 0x01; + response->ip_hdr.dadr = request->ip_hdr.sadr; + response->ip_hdr.sadr = request->ip_hdr.dadr; + response->ip_hdr.tot_lngth = request->ip_hdr.tot_lngth; + + response->ip_hdr.chks = + calculate_ip_checksum ((uint16_t *) & response->ip_hdr, 20); + + response->icmp_hdr.code = 0; + response->icmp_hdr.type = 0x0; + + /* Magic, more Magic! */ + response->icmp_hdr.chks = request->icmp_hdr.chks + 0x8; + + /* Copy the rest of the packet */ + memcpy (response + 1, request + 1, + ntohs (request->shdr.size) - sizeof (struct ip_icmp)); + + write_to_helper (response, ntohs (response->shdr.size)); + + GNUNET_free (request); +} + +void +send_icmp6_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) + return; - struct ip6_icmp* request = cls; + struct ip6_icmp *request = cls; - struct ip6_icmp* response = alloca(ntohs(request->shdr.size)); - GNUNET_assert(response != NULL); - memset(response, 0, ntohs(request->shdr.size)); + struct ip6_icmp *response = alloca (ntohs (request->shdr.size)); - response->shdr.size = request->shdr.size; - response->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER); + GNUNET_assert (response != NULL); + memset (response, 0, ntohs (request->shdr.size)); - response->tun.flags = 0; - response->tun.type = htons(0x86dd); + response->shdr.size = request->shdr.size; + response->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); - response->ip6_hdr.hoplmt = 255; - response->ip6_hdr.paylgth = request->ip6_hdr.paylgth; - response->ip6_hdr.nxthdr = 0x3a; - response->ip6_hdr.version = 6; - memcpy(&response->ip6_hdr.sadr, &request->ip6_hdr.dadr, 16); - memcpy(&response->ip6_hdr.dadr, &request->ip6_hdr.sadr, 16); + response->tun.flags = 0; + response->tun.type = htons (0x86dd); - response->icmp_hdr.code = 0; - response->icmp_hdr.type = 0x81; + response->ip6_hdr.hoplmt = 255; + response->ip6_hdr.paylgth = request->ip6_hdr.paylgth; + response->ip6_hdr.nxthdr = 0x3a; + response->ip6_hdr.version = 6; + memcpy (&response->ip6_hdr.sadr, &request->ip6_hdr.dadr, 16); + memcpy (&response->ip6_hdr.dadr, &request->ip6_hdr.sadr, 16); - /* Magic, more Magic! */ - response->icmp_hdr.chks = request->icmp_hdr.chks - 0x1; + response->icmp_hdr.code = 0; + response->icmp_hdr.type = 0x81; - /* Copy the rest of the packet */ - memcpy(response+1, request+1, ntohs(request->shdr.size) - sizeof(struct ip6_icmp)); + /* Magic, more Magic! */ + response->icmp_hdr.chks = request->icmp_hdr.chks - 0x1; - write_to_helper(response, ntohs(response->shdr.size)); + /* Copy the rest of the packet */ + memcpy (response + 1, request + 1, + ntohs (request->shdr.size) - sizeof (struct ip6_icmp)); - GNUNET_free(request); + write_to_helper (response, ntohs (response->shdr.size)); + + GNUNET_free (request); } /** @@ -171,14 +281,46 @@ static size_t send_pkt_to_peer_notify_callback (void *cls, size_t size, void *buf) { struct GNUNET_MESH_Tunnel **tunnel = cls; - struct GNUNET_MessageHeader *hdr = - (struct GNUNET_MessageHeader *) (tunnel + 1); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "send_pkt_to_peer_notify_callback: buf = %x; size = %u;\n", buf, size); - GNUNET_assert (size >= ntohs (hdr->size)); - memcpy (buf, hdr, ntohs (hdr->size)); - size = ntohs(hdr->size); + + struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel); + + ts->th = NULL; + + if (NULL != buf) + { + struct GNUNET_MessageHeader *hdr = + (struct GNUNET_MessageHeader *) (tunnel + 1); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "send_pkt_to_peer_notify_callback: buf = %x; size = %u;\n", buf, + size); + GNUNET_assert (size >= ntohs (hdr->size)); + memcpy (buf, hdr, ntohs (hdr->size)); + size = ntohs (hdr->size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent!\n"); + } + else + size = 0; + + if (NULL != ts->head) + { + struct tunnel_notify_queue *element = ts->head; + + GNUNET_CONTAINER_DLL_remove (ts->head, ts->tail, element); + + ts->th = + GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42, + GNUNET_TIME_relative_divide + (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2), + (const struct GNUNET_PeerIdentity *) + NULL, element->len, + send_pkt_to_peer_notify_callback, + element->cls); + + /* save the handle */ + GNUNET_free (element); + } GNUNET_free (cls); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent!\n"); + return size; } @@ -186,59 +328,87 @@ unsigned int port_in_ports (uint64_t ports, uint16_t port) { uint16_t *ps = (uint16_t *) & ports; - return ps[0] == port || ps[1] == port || ps[2] == port || ps[3] == port; + + return ports == 0 || ps[0] == port || ps[1] == port || ps[2] == port || + ps[3] == port; } void -send_pkt_to_peer (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused))) +send_pkt_to_peer (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_ATS_Information *atsi + __attribute__ ((unused))) { /* peer == NULL means that all peers in this request are connected */ - if (peer == NULL) return; + if (peer == NULL) + return; struct GNUNET_MESH_Tunnel **tunnel = cls; struct GNUNET_MessageHeader *hdr = - (struct GNUNET_MessageHeader *) (tunnel + 1); - - GNUNET_assert(NULL != tunnel); - GNUNET_assert(NULL != *tunnel); - - GNUNET_MESH_notify_transmit_ready (*tunnel, - GNUNET_NO, - 42, - GNUNET_TIME_relative_divide(GNUNET_CONSTANTS_MAX_CORK_DELAY, 2), - (const struct GNUNET_PeerIdentity *)NULL, - ntohs(hdr->size), - send_pkt_to_peer_notify_callback, - cls); + (struct GNUNET_MessageHeader *) (tunnel + 1); + + GNUNET_assert (NULL != tunnel); + GNUNET_assert (NULL != *tunnel); + + struct tunnel_state *ts = GNUNET_MESH_tunnel_get_data (*tunnel); + + if (NULL == ts->th) + { + ts->th = + GNUNET_MESH_notify_transmit_ready (*tunnel, GNUNET_NO, 42, + GNUNET_TIME_relative_divide + (GNUNET_CONSTANTS_MAX_CORK_DELAY, 2), + (const struct GNUNET_PeerIdentity *) + NULL, ntohs (hdr->size), + send_pkt_to_peer_notify_callback, + cls); + } + else + { + struct tunnel_notify_queue *element = GNUNET_malloc (sizeof *element); + + element->cls = cls; + element->len = ntohs (hdr->size); + + GNUNET_CONTAINER_DLL_insert_tail (ts->head, ts->tail, element); + } } /** * Create a new Address from an answer-packet */ void -new_ip6addr(unsigned char* buf, const GNUNET_HashCode *peer, const GNUNET_HashCode *service_desc) { /* {{{ */ - char* ipv6addr; - unsigned long long ipv6prefix; - GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "vpn", "IPV6ADDR", &ipv6addr)); - GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "vpn", "IPV6PREFIX", &ipv6prefix)); - GNUNET_assert(ipv6prefix < 127); - ipv6prefix = (ipv6prefix + 7)/8; - - inet_pton (AF_INET6, ipv6addr, buf); - GNUNET_free(ipv6addr); - - int peer_length = 16 - ipv6prefix - 6; - if (peer_length <= 0) - peer_length = 0; - - int service_length = 16 - ipv6prefix - peer_length; - if (service_length <= 0) - service_length = 0; - - memcpy(buf+ipv6prefix, service_desc, service_length); - memcpy(buf+ipv6prefix+service_length, peer, peer_length); +new_ip6addr (unsigned char *buf, const GNUNET_HashCode * peer, + const GNUNET_HashCode * service_desc) +{ /* {{{ */ + char *ipv6addr; + unsigned long long ipv6prefix; + + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", + &ipv6addr)); + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", + "IPV6PREFIX", + &ipv6prefix)); + GNUNET_assert (ipv6prefix < 127); + ipv6prefix = (ipv6prefix + 7) / 8; + + inet_pton (AF_INET6, ipv6addr, buf); + GNUNET_free (ipv6addr); + + int peer_length = 16 - ipv6prefix - 6; + + if (peer_length <= 0) + peer_length = 0; + + int service_length = 16 - ipv6prefix - peer_length; + + if (service_length <= 0) + service_length = 0; + + memcpy (buf + ipv6prefix, service_desc, service_length); + memcpy (buf + ipv6prefix + service_length, peer, peer_length); } + /*}}}*/ @@ -250,9 +420,9 @@ new_ip6addr_remote (unsigned char *buf, unsigned char *addr, char addrlen) { /* {{{ */ char *ipv6addr; unsigned long long ipv6prefix; + GNUNET_assert (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", - "IPV6ADDR", + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV6ADDR", &ipv6addr)); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", @@ -266,8 +436,66 @@ new_ip6addr_remote (unsigned char *buf, unsigned char *addr, char addrlen) int local_length = 16 - ipv6prefix; - memcpy (buf + ipv6prefix, addr, GNUNET_MAX (addrlen, local_length)); + memcpy (buf + ipv6prefix, addr, GNUNET_MIN (addrlen, local_length)); } + +/*}}}*/ + +/** + * Create a new Address from an answer-packet + */ +void +new_ip4addr_remote (unsigned char *buf, unsigned char *addr, char addrlen) +{ /* {{{ */ + char *ipv4addr; + char *ipv4mask; + + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", + &ipv4addr)); + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", + &ipv4mask)); + uint32_t mask; + + inet_pton (AF_INET, ipv4addr, buf); + int r = inet_pton (AF_INET, ipv4mask, &mask); + + mask = htonl (mask); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inet_pton: %d; %m; mask: %08x\n", r, + mask); + + GNUNET_free (ipv4addr); + + int c; + + if (mask) + { + mask = (mask ^ (mask - 1)) >> 1; + for (c = 0; mask; c++) + { + mask >>= 1; + } + } + else + { + c = CHAR_BIT * sizeof (mask); + } + + c = 32 - c; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "The mask %s has %d leading 1s.\n", + ipv4mask, c); + + GNUNET_free (ipv4mask); + + if (c % 8 == 0) + c = c / 8; + else + GNUNET_assert (0); + + memcpy (buf + c, addr, GNUNET_MIN (addrlen, 4 - c)); +} + /*}}}*/ /** @@ -278,188 +506,286 @@ new_ip6addr_remote (unsigned char *buf, unsigned char *addr, char addrlen) * doing nothing for "real" services. */ void -process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { - if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - return; +process_answer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) + return; + + struct answer_packet *pkt = cls; + struct answer_packet_list *list; + + /* This answer is about a .gnunet-service + * + * It contains an almost complete DNS-Response, we have to fill in the ip + * at the offset pkt->addroffset + */ + if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_SERVICE) + { + pkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP; - struct answer_packet* pkt = cls; - struct answer_packet_list* list; + GNUNET_HashCode key; - /* This answer is about a .gnunet-service - * - * It contains an almost complete DNS-Response, we have to fill in the ip - * at the offset pkt->addroffset + memset (&key, 0, sizeof (GNUNET_HashCode)); + + unsigned char *c = ((unsigned char *) pkt) + ntohs (pkt->addroffset); + unsigned char *k = (unsigned char *) &key; + + new_ip6addr (c, &pkt->service_descr.peer, + &pkt->service_descr.service_descriptor); + /* + * Copy the newly generated ip-address to the key backwarts (as only the first part is hashed) */ - if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_SERVICE) - { - pkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP; + unsigned int i; + + for (i = 0; i < 16; i++) + k[15 - i] = c[i]; + + uint16_t namelen = strlen ((char *) pkt->data + 12) + 1; + + struct map_entry *value = + GNUNET_malloc (sizeof (struct map_entry) + namelen); + char *name = (char *) (value + 1); + + value->namelen = namelen; + memcpy (name, pkt->data + 12, namelen); - GNUNET_HashCode key; - memset(&key, 0, sizeof(GNUNET_HashCode)); + memcpy (&value->desc, &pkt->service_descr, + sizeof (struct GNUNET_vpn_service_descriptor)); - unsigned char* c = ((unsigned char*)pkt)+ntohs(pkt->addroffset); - unsigned char* k = (unsigned char*)&key; - new_ip6addr(c, &pkt->service_descr.peer, &pkt->service_descr.service_descriptor); - /* - * Copy the newly generated ip-address to the key backwarts (as only the first part is hashed) - */ - unsigned int i; - for (i = 0; i < 16; i++) - k[15-i] = c[i]; + memset (value->additional_ports, 0, 8192); - uint16_t namelen = strlen((char*)pkt->data+12)+1; + memcpy (&value->hash, &key, sizeof (GNUNET_HashCode)); - struct map_entry* value = GNUNET_malloc(sizeof(struct map_entry) + namelen); - char* name = (char*)(value +1); + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (hashmap, &key)) + { + GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + + value->heap_node = + GNUNET_CONTAINER_heap_insert (heap, value, + GNUNET_TIME_absolute_get ().abs_value); + if (GNUNET_CONTAINER_heap_get_size (heap) > max_mappings) + GNUNET_SCHEDULER_add_now (collect_mappings, NULL); + } + else + GNUNET_free (value); + + + list = + GNUNET_malloc (htons (pkt->hdr.size) + + sizeof (struct answer_packet_list) - + sizeof (struct answer_packet)); - value->namelen = namelen; - memcpy(name, pkt->data+12, namelen); + memcpy (&list->pkt, pkt, htons (pkt->hdr.size)); - memcpy(&value->desc, &pkt->service_descr, sizeof(struct GNUNET_vpn_service_descriptor)); + } + else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_REV) + { + GNUNET_HashCode key; - memset(value->additional_ports, 0, 8192); + memset (&key, 0, sizeof key); + unsigned char *k = (unsigned char *) &key; + unsigned char *s = pkt->data + 12; + int i = 0; - memcpy(&value->hash, &key, sizeof(GNUNET_HashCode)); + /* Whoever designed the reverse IPv6-lookup is batshit insane */ + for (i = 0; i < 16; i++) + { + unsigned char c1 = s[(4 * i) + 1]; + unsigned char c2 = s[(4 * i) + 3]; + + if (c1 <= '9') + k[i] = c1 - '0'; + else + k[i] = c1 - 87; /* 87 is the difference between 'a' and 10 */ + if (c2 <= '9') + k[i] += 16 * (c2 - '0'); + else + k[i] += 16 * (c2 - 87); + } - if (GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (hashmap, &key)) - { - GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + struct map_entry *map_entry = + GNUNET_CONTAINER_multihashmap_get (hashmap, &key); + uint16_t offset = ntohs (pkt->addroffset); - value->heap_node = GNUNET_CONTAINER_heap_insert (heap, value, - GNUNET_TIME_absolute_get ().abs_value); - if (GNUNET_CONTAINER_heap_get_size(heap) > max_mappings) - GNUNET_SCHEDULER_add_now(collect_mappings, NULL); - } - else - GNUNET_free(value); + if (map_entry == NULL) + { + GNUNET_free (pkt); + return; + } + GNUNET_CONTAINER_heap_update_cost (heap, map_entry->heap_node, + GNUNET_TIME_absolute_get ().abs_value); - list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*)); - memcpy(&list->pkt, pkt, htons(pkt->hdr.size)); + unsigned short namelen = htons (map_entry->namelen); + char *name = (char *) (map_entry + 1); - } - else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_REV) - { - GNUNET_HashCode key; - memset(&key, 0, sizeof key); - unsigned char* k = (unsigned char*)&key; - unsigned char* s = pkt->data+12; - int i = 0; - /* Whoever designed the reverse IPv6-lookup is batshit insane */ - for (i = 0; i < 16; i++) - { - unsigned char c1 = s[(4*i)+1]; - unsigned char c2 = s[(4*i)+3]; - if (c1 <= '9') - k[i] = c1 - '0'; - else - k[i] = c1 - 87; /* 87 is the difference between 'a' and 10 */ - if (c2 <= '9') - k[i] += 16*(c2 - '0'); - else - k[i] += 16*(c2 - 87); - } - - struct map_entry* map_entry = GNUNET_CONTAINER_multihashmap_get(hashmap, &key); - uint16_t offset = ntohs(pkt->addroffset); - - if (map_entry == NULL) - { - GNUNET_free(pkt); - return; - } - - GNUNET_CONTAINER_heap_update_cost (heap, map_entry->heap_node, - GNUNET_TIME_absolute_get ().abs_value); - - - unsigned short namelen = htons(map_entry->namelen); - char* name = (char*)(map_entry + 1); - - list = GNUNET_malloc(2*sizeof(struct answer_packet_list*) + offset + 2 + ntohs(namelen)); - - struct answer_packet* rpkt = &list->pkt; - - /* The offset points to the first byte belonging to the address */ - memcpy(rpkt, pkt, offset - 1); - - rpkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP; - rpkt->hdr.size = ntohs(offset + 2 + ntohs(namelen)); - - memcpy(((char*)rpkt)+offset, &namelen, 2); - memcpy(((char*)rpkt)+offset+2, name, ntohs(namelen)); + list = + GNUNET_malloc (sizeof (struct answer_packet_list) - + sizeof (struct answer_packet) + offset + 2 + + ntohs (namelen)); - } - else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_IP) - { - list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*)); - memcpy(&list->pkt, pkt, htons(pkt->hdr.size)); - } - else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_REMOTE) - { - pkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP; - - GNUNET_HashCode key; - memset(&key, 0, sizeof(GNUNET_HashCode)); - - unsigned char* c = ((unsigned char*)pkt)+ntohs(pkt->addroffset); - new_ip6addr_remote(c, pkt->addr, pkt->addrsize); - unsigned char* k = (unsigned char*)&key; - /* - * Copy the newly generated ip-address to the key backwards (as only the first part is used in the hash-table) - */ - unsigned int i; - for (i = 0; i < 16; i++) - k[15-i] = c[i]; - - uint16_t namelen = strlen((char*)pkt->data+12)+1; - - struct map_entry* value = GNUNET_malloc(sizeof(struct map_entry) + namelen); - char* name = (char*)(value +1); - - value->namelen = namelen; - memcpy(name, pkt->data+12, namelen); - - value->addrlen = pkt->addrsize; - memcpy(&value->addr, &pkt->addr, pkt->addrsize); - memset(value->additional_ports, 0, 8192); - - memcpy(&value->hash, &key, sizeof(GNUNET_HashCode)); - - if (GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (hashmap, &key)) - { - GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); - value->heap_node = GNUNET_CONTAINER_heap_insert (heap, value, - GNUNET_TIME_absolute_get ().abs_value); - if (GNUNET_CONTAINER_heap_get_size(heap) > max_mappings) - GNUNET_SCHEDULER_add_now(collect_mappings, NULL); - } - else - GNUNET_free(value); - - list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*)); - - memcpy(&list->pkt, pkt, htons(pkt->hdr.size)); - } + struct answer_packet *rpkt = &list->pkt; + + /* The offset points to the first byte belonging to the address */ + memcpy (rpkt, pkt, offset - 1); + + rpkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP; + rpkt->hdr.size = ntohs (offset + 2 + ntohs (namelen)); + + memcpy (((char *) rpkt) + offset, &namelen, 2); + memcpy (((char *) rpkt) + offset + 2, name, ntohs (namelen)); + + } + else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_IP) + { + list = + GNUNET_malloc (htons (pkt->hdr.size) + + sizeof (struct answer_packet_list) - + sizeof (struct answer_packet)); + memcpy (&list->pkt, pkt, htons (pkt->hdr.size)); + } + else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_REMOTE_AAAA) + { + pkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP; + + GNUNET_HashCode key; + + memset (&key, 0, sizeof (GNUNET_HashCode)); + + unsigned char *c = ((unsigned char *) pkt) + ntohs (pkt->addroffset); + + new_ip6addr_remote (c, pkt->addr, pkt->addrsize); + 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", + c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], + c[10], c[11], c[12], c[13], c[14], c[15]); + unsigned char *k = (unsigned char *) &key; + + /* + * Copy the newly generated ip-address to the key backwards (as only the first part is used in the hash-table) + */ + unsigned int i; + + for (i = 0; i < 16; i++) + k[15 - i] = c[i]; + + uint16_t namelen = strlen ((char *) pkt->data + 12) + 1; + + struct map_entry *value = + GNUNET_malloc (sizeof (struct map_entry) + namelen); + char *name = (char *) (value + 1); + + value->namelen = namelen; + memcpy (name, pkt->data + 12, namelen); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting addrlen to %d\n", + pkt->addrsize); + value->addrlen = pkt->addrsize; + memcpy (&value->addr, &pkt->addr, pkt->addrsize); + memset (value->additional_ports, 0, 8192); + + memcpy (&value->hash, &key, sizeof (GNUNET_HashCode)); + + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (hashmap, &key)) + { + GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + value->heap_node = + GNUNET_CONTAINER_heap_insert (heap, value, + GNUNET_TIME_absolute_get ().abs_value); + if (GNUNET_CONTAINER_heap_get_size (heap) > max_mappings) + GNUNET_SCHEDULER_add_now (collect_mappings, NULL); + } else - { - GNUNET_break(0); - GNUNET_free(pkt); - return; - } + GNUNET_free (value); + + list = + GNUNET_malloc (htons (pkt->hdr.size) + + sizeof (struct answer_packet_list) - + sizeof (struct answer_packet)); + + memcpy (&list->pkt, pkt, htons (pkt->hdr.size)); + } + else if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_REMOTE_A) + { + pkt->subtype = GNUNET_DNS_ANSWER_TYPE_IP; + + GNUNET_HashCode key; + + memset (&key, 0, sizeof (GNUNET_HashCode)); + + unsigned char *c = ((unsigned char *) pkt) + ntohs (pkt->addroffset); + + new_ip4addr_remote (c, pkt->addr, pkt->addrsize); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New mapping to %d.%d.%d.%d\n", c[0], + c[1], c[2], c[3]); + unsigned char *k = (unsigned char *) &key; + + /* + * Copy the newly generated ip-address to the key backwards (as only the first part is used in the hash-table) + */ + unsigned int i; + + for (i = 0; i < 4; i++) + k[3 - i] = c[i]; + + uint16_t namelen = strlen ((char *) pkt->data + 12) + 1; - GNUNET_free(pkt); + struct map_entry *value = + GNUNET_malloc (sizeof (struct map_entry) + namelen); + char *name = (char *) (value + 1); - GNUNET_CONTAINER_DLL_insert_after(answer_proc_head, answer_proc_tail, answer_proc_tail, list); + value->namelen = namelen; + memcpy (name, pkt->data + 12, namelen); - schedule_helper_write(GNUNET_TIME_UNIT_FOREVER_REL, NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting addrlen to %d\n", + pkt->addrsize); + value->addrlen = pkt->addrsize; + memcpy (&value->addr, &pkt->addr, pkt->addrsize); + memset (value->additional_ports, 0, 8192); + memcpy (&value->hash, &key, sizeof (GNUNET_HashCode)); + + if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (hashmap, &key)) + { + GNUNET_CONTAINER_multihashmap_put (hashmap, &key, value, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + value->heap_node = + GNUNET_CONTAINER_heap_insert (heap, value, + GNUNET_TIME_absolute_get ().abs_value); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Mapping is saved in the hashmap with key %08x.\n", + *((uint32_t *) (&key))); + if (GNUNET_CONTAINER_heap_get_size (heap) > max_mappings) + GNUNET_SCHEDULER_add_now (collect_mappings, NULL); + } + else + GNUNET_free (value); + + list = + GNUNET_malloc (htons (pkt->hdr.size) + + sizeof (struct answer_packet_list) - + sizeof (struct answer_packet)); + + memcpy (&list->pkt, pkt, htons (pkt->hdr.size)); + } + else + { + GNUNET_break (0); + GNUNET_free (pkt); return; + } + + GNUNET_free (pkt); + + GNUNET_CONTAINER_DLL_insert_after (answer_proc_head, answer_proc_tail, + answer_proc_tail, list); + + schedule_helper_write (GNUNET_TIME_UNIT_FOREVER_REL, NULL); + + return; } /** @@ -526,174 +852,390 @@ testBit (char *bitArray, unsigned int bitIdx) static void add_additional_port (struct map_entry *me, uint16_t port) { - setBit(me->additional_ports, port); + setBit (me->additional_ports, port); } static int -receive_udp_back (void *cls __attribute__((unused)), struct GNUNET_MESH_Tunnel* tunnel, - void **tunnel_ctx __attribute__((unused)), - const struct GNUNET_PeerIdentity *sender __attribute__((unused)), - const struct GNUNET_MessageHeader *message, - const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused))) +receive_udp_back (void *cls + __attribute__ ((unused)), struct GNUNET_MESH_Tunnel *tunnel, + void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_ATS_Information *atsi + __attribute__ ((unused))) { GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1); - struct remote_addr* s = (struct remote_addr*)desc; + struct remote_addr *s = (struct remote_addr *) desc; struct udp_pkt *pkt = (struct udp_pkt *) (desc + 1); - const struct GNUNET_PeerIdentity* other = GNUNET_MESH_get_peer(tunnel); + const struct GNUNET_PeerIdentity *other = sender; + struct tunnel_state *ts = *tunnel_ctx; - size_t size = sizeof(struct ip6_udp) + ntohs(pkt->len) - 1 - sizeof(struct udp_pkt); + if (16 == ts->addrlen) + { + size_t size = + sizeof (struct ip6_udp) + ntohs (pkt->len) - 1 - + sizeof (struct udp_pkt); - struct ip6_udp* pkt6 = alloca(size); + struct ip6_udp *pkt6 = alloca (size); - GNUNET_assert(pkt6 != NULL); + GNUNET_assert (pkt6 != NULL); - if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK) - new_ip6addr(pkt6->ip6_hdr.sadr, &other->hashPubKey, desc); - else - new_ip6addr_remote(pkt6->ip6_hdr.sadr, s->addr, s->addrlen); + if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK) + new_ip6addr (pkt6->ip6_hdr.sadr, &other->hashPubKey, desc); + else + new_ip6addr_remote (pkt6->ip6_hdr.sadr, s->addr, s->addrlen); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Relaying calc:%d gnu:%d udp:%d bytes!\n", size, ntohs(message->size), ntohs(pkt->len)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Relaying calc:%d gnu:%d udp:%d bytes!\n", size, + ntohs (message->size), ntohs (pkt->len)); - pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER); - pkt6->shdr.size = htons(size); + pkt6->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + pkt6->shdr.size = htons (size); - pkt6->tun.flags = 0; - pkt6->tun.type = htons(0x86dd); + 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 = pkt->len; - pkt6->ip6_hdr.nxthdr = 0x11; - pkt6->ip6_hdr.hoplmt = 0xff; + 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 = pkt->len; + pkt6->ip6_hdr.nxthdr = IPPROTO_UDP; + 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->udp_hdr, pkt, ntohs(pkt->len)); + { + 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->udp_hdr, pkt, ntohs (pkt->len)); + + GNUNET_HashCode *key = address6_mapping_exists (pkt6->ip6_hdr.sadr); + + GNUNET_assert (key != NULL); - GNUNET_HashCode* key = address_mapping_exists(pkt6->ip6_hdr.sadr); - GNUNET_assert (key != NULL); + struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); - struct map_entry *me = GNUNET_CONTAINER_multihashmap_get(hashmap, key); - GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, - GNUNET_TIME_absolute_get ().abs_value); + GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, + GNUNET_TIME_absolute_get ().abs_value); - GNUNET_free(key); + GNUNET_free (key); - GNUNET_assert (me != NULL); - if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK) + GNUNET_assert (me != NULL); + if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK) { - GNUNET_assert (me->desc.service_type & htonl(GNUNET_DNS_SERVICE_TYPE_UDP)); - if (!port_in_ports(me->desc.ports, pkt6->udp_hdr.spt) && - !testBit(me->additional_ports, ntohs(pkt6->udp_hdr.spt))) { - add_additional_port(me, ntohs(pkt6->udp_hdr.spt)); + GNUNET_assert (me->desc. + service_type & htonl (GNUNET_DNS_SERVICE_TYPE_UDP)); + if (!port_in_ports (me->desc.ports, pkt6->udp_hdr.spt) && + !testBit (me->additional_ports, ntohs (pkt6->udp_hdr.spt))) + { + add_additional_port (me, ntohs (pkt6->udp_hdr.spt)); } } - pkt6->udp_hdr.crc = 0; - uint32_t sum = 0; - sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.sadr, 16); - sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->ip6_hdr.dadr, 16); - uint32_t tmp = (pkt6->udp_hdr.len & 0xffff); - sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4); - tmp = htons(((pkt6->ip6_hdr.nxthdr & 0x00ff))); - sum = calculate_checksum_update(sum, (uint16_t*)&tmp, 4); + pkt6->udp_hdr.crc = 0; + uint32_t sum = 0; + + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.sadr, 16); + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt6->ip6_hdr.dadr, 16); + uint32_t tmp = (pkt6->udp_hdr.len & 0xffff); + + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + tmp = htons (((pkt6->ip6_hdr.nxthdr & 0x00ff))); + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt6->udp_hdr, + ntohs (pkt->len)); + pkt6->udp_hdr.crc = calculate_checksum_end (sum); + + write_to_helper (pkt6, size); + } + else + { + size_t size = + sizeof (struct ip_udp) + ntohs (pkt->len) - 1 - sizeof (struct udp_pkt); + + struct ip_udp *pkt4 = alloca (size); + + GNUNET_assert (pkt4 != NULL); + + GNUNET_assert (ntohs (message->type) == + GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK); + uint32_t sadr; + + new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen); + pkt4->ip_hdr.sadr = sadr; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Relaying calc:%d gnu:%d udp:%d bytes!\n", size, + ntohs (message->size), ntohs (pkt->len)); + + pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + pkt4->shdr.size = htons (size); + + pkt4->tun.flags = 0; + pkt4->tun.type = htons (0x0800); + + pkt4->ip_hdr.version = 4; + pkt4->ip_hdr.hdr_lngth = 5; + pkt4->ip_hdr.diff_serv = 0; + pkt4->ip_hdr.tot_lngth = htons (20 + ntohs (pkt->len)); + pkt4->ip_hdr.ident = 0; + pkt4->ip_hdr.flags = 0; + pkt4->ip_hdr.frag_off = 0; + pkt4->ip_hdr.ttl = 255; + pkt4->ip_hdr.proto = IPPROTO_UDP; + pkt4->ip_hdr.chks = 0; /* Will be calculated later */ + + { + char *ipv4addr; + uint32_t dadr; + + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", + "IPV4ADDR", + &ipv4addr)); + inet_pton (AF_INET, ipv4addr, &dadr); + GNUNET_free (ipv4addr); + pkt4->ip_hdr.dadr = dadr; + } + memcpy (&pkt4->udp_hdr, pkt, ntohs (pkt->len)); + + GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr); + + GNUNET_assert (key != NULL); + + struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); - sum = calculate_checksum_update(sum, (uint16_t*)&pkt6->udp_hdr, ntohs(pkt->len)); - pkt6->udp_hdr.crc = calculate_checksum_end(sum); + GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, + GNUNET_TIME_absolute_get ().abs_value); - write_to_helper(pkt6, size); + GNUNET_free (key); + + GNUNET_assert (me != NULL); + + pkt4->udp_hdr.crc = 0; /* Optional for IPv4 */ + + pkt4->ip_hdr.chks = + calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); + + write_to_helper (pkt4, size); + } return GNUNET_OK; } static int -receive_tcp_back (void *cls __attribute__((unused)), struct GNUNET_MESH_Tunnel* tunnel, - void **tunnel_ctx __attribute__((unused)), - const struct GNUNET_PeerIdentity *sender __attribute__((unused)), - const struct GNUNET_MessageHeader *message, - const struct GNUNET_TRANSPORT_ATS_Information *atsi __attribute__((unused))) +receive_tcp_back (void *cls + __attribute__ ((unused)), struct GNUNET_MESH_Tunnel *tunnel, + void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender + __attribute__ ((unused)), + const struct GNUNET_MessageHeader *message, + const struct GNUNET_ATS_Information *atsi + __attribute__ ((unused))) { GNUNET_HashCode *desc = (GNUNET_HashCode *) (message + 1); - struct remote_addr* s = (struct remote_addr*)desc; + struct remote_addr *s = (struct remote_addr *) desc; struct tcp_pkt *pkt = (struct tcp_pkt *) (desc + 1); - const struct GNUNET_PeerIdentity* other = GNUNET_MESH_get_peer(tunnel); + const struct GNUNET_PeerIdentity *other = sender; + struct tunnel_state *ts = *tunnel_ctx; - size_t pktlen = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader) - sizeof(GNUNET_HashCode); - size_t size = pktlen + sizeof(struct ip6_tcp) - 1; + size_t pktlen = + ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) - + sizeof (GNUNET_HashCode); - struct ip6_tcp* pkt6 = alloca(size); - memset(pkt6, 0, size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received TCP-Packet back, addrlen = %d\n", s->addrlen); - GNUNET_assert(pkt6 != NULL); + if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK || + ts->addrlen == 16) + { + size_t size = pktlen + sizeof (struct ip6_tcp) - 1; - if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_TCP_BACK) - new_ip6addr(pkt6->ip6_hdr.sadr, &other->hashPubKey, desc); - else - new_ip6addr_remote(pkt6->ip6_hdr.sadr, s->addr, s->addrlen); + struct ip6_tcp *pkt6 = alloca (size); - pkt6->shdr.type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER); - pkt6->shdr.size = htons(size); + memset (pkt6, 0, size); - pkt6->tun.flags = 0; - pkt6->tun.type = htons(0x86dd); + GNUNET_assert (pkt6 != NULL); - 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; + if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK) + new_ip6addr (pkt6->ip6_hdr.sadr, &other->hashPubKey, desc); + else + new_ip6addr_remote (pkt6->ip6_hdr.sadr, s->addr, s->addrlen); - { - 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); + 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 = IPPROTO_TCP; + 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 = address6_mapping_exists (pkt6->ip6_hdr.sadr); + + GNUNET_assert (key != NULL); + + struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); + + GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, + GNUNET_TIME_absolute_get ().abs_value); + + GNUNET_free (key); + + GNUNET_assert (me != NULL); + if (ntohs (message->type) == GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK) + 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); } - memcpy(&pkt6->tcp_hdr, pkt, pktlen); + else + { + size_t size = pktlen + sizeof (struct ip_tcp) - 1; + + struct ip_tcp *pkt4 = alloca (size); + + GNUNET_assert (pkt4 != NULL); + memset (pkt4, 0, size); + + GNUNET_assert (ntohs (message->type) == + GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK); + uint32_t sadr; + + new_ip4addr_remote ((unsigned char *) &sadr, s->addr, s->addrlen); + pkt4->ip_hdr.sadr = sadr; - GNUNET_HashCode* key = address_mapping_exists(pkt6->ip6_hdr.sadr); - GNUNET_assert (key != NULL); + pkt4->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + pkt4->shdr.size = htons (size); + + pkt4->tun.flags = 0; + pkt4->tun.type = htons (0x0800); + + pkt4->ip_hdr.version = 4; + pkt4->ip_hdr.hdr_lngth = 5; + pkt4->ip_hdr.diff_serv = 0; + pkt4->ip_hdr.tot_lngth = htons (20 + pktlen); + pkt4->ip_hdr.ident = 0; + pkt4->ip_hdr.flags = 0; + pkt4->ip_hdr.frag_off = 0; + pkt4->ip_hdr.ttl = 255; + pkt4->ip_hdr.proto = IPPROTO_TCP; + pkt4->ip_hdr.chks = 0; /* Will be calculated later */ + + { + char *ipv4addr; + uint32_t dadr; + + GNUNET_assert (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", + "IPV4ADDR", + &ipv4addr)); + inet_pton (AF_INET, ipv4addr, &dadr); + GNUNET_free (ipv4addr); + pkt4->ip_hdr.dadr = dadr; + } - struct map_entry *me = GNUNET_CONTAINER_multihashmap_get(hashmap, key); - GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, - GNUNET_TIME_absolute_get ().abs_value); + memcpy (&pkt4->tcp_hdr, pkt, pktlen); - GNUNET_free(key); + GNUNET_HashCode *key = address4_mapping_exists (pkt4->ip_hdr.sadr); - GNUNET_assert (me != NULL); - if (ntohs(message->type) == GNUNET_MESSAGE_TYPE_SERVICE_UDP_BACK) - GNUNET_assert (me->desc.service_type & htonl(GNUNET_DNS_SERVICE_TYPE_TCP)); + GNUNET_assert (key != NULL); - 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); + struct map_entry *me = GNUNET_CONTAINER_multihashmap_get (hashmap, key); - sum = - calculate_checksum_update (sum, (uint16_t *) & pkt6->tcp_hdr, - ntohs (pkt6->ip6_hdr.paylgth)); - pkt6->tcp_hdr.crc = calculate_checksum_end (sum); + GNUNET_CONTAINER_heap_update_cost (heap, me->heap_node, + GNUNET_TIME_absolute_get ().abs_value); - write_to_helper(pkt6, size); + GNUNET_free (key); + + GNUNET_assert (me != NULL); + pkt4->tcp_hdr.crc = 0; + uint32_t sum = 0; + uint32_t tmp; + + tmp = pkt4->ip_hdr.sadr; + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + tmp = pkt4->ip_hdr.dadr; + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + + tmp = (0x06 << 16) | (0xffff & pktlen); // 0x06 for TCP? + + tmp = htonl (tmp); + + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + + sum = calculate_checksum_update (sum, (uint16_t *) & pkt4->tcp_hdr, pktlen); + pkt4->tcp_hdr.crc = calculate_checksum_end (sum); + + pkt4->ip_hdr.chks = + calculate_ip_checksum ((uint16_t *) & pkt4->ip_hdr, 5 * 4); + + write_to_helper (pkt4, size); + } return GNUNET_OK; } +static void * +new_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, + const struct GNUNET_PeerIdentity *initiator, + const struct GNUNET_ATS_Information *atsi) +{ + /* Why should anyone open an inbound tunnel to vpn? */ + GNUNET_break (0); + return NULL; +} + +static void +cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, void *tunnel_ctx) +{ + /* Why should anyone open an inbound tunnel to vpn? */ + GNUNET_break (0); +} + /** * Main function that will be run by the scheduler. * @@ -703,38 +1245,35 @@ receive_tcp_back (void *cls __attribute__((unused)), struct GNUNET_MESH_Tunnel* * @param cfg_ configuration */ static void -run (void *cls, - char *const *args __attribute__((unused)), - const char *cfgfilep __attribute__((unused)), - const struct GNUNET_CONFIGURATION_Handle *cfg_) +run (void *cls, char *const *args __attribute__ ((unused)), const char *cfgfilep + __attribute__ ((unused)), const struct GNUNET_CONFIGURATION_Handle *cfg_) { - static const 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}, - {receive_udp_back, GNUNET_MESSAGE_TYPE_REMOTE_UDP_BACK, 0}, - {receive_tcp_back, GNUNET_MESSAGE_TYPE_REMOTE_TCP_BACK, 0}, - {NULL, 0, 0} - }; - - static const GNUNET_MESH_ApplicationType types[] = { - GNUNET_APPLICATION_TYPE_END - }; - - mesh_handle = GNUNET_MESH_connect(cfg_, - NULL, - NULL, - handlers, - types); - cfg = cfg_; - restart_hijack = 0; - hashmap = GNUNET_CONTAINER_multihashmap_create(65536); - heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); - GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPINGg", - &max_mappings); - udp_connections = GNUNET_CONTAINER_multihashmap_create(65536); - GNUNET_SCHEDULER_TaskIdentifier conn_task = GNUNET_SCHEDULER_add_now (connect_to_service_dns, NULL); - GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL); - GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); + static const struct GNUNET_MESH_MessageHandler handlers[] = { + {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_UDP_BACK, 0}, + {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_SERVICE_TCP_BACK, 0}, + {receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_UDP_BACK, 0}, + {receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_REMOTE_TCP_BACK, 0}, + {NULL, 0, 0} + }; + + static const GNUNET_MESH_ApplicationType types[] = { + GNUNET_APPLICATION_TYPE_END + }; + + mesh_handle = + GNUNET_MESH_connect (cfg_, 42, NULL, new_tunnel, cleaner, handlers, + types); + cfg = cfg_; + restart_hijack = 0; + hashmap = GNUNET_CONTAINER_multihashmap_create (65536); + heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); + GNUNET_CONFIGURATION_get_value_number (cfg, "vpn", "MAX_MAPPINGg", + &max_mappings); + udp_connections = GNUNET_CONTAINER_multihashmap_create (65536); + conn_task = GNUNET_SCHEDULER_add_now (connect_to_service_dns, NULL); + shs_task = + GNUNET_SCHEDULER_add_after (conn_task, start_helper_and_schedule, NULL); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); } /** @@ -745,18 +1284,15 @@ run (void *cls, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) { - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - - return (GNUNET_OK == - GNUNET_PROGRAM_run (argc, - argv, - "gnunet-daemon-vpn", - gettext_noop ("help text"), - options, &run, NULL)) ? ret : 1; +main (int argc, char *const *argv) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + + return (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "vpn", gettext_noop ("help text"), + options, &run, NULL)) ? ret : 1; } /* end of gnunet-daemon-vpn.c */ -