From c7446050aa9469ce67ade9aee66239f4eeb679a6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Philipp=20T=C3=B6lke?= Date: Thu, 4 Nov 2010 17:26:57 +0000 Subject: [PATCH] Answer PTR-Requests (mock-version) --- src/vpn/gnunet-daemon-vpn.c | 31 +++++++++++- src/vpn/gnunet-service-dns-p.h | 8 ++- src/vpn/gnunet-service-dns.c | 92 +++++++++++++++++++++++++++++++++- 3 files changed, 126 insertions(+), 5 deletions(-) diff --git a/src/vpn/gnunet-daemon-vpn.c b/src/vpn/gnunet-daemon-vpn.c index 566388a66..f7be9013e 100644 --- a/src/vpn/gnunet-daemon-vpn.c +++ b/src/vpn/gnunet-daemon-vpn.c @@ -455,12 +455,14 @@ connect_to_service_dns (void *cls, static void process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { 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 */ + //FIXME htons? if (pkt->subtype == GNUNET_DNS_ANSWER_TYPE_SERVICE) { unsigned char ip6addr[16]; @@ -479,11 +481,36 @@ process_answer(void* cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { * have a last-used field * don't remove if last-used "recent", ask dht again if record expired */ + + 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_REV) + { + unsigned short offset = ntohs(pkt->addroffset); + + unsigned short namelen = htons(22); /* calculate the length of the answer */ + char name[22] = {13, 'p', 'h', 'i', 'l', 'i', 'p', 'p', 't', 'o', 'e', 'l', 'k', 'e', 6, 'g', 'n', 'u', 'n', 'e', 't', 0}; + + list = GNUNET_malloc(2*sizeof(struct answer_packet_list*) + offset + 2 + ntohs(namelen)); + + struct answer_packet* rpkt = &list->pkt; - struct answer_packet_list* list = GNUNET_malloc(htons(pkt->hdr.size) + 2*sizeof(struct answer_packet_list*)); + memcpy(rpkt, pkt, offset); - memcpy(&list->pkt, pkt, htons(pkt->hdr.size)); + 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) + 2*sizeof(struct answer_packet_list*)); + memcpy(&list->pkt, pkt, htons(pkt->hdr.size)); + } GNUNET_CONTAINER_DLL_insert_after(answer_proc_head, answer_proc_tail, answer_proc_tail, list); diff --git a/src/vpn/gnunet-service-dns-p.h b/src/vpn/gnunet-service-dns-p.h index 5b61ba653..a8944fbae 100644 --- a/src/vpn/gnunet-service-dns-p.h +++ b/src/vpn/gnunet-service-dns-p.h @@ -38,7 +38,13 @@ enum GNUNET_DNS_ANSWER_Subtype { * Answers of this type contain an incomplete dns-packet. The IP-Address * is all 0s. The addroffset points to it. */ - GNUNET_DNS_ANSWER_TYPE_SERVICE + GNUNET_DNS_ANSWER_TYPE_SERVICE, + + /** + * Answers of this type contain an incomplete dns-packet as answer to a + * PTR-Query. The resolved name is not allocated. The addroffset points to it. + */ + GNUNET_DNS_ANSWER_TYPE_REV }; struct answer_packet { diff --git a/src/vpn/gnunet-service-dns.c b/src/vpn/gnunet-service-dns.c index 3e69f8660..151561fe4 100644 --- a/src/vpn/gnunet-service-dns.c +++ b/src/vpn/gnunet-service-dns.c @@ -166,6 +166,81 @@ send_answer(void* cls, size_t size, void* buf) { return len; } +static void +send_rev_query(void * cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + struct dns_pkt_parsed* pdns = (struct dns_pkt_parsed*) cls; + + unsigned short id = pdns->s.id; + + if (query_states[id].valid != GNUNET_YES) return; + query_states[id].valid = GNUNET_NO; + + GNUNET_assert(query_states[id].namelen == 74); + + size_t len = sizeof(struct answer_packet) - 1 \ + + sizeof(struct dns_static) \ + + 74 /* this is the length of a reverse ipv6-lookup */ \ + + sizeof(struct dns_query_line) \ + + 2 /* To hold the pointer (as defined in RFC1035) to the name */ \ + + sizeof(struct dns_record_line) - 1 \ + - 2 /* We do not know the lenght of the answer yet*/ \ + - 2 /* No idea why... */ ; + + struct answer_packet_list* answer = GNUNET_malloc(len + 2*sizeof(struct answer_packet_list*)); + memset(answer, 0, len + 2*sizeof(struct answer_packet_list*)); + + answer->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS); + answer->pkt.hdr.size = htons(len); + answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REV; + + answer->pkt.from = query_states[id].remote_ip; + + answer->pkt.to = query_states[id].local_ip; + answer->pkt.dst_port = query_states[id].local_port; + + struct dns_pkt *dpkt = (struct dns_pkt*)answer->pkt.data; + + dpkt->s.id = id; + dpkt->s.aa = 1; + dpkt->s.qr = 1; + dpkt->s.ra = 1; + dpkt->s.qdcount = htons(1); + dpkt->s.ancount = htons(1); + + memcpy(dpkt->data, query_states[id].name, query_states[id].namelen); + GNUNET_free(query_states[id].name); + + struct dns_query_line* dque = (struct dns_query_line*)(dpkt->data+(query_states[id].namelen)); + dque->type = htons(12); /* PTR */ + dque->class = htons(1); /* IN */ + + char* anname = (char*)(dpkt->data+(query_states[id].namelen)+sizeof(struct dns_query_line)); + memcpy(anname, (char[]){0xc0, 0x0c}, 2); + + struct dns_record_line *drec_data = (struct dns_record_line*)(dpkt->data+(query_states[id].namelen)+sizeof(struct dns_query_line)+2); + drec_data->type = htons(12); /* AAAA */ + drec_data->class = htons(1); /* IN */ + drec_data->ttl = htonl(3600); /* FIXME: read from block */ + + /* Calculate at which offset in the packet the length of the name and the + * name, it is filled in by the daemon-vpn */ + answer->pkt.addroffset = htons((unsigned short)((unsigned long)(&drec_data->data_len)-(unsigned long)(&answer->pkt))); + + GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, answer); + + GNUNET_SERVER_notify_transmit_ready(query_states[id].client, + len, + GNUNET_TIME_UNIT_FOREVER_REL, + &send_answer, + query_states[id].client); + + /* + * build + * complete dns-packet with empty name in the answer + * provide offsett of the name + */ +} + /** * Receive a block from the dht. */ @@ -240,7 +315,6 @@ receive_dht(void *cls, memcpy(dpkt->data, query_states[id].name, query_states[id].namelen); GNUNET_free(query_states[id].name); - struct dns_query_line* dque = (struct dns_query_line*)(dpkt->data+(query_states[id].namelen)); dque->type = htons(28); /* AAAA */ dque->class = htons(1); /* IN */ @@ -302,6 +376,7 @@ receive_query(void *cls, query_states[dns->s.id].name = GNUNET_malloc(query_states[dns->s.id].namelen); memcpy(query_states[dns->s.id].name, dns->data, query_states[dns->s.id].namelen); + /* The query is for a .gnunet-address */ if (pdns->queries[0]->namelen > 9 && 0 == strncmp(pdns->queries[0]->name+(pdns->queries[0]->namelen - 9), ".gnunet.", 9)) { @@ -329,6 +404,18 @@ receive_query(void *cls, receive_dht, cls); + goto outfree; + } + + /* The query is for a PTR of a previosly resolved virtual IP */ + if (htons(pdns->queries[0]->qtype) == 12 && + pdns->queries[0]->namelen > 19 && + 0 == strncmp(pdns->queries[0]->name+(pdns->queries[0]->namelen - 19), ".4.3.2.1.ip6.arpa.", 19)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Reverse-Query for .gnunet!\n"); + + GNUNET_SCHEDULER_add_now(sched, send_rev_query, pdns); + goto out; } @@ -345,9 +432,10 @@ receive_query(void *cls, (struct sockaddr*) &dest, sizeof dest); -out: +outfree: free_parsed_dns_packet(pdns); pdns = NULL; +out: GNUNET_SERVER_receive_done(client, GNUNET_OK); } -- 2.25.1