aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-08-13 19:14:19 +0000
committerChristian Grothoff <christian@grothoff.org>2013-08-13 19:14:19 +0000
commit5f5f1974b15c646bde44583aede2433254138661 (patch)
tree6197cc994723c804e261ff15c9a04e800f3988ee
parentadc6e4a5804d4cb43516383ff1d97065df0d0fd9 (diff)
downloadgnunet-5f5f1974b15c646bde44583aede2433254138661.tar.gz
gnunet-5f5f1974b15c646bde44583aede2433254138661.zip
-more coding towards working new GNS service
-rw-r--r--src/gns/gnunet-service-gns.c494
-rw-r--r--src/gns/gnunet-service-gns_interceptor.c401
-rw-r--r--src/gns/gnunet-service-gns_interceptor.h11
-rw-r--r--src/gns/gnunet-service-gns_resolver.c1551
-rw-r--r--src/gns/gnunet-service-gns_resolver.h606
-rw-r--r--src/include/gnunet_dht_service.h8
6 files changed, 858 insertions, 2213 deletions
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index 822cc7d12..be41f8c84 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) 3 (C) 2011-2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -50,7 +50,7 @@
50 50
51/** 51/**
52 * The default put interval for the zone iteration. In case 52 * The default put interval for the zone iteration. In case
53 * No option is found 53 * no option is found
54 */ 54 */
55#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4) 55#define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4)
56 56
@@ -60,6 +60,16 @@
60 */ 60 */
61#define LATE_ITERATION_SPEEDUP_FACTOR 2 61#define LATE_ITERATION_SPEEDUP_FACTOR 2
62 62
63/**
64 * How long until a DHT PUT attempt should time out?
65 */
66#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
67
68/**
69 * What replication level do we use for DHT PUT operations?
70 */
71#define DHT_GNS_REPLICATION_LEVEL 5
72
63 73
64/** 74/**
65 * Handle to a lookup operation from api 75 * Handle to a lookup operation from api
@@ -68,39 +78,30 @@ struct ClientLookupHandle
68{ 78{
69 79
70 /** 80 /**
71 * Handle to the requesting client 81 * We keep these in a DLL.
72 */ 82 */
73 struct GNUNET_SERVER_Client *client; 83 struct ClientLookupHandle *next;
74 84
75 /** 85 /**
76 * optional zone private key used for shorten 86 * We keep these in a DLL.
77 */ 87 */
78 struct GNUNET_CRYPTO_EccPrivateKey *shorten_key; 88 struct ClientLookupHandle *prev;
79 89
80 /** 90 /**
81 * the name to look up 91 * Handle to the requesting client
82 */ 92 */
83 char *name; 93 struct GNUNET_SERVER_Client *client;
84 94
85 /** 95 /**
86 * The zone we look up in 96 * Active handle for the lookup.
87 */ 97 */
88 struct GNUNET_CRYPTO_ShortHashCode zone; 98 struct GNS_ResolverHandle *lookup;
89 99
90 /** 100 /**
91 * request id 101 * request id
92 */ 102 */
93 uint32_t request_id; 103 uint32_t request_id;
94 104
95 /**
96 * GNUNET_YES if we only want to lookup from local cache
97 */
98 int only_cached;
99
100 /**
101 * request type
102 */
103 int type;
104}; 105};
105 106
106 107
@@ -110,9 +111,9 @@ struct ClientLookupHandle
110static struct GNUNET_DHT_Handle *dht_handle; 111static struct GNUNET_DHT_Handle *dht_handle;
111 112
112/** 113/**
113 * Our zone's private key 114 * Active DHT put operation (or NULL)
114 */ 115 */
115static struct GNUNET_CRYPTO_EccPrivateKey *zone_key; 116static struct GNUNET_DHT_PutHandle *active_put;
116 117
117/** 118/**
118 * Our handle to the namestore service 119 * Our handle to the namestore service
@@ -130,9 +131,14 @@ static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter;
130static struct GNUNET_SERVER_NotificationContext *nc; 131static struct GNUNET_SERVER_NotificationContext *nc;
131 132
132/** 133/**
133 * Our zone hash 134 * Head of the DLL.
135 */
136static struct ClientLookupHandle *clh_head;
137
138/**
139 * Tail of the DLL.
134 */ 140 */
135static struct GNUNET_CRYPTO_ShortHashCode zone_hash; 141static struct ClientLookupHandle *clh_tail;
136 142
137/** 143/**
138 * Useful for zone update for DHT put 144 * Useful for zone update for DHT put
@@ -160,13 +166,7 @@ static struct GNUNET_TIME_Relative zone_publish_time_window;
160static GNUNET_SCHEDULER_TaskIdentifier zone_publish_task; 166static GNUNET_SCHEDULER_TaskIdentifier zone_publish_task;
161 167
162/** 168/**
163 * GNUNET_YES if automatic pkey import for name shortening 169 * #GNUNET_YES if zone has never been published before
164 * is enabled
165 */
166static int auto_import_pkey;
167
168/**
169 * GNUNET_YES if zone has never been published before
170 */ 170 */
171static int first_zone_iteration; 171static int first_zone_iteration;
172 172
@@ -176,12 +176,12 @@ static int first_zone_iteration;
176static struct GNUNET_TIME_Relative default_lookup_timeout; 176static struct GNUNET_TIME_Relative default_lookup_timeout;
177 177
178/** 178/**
179 * GNUNET_YES if ipv6 is supported 179 * #GNUNET_YES if ipv6 is supported
180 */ 180 */
181static int v6_enabled; 181static int v6_enabled;
182 182
183/** 183/**
184 * GNUNET_YES if ipv4 is supported 184 * #GNUNET_YES if ipv4 is supported
185 */ 185 */
186static int v4_enabled; 186static int v4_enabled;
187 187
@@ -200,13 +200,20 @@ static struct GNUNET_STATISTICS_Handle *statistics;
200static void 200static void
201shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 201shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
202{ 202{
203 struct ClientShortenHandle *csh_tmp; 203 struct ClientLookupHandle *clh;
204 204
205 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
206 "Shutting down!\n"); 206 "Shutting down!\n");
207 GNUNET_SERVER_notification_context_destroy (nc); 207 GNUNET_SERVER_notification_context_destroy (nc);
208 gns_interceptor_stop (); 208 while (NULL != (clh = clh_head))
209 gns_resolver_cleanup (); 209 {
210 GNS_resolver_lookup_cancel (clh->lookup);
211 GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh);
212 GNUNET_free (clh);
213 }
214
215 GNS_interceptor_done ();
216 GNS_resolver_done ();
210 if (NULL != statistics) 217 if (NULL != statistics)
211 { 218 {
212 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); 219 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
@@ -227,6 +234,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
227 GNUNET_NAMESTORE_disconnect (namestore_handle); 234 GNUNET_NAMESTORE_disconnect (namestore_handle);
228 namestore_handle = NULL; 235 namestore_handle = NULL;
229 } 236 }
237 if (NULL != active_put)
238 {
239 GNUNET_DHT_put_cancel (active_put);
240 active_put = NULL;
241 }
230 if (NULL != dht_handle) 242 if (NULL != dht_handle)
231 { 243 {
232 GNUNET_DHT_disconnect (dht_handle); 244 GNUNET_DHT_disconnect (dht_handle);
@@ -262,36 +274,65 @@ publish_zone_dht_start (void *cls,
262 274
263 275
264/** 276/**
277 * Continuation called from DHT once the PUT operation is done.
278 *
279 * @param cls closure, NULL
280 * @param success #GNUNET_OK on success
281 */
282static void
283dht_put_continuation (void *cls,
284 int success)
285{
286 struct GNUNET_TIME_Relative next_put_interval;
287
288 num_public_records++;
289 if ( (num_public_records > last_num_public_records) &&
290 (GNUNET_NO == first_zone_iteration) )
291 {
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
293 "Last record count was lower than current record count. Reducing interval.\n");
294 put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
295 num_public_records);
296 next_put_interval = GNUNET_TIME_relative_divide (put_interval,
297 LATE_ITERATION_SPEEDUP_FACTOR);
298 }
299 else
300 next_put_interval = put_interval;
301
302 GNUNET_STATISTICS_set (statistics,
303 "Current zone iteration interval (ms)",
304 next_put_interval.rel_value_us / 1000LL,
305 GNUNET_NO);
306 zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval,
307 &publish_zone_dht_next,
308 NULL);
309}
310
311
312/**
265 * Function used to put all records successively into the DHT. 313 * Function used to put all records successively into the DHT.
266 * 314 *
267 * @param cls the closure (NULL) 315 * @param cls the closure (NULL)
268 * @param key the public key of the authority (ours) 316 * @param key the private key of the authority (ours)
269 * @param expiration lifetime of the namestore entry 317 * @param name the name of the records, NULL once the iteration is done
270 * @param name the name of the records 318 * @param rd_count the number of records in @a rd
271 * @param rd_count the number of records in data
272 * @param rd the record data 319 * @param rd the record data
273 * @param signature the signature for the record data
274 */ 320 */
275static void 321static void
276put_gns_record (void *cls, 322put_gns_record (void *cls,
277 const struct GNUNET_CRYPTO_EccPublicKey *key, 323 const struct GNUNET_CRYPTO_EccPrivateKey *key,
278 struct GNUNET_TIME_Absolute expiration,
279 const char *name, 324 const char *name,
280 unsigned int rd_count, 325 unsigned int rd_count,
281 const struct GNUNET_NAMESTORE_RecordData *rd, 326 const struct GNUNET_NAMESTORE_RecordData *rd)
282 const struct GNUNET_CRYPTO_EccSignature *signature)
283{ 327{
284 struct GNSNameRecordBlock *nrb; 328 struct GNUNET_NAMESTORE_Block *block;
285 struct GNUNET_CRYPTO_ShortHashCode zhash; 329 struct GNUNET_HashCode query;
286 struct GNUNET_HashCode dht_key; 330 struct GNUNET_TIME_Absolute expire;
287 uint32_t rd_payload_length; 331 size_t block_size;
288 char* nrb_data = NULL;
289 size_t namelen;
290 struct GNUNET_TIME_Relative next_put_interval;
291 332
292 if (NULL == name) 333 if (NULL == name)
293 { 334 {
294 /* we're done */ 335 /* we're done with one iteration, calculate when to do the next one */
295 namestore_iter = NULL; 336 namestore_iter = NULL;
296 last_num_public_records = num_public_records; 337 last_num_public_records = num_public_records;
297 first_zone_iteration = GNUNET_NO; 338 first_zone_iteration = GNUNET_NO;
@@ -304,7 +345,7 @@ put_gns_record (void *cls,
304 */ 345 */
305 put_interval = zone_publish_time_window; 346 put_interval = zone_publish_time_window;
306 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
307 "No records in db.\n"); 348 "No records in namestore database.\n");
308 } 349 }
309 else 350 else
310 { 351 {
@@ -322,126 +363,62 @@ put_gns_record (void *cls,
322 put_interval.rel_value_us / 1000LL, 363 put_interval.rel_value_us / 1000LL,
323 GNUNET_NO); 364 GNUNET_NO);
324 GNUNET_STATISTICS_update (statistics, 365 GNUNET_STATISTICS_update (statistics,
325 "Number of zone iterations", 1, GNUNET_NO); 366 "Number of zone iterations",
367 1,
368 GNUNET_NO);
326 GNUNET_STATISTICS_set (statistics, 369 GNUNET_STATISTICS_set (statistics,
327 "Number of public records in DHT", 370 "Number of public records in DHT",
328 last_num_public_records, 371 last_num_public_records,
329 GNUNET_NO); 372 GNUNET_NO);
330 if (0 == num_public_records) 373 if (0 == num_public_records)
331 zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval, 374 zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval,
332 &publish_zone_dht_start, 375 &publish_zone_dht_start,
333 NULL); 376 NULL);
334 else 377 else
335 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL); 378 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
379 NULL);
336 return; 380 return;
337 } 381 }
338 382
339 namelen = strlen (name) + 1; 383 /* FIXME: filter out records that are not public! */
384
385 /* We got a set of records to publish */
340 if (0 == rd_count) 386 if (0 == rd_count)
341 { 387 {
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "No records for name `%s'! Skipping.\n",
344 name);
345 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, 388 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next,
346 NULL); 389 NULL);
347 return; 390 return;
348 } 391 }
349 if (NULL == signature) 392 expire = GNUNET_NAMESTORE_record_get_expiration_time (rd_count,
393 rd);
394 block = GNUNET_NAMESTORE_block_create (key,
395 expire,
396 name,
397 rd,
398 rd_count);
399 block_size = ntohl (block->purpose.size)
400 + sizeof (struct GNUNET_CRYPTO_EccSignature)
401 + sizeof (struct GNUNET_CRYPTO_EccPublicKey);
402 GNUNET_NAMESTORE_query_from_private_key (key,
403 name,
404 &query);
405
406 active_put = GNUNET_DHT_put (dht_handle, &query,
407 DHT_GNS_REPLICATION_LEVEL,
408 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
409 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
410 block_size,
411 block,
412 expire,
413 DHT_OPERATION_TIMEOUT,
414 &dht_put_continuation,
415 NULL);
416 if (NULL == active_put)
350 { 417 {
351 GNUNET_break (0); 418 GNUNET_break (0);
352 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, 419 dht_put_continuation (NULL, GNUNET_NO);
353 NULL);
354 return;
355 }
356
357 /* TODO 2) AB: New publishing
358 *
359 * - Use new signature S_d
360 * - Obtain new derived public key V = H(H(i,Q) * Q)
361 * - Obtain HKDF(i,Q)
362 * - Compute encrypte record block E with HKDF(i,Q) (rd, rd_count)
363 * - Create block B = |V,E,S_d|
364 * - Compute new DHT key H(V) in TODO 3)
365 *
366 * -> Put (H(V), B)
367 */
368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
369 "Putting records for `%s' into the DHT\n", name);
370 rd_payload_length = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
371 nrb = GNUNET_malloc (rd_payload_length + namelen
372 + sizeof (struct GNSNameRecordBlock));
373 nrb->signature = *signature;
374 nrb->public_key = *key;
375 nrb->rd_count = htonl (rd_count);
376 memcpy (&nrb[1], name, namelen);
377 nrb_data = (char *) &nrb[1];
378 nrb_data += namelen;
379 rd_payload_length += sizeof(struct GNSNameRecordBlock) + namelen;
380 GNUNET_CRYPTO_short_hash (key,
381 sizeof (struct GNUNET_CRYPTO_EccPublicKey),
382 &zhash);
383 if (-1 == GNUNET_NAMESTORE_records_serialize (rd_count,
384 rd,
385 rd_payload_length,
386 nrb_data))
387 {
388 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
389 _("Records for name `%s' in zone %s too large to fit into DHT"),
390 name,
391 GNUNET_short_h2s (&zhash));
392 GNUNET_free (nrb);
393 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next,
394 NULL);
395 return;
396 }
397 /* TODO AB: Here records are put in the DHT: modify dht_key to H(key) = H(H(name,zone) * zone) */
398 GNUNET_GNS_get_key_for_record (name, &zhash, &dht_key);
399 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
400 "putting %u records from zone %s for `%s' under key: %s with size %u and timeout %s\n",
401 rd_count,
402 GNUNET_short_h2s (&zhash),
403 name,
404 GNUNET_h2s (&dht_key),
405 (unsigned int) rd_payload_length,
406 GNUNET_STRINGS_relative_time_to_string (DHT_OPERATION_TIMEOUT, GNUNET_YES));
407
408 GNUNET_STATISTICS_update (statistics,
409 "Record bytes put into DHT",
410 rd_payload_length, GNUNET_NO);
411
412 (void) GNUNET_DHT_put (dht_handle, &dht_key,
413 DHT_GNS_REPLICATION_LEVEL,
414 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
415 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
416 rd_payload_length,
417 (char*)nrb,
418 expiration,
419 DHT_OPERATION_TIMEOUT,
420 NULL,
421 NULL);
422 GNUNET_free (nrb);
423
424 num_public_records++;
425 if ( (num_public_records > last_num_public_records)
426 && (GNUNET_NO == first_zone_iteration) )
427 {
428 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
429 "Last record count was lower than current record count. Reducing interval.\n");
430 put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window,
431 num_public_records);
432 next_put_interval = GNUNET_TIME_relative_divide (put_interval,
433 LATE_ITERATION_SPEEDUP_FACTOR);
434 } 420 }
435 else 421 GNUNET_free (block);
436 next_put_interval = put_interval;
437
438 GNUNET_STATISTICS_set (statistics,
439 "Current zone iteration interval (ms)",
440 next_put_interval.rel_value_us / 1000LL,
441 GNUNET_NO);
442 zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval,
443 &publish_zone_dht_next,
444 NULL);
445} 422}
446 423
447 424
@@ -463,8 +440,6 @@ publish_zone_dht_start (void *cls,
463 num_public_records = 0; 440 num_public_records = 0;
464 namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle, 441 namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle,
465 NULL, /* All zones */ 442 NULL, /* All zones */
466 GNUNET_NAMESTORE_RF_AUTHORITY,
467 GNUNET_NAMESTORE_RF_PRIVATE,
468 &put_gns_record, 443 &put_gns_record,
469 NULL); 444 NULL);
470} 445}
@@ -485,40 +460,39 @@ send_lookup_response (void* cls,
485 uint32_t rd_count, 460 uint32_t rd_count,
486 const struct GNUNET_NAMESTORE_RecordData *rd) 461 const struct GNUNET_NAMESTORE_RecordData *rd)
487{ 462{
488 struct ClientLookupHandle* clh = cls; 463 struct ClientLookupHandle *clh = cls;
489 struct GNUNET_GNS_ClientLookupResultMessage *rmsg; 464 struct GNUNET_GNS_ClientLookupResultMessage *rmsg;
490 size_t len; 465 size_t len;
491 466
492 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %d results\n", 467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
493 "LOOKUP_RESULT", rd_count); 468 "Sending `%s' message with %d results\n",
469 "LOOKUP_RESULT",
470 rd_count);
494 471
495 len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); 472 len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
496 rmsg = GNUNET_malloc (len + sizeof (struct GNUNET_GNS_ClientLookupResultMessage)); 473 rmsg = GNUNET_malloc (len + sizeof (struct GNUNET_GNS_ClientLookupResultMessage));
497 474 rmsg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT);
475 rmsg->header.size = htons (len + sizeof(struct GNUNET_GNS_ClientLookupResultMessage));
498 rmsg->id = clh->request_id; 476 rmsg->id = clh->request_id;
499 rmsg->rd_count = htonl(rd_count); 477 rmsg->rd_count = htonl (rd_count);
500 rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT); 478 GNUNET_NAMESTORE_records_serialize (rd_count, rd, len,
501 rmsg->header.size = 479 (char*) &rmsg[1]);
502 htons(len+sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); 480 GNUNET_SERVER_notification_context_unicast (nc,
503 481 clh->client,
504 GNUNET_NAMESTORE_records_serialize (rd_count, rd, len, (char*)&rmsg[1]); 482 &rmsg->header,
505 483 GNUNET_NO);
506 GNUNET_SERVER_notification_context_unicast (nc, clh->client, 484 GNUNET_free (rmsg);
507 (const struct GNUNET_MessageHeader *) rmsg, 485 GNUNET_SERVER_receive_done (clh->client,
508 GNUNET_NO); 486 GNUNET_OK);
509 GNUNET_SERVER_receive_done (clh->client, GNUNET_OK); 487 GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh);
510
511 GNUNET_free(rmsg);
512 GNUNET_free(clh->name);
513
514 if (NULL != clh->shorten_key)
515 GNUNET_CRYPTO_ecc_key_free (clh->shorten_key);
516 GNUNET_free (clh); 488 GNUNET_free (clh);
517 GNUNET_STATISTICS_update (statistics, 489 GNUNET_STATISTICS_update (statistics,
518 "Completed lookups", 1, GNUNET_NO); 490 "Completed lookups", 1,
519 if (NULL != rd) 491 GNUNET_NO);
520 GNUNET_STATISTICS_update (statistics, 492 GNUNET_STATISTICS_update (statistics,
521 "Records resolved", rd_count, GNUNET_NO); 493 "Records resolved",
494 rd_count,
495 GNUNET_NO);
522} 496}
523 497
524 498
@@ -531,22 +505,21 @@ send_lookup_response (void* cls,
531 */ 505 */
532static void 506static void
533handle_lookup (void *cls, 507handle_lookup (void *cls,
534 struct GNUNET_SERVER_Client * client, 508 struct GNUNET_SERVER_Client *client,
535 const struct GNUNET_MessageHeader * message) 509 const struct GNUNET_MessageHeader *message)
536{ 510{
537 size_t namelen; 511 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1];
538 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
539 struct ClientLookupHandle *clh; 512 struct ClientLookupHandle *clh;
540 char* nameptr = name; 513 char *nameptr = name;
541 const char *utf_in; 514 const char *utf_in;
542 int only_cached;
543 const struct GNUNET_CRYPTO_EccPrivateKey *key; 515 const struct GNUNET_CRYPTO_EccPrivateKey *key;
544 uint16_t msg_size; 516 uint16_t msg_size;
545 const struct GNUNET_GNS_ClientLookupMessage *sh_msg; 517 const struct GNUNET_GNS_ClientLookupMessage *sh_msg;
546 518
547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 "Received `%s' message\n", "LOOKUP"); 520 "Received `%s' message\n",
549 msg_size = ntohs(message->size); 521 "LOOKUP");
522 msg_size = ntohs (message->size);
550 if (msg_size < sizeof (struct GNUNET_GNS_ClientLookupMessage)) 523 if (msg_size < sizeof (struct GNUNET_GNS_ClientLookupMessage))
551 { 524 {
552 GNUNET_break (0); 525 GNUNET_break (0);
@@ -556,88 +529,48 @@ handle_lookup (void *cls,
556 sh_msg = (const struct GNUNET_GNS_ClientLookupMessage *) message; 529 sh_msg = (const struct GNUNET_GNS_ClientLookupMessage *) message;
557 GNUNET_SERVER_notification_context_add (nc, client); 530 GNUNET_SERVER_notification_context_add (nc, client);
558 if (GNUNET_YES == ntohl (sh_msg->have_key)) 531 if (GNUNET_YES == ntohl (sh_msg->have_key))
559 {
560 key = &sh_msg->shorten_key; 532 key = &sh_msg->shorten_key;
561 }
562 else 533 else
563 {
564 key = NULL; 534 key = NULL;
565 }
566 utf_in = (const char *) &sh_msg[1]; 535 utf_in = (const char *) &sh_msg[1];
567 if ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientLookupMessage) - 1]) 536 if ( ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientLookupMessage) - 1]) ||
537 (strlen (utf_in) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) )
568 { 538 {
569 GNUNET_break (0); 539 GNUNET_break (0);
570 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 540 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
571 return; 541 return;
572 } 542 }
573 GNUNET_STRINGS_utf8_tolower (utf_in, &nameptr); 543 GNUNET_STRINGS_utf8_tolower (utf_in, &nameptr);
574 544
575 namelen = strlen (name) + 1; 545 clh = GNUNET_new (struct ClientLookupHandle);
576 clh = GNUNET_malloc (sizeof (struct ClientLookupHandle)); 546 GNUNET_CONTAINER_DLL_insert (clh_head, clh_tail, clh);
577 memset (clh, 0, sizeof (struct ClientLookupHandle));
578 clh->client = client; 547 clh->client = client;
579 clh->name = GNUNET_malloc (namelen);
580 strcpy (clh->name, name);
581 clh->request_id = sh_msg->id; 548 clh->request_id = sh_msg->id;
582 clh->type = ntohl (sh_msg->type); 549 if ( (GNUNET_DNSPARSER_TYPE_A == ntohl (sh_msg->type)) &&
583 if (NULL != key) 550 (GNUNET_OK != v4_enabled) )
584 { 551 {
585 clh->shorten_key = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
586 *clh->shorten_key = *key;
587 }
588 only_cached = ntohl (sh_msg->only_cached);
589
590 if (strlen (name) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) {
591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
592 "LOOKUP: %s is too long", name); 553 "LOOKUP: Query for A record but AF_INET not supported!");
593 clh->name = NULL;
594 send_lookup_response (clh, 0, NULL);
595 return;
596 }
597
598 if ((GNUNET_DNSPARSER_TYPE_A == clh->type) &&
599 (GNUNET_OK != v4_enabled))
600 {
601 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
602 "LOOKUP: Query for A record but AF_INET not supported!");
603 clh->name = NULL;
604 send_lookup_response (clh, 0, NULL); 554 send_lookup_response (clh, 0, NULL);
605 return; 555 return;
606 } 556 }
607 557 if ( (GNUNET_DNSPARSER_TYPE_AAAA == ntohl (sh_msg->type)) &&
608 if ((GNUNET_DNSPARSER_TYPE_AAAA == clh->type) && 558 (GNUNET_OK != v6_enabled) )
609 (GNUNET_OK != v6_enabled))
610 { 559 {
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 560 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
612 "LOOKUP: Query for AAAA record but AF_INET6 not supported!"); 561 "LOOKUP: Query for AAAA record but AF_INET6 not supported!");
613 clh->name = NULL;
614 send_lookup_response (clh, 0, NULL); 562 send_lookup_response (clh, 0, NULL);
615 return; 563 return;
616 } 564 }
617 565 clh->lookup = GNS_resolver_lookup (&sh_msg->zone,
618 if (GNUNET_NO == ntohl (sh_msg->have_zone)) 566 ntohl (sh_msg->type),
619 clh->zone = zone_hash; /* Default zone */ 567 name,
620 else 568 key,
621 clh->zone = sh_msg->zone; 569 ntohl (sh_msg->only_cached),
622 570 &send_lookup_response, clh);
623 if (GNUNET_YES == auto_import_pkey)
624 {
625 gns_resolver_lookup_record (clh->zone, clh->zone, clh->type, clh->name,
626 clh->shorten_key,
627 default_lookup_timeout,
628 clh->only_cached,
629 &send_lookup_response, clh);
630 }
631 else
632 {
633 gns_resolver_lookup_record (clh->zone, clh->zone, clh->type, name,
634 NULL,
635 default_lookup_timeout,
636 only_cached,
637 &send_lookup_response, clh);
638 }
639 GNUNET_STATISTICS_update (statistics, 571 GNUNET_STATISTICS_update (statistics,
640 "Record lookup attempts", 1, GNUNET_NO); 572 "Lookup attempts",
573 1, GNUNET_NO);
641} 574}
642 575
643 576
@@ -656,9 +589,10 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
656 { &handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0}, 589 { &handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0},
657 {NULL, NULL, 0, 0} 590 {NULL, NULL, 0, 0}
658 }; 591 };
659 struct GNUNET_CRYPTO_EccPublicKey pkey; 592 struct GNUNET_CRYPTO_EccPublicKey dns_root;
660 unsigned long long max_parallel_bg_queries = 0; 593 unsigned long long max_parallel_bg_queries = 0;
661 int ignore_pending = GNUNET_NO; 594 int ignore_pending = GNUNET_NO;
595 char *dns_root_name;
662 596
663 v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); 597 v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6);
664 v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); 598 v4_enabled = GNUNET_NETWORK_test_pf (PF_INET);
@@ -672,15 +606,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
672 return; 606 return;
673 } 607 }
674 608
675 auto_import_pkey = GNUNET_NO;
676 if (GNUNET_YES ==
677 GNUNET_CONFIGURATION_get_value_yesno (c, "gns",
678 "AUTO_IMPORT_PKEY"))
679 {
680 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
681 "Automatic PKEY import is enabled.\n");
682 auto_import_pkey = GNUNET_YES;
683 }
684 put_interval = INITIAL_PUT_INTERVAL; 609 put_interval = INITIAL_PUT_INTERVAL;
685 zone_publish_time_window = DEFAULT_ZONE_PUBLISH_TIME_WINDOW; 610 zone_publish_time_window = DEFAULT_ZONE_PUBLISH_TIME_WINDOW;
686 611
@@ -734,7 +659,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
734 } 659 }
735 660
736 if (GNUNET_SYSERR == 661 if (GNUNET_SYSERR ==
737 gns_resolver_init (namestore_handle, dht_handle, zone_hash, c, 662 GNS_resolver_init (namestore_handle, dht_handle,
663 c,
738 max_parallel_bg_queries, 664 max_parallel_bg_queries,
739 ignore_pending)) 665 ignore_pending))
740 { 666 {
@@ -744,31 +670,45 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
744 return; 670 return;
745 } 671 }
746 672
747 if (GNUNET_YES == 673 if (GNUNET_OK ==
748 GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "HIJACK_DNS")) 674 GNUNET_CONFIGURATION_get_value_string (c, "gns", "DNS_ROOT",
675 &dns_root_name))
749 { 676 {
677 if (GNUNET_OK !=
678 GNUNET_CRYPTO_ecc_public_key_from_string (dns_root_name,
679 strlen (dns_root_name),
680 &dns_root))
681 {
682 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
683 "gns", "DNS_ROOT",
684 _("valid public key required"));
685 GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
686 GNUNET_free (dns_root_name);
687 return;
688 }
750 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 689 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
751 "DNS hijacking enabled. Connecting to DNS service.\n"); 690 "DNS hijacking with root `%s' enabled. Connecting to DNS service.\n",
752 691 dns_root_name);
692 GNUNET_free (dns_root_name);
753 if (GNUNET_SYSERR == 693 if (GNUNET_SYSERR ==
754 gns_interceptor_init (zone_hash, zone_key, c)) 694 GNS_interceptor_init (&dns_root, c))
755 { 695 {
756 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 696 GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
757 "Failed to enable the DNS interceptor!\n"); 697 return;
758 } 698 }
759 } 699 }
700 /* FIXME: install client disconnect handle to clean up pending
701 lookups on client disconnect! */
760 702
761 /** 703 /* Schedule periodic put for our records. */
762 * Schedule periodic put for our records We have roughly an hour for
763 * all records;
764 */
765 first_zone_iteration = GNUNET_YES; 704 first_zone_iteration = GNUNET_YES;
766 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL);
767 GNUNET_SERVER_add_handlers (server, handlers); 705 GNUNET_SERVER_add_handlers (server, handlers);
768 statistics = GNUNET_STATISTICS_create ("gns", c); 706 statistics = GNUNET_STATISTICS_create ("gns", c);
769 nc = GNUNET_SERVER_notification_context_create (server, 1); 707 nc = GNUNET_SERVER_notification_context_create (server, 1);
770 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, 708 zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start,
771 NULL); 709 NULL);
710 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
711 &shutdown_task, NULL);
772} 712}
773 713
774 714
diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c
index 8f1f1fb0b..ec6664454 100644
--- a/src/gns/gnunet-service-gns_interceptor.c
+++ b/src/gns/gnunet-service-gns_interceptor.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) 3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -24,18 +24,30 @@
24 */ 24 */
25#include "platform.h" 25#include "platform.h"
26#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
27#include "gnunet_transport_service.h"
28#include "gnunet_dns_service.h" 27#include "gnunet_dns_service.h"
29#include "gnunet_dnsparser_lib.h" 28#include "gnunet_dnsparser_lib.h"
30#include "gnunet-service-gns_resolver.h" 29#include "gnunet-service-gns_resolver.h"
30#include "gnunet-service-gns_interceptor.h"
31#include "gns.h" 31#include "gns.h"
32 32
33
33/** 34/**
34 * Handle to a DNS intercepted 35 * Handle to a DNS intercepted
35 * reslution request 36 * reslution request
36 */ 37 */
37struct InterceptLookupHandle 38struct InterceptLookupHandle
38{ 39{
40
41 /**
42 * We keep these in a DLL.
43 */
44 struct InterceptLookupHandle *next;
45
46 /**
47 * We keep these in a DLL.
48 */
49 struct InterceptLookupHandle *prev;
50
39 /** 51 /**
40 * the request handle to reply to 52 * the request handle to reply to
41 */ 53 */
@@ -45,11 +57,12 @@ struct InterceptLookupHandle
45 * the dns parser packet received 57 * the dns parser packet received
46 */ 58 */
47 struct GNUNET_DNSPARSER_Packet *packet; 59 struct GNUNET_DNSPARSER_Packet *packet;
48 60
49 /** 61 /**
50 * the query parsed from the packet 62 * Handle for the lookup operation.
51 */ 63 */
52 struct GNUNET_DNSPARSER_Query *query; 64 struct GNS_ResolverHandle *lookup;
65
53}; 66};
54 67
55 68
@@ -59,19 +72,19 @@ struct InterceptLookupHandle
59static struct GNUNET_DNS_Handle *dns_handle; 72static struct GNUNET_DNS_Handle *dns_handle;
60 73
61/** 74/**
62 * The root zone for this interceptor 75 * Key of the zone we start lookups in.
63 */ 76 */
64static struct GNUNET_CRYPTO_ShortHashCode our_zone; 77static struct GNUNET_CRYPTO_EccPublicKey zone;
65 78
66/** 79/**
67 * Our priv key 80 * Head of the DLL.
68 */ 81 */
69static struct GNUNET_CRYPTO_EccPrivateKey *our_key; 82static struct InterceptLookupHandle *ilh_head;
70 83
71/** 84/**
72 * Default timeout 85 * Tail of the DLL.
73 */ 86 */
74static struct GNUNET_TIME_Relative default_lookup_timeout; 87static struct InterceptLookupHandle *ilh_tail;
75 88
76 89
77/** 90/**
@@ -82,189 +95,132 @@ static struct GNUNET_TIME_Relative default_lookup_timeout;
82 * @param rd the record data 95 * @param rd the record data
83 */ 96 */
84static void 97static void
85reply_to_dns (void* cls, uint32_t rd_count, 98reply_to_dns (void *cls, uint32_t rd_count,
86 const struct GNUNET_NAMESTORE_RecordData *rd) 99 const struct GNUNET_NAMESTORE_RecordData *rd)
87{ 100{
101 struct InterceptLookupHandle *ilh = cls;
102 struct GNUNET_DNSPARSER_Packet *packet = ilh->packet;
103 struct GNUNET_DNSPARSER_Query *query = &packet->queries[0];
88 uint32_t i; 104 uint32_t i;
89 size_t len; 105 size_t len;
90 int ret; 106 int ret;
91 char *buf; 107 char *buf;
92 struct InterceptLookupHandle* ilh = (struct InterceptLookupHandle*)cls; 108 unsigned int num_answers;
93 struct GNUNET_DNSPARSER_Packet *packet = ilh->packet; 109
94 unsigned int num_answers = 0; 110 /* Put records in the DNS packet */
95 111 num_answers = 0;
96
97 /**
98 * Put records in the DNS packet and modify it
99 * to a response
100 */
101 for (i=0; i < rd_count; i++) 112 for (i=0; i < rd_count; i++)
102 { 113 if (rd[i].record_type == query->type)
103 if (rd[i].record_type == ilh->query->type)
104 num_answers++; 114 num_answers++;
105 }
106 115
107 struct GNUNET_DNSPARSER_Record answer_records[num_answers];
108 struct GNUNET_DNSPARSER_Record additional_records[rd_count-(num_answers)];
109 packet->answers = answer_records;
110 packet->additional_records = additional_records;
111
112 for (i=0; i < rd_count; i++)
113 { 116 {
114 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 117 struct GNUNET_DNSPARSER_Record answer_records[num_answers];
115 "Adding type %d to DNS response\n", rd[i].record_type); 118 struct GNUNET_DNSPARSER_Record additional_records[rd_count - num_answers];
116 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", ilh->query->name); 119
117 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count); 120 packet->answers = answer_records;
118 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size); 121 packet->additional_records = additional_records;
119 122
120 if (rd[i].record_type == ilh->query->type) 123 for (i=0; i < rd_count; i++)
121 { 124 {
122 answer_records[i].name = ilh->query->name; 125 if (rd[i].record_type == query->type)
123 answer_records[i].type = rd[i].record_type;
124 switch(rd[i].record_type)
125 { 126 {
126 case GNUNET_DNSPARSER_TYPE_NS: 127 answer_records[i].name = query->name;
127 case GNUNET_DNSPARSER_TYPE_CNAME: 128 answer_records[i].type = rd[i].record_type;
128 case GNUNET_DNSPARSER_TYPE_PTR: 129 switch(rd[i].record_type)
129 answer_records[i].data.hostname = (char*)rd[i].data; 130 {
130 break; 131 case GNUNET_DNSPARSER_TYPE_NS:
131 case GNUNET_DNSPARSER_TYPE_SOA: 132 case GNUNET_DNSPARSER_TYPE_CNAME:
132 answer_records[i].data.soa = 133 case GNUNET_DNSPARSER_TYPE_PTR:
133 (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; 134 answer_records[i].data.hostname = (char*)rd[i].data;
134 break; 135 break;
135 case GNUNET_DNSPARSER_TYPE_MX: 136 case GNUNET_DNSPARSER_TYPE_SOA:
136 answer_records[i].data.mx = 137 answer_records[i].data.soa =
137 (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data; 138 (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data;
138 break; 139 break;
139 default: 140 case GNUNET_DNSPARSER_TYPE_MX:
140 answer_records[i].data.raw.data_len = rd[i].data_size; 141 answer_records[i].data.mx =
141 answer_records[i].data.raw.data = (char*)rd[i].data; 142 (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data;
143 break;
144 default:
145 answer_records[i].data.raw.data_len = rd[i].data_size;
146 answer_records[i].data.raw.data = (char*)rd[i].data;
147 break;
148 }
149 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
150 answer_records[i].expiration_time.abs_value_us = rd[i].expiration_time;
151 answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;
142 } 152 }
143 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)); 153 else
144 answer_records[i].expiration_time.abs_value_us = rd[i].expiration_time;
145 answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
146 }
147 else
148 {
149 additional_records[i].name = ilh->query->name;
150 additional_records[i].type = rd[i].record_type;
151 switch(rd[i].record_type)
152 { 154 {
153 case GNUNET_DNSPARSER_TYPE_NS: 155 additional_records[i].name = query->name;
154 case GNUNET_DNSPARSER_TYPE_CNAME: 156 additional_records[i].type = rd[i].record_type;
155 case GNUNET_DNSPARSER_TYPE_PTR: 157 switch(rd[i].record_type)
156 additional_records[i].data.hostname = (char*)rd[i].data; 158 {
157 break; 159 case GNUNET_DNSPARSER_TYPE_NS:
158 case GNUNET_DNSPARSER_TYPE_SOA: 160 case GNUNET_DNSPARSER_TYPE_CNAME:
159 additional_records[i].data.soa = 161 case GNUNET_DNSPARSER_TYPE_PTR:
160 (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data; 162 additional_records[i].data.hostname = (char*)rd[i].data;
161 break; 163 break;
162 case GNUNET_DNSPARSER_TYPE_MX: 164 case GNUNET_DNSPARSER_TYPE_SOA:
163 additional_records[i].data.mx = 165 additional_records[i].data.soa =
164 (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data; 166 (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data;
165 break; 167 break;
166 default: 168 case GNUNET_DNSPARSER_TYPE_MX:
167 additional_records[i].data.raw.data_len = rd[i].data_size; 169 additional_records[i].data.mx =
168 additional_records[i].data.raw.data = (char*)rd[i].data; 170 (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data;
171 break;
172 default:
173 additional_records[i].data.raw.data_len = rd[i].data_size;
174 additional_records[i].data.raw.data = (char*)rd[i].data;
175 break;
176 }
177 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
178 additional_records[i].expiration_time.abs_value_us = rd[i].expiration_time;
179 additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;
169 } 180 }
170 GNUNET_break (0 == (rd[i].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION));
171 additional_records[i].expiration_time.abs_value_us = rd[i].expiration_time;
172 additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
173 } 181 }
182 packet->num_answers = num_answers;
183 packet->num_additional_records = rd_count - num_answers;
184 packet->flags.authoritative_answer = 1;
185 if (NULL == rd)
186 packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR;
187 else
188 packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR;
189 packet->flags.query_or_response = 1;
190 ret = GNUNET_DNSPARSER_pack (packet,
191 1024, /* maximum allowed size for DNS reply */
192 &buf,
193 &len);
194 if (GNUNET_OK != ret)
195 {
196 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
197 _("Error converting GNS response to DNS response!\n"));
198 }
199 else
200 {
201 GNUNET_DNS_request_answer (ilh->request_handle,
202 len,
203 buf);
204 GNUNET_free (buf);
205 }
206 packet->num_answers = 0;
207 packet->answers = NULL;
208 packet->num_additional_records = 0;
209 packet->additional_records = NULL;
210 GNUNET_DNSPARSER_free_packet (packet);
174 } 211 }
175 212 GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh);
176 packet->num_answers = num_answers; 213 GNUNET_free (ilh);
177 packet->num_additional_records = rd_count-(num_answers);
178
179 packet->flags.authoritative_answer = 1;
180
181 if (rd == NULL)
182 packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR;
183 else
184 packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR;
185
186 packet->flags.query_or_response = 1;
187
188
189 /**
190 * Reply to DNS
191 */
192 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
193 "Building DNS response\n");
194 ret = GNUNET_DNSPARSER_pack (packet,
195 1024, /* FIXME magic from dns redirector */
196 &buf,
197 &len);
198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
199 "Built DNS response! (ret=%d,len=%d)\n",
200 ret, len);
201 if (ret == GNUNET_OK)
202 {
203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
204 "Answering DNS request\n");
205 GNUNET_DNS_request_answer (ilh->request_handle,
206 len,
207 buf);
208
209 GNUNET_free (buf);
210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
211 "Answered DNS request\n");
212 }
213 else
214 {
215 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
216 "Error building DNS response! (ret=%d)", ret);
217 }
218
219 packet->num_answers = 0;
220 packet->answers = NULL;
221 packet->num_additional_records = 0;
222 packet->additional_records = NULL;
223 GNUNET_DNSPARSER_free_packet(packet);
224 GNUNET_free(ilh);
225}
226
227
228/**
229 * Entry point for name resolution
230 * Setup a new query and try to resolve
231 *
232 * @param request the request handle of the DNS request from a client
233 * @param p the DNS query packet we received
234 * @param q the DNS query we received parsed from p
235 */
236static void
237start_resolution_for_dns (struct GNUNET_DNS_RequestHandle *request,
238 struct GNUNET_DNSPARSER_Packet *p,
239 struct GNUNET_DNSPARSER_Query *q)
240{
241 struct InterceptLookupHandle* ilh;
242
243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
244 "Starting resolution for %s (type=%d)!\n",
245 q->name, q->type);
246 ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle));
247 ilh->packet = p;
248 ilh->query = q;
249 ilh->request_handle = request;
250
251 /* Start resolution in our zone */
252 gns_resolver_lookup_record(our_zone, our_zone, q->type, q->name,
253 our_key,
254 default_lookup_timeout,
255 GNUNET_NO,
256 &reply_to_dns, ilh);
257} 214}
258 215
259 216
260/** 217/**
261 * The DNS request handler 218 * The DNS request handler. Called for every incoming DNS request.
262 * Called for every incoming DNS request.
263 * 219 *
264 * @param cls closure 220 * @param cls closure, unused
265 * @param rh request handle to user for reply 221 * @param rh request handle to user for reply
266 * @param request_length number of bytes in request 222 * @param request_length number of bytes in @a request
267 * @param request udp payload of the DNS request 223 * @param request UDP payload of the DNS request
268 */ 224 */
269static void 225static void
270handle_dns_request (void *cls, 226handle_dns_request (void *cls,
@@ -273,61 +229,50 @@ handle_dns_request (void *cls,
273 const char *request) 229 const char *request)
274{ 230{
275 struct GNUNET_DNSPARSER_Packet *p; 231 struct GNUNET_DNSPARSER_Packet *p;
232 struct InterceptLookupHandle *ilh;
276 233
277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
278 "Hijacked a DNS request...processing\n"); 235 "Hijacked a DNS request. Processing.\n");
279 if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length))) 236 if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length)))
280 { 237 {
281 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 238 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
282 "Received malformed DNS packet, leaving it untouched\n"); 239 "Received malformed DNS packet, leaving it untouched.\n");
283 GNUNET_DNS_request_forward (rh); 240 GNUNET_DNS_request_forward (rh);
284 GNUNET_DNSPARSER_free_packet (p); 241 GNUNET_DNSPARSER_free_packet (p);
285 return; 242 return;
286 } 243 }
287 244
288 /** 245 /* Check TLD and decide if we or legacy dns is responsible */
289 * Check tld and decide if we or 246 if (1 != p->num_queries)
290 * legacy dns is responsible
291 *
292 * FIXME now in theory there could be more than 1 query in the request
293 * but if this is case we get into trouble:
294 * either we query the GNS or the DNS. We cannot do both!
295 * So I suggest to either only allow a single query per request or
296 * only allow GNS or DNS requests.
297 * The way it is implemented here now is buggy and will lead to erratic
298 * behaviour (if multiple queries are present).
299 */
300 if (0 == p->num_queries)
301 { 247 {
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
303 "No Queries in DNS packet... forwarding\n"); 249 "Not exactly one query in DNS packet. Forwarding untouched.\n");
304 GNUNET_DNS_request_forward (rh); 250 GNUNET_DNS_request_forward (rh);
305 GNUNET_DNSPARSER_free_packet(p); 251 GNUNET_DNSPARSER_free_packet(p);
306 return; 252 return;
307 } 253 }
308 254
309 /** 255 /* Check for GNS TLDs. */
310 * Check for .gads/.zkey 256 if ( (GNUNET_YES == is_gads_tld (p->queries[0].name)) ||
311 */ 257 (GNUNET_YES == is_zkey_tld (p->queries[0].name)) ||
312 258 (0 == strcmp (p->queries[0].name, GNUNET_GNS_TLD)) )
313 if ((is_gads_tld(p->queries[0].name) == GNUNET_YES) ||
314 (is_zkey_tld(p->queries[0].name) == GNUNET_YES) ||
315 (strcmp(p->queries[0].name, GNUNET_GNS_TLD) == 0))
316 { 259 {
317 if (p->num_queries > 1) 260 /* Start resolution in GNS */
318 { 261 ilh = GNUNET_new (struct InterceptLookupHandle);
319 /* Note: We could also look for .gads */ 262 GNUNET_CONTAINER_DLL_insert (ilh_head, ilh_tail, ilh);
320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 263 ilh->packet = p;
321 ">1 queriy in DNS packet... odd. We only process #1\n"); 264 ilh->request_handle = rh;
322 } 265 ilh->lookup = GNS_resolver_lookup (&zone,
323 start_resolution_for_dns (rh, p, p->queries); 266 p->queries[0].type,
267 p->queries[0].name,
268 NULL /* FIXME: enable shorten for DNS intercepts? */,
269 GNUNET_NO,
270 &reply_to_dns, ilh);
324 return; 271 return;
325 } 272 }
326 /** 273 /* This request does not concern us. Forward to real DNS. */
327 * This request does not concern us. Forward to real DNS.
328 */
329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
330 "Request for %s is forwarded to DNS\n", 275 "Request for `%s' is forwarded to DNS untouched.\n",
331 p->queries[0].name); 276 p->queries[0].name);
332 GNUNET_DNS_request_forward (rh); 277 GNUNET_DNS_request_forward (rh);
333 GNUNET_DNSPARSER_free_packet (p); 278 GNUNET_DNSPARSER_free_packet (p);
@@ -337,37 +282,25 @@ handle_dns_request (void *cls,
337/** 282/**
338 * Initialized the interceptor 283 * Initialized the interceptor
339 * 284 *
340 * @param zone the zone to work in 285 * @param gnu_zone the zone to work in
341 * @param key the prov key of the zone (can be null, needed for caching)
342 * @param c the configuration 286 * @param c the configuration
343 * @return GNUNET_OK on success 287 * @return GNUNET_OK on success
344 */ 288 */
345int 289int
346gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone, 290GNS_interceptor_init (const struct GNUNET_CRYPTO_EccPublicKey *gnu_zone,
347 struct GNUNET_CRYPTO_EccPrivateKey *key,
348 const struct GNUNET_CONFIGURATION_Handle *c) 291 const struct GNUNET_CONFIGURATION_Handle *c)
349{ 292{
350 GNUNET_log(GNUNET_ERROR_TYPE_INFO, 293 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
351 "DNS hijacking enabled... connecting to service.\n"); 294 "DNS hijacking enabled. Connecting to DNS service.\n");
352 our_zone = zone; 295 zone = *gnu_zone;
353 our_key = key;
354 /**
355 * Do gnunet dns init here
356 */
357 dns_handle = GNUNET_DNS_connect (c, 296 dns_handle = GNUNET_DNS_connect (c,
358 GNUNET_DNS_FLAG_PRE_RESOLUTION, 297 GNUNET_DNS_FLAG_PRE_RESOLUTION,
359 &handle_dns_request, /* rh */ 298 &handle_dns_request,
360 NULL); /* Closure */ 299 NULL);
361
362 if (GNUNET_OK !=
363 GNUNET_CONFIGURATION_get_value_time (c, "gns",
364 "DEFAULT_LOOKUP_TIMEOUT",
365 &default_lookup_timeout))
366 default_lookup_timeout = GNUNET_TIME_UNIT_ZERO;
367 if (NULL == dns_handle) 300 if (NULL == dns_handle)
368 { 301 {
369 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, 302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
370 "Failed to connect to the dnsservice!\n"); 303 _("Failed to connect to the DNS service!\n"));
371 return GNUNET_SYSERR; 304 return GNUNET_SYSERR;
372 } 305 }
373 return GNUNET_YES; 306 return GNUNET_YES;
@@ -378,13 +311,23 @@ gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone,
378 * Disconnect from interceptor 311 * Disconnect from interceptor
379 */ 312 */
380void 313void
381gns_interceptor_stop () 314GNS_interceptor_done ()
382{ 315{
316 struct InterceptLookupHandle *ilh;
317
318 while (NULL != (ilh = ilh_head))
319 {
320 GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh);
321 GNS_resolver_lookup_cancel (ilh->lookup);
322 GNUNET_DNS_request_drop (ilh->request_handle);
323 GNUNET_DNSPARSER_free_packet (ilh->packet);
324 GNUNET_free (ilh);
325 }
383 if (NULL != dns_handle) 326 if (NULL != dns_handle)
384 { 327 {
385 GNUNET_DNS_disconnect(dns_handle); 328 GNUNET_DNS_disconnect (dns_handle);
386 dns_handle = NULL; 329 dns_handle = NULL;
387 } 330 }
388} 331}
389 332
390/* end of gns_interceptor.c */ 333/* end of gnunet-service-gns_interceptor.c */
diff --git a/src/gns/gnunet-service-gns_interceptor.h b/src/gns/gnunet-service-gns_interceptor.h
index a1da4938b..92a154e2c 100644
--- a/src/gns/gnunet-service-gns_interceptor.h
+++ b/src/gns/gnunet-service-gns_interceptor.h
@@ -27,23 +27,22 @@
27 27
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29 29
30
30/** 31/**
31 * Initialize dns interceptor 32 * Initialize DNS interceptor
32 * 33 *
33 * @param zone the zone 34 * @param gnu_zone the zone we start lookups in
34 * @param key the private key of the local zone
35 * @param c the configuration 35 * @param c the configuration
36 * @return GNUNET_YES on success GNUNET_SYSERR on error 36 * @return GNUNET_YES on success GNUNET_SYSERR on error
37 */ 37 */
38int 38int
39gns_interceptor_init (struct GNUNET_CRYPTO_ShortHashCode zone, 39GNS_interceptor_init (const struct GNUNET_CRYPTO_EccPublicKey *gnu_zone,
40 struct GNUNET_CRYPTO_EccPrivateKey *key,
41 const struct GNUNET_CONFIGURATION_Handle *c); 40 const struct GNUNET_CONFIGURATION_Handle *c);
42 41
43/** 42/**
44 * Stops the interceptor 43 * Stops the interceptor
45 */ 44 */
46void 45void
47gns_interceptor_stop (void); 46GNS_interceptor_done (void);
48 47
49#endif 48#endif
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c
index b01200d8e..fb334c1a0 100644
--- a/src/gns/gnunet-service-gns_resolver.c
+++ b/src/gns/gnunet-service-gns_resolver.c
@@ -36,7 +36,6 @@
36#include "gns_protocol.h" 36#include "gns_protocol.h"
37#include "gnunet_gns_service.h" 37#include "gnunet_gns_service.h"
38#include "gns_common.h" 38#include "gns_common.h"
39#include "block_gns.h"
40#include "gns.h" 39#include "gns.h"
41#include "gnunet-service-gns_resolver.h" 40#include "gnunet-service-gns_resolver.h"
42#ifndef WINDOWS 41#ifndef WINDOWS
@@ -44,6 +43,20 @@
44#endif 43#endif
45 44
46 45
46#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
47
48#define GNUNET_GNS_DEFAULT_LOOKUP_TIMEOUT \
49 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
50
51#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
52
53#define DHT_GNS_REPLICATION_LEVEL 5
54
55#define GNUNET_GNS_MAX_PARALLEL_LOOKUPS 500
56
57#define GNUNET_GNS_MAX_NS_TASKS 500
58
59
47/** 60/**
48 * Default DHT timeout 61 * Default DHT timeout
49 */ 62 */
@@ -55,92 +68,446 @@
55#define DHT_GNS_REPLICATION_LEVEL 5 68#define DHT_GNS_REPLICATION_LEVEL 5
56 69
57 70
71/*
72 * DLL to hold the authority chain
73 * we had to pass in the resolution process
74 */
75struct AuthorityChain
76{
77 struct AuthorityChain *prev;
78
79 struct AuthorityChain *next;
80
81 /**
82 * the zone hash of the authority
83 */
84 struct GNUNET_CRYPTO_ShortHashCode zone;
85
86 /**
87 * (local) name of the authority
88 */
89 char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
90
91 /**
92 * was the ns entry fresh
93 */
94 int fresh;
95};
96
97
58/** 98/**
59 * Our handle to the namestore service 99 * handle to a resolution process
60 */ 100 */
61static struct GNUNET_NAMESTORE_Handle *namestore_handle; 101struct ResolverHandle;
102
62 103
63#ifndef WINDOWS
64/** 104/**
65 * Our handle to the vpn service 105 * processor for a record lookup result
106 *
107 * @param cls the closure
108 * @param rd_count number of results
109 * @param rd result data
66 */ 110 */
67static struct GNUNET_VPN_Handle *vpn_handle; 111typedef void (*RecordLookupProcessor) (void *cls,
68#endif 112 uint32_t rd_count,
113 const struct GNUNET_NAMESTORE_RecordData *rd);
114
69 115
70/** 116/**
71 * Resolver handle to the dht 117 * processor for a resolution result
118 *
119 * @param cls the closure
120 * @param rh the resolution handle
121 * @param rd_count number of results
122 * @param rd result data (array of 'rd_count' records)
72 */ 123 */
73static struct GNUNET_DHT_Handle *dht_handle; 124typedef void (*ResolutionResultProcessor) (void *cls,
125 struct ResolverHandle *rh,
126 uint32_t rd_count,
127 const struct GNUNET_NAMESTORE_RecordData *rd);
128
74 129
75/** 130/**
76 * Heap for parallel DHT lookups 131 * Resolution status indicator
77 */ 132 */
78static struct GNUNET_CONTAINER_Heap *dht_lookup_heap; 133enum ResolutionStatus
134{
135 /**
136 * the name to lookup exists
137 */
138 RSL_RECORD_EXISTS = 1,
139
140 /**
141 * the name in the record expired
142 */
143 RSL_RECORD_EXPIRED = 2,
144
145 /**
146 * resolution timed out
147 */
148 RSL_TIMED_OUT = 4,
149
150 /**
151 * Found VPN delegation
152 */
153 RSL_DELEGATE_VPN = 8,
154
155 /**
156 * Found NS delegation
157 */
158 RSL_DELEGATE_NS = 16,
159
160 /**
161 * Found PKEY delegation
162 */
163 RSL_DELEGATE_PKEY = 32,
164
165 /**
166 * Found CNAME record
167 */
168 RSL_CNAME_FOUND = 64,
169
170 /**
171 * Found PKEY has been revoked
172 */
173 RSL_PKEY_REVOKED = 128
174};
175
79 176
80/** 177/**
81 * Heap for namestore queues 178 * Handle to a currenty pending resolution
179 * a ResolverHandle is passed to, for example
180 * resolve_record_ns to resolve a record in the namestore.
181 * On result (positive or negative) the ResolutionResultProcessor
182 * is called.
183 * If a timeout is set timeout_cont will be called.
184 * If no timeout is set (ie timeout forever) then background resolutions
185 * might be triggered.
82 */ 186 */
83static struct GNUNET_CONTAINER_Heap *ns_task_heap; 187struct GNS_ResolverHandle
188{
189
190 /**
191 * DLL
192 */
193 struct ResolverHandle *next;
194
195 /**
196 * DLL
197 */
198 struct ResolverHandle *prev;
199
200 /**
201 * Last record data found
202 */
203 struct GNUNET_NAMESTORE_RecordData rd;
204
205 /**
206 * Number of last record data found
207 */
208 unsigned int rd_count;
209
210 /**
211 * The name to resolve
212 */
213 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
214
215 /**
216 * has this query been answered? how many matches
217 */
218 int answered;
219
220 /**
221 * Use only cache
222 */
223 int only_cached;
224
225 /**
226 * the authoritative zone to query
227 */
228 struct GNUNET_CRYPTO_ShortHashCode authority;
229
230 /**
231 * the name of the authoritative zone to query
232 */
233 char authority_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
234
235 /**
236 * a handle for dht lookups. should be NULL if no lookups are in progress
237 */
238 struct GNUNET_DHT_GetHandle *get_handle;
239
240 /**
241 * timeout set for this lookup task
242 */
243 struct GNUNET_TIME_Relative timeout;
244
245 /**
246 * a handle to a vpn request
247 */
248 struct GNUNET_VPN_RedirectionRequest *vpn_handle;
249
250 /**
251 * a socket for a dns request
252 */
253 struct GNUNET_NETWORK_Handle *dns_sock;
254
255 /**
256 * a synthesized dns name
257 */
258 char dns_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
259
260 /**
261 * the authoritative dns zone
262 */
263 char dns_zone[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
264
265 /**
266 * the address of the DNS server FIXME not needed?
267 */
268 struct sockaddr_in dns_addr;
269
270 /**
271 * handle to the local stub resolver request
272 */
273 struct GNUNET_RESOLVER_RequestHandle *dns_resolver_handle;
274
275 /**
276 * select task for DNS
277 */
278 GNUNET_SCHEDULER_TaskIdentifier dns_read_task;
279
280 /**
281 * pointer to raw dns query payload FIXME needs to be freed/NULL
282 */
283 char *dns_raw_packet;
284
285 /**
286 * size of the raw dns query
287 */
288 size_t dns_raw_packet_size;
289
290 /**
291 * timeout task for the lookup
292 */
293 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
294
295 /**
296 * continuation to call on timeout
297 */
298 GNUNET_SCHEDULER_Task timeout_cont;
299
300 /**
301 * closure for timeout cont
302 */
303 void* timeout_cont_cls;
304
305 /**
306 * called when resolution phase finishes
307 */
308 ResolutionResultProcessor proc;
309
310 /**
311 * closure passed to proc
312 */
313 void* proc_cls;
314
315 /**
316 * DLL to store the authority chain
317 */
318 struct AuthorityChain *authority_chain_head;
319
320 /**
321 * DLL to store the authority chain
322 */
323 struct AuthorityChain *authority_chain_tail;
324
325 /**
326 * status of the resolution result
327 */
328 enum ResolutionStatus status;
329
330 /**
331 * The provate local zone of this request
332 */
333 struct GNUNET_CRYPTO_ShortHashCode private_local_zone;
334
335 /**
336 * private key of an/our authoritative zone
337 * can be NULL but automatical PKEY import will not work
338 */
339 struct GNUNET_CRYPTO_EccPrivateKey *priv_key;
340
341 /**
342 * the heap node associated with this lookup, null if timeout is set
343 * used for DHT background lookups.
344 */
345 struct GNUNET_CONTAINER_HeapNode *dht_heap_node;
346
347 /**
348 * Id for resolution process
349 */
350 unsigned long long id;
351
352 /**
353 * Pending Namestore task
354 */
355 struct GNUNET_NAMESTORE_QueueEntry *namestore_task;
356
357};
358
84 359
85/** 360/**
86 * Maximum amount of parallel queries in background 361 * Handle to a record lookup
87 */ 362 */
88static unsigned long long max_allowed_background_queries; 363struct RecordLookupHandle
364{
365 /**
366 * the record type to look up
367 */
368 int record_type;
369
370 /**
371 * the name to look up
372 */
373 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
374
375 /**
376 * Method to call on record resolution result
377 */
378 RecordLookupProcessor proc;
379
380 /**
381 * closure to pass to proc
382 */
383 void* proc_cls;
384
385};
386
89 387
90/** 388/**
91 * Maximum amount of parallel namestore tasks in background 389 * Handle to a pseu lookup
92 */ 390 */
93static unsigned long long max_allowed_ns_tasks; 391struct GetPseuAuthorityHandle
392{
393 /**
394 * DLL
395 */
396 struct GetPseuAuthorityHandle *next;
397
398 /**
399 * DLL
400 */
401 struct GetPseuAuthorityHandle *prev;
402
403 /**
404 * the name to store the zone under
405 */
406 char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
407
408 /**
409 * test name to store the zone under
410 */
411 char test_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
412
413 /**
414 * the zone of our authority
415 */
416 struct GNUNET_CRYPTO_ShortHashCode our_zone;
417
418 /**
419 * the private key of the zone to store the pseu in
420 */
421 struct GNUNET_CRYPTO_EccPrivateKey *key;
422
423 /**
424 * a handle for dht lookups. should be NULL if no lookups are in progress
425 */
426 struct GNUNET_DHT_GetHandle *get_handle;
427
428 /**
429 * timeout task for lookup
430 */
431 GNUNET_SCHEDULER_TaskIdentifier timeout;
432
433 /**
434 * Authority to shorten
435 */
436 struct AuthorityChain *auth;
437
438 /**
439 * handle to namestore request
440 */
441 struct GNUNET_NAMESTORE_QueueEntry* namestore_task;
442};
443
94 444
95/** 445/**
96 * Wheather or not to ignore pending records 446 * Namestore queue entries in background
97 */ 447 */
98static int ignore_pending_records; 448struct NamestoreBGTask
449{
450 /**
451 * node in heap
452 */
453 struct GNUNET_CONTAINER_HeapNode *node;
454
455 /**
456 * queue entry
457 */
458 struct GNUNET_NAMESTORE_QueueEntry *qe;
459};
460
99 461
100/** 462/**
101 * Our local zone 463 * Our handle to the namestore service
102 */ 464 */
103static struct GNUNET_CRYPTO_ShortHashCode local_zone; 465static struct GNUNET_NAMESTORE_Handle *namestore_handle;
104 466
105/** 467/**
106 * Background shortening handles 468 * Our handle to the vpn service
107 */ 469 */
108static struct GetPseuAuthorityHandle *gph_head; 470static struct GNUNET_VPN_Handle *vpn_handle;
109 471
110/** 472/**
111 * Background shortening handles 473 * Resolver handle to the dht
112 */ 474 */
113static struct GetPseuAuthorityHandle *gph_tail; 475static struct GNUNET_DHT_Handle *dht_handle;
114 476
115/** 477/**
116 * Resolver lookup list 478 * Heap for parallel DHT lookups
117 */ 479 */
118static struct ResolverHandle *rlh_head; 480static struct GNUNET_CONTAINER_Heap *dht_lookup_heap;
119 481
120/** 482/**
121 * Resolver lookup list 483 * Heap for namestore queues
122 */ 484 */
123static struct ResolverHandle *rlh_tail; 485static struct GNUNET_CONTAINER_Heap *ns_task_heap;
486
487/**
488 * Maximum amount of parallel queries in background
489 */
490static unsigned long long max_allowed_background_queries;
124 491
125/** 492/**
126 * Resolver shorten list 493 * Maximum amount of parallel namestore tasks in background
127 */ 494 */
128static struct ResolverHandle *nsh_head; 495static unsigned long long max_allowed_ns_tasks;
129 496
130/** 497/**
131 * Resolver shorten list 498 * Whether or not to ignore pending records
132 */ 499 */
133static struct ResolverHandle *nsh_tail; 500static int ignore_pending_records;
134 501
135/** 502/**
136 * Resolver get auth list 503 * Resolver lookup list
137 */ 504 */
138static struct ResolverHandle *nah_head; 505static struct ResolverHandle *rlh_head;
139 506
140/** 507/**
141 * Resolver get auth list 508 * Resolver lookup list
142 */ 509 */
143static struct ResolverHandle *nah_tail; 510static struct ResolverHandle *rlh_tail;
144 511
145/** 512/**
146 * Global configuration. 513 * Global configuration.
@@ -345,245 +712,6 @@ process_pseu_result (struct GetPseuAuthorityHandle* gph,
345 712
346 713
347/** 714/**
348 * Handle timeout for dht request
349 *
350 * @param cls the request handle as closure
351 * @param tc the task context
352 */
353static void
354handle_auth_discovery_timeout (void *cls,
355 const struct GNUNET_SCHEDULER_TaskContext *tc)
356{
357 struct GetPseuAuthorityHandle* gph = cls;
358
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 "GNS_GET_AUTH: dht lookup for query PSEU timed out.\n");
361 GNUNET_DHT_get_stop (gph->get_handle);
362 gph->get_handle = NULL;
363 process_pseu_result (gph, NULL);
364}
365
366
367/**
368 * Function called when we find a PSEU entry in the DHT
369 *
370 * @param cls the request handle
371 * @param exp lifetime
372 * @param key the key the record was stored under
373 * @param get_path get path
374 * @param get_path_length get path length
375 * @param put_path put path
376 * @param put_path_length put path length
377 * @param type the block type
378 * @param size the size of the record
379 * @param data the record data
380 */
381static void
382process_auth_discovery_dht_result (void* cls,
383 struct GNUNET_TIME_Absolute exp,
384 const struct GNUNET_HashCode * key,
385 const struct GNUNET_PeerIdentity *get_path,
386 unsigned int get_path_length,
387 const struct GNUNET_PeerIdentity *put_path,
388 unsigned int put_path_length,
389 enum GNUNET_BLOCK_Type type,
390 size_t size,
391 const void *data)
392{
393 struct GetPseuAuthorityHandle* gph = cls;
394 struct GNSNameRecordBlock *nrb;
395 const char* rd_data = data;
396 char* name;
397 int num_records;
398 size_t rd_size;
399 int i;
400
401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
402 "GNS_GET_AUTH: got dht result (size=%d)\n", size);
403
404 /* stop lookup and timeout task */
405 GNUNET_DHT_get_stop (gph->get_handle);
406 gph->get_handle = NULL;
407 GNUNET_SCHEDULER_cancel (gph->timeout);
408
409 if (NULL == data)
410 {
411 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
412 "GNS_GET_AUTH: got dht result null!\n", size);
413 free_get_pseu_authority_handle (gph);
414 return;
415 }
416
417 nrb = (struct GNSNameRecordBlock*)data;
418 name = (char*)&nrb[1];
419 num_records = ntohl (nrb->rd_count);
420 {
421 struct GNUNET_NAMESTORE_RecordData rd[num_records];
422
423 rd_data += strlen (name) + 1 + sizeof (struct GNSNameRecordBlock);
424 rd_size = size - strlen (name) - 1 - sizeof (struct GNSNameRecordBlock);
425
426 if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size,
427 rd_data,
428 num_records,
429 rd))
430 {
431 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
432 "GNS_GET_AUTH: Error deserializing data!\n");
433 }
434 else
435 {
436 for (i=0; i < num_records; i++)
437 {
438 if ((strcmp (name, GNUNET_GNS_MASTERZONE_STR) == 0) &&
439 (rd[i].record_type == GNUNET_NAMESTORE_TYPE_PSEU))
440 {
441 /* found pseu */
442 process_pseu_result (gph, (char*)rd[i].data);
443 return;
444 }
445 }
446 }
447 }
448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
449 "GNS_GET_AUTH: finished shorten, no results!\n");
450 process_pseu_result (gph, NULL);
451}
452
453
454/**
455 * Process PSEU discovery for shorten via namestore
456 *
457 * @param cls the GetPseuAuthorityHandle
458 * @param key the public key
459 * @param expiration recorddata expiration
460 * @param name the looked up name
461 * @param rd_count number of records in set
462 * @param rd record data
463 * @param signature the signature
464 */
465static void
466process_auth_discovery_ns_result (void* cls,
467 const struct GNUNET_CRYPTO_EccPublicKey *key,
468 struct GNUNET_TIME_Absolute expiration,
469 const char *name,
470 unsigned int rd_count,
471 const struct GNUNET_NAMESTORE_RecordData *rd,
472 const struct GNUNET_CRYPTO_EccSignature *signature)
473{
474 struct GetPseuAuthorityHandle* gph = cls;
475 struct GNUNET_HashCode lookup_key;
476 unsigned int i;
477 uint32_t xquery;
478
479 gph->namestore_task = NULL;
480 /* no pseu found */
481 if (0 == rd_count)
482 {
483 GNUNET_GNS_get_key_for_record (GNUNET_GNS_TLD_PLUS, &gph->auth->zone, &lookup_key);
484 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
485 "GNS_AUTO_PSEU: starting dht lookup for %s with key: %s\n",
486 GNUNET_GNS_TLD_PLUS,
487 GNUNET_h2s (&lookup_key));
488
489 gph->timeout = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT,
490 &handle_auth_discovery_timeout, gph);
491
492 xquery = htonl (GNUNET_NAMESTORE_TYPE_PSEU);
493
494 GNUNET_assert (gph->get_handle == NULL);
495
496 gph->get_handle = GNUNET_DHT_get_start (dht_handle,
497 GNUNET_BLOCK_TYPE_GNS_NAMERECORD,
498 &lookup_key,
499 DHT_GNS_REPLICATION_LEVEL,
500 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
501 &xquery,
502 sizeof(xquery),
503 &process_auth_discovery_dht_result,
504 gph);
505 return;
506 }
507
508 for (i=0; i < rd_count; i++)
509 {
510 if (0 != (strcmp (name, GNUNET_GNS_TLD_PLUS)))
511 continue;
512
513 if (rd[i].record_type != GNUNET_NAMESTORE_TYPE_PSEU)
514 continue;
515
516 /* found pseu */
517 process_pseu_result (gph, (char*)rd[i].data);
518 return;
519 }
520
521 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNS_GET_AUTH: no pseu in namestore!\n");
522 process_pseu_result (gph, NULL);
523}
524
525
526/**
527 * Callback called by namestore for a zone to name
528 * result
529 *
530 * @param cls the closure
531 * @param zone_key the zone we queried
532 * @param expire the expiration time of the name
533 * @param name the name found or NULL
534 * @param rd_len number of records for the name
535 * @param rd the record data (PKEY) for the name
536 * @param signature the signature for the record data
537 */
538static void
539process_zone_to_name_discover (void *cls,
540 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
541 struct GNUNET_TIME_Absolute expire,
542 const char *name,
543 unsigned int rd_len,
544 const struct GNUNET_NAMESTORE_RecordData *rd,
545 const struct GNUNET_CRYPTO_EccSignature *signature)
546{
547 struct GetPseuAuthorityHandle* gph = cls;
548
549 gph->namestore_task = NULL;
550 if (0 == rd_len)
551 {
552 gph->namestore_task = GNUNET_NAMESTORE_lookup_record (namestore_handle,
553 &gph->auth->zone,
554 GNUNET_GNS_MASTERZONE_STR,
555 GNUNET_NAMESTORE_TYPE_PSEU,
556 &process_auth_discovery_ns_result,
557 gph);
558 return;
559 }
560 /* we found a match in our own zone */
561 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
562 "GNS_AUTO_PSEU: name for zone in our root %s\n", name);
563 free_get_pseu_authority_handle (gph);
564}
565
566
567/**
568 * Callback that shortens authorities
569 *
570 * @param gph the handle to the shorten request
571 */
572static void
573shorten_authority_chain (struct GetPseuAuthorityHandle *gph)
574{
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
576 "GNS_AUTO_PSEU: New authority %s discovered\n",
577 gph->auth->name);
578 gph->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
579 &gph->our_zone,
580 &gph->auth->zone,
581 &process_zone_to_name_discover,
582 gph);
583}
584
585
586/**
587 * Start shortening algorithm using auth as 715 * Start shortening algorithm using auth as
588 * authority chain 716 * authority chain
589 * 717 *
@@ -631,9 +759,8 @@ start_shorten (struct AuthorityChain *auth,
631 * @return GNUNET_OK on success 759 * @return GNUNET_OK on success
632 */ 760 */
633int 761int
634gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, 762GNS_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
635 struct GNUNET_DHT_Handle *dh, 763 struct GNUNET_DHT_Handle *dh,
636 struct GNUNET_CRYPTO_ShortHashCode lz,
637 const struct GNUNET_CONFIGURATION_Handle *c, 764 const struct GNUNET_CONFIGURATION_Handle *c,
638 unsigned long long max_bg_queries, 765 unsigned long long max_bg_queries,
639 int ignore_pending) 766 int ignore_pending)
@@ -657,6 +784,7 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
657 return GNUNET_OK; 784 return GNUNET_OK;
658} 785}
659 786
787
660/** 788/**
661 * finish lookup 789 * finish lookup
662 * 790 *
@@ -744,7 +872,7 @@ finish_get_auth (struct ResolverHandle *rh,
744 * Shutdown resolver 872 * Shutdown resolver
745 */ 873 */
746void 874void
747gns_resolver_cleanup () 875GNS_resolver_done ()
748{ 876{
749 struct GetPseuAuthorityHandle *tmp; 877 struct GetPseuAuthorityHandle *tmp;
750 struct ResolverHandle *rh; 878 struct ResolverHandle *rh;
@@ -3311,25 +3439,21 @@ resolve_delegation_ns (struct ResolverHandle *rh)
3311 * calls lookup result processor on result 3439 * calls lookup result processor on result
3312 * 3440 *
3313 * @param zone the root zone 3441 * @param zone the root zone
3314 * @param pzone the private local zone
3315 * @param record_type the record type to look up 3442 * @param record_type the record type to look up
3316 * @param name the name to look up 3443 * @param name the name to look up
3317 * @param key a private key for use with PSEU import (can be NULL) 3444 * @param shorten_key a private key for use with PSEU import (can be NULL)
3318 * @param timeout timeout for resolution
3319 * @param only_cached GNUNET_NO to only check locally not DHT for performance 3445 * @param only_cached GNUNET_NO to only check locally not DHT for performance
3320 * @param proc the processor to call on result 3446 * @param proc the processor to call on result
3321 * @param cls the closure to pass to proc 3447 * @param proc_cls the closure to pass to @a proc
3322 */ 3448 */
3323void 3449void
3324gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone, 3450GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey * zone,
3325 struct GNUNET_CRYPTO_ShortHashCode pzone, 3451 uint32_t record_type,
3326 uint32_t record_type, 3452 const char* name,
3327 const char* name, 3453 struct GNUNET_CRYPTO_EccPrivateKey *shorten_key,
3328 struct GNUNET_CRYPTO_EccPrivateKey *key, 3454 int only_cached,
3329 struct GNUNET_TIME_Relative timeout, 3455 RecordLookupProcessor proc,
3330 int only_cached, 3456 void *proc_cls)
3331 RecordLookupProcessor proc,
3332 void* cls)
3333{ 3457{
3334 struct ResolverHandle *rh; 3458 struct ResolverHandle *rh;
3335 struct RecordLookupHandle* rlh; 3459 struct RecordLookupHandle* rlh;
@@ -3479,848 +3603,5 @@ gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone,
3479 resolve_delegation_ns (rh); 3603 resolve_delegation_ns (rh);
3480} 3604}
3481 3605
3482/******** END Record Resolver ***********/
3483
3484static void
3485finish_shorten (struct ResolverHandle *rh,
3486 struct NameShortenHandle *nsh)
3487{
3488 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3489 "Sending %s as shorten result\n", nsh->result);
3490 nsh->proc (nsh->proc_cls, nsh->result);
3491 GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
3492 GNUNET_free (nsh);
3493 free_resolver_handle (rh);
3494}
3495
3496
3497/**
3498 * Callback calles by namestore for a zone to name
3499 * result
3500 *
3501 * @param cls the closure
3502 * @param zone_key the zone we queried
3503 * @param expire the expiration time of the name
3504 * @param name the name found or NULL
3505 * @param rd_len number of records for the name
3506 * @param rd the record data (PKEY) for the name
3507 * @param signature the signature for the record data
3508 */
3509static void
3510process_zone_to_name_shorten_root (void *cls,
3511 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
3512 struct GNUNET_TIME_Absolute expire,
3513 const char *name,
3514 unsigned int rd_len,
3515 const struct GNUNET_NAMESTORE_RecordData *rd,
3516 const struct GNUNET_CRYPTO_EccSignature *signature);
3517
3518
3519/**
3520 * Callback called by namestore for a zone to name
3521 * result
3522 *
3523 * @param cls the closure
3524 * @param zone_key the zone we queried
3525 * @param expire the expiration time of the name
3526 * @param name the name found or NULL
3527 * @param rd_len number of records for the name
3528 * @param rd the record data (PKEY) for the name
3529 * @param signature the signature for the record data
3530 */
3531static void
3532process_zone_to_name_shorten_shorten (void *cls,
3533 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
3534 struct GNUNET_TIME_Absolute expire,
3535 const char *name,
3536 unsigned int rd_len,
3537 const struct GNUNET_NAMESTORE_RecordData *rd,
3538 const struct GNUNET_CRYPTO_EccSignature *signature)
3539{
3540 struct ResolverHandle *rh = cls;
3541 struct NameShortenHandle* nsh = rh->proc_cls;
3542 struct AuthorityChain *next_authority;
3543
3544 char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3545 char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3546 size_t answer_len;
3547
3548 rh->namestore_task = NULL;
3549 /* we found a match in our own root zone */
3550 if (rd_len != 0)
3551 {
3552 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3553 memset(result, 0, answer_len);
3554
3555 if (strlen(rh->name) > 0)
3556 {
3557 sprintf (result, "%s.%s.%s.%s",
3558 rh->name, name,
3559 nsh->shorten_zone_name,
3560 GNUNET_GNS_TLD);
3561 }
3562 else
3563 {
3564 sprintf (result, "%s.%s.%s", name,
3565 nsh->shorten_zone_name,
3566 GNUNET_GNS_TLD);
3567 }
3568
3569 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3570 "Found shorten result %s\n", result);
3571 if (strlen (nsh->result) > strlen (result))
3572 strcpy (nsh->result, result);
3573 }
3574 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3575 nsh->shorten_zone) == 0)
3576 {
3577 /**
3578 * This is our zone append .gads unless name is empty
3579 * (it shouldn't be, usually FIXME what happens if we
3580 * shorten to our zone to a "" record??)
3581 */
3582
3583 sprintf (result, "%s.%s.%s",
3584 rh->name,
3585 nsh->shorten_zone_name,
3586 GNUNET_GNS_TLD);
3587 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3588 "Our zone: Found %s as shorten result\n", result);
3589
3590 if (strlen (nsh->result) > strlen (result))
3591 strcpy (nsh->result, result);
3592 //nsh->proc(nsh->proc_cls, result);
3593 //GNUNET_free(nsh);
3594 //free_resolver_handle(rh);
3595 //return;
3596 }
3597
3598
3599 /**
3600 * No PSEU found.
3601 * continue with next authority if exists
3602 */
3603 if (NULL == rh->authority_chain_head->next)
3604 {
3605 finish_shorten (rh, nsh);
3606 return;
3607 }
3608 next_authority = rh->authority_chain_head;
3609
3610 if (0 == strcmp (rh->name, ""))
3611 strcpy (tmp_name, next_authority->name);
3612 else
3613 GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH,
3614 "%s.%s", rh->name, next_authority->name);
3615
3616 strcpy(rh->name, tmp_name);
3617 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3618 "No PSEU found for authority %s. Promoting back: %s\n",
3619 next_authority->name, rh->name);
3620
3621 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3622 rh->authority_chain_tail,
3623 next_authority);
3624
3625 GNUNET_free (next_authority);
3626
3627 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3628 &rh->authority_chain_tail->zone,
3629 &rh->authority_chain_head->zone,
3630 &process_zone_to_name_shorten_root,
3631 rh);
3632}
3633
3634
3635/**
3636 * Callback calles by namestore for a zone to name
3637 * result
3638 *
3639 * @param cls the closure
3640 * @param zone_key the zone we queried
3641 * @param expire the expiration time of the name
3642 * @param name the name found or NULL
3643 * @param rd_len number of records for the name
3644 * @param rd the record data (PKEY) for the name
3645 * @param signature the signature for the record data
3646 */
3647static void
3648process_zone_to_name_shorten_private (void *cls,
3649 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
3650 struct GNUNET_TIME_Absolute expire,
3651 const char *name,
3652 unsigned int rd_len,
3653 const struct GNUNET_NAMESTORE_RecordData *rd,
3654 const struct GNUNET_CRYPTO_EccSignature *signature)
3655{
3656 struct ResolverHandle *rh = cls;
3657 struct NameShortenHandle* nsh = rh->proc_cls;
3658 struct AuthorityChain *next_authority;
3659
3660 char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3661 char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3662 size_t answer_len;
3663
3664 rh->namestore_task = NULL;
3665 /* we found a match in our own root zone */
3666 if (rd_len != 0)
3667 {
3668 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3669 memset(result, 0, answer_len);
3670
3671 if (strlen(rh->name) > 0)
3672 {
3673 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
3674 }
3675 else
3676 {
3677 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
3678 }
3679
3680 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3681 "Found shorten result %s\n", result);
3682 if (strlen (nsh->result) > strlen (result))
3683 strcpy (nsh->result, result);
3684 }
3685 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3686 nsh->private_zone) == 0)
3687 {
3688 /**
3689 * This is our zone append .gads unless name is empty
3690 * (it shouldn't be, usually FIXME what happens if we
3691 * shorten to our zone to a "" record??)
3692 */
3693
3694 sprintf (result, "%s.%s.%s",
3695 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3696 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3697 "Our private zone: Found %s as shorten result %s\n", result);
3698 if (strlen (nsh->result) > strlen (result))
3699 strcpy (nsh->result, result);
3700 }
3701
3702 if (0 != strcmp (nsh->shorten_zone_name, ""))
3703 {
3704 /* backtrack authorities for names in priv zone */
3705 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3706 nsh->shorten_zone,
3707 &rh->authority_chain_head->zone,
3708 &process_zone_to_name_shorten_shorten,
3709 rh);
3710 }
3711 else
3712 {
3713 /**
3714 * No PSEU found.
3715 * continue with next authority if exists
3716 */
3717 if (NULL == rh->authority_chain_head->next)
3718 {
3719 finish_shorten (rh, nsh);
3720 return;
3721 }
3722 next_authority = rh->authority_chain_head;
3723
3724 if (0 == strcmp (rh->name, ""))
3725 strcpy (tmp_name, next_authority->name);
3726 else
3727 GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH,
3728 "%s.%s", rh->name, next_authority->name);
3729
3730 strcpy(rh->name, tmp_name);
3731 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3732 "No PSEU found for authority %s. Promoting back: %s\n",
3733 next_authority->name, rh->name);
3734
3735 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3736 rh->authority_chain_tail,
3737 next_authority);
3738
3739 GNUNET_free (next_authority);
3740
3741 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3742 &rh->authority_chain_tail->zone,
3743 &rh->authority_chain_head->zone,
3744 &process_zone_to_name_shorten_root,
3745 rh);
3746 }
3747}
3748
3749
3750/**
3751 * Callback calles by namestore for a zone to name
3752 * result
3753 *
3754 * @param cls the closure
3755 * @param zone_key the zone we queried
3756 * @param expire the expiration time of the name
3757 * @param name the name found or NULL
3758 * @param rd_len number of records for the name
3759 * @param rd the record data (PKEY) for the name
3760 * @param signature the signature for the record data
3761 */
3762static void
3763process_zone_to_name_shorten_root (void *cls,
3764 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
3765 struct GNUNET_TIME_Absolute expire,
3766 const char *name,
3767 unsigned int rd_len,
3768 const struct GNUNET_NAMESTORE_RecordData *rd,
3769 const struct GNUNET_CRYPTO_EccSignature *signature)
3770{
3771 struct ResolverHandle *rh = cls;
3772 struct NameShortenHandle* nsh = rh->proc_cls;
3773 struct AuthorityChain *next_authority;
3774 char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3775 char tmp_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3776 size_t answer_len;
3777
3778 rh->namestore_task = NULL;
3779 /* we found a match in our own root zone */
3780 if (rd_len != 0)
3781 {
3782 answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3;
3783 memset(result, 0, answer_len);
3784
3785 if (strlen(rh->name) > 0)
3786 {
3787 sprintf (result, "%s.%s.%s", rh->name, name, GNUNET_GNS_TLD);
3788 }
3789 else
3790 {
3791 sprintf (result, "%s.%s", name, GNUNET_GNS_TLD);
3792 }
3793
3794 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3795 "Found shorten result %s\n", result);
3796 if (strlen (nsh->result) > strlen (result))
3797 strcpy (nsh->result, result);
3798 }
3799 else if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3800 nsh->root_zone) == 0)
3801 {
3802 /**
3803 * This is our zone append .gads unless name is empty
3804 * (it shouldn't be, usually FIXME what happens if we
3805 * shorten to our zone to a "" record??)
3806 */
3807
3808 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
3809 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3810 "Our zone: Found %s as shorten result\n", result);
3811 if (strlen (nsh->result) > strlen (result))
3812 strcpy (nsh->result, result);
3813 }
3814
3815 if (NULL != nsh->private_zone)
3816 {
3817 /* backtrack authorities for names in priv zone */
3818 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3819 nsh->private_zone,
3820 &rh->authority_chain_head->zone,
3821 &process_zone_to_name_shorten_private,
3822 rh);
3823 }
3824 else if (NULL != nsh->shorten_zone)
3825 {
3826 /* backtrack authorities for names in shorten zone */
3827 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3828 nsh->shorten_zone,
3829 &rh->authority_chain_head->zone,
3830 &process_zone_to_name_shorten_shorten,
3831 rh);
3832 }
3833 else
3834 {
3835 /**
3836 * No PSEU found.
3837 * continue with next authority if exists
3838 */
3839 if (NULL == rh->authority_chain_head->next)
3840 {
3841 finish_shorten (rh, nsh);
3842 return;
3843 }
3844 next_authority = rh->authority_chain_head;
3845
3846 if (0 == strcmp (rh->name, ""))
3847 strcpy (tmp_name, next_authority->name);
3848 else
3849 GNUNET_snprintf(tmp_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH,
3850 "%s.%s", rh->name, next_authority->name);
3851
3852 strcpy(rh->name, tmp_name);
3853 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3854 "No PSEU found for authority %s. Promoting back: %s\n",
3855 next_authority->name, rh->name);
3856
3857 GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head,
3858 rh->authority_chain_tail,
3859 next_authority);
3860
3861 GNUNET_free (next_authority);
3862
3863 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3864 &rh->authority_chain_tail->zone,
3865 &rh->authority_chain_head->zone,
3866 &process_zone_to_name_shorten_root,
3867 rh);
3868 }
3869}
3870
3871
3872/**
3873 * Process result from namestore delegation lookup
3874 * for shorten operation
3875 *
3876 * @param cls the client shorten handle
3877 * @param rh the resolver handle
3878 * @param rd_count number of results (0)
3879 * @param rd data (NULL)
3880 */
3881static void
3882handle_delegation_ns_shorten (void* cls,
3883 struct ResolverHandle *rh,
3884 uint32_t rd_count,
3885 const struct GNUNET_NAMESTORE_RecordData *rd)
3886{
3887 struct NameShortenHandle *nsh;
3888 char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3889
3890 nsh = (struct NameShortenHandle *)cls;
3891 rh->namestore_task = NULL;
3892 /**
3893 * At this point rh->name contains the part of the name
3894 * that we do not have a PKEY in our namestore to resolve.
3895 * The authority chain in the resolver handle is now
3896 * useful to backtrack if needed
3897 */
3898
3899 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3900 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
3901 memset(result, 0, sizeof (result));
3902
3903 if (0 == GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3904 nsh->root_zone))
3905 {
3906 /**
3907 * This is our zone append .gads unless name is empty
3908 * (it shouldn't be, usually FIXME what happens if we
3909 * shorten to our zone to a "" record??)
3910 */
3911
3912 sprintf (result, "%s.%s", rh->name, GNUNET_GNS_TLD);
3913 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3914 "Our zone: Found %s as shorten result\n", result);
3915
3916 if (strlen (nsh->result) > strlen (result))
3917 strcpy (nsh->result, result);
3918
3919 }
3920 else if (NULL != nsh->private_zone)
3921 {
3922 /**
3923 * This is our zone append .gads unless name is empty
3924 * (it shouldn't be, usually FIXME what happens if we
3925 * shorten to our zone to a "" record??)
3926 */
3927 if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3928 nsh->private_zone) == 0)
3929 {
3930
3931 sprintf (result, "%s.%s.%s",
3932 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3933 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3934 "Our zone: Found %s as shorten result in private zone %s\n",
3935 result);
3936
3937 if (strlen (nsh->result) > strlen (result))
3938 strcpy (nsh->result, result);
3939 }
3940 }
3941 else if (NULL != nsh->shorten_zone)
3942 {
3943 /**
3944 * This is our zone append .gads unless name is empty
3945 * (it shouldn't be, usually FIXME what happens if we
3946 * shorten to our zone to a "" record??)
3947 */
3948 if (GNUNET_CRYPTO_short_hash_cmp(&rh->authority_chain_head->zone,
3949 nsh->shorten_zone) == 0)
3950 {
3951 sprintf (result, "%s.%s.%s",
3952 rh->name, nsh->private_zone_name, GNUNET_GNS_TLD);
3953 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
3954 "Our zone: Found %s as shorten result in shorten zone\n",
3955 result);
3956
3957 if (strlen (nsh->result) > strlen (result))
3958 strcpy (nsh->result, result);
3959 }
3960 }
3961
3962
3963 /* backtrack authorities for names */
3964 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
3965 nsh->root_zone,
3966 &rh->authority_chain_head->zone,
3967 &process_zone_to_name_shorten_root,
3968 rh);
3969
3970}
3971
3972
3973/**
3974 * Callback calles by namestore for a zone to name
3975 * result
3976 *
3977 * @param cls the closure
3978 * @param zone_key the zone we queried
3979 * @param expire the expiration time of the name
3980 * @param name the name found or NULL
3981 * @param rd_len number of records for the name
3982 * @param rd the record data (PKEY) for the name
3983 * @param signature the signature for the record data
3984 */
3985static void
3986process_zone_to_name_zkey (void *cls,
3987 const struct GNUNET_CRYPTO_EccPublicKey *zone_key,
3988 struct GNUNET_TIME_Absolute expire,
3989 const char *name,
3990 unsigned int rd_len,
3991 const struct GNUNET_NAMESTORE_RecordData *rd,
3992 const struct GNUNET_CRYPTO_EccSignature *signature)
3993{
3994 struct ResolverHandle *rh = cls;
3995 struct NameShortenHandle *nsh = rh->proc_cls;
3996 char new_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
3997
3998 rh->namestore_task = NULL;
3999
4000 /* zkey not in our zone */
4001 if (name == NULL)
4002 {
4003 /**
4004 * In this case we have not given this PKEY a name (yet)
4005 * It is either just not in our zone or not even cached
4006 * Since we do not know at this point we will not try to shorten
4007 * because PKEY import will happen if the user follows the zkey
4008 * link.
4009 */
4010 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4011 "No name found for zkey %s returning verbatim!\n", nsh->result);
4012 /*if (strcmp(rh->name, "") != 0)
4013 GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s.%s",
4014 rh->name, enc, GNUNET_GNS_TLD_ZKEY);
4015 else
4016 GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s",
4017 enc, GNUNET_GNS_TLD_ZKEY);
4018
4019 strcpy (nsh->result, new_name);*/
4020
4021 finish_shorten (rh, nsh);
4022 return;
4023 }
4024
4025 if (strcmp(rh->name, "") != 0)
4026 GNUNET_snprintf(new_name, GNUNET_DNSPARSER_MAX_NAME_LENGTH, "%s.%s",
4027 rh->name, name);
4028 else
4029 strcpy(new_name, name);
4030
4031 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4032 "Continue shorten for %s!\n", new_name);
4033
4034 strcpy(rh->name, new_name);
4035
4036 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
4037 rh->authority_chain_tail = rh->authority_chain_head;
4038 rh->authority_chain_head->zone = rh->authority;
4039
4040
4041 /* Start delegation resolution in our namestore */
4042 resolve_delegation_ns (rh);
4043}
4044
4045
4046/**
4047 * Shorten api from resolver
4048 *
4049 * @param zone the root zone to use
4050 * @param pzone the private zone to use
4051 * @param szone the shorten zone to use
4052 * @param name the name to shorten
4053 * @param private_zone_name name of the private zone
4054 * @param shorten_zone_name name of the shorten zone
4055 * @param proc the processor to call with result
4056 * @param proc_cls closure to pass to proc
4057 */
4058void
4059gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone,
4060 struct GNUNET_CRYPTO_ShortHashCode *pzone,
4061 struct GNUNET_CRYPTO_ShortHashCode *szone,
4062 const char* name,
4063 const char* private_zone_name,
4064 const char* shorten_zone_name,
4065 ShortenResultProcessor proc,
4066 void* proc_cls)
4067{
4068 struct ResolverHandle *rh;
4069 struct NameShortenHandle *nsh;
4070 char string_hash[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
4071 struct GNUNET_CRYPTO_ShortHashCode zkey;
4072 char nzkey[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
4073 char* nzkey_ptr = nzkey;
4074
4075 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4076 "Starting shorten for %s!\n", name);
4077
4078 if (is_canonical ((char*)name) == GNUNET_YES)
4079 {
4080 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4081 "%s is canonical. Returning verbatim\n", name);
4082 proc (proc_cls, name);
4083 return;
4084 }
4085
4086 nsh = GNUNET_malloc (sizeof (struct NameShortenHandle));
4087 nsh->proc = proc;
4088 nsh->proc_cls = proc_cls;
4089 nsh->root_zone = zone;
4090 nsh->private_zone = pzone;
4091 nsh->shorten_zone = szone;
4092 strcpy (nsh->private_zone_name, private_zone_name);
4093 strcpy (nsh->shorten_zone_name, shorten_zone_name);
4094 strcpy (nsh->result, name);
4095
4096 rh = GNUNET_malloc (sizeof (struct ResolverHandle));
4097 rh->authority = *zone;
4098 rh->id = rid_gen++;
4099 rh->proc = &handle_delegation_ns_shorten;
4100 rh->proc_cls = nsh;
4101 rh->private_local_zone = *zone;
4102
4103 GNUNET_CONTAINER_DLL_insert (nsh_head, nsh_tail, rh);
4104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4105 "Checking for TLD...\n");
4106 if (is_zkey_tld (name) == GNUNET_YES)
4107 {
4108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4109 "TLD is zkey\n");
4110 /**
4111 * This is a zkey tld
4112 * build hash and use as initial authority
4113 * FIXME sscanf
4114 */
4115 memset (rh->name, 0,
4116 strlen (name)-strlen (GNUNET_GNS_TLD_ZKEY));
4117 memcpy (rh->name, name,
4118 strlen(name)-strlen (GNUNET_GNS_TLD_ZKEY) - 1);
4119 pop_tld (rh->name, string_hash);
4120
4121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4122 "ZKEY is %s!\n", string_hash);
4123
4124 GNUNET_STRINGS_utf8_toupper (string_hash, &nzkey_ptr);
4125
4126 if (GNUNET_OK != GNUNET_CRYPTO_short_hash_from_string (nzkey,
4127 &zkey))
4128 {
4129 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4130 "Cannot convert ZKEY %s to hash!\n", nzkey);
4131 GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
4132 GNUNET_free (rh);
4133 GNUNET_free (nsh);
4134 proc (proc_cls, name);
4135 return;
4136 }
4137 rh->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle,
4138 zone, //ours
4139 &zkey,
4140 &process_zone_to_name_zkey,
4141 rh);
4142 return;
4143
4144 }
4145 else if (is_gads_tld (name) == GNUNET_YES)
4146 {
4147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4148 "TLD is gnunet\n");
4149 /**
4150 * Presumably GNUNET tld
4151 */
4152 memset (rh->name, 0,
4153 strlen (name)-strlen (GNUNET_GNS_TLD));
4154 memcpy (rh->name, name,
4155 strlen (name)-strlen (GNUNET_GNS_TLD) - 1);
4156 }
4157 else
4158 {
4159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown TLD in %s\n", name);
4160 GNUNET_CONTAINER_DLL_remove (nsh_head, nsh_tail, rh);
4161 GNUNET_free (rh);
4162 GNUNET_free (nsh);
4163 proc (proc_cls, name);
4164 return;
4165 }
4166
4167 rh->authority_chain_head = GNUNET_malloc (sizeof (struct AuthorityChain));
4168 rh->authority_chain_tail = rh->authority_chain_head;
4169 rh->authority_chain_head->zone = *zone;
4170
4171 /* Start delegation resolution in our namestore */
4172 resolve_delegation_ns (rh);
4173}
4174
4175/*********** END NAME SHORTEN ********************/
4176
4177/**
4178 * Conclude get authority lookup
4179 *
4180 * @param rh resolver handle
4181 * @param nah get authority lookup handle
4182 */
4183static void
4184finish_get_auth (struct ResolverHandle *rh,
4185 struct GetNameAuthorityHandle *nah)
4186{
4187 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4188 "Got authority result %s\n", nah->result);
4189
4190 nah->proc (nah->proc_cls, nah->result);
4191 GNUNET_CONTAINER_DLL_remove (nah_head, nah_tail, rh);
4192 GNUNET_free (nah);
4193 free_resolver_handle (rh);
4194}
4195
4196
4197/**
4198 * Process result from namestore delegation lookup
4199 * for get authority operation
4200 *
4201 * @param cls the client get auth handle
4202 * @param rh the resolver handle
4203 * @param rd_count number of results (0)
4204 * @param rd data (NULL)
4205 */
4206static void
4207handle_delegation_result_ns_get_auth(void* cls,
4208 struct ResolverHandle *rh,
4209 uint32_t rd_count,
4210 const struct GNUNET_NAMESTORE_RecordData *rd)
4211{
4212 struct GetNameAuthorityHandle* nah = rh->proc_cls;
4213 size_t answer_len;
4214
4215 /**
4216 * At this point rh->name contains the part of the name
4217 * that we do not have a PKEY in our namestore to resolve.
4218 * The authority chain in the resolver handle is now
4219 * useful to backtrack if needed
4220 */
4221
4222 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4223 "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
4224
4225 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4226 "Building response!\n");
4227 if (is_canonical (rh->name) == GNUNET_YES)
4228 {
4229 /**
4230 * We successfully resolved the authority in the ns
4231 * FIXME for our purposes this is fine
4232 * but maybe we want to have an api that also looks
4233 * into the dht (i.e. option in message)
4234 **/
4235 if (strlen(rh->name) > strlen(nah->name))
4236 {
4237 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4238 "Record name longer than original lookup name... odd!\n");
4239 //FIXME to sth here
4240 }
4241
4242 answer_len = strlen(nah->name) - strlen(rh->name)
4243 + strlen(GNUNET_GNS_TLD) + 1;
4244 memset(nah->result, 0, answer_len);
4245 if (0 != strcmp (rh->name, ""))
4246 strcpy(nah->result, nah->name + strlen(rh->name) + 1);
4247 else
4248 strcpy(nah->result, nah->name);
4249
4250 finish_get_auth (rh, nah);
4251 }
4252 else
4253 {
4254 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
4255 "Unable to resolve authority for remaining %s!\n", rh->name);
4256 strcpy(nah->result, "");
4257 finish_get_auth (rh, nah);
4258 }
4259}
4260
4261
4262/**
4263 * Tries to resolve the authority for name
4264 * in our namestore
4265 *
4266 * @param zone the root zone to look up for
4267 * @param pzone the private local zone
4268 * @param name the name to lookup up
4269 * @param proc the processor to call when finished
4270 * @param proc_cls the closure to pass to the processor
4271 */
4272void
4273gns_resolver_get_authority(struct GNUNET_CRYPTO_ShortHashCode zone,
4274 struct GNUNET_CRYPTO_ShortHashCode pzone,
4275 const char* name,
4276 GetAuthorityResultProcessor proc,
4277 void* proc_cls)
4278{
4279 struct ResolverHandle *rh;
4280 struct GetNameAuthorityHandle *nah;
4281
4282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4283 "Starting authority resolution for %s!\n", name);
4284
4285 nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle));
4286 rh = GNUNET_malloc(sizeof (struct ResolverHandle));
4287 rh->authority = zone;
4288 rh->id = rid_gen++;
4289 rh->private_local_zone = pzone;
4290
4291 GNUNET_CONTAINER_DLL_insert (nah_head, nah_tail, rh);
4292
4293 if (strcmp(GNUNET_GNS_TLD, name) == 0)
4294 {
4295 strcpy(rh->name, "\0");
4296 }
4297 else
4298 {
4299 memset(rh->name, 0,
4300 strlen(name)-strlen(GNUNET_GNS_TLD));
4301 memcpy(rh->name, name,
4302 strlen(name)-strlen(GNUNET_GNS_TLD) - 1);
4303 }
4304
4305 memset(nah->name, 0,
4306 strlen(name)+1);
4307 strcpy(nah->name, name);
4308
4309 rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
4310 rh->authority_chain_tail = rh->authority_chain_head;
4311 rh->authority_chain_head->zone = zone;
4312 rh->proc = &handle_delegation_result_ns_get_auth;
4313 rh->proc_cls = (void*)nah;
4314
4315 nah->proc = proc;
4316 nah->proc_cls = proc_cls;
4317 strcpy (nah->result, "");
4318
4319 /* Start delegation resolution in our namestore */
4320 resolve_delegation_ns(rh);
4321
4322}
4323
4324/******** END GET AUTHORITY *************/
4325 3606
4326/* end of gnunet-service-gns_resolver.c */ 3607/* end of gnunet-service-gns_resolver.c */
diff --git a/src/gns/gnunet-service-gns_resolver.h b/src/gns/gnunet-service-gns_resolver.h
index 1b10297c2..bc83b6b3d 100644
--- a/src/gns/gnunet-service-gns_resolver.h
+++ b/src/gns/gnunet-service-gns_resolver.h
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) 3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -24,514 +24,16 @@
24 */ 24 */
25#ifndef GNS_RESOLVER_H 25#ifndef GNS_RESOLVER_H
26#define GNS_RESOLVER_H 26#define GNS_RESOLVER_H
27
28#include "gns.h" 27#include "gns.h"
29#include "gnunet_dht_service.h" 28#include "gnunet_dht_service.h"
30 29
31#define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
32
33#define GNUNET_GNS_DEFAULT_LOOKUP_TIMEOUT \
34 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
35
36#define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT
37
38#define DHT_GNS_REPLICATION_LEVEL 5
39
40#define GNUNET_GNS_MAX_PARALLEL_LOOKUPS 500
41
42#define GNUNET_GNS_MAX_NS_TASKS 500
43
44/*
45 * DLL to hold the authority chain
46 * we had to pass in the resolution process
47 */
48struct AuthorityChain
49{
50 struct AuthorityChain *prev;
51
52 struct AuthorityChain *next;
53
54 /**
55 * the zone hash of the authority
56 */
57 struct GNUNET_CRYPTO_ShortHashCode zone;
58
59 /**
60 * (local) name of the authority
61 */
62 char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
63
64 /**
65 * was the ns entry fresh
66 */
67 int fresh;
68};
69
70
71/**
72 * handle to a resolution process
73 */
74struct ResolverHandle;
75
76 30
77/** 31/**
78 * processor for a record lookup result 32 * Initialize the resolver subsystem.
79 * 33 * MUST be called before #GNS_resolver_lookup.
80 * @param cls the closure
81 * @param rd_count number of results
82 * @param rd result data
83 */
84typedef void (*RecordLookupProcessor) (void *cls,
85 uint32_t rd_count,
86 const struct GNUNET_NAMESTORE_RecordData *rd);
87
88
89/**
90 * processor for a shorten result
91 *
92 * @param cls the closure
93 * @param name shortened name
94 */
95typedef void (*ShortenResultProcessor) (void *cls,
96 const char* name);
97
98
99/**
100 * processor for an authority result
101 *
102 * @param cls the closure
103 * @param name name of the authority
104 */
105typedef void (*GetAuthorityResultProcessor) (void *cls,
106 const char* name);
107
108/**
109 * processor for a resolution result
110 *
111 * @param cls the closure
112 * @param rh the resolution handle
113 * @param rd_count number of results
114 * @param rd result data (array of 'rd_count' records)
115 */
116typedef void (*ResolutionResultProcessor) (void *cls,
117 struct ResolverHandle *rh,
118 uint32_t rd_count,
119 const struct GNUNET_NAMESTORE_RecordData *rd);
120
121
122/**
123 * Resolution status indicator
124 */
125enum ResolutionStatus
126{
127 /**
128 * the name to lookup exists
129 */
130 RSL_RECORD_EXISTS = 1,
131
132 /**
133 * the name in the record expired
134 */
135 RSL_RECORD_EXPIRED = 2,
136
137 /**
138 * resolution timed out
139 */
140 RSL_TIMED_OUT = 4,
141
142 /**
143 * Found VPN delegation
144 */
145 RSL_DELEGATE_VPN = 8,
146
147 /**
148 * Found NS delegation
149 */
150 RSL_DELEGATE_NS = 16,
151
152 /**
153 * Found PKEY delegation
154 */
155 RSL_DELEGATE_PKEY = 32,
156
157 /**
158 * Found CNAME record
159 */
160 RSL_CNAME_FOUND = 64,
161
162 /**
163 * Found PKEY has been revoked
164 */
165 RSL_PKEY_REVOKED = 128
166};
167
168/**
169 * Handle to a currenty pending resolution
170 * a ResolverHandle is passed to, for example
171 * resolve_record_ns to resolve a record in the namestore.
172 * On result (positive or negative) the ResolutionResultProcessor
173 * is called.
174 * If a timeout is set timeout_cont will be called.
175 * If no timeout is set (ie timeout forever) then background resolutions
176 * might be triggered.
177 */
178struct ResolverHandle
179{
180
181 /**
182 * DLL
183 */
184 struct ResolverHandle *next;
185
186 /**
187 * DLL
188 */
189 struct ResolverHandle *prev;
190
191 /**
192 * Last record data found
193 */
194 struct GNUNET_NAMESTORE_RecordData rd;
195
196 /**
197 * Number of last record data found
198 */
199 unsigned int rd_count;
200
201 /**
202 * The name to resolve
203 */
204 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
205
206 /**
207 * has this query been answered? how many matches
208 */
209 int answered;
210
211 /**
212 * Use only cache
213 */
214 int only_cached;
215
216 /**
217 * the authoritative zone to query
218 */
219 struct GNUNET_CRYPTO_ShortHashCode authority;
220
221 /**
222 * the name of the authoritative zone to query
223 */
224 char authority_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
225
226 /**
227 * a handle for dht lookups. should be NULL if no lookups are in progress
228 */
229 struct GNUNET_DHT_GetHandle *get_handle;
230
231 /**
232 * timeout set for this lookup task
233 */
234 struct GNUNET_TIME_Relative timeout;
235
236 /**
237 * a handle to a vpn request
238 */
239 struct GNUNET_VPN_RedirectionRequest *vpn_handle;
240
241 /**
242 * a socket for a dns request
243 */
244 struct GNUNET_NETWORK_Handle *dns_sock;
245
246 /**
247 * a synthesized dns name
248 */
249 char dns_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
250
251 /**
252 * the authoritative dns zone
253 */
254 char dns_zone[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
255
256 /**
257 * the address of the DNS server FIXME not needed?
258 */
259 struct sockaddr_in dns_addr;
260
261 /**
262 * handle to the local stub resolver request
263 */
264 struct GNUNET_RESOLVER_RequestHandle *dns_resolver_handle;
265
266 /**
267 * select task for DNS
268 */
269 GNUNET_SCHEDULER_TaskIdentifier dns_read_task;
270
271 /**
272 * pointer to raw dns query payload FIXME needs to be freed/NULL
273 */
274 char *dns_raw_packet;
275
276 /**
277 * size of the raw dns query
278 */
279 size_t dns_raw_packet_size;
280
281 /**
282 * timeout task for the lookup
283 */
284 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
285
286 /**
287 * continuation to call on timeout
288 */
289 GNUNET_SCHEDULER_Task timeout_cont;
290
291 /**
292 * closure for timeout cont
293 */
294 void* timeout_cont_cls;
295
296 /**
297 * called when resolution phase finishes
298 */
299 ResolutionResultProcessor proc;
300
301 /**
302 * closure passed to proc
303 */
304 void* proc_cls;
305
306 /**
307 * DLL to store the authority chain
308 */
309 struct AuthorityChain *authority_chain_head;
310
311 /**
312 * DLL to store the authority chain
313 */
314 struct AuthorityChain *authority_chain_tail;
315
316 /**
317 * status of the resolution result
318 */
319 enum ResolutionStatus status;
320
321 /**
322 * The provate local zone of this request
323 */
324 struct GNUNET_CRYPTO_ShortHashCode private_local_zone;
325
326 /**
327 * private key of an/our authoritative zone
328 * can be NULL but automatical PKEY import will not work
329 */
330 struct GNUNET_CRYPTO_EccPrivateKey *priv_key;
331
332 /**
333 * the heap node associated with this lookup, null if timeout is set
334 * used for DHT background lookups.
335 */
336 struct GNUNET_CONTAINER_HeapNode *dht_heap_node;
337
338 /**
339 * Id for resolution process
340 */
341 unsigned long long id;
342
343 /**
344 * Pending Namestore task
345 */
346 struct GNUNET_NAMESTORE_QueueEntry *namestore_task;
347
348};
349
350
351/**
352 * Handle to a record lookup
353 */
354struct RecordLookupHandle
355{
356 /**
357 * the record type to look up
358 */
359 int record_type;
360
361 /**
362 * the name to look up
363 */
364 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
365
366 /**
367 * Method to call on record resolution result
368 */
369 RecordLookupProcessor proc;
370
371 /**
372 * closure to pass to proc
373 */
374 void* proc_cls;
375
376};
377
378
379/**
380 * Handle to a shorten context
381 */
382struct NameShortenHandle
383{
384 /**
385 * Method to call on shorten result
386 */
387 ShortenResultProcessor proc;
388
389 /**
390 * closure to pass to proc
391 */
392 void* proc_cls;
393
394 /**
395 * result of shorten
396 */
397 char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
398
399 /**
400 * root zone
401 */
402 struct GNUNET_CRYPTO_ShortHashCode *root_zone;
403
404 /**
405 * private zone
406 */
407 struct GNUNET_CRYPTO_ShortHashCode *private_zone;
408
409 /**
410 * name of private zone
411 */
412 char private_zone_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
413
414 /**
415 * shorten zone
416 */
417 struct GNUNET_CRYPTO_ShortHashCode *shorten_zone;
418
419 /**
420 * name of shorten zone
421 */
422 char shorten_zone_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
423
424};
425
426
427/**
428 * Handle to a get authority context
429 */
430struct GetNameAuthorityHandle
431{
432 /**
433 * the name to look up authority for
434 */
435 char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
436
437 /**
438 * the result
439 */
440 char result[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
441
442 /**
443 * Method to call on result
444 */
445 GetAuthorityResultProcessor proc;
446
447 /**
448 * closure to pass to proc
449 */
450 void* proc_cls;
451};
452
453
454/**
455 * Handle to a pseu lookup
456 */
457struct GetPseuAuthorityHandle
458{
459 /**
460 * DLL
461 */
462 struct GetPseuAuthorityHandle *next;
463
464 /**
465 * DLL
466 */
467 struct GetPseuAuthorityHandle *prev;
468
469 /**
470 * the name to store the zone under
471 */
472 char name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
473
474 /**
475 * test name to store the zone under
476 */
477 char test_name[GNUNET_DNSPARSER_MAX_LABEL_LENGTH];
478
479 /**
480 * the zone of our authority
481 */
482 struct GNUNET_CRYPTO_ShortHashCode our_zone;
483
484 /**
485 * the private key of the zone to store the pseu in
486 */
487 struct GNUNET_CRYPTO_EccPrivateKey *key;
488
489 /**
490 * a handle for dht lookups. should be NULL if no lookups are in progress
491 */
492 struct GNUNET_DHT_GetHandle *get_handle;
493
494 /**
495 * timeout task for lookup
496 */
497 GNUNET_SCHEDULER_TaskIdentifier timeout;
498
499 /**
500 * Authority to shorten
501 */
502 struct AuthorityChain *auth;
503
504 /**
505 * handle to namestore request
506 */
507 struct GNUNET_NAMESTORE_QueueEntry* namestore_task;
508};
509
510
511/**
512 * Namestore queue entries in background
513 */
514struct NamestoreBGTask
515{
516 /**
517 * node in heap
518 */
519 struct GNUNET_CONTAINER_HeapNode *node;
520
521 /**
522 * queue entry
523 */
524 struct GNUNET_NAMESTORE_QueueEntry *qe;
525};
526
527
528/**
529 * Initialize the resolver
530 * MUST be called before other gns_resolver_* methods
531 * 34 *
532 * @param nh handle to the namestore 35 * @param nh handle to the namestore
533 * @param dh handle to the dht 36 * @param dht handle to the dht
534 * @param lz the local zone
535 * @param c configuration handle 37 * @param c configuration handle
536 * @param max_bg_queries maximum amount of background queries 38 * @param max_bg_queries maximum amount of background queries
537 * @param ignore_pending ignore records that still require user confirmation 39 * @param ignore_pending ignore records that still require user confirmation
@@ -539,9 +41,8 @@ struct NamestoreBGTask
539 * @returns GNUNET_OK on success 41 * @returns GNUNET_OK on success
540 */ 42 */
541int 43int
542gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh, 44GNS_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
543 struct GNUNET_DHT_Handle *dh, 45 struct GNUNET_DHT_Handle *dht,
544 struct GNUNET_CRYPTO_ShortHashCode lz,
545 const struct GNUNET_CONFIGURATION_Handle *c, 46 const struct GNUNET_CONFIGURATION_Handle *c,
546 unsigned long long max_bg_queries, 47 unsigned long long max_bg_queries,
547 int ignore_pending); 48 int ignore_pending);
@@ -551,78 +52,59 @@ gns_resolver_init (struct GNUNET_NAMESTORE_Handle *nh,
551 * Cleanup resolver: Terminate pending lookups 52 * Cleanup resolver: Terminate pending lookups
552 */ 53 */
553void 54void
554gns_resolver_cleanup (void); 55GNS_resolver_done (void);
56
57
58/**
59 * Handle for an active request.
60 */
61struct GNS_ResolverHandle;
62
63
64/**
65 * Function called with results for a GNS resolution.
66 *
67 * @param cls closure
68 * @param rd_count number of records in @a rd
69 * @param rd records returned for the lookup
70 */
71typedef void (*GNS_ResultProcessor)(void *cls,
72 uint32_t rd_count,
73 const struct GNUNET_NAMESTORE_RecordData *rd);
555 74
556 75
557/** 76/**
558 * Lookup of a record in a specific zone 77 * Lookup of a record in a specific zone
559 * calls RecordLookupProcessor on result or timeout 78 * calls RecordLookupProcessor on result or timeout
560 * 79 *
561 * @param zone the root zone 80 * @param zone the zone to perform the lookup in
562 * @param pzone the private local zone
563 * @param record_type the record type to look up 81 * @param record_type the record type to look up
564 * @param name the name to look up 82 * @param name the name to look up
565 * @param key optional private key for authority caching 83 * @param shorten_key optional private key for authority caching, can be NULL
566 * @param timeout timeout for the resolution
567 * @param only_cached GNUNET_NO to only check locally not DHT for performance 84 * @param only_cached GNUNET_NO to only check locally not DHT for performance
568 * @param proc the processor to call 85 * @param proc the processor to call
569 * @param cls the closure to pass to proc 86 * @param proc_cls the closure to pass to @a proc
570 */ 87 */
571void 88struct GNS_ResolverHandle *
572gns_resolver_lookup_record (struct GNUNET_CRYPTO_ShortHashCode zone, 89GNS_resolver_lookup (const struct GNUNET_CRYPTO_EccPublicKey *zone,
573 struct GNUNET_CRYPTO_ShortHashCode pzone, 90 uint32_t record_type,
574 uint32_t record_type, 91 const char *name,
575 const char* name, 92 const struct GNUNET_CRYPTO_EccPrivateKey *shorten_key,
576 struct GNUNET_CRYPTO_EccPrivateKey *key, 93 int only_cached,
577 struct GNUNET_TIME_Relative timeout, 94 GNS_ResultProcessor proc,
578 int only_cached, 95 void *proc_cls);
579 RecordLookupProcessor proc,
580 void* cls);
581 96
582 97
583/** 98/**
584 * Shortens a name if possible. If the shortening fails 99 * Cancel active resolution (i.e. client disconnected).
585 * name will be returned as shortened string. Else
586 * a shorter version of the name will be returned.
587 * There is no guarantee that the shortened name will
588 * actually be canonical/short etc.
589 * 100 *
590 * @param zone the root zone to use 101 * @param h resolution to abort
591 * @param pzone the private zone to use
592 * @param szone the shorten zone to use
593 * @param name name to shorten
594 * @param private_zone_name name of the private zone
595 * @param shorten_zone_name name of the shorten zone
596 * @param proc the processor to call on shorten result
597 * @param proc_cls the closure to pass to proc
598 */ 102 */
599void 103void
600gns_resolver_shorten_name (struct GNUNET_CRYPTO_ShortHashCode *zone, 104GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *h);
601 struct GNUNET_CRYPTO_ShortHashCode *pzone, 105
602 struct GNUNET_CRYPTO_ShortHashCode *szone,
603 const char* name,
604 const char* private_zone_name,
605 const char* shorten_zone_name,
606 ShortenResultProcessor proc,
607 void* proc_cls);
608 106
609 107
610/**
611 * Tries to resolve the authority for name
612 * in our namestore
613 *
614 * @param zone the root zone to look up for
615 * @param pzone the private local zone
616 * @param name the name to lookup up
617 * @param proc the processor to call when finished
618 * @param proc_cls the closure to pass to the processor
619 */
620void
621gns_resolver_get_authority (struct GNUNET_CRYPTO_ShortHashCode zone,
622 struct GNUNET_CRYPTO_ShortHashCode pzone,
623 const char* name,
624 GetAuthorityResultProcessor proc,
625 void* proc_cls);
626 108
627 109
628/** 110/**
@@ -630,16 +112,16 @@ gns_resolver_get_authority (struct GNUNET_CRYPTO_ShortHashCode zone,
630 * 112 *
631 * @param name the name to check 113 * @param name the name to check
632 * @param tld the tld to check 114 * @param tld the tld to check
633 * @return GNUNET_YES or GNUNET_NO 115 * @return #GNUNET_YES or #GNUNET_NO
634 */ 116 */
635int 117int
636is_tld (const char* name, 118is_tld (const char *name,
637 const char* tld); 119 const char *tld);
638 120
639 121
640 122
641/** 123/**
642 * Checks for gads/zkey 124 * Checks for gnu/zkey
643 */ 125 */
644#define is_gads_tld(name) is_tld(name, GNUNET_GNS_TLD) 126#define is_gads_tld(name) is_tld(name, GNUNET_GNS_TLD)
645#define is_zkey_tld(name) is_tld(name, GNUNET_GNS_TLD_ZKEY) 127#define is_zkey_tld(name) is_tld(name, GNUNET_GNS_TLD_ZKEY)
diff --git a/src/include/gnunet_dht_service.h b/src/include/gnunet_dht_service.h
index 7fa100679..46ef5847b 100644
--- a/src/include/gnunet_dht_service.h
+++ b/src/include/gnunet_dht_service.h
@@ -130,12 +130,12 @@ struct GNUNET_DHT_PutHandle;
130 130
131/** 131/**
132 * Type of a PUT continuation. You must not call 132 * Type of a PUT continuation. You must not call
133 * "GNUNET_DHT_disconnect" in this continuation. 133 * #GNUNET_DHT_disconnect in this continuation.
134 * 134 *
135 * @param cls closure 135 * @param cls closure
136 * @param success GNUNET_OK if the PUT was transmitted, 136 * @param success #GNUNET_OK if the PUT was transmitted,
137 * GNUNET_NO on timeout, 137 * #GNUNET_NO on timeout,
138 * GNUNET_SYSERR on disconnect from service 138 * #GNUNET_SYSERR on disconnect from service
139 * after the PUT message was transmitted 139 * after the PUT message was transmitted
140 * (so we don't know if it was received or not) 140 * (so we don't know if it was received or not)
141 */ 141 */