aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-service-gns.c
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 /src/gns/gnunet-service-gns.c
parentadc6e4a5804d4cb43516383ff1d97065df0d0fd9 (diff)
downloadgnunet-5f5f1974b15c646bde44583aede2433254138661.tar.gz
gnunet-5f5f1974b15c646bde44583aede2433254138661.zip
-more coding towards working new GNS service
Diffstat (limited to 'src/gns/gnunet-service-gns.c')
-rw-r--r--src/gns/gnunet-service-gns.c494
1 files changed, 217 insertions, 277 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