-process_auth_records (void *cls,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd)
-{
- struct GetPseuAuthorityHandle *gph = cls;
- unsigned int i;
-
- for (i=0; i < rd_count; i++)
- {
- if (GNUNET_NAMESTORE_TYPE_PSEU == rd[i].record_type)
- {
- /* found pseu */
- process_pseu_result (gph,
- (const char *) rd[i].data);
- return;
- }
- }
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "No PSEU record found in DHT reply.\n");
- process_pseu_result (gph, NULL);
-}
-
-
-/**
- * Function called when we find a PSEU entry in the DHT
- *
- * @param cls the request handle
- * @param exp lifetime
- * @param key the key the record was stored under
- * @param get_path get path
- * @param get_path_length get path length
- * @param put_path put path
- * @param put_path_length put path length
- * @param type the block type
- * @param size the size of the record
- * @param data the record data
- */
-static void
-process_auth_discovery_dht_result (void* cls,
- struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode *key,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int put_path_length,
- enum GNUNET_BLOCK_Type type,
- size_t size,
- const void *data)
-{
- struct GetPseuAuthorityHandle *gph = cls;
- const struct GNUNET_NAMESTORE_Block *block;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got DHT result for PSEU request\n");
- GNUNET_DHT_get_stop (gph->get_handle);
- gph->get_handle = NULL;
- GNUNET_SCHEDULER_cancel (gph->timeout_task);
- gph->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-
- if (NULL == data)
- {
- /* is this allowed!? */
- GNUNET_break (0);
- process_pseu_result (gph, NULL);
- return;
- }
- if (size < sizeof (struct GNUNET_NAMESTORE_Block))
- {
- /* how did this pass DHT block validation!? */
- GNUNET_break (0);
- process_pseu_result (gph, NULL);
- return;
- }
- block = data;
- if (size !=
- ntohs (block->purpose.size) +
- sizeof (struct GNUNET_CRYPTO_EccPublicKey) +
- sizeof (struct GNUNET_CRYPTO_EccSignature))
- {
- /* how did this pass DHT block validation!? */
- GNUNET_break (0);
- process_pseu_result (gph, NULL);
- return;
- }
- if (GNUNET_OK !=
- GNUNET_NAMESTORE_block_decrypt (block,
- &gph->target_zone,
- GNUNET_GNS_TLD_PLUS,
- &process_auth_records,
- gph))
- {
- /* other peer encrypted invalid block, complain */
- GNUNET_break_op (0);
- process_pseu_result (gph, NULL);
- return;
- }
-}
-
-
-/**
- * Callback called by namestore for a zone to name result. We're
- * trying to see if a short name for a given zone already exists.
- *
- * @param cls the closure
- * @param zone_key the zone we queried
- * @param name the name found or NULL
- * @param rd_len number of records for the name
- * @param rd the record data (PKEY) for the name
- */
-static void
-process_zone_to_name_discover (void *cls,
- const struct GNUNET_CRYPTO_EccPrivateKey *zone_key,
- const char *name,
- unsigned int rd_len,
- const struct GNUNET_NAMESTORE_RecordData *rd)
-{
- struct GetPseuAuthorityHandle* gph = cls;
- struct GNUNET_HashCode lookup_key;
-
- gph->namestore_task = NULL;
- if (0 != rd_len)
- {
- /* we found a match in our own zone */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Shortening aborted, name `%s' already reserved for the zone\n",
- name);
- free_get_pseu_authority_handle (gph);
- return;
- }
- /* record does not yet exist, go into DHT to find PSEU record */
- GNUNET_NAMESTORE_query_from_public_key (&gph->target_zone,
- GNUNET_GNS_TLD_PLUS,
- &lookup_key);
- gph->timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
- &handle_auth_discovery_timeout,
- gph);
- gph->get_handle = GNUNET_DHT_get_start (dht_handle,
- GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
- &lookup_key,
- DHT_GNS_REPLICATION_LEVEL,
- GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
- NULL, 0,
- &process_auth_discovery_dht_result,
- gph);
-}
-
-
-/**
- * Start shortening algorithm, try to allocate a nice short
- * canonical name for @a pub in @a shorten_zone, using
- * @a original_label as one possible suggestion.
- *
- * @param original_label original label for the zone
- * @param pub public key of the zone to shorten
- * @param shorten_zone private key of the target zone for the new record
- */
-static void
-start_shorten (const char *original_label,
- const struct GNUNET_CRYPTO_EccPublicKey *pub,
- const struct GNUNET_CRYPTO_EccPrivateKey *shorten_zone)
-{
- struct GetPseuAuthorityHandle *gph;
-
- if (strlen (original_label) > GNUNET_DNSPARSER_MAX_LABEL_LENGTH)
- {
- GNUNET_break (0);
- return;
- }
- gph = GNUNET_new (struct GetPseuAuthorityHandle);
- gph->shorten_zone_key = *shorten_zone;
- gph->target_zone = *pub;
- strcpy (gph->label, original_label);
- GNUNET_CONTAINER_DLL_insert (gph_head, gph_tail, gph);
- /* first, check if we *already* have a record for this zone */
- gph->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
- shorten_zone,
- pub,
- &process_zone_to_name_discover,
- gph);
-}
-
-
-/* ************************** Resolution **************************** */
-
-#if 0
-
-
-//FIXME maybe define somewhere else?
-#define MAX_SOA_LENGTH sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)+sizeof(uint32_t)\
- +(GNUNET_DNSPARSER_MAX_NAME_LENGTH*2)
-#define MAX_MX_LENGTH sizeof(uint16_t)+GNUNET_DNSPARSER_MAX_NAME_LENGTH
-#define MAX_SRV_LENGTH (sizeof(uint16_t)*3)+GNUNET_DNSPARSER_MAX_NAME_LENGTH
-
-
-/**
- * Exands a name ending in .+ with the zone of origin.
- * FIXME: funky api: 'dest' must be large enough to hold
- * the result; this is a bit yucky...
- *
- * @param dest destination buffer
- * @param src the .+ name
- * @param repl the string to replace the + with
- */
-static void
-expand_plus (char* dest,
- const char* src,
- const char* repl)
-{
- char* pos;
- size_t s_len = strlen (src) + 1;
-
- //Eh? I guess this is at least strlen ('x.+') == 3 FIXME
- if (3 > s_len)
- {
- /* no postprocessing */
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_POSTPROCESS: %s too short\n", src);
- memcpy (dest, src, s_len);
- return;
- }
- if (0 == strcmp (src + s_len - 3, ".+"))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_POSTPROCESS: Expanding .+ in %s\n",
- src);
- memset (dest, 0, s_len + strlen (repl) + strlen(GNUNET_GNS_TLD));
- strcpy (dest, src);
- pos = dest + s_len - 2;
- strcpy (pos, repl);
- pos += strlen (repl);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "GNS_POSTPROCESS: Expanded to %s\n",
- dest);
- }
- else
- {
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_POSTPROCESS: No postprocessing for %s\n", src);
- memcpy (dest, src, s_len);
- }
-}
-
-
-/**
- * finish lookup
- */
-static void
-finish_lookup (struct ResolverHandle *rh,
- struct RecordLookupHandle* rlh,
- unsigned int rd_count,
- const struct GNUNET_NAMESTORE_RecordData *rd)
-{
- unsigned int i;
- char new_rr_data[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
- char new_mx_data[MAX_MX_LENGTH];
- char new_soa_data[MAX_SOA_LENGTH];
- char new_srv_data[MAX_SRV_LENGTH];
- struct GNUNET_TUN_DnsSrvRecord *old_srv;
- struct GNUNET_TUN_DnsSrvRecord *new_srv;
- struct GNUNET_TUN_DnsSoaRecord *old_soa;
- struct GNUNET_TUN_DnsSoaRecord *new_soa;
- struct GNUNET_NAMESTORE_RecordData p_rd[rd_count];
- char* repl_string;
- char* pos;
- unsigned int offset;
-
- if (GNUNET_SCHEDULER_NO_TASK != rh->timeout_task)
- {
- GNUNET_SCHEDULER_cancel(rh->timeout_task);
- rh->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh);
-
- if (0 < rd_count)
- memcpy(p_rd, rd, rd_count*sizeof(struct GNUNET_NAMESTORE_RecordData));
-
- for (i = 0; i < rd_count; i++)
- {
-
- if ((GNUNET_DNSPARSER_TYPE_NS != rd[i].record_type) &&
- (GNUNET_DNSPARSER_TYPE_PTR != rd[i].record_type) &&
- (GNUNET_DNSPARSER_TYPE_CNAME != rd[i].record_type) &&
- (GNUNET_DNSPARSER_TYPE_MX != rd[i].record_type) &&
- (GNUNET_DNSPARSER_TYPE_SOA != rd[i].record_type) &&
- (GNUNET_DNSPARSER_TYPE_SRV != rd[i].record_type))
- {
- p_rd[i].data = rd[i].data;
- continue;
- }
-
- /**
- * for all those records we 'should'
- * also try to resolve the A/AAAA records (RFC1035)
- * This is a feature and not important
- */
-
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
- "GNS_POSTPROCESS: Postprocessing\n");
- if (0 == strcmp(rh->name, GNUNET_GNS_MASTERZONE_STR))
- repl_string = rlh->name;
- else
- repl_string = rlh->name+strlen(rh->name)+1;
-
- offset = 0;
- if (GNUNET_DNSPARSER_TYPE_MX == rd[i].record_type)
- {
- memcpy (new_mx_data, (char*)rd[i].data, sizeof(uint16_t));
- offset = sizeof (uint16_t);
- pos = new_mx_data + offset;
- // FIXME: how do we know that 'pos' has enough space for the new name?
- expand_plus (pos, (char*)rd[i].data+sizeof(uint16_t),
- repl_string);
- offset += strlen(new_mx_data+sizeof(uint16_t)) + 1;
- p_rd[i].data = new_mx_data;
- p_rd[i].data_size = offset;
- }
- else if (GNUNET_DNSPARSER_TYPE_SRV == rd[i].record_type)
- {
- /*
- * Prio, weight and port
- */
- new_srv = (struct GNUNET_TUN_DnsSrvRecord*)new_srv_data;
- old_srv = (struct GNUNET_TUN_DnsSrvRecord*)rd[i].data;
- new_srv->prio = old_srv->prio;
- new_srv->weight = old_srv->weight;
- new_srv->port = old_srv->port;
- // FIXME: how do we know that '&new_srv[1]' has enough space for the new name?
- expand_plus((char*)&new_srv[1], (char*)&old_srv[1],
- repl_string);
- p_rd[i].data = new_srv_data;
- p_rd[i].data_size = sizeof (struct GNUNET_TUN_DnsSrvRecord) + strlen ((char*)&new_srv[1]) + 1;
- }
- else if (GNUNET_DNSPARSER_TYPE_SOA == rd[i].record_type)
- {
- /* expand mname and rname */
- old_soa = (struct GNUNET_TUN_DnsSoaRecord*)rd[i].data;
- new_soa = (struct GNUNET_TUN_DnsSoaRecord*)new_soa_data;
- memcpy (new_soa, old_soa, sizeof (struct GNUNET_TUN_DnsSoaRecord));
- // FIXME: how do we know that 'new_soa[1]' has enough space for the new name?
- expand_plus((char*)&new_soa[1], (char*)&old_soa[1], repl_string);
- offset = strlen ((char*)&new_soa[1]) + 1;
- // FIXME: how do we know that 'new_soa[1]' has enough space for the new name?
- expand_plus((char*)&new_soa[1] + offset,
- (char*)&old_soa[1] + strlen ((char*)&old_soa[1]) + 1,
- repl_string);
- p_rd[i].data_size = sizeof (struct GNUNET_TUN_DnsSoaRecord)
- + offset
- + strlen ((char*)&new_soa[1] + offset);
- p_rd[i].data = new_soa_data;
- }
- else
- {
- pos = new_rr_data;
- // FIXME: how do we know that 'rd[i].data' has enough space for the new name?
- expand_plus(pos, (char*)rd[i].data, repl_string);
- p_rd[i].data_size = strlen(new_rr_data)+1;
- p_rd[i].data = new_rr_data;
- }
-
- }
-
- rlh->proc(rlh->proc_cls, rd_count, p_rd);
- GNUNET_free(rlh);
- free_resolver_handle (rh);
-}
-
-
-#endif
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-/**
- * Task scheduled to asynchronously fail a resolution.
- *
- * @param cls the 'struct GNS_ResolverHandle' of the resolution to fail
- * @param tc task context
- */
-static void
-fail_resolution (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct GNS_ResolverHandle *rh = cls;
-
- rh->task_id = GNUNET_SCHEDULER_NO_TASK;
- rh->proc (rh->proc_cls, 0, NULL);
- GNS_resolver_lookup_cancel (rh);
-}
-
-#ifdef WINDOWS
-/* Don't have this on W32, here's a naive implementation */
-void *
-memrchr (const void *s, int c, size_t n)
-{
- size_t i;
- unsigned char *ucs = (unsigned char *) s;
-
- for (i = n - 1; i >= 0; i--)
- if (ucs[i] == c)
- return (void *) &ucs[i];
- return NULL;
-}
-#endif
-
-/**
- * Get the next, rightmost label from the name that we are trying to resolve,
- * and update the resolution position accordingly.
- *
- * @param rh handle to the resolution operation to get the next label from
- * @return NULL if there are no more labels
- */
-static char *
-resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh)
-{
- const char *rp;
- const char *dot;
- size_t len;
-
- if (0 == rh->name_resolution_pos)
- return NULL;
- dot = memrchr (rh->name, (int) '.', rh->name_resolution_pos);
- if (NULL == dot)
- {
- /* done, this was the last one */
- len = rh->name_resolution_pos;
- rp = rh->name;
- rh->name_resolution_pos = 0;
- }
- else
- {
- /* advance by one label */
- len = rh->name_resolution_pos - (dot - rh->name) - 1;
- rp = dot + 1;
- rh->name_resolution_pos = dot - rh->name;
- }
- return GNUNET_strndup (rp, len);
-}
-
-
-/**
- * Gives the cummulative result obtained to the callback and clean up the request.
- *
- * @param rh resolution process that has culminated in a result
- */
-static void
-transmit_lookup_dns_result (struct GNS_ResolverHandle *rh)
-{
- struct DnsResult *pos;
- unsigned int n;
- unsigned int i;
-
- n = 0;
- for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
- n++;
- {
- struct GNUNET_NAMESTORE_RecordData rd[n];
-
- i = 0;
- for (pos = rh->dns_result_head; NULL != pos; pos = pos->next)
- {
- rd[i].data = pos->data;
- rd[i].data_size = pos->data_size;
- rd[i].record_type = pos->record_type;
- if (0 == pos->expiration_time)
- {
- rd[i].flags = GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
- rd[i].expiration_time = 0;
- }
- else
- {
- rd[i].flags = GNUNET_NAMESTORE_RF_NONE;
- rd[i].expiration_time = pos->expiration_time;
- }
- }
- rh->proc (rh->proc_cls,
- n,
- rd);
- }
- GNS_resolver_lookup_cancel (rh);
-}
-
-
-/**
- * Add a result from DNS to the records to be returned to the application.
- *
- * @param rh resolution request to extend with a result
- * @param expiration_time expiration time for the answer
- * @param record_type DNS record type of the answer
- * @param data_size number of bytes in @a data
- * @param data binary data to return in DNS record
- */
-static void
-add_dns_result (struct GNS_ResolverHandle *rh,
- uint64_t expiration_time,
- uint32_t record_type,
- size_t data_size,
- const void *data)
-{
- struct DnsResult *res;
-
- res = GNUNET_malloc (sizeof (struct DnsResult) + data_size);
- res->expiration_time = expiration_time;
- res->data_size = data_size;
- res->record_type = record_type;
- res->data = &res[1];
- memcpy (&res[1], data, data_size);
- GNUNET_CONTAINER_DLL_insert (rh->dns_result_head,
- rh->dns_result_tail,
- res);
-}
-
-
-/**
- * We had to do a DNS lookup. Convert the result (if any) and return
- * it.
- *
- * @param cls closure with the 'struct GNS_ResolverHandle'
- * @param addr one of the addresses of the host, NULL for the last address
- * @param addrlen length of the address
- */
-static void
-handle_dns_result (void *cls,
- const struct sockaddr *addr,
- socklen_t addrlen)
-{
- struct GNS_ResolverHandle *rh = cls;
- const struct sockaddr_in *sa4;
- const struct sockaddr_in6 *sa6;
-
- rh->std_resolve = NULL;
- if (NULL == addr)
- {
- transmit_lookup_dns_result (rh);
- return;
- }
- switch (addr->sa_family)
- {
- case AF_INET:
- sa4 = (const struct sockaddr_in *) addr;
- add_dns_result (rh,
- 0 /* expiration time is unknown */,
- GNUNET_DNSPARSER_TYPE_A,
- sizeof (struct in_addr),
- &sa4->sin_addr);
- break;
- case AF_INET6:
- sa6 = (const struct sockaddr_in6 *) addr;
- add_dns_result (rh,
- 0 /* expiration time is unknown */,
- GNUNET_DNSPARSER_TYPE_AAAA,
- sizeof (struct in6_addr),
- &sa6->sin6_addr);
- break;
- default:
- GNUNET_break (0);
- break;
- }
-}