diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2012-03-14 13:16:35 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2012-03-14 13:16:35 +0000 |
commit | 763feb7960b78a14971a6f36b73ceb92ff9b3ad4 (patch) | |
tree | 47ebecb1668b54bca366b4c0a5b7bfa34b419533 | |
parent | d09c4cbf182c5fb83c2bf4b1929a959db4438860 (diff) | |
download | gnunet-763feb7960b78a14971a6f36b73ceb92ff9b3ad4.tar.gz gnunet-763feb7960b78a14971a6f36b73ceb92ff9b3ad4.zip |
-large cleanup and bugfixes
-rw-r--r-- | src/gns/Makefile.am | 20 | ||||
-rw-r--r-- | src/gns/gns.h | 2 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns.c | 2180 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns_interceptor.c | 327 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns_interceptor.h | 18 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns_resolver.c | 1712 | ||||
-rw-r--r-- | src/gns/gnunet-service-gns_resolver.h | 226 | ||||
-rw-r--r-- | src/gns/test_gns_dht_shorten.c | 500 | ||||
-rw-r--r-- | src/gns/test_gns_simple_shorten.c | 19 |
9 files changed, 2331 insertions, 2673 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 866df1d88..679991fe1 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am | |||
@@ -28,7 +28,6 @@ bin_PROGRAMS = \ | |||
28 | 28 | ||
29 | check_PROGRAMS = \ | 29 | check_PROGRAMS = \ |
30 | test_gns_simple_shorten \ | 30 | test_gns_simple_shorten \ |
31 | test_gns_dht_shorten \ | ||
32 | test_gns_simple_get_authority \ | 31 | test_gns_simple_get_authority \ |
33 | test_gns_simple_lookup \ | 32 | test_gns_simple_lookup \ |
34 | test_gns_simple_delegated_lookup \ | 33 | test_gns_simple_delegated_lookup \ |
@@ -108,21 +107,6 @@ test_gns_simple_shorten_DEPENDENCIES = \ | |||
108 | $(top_builddir)/src/gns/libgnunetgns.la \ | 107 | $(top_builddir)/src/gns/libgnunetgns.la \ |
109 | $(top_builddir)/src/testing/libgnunettesting.la | 108 | $(top_builddir)/src/testing/libgnunettesting.la |
110 | 109 | ||
111 | test_gns_dht_shorten_SOURCES = \ | ||
112 | test_gns_dht_shorten.c | ||
113 | test_gns_dht_shorten_LDADD = \ | ||
114 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
115 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
116 | $(top_builddir)/src/gns/libgnunetgns.la \ | ||
117 | $(top_builddir)/src/dht/libgnunetdht.la \ | ||
118 | $(top_builddir)/src/testing/libgnunettesting.la | ||
119 | test_gns_dht_shorten_DEPENDENCIES = \ | ||
120 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
121 | $(top_builddir)/src/namestore/libgnunetnamestore.la \ | ||
122 | $(top_builddir)/src/gns/libgnunetgns.la \ | ||
123 | $(top_builddir)/src/dht/libgnunetdht.la \ | ||
124 | $(top_builddir)/src/testing/libgnunettesting.la | ||
125 | |||
126 | test_gns_simple_get_authority_SOURCES = \ | 110 | test_gns_simple_get_authority_SOURCES = \ |
127 | test_gns_simple_get_authority.c | 111 | test_gns_simple_get_authority.c |
128 | test_gns_simple_get_authority_LDADD = \ | 112 | test_gns_simple_get_authority_LDADD = \ |
@@ -148,7 +132,9 @@ gnunet_gns_DEPENDENCIES = \ | |||
148 | libgnunetgns.la | 132 | libgnunetgns.la |
149 | 133 | ||
150 | gnunet_service_gns_SOURCES = \ | 134 | gnunet_service_gns_SOURCES = \ |
151 | gnunet-service-gns.c | 135 | gnunet-service-gns.c \ |
136 | gnunet-service-gns_resolver.c \ | ||
137 | gnunet-service-gns_interceptor.c | ||
152 | gnunet_service_gns_LDADD = \ | 138 | gnunet_service_gns_LDADD = \ |
153 | $(top_builddir)/src/tun/libgnunettun.la \ | 139 | $(top_builddir)/src/tun/libgnunettun.la \ |
154 | $(top_builddir)/src/mesh/libgnunetmesh.la \ | 140 | $(top_builddir)/src/mesh/libgnunetmesh.la \ |
diff --git a/src/gns/gns.h b/src/gns/gns.h index aad36ebfe..31730f8ac 100644 --- a/src/gns/gns.h +++ b/src/gns/gns.h | |||
@@ -28,6 +28,8 @@ | |||
28 | #ifndef GNS_H | 28 | #ifndef GNS_H |
29 | #define GNS_H | 29 | #define GNS_H |
30 | 30 | ||
31 | #define GNUNET_GNS_TLD "gnunet" | ||
32 | |||
31 | GNUNET_NETWORK_STRUCT_BEGIN | 33 | GNUNET_NETWORK_STRUCT_BEGIN |
32 | 34 | ||
33 | /** | 35 | /** |
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c index ea9afcb4c..0d33fad81 100644 --- a/src/gns/gnunet-service-gns.c +++ b/src/gns/gnunet-service-gns.c | |||
@@ -38,11 +38,8 @@ | |||
38 | #include "gnunet_gns_service.h" | 38 | #include "gnunet_gns_service.h" |
39 | #include "block_gns.h" | 39 | #include "block_gns.h" |
40 | #include "gns.h" | 40 | #include "gns.h" |
41 | 41 | #include "gnunet-service-gns_resolver.h" | |
42 | #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) | 42 | #include "gnunet-service-gns_interceptor.h" |
43 | #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT | ||
44 | #define DHT_GNS_REPLICATION_LEVEL 5 | ||
45 | #define MAX_DNS_LABEL_LENGTH 63 | ||
46 | 43 | ||
47 | /* FIXME move to proper header in include */ | 44 | /* FIXME move to proper header in include */ |
48 | #define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23 | 45 | #define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23 |
@@ -53,113 +50,6 @@ | |||
53 | #define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28 | 50 | #define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28 |
54 | 51 | ||
55 | 52 | ||
56 | struct AuthorityChain | ||
57 | { | ||
58 | struct AuthorityChain *prev; | ||
59 | |||
60 | struct AuthorityChain *next; | ||
61 | |||
62 | GNUNET_HashCode zone; | ||
63 | |||
64 | /* (local) name of the authority */ | ||
65 | char* name; | ||
66 | |||
67 | /* was the ns entry fresh */ | ||
68 | int fresh; | ||
69 | }; | ||
70 | |||
71 | /* handle to a resolution process */ | ||
72 | struct GNUNET_GNS_ResolverHandle; | ||
73 | |||
74 | /** | ||
75 | * processor for a resultion result | ||
76 | * | ||
77 | * @param cls the closure | ||
78 | * @param rh the resolution handle | ||
79 | * @param rd_count number of results | ||
80 | * @pram rd resukt data | ||
81 | */ | ||
82 | typedef void (*ResolutionResultProcessor) (void *cls, | ||
83 | struct GNUNET_GNS_ResolverHandle *rh, | ||
84 | uint32_t rd_count, | ||
85 | const struct GNUNET_NAMESTORE_RecordData *rd); | ||
86 | |||
87 | /** | ||
88 | * Resoltion status indicator | ||
89 | * EXISTS: the name to lookup exists | ||
90 | * EXPIRED: the name in the record expired | ||
91 | */ | ||
92 | enum ResolutionStatus | ||
93 | { | ||
94 | EXISTS = 1, | ||
95 | EXPIRED = 2 | ||
96 | }; | ||
97 | |||
98 | /** | ||
99 | * Handle to a currenty pending resolution | ||
100 | */ | ||
101 | struct GNUNET_GNS_ResolverHandle | ||
102 | { | ||
103 | /* The name to resolve */ | ||
104 | char *name; | ||
105 | |||
106 | /* has this query been answered? how many matches */ | ||
107 | int answered; | ||
108 | |||
109 | /* the authoritative zone to query */ | ||
110 | GNUNET_HashCode authority; | ||
111 | |||
112 | /* the name of the authoritative zone to query */ | ||
113 | char *authority_name; | ||
114 | |||
115 | /** | ||
116 | * we have an authority in namestore that | ||
117 | * may be able to resolve | ||
118 | */ | ||
119 | int authority_found; | ||
120 | |||
121 | /* a handle for dht lookups. should be NULL if no lookups are in progress */ | ||
122 | struct GNUNET_DHT_GetHandle *get_handle; | ||
123 | |||
124 | /* timeout task for dht lookups */ | ||
125 | GNUNET_SCHEDULER_TaskIdentifier dht_timeout_task; | ||
126 | |||
127 | /* called when resolution phase finishes */ | ||
128 | ResolutionResultProcessor proc; | ||
129 | |||
130 | /* closure passed to proc */ | ||
131 | void* proc_cls; | ||
132 | |||
133 | /* DLL to store the authority chain */ | ||
134 | struct AuthorityChain *authority_chain_head; | ||
135 | |||
136 | /* DLL to store the authority chain */ | ||
137 | struct AuthorityChain *authority_chain_tail; | ||
138 | |||
139 | /* status of the resolution result */ | ||
140 | enum ResolutionStatus status; | ||
141 | |||
142 | }; | ||
143 | |||
144 | /** | ||
145 | * Handle to a record lookup | ||
146 | */ | ||
147 | struct RecordLookupHandle | ||
148 | { | ||
149 | /* the record type to look up */ | ||
150 | enum GNUNET_GNS_RecordType record_type; | ||
151 | |||
152 | /* the name to look up */ | ||
153 | char *name; | ||
154 | |||
155 | /* Method to call on record resolution result */ | ||
156 | ResolutionResultProcessor proc; | ||
157 | |||
158 | /* closure to pass to proc */ | ||
159 | void* proc_cls; | ||
160 | |||
161 | }; | ||
162 | |||
163 | /** | 53 | /** |
164 | * Handle to a shorten operation from api | 54 | * Handle to a shorten operation from api |
165 | */ | 55 | */ |
@@ -216,28 +106,6 @@ struct ClientLookupHandle | |||
216 | }; | 106 | }; |
217 | 107 | ||
218 | /** | 108 | /** |
219 | * Handle to a DNS intercepted | ||
220 | * reslution request | ||
221 | */ | ||
222 | struct InterceptLookupHandle | ||
223 | { | ||
224 | /* the request handle to reply to */ | ||
225 | struct GNUNET_DNS_RequestHandle *request_handle; | ||
226 | |||
227 | /* the dns parser packet received */ | ||
228 | struct GNUNET_DNSPARSER_Packet *packet; | ||
229 | |||
230 | /* the query parsed from the packet */ | ||
231 | struct GNUNET_DNSPARSER_Query *query; | ||
232 | }; | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Our handle to the DNS handler library | ||
237 | */ | ||
238 | struct GNUNET_DNS_Handle *dns_handle; | ||
239 | |||
240 | /** | ||
241 | * Our handle to the DHT | 109 | * Our handle to the DHT |
242 | */ | 110 | */ |
243 | struct GNUNET_DHT_Handle *dht_handle; | 111 | struct GNUNET_DHT_Handle *dht_handle; |
@@ -274,11 +142,6 @@ static struct GNUNET_SERVER_NotificationContext *nc; | |||
274 | GNUNET_HashCode zone_hash; | 142 | GNUNET_HashCode zone_hash; |
275 | 143 | ||
276 | /** | 144 | /** |
277 | * Our tld. Maybe get from config file | ||
278 | */ | ||
279 | const char* gnunet_tld = ".gnunet"; | ||
280 | |||
281 | /** | ||
282 | * Useful for zone update for DHT put | 145 | * Useful for zone update for DHT put |
283 | */ | 146 | */ |
284 | static int num_public_records = 3600; | 147 | static int num_public_records = 3600; |
@@ -290,150 +153,6 @@ static struct GNUNET_TIME_Relative dht_update_interval; | |||
290 | GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK; | 153 | GNUNET_SCHEDULER_TaskIdentifier zone_update_taskid = GNUNET_SCHEDULER_NO_TASK; |
291 | 154 | ||
292 | /** | 155 | /** |
293 | * Helper function to free resolver handle | ||
294 | * | ||
295 | * @rh the handle to free | ||
296 | */ | ||
297 | static void | ||
298 | free_resolver_handle(struct GNUNET_GNS_ResolverHandle* rh) | ||
299 | { | ||
300 | struct AuthorityChain *ac; | ||
301 | struct AuthorityChain *ac_next; | ||
302 | |||
303 | if (NULL == rh) | ||
304 | return; | ||
305 | |||
306 | GNUNET_free_non_null (rh->name); | ||
307 | GNUNET_free_non_null (rh->authority_name); | ||
308 | |||
309 | ac = rh->authority_chain_head; | ||
310 | |||
311 | while (NULL != ac) | ||
312 | { | ||
313 | ac_next = ac->next; | ||
314 | GNUNET_free_non_null (ac->name); | ||
315 | GNUNET_free(ac); | ||
316 | ac = ac_next; | ||
317 | } | ||
318 | GNUNET_free(rh); | ||
319 | } | ||
320 | |||
321 | |||
322 | /** | ||
323 | * Reply to dns request with the result from our lookup. | ||
324 | * | ||
325 | * @param cls the closure to the request (an InterceptLookupHandle) | ||
326 | * @param rh the request handle of the lookup | ||
327 | * @param rd_count the number of records to return | ||
328 | * @param rd the record data | ||
329 | */ | ||
330 | static void | ||
331 | reply_to_dns(void* cls, struct GNUNET_GNS_ResolverHandle *rh, uint32_t rd_count, | ||
332 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
333 | { | ||
334 | int i; | ||
335 | size_t len; | ||
336 | int ret; | ||
337 | char *buf; | ||
338 | struct InterceptLookupHandle* ilh = (struct InterceptLookupHandle*)cls; | ||
339 | struct GNUNET_DNSPARSER_Packet *packet = ilh->packet; | ||
340 | struct GNUNET_DNSPARSER_Record answer_records[rh->answered]; | ||
341 | struct GNUNET_DNSPARSER_Record additional_records[rd_count-(rh->answered)]; | ||
342 | packet->answers = answer_records; | ||
343 | packet->additional_records = additional_records; | ||
344 | |||
345 | /** | ||
346 | * Put records in the DNS packet and modify it | ||
347 | * to a response | ||
348 | */ | ||
349 | len = sizeof(struct GNUNET_DNSPARSER_Record*); | ||
350 | for (i=0; i < rd_count; i++) | ||
351 | { | ||
352 | |||
353 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
354 | "Adding type %d to DNS response\n", rd[i].record_type); | ||
355 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", rh->name); | ||
356 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "QName: %s\n", ilh->query->name); | ||
357 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count); | ||
358 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size); | ||
359 | |||
360 | if (rd[i].record_type == ilh->query->type) | ||
361 | { | ||
362 | answer_records[i].name = ilh->query->name; | ||
363 | answer_records[i].type = rd[i].record_type; | ||
364 | answer_records[i].data.raw.data_len = rd[i].data_size; | ||
365 | answer_records[i].data.raw.data = (char*)rd[i].data; | ||
366 | answer_records[i].expiration_time = rd[i].expiration; | ||
367 | answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn | ||
368 | } | ||
369 | else | ||
370 | { | ||
371 | additional_records[i].name = ilh->query->name; | ||
372 | additional_records[i].type = rd[i].record_type; | ||
373 | additional_records[i].data.raw.data_len = rd[i].data_size; | ||
374 | additional_records[i].data.raw.data = (char*)rd[i].data; | ||
375 | additional_records[i].expiration_time = rd[i].expiration; | ||
376 | additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn | ||
377 | } | ||
378 | } | ||
379 | |||
380 | packet->num_answers = rh->answered; | ||
381 | packet->num_additional_records = rd_count-(rh->answered); | ||
382 | |||
383 | if (0 == GNUNET_CRYPTO_hash_cmp(&rh->authority, &zone_hash)) | ||
384 | packet->flags.authoritative_answer = 1; | ||
385 | else | ||
386 | packet->flags.authoritative_answer = 0; | ||
387 | |||
388 | if (rd == NULL) | ||
389 | packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR; | ||
390 | else | ||
391 | packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR; | ||
392 | |||
393 | packet->flags.query_or_response = 1; | ||
394 | |||
395 | |||
396 | /** | ||
397 | * Reply to DNS | ||
398 | */ | ||
399 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
400 | "Building DNS response\n"); | ||
401 | ret = GNUNET_DNSPARSER_pack (packet, | ||
402 | 1024, /* FIXME magic from dns redirector */ | ||
403 | &buf, | ||
404 | &len); | ||
405 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
406 | "Built DNS response! (ret=%d,len=%d)\n", ret, len); | ||
407 | if (ret == GNUNET_OK) | ||
408 | { | ||
409 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
410 | "Answering DNS request\n"); | ||
411 | GNUNET_DNS_request_answer(ilh->request_handle, | ||
412 | len, | ||
413 | buf); | ||
414 | |||
415 | GNUNET_free(buf); | ||
416 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n"); | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
421 | "Error building DNS response! (ret=%d)", ret); | ||
422 | } | ||
423 | |||
424 | packet->num_answers = 0; | ||
425 | packet->answers = NULL; | ||
426 | packet->num_additional_records = 0; | ||
427 | packet->additional_records = NULL; | ||
428 | GNUNET_DNSPARSER_free_packet(packet); | ||
429 | //FIXME free more! | ||
430 | GNUNET_free((struct RecordLookupHandle*)rh->proc_cls); | ||
431 | free_resolver_handle(rh); | ||
432 | GNUNET_free(ilh); | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Task run during shutdown. | 156 | * Task run during shutdown. |
438 | * | 157 | * |
439 | * @param cls unused | 158 | * @param cls unused |
@@ -451,1115 +170,14 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
451 | 170 | ||
452 | GNUNET_SERVER_notification_context_destroy (nc); | 171 | GNUNET_SERVER_notification_context_destroy (nc); |
453 | 172 | ||
454 | if (dns_handle) | 173 | gns_interceptor_stop(); |
455 | GNUNET_DNS_disconnect(dns_handle); | 174 | |
456 | |||
457 | GNUNET_NAMESTORE_disconnect(namestore_handle, 1); | 175 | GNUNET_NAMESTORE_disconnect(namestore_handle, 1); |
458 | GNUNET_DHT_disconnect(dht_handle); | 176 | GNUNET_DHT_disconnect(dht_handle); |
459 | } | 177 | } |
460 | 178 | ||
461 | 179 | ||
462 | /** | 180 | /** |
463 | * Callback when record data is put into namestore | ||
464 | * | ||
465 | * @param cls the closure | ||
466 | * @param success GNUNET_OK on success | ||
467 | * @param emsg the error message. NULL if SUCCESS==GNUNET_OK | ||
468 | */ | ||
469 | void | ||
470 | on_namestore_record_put_result(void *cls, | ||
471 | int32_t success, | ||
472 | const char *emsg) | ||
473 | { | ||
474 | if (GNUNET_NO == success) | ||
475 | { | ||
476 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n"); | ||
477 | return; | ||
478 | } | ||
479 | else if (GNUNET_YES == success) | ||
480 | { | ||
481 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
482 | "records successfully put in namestore\n"); | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
487 | "Error putting records into namestore: %s\n", emsg); | ||
488 | } | ||
489 | |||
490 | |||
491 | /** | ||
492 | * Handle timeout for DHT requests | ||
493 | * | ||
494 | * @param cls the request handle as closure | ||
495 | * @param tc the task context | ||
496 | */ | ||
497 | static void | ||
498 | dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
499 | { | ||
500 | struct GNUNET_GNS_ResolverHandle *rh = cls; | ||
501 | |||
502 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
503 | "dht lookup for query %s timed out.\n", | ||
504 | rh->name); | ||
505 | |||
506 | GNUNET_DHT_get_stop (rh->get_handle); | ||
507 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
508 | } | ||
509 | |||
510 | |||
511 | /** | ||
512 | * Function called when we get a result from the dht | ||
513 | * for our record query | ||
514 | * | ||
515 | * @param cls the request handle | ||
516 | * @param exp lifetime | ||
517 | * @param key the key the record was stored under | ||
518 | * @param get_path get path | ||
519 | * @param get_path_length get path length | ||
520 | * @param put_path put path | ||
521 | * @param put_path_length put path length | ||
522 | * @param type the block type | ||
523 | * @param size the size of the record | ||
524 | * @param data the record data | ||
525 | */ | ||
526 | static void | ||
527 | process_record_dht_result(void* cls, | ||
528 | struct GNUNET_TIME_Absolute exp, | ||
529 | const GNUNET_HashCode * key, | ||
530 | const struct GNUNET_PeerIdentity *get_path, | ||
531 | unsigned int get_path_length, | ||
532 | const struct GNUNET_PeerIdentity *put_path, | ||
533 | unsigned int put_path_length, | ||
534 | enum GNUNET_BLOCK_Type type, | ||
535 | size_t size, const void *data) | ||
536 | { | ||
537 | struct GNUNET_GNS_ResolverHandle *rh; | ||
538 | struct RecordLookupHandle *rlh; | ||
539 | struct GNSNameRecordBlock *nrb; | ||
540 | uint32_t num_records; | ||
541 | char* name = NULL; | ||
542 | char* rd_data = (char*)data; | ||
543 | int i; | ||
544 | int rd_size; | ||
545 | |||
546 | GNUNET_HashCode zone, name_hash; | ||
547 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size); | ||
548 | |||
549 | if (data == NULL) | ||
550 | return; | ||
551 | |||
552 | //FIXME maybe check expiration here, check block type | ||
553 | |||
554 | rh = (struct GNUNET_GNS_ResolverHandle *)cls; | ||
555 | rlh = (struct RecordLookupHandle *) rh->proc_cls; | ||
556 | nrb = (struct GNSNameRecordBlock*)data; | ||
557 | |||
558 | /* stop lookup and timeout task */ | ||
559 | GNUNET_DHT_get_stop (rh->get_handle); | ||
560 | GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); | ||
561 | |||
562 | rh->get_handle = NULL; | ||
563 | name = (char*)&nrb[1]; | ||
564 | num_records = ntohl(nrb->rd_count); | ||
565 | { | ||
566 | struct GNUNET_NAMESTORE_RecordData rd[num_records]; | ||
567 | |||
568 | rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); | ||
569 | rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); | ||
570 | |||
571 | if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, | ||
572 | rd_data, | ||
573 | num_records, | ||
574 | rd)) | ||
575 | { | ||
576 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | for (i=0; i<num_records; i++) | ||
581 | { | ||
582 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
583 | "Got name: %s (wanted %s)\n", name, rh->name); | ||
584 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
585 | "Got type: %d\n", | ||
586 | rd[i].record_type); | ||
587 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
588 | "Got data length: %d\n", rd[i].data_size); | ||
589 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
590 | "Got flag %d\n", rd[i].flags); | ||
591 | |||
592 | if ((strcmp(name, rh->name) == 0) && | ||
593 | (rd[i].record_type == rlh->record_type)) | ||
594 | { | ||
595 | rh->answered++; | ||
596 | } | ||
597 | |||
598 | } | ||
599 | |||
600 | GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); | ||
601 | GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); | ||
602 | |||
603 | /** | ||
604 | * FIXME check pubkey against existing key in namestore? | ||
605 | * https://gnunet.org/bugs/view.php?id=2179 | ||
606 | */ | ||
607 | |||
608 | /* Save to namestore */ | ||
609 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
610 | &nrb->public_key, | ||
611 | name, | ||
612 | exp, | ||
613 | num_records, | ||
614 | rd, | ||
615 | &nrb->signature, | ||
616 | &on_namestore_record_put_result, //cont | ||
617 | NULL); //cls | ||
618 | |||
619 | if (rh->answered) | ||
620 | rh->proc(rh->proc_cls, rh, num_records, rd); | ||
621 | else | ||
622 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
623 | } | ||
624 | |||
625 | } | ||
626 | |||
627 | |||
628 | /** | ||
629 | * Start DHT lookup for a (name -> query->record_type) record in | ||
630 | * rh->authority's zone | ||
631 | * | ||
632 | * @param rh the pending gns query context | ||
633 | */ | ||
634 | static void | ||
635 | resolve_record_dht(struct GNUNET_GNS_ResolverHandle *rh) | ||
636 | { | ||
637 | uint32_t xquery; | ||
638 | GNUNET_HashCode name_hash; | ||
639 | GNUNET_HashCode lookup_key; | ||
640 | struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string; | ||
641 | struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; | ||
642 | |||
643 | GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash); | ||
644 | GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); | ||
645 | GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string); | ||
646 | |||
647 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
648 | "starting dht lookup for %s with key: %s\n", | ||
649 | rh->name, (char*)&lookup_key_string); | ||
650 | |||
651 | rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT, | ||
652 | &dht_lookup_timeout, rh); | ||
653 | |||
654 | xquery = htonl(rlh->record_type); | ||
655 | rh->get_handle = GNUNET_DHT_get_start(dht_handle, | ||
656 | DHT_OPERATION_TIMEOUT, | ||
657 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
658 | &lookup_key, | ||
659 | DHT_GNS_REPLICATION_LEVEL, | ||
660 | GNUNET_DHT_RO_NONE, | ||
661 | &xquery, | ||
662 | sizeof(xquery), | ||
663 | &process_record_dht_result, | ||
664 | rh); | ||
665 | |||
666 | } | ||
667 | |||
668 | |||
669 | /** | ||
670 | * Namestore calls this function if we have record for this name. | ||
671 | * (or with rd_count=0 to indicate no matches) | ||
672 | * | ||
673 | * @param cls the pending query | ||
674 | * @param key the key of the zone we did the lookup | ||
675 | * @param expiration expiration date of the namestore entry | ||
676 | * @param name the name for which we need an authority | ||
677 | * @param rd_count the number of records with 'name' | ||
678 | * @param rd the record data | ||
679 | * @param signature the signature of the authority for the record data | ||
680 | */ | ||
681 | static void | ||
682 | process_record_lookup_ns(void* cls, | ||
683 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, | ||
684 | struct GNUNET_TIME_Absolute expiration, | ||
685 | const char *name, unsigned int rd_count, | ||
686 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
687 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
688 | { | ||
689 | struct GNUNET_GNS_ResolverHandle *rh; | ||
690 | struct RecordLookupHandle *rlh; | ||
691 | struct GNUNET_TIME_Relative remaining_time; | ||
692 | GNUNET_HashCode zone; | ||
693 | |||
694 | rh = (struct GNUNET_GNS_ResolverHandle *) cls; | ||
695 | rlh = (struct RecordLookupHandle *)rh->proc_cls; | ||
696 | GNUNET_CRYPTO_hash(key, | ||
697 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
698 | &zone); | ||
699 | remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); | ||
700 | |||
701 | rh->status = 0; | ||
702 | |||
703 | if (name != NULL) | ||
704 | { | ||
705 | rh->status |= EXISTS; | ||
706 | } | ||
707 | |||
708 | if (remaining_time.rel_value == 0) | ||
709 | { | ||
710 | rh->status |= EXPIRED; | ||
711 | } | ||
712 | |||
713 | if (rd_count == 0) | ||
714 | { | ||
715 | /** | ||
716 | * Lookup terminated and no results | ||
717 | */ | ||
718 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
719 | "Namestore lookup for %s terminated without results\n", name); | ||
720 | |||
721 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
722 | "Record %s unknown in namestore\n", | ||
723 | rh->name); | ||
724 | /** | ||
725 | * Our zone and no result? Cannot resolve TT | ||
726 | */ | ||
727 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
728 | return; | ||
729 | |||
730 | } | ||
731 | else | ||
732 | { | ||
733 | |||
734 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
735 | "Processing additional result %s from namestore\n", name); | ||
736 | int i; | ||
737 | for (i=0; i<rd_count;i++) | ||
738 | { | ||
739 | |||
740 | if (rd[i].record_type != rlh->record_type) | ||
741 | continue; | ||
742 | |||
743 | if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value | ||
744 | == 0) | ||
745 | { | ||
746 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This record is expired. Skipping\n"); | ||
747 | continue; | ||
748 | } | ||
749 | |||
750 | rh->answered++; | ||
751 | |||
752 | } | ||
753 | |||
754 | /** | ||
755 | * no answers found | ||
756 | */ | ||
757 | if (rh->answered == 0) | ||
758 | { | ||
759 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
760 | "No answers found. This is odd!\n"); | ||
761 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
762 | return; | ||
763 | } | ||
764 | |||
765 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n", | ||
766 | rh->answered); | ||
767 | |||
768 | rh->proc(rh->proc_cls, rh, rd_count, rd); | ||
769 | } | ||
770 | } | ||
771 | |||
772 | |||
773 | /** | ||
774 | * The final phase of resolution. | ||
775 | * rh->name is a name that is canonical and we do not have a delegation. | ||
776 | * Query namestore for this record | ||
777 | * | ||
778 | * @param rh the pending lookup | ||
779 | */ | ||
780 | static void | ||
781 | resolve_record_ns(struct GNUNET_GNS_ResolverHandle *rh) | ||
782 | { | ||
783 | struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; | ||
784 | |||
785 | /** | ||
786 | * Try to resolve this record in our namestore. | ||
787 | * The name to resolve is now in rh->authority_name | ||
788 | * since we tried to resolve it to an authority | ||
789 | * and failed. | ||
790 | **/ | ||
791 | GNUNET_NAMESTORE_lookup_record(namestore_handle, | ||
792 | &rh->authority, | ||
793 | rh->name, | ||
794 | rlh->record_type, | ||
795 | &process_record_lookup_ns, | ||
796 | rh); | ||
797 | } | ||
798 | |||
799 | |||
800 | /** | ||
801 | * Handle timeout for DHT requests | ||
802 | * | ||
803 | * @param cls the request handle as closure | ||
804 | * @param tc the task context | ||
805 | */ | ||
806 | static void | ||
807 | dht_authority_lookup_timeout(void *cls, | ||
808 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
809 | { | ||
810 | struct GNUNET_GNS_ResolverHandle *rh = cls; | ||
811 | |||
812 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
813 | "dht lookup for query %s timed out.\n", | ||
814 | rh->name); | ||
815 | |||
816 | GNUNET_DHT_get_stop (rh->get_handle); | ||
817 | if (strcmp(rh->name, "") == 0) | ||
818 | { | ||
819 | /* | ||
820 | * promote authority back to name and try to resolve record | ||
821 | */ | ||
822 | strcpy(rh->name, rh->authority_name); | ||
823 | } | ||
824 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
825 | } | ||
826 | |||
827 | /* Prototype */ | ||
828 | static void resolve_delegation_dht(struct GNUNET_GNS_ResolverHandle *rh); | ||
829 | |||
830 | /** | ||
831 | * Function called when we get a result from the dht | ||
832 | * for our query. Recursively tries to resolve authorities | ||
833 | * for name in DHT. | ||
834 | * | ||
835 | * @param cls the request handle | ||
836 | * @param exp lifetime | ||
837 | * @param key the key the record was stored under | ||
838 | * @param get_path get path | ||
839 | * @param get_path_length get path length | ||
840 | * @param put_path put path | ||
841 | * @param put_path_length put path length | ||
842 | * @param type the block type | ||
843 | * @param size the size of the record | ||
844 | * @param data the record data | ||
845 | */ | ||
846 | static void | ||
847 | process_delegation_result_dht(void* cls, | ||
848 | struct GNUNET_TIME_Absolute exp, | ||
849 | const GNUNET_HashCode * key, | ||
850 | const struct GNUNET_PeerIdentity *get_path, | ||
851 | unsigned int get_path_length, | ||
852 | const struct GNUNET_PeerIdentity *put_path, | ||
853 | unsigned int put_path_length, | ||
854 | enum GNUNET_BLOCK_Type type, | ||
855 | size_t size, const void *data) | ||
856 | { | ||
857 | struct GNUNET_GNS_ResolverHandle *rh; | ||
858 | struct GNSNameRecordBlock *nrb; | ||
859 | uint32_t num_records; | ||
860 | char* name = NULL; | ||
861 | char* rd_data = (char*) data; | ||
862 | int i; | ||
863 | int rd_size; | ||
864 | GNUNET_HashCode zone, name_hash; | ||
865 | |||
866 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n"); | ||
867 | |||
868 | if (data == NULL) | ||
869 | return; | ||
870 | |||
871 | //FIXME check expiration? | ||
872 | |||
873 | rh = (struct GNUNET_GNS_ResolverHandle *)cls; | ||
874 | nrb = (struct GNSNameRecordBlock*)data; | ||
875 | |||
876 | /* stop dht lookup and timeout task */ | ||
877 | GNUNET_DHT_get_stop (rh->get_handle); | ||
878 | GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); | ||
879 | |||
880 | rh->get_handle = NULL; | ||
881 | num_records = ntohl(nrb->rd_count); | ||
882 | name = (char*)&nrb[1]; | ||
883 | { | ||
884 | struct GNUNET_NAMESTORE_RecordData rd[num_records]; | ||
885 | |||
886 | rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); | ||
887 | rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); | ||
888 | |||
889 | if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, | ||
890 | rd_data, | ||
891 | num_records, | ||
892 | rd)) | ||
893 | { | ||
894 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); | ||
895 | return; | ||
896 | } | ||
897 | |||
898 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
899 | "Got name: %s (wanted %s)\n", name, rh->authority_name); | ||
900 | for (i=0; i<num_records; i++) | ||
901 | { | ||
902 | |||
903 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
904 | "Got name: %s (wanted %s)\n", name, rh->authority_name); | ||
905 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
906 | "Got type: %d (wanted %d)\n", | ||
907 | rd[i].record_type, GNUNET_GNS_RECORD_PKEY); | ||
908 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
909 | "Got data length: %d\n", rd[i].data_size); | ||
910 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
911 | "Got flag %d\n", rd[i].flags); | ||
912 | |||
913 | if ((strcmp(name, rh->authority_name) == 0) && | ||
914 | (rd[i].record_type == GNUNET_GNS_RECORD_PKEY)) | ||
915 | { | ||
916 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n"); | ||
917 | rh->answered = 1; | ||
918 | memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); | ||
919 | struct AuthorityChain *auth = | ||
920 | GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
921 | auth->zone = rh->authority; | ||
922 | auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); | ||
923 | memset(auth->name, 0, strlen(rh->authority_name)+1); | ||
924 | strcpy(auth->name, rh->authority_name); | ||
925 | GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head, | ||
926 | rh->authority_chain_tail, | ||
927 | auth); | ||
928 | } | ||
929 | |||
930 | } | ||
931 | |||
932 | |||
933 | GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); | ||
934 | GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); | ||
935 | |||
936 | /* Save to namestore */ | ||
937 | if (0 != GNUNET_CRYPTO_hash_cmp(&zone_hash, &zone)) | ||
938 | { | ||
939 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
940 | &nrb->public_key, | ||
941 | name, | ||
942 | exp, | ||
943 | num_records, | ||
944 | rd, | ||
945 | &nrb->signature, | ||
946 | &on_namestore_record_put_result, //cont | ||
947 | NULL); //cls | ||
948 | } | ||
949 | } | ||
950 | |||
951 | if (rh->answered) | ||
952 | { | ||
953 | rh->answered = 0; | ||
954 | /** | ||
955 | * delegate | ||
956 | * FIXME in this case. should we ask namestore again? | ||
957 | */ | ||
958 | if (strcmp(rh->name, "") == 0) | ||
959 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
960 | else | ||
961 | resolve_delegation_dht(rh); | ||
962 | return; | ||
963 | } | ||
964 | |||
965 | /** | ||
966 | * should never get here unless false dht key/put | ||
967 | * block plugin should handle this | ||
968 | **/ | ||
969 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup error!\n"); | ||
970 | GNUNET_break(0); | ||
971 | } | ||
972 | |||
973 | |||
974 | /** | ||
975 | * Process DHT lookup result for record. | ||
976 | * | ||
977 | * @param cls the closure | ||
978 | * @param rh resolver handle | ||
979 | * @param rd_count number of results (always 0) | ||
980 | * @param rd record data (always NULL) | ||
981 | */ | ||
982 | static void | ||
983 | process_record_result_dht(void* cls, struct GNUNET_GNS_ResolverHandle *rh, | ||
984 | unsigned int rd_count, | ||
985 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
986 | { | ||
987 | struct RecordLookupHandle* rlh; | ||
988 | rlh = (struct RecordLookupHandle*)cls; | ||
989 | if (rd_count == 0) | ||
990 | { | ||
991 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
992 | "No records for %s found in DHT. Aborting\n", | ||
993 | rh->name); | ||
994 | /* give up, cannot resolve */ | ||
995 | rlh->proc(rlh->proc_cls, rh, 0, NULL); | ||
996 | return; | ||
997 | } | ||
998 | |||
999 | /* results found yay */ | ||
1000 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1001 | "Record resolved from namestore!"); | ||
1002 | rlh->proc(rlh->proc_cls, rh, rd_count, rd); | ||
1003 | |||
1004 | } | ||
1005 | |||
1006 | |||
1007 | /** | ||
1008 | * Process namestore lookup result for record. | ||
1009 | * | ||
1010 | * @param cls the closure | ||
1011 | * @param rh resolver handle | ||
1012 | * @param rd_count number of results (always 0) | ||
1013 | * @param rd record data (always NULL) | ||
1014 | */ | ||
1015 | static void | ||
1016 | process_record_result_ns(void* cls, struct GNUNET_GNS_ResolverHandle *rh, | ||
1017 | unsigned int rd_count, | ||
1018 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
1019 | { | ||
1020 | struct RecordLookupHandle* rlh; | ||
1021 | rlh = (struct RecordLookupHandle*) cls; | ||
1022 | if (rd_count == 0) | ||
1023 | { | ||
1024 | /* ns entry expired. try dht */ | ||
1025 | if (rh->status & (EXPIRED | !EXISTS)) | ||
1026 | { | ||
1027 | rh->proc = &process_record_result_dht; | ||
1028 | resolve_record_dht(rh); | ||
1029 | return; | ||
1030 | } | ||
1031 | /* give up, cannot resolve */ | ||
1032 | rlh->proc(rlh->proc_cls, rh, 0, NULL); | ||
1033 | return; | ||
1034 | } | ||
1035 | |||
1036 | /* results found yay */ | ||
1037 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1038 | "Record resolved from namestore!"); | ||
1039 | rlh->proc(rlh->proc_cls, rh, rd_count, rd); | ||
1040 | |||
1041 | } | ||
1042 | |||
1043 | |||
1044 | /** | ||
1045 | * Determine if this name is canonical. | ||
1046 | * i.e. | ||
1047 | * a.b.gnunet = not canonical | ||
1048 | * a = canonical | ||
1049 | * | ||
1050 | * @param name the name to test | ||
1051 | * @return 1 if canonical | ||
1052 | */ | ||
1053 | static int | ||
1054 | is_canonical(char* name) | ||
1055 | { | ||
1056 | uint32_t len = strlen(name); | ||
1057 | int i; | ||
1058 | |||
1059 | for (i=0; i<len; i++) | ||
1060 | { | ||
1061 | if (*(name+i) == '.') | ||
1062 | return 0; | ||
1063 | } | ||
1064 | return 1; | ||
1065 | } | ||
1066 | |||
1067 | /** | ||
1068 | * Move one level up in the domain hierarchy and return the | ||
1069 | * passed top level domain. | ||
1070 | * | ||
1071 | * @param name the domain | ||
1072 | * @param dest the destination where the tld will be put | ||
1073 | */ | ||
1074 | void | ||
1075 | pop_tld(char* name, char* dest) | ||
1076 | { | ||
1077 | uint32_t len; | ||
1078 | |||
1079 | if (is_canonical(name)) | ||
1080 | { | ||
1081 | strcpy(dest, name); | ||
1082 | strcpy(name, ""); | ||
1083 | return; | ||
1084 | } | ||
1085 | |||
1086 | for (len = strlen(name); len > 0; len--) | ||
1087 | { | ||
1088 | if (*(name+len) == '.') | ||
1089 | break; | ||
1090 | } | ||
1091 | |||
1092 | //Was canonical? | ||
1093 | if (len == 0) | ||
1094 | return; | ||
1095 | |||
1096 | name[len] = '\0'; | ||
1097 | |||
1098 | strcpy(dest, (name+len+1)); | ||
1099 | } | ||
1100 | |||
1101 | /** | ||
1102 | * DHT resolution for delegation finished. Processing result. | ||
1103 | * | ||
1104 | * @param cls the closure | ||
1105 | * @param rh resolver handle | ||
1106 | * @param rd_count number of results (always 0) | ||
1107 | * @param rd record data (always NULL) | ||
1108 | */ | ||
1109 | static void | ||
1110 | process_delegation_dht(void* cls, struct GNUNET_GNS_ResolverHandle *rh, | ||
1111 | unsigned int rd_count, | ||
1112 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
1113 | { | ||
1114 | struct RecordLookupHandle* rlh; | ||
1115 | rlh = (struct RecordLookupHandle*) cls; | ||
1116 | |||
1117 | if (strcmp(rh->name, "") == 0) | ||
1118 | { | ||
1119 | /* We resolved full name for delegation. resolving record */ | ||
1120 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1121 | "Resolved full name for delegation via DHT. resolving record '' in ns\n"); | ||
1122 | rh->proc = &process_record_result_ns; | ||
1123 | resolve_record_ns(rh); | ||
1124 | return; | ||
1125 | } | ||
1126 | |||
1127 | /** | ||
1128 | * we still have some left | ||
1129 | **/ | ||
1130 | if (is_canonical(rh->name)) | ||
1131 | { | ||
1132 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1133 | "Resolving canonical record %s in ns\n", rh->name); | ||
1134 | rh->proc = &process_record_result_ns; | ||
1135 | resolve_record_ns(rh); | ||
1136 | return; | ||
1137 | } | ||
1138 | /* give up, cannot resolve */ | ||
1139 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1140 | "Cannot fully resolve delegation for %s via DHT!\n", | ||
1141 | rh->name); | ||
1142 | rlh->proc(rlh->proc_cls, rh, 0, NULL); | ||
1143 | } | ||
1144 | |||
1145 | |||
1146 | /** | ||
1147 | * Start DHT lookup for a name -> PKEY (compare NS) record in | ||
1148 | * rh->authority's zone | ||
1149 | * | ||
1150 | * @param rh the pending gns query | ||
1151 | * @param name the name of the PKEY record | ||
1152 | */ | ||
1153 | static void | ||
1154 | resolve_delegation_dht(struct GNUNET_GNS_ResolverHandle *rh) | ||
1155 | { | ||
1156 | uint32_t xquery; | ||
1157 | GNUNET_HashCode name_hash; | ||
1158 | GNUNET_HashCode lookup_key; | ||
1159 | |||
1160 | GNUNET_CRYPTO_hash(rh->authority_name, | ||
1161 | strlen(rh->authority_name), | ||
1162 | &name_hash); | ||
1163 | GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); | ||
1164 | |||
1165 | rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, | ||
1166 | &dht_authority_lookup_timeout, | ||
1167 | rh); | ||
1168 | |||
1169 | xquery = htonl(GNUNET_GNS_RECORD_PKEY); | ||
1170 | |||
1171 | rh->get_handle = GNUNET_DHT_get_start(dht_handle, | ||
1172 | DHT_OPERATION_TIMEOUT, | ||
1173 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
1174 | &lookup_key, | ||
1175 | DHT_GNS_REPLICATION_LEVEL, | ||
1176 | GNUNET_DHT_RO_NONE, | ||
1177 | &xquery, | ||
1178 | sizeof(xquery), | ||
1179 | &process_delegation_result_dht, | ||
1180 | rh); | ||
1181 | |||
1182 | } | ||
1183 | |||
1184 | |||
1185 | /** | ||
1186 | * Namestore resolution for delegation finished. Processing result. | ||
1187 | * | ||
1188 | * @param cls the closure | ||
1189 | * @param rh resolver handle | ||
1190 | * @param rd_count number of results (always 0) | ||
1191 | * @param rd record data (always NULL) | ||
1192 | */ | ||
1193 | static void | ||
1194 | process_delegation_ns(void* cls, struct GNUNET_GNS_ResolverHandle *rh, | ||
1195 | unsigned int rd_count, | ||
1196 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
1197 | { | ||
1198 | struct RecordLookupHandle* rlh; | ||
1199 | rlh = (struct RecordLookupHandle*) cls; | ||
1200 | |||
1201 | if (strcmp(rh->name, "") == 0) | ||
1202 | { | ||
1203 | /* We resolved full name for delegation. resolving record */ | ||
1204 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1205 | "Resolved full name for delegation. resolving record ''\n"); | ||
1206 | rh->proc = &process_record_result_ns; | ||
1207 | resolve_record_ns(rh); | ||
1208 | return; | ||
1209 | } | ||
1210 | |||
1211 | /** | ||
1212 | * we still have some left | ||
1213 | * check if ns entry is fresh | ||
1214 | **/ | ||
1215 | if (rh->status & (EXISTS | !EXPIRED)) | ||
1216 | { | ||
1217 | if (is_canonical(rh->name)) | ||
1218 | { | ||
1219 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1220 | "Resolving canonical record %s\n", rh->name); | ||
1221 | rh->proc = &process_record_result_ns; | ||
1222 | resolve_record_ns(rh); | ||
1223 | } | ||
1224 | else | ||
1225 | { | ||
1226 | /* give up, cannot resolve */ | ||
1227 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1228 | "Cannot fully resolve delegation for %s!\n", | ||
1229 | rh->name); | ||
1230 | rlh->proc(rlh->proc_cls, rh, 0, NULL); | ||
1231 | } | ||
1232 | return; | ||
1233 | } | ||
1234 | |||
1235 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1236 | "Trying to resolve delegation for %s via DHT\n", | ||
1237 | rh->name); | ||
1238 | rh->proc = &process_delegation_dht; | ||
1239 | resolve_delegation_dht(rh); | ||
1240 | } | ||
1241 | |||
1242 | //Prototype | ||
1243 | static void resolve_delegation_ns(struct GNUNET_GNS_ResolverHandle *rh); | ||
1244 | |||
1245 | /** | ||
1246 | * This is a callback function that should give us only PKEY | ||
1247 | * records. Used to query the namestore for the authority (PKEY) | ||
1248 | * for 'name'. It will recursively try to resolve the | ||
1249 | * authority for a given name from the namestore. | ||
1250 | * | ||
1251 | * @param cls the pending query | ||
1252 | * @param key the key of the zone we did the lookup | ||
1253 | * @param expiration expiration date of the record data set in the namestore | ||
1254 | * @param name the name for which we need an authority | ||
1255 | * @param rd_count the number of records with 'name' | ||
1256 | * @param rd the record data | ||
1257 | * @param signature the signature of the authority for the record data | ||
1258 | */ | ||
1259 | static void | ||
1260 | process_delegation_result_ns(void* cls, | ||
1261 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, | ||
1262 | struct GNUNET_TIME_Absolute expiration, | ||
1263 | const char *name, | ||
1264 | unsigned int rd_count, | ||
1265 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
1266 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
1267 | { | ||
1268 | struct GNUNET_GNS_ResolverHandle *rh; | ||
1269 | struct GNUNET_TIME_Relative remaining_time; | ||
1270 | GNUNET_HashCode zone; | ||
1271 | char* new_name; | ||
1272 | |||
1273 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n", | ||
1274 | rd_count); | ||
1275 | |||
1276 | rh = (struct GNUNET_GNS_ResolverHandle *)cls; | ||
1277 | GNUNET_CRYPTO_hash(key, | ||
1278 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
1279 | &zone); | ||
1280 | remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); | ||
1281 | |||
1282 | rh->status = 0; | ||
1283 | |||
1284 | if (name != NULL) | ||
1285 | { | ||
1286 | rh->status |= EXISTS; | ||
1287 | } | ||
1288 | |||
1289 | if (remaining_time.rel_value == 0) | ||
1290 | { | ||
1291 | rh->status |= EXPIRED; | ||
1292 | } | ||
1293 | |||
1294 | /** | ||
1295 | * No authority found in namestore. | ||
1296 | */ | ||
1297 | if (rd_count == 0) | ||
1298 | { | ||
1299 | /** | ||
1300 | * We did not find an authority in the namestore | ||
1301 | */ | ||
1302 | |||
1303 | /** | ||
1304 | * No PKEY in zone. | ||
1305 | * Promote this authority back to a name maybe it is | ||
1306 | * our record. | ||
1307 | */ | ||
1308 | if (strcmp(rh->name, "") == 0) | ||
1309 | { | ||
1310 | /* simply promote back */ | ||
1311 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1312 | "Promoting %s back to name\n", rh->authority_name); | ||
1313 | strcpy(rh->name, rh->authority_name); | ||
1314 | } | ||
1315 | else | ||
1316 | { | ||
1317 | /* add back to existing name */ | ||
1318 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1319 | "Adding %s back to %s\n", | ||
1320 | rh->authority_name, rh->name); | ||
1321 | new_name = GNUNET_malloc(strlen(rh->name) | ||
1322 | + strlen(rh->authority_name) + 2); | ||
1323 | memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2); | ||
1324 | strcpy(new_name, rh->name); | ||
1325 | strcpy(new_name+strlen(new_name)+1, "."); | ||
1326 | strcpy(new_name+strlen(new_name)+2, rh->authority_name); | ||
1327 | GNUNET_free(rh->name); | ||
1328 | rh->name = new_name; | ||
1329 | } | ||
1330 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1331 | return; | ||
1332 | } | ||
1333 | |||
1334 | //Note only 1 pkey should have been returned.. anything else would be strange | ||
1335 | /** | ||
1336 | * We found an authority that may be able to help us | ||
1337 | * move on with query | ||
1338 | */ | ||
1339 | int i; | ||
1340 | for (i=0; i<rd_count;i++) | ||
1341 | { | ||
1342 | |||
1343 | if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY) | ||
1344 | continue; | ||
1345 | |||
1346 | if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value | ||
1347 | == 0) | ||
1348 | { | ||
1349 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n"); | ||
1350 | if (remaining_time.rel_value == 0) | ||
1351 | { | ||
1352 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1353 | "This dht entry is expired.\n"); | ||
1354 | rh->authority_chain_head->fresh = 0; | ||
1355 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1356 | return; | ||
1357 | } | ||
1358 | |||
1359 | continue; | ||
1360 | } | ||
1361 | |||
1362 | /** | ||
1363 | * Resolve rest of query with new authority | ||
1364 | */ | ||
1365 | GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY); | ||
1366 | memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); | ||
1367 | struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
1368 | auth->zone = rh->authority; | ||
1369 | auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); | ||
1370 | memset(auth->name, 0, strlen(rh->authority_name)+1); | ||
1371 | strcpy(auth->name, rh->authority_name); | ||
1372 | GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head, | ||
1373 | rh->authority_chain_tail, | ||
1374 | auth); | ||
1375 | |||
1376 | /** | ||
1377 | * We are done with PKEY resolution if name is empty | ||
1378 | * else resolve again with new authority | ||
1379 | */ | ||
1380 | if (strcmp(rh->name, "") == 0) | ||
1381 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1382 | else | ||
1383 | resolve_delegation_ns(rh); | ||
1384 | return; | ||
1385 | } | ||
1386 | |||
1387 | /** | ||
1388 | * no answers found | ||
1389 | */ | ||
1390 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1391 | "Authority lookup successful but no PKEY... never get here\n"); | ||
1392 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1393 | } | ||
1394 | |||
1395 | |||
1396 | /** | ||
1397 | * Resolve the delegation chain for the request in our namestore | ||
1398 | * | ||
1399 | * @param rh the resolver handle | ||
1400 | */ | ||
1401 | static void | ||
1402 | resolve_delegation_ns(struct GNUNET_GNS_ResolverHandle *rh) | ||
1403 | { | ||
1404 | |||
1405 | pop_tld(rh->name, rh->authority_name); | ||
1406 | GNUNET_NAMESTORE_lookup_record(namestore_handle, | ||
1407 | &rh->authority, | ||
1408 | rh->authority_name, | ||
1409 | GNUNET_GNS_RECORD_PKEY, | ||
1410 | &process_delegation_result_ns, | ||
1411 | rh); | ||
1412 | |||
1413 | } | ||
1414 | |||
1415 | /** | ||
1416 | * Entry point for name resolution | ||
1417 | * Setup a new query and try to resolve | ||
1418 | * | ||
1419 | * @param request the request handle of the DNS request from a client | ||
1420 | * @param p the DNS query packet we received | ||
1421 | * @param q the DNS query we received parsed from p | ||
1422 | */ | ||
1423 | static void | ||
1424 | start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, | ||
1425 | struct GNUNET_DNSPARSER_Packet *p, | ||
1426 | struct GNUNET_DNSPARSER_Query *q) | ||
1427 | { | ||
1428 | struct GNUNET_GNS_ResolverHandle *rh; | ||
1429 | struct RecordLookupHandle* rlh; | ||
1430 | struct InterceptLookupHandle* ilh; | ||
1431 | |||
1432 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1433 | "Starting resolution for %s (type=%d)!\n", | ||
1434 | q->name, q->type); | ||
1435 | |||
1436 | rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); | ||
1437 | rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle)); | ||
1438 | ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle)); | ||
1439 | ilh->packet = p; | ||
1440 | ilh->query = q; | ||
1441 | ilh->request_handle = request; | ||
1442 | |||
1443 | rh->authority = zone_hash; | ||
1444 | |||
1445 | rlh->record_type = q->type; | ||
1446 | rlh->name = q->name; | ||
1447 | rlh->proc = &reply_to_dns; | ||
1448 | rlh->proc_cls = ilh; | ||
1449 | |||
1450 | rh->proc_cls = rlh; | ||
1451 | |||
1452 | rh->name = GNUNET_malloc(strlen(q->name) | ||
1453 | - strlen(gnunet_tld) + 1); | ||
1454 | memset(rh->name, 0, | ||
1455 | strlen(q->name)-strlen(gnunet_tld) + 1); | ||
1456 | memcpy(rh->name, q->name, | ||
1457 | strlen(q->name)-strlen(gnunet_tld)); | ||
1458 | |||
1459 | rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); | ||
1460 | |||
1461 | rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
1462 | rh->authority_chain_head->prev = NULL; | ||
1463 | rh->authority_chain_head->next = NULL; | ||
1464 | rh->authority_chain_tail = rh->authority_chain_head; | ||
1465 | rh->authority_chain_head->zone = zone_hash; | ||
1466 | |||
1467 | /* Start resolution in our zone */ | ||
1468 | rh->proc = &process_delegation_ns; | ||
1469 | resolve_delegation_ns(rh); | ||
1470 | } | ||
1471 | |||
1472 | |||
1473 | |||
1474 | /** | ||
1475 | * The DNS request handler | ||
1476 | * Called for every incoming DNS request. | ||
1477 | * | ||
1478 | * @param cls closure | ||
1479 | * @param rh request handle to user for reply | ||
1480 | * @param request_length number of bytes in request | ||
1481 | * @param request udp payload of the DNS request | ||
1482 | */ | ||
1483 | static void | ||
1484 | handle_dns_request(void *cls, | ||
1485 | struct GNUNET_DNS_RequestHandle *rh, | ||
1486 | size_t request_length, | ||
1487 | const char *request) | ||
1488 | { | ||
1489 | struct GNUNET_DNSPARSER_Packet *p; | ||
1490 | int i; | ||
1491 | char *tldoffset; | ||
1492 | |||
1493 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n"); | ||
1494 | p = GNUNET_DNSPARSER_parse (request, request_length); | ||
1495 | |||
1496 | if (NULL == p) | ||
1497 | { | ||
1498 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1499 | "Received malformed DNS packet, leaving it untouched\n"); | ||
1500 | GNUNET_DNS_request_forward (rh); | ||
1501 | GNUNET_DNSPARSER_free_packet (p); | ||
1502 | return; | ||
1503 | } | ||
1504 | |||
1505 | /** | ||
1506 | * Check tld and decide if we or | ||
1507 | * legacy dns is responsible | ||
1508 | * | ||
1509 | * FIXME now in theory there could be more than 1 query in the request | ||
1510 | * but if this is case we get into trouble: | ||
1511 | * either we query the GNS or the DNS. We cannot do both! | ||
1512 | * So I suggest to either only allow a single query per request or | ||
1513 | * only allow GNS or DNS requests. | ||
1514 | * The way it is implemented here now is buggy and will lead to erratic | ||
1515 | * behaviour (if multiple queries are present). | ||
1516 | */ | ||
1517 | if (p->num_queries == 0) | ||
1518 | { | ||
1519 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1520 | "No Queries in DNS packet... forwarding\n"); | ||
1521 | GNUNET_DNS_request_forward (rh); | ||
1522 | GNUNET_DNSPARSER_free_packet(p); | ||
1523 | return; | ||
1524 | } | ||
1525 | |||
1526 | if (p->num_queries > 1) | ||
1527 | { | ||
1528 | /* Note: We could also look for .gnunet */ | ||
1529 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1530 | ">1 queriy in DNS packet... odd. We only process #1\n"); | ||
1531 | } | ||
1532 | |||
1533 | |||
1534 | /** | ||
1535 | * Check for .gnunet | ||
1536 | */ | ||
1537 | tldoffset = p->queries[0].name + strlen(p->queries[0].name) - 1; | ||
1538 | |||
1539 | for (i=0; i<strlen(p->queries[0].name); i++) | ||
1540 | { | ||
1541 | if (*(tldoffset-i) == '.') | ||
1542 | break; | ||
1543 | } | ||
1544 | |||
1545 | if ((i==strlen(gnunet_tld)-1) && (0 == strcmp(tldoffset-i, gnunet_tld))) | ||
1546 | { | ||
1547 | start_resolution_for_dns(rh, p, p->queries); | ||
1548 | } | ||
1549 | else | ||
1550 | { | ||
1551 | /** | ||
1552 | * This request does not concern us. Forward to real DNS. | ||
1553 | */ | ||
1554 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1555 | "Request for %s is forwarded to DNS\n", p->queries[0].name); | ||
1556 | GNUNET_DNS_request_forward (rh); | ||
1557 | GNUNET_DNSPARSER_free_packet (p); | ||
1558 | } | ||
1559 | |||
1560 | } | ||
1561 | |||
1562 | /** | ||
1563 | * Method called periodicattluy that triggers | 181 | * Method called periodicattluy that triggers |
1564 | * iteration over root zone | 182 | * iteration over root zone |
1565 | * | 183 | * |
@@ -1727,577 +345,8 @@ update_zone_dht_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1727 | NULL); | 345 | NULL); |
1728 | } | 346 | } |
1729 | 347 | ||
1730 | //Prototype | ||
1731 | static void send_shorten_response(const char* name, | ||
1732 | struct ClientShortenHandle *csh); | ||
1733 | static void | ||
1734 | process_shorten_pseu_lookup_ns(void *cls, | ||
1735 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, | ||
1736 | struct GNUNET_TIME_Absolute expire, | ||
1737 | const char *name, | ||
1738 | unsigned int rd_len, | ||
1739 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
1740 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
1741 | { | ||
1742 | struct GNUNET_GNS_ResolverHandle *rh = | ||
1743 | (struct GNUNET_GNS_ResolverHandle *)cls; | ||
1744 | struct GNUNET_TIME_Relative remaining_time; | ||
1745 | |||
1746 | GNUNET_TIME_absolute_get_remaining (expire); | ||
1747 | rh->status = 0; | ||
1748 | |||
1749 | if (name != NULL) | ||
1750 | { | ||
1751 | rh->status |= EXISTS; | ||
1752 | } | ||
1753 | |||
1754 | if (remaining_time.rel_value == 0) | ||
1755 | { | ||
1756 | rh->status |= EXPIRED; | ||
1757 | } | ||
1758 | |||
1759 | rh->proc(rh->proc_cls, rh, rd_len, rd); | ||
1760 | } | ||
1761 | |||
1762 | |||
1763 | /** | ||
1764 | * Function called when we get a result from the dht | ||
1765 | * for our record query | ||
1766 | * | ||
1767 | * @param cls the request handle | ||
1768 | * @param exp lifetime | ||
1769 | * @param key the key the record was stored under | ||
1770 | * @param get_path get path | ||
1771 | * @param get_path_length get path length | ||
1772 | * @param put_path put path | ||
1773 | * @param put_path_length put path length | ||
1774 | * @param type the block type | ||
1775 | * @param size the size of the record | ||
1776 | * @param data the record data | ||
1777 | */ | ||
1778 | static void | ||
1779 | process_pseu_dht_result(void* cls, | ||
1780 | struct GNUNET_TIME_Absolute exp, | ||
1781 | const GNUNET_HashCode * key, | ||
1782 | const struct GNUNET_PeerIdentity *get_path, | ||
1783 | unsigned int get_path_length, | ||
1784 | const struct GNUNET_PeerIdentity *put_path, | ||
1785 | unsigned int put_path_length, | ||
1786 | enum GNUNET_BLOCK_Type type, | ||
1787 | size_t size, const void *data) | ||
1788 | { | ||
1789 | struct GNUNET_GNS_ResolverHandle *rh; | ||
1790 | struct RecordLookupHandle *rlh; | ||
1791 | struct GNSNameRecordBlock *nrb; | ||
1792 | uint32_t num_records; | ||
1793 | char* name = NULL; | ||
1794 | char* rd_data = (char*)data; | ||
1795 | int i; | ||
1796 | int rd_size; | ||
1797 | |||
1798 | GNUNET_HashCode zone, name_hash; | ||
1799 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got PSEU dht result (size=%d)\n", size); | ||
1800 | |||
1801 | if (data == NULL) | ||
1802 | return; | ||
1803 | |||
1804 | //FIXME maybe check expiration here, check block type | ||
1805 | |||
1806 | rh = (struct GNUNET_GNS_ResolverHandle *)cls; | ||
1807 | rlh = (struct RecordLookupHandle *) rh->proc_cls; | ||
1808 | nrb = (struct GNSNameRecordBlock*)data; | ||
1809 | |||
1810 | /* stop lookup and timeout task */ | ||
1811 | GNUNET_DHT_get_stop (rh->get_handle); | ||
1812 | GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); | ||
1813 | |||
1814 | rh->get_handle = NULL; | ||
1815 | name = (char*)&nrb[1]; | ||
1816 | num_records = ntohl(nrb->rd_count); | ||
1817 | { | ||
1818 | struct GNUNET_NAMESTORE_RecordData rd[num_records]; | ||
1819 | |||
1820 | rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); | ||
1821 | rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); | ||
1822 | |||
1823 | if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, | ||
1824 | rd_data, | ||
1825 | num_records, | ||
1826 | rd)) | ||
1827 | { | ||
1828 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); | ||
1829 | return; | ||
1830 | } | ||
1831 | |||
1832 | for (i=0; i<num_records; i++) | ||
1833 | { | ||
1834 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1835 | "Got name: %s (wanted %s)\n", name, rh->name); | ||
1836 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1837 | "Got type: %d\n", | ||
1838 | rd[i].record_type); | ||
1839 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1840 | "Got data length: %d\n", rd[i].data_size); | ||
1841 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1842 | "Got flag %d\n", rd[i].flags); | ||
1843 | |||
1844 | if ((strcmp(name, "+") == 0) && | ||
1845 | (rd[i].record_type == GNUNET_GNS_RECORD_PSEU)) | ||
1846 | { | ||
1847 | rh->answered++; | ||
1848 | } | ||
1849 | |||
1850 | } | ||
1851 | |||
1852 | GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); | ||
1853 | GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); | ||
1854 | |||
1855 | /** | ||
1856 | * FIXME check pubkey against existing key in namestore? | ||
1857 | * https://gnunet.org/bugs/view.php?id=2179 | ||
1858 | */ | ||
1859 | |||
1860 | /* Save to namestore */ | ||
1861 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
1862 | &nrb->public_key, | ||
1863 | name, | ||
1864 | exp, | ||
1865 | num_records, | ||
1866 | rd, | ||
1867 | &nrb->signature, | ||
1868 | &on_namestore_record_put_result, //cont | ||
1869 | NULL); //cls | ||
1870 | |||
1871 | if (rh->answered) | ||
1872 | rh->proc(rh->proc_cls, rh, num_records, rd); | ||
1873 | else | ||
1874 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1875 | } | ||
1876 | |||
1877 | } | ||
1878 | 348 | ||
1879 | 349 | /* END DHT ZONE PROPAGATION */ | |
1880 | /** | ||
1881 | * Start DHT lookup for a PSEUdonym record in | ||
1882 | * rh->authority's zone | ||
1883 | * | ||
1884 | * @param rh the pending gns query | ||
1885 | */ | ||
1886 | static void | ||
1887 | resolve_pseu_dht(struct GNUNET_GNS_ResolverHandle *rh) | ||
1888 | { | ||
1889 | uint32_t xquery; | ||
1890 | GNUNET_HashCode name_hash; | ||
1891 | GNUNET_HashCode lookup_key; | ||
1892 | |||
1893 | GNUNET_CRYPTO_hash("+", | ||
1894 | strlen("+"), | ||
1895 | &name_hash); | ||
1896 | |||
1897 | GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); | ||
1898 | |||
1899 | rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, | ||
1900 | &dht_lookup_timeout, | ||
1901 | rh); | ||
1902 | |||
1903 | xquery = htonl(GNUNET_GNS_RECORD_PSEU); | ||
1904 | |||
1905 | rh->get_handle = GNUNET_DHT_get_start(dht_handle, | ||
1906 | DHT_OPERATION_TIMEOUT, | ||
1907 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
1908 | &lookup_key, | ||
1909 | DHT_GNS_REPLICATION_LEVEL, | ||
1910 | GNUNET_DHT_RO_NONE, | ||
1911 | &xquery, | ||
1912 | sizeof(xquery), | ||
1913 | &process_pseu_dht_result, | ||
1914 | rh); | ||
1915 | |||
1916 | } | ||
1917 | |||
1918 | //Prototype | ||
1919 | static void | ||
1920 | handle_shorten_pseu_ns_result(void* cls, | ||
1921 | struct GNUNET_GNS_ResolverHandle *rh, | ||
1922 | uint32_t rd_count, | ||
1923 | const struct GNUNET_NAMESTORE_RecordData *rd); | ||
1924 | |||
1925 | static void | ||
1926 | handle_shorten_zone_to_name(void *cls, | ||
1927 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, | ||
1928 | struct GNUNET_TIME_Absolute expire, | ||
1929 | const char *name, | ||
1930 | unsigned int rd_len, | ||
1931 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
1932 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
1933 | { | ||
1934 | struct GNUNET_GNS_ResolverHandle *rh = | ||
1935 | (struct GNUNET_GNS_ResolverHandle *)cls; | ||
1936 | struct ClientShortenHandle* csh = (struct ClientShortenHandle*) rh->proc_cls; | ||
1937 | |||
1938 | char* result; | ||
1939 | size_t answer_len; | ||
1940 | |||
1941 | /* we found a match in our own zone */ | ||
1942 | if (rd_len != 0) | ||
1943 | { | ||
1944 | answer_len = strlen(rh->name) + strlen(name) + strlen(gnunet_tld) + 2; | ||
1945 | result = GNUNET_malloc(answer_len); | ||
1946 | memset(result, 0, answer_len); | ||
1947 | strcpy(result, rh->name); | ||
1948 | strcpy(result+strlen(rh->name), "."); | ||
1949 | strcpy(result+strlen(rh->name)+1, name); | ||
1950 | strcpy(result+strlen(rh->name)+strlen(name), gnunet_tld); | ||
1951 | |||
1952 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1953 | "Sending shorten result %s\n", result); | ||
1954 | |||
1955 | send_shorten_response(result, csh); | ||
1956 | free_resolver_handle(rh); | ||
1957 | GNUNET_free(result); | ||
1958 | } | ||
1959 | else | ||
1960 | { | ||
1961 | /** | ||
1962 | * Nothing in our zone | ||
1963 | * check PSEU for this authority in namestore | ||
1964 | */ | ||
1965 | rh->proc = &handle_shorten_pseu_ns_result; | ||
1966 | GNUNET_NAMESTORE_lookup_record(namestore_handle, | ||
1967 | &rh->authority_chain_head->zone, | ||
1968 | "+", | ||
1969 | GNUNET_GNS_RECORD_PSEU, | ||
1970 | &process_shorten_pseu_lookup_ns, | ||
1971 | rh); | ||
1972 | } | ||
1973 | } | ||
1974 | |||
1975 | /** | ||
1976 | * Process result from namestore delegation lookup | ||
1977 | * for shorten operation | ||
1978 | * | ||
1979 | * @param cls the client shorten handle | ||
1980 | * @param rh the resolver handle | ||
1981 | * @param rd_count number of results (0) | ||
1982 | * @param rd data (NULL) | ||
1983 | */ | ||
1984 | void | ||
1985 | handle_shorten_pseu_dht_result(void* cls, | ||
1986 | struct GNUNET_GNS_ResolverHandle *rh, | ||
1987 | uint32_t rd_len, | ||
1988 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
1989 | { | ||
1990 | struct ClientShortenHandle* csh = (struct ClientShortenHandle*) cls; | ||
1991 | struct AuthorityChain *auth_chain; | ||
1992 | char* pseu; | ||
1993 | char* result; | ||
1994 | char* new_name; | ||
1995 | size_t answer_len; | ||
1996 | int i; | ||
1997 | |||
1998 | /** | ||
1999 | * PSEU found | ||
2000 | */ | ||
2001 | if (rd_len != 0) | ||
2002 | { | ||
2003 | for (i=0; i < rd_len; i++) | ||
2004 | { | ||
2005 | if (rd[i].record_type == GNUNET_GNS_RECORD_PSEU) | ||
2006 | { | ||
2007 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2008 | "Found PSEU %s\n", (char*) rd[i].data); | ||
2009 | break; | ||
2010 | } | ||
2011 | } | ||
2012 | |||
2013 | pseu = (char*) rd[i].data; | ||
2014 | answer_len = strlen(rh->name) + strlen(pseu) + strlen(gnunet_tld) + 2; | ||
2015 | result = GNUNET_malloc(answer_len); | ||
2016 | memset(result, 0, answer_len); | ||
2017 | strcpy(result, rh->name); | ||
2018 | strcpy(result+strlen(rh->name), "."); | ||
2019 | strcpy(result+strlen(rh->name)+1, pseu); | ||
2020 | strcpy(result+strlen(rh->name)+strlen(pseu)+1, gnunet_tld); | ||
2021 | |||
2022 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2023 | "Sending pseudonym shorten result %s\n", result); | ||
2024 | |||
2025 | send_shorten_response(result, csh); | ||
2026 | free_resolver_handle(rh); | ||
2027 | GNUNET_free(result); | ||
2028 | return; | ||
2029 | } | ||
2030 | |||
2031 | /** | ||
2032 | * No PSEU found. | ||
2033 | * continue with next authority | ||
2034 | * backtrack | ||
2035 | */ | ||
2036 | auth_chain = rh->authority_chain_head; | ||
2037 | |||
2038 | if ((auth_chain->next->next == NULL) && | ||
2039 | GNUNET_CRYPTO_hash_cmp(&auth_chain->next->zone, &zone_hash) == 0) | ||
2040 | { | ||
2041 | /** | ||
2042 | * Our zone is next | ||
2043 | */ | ||
2044 | answer_len = strlen(rh->name) + strlen(auth_chain->name) | ||
2045 | + strlen(gnunet_tld) + 2; | ||
2046 | |||
2047 | result = GNUNET_malloc(answer_len); | ||
2048 | memset(result, 0, answer_len); | ||
2049 | strcpy(result, rh->name); | ||
2050 | strcpy(result+strlen(rh->name), "."); | ||
2051 | strcpy(result+strlen(rh->name)+1, auth_chain->name); | ||
2052 | strcpy(result+strlen(rh->name)+strlen(auth_chain->name)+1, gnunet_tld); | ||
2053 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2054 | "Sending non pseudonym shorten result %s\n", result); | ||
2055 | |||
2056 | send_shorten_response(result, csh); | ||
2057 | free_resolver_handle(rh); | ||
2058 | GNUNET_free(result); | ||
2059 | return; | ||
2060 | } | ||
2061 | |||
2062 | /** | ||
2063 | * Continue with next authority | ||
2064 | */ | ||
2065 | new_name = GNUNET_malloc(strlen(rh->name)+ | ||
2066 | strlen(auth_chain->name) + 2); | ||
2067 | memset(new_name, 0, strlen(rh->name)+ | ||
2068 | strlen(auth_chain->name) + 2); | ||
2069 | strcpy(new_name, rh->name); | ||
2070 | strcpy(new_name+strlen(rh->name)+1, "."); | ||
2071 | strcpy(new_name+strlen(rh->name)+2, auth_chain->name); | ||
2072 | GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, | ||
2073 | rh->authority_chain_tail, | ||
2074 | auth_chain); | ||
2075 | GNUNET_free(rh->name); | ||
2076 | rh->name = new_name; | ||
2077 | GNUNET_free(auth_chain->name); | ||
2078 | GNUNET_free(auth_chain); | ||
2079 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, | ||
2080 | &zone_hash, | ||
2081 | &rh->authority_chain_head->zone, | ||
2082 | &handle_shorten_zone_to_name, | ||
2083 | rh); | ||
2084 | |||
2085 | } | ||
2086 | |||
2087 | |||
2088 | |||
2089 | /** | ||
2090 | * Process result from namestore PSEU lookup | ||
2091 | * for shorten operation | ||
2092 | * FIXME do we need to check for own zone here? | ||
2093 | * | ||
2094 | * @param cls the client shorten handle | ||
2095 | * @param rh the resolver handle | ||
2096 | * @param rd_count number of results (0 if none found) | ||
2097 | * @param rd data (NULL if none found) | ||
2098 | */ | ||
2099 | static void | ||
2100 | handle_shorten_pseu_ns_result(void* cls, | ||
2101 | struct GNUNET_GNS_ResolverHandle *rh, | ||
2102 | uint32_t rd_len, | ||
2103 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
2104 | { | ||
2105 | struct ClientShortenHandle* csh = (struct ClientShortenHandle*) cls; | ||
2106 | struct AuthorityChain *auth_chain; | ||
2107 | char* pseu; | ||
2108 | char* result; | ||
2109 | char* new_name; | ||
2110 | size_t answer_len; | ||
2111 | int i; | ||
2112 | |||
2113 | /** | ||
2114 | * PSEU found | ||
2115 | */ | ||
2116 | if (rd_len != 0) | ||
2117 | { | ||
2118 | for (i=0; i < rd_len; i++) | ||
2119 | { | ||
2120 | if (rd[i].record_type == GNUNET_GNS_RECORD_PSEU) | ||
2121 | { | ||
2122 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2123 | "Found PSEU %s\n", (char*) rd[i].data); | ||
2124 | break; | ||
2125 | } | ||
2126 | } | ||
2127 | |||
2128 | pseu = (char*) rd[i].data; | ||
2129 | answer_len = strlen(rh->name) + strlen(pseu) + strlen(gnunet_tld) + 2; | ||
2130 | result = GNUNET_malloc(answer_len); | ||
2131 | memset(result, 0, answer_len); | ||
2132 | strcpy(result, rh->name); | ||
2133 | strcpy(result+strlen(rh->name), "."); | ||
2134 | strcpy(result+strlen(rh->name)+1, pseu); | ||
2135 | strcpy(result+strlen(rh->name)+strlen(pseu)+1, gnunet_tld); | ||
2136 | |||
2137 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2138 | "Sending shorten result %s\n", result); | ||
2139 | |||
2140 | send_shorten_response(result, csh); | ||
2141 | free_resolver_handle(rh); | ||
2142 | GNUNET_free(result); | ||
2143 | return; | ||
2144 | } | ||
2145 | |||
2146 | /** | ||
2147 | * No PSEU found. Ask DHT if expired. | ||
2148 | * Else contunue with next authority | ||
2149 | */ | ||
2150 | if (rh->status & (EXISTS | !EXPIRED)) | ||
2151 | { | ||
2152 | /** | ||
2153 | * backtrack | ||
2154 | */ | ||
2155 | auth_chain = rh->authority_chain_head; | ||
2156 | new_name = GNUNET_malloc(strlen(rh->name)+ | ||
2157 | strlen(auth_chain->name) + 2); | ||
2158 | memset(new_name, 0, strlen(rh->name)+ | ||
2159 | strlen(auth_chain->name) + 2); | ||
2160 | strcpy(new_name, rh->name); | ||
2161 | strcpy(new_name+strlen(rh->name)+1, "."); | ||
2162 | strcpy(new_name+strlen(rh->name)+2, auth_chain->name); | ||
2163 | |||
2164 | GNUNET_free(rh->name); | ||
2165 | rh->name = new_name; | ||
2166 | GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, | ||
2167 | rh->authority_chain_tail, | ||
2168 | auth_chain); | ||
2169 | |||
2170 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, | ||
2171 | &zone_hash, | ||
2172 | &rh->authority_chain_head->zone, | ||
2173 | &handle_shorten_zone_to_name, | ||
2174 | rh); | ||
2175 | return; | ||
2176 | } | ||
2177 | |||
2178 | /** | ||
2179 | * Ask DHT | ||
2180 | */ | ||
2181 | rh->authority = rh->authority_chain_head->zone; | ||
2182 | rh->proc = &handle_shorten_pseu_dht_result; | ||
2183 | resolve_pseu_dht(rh); | ||
2184 | |||
2185 | } | ||
2186 | |||
2187 | |||
2188 | |||
2189 | /** | ||
2190 | * Process result from namestore delegation lookup | ||
2191 | * for shorten operation | ||
2192 | * | ||
2193 | * @param cls the client shorten handle | ||
2194 | * @param rh the resolver handle | ||
2195 | * @param rd_count number of results (0) | ||
2196 | * @param rd data (NULL) | ||
2197 | */ | ||
2198 | void | ||
2199 | handle_shorten_delegation_result(void* cls, | ||
2200 | struct GNUNET_GNS_ResolverHandle *rh, | ||
2201 | uint32_t rd_count, | ||
2202 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
2203 | { | ||
2204 | struct ClientShortenHandle* csh = (struct ClientShortenHandle*) cls; | ||
2205 | struct AuthorityChain *auth_chain; | ||
2206 | char* result; | ||
2207 | size_t answer_len; | ||
2208 | |||
2209 | /** | ||
2210 | * At this point rh->name contains the part of the name | ||
2211 | * that we do not have a PKEY in our namestore to resolve. | ||
2212 | * The authority chain in the resolver handle is now | ||
2213 | * useful to backtrack if needed | ||
2214 | */ | ||
2215 | |||
2216 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2217 | "PKEY resolved as far as possible in ns up to %s!\n", rh->name); | ||
2218 | |||
2219 | if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone, | ||
2220 | &zone_hash) == 0) | ||
2221 | { | ||
2222 | /** | ||
2223 | * This is our zone append .gnunet unless name is empty | ||
2224 | * (it shouldn't be, usually FIXME what happens if we | ||
2225 | * shorten to our zone to a "" record??) | ||
2226 | **/ | ||
2227 | |||
2228 | answer_len = strlen(rh->name) + strlen(gnunet_tld) + 2; | ||
2229 | result = GNUNET_malloc(answer_len); | ||
2230 | memset(result, 0, answer_len); | ||
2231 | strcpy(result, rh->name); | ||
2232 | strcpy(result+strlen(rh->name), "."); | ||
2233 | strcpy(result+strlen(rh->name)+1, gnunet_tld); | ||
2234 | |||
2235 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2236 | "Our zone: Sending name as shorten result %s\n", rh->name); | ||
2237 | |||
2238 | send_shorten_response(result, csh); //FIXME +.gnunet! | ||
2239 | free_resolver_handle(rh); | ||
2240 | GNUNET_free(result); | ||
2241 | return; | ||
2242 | } | ||
2243 | |||
2244 | auth_chain = rh->authority_chain_head; | ||
2245 | /* backtrack authorities for pseu */ | ||
2246 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, | ||
2247 | &zone_hash, //ours | ||
2248 | &auth_chain->zone, | ||
2249 | &handle_shorten_zone_to_name, | ||
2250 | rh); | ||
2251 | |||
2252 | } | ||
2253 | |||
2254 | typedef void (*ShortenResponseProc) (void* cls, const char* name); | ||
2255 | |||
2256 | /** | ||
2257 | * Shorten a given name | ||
2258 | * | ||
2259 | * @param name the name to shorten | ||
2260 | * @param csh the shorten handle of the request | ||
2261 | */ | ||
2262 | static void | ||
2263 | shorten_name(char* name, struct ClientShortenHandle* csh) | ||
2264 | { | ||
2265 | |||
2266 | struct GNUNET_GNS_ResolverHandle *rh; | ||
2267 | |||
2268 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2269 | "Starting resolution for %s (type=%d)!\n", | ||
2270 | name, GNUNET_GNS_RECORD_PKEY); | ||
2271 | |||
2272 | rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); | ||
2273 | rh->authority = zone_hash; | ||
2274 | |||
2275 | rh->name = GNUNET_malloc(strlen(name) | ||
2276 | - strlen(gnunet_tld) + 1); | ||
2277 | memset(rh->name, 0, | ||
2278 | strlen(name)-strlen(gnunet_tld) + 1); | ||
2279 | memcpy(rh->name, name, | ||
2280 | strlen(name)-strlen(gnunet_tld)); | ||
2281 | |||
2282 | csh->name = GNUNET_malloc(strlen(name) | ||
2283 | - strlen(gnunet_tld) + 1); | ||
2284 | memset(csh->name, 0, | ||
2285 | strlen(name)-strlen(gnunet_tld) + 1); | ||
2286 | memcpy(csh->name, name, | ||
2287 | strlen(name)-strlen(gnunet_tld)); | ||
2288 | |||
2289 | rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); | ||
2290 | |||
2291 | rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
2292 | rh->authority_chain_tail = rh->authority_chain_head; | ||
2293 | rh->authority_chain_head->zone = zone_hash; | ||
2294 | rh->proc = &handle_shorten_delegation_result; | ||
2295 | rh->proc_cls = (void*)csh; | ||
2296 | |||
2297 | /* Start delegation resolution in our namestore */ | ||
2298 | resolve_delegation_ns(rh); | ||
2299 | |||
2300 | } | ||
2301 | 350 | ||
2302 | /** | 351 | /** |
2303 | * Send shorten response back to client | 352 | * Send shorten response back to client |
@@ -2306,11 +355,12 @@ shorten_name(char* name, struct ClientShortenHandle* csh) | |||
2306 | * @param csh the handle to the shorten request | 355 | * @param csh the handle to the shorten request |
2307 | */ | 356 | */ |
2308 | static void | 357 | static void |
2309 | send_shorten_response(const char* name, struct ClientShortenHandle *csh) | 358 | send_shorten_response(void* cls, const char* name) |
2310 | { | 359 | { |
2311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", | 360 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", |
2312 | "SHORTEN_RESULT", name); | 361 | "SHORTEN_RESULT", name); |
2313 | struct GNUNET_GNS_ClientShortenResultMessage *rmsg; | 362 | struct GNUNET_GNS_ClientShortenResultMessage *rmsg; |
363 | struct ClientShortenHandle *csh = (struct ClientShortenHandle *)cls; | ||
2314 | 364 | ||
2315 | if (name == NULL) | 365 | if (name == NULL) |
2316 | { | 366 | { |
@@ -2354,6 +404,7 @@ static void handle_shorten(void *cls, | |||
2354 | 404 | ||
2355 | size_t msg_size = 0; | 405 | size_t msg_size = 0; |
2356 | struct ClientShortenHandle *csh; | 406 | struct ClientShortenHandle *csh; |
407 | const char* name; | ||
2357 | 408 | ||
2358 | if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientShortenMessage)) | 409 | if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientShortenMessage)) |
2359 | { | 410 | { |
@@ -2380,8 +431,16 @@ static void handle_shorten(void *cls, | |||
2380 | csh->client = client; | 431 | csh->client = client; |
2381 | csh->unique_id = sh_msg->id; | 432 | csh->unique_id = sh_msg->id; |
2382 | 433 | ||
2383 | shorten_name((char*)&sh_msg[1], csh); | 434 | name = (char*)&sh_msg[1]; |
435 | csh->name = GNUNET_malloc(strlen(name) | ||
436 | - strlen(GNUNET_GNS_TLD) + 1); | ||
437 | memset(csh->name, 0, | ||
438 | strlen(name)-strlen(GNUNET_GNS_TLD) + 1); | ||
439 | memcpy(csh->name, name, | ||
440 | strlen(name)-strlen(GNUNET_GNS_TLD)); | ||
2384 | 441 | ||
442 | /* Start shortening */ | ||
443 | gns_resolver_shorten_name(zone_hash, name, &send_shorten_response, csh); | ||
2385 | } | 444 | } |
2386 | 445 | ||
2387 | 446 | ||
@@ -2392,11 +451,12 @@ static void handle_shorten(void *cls, | |||
2392 | * @param cah the handle to the get authority request | 451 | * @param cah the handle to the get authority request |
2393 | */ | 452 | */ |
2394 | static void | 453 | static void |
2395 | send_get_auth_response(const char* name, struct ClientGetAuthHandle *cah) | 454 | send_get_auth_response(void *cls, const char* name) |
2396 | { | 455 | { |
2397 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", | 456 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n", |
2398 | "GET_AUTH_RESULT", name); | 457 | "GET_AUTH_RESULT", name); |
2399 | struct GNUNET_GNS_ClientGetAuthResultMessage *rmsg; | 458 | struct GNUNET_GNS_ClientGetAuthResultMessage *rmsg; |
459 | struct ClientGetAuthHandle *cah = (struct ClientGetAuthHandle *)cls; | ||
2400 | 460 | ||
2401 | if (name == NULL) | 461 | if (name == NULL) |
2402 | { | 462 | { |
@@ -2429,124 +489,6 @@ send_get_auth_response(const char* name, struct ClientGetAuthHandle *cah) | |||
2429 | 489 | ||
2430 | } | 490 | } |
2431 | 491 | ||
2432 | /** | ||
2433 | * Process result from namestore delegation lookup | ||
2434 | * for get authority operation | ||
2435 | * | ||
2436 | * @param cls the client get auth handle | ||
2437 | * @param rh the resolver handle | ||
2438 | * @param rd_count number of results (0) | ||
2439 | * @param rd data (NULL) | ||
2440 | */ | ||
2441 | void | ||
2442 | handle_get_auth_delegation_result(void* cls, | ||
2443 | struct GNUNET_GNS_ResolverHandle *rh, | ||
2444 | uint32_t rd_count, | ||
2445 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
2446 | { | ||
2447 | struct ClientGetAuthHandle* cah = (struct ClientGetAuthHandle*) cls; | ||
2448 | struct AuthorityChain *auth_chain; | ||
2449 | char* result; | ||
2450 | size_t answer_len; | ||
2451 | |||
2452 | /** | ||
2453 | * At this point rh->name contains the part of the name | ||
2454 | * that we do not have a PKEY in our namestore to resolve. | ||
2455 | * The authority chain in the resolver handle is now | ||
2456 | * useful to backtrack if needed | ||
2457 | */ | ||
2458 | |||
2459 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2460 | "PKEY resolved as far as possible in ns up to %s!\n", rh->name); | ||
2461 | |||
2462 | if (is_canonical(rh->name)) | ||
2463 | { | ||
2464 | /** | ||
2465 | * We successfully resolved the authority in the ns | ||
2466 | * FIXME for our purposes this is fine | ||
2467 | * but maybe we want to have an api that also looks | ||
2468 | * into the dht (i.e. option in message) | ||
2469 | **/ | ||
2470 | if (strlen(rh->name) > strlen(cah->name)) | ||
2471 | { | ||
2472 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2473 | "Record name longer than original lookup name... odd!\n"); | ||
2474 | //FIXME to sth here | ||
2475 | } | ||
2476 | |||
2477 | |||
2478 | answer_len = strlen(cah->name) - strlen(rh->name) + strlen(gnunet_tld) + 1; | ||
2479 | result = GNUNET_malloc(answer_len); | ||
2480 | memset(result, 0, answer_len); | ||
2481 | strcpy(result, cah->name + strlen(rh->name) + 1); | ||
2482 | strcpy(result+strlen(result), gnunet_tld); | ||
2483 | |||
2484 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
2485 | "Got authority result %s\n", result); | ||
2486 | |||
2487 | send_get_auth_response(result, cah); | ||
2488 | free_resolver_handle(rh); | ||
2489 | GNUNET_free(result); | ||
2490 | return; | ||
2491 | } | ||
2492 | |||
2493 | auth_chain = rh->authority_chain_head; | ||
2494 | /* backtrack authorities for pseu */ | ||
2495 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, | ||
2496 | &zone_hash, //ours | ||
2497 | &auth_chain->zone, | ||
2498 | &handle_shorten_zone_to_name, | ||
2499 | rh); | ||
2500 | |||
2501 | } | ||
2502 | |||
2503 | |||
2504 | /** | ||
2505 | * Get authority for a given name | ||
2506 | * | ||
2507 | * @param name the name to shorten | ||
2508 | * @param csh the shorten handle of the request | ||
2509 | */ | ||
2510 | static void | ||
2511 | get_authority(char* name, struct ClientGetAuthHandle* cah) | ||
2512 | { | ||
2513 | |||
2514 | struct GNUNET_GNS_ResolverHandle *rh; | ||
2515 | |||
2516 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2517 | "Starting authority resolution for %s (type=%d)!\n", | ||
2518 | name, GNUNET_GNS_RECORD_PKEY); | ||
2519 | |||
2520 | rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); | ||
2521 | rh->authority = zone_hash; | ||
2522 | |||
2523 | rh->name = GNUNET_malloc(strlen(name) | ||
2524 | - strlen(gnunet_tld) + 1); | ||
2525 | memset(rh->name, 0, | ||
2526 | strlen(name)-strlen(gnunet_tld) + 1); | ||
2527 | memcpy(rh->name, name, | ||
2528 | strlen(name)-strlen(gnunet_tld)); | ||
2529 | |||
2530 | cah->name = GNUNET_malloc(strlen(name) | ||
2531 | - strlen(gnunet_tld) + 1); | ||
2532 | memset(cah->name, 0, | ||
2533 | strlen(name)-strlen(gnunet_tld) + 1); | ||
2534 | memcpy(cah->name, name, | ||
2535 | strlen(name)-strlen(gnunet_tld)); | ||
2536 | |||
2537 | rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); | ||
2538 | |||
2539 | rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
2540 | rh->authority_chain_tail = rh->authority_chain_head; | ||
2541 | rh->authority_chain_head->zone = zone_hash; | ||
2542 | rh->proc = &handle_get_auth_delegation_result; | ||
2543 | rh->proc_cls = (void*)cah; | ||
2544 | |||
2545 | /* Start delegation resolution in our namestore */ | ||
2546 | resolve_delegation_ns(rh); | ||
2547 | |||
2548 | } | ||
2549 | |||
2550 | 492 | ||
2551 | /** | 493 | /** |
2552 | * Handle a get authority message from the api | 494 | * Handle a get authority message from the api |
@@ -2563,6 +505,7 @@ static void handle_get_authority(void *cls, | |||
2563 | 505 | ||
2564 | size_t msg_size = 0; | 506 | size_t msg_size = 0; |
2565 | struct ClientGetAuthHandle *cah; | 507 | struct ClientGetAuthHandle *cah; |
508 | const char* name; | ||
2566 | 509 | ||
2567 | if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientGetAuthMessage)) | 510 | if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientGetAuthMessage)) |
2568 | { | 511 | { |
@@ -2589,8 +532,16 @@ static void handle_get_authority(void *cls, | |||
2589 | cah->client = client; | 532 | cah->client = client; |
2590 | cah->unique_id = sh_msg->id; | 533 | cah->unique_id = sh_msg->id; |
2591 | 534 | ||
2592 | get_authority((char*)&sh_msg[1], cah); | 535 | name = (char*)&sh_msg[1]; |
536 | cah->name = GNUNET_malloc(strlen(name) | ||
537 | - strlen(GNUNET_GNS_TLD) + 1); | ||
538 | memset(cah->name, 0, | ||
539 | strlen(name)-strlen(GNUNET_GNS_TLD) + 1); | ||
540 | memcpy(cah->name, name, | ||
541 | strlen(name)-strlen(GNUNET_GNS_TLD)); | ||
2593 | 542 | ||
543 | /* Start delegation resolution in our namestore */ | ||
544 | gns_resolver_get_authority(zone_hash, name, &send_get_auth_response, cah); | ||
2594 | } | 545 | } |
2595 | 546 | ||
2596 | 547 | ||
@@ -2603,9 +554,9 @@ static void handle_get_authority(void *cls, | |||
2603 | * @param rd the record data | 554 | * @param rd the record data |
2604 | */ | 555 | */ |
2605 | static void | 556 | static void |
2606 | reply_to_client(void* cls, struct GNUNET_GNS_ResolverHandle *rh, | 557 | send_lookup_response(void* cls, |
2607 | uint32_t rd_count, | 558 | uint32_t rd_count, |
2608 | const struct GNUNET_NAMESTORE_RecordData *rd) | 559 | const struct GNUNET_NAMESTORE_RecordData *rd) |
2609 | { | 560 | { |
2610 | struct ClientLookupHandle* clh = (struct ClientLookupHandle*)cls; | 561 | struct ClientLookupHandle* clh = (struct ClientLookupHandle*)cls; |
2611 | struct GNUNET_GNS_ClientLookupResultMessage *rmsg; | 562 | struct GNUNET_GNS_ClientLookupResultMessage *rmsg; |
@@ -2630,63 +581,12 @@ reply_to_client(void* cls, struct GNUNET_GNS_ResolverHandle *rh, | |||
2630 | GNUNET_NO); | 581 | GNUNET_NO); |
2631 | GNUNET_SERVER_receive_done (clh->client, GNUNET_OK); | 582 | GNUNET_SERVER_receive_done (clh->client, GNUNET_OK); |
2632 | 583 | ||
2633 | GNUNET_free(rh->proc_cls); | ||
2634 | free_resolver_handle(rh); | ||
2635 | GNUNET_free(rmsg); | 584 | GNUNET_free(rmsg); |
2636 | GNUNET_free(clh->name); | 585 | GNUNET_free(clh->name); |
2637 | GNUNET_free(clh); | 586 | GNUNET_free(clh); |
2638 | 587 | ||
2639 | } | 588 | } |
2640 | 589 | ||
2641 | /** | ||
2642 | * Lookup a given name | ||
2643 | * | ||
2644 | * @param name the name to looku[ | ||
2645 | * @param clh the client lookup handle | ||
2646 | */ | ||
2647 | static void | ||
2648 | lookup_name(char* name, struct ClientLookupHandle* clh) | ||
2649 | { | ||
2650 | |||
2651 | struct GNUNET_GNS_ResolverHandle *rh; | ||
2652 | struct RecordLookupHandle* rlh; | ||
2653 | |||
2654 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2655 | "Starting resolution for %s (type=%d)!\n", | ||
2656 | name, clh->type); | ||
2657 | |||
2658 | rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle)); | ||
2659 | rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle)); | ||
2660 | |||
2661 | rh->authority = zone_hash; | ||
2662 | |||
2663 | rlh->record_type = clh->type; | ||
2664 | rlh->name = clh->name; | ||
2665 | rlh->proc = &reply_to_client; | ||
2666 | rlh->proc_cls = clh; | ||
2667 | |||
2668 | rh->proc_cls = rlh; | ||
2669 | |||
2670 | rh->name = GNUNET_malloc(strlen(name) | ||
2671 | - strlen(gnunet_tld) + 1); | ||
2672 | memset(rh->name, 0, | ||
2673 | strlen(name)-strlen(gnunet_tld) + 1); | ||
2674 | memcpy(rh->name, name, | ||
2675 | strlen(name)-strlen(gnunet_tld)); | ||
2676 | |||
2677 | rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); | ||
2678 | |||
2679 | rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
2680 | rh->authority_chain_head->prev = NULL; | ||
2681 | rh->authority_chain_head->next = NULL; | ||
2682 | rh->authority_chain_tail = rh->authority_chain_head; | ||
2683 | rh->authority_chain_head->zone = zone_hash; | ||
2684 | |||
2685 | /* Start resolution in our zone */ | ||
2686 | rh->proc = &process_delegation_ns; | ||
2687 | resolve_delegation_ns(rh); | ||
2688 | } | ||
2689 | |||
2690 | 590 | ||
2691 | /** | 591 | /** |
2692 | * Handle lookup requests from client | 592 | * Handle lookup requests from client |
@@ -2733,7 +633,8 @@ handle_lookup(void *cls, | |||
2733 | clh->unique_id = sh_msg->id; | 633 | clh->unique_id = sh_msg->id; |
2734 | clh->type = ntohl(sh_msg->type); | 634 | clh->type = ntohl(sh_msg->type); |
2735 | 635 | ||
2736 | lookup_name((char*)&sh_msg[1], clh); | 636 | gns_resolver_lookup_record(zone_hash, clh->type, (char*)&sh_msg[1], |
637 | &send_lookup_response, clh); | ||
2737 | } | 638 | } |
2738 | 639 | ||
2739 | 640 | ||
@@ -2778,24 +679,17 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
2778 | GNUNET_free(keyfile); | 679 | GNUNET_free(keyfile); |
2779 | 680 | ||
2780 | 681 | ||
2781 | dns_handle = NULL; | ||
2782 | if (GNUNET_YES == | 682 | if (GNUNET_YES == |
2783 | GNUNET_CONFIGURATION_get_value_yesno (c, "gns", | 683 | GNUNET_CONFIGURATION_get_value_yesno (c, "gns", |
2784 | "HIJACK_DNS")) | 684 | "HIJACK_DNS")) |
2785 | { | 685 | { |
2786 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, | 686 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, |
2787 | "DNS hijacking enabled... connecting to service.\n"); | 687 | "DNS hijacking enabled... connecting to service.\n"); |
2788 | /** | 688 | |
2789 | * Do gnunet dns init here | 689 | if (gns_interceptor_init(zone_hash, c) == GNUNET_SYSERR) |
2790 | */ | ||
2791 | dns_handle = GNUNET_DNS_connect(c, | ||
2792 | GNUNET_DNS_FLAG_PRE_RESOLUTION, | ||
2793 | &handle_dns_request, /* rh */ | ||
2794 | NULL); /* Closure */ | ||
2795 | if (NULL == dns_handle) | ||
2796 | { | 690 | { |
2797 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 691 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, |
2798 | "Failed to connect to the dnsservice!\n"); | 692 | "Failed to enable the dns interceptor!\n"); |
2799 | } | 693 | } |
2800 | } | 694 | } |
2801 | 695 | ||
diff --git a/src/gns/gnunet-service-gns_interceptor.c b/src/gns/gnunet-service-gns_interceptor.c new file mode 100644 index 000000000..1a14eb96e --- /dev/null +++ b/src/gns/gnunet-service-gns_interceptor.c | |||
@@ -0,0 +1,327 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
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 | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * | ||
23 | * @file gns/gns_interceptor.c | ||
24 | * @brief GNUnet GNS interceptor logic | ||
25 | * @author Martin Schanzenbach | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_transport_service.h" | ||
30 | #include "gnunet_dns_service.h" | ||
31 | #include "gnunet_dnsparser_lib.h" | ||
32 | #include "gnunet-service-gns_resolver.h" | ||
33 | #include "gns.h" | ||
34 | |||
35 | #define MAX_DNS_LABEL_LENGTH 63 | ||
36 | |||
37 | /** | ||
38 | * Handle to a DNS intercepted | ||
39 | * reslution request | ||
40 | */ | ||
41 | struct InterceptLookupHandle | ||
42 | { | ||
43 | /* the request handle to reply to */ | ||
44 | struct GNUNET_DNS_RequestHandle *request_handle; | ||
45 | |||
46 | /* the dns parser packet received */ | ||
47 | struct GNUNET_DNSPARSER_Packet *packet; | ||
48 | |||
49 | /* the query parsed from the packet */ | ||
50 | struct GNUNET_DNSPARSER_Query *query; | ||
51 | }; | ||
52 | |||
53 | |||
54 | /** | ||
55 | * Our handle to the DNS handler library | ||
56 | */ | ||
57 | struct GNUNET_DNS_Handle *dns_handle; | ||
58 | |||
59 | /** | ||
60 | * The root zone for this interceptor | ||
61 | */ | ||
62 | static GNUNET_HashCode our_zone; | ||
63 | |||
64 | /** | ||
65 | * Reply to dns request with the result from our lookup. | ||
66 | * | ||
67 | * @param cls the closure to the request (an InterceptLookupHandle) | ||
68 | * @param rh the request handle of the lookup | ||
69 | * @param rd_count the number of records to return | ||
70 | * @param rd the record data | ||
71 | */ | ||
72 | static void | ||
73 | reply_to_dns(void* cls, uint32_t rd_count, | ||
74 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
75 | { | ||
76 | int i; | ||
77 | size_t len; | ||
78 | int ret; | ||
79 | char *buf; | ||
80 | struct InterceptLookupHandle* ilh = (struct InterceptLookupHandle*)cls; | ||
81 | struct GNUNET_DNSPARSER_Packet *packet = ilh->packet; | ||
82 | unsigned int num_answers = 0; | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Put records in the DNS packet and modify it | ||
87 | * to a response | ||
88 | */ | ||
89 | for (i=0; i < rd_count; i++) | ||
90 | { | ||
91 | if (rd[i].record_type == ilh->query->type) | ||
92 | num_answers++; | ||
93 | } | ||
94 | |||
95 | struct GNUNET_DNSPARSER_Record answer_records[num_answers]; | ||
96 | struct GNUNET_DNSPARSER_Record additional_records[rd_count-(num_answers)]; | ||
97 | packet->answers = answer_records; | ||
98 | packet->additional_records = additional_records; | ||
99 | |||
100 | for (i=0; i < rd_count; i++) | ||
101 | { | ||
102 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
103 | "Adding type %d to DNS response\n", rd[i].record_type); | ||
104 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", ilh->query->name); | ||
105 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count); | ||
106 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size); | ||
107 | |||
108 | if (rd[i].record_type == ilh->query->type) | ||
109 | { | ||
110 | num_answers++; | ||
111 | answer_records[i].name = ilh->query->name; | ||
112 | answer_records[i].type = rd[i].record_type; | ||
113 | answer_records[i].data.raw.data_len = rd[i].data_size; | ||
114 | answer_records[i].data.raw.data = (char*)rd[i].data; | ||
115 | answer_records[i].expiration_time = rd[i].expiration; | ||
116 | answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn | ||
117 | } | ||
118 | else | ||
119 | { | ||
120 | additional_records[i].name = ilh->query->name; | ||
121 | additional_records[i].type = rd[i].record_type; | ||
122 | additional_records[i].data.raw.data_len = rd[i].data_size; | ||
123 | additional_records[i].data.raw.data = (char*)rd[i].data; | ||
124 | additional_records[i].expiration_time = rd[i].expiration; | ||
125 | additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn | ||
126 | } | ||
127 | } | ||
128 | |||
129 | packet->num_answers = num_answers; | ||
130 | packet->num_additional_records = rd_count-(num_answers); | ||
131 | |||
132 | packet->flags.authoritative_answer = 1; | ||
133 | |||
134 | if (rd == NULL) | ||
135 | packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR; | ||
136 | else | ||
137 | packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR; | ||
138 | |||
139 | packet->flags.query_or_response = 1; | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Reply to DNS | ||
144 | */ | ||
145 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
146 | "Building DNS response\n"); | ||
147 | ret = GNUNET_DNSPARSER_pack (packet, | ||
148 | 1024, /* FIXME magic from dns redirector */ | ||
149 | &buf, | ||
150 | &len); | ||
151 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
152 | "Built DNS response! (ret=%d,len=%d)\n", ret, len); | ||
153 | if (ret == GNUNET_OK) | ||
154 | { | ||
155 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
156 | "Answering DNS request\n"); | ||
157 | GNUNET_DNS_request_answer(ilh->request_handle, | ||
158 | len, | ||
159 | buf); | ||
160 | |||
161 | GNUNET_free(buf); | ||
162 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n"); | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
167 | "Error building DNS response! (ret=%d)", ret); | ||
168 | } | ||
169 | |||
170 | packet->num_answers = 0; | ||
171 | packet->answers = NULL; | ||
172 | packet->num_additional_records = 0; | ||
173 | packet->additional_records = NULL; | ||
174 | GNUNET_DNSPARSER_free_packet(packet); | ||
175 | //FIXME free resolver handle in resp functions in resolver! | ||
176 | //GNUNET_free((struct RecordLookupHandle*)rh->proc_cls); | ||
177 | //free_resolver_handle(rh); | ||
178 | GNUNET_free(ilh); | ||
179 | } | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Entry point for name resolution | ||
184 | * Setup a new query and try to resolve | ||
185 | * | ||
186 | * @param request the request handle of the DNS request from a client | ||
187 | * @param p the DNS query packet we received | ||
188 | * @param q the DNS query we received parsed from p | ||
189 | */ | ||
190 | static void | ||
191 | start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request, | ||
192 | struct GNUNET_DNSPARSER_Packet *p, | ||
193 | struct GNUNET_DNSPARSER_Query *q) | ||
194 | { | ||
195 | struct InterceptLookupHandle* ilh; | ||
196 | |||
197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
198 | "Starting resolution for %s (type=%d)!\n", | ||
199 | q->name, q->type); | ||
200 | |||
201 | ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle)); | ||
202 | ilh->packet = p; | ||
203 | ilh->query = q; | ||
204 | ilh->request_handle = request; | ||
205 | |||
206 | /* Start resolution in our zone */ | ||
207 | gns_resolver_lookup_record(our_zone, q->type, q->name, &reply_to_dns, ilh); | ||
208 | } | ||
209 | |||
210 | |||
211 | |||
212 | /** | ||
213 | * The DNS request handler | ||
214 | * Called for every incoming DNS request. | ||
215 | * | ||
216 | * @param cls closure | ||
217 | * @param rh request handle to user for reply | ||
218 | * @param request_length number of bytes in request | ||
219 | * @param request udp payload of the DNS request | ||
220 | */ | ||
221 | static void | ||
222 | handle_dns_request(void *cls, | ||
223 | struct GNUNET_DNS_RequestHandle *rh, | ||
224 | size_t request_length, | ||
225 | const char *request) | ||
226 | { | ||
227 | struct GNUNET_DNSPARSER_Packet *p; | ||
228 | int i; | ||
229 | char *tldoffset; | ||
230 | |||
231 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n"); | ||
232 | p = GNUNET_DNSPARSER_parse (request, request_length); | ||
233 | |||
234 | if (NULL == p) | ||
235 | { | ||
236 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
237 | "Received malformed DNS packet, leaving it untouched\n"); | ||
238 | GNUNET_DNS_request_forward (rh); | ||
239 | GNUNET_DNSPARSER_free_packet (p); | ||
240 | return; | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * Check tld and decide if we or | ||
245 | * legacy dns is responsible | ||
246 | * | ||
247 | * FIXME now in theory there could be more than 1 query in the request | ||
248 | * but if this is case we get into trouble: | ||
249 | * either we query the GNS or the DNS. We cannot do both! | ||
250 | * So I suggest to either only allow a single query per request or | ||
251 | * only allow GNS or DNS requests. | ||
252 | * The way it is implemented here now is buggy and will lead to erratic | ||
253 | * behaviour (if multiple queries are present). | ||
254 | */ | ||
255 | if (p->num_queries == 0) | ||
256 | { | ||
257 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
258 | "No Queries in DNS packet... forwarding\n"); | ||
259 | GNUNET_DNS_request_forward (rh); | ||
260 | GNUNET_DNSPARSER_free_packet(p); | ||
261 | return; | ||
262 | } | ||
263 | |||
264 | if (p->num_queries > 1) | ||
265 | { | ||
266 | /* Note: We could also look for .gnunet */ | ||
267 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
268 | ">1 queriy in DNS packet... odd. We only process #1\n"); | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * Check for .gnunet | ||
274 | */ | ||
275 | tldoffset = p->queries[0].name + strlen(p->queries[0].name) - 1; | ||
276 | |||
277 | for (i=0; i<strlen(p->queries[0].name); i++) | ||
278 | { | ||
279 | if (*(tldoffset-i) == '.') | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | if ((i==strlen(GNUNET_GNS_TLD)-1) | ||
284 | && (0 == strcmp(tldoffset-i, GNUNET_GNS_TLD))) | ||
285 | { | ||
286 | start_resolution_for_dns(rh, p, p->queries); | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | /** | ||
291 | * This request does not concern us. Forward to real DNS. | ||
292 | */ | ||
293 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
294 | "Request for %s is forwarded to DNS\n", p->queries[0].name); | ||
295 | GNUNET_DNS_request_forward (rh); | ||
296 | GNUNET_DNSPARSER_free_packet (p); | ||
297 | } | ||
298 | |||
299 | } | ||
300 | |||
301 | |||
302 | int | ||
303 | gns_interceptor_init(GNUNET_HashCode zone, | ||
304 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
305 | { | ||
306 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, | ||
307 | "DNS hijacking enabled... connecting to service.\n"); | ||
308 | |||
309 | our_zone = zone; | ||
310 | /** | ||
311 | * Do gnunet dns init here | ||
312 | */ | ||
313 | dns_handle = GNUNET_DNS_connect(c, | ||
314 | GNUNET_DNS_FLAG_PRE_RESOLUTION, | ||
315 | &handle_dns_request, /* rh */ | ||
316 | NULL); /* Closure */ | ||
317 | if (NULL == dns_handle) | ||
318 | { | ||
319 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
320 | "Failed to connect to the dnsservice!\n"); | ||
321 | return GNUNET_SYSERR; | ||
322 | } | ||
323 | |||
324 | return GNUNET_YES; | ||
325 | } | ||
326 | |||
327 | /* end of gns_interceptor.c */ | ||
diff --git a/src/gns/gnunet-service-gns_interceptor.h b/src/gns/gnunet-service-gns_interceptor.h new file mode 100644 index 000000000..03b91856e --- /dev/null +++ b/src/gns/gnunet-service-gns_interceptor.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef GNUNET_GNS_INTERCEPTOR_H | ||
2 | #define GNUNET_GNS_INTERCEPTOR_H | ||
3 | |||
4 | /** | ||
5 | * Initialize dns interceptor | ||
6 | * | ||
7 | * @param zone the zone | ||
8 | * @param c the configuration | ||
9 | * @return GNUNET_YES on success GNUNET_SYSERR on error | ||
10 | */ | ||
11 | int | ||
12 | gns_interceptor_init(GNUNET_HashCode zone, | ||
13 | const struct GNUNET_CONFIGURATION_Handle *c); | ||
14 | |||
15 | void | ||
16 | gns_interceptor_stop(void){}; | ||
17 | |||
18 | #endif | ||
diff --git a/src/gns/gnunet-service-gns_resolver.c b/src/gns/gnunet-service-gns_resolver.c new file mode 100644 index 000000000..53fdcc463 --- /dev/null +++ b/src/gns/gnunet-service-gns_resolver.c | |||
@@ -0,0 +1,1712 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) | ||
4 | |||
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 | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * | ||
23 | * | ||
24 | * @file gns/gns_resolver.c | ||
25 | * @brief GNUnet GNS service | ||
26 | * @author Martin Schanzenbach | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_transport_service.h" | ||
31 | #include "gnunet_dns_service.h" | ||
32 | #include "gnunet_dht_service.h" | ||
33 | #include "gnunet_namestore_service.h" | ||
34 | #include "gnunet_dns_service.h" | ||
35 | #include "gnunet_dnsparser_lib.h" | ||
36 | #include "gnunet_gns_service.h" | ||
37 | #include "block_gns.h" | ||
38 | #include "gns.h" | ||
39 | #include "gnunet-service-gns_resolver.h" | ||
40 | |||
41 | #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) | ||
42 | #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT | ||
43 | #define DHT_GNS_REPLICATION_LEVEL 5 | ||
44 | #define MAX_DNS_LABEL_LENGTH 63 | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Our handle to the namestore service | ||
49 | * FIXME maybe need a second handle for iteration | ||
50 | */ | ||
51 | struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
52 | |||
53 | struct GNUNET_DHT_Handle *dht_handle; | ||
54 | |||
55 | static void | ||
56 | connect_to_dht() | ||
57 | { | ||
58 | //FIXME | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * Helper function to free resolver handle | ||
63 | * | ||
64 | * @rh the handle to free | ||
65 | */ | ||
66 | static void | ||
67 | free_resolver_handle(struct ResolverHandle* rh) | ||
68 | { | ||
69 | struct AuthorityChain *ac; | ||
70 | struct AuthorityChain *ac_next; | ||
71 | |||
72 | if (NULL == rh) | ||
73 | return; | ||
74 | |||
75 | GNUNET_free_non_null (rh->name); | ||
76 | GNUNET_free_non_null (rh->authority_name); | ||
77 | |||
78 | ac = rh->authority_chain_head; | ||
79 | |||
80 | while (NULL != ac) | ||
81 | { | ||
82 | ac_next = ac->next; | ||
83 | GNUNET_free_non_null (ac->name); | ||
84 | GNUNET_free(ac); | ||
85 | ac = ac_next; | ||
86 | } | ||
87 | GNUNET_free(rh); | ||
88 | } | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Callback when record data is put into namestore | ||
93 | * | ||
94 | * @param cls the closure | ||
95 | * @param success GNUNET_OK on success | ||
96 | * @param emsg the error message. NULL if SUCCESS==GNUNET_OK | ||
97 | */ | ||
98 | void | ||
99 | on_namestore_record_put_result(void *cls, | ||
100 | int32_t success, | ||
101 | const char *emsg) | ||
102 | { | ||
103 | if (GNUNET_NO == success) | ||
104 | { | ||
105 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "records already in namestore\n"); | ||
106 | return; | ||
107 | } | ||
108 | else if (GNUNET_YES == success) | ||
109 | { | ||
110 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
111 | "records successfully put in namestore\n"); | ||
112 | return; | ||
113 | } | ||
114 | |||
115 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | ||
116 | "Error putting records into namestore: %s\n", emsg); | ||
117 | } | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Handle timeout for DHT requests | ||
122 | * | ||
123 | * @param cls the request handle as closure | ||
124 | * @param tc the task context | ||
125 | */ | ||
126 | static void | ||
127 | dht_lookup_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
128 | { | ||
129 | struct ResolverHandle *rh = cls; | ||
130 | |||
131 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
132 | "dht lookup for query %s timed out.\n", | ||
133 | rh->name); | ||
134 | |||
135 | GNUNET_DHT_get_stop (rh->get_handle); | ||
136 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
137 | } | ||
138 | |||
139 | |||
140 | /** | ||
141 | * Function called when we get a result from the dht | ||
142 | * for our record query | ||
143 | * | ||
144 | * @param cls the request handle | ||
145 | * @param exp lifetime | ||
146 | * @param key the key the record was stored under | ||
147 | * @param get_path get path | ||
148 | * @param get_path_length get path length | ||
149 | * @param put_path put path | ||
150 | * @param put_path_length put path length | ||
151 | * @param type the block type | ||
152 | * @param size the size of the record | ||
153 | * @param data the record data | ||
154 | */ | ||
155 | static void | ||
156 | process_record_result_dht(void* cls, | ||
157 | struct GNUNET_TIME_Absolute exp, | ||
158 | const GNUNET_HashCode * key, | ||
159 | const struct GNUNET_PeerIdentity *get_path, | ||
160 | unsigned int get_path_length, | ||
161 | const struct GNUNET_PeerIdentity *put_path, | ||
162 | unsigned int put_path_length, | ||
163 | enum GNUNET_BLOCK_Type type, | ||
164 | size_t size, const void *data) | ||
165 | { | ||
166 | struct ResolverHandle *rh; | ||
167 | struct RecordLookupHandle *rlh; | ||
168 | struct GNSNameRecordBlock *nrb; | ||
169 | uint32_t num_records; | ||
170 | char* name = NULL; | ||
171 | char* rd_data = (char*)data; | ||
172 | int i; | ||
173 | int rd_size; | ||
174 | |||
175 | GNUNET_HashCode zone, name_hash; | ||
176 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got dht result (size=%d)\n", size); | ||
177 | |||
178 | if (data == NULL) | ||
179 | return; | ||
180 | |||
181 | //FIXME maybe check expiration here, check block type | ||
182 | |||
183 | rh = (struct ResolverHandle *)cls; | ||
184 | rlh = (struct RecordLookupHandle *) rh->proc_cls; | ||
185 | nrb = (struct GNSNameRecordBlock*)data; | ||
186 | |||
187 | /* stop lookup and timeout task */ | ||
188 | GNUNET_DHT_get_stop (rh->get_handle); | ||
189 | GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); | ||
190 | |||
191 | rh->get_handle = NULL; | ||
192 | name = (char*)&nrb[1]; | ||
193 | num_records = ntohl(nrb->rd_count); | ||
194 | { | ||
195 | struct GNUNET_NAMESTORE_RecordData rd[num_records]; | ||
196 | |||
197 | rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); | ||
198 | rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); | ||
199 | |||
200 | if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, | ||
201 | rd_data, | ||
202 | num_records, | ||
203 | rd)) | ||
204 | { | ||
205 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | for (i=0; i<num_records; i++) | ||
210 | { | ||
211 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
212 | "Got name: %s (wanted %s)\n", name, rh->name); | ||
213 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
214 | "Got type: %d\n", | ||
215 | rd[i].record_type); | ||
216 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
217 | "Got data length: %d\n", rd[i].data_size); | ||
218 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
219 | "Got flag %d\n", rd[i].flags); | ||
220 | |||
221 | if ((strcmp(name, rh->name) == 0) && | ||
222 | (rd[i].record_type == rlh->record_type)) | ||
223 | { | ||
224 | rh->answered++; | ||
225 | } | ||
226 | |||
227 | } | ||
228 | |||
229 | GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); | ||
230 | GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); | ||
231 | |||
232 | /** | ||
233 | * FIXME check pubkey against existing key in namestore? | ||
234 | * https://gnunet.org/bugs/view.php?id=2179 | ||
235 | */ | ||
236 | |||
237 | /* Save to namestore */ | ||
238 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
239 | &nrb->public_key, | ||
240 | name, | ||
241 | exp, | ||
242 | num_records, | ||
243 | rd, | ||
244 | &nrb->signature, | ||
245 | &on_namestore_record_put_result, //cont | ||
246 | NULL); //cls | ||
247 | |||
248 | if (rh->answered) | ||
249 | rh->proc(rh->proc_cls, rh, num_records, rd); | ||
250 | else | ||
251 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
252 | } | ||
253 | |||
254 | } | ||
255 | |||
256 | |||
257 | /** | ||
258 | * Start DHT lookup for a (name -> query->record_type) record in | ||
259 | * rh->authority's zone | ||
260 | * | ||
261 | * @param rh the pending gns query context | ||
262 | */ | ||
263 | static void | ||
264 | resolve_record_dht(struct ResolverHandle *rh) | ||
265 | { | ||
266 | uint32_t xquery; | ||
267 | GNUNET_HashCode name_hash; | ||
268 | GNUNET_HashCode lookup_key; | ||
269 | struct GNUNET_CRYPTO_HashAsciiEncoded lookup_key_string; | ||
270 | struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; | ||
271 | |||
272 | GNUNET_CRYPTO_hash(rh->name, strlen(rh->name), &name_hash); | ||
273 | GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); | ||
274 | GNUNET_CRYPTO_hash_to_enc (&lookup_key, &lookup_key_string); | ||
275 | |||
276 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
277 | "starting dht lookup for %s with key: %s\n", | ||
278 | rh->name, (char*)&lookup_key_string); | ||
279 | |||
280 | rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed(DHT_LOOKUP_TIMEOUT, | ||
281 | &dht_lookup_timeout, rh); | ||
282 | |||
283 | xquery = htonl(rlh->record_type); | ||
284 | rh->get_handle = GNUNET_DHT_get_start(dht_handle, | ||
285 | DHT_OPERATION_TIMEOUT, | ||
286 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
287 | &lookup_key, | ||
288 | DHT_GNS_REPLICATION_LEVEL, | ||
289 | GNUNET_DHT_RO_NONE, | ||
290 | &xquery, | ||
291 | sizeof(xquery), | ||
292 | &process_record_result_dht, | ||
293 | rh); | ||
294 | |||
295 | } | ||
296 | |||
297 | |||
298 | /** | ||
299 | * Namestore calls this function if we have record for this name. | ||
300 | * (or with rd_count=0 to indicate no matches) | ||
301 | * | ||
302 | * @param cls the pending query | ||
303 | * @param key the key of the zone we did the lookup | ||
304 | * @param expiration expiration date of the namestore entry | ||
305 | * @param name the name for which we need an authority | ||
306 | * @param rd_count the number of records with 'name' | ||
307 | * @param rd the record data | ||
308 | * @param signature the signature of the authority for the record data | ||
309 | */ | ||
310 | static void | ||
311 | process_record_result_ns(void* cls, | ||
312 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, | ||
313 | struct GNUNET_TIME_Absolute expiration, | ||
314 | const char *name, unsigned int rd_count, | ||
315 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
316 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
317 | { | ||
318 | struct ResolverHandle *rh; | ||
319 | struct RecordLookupHandle *rlh; | ||
320 | struct GNUNET_TIME_Relative remaining_time; | ||
321 | GNUNET_HashCode zone; | ||
322 | |||
323 | rh = (struct ResolverHandle *) cls; | ||
324 | rlh = (struct RecordLookupHandle *)rh->proc_cls; | ||
325 | GNUNET_CRYPTO_hash(key, | ||
326 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
327 | &zone); | ||
328 | remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); | ||
329 | |||
330 | rh->status = 0; | ||
331 | |||
332 | if (name != NULL) | ||
333 | { | ||
334 | rh->status |= EXISTS; | ||
335 | } | ||
336 | |||
337 | if (remaining_time.rel_value == 0) | ||
338 | { | ||
339 | rh->status |= EXPIRED; | ||
340 | } | ||
341 | |||
342 | if (rd_count == 0) | ||
343 | { | ||
344 | /** | ||
345 | * Lookup terminated and no results | ||
346 | */ | ||
347 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
348 | "Namestore lookup for %s terminated without results\n", name); | ||
349 | |||
350 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
351 | "Record %s unknown in namestore\n", | ||
352 | rh->name); | ||
353 | /** | ||
354 | * Our zone and no result? Cannot resolve TT | ||
355 | */ | ||
356 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
357 | return; | ||
358 | |||
359 | } | ||
360 | else | ||
361 | { | ||
362 | |||
363 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
364 | "Processing additional result %s from namestore\n", name); | ||
365 | int i; | ||
366 | for (i=0; i<rd_count;i++) | ||
367 | { | ||
368 | |||
369 | if (rd[i].record_type != rlh->record_type) | ||
370 | continue; | ||
371 | |||
372 | if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value | ||
373 | == 0) | ||
374 | { | ||
375 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
376 | "This record is expired. Skipping\n"); | ||
377 | continue; | ||
378 | } | ||
379 | |||
380 | rh->answered++; | ||
381 | |||
382 | } | ||
383 | |||
384 | /** | ||
385 | * no answers found | ||
386 | */ | ||
387 | if (rh->answered == 0) | ||
388 | { | ||
389 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
390 | "No answers found. This is odd!\n"); | ||
391 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
392 | return; | ||
393 | } | ||
394 | |||
395 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found %d answer(s) to query!\n", | ||
396 | rh->answered); | ||
397 | |||
398 | rh->proc(rh->proc_cls, rh, rd_count, rd); | ||
399 | } | ||
400 | } | ||
401 | |||
402 | |||
403 | /** | ||
404 | * The final phase of resolution. | ||
405 | * rh->name is a name that is canonical and we do not have a delegation. | ||
406 | * Query namestore for this record | ||
407 | * | ||
408 | * @param rh the pending lookup | ||
409 | */ | ||
410 | static void | ||
411 | resolve_record_ns(struct ResolverHandle *rh) | ||
412 | { | ||
413 | struct RecordLookupHandle *rlh = (struct RecordLookupHandle *)rh->proc_cls; | ||
414 | |||
415 | /** | ||
416 | * Try to resolve this record in our namestore. | ||
417 | * The name to resolve is now in rh->authority_name | ||
418 | * since we tried to resolve it to an authority | ||
419 | * and failed. | ||
420 | **/ | ||
421 | GNUNET_NAMESTORE_lookup_record(namestore_handle, | ||
422 | &rh->authority, | ||
423 | rh->name, | ||
424 | rlh->record_type, | ||
425 | &process_record_result_ns, | ||
426 | rh); | ||
427 | } | ||
428 | |||
429 | |||
430 | /** | ||
431 | * Handle timeout for DHT requests | ||
432 | * | ||
433 | * @param cls the request handle as closure | ||
434 | * @param tc the task context | ||
435 | */ | ||
436 | static void | ||
437 | dht_authority_lookup_timeout(void *cls, | ||
438 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
439 | { | ||
440 | struct ResolverHandle *rh = cls; | ||
441 | |||
442 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
443 | "dht lookup for query %s timed out.\n", | ||
444 | rh->name); | ||
445 | |||
446 | GNUNET_DHT_get_stop (rh->get_handle); | ||
447 | if (strcmp(rh->name, "") == 0) | ||
448 | { | ||
449 | /* | ||
450 | * promote authority back to name and try to resolve record | ||
451 | */ | ||
452 | strcpy(rh->name, rh->authority_name); | ||
453 | } | ||
454 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
455 | } | ||
456 | |||
457 | /* Prototype */ | ||
458 | static void resolve_delegation_dht(struct ResolverHandle *rh); | ||
459 | |||
460 | /** | ||
461 | * Function called when we get a result from the dht | ||
462 | * for our query. Recursively tries to resolve authorities | ||
463 | * for name in DHT. | ||
464 | * | ||
465 | * @param cls the request handle | ||
466 | * @param exp lifetime | ||
467 | * @param key the key the record was stored under | ||
468 | * @param get_path get path | ||
469 | * @param get_path_length get path length | ||
470 | * @param put_path put path | ||
471 | * @param put_path_length put path length | ||
472 | * @param type the block type | ||
473 | * @param size the size of the record | ||
474 | * @param data the record data | ||
475 | */ | ||
476 | static void | ||
477 | process_delegation_result_dht(void* cls, | ||
478 | struct GNUNET_TIME_Absolute exp, | ||
479 | const GNUNET_HashCode * key, | ||
480 | const struct GNUNET_PeerIdentity *get_path, | ||
481 | unsigned int get_path_length, | ||
482 | const struct GNUNET_PeerIdentity *put_path, | ||
483 | unsigned int put_path_length, | ||
484 | enum GNUNET_BLOCK_Type type, | ||
485 | size_t size, const void *data) | ||
486 | { | ||
487 | struct ResolverHandle *rh; | ||
488 | struct GNSNameRecordBlock *nrb; | ||
489 | uint32_t num_records; | ||
490 | char* name = NULL; | ||
491 | char* rd_data = (char*) data; | ||
492 | int i; | ||
493 | int rd_size; | ||
494 | GNUNET_HashCode zone, name_hash; | ||
495 | |||
496 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got DHT result\n"); | ||
497 | |||
498 | if (data == NULL) | ||
499 | return; | ||
500 | |||
501 | //FIXME check expiration? | ||
502 | |||
503 | rh = (struct ResolverHandle *)cls; | ||
504 | nrb = (struct GNSNameRecordBlock*)data; | ||
505 | |||
506 | /* stop dht lookup and timeout task */ | ||
507 | GNUNET_DHT_get_stop (rh->get_handle); | ||
508 | GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); | ||
509 | |||
510 | rh->get_handle = NULL; | ||
511 | num_records = ntohl(nrb->rd_count); | ||
512 | name = (char*)&nrb[1]; | ||
513 | { | ||
514 | struct GNUNET_NAMESTORE_RecordData rd[num_records]; | ||
515 | |||
516 | rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); | ||
517 | rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); | ||
518 | |||
519 | if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, | ||
520 | rd_data, | ||
521 | num_records, | ||
522 | rd)) | ||
523 | { | ||
524 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); | ||
525 | return; | ||
526 | } | ||
527 | |||
528 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
529 | "Got name: %s (wanted %s)\n", name, rh->authority_name); | ||
530 | for (i=0; i<num_records; i++) | ||
531 | { | ||
532 | |||
533 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
534 | "Got name: %s (wanted %s)\n", name, rh->authority_name); | ||
535 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
536 | "Got type: %d (wanted %d)\n", | ||
537 | rd[i].record_type, GNUNET_GNS_RECORD_PKEY); | ||
538 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
539 | "Got data length: %d\n", rd[i].data_size); | ||
540 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
541 | "Got flag %d\n", rd[i].flags); | ||
542 | |||
543 | if ((strcmp(name, rh->authority_name) == 0) && | ||
544 | (rd[i].record_type == GNUNET_GNS_RECORD_PKEY)) | ||
545 | { | ||
546 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Authority found in DHT\n"); | ||
547 | rh->answered = 1; | ||
548 | memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); | ||
549 | struct AuthorityChain *auth = | ||
550 | GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
551 | auth->zone = rh->authority; | ||
552 | auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); | ||
553 | memset(auth->name, 0, strlen(rh->authority_name)+1); | ||
554 | strcpy(auth->name, rh->authority_name); | ||
555 | GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head, | ||
556 | rh->authority_chain_tail, | ||
557 | auth); | ||
558 | } | ||
559 | |||
560 | } | ||
561 | |||
562 | |||
563 | GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); | ||
564 | GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); | ||
565 | |||
566 | /* Save to namestore */ | ||
567 | if (0 != GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_tail->zone, &zone)) | ||
568 | { | ||
569 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
570 | &nrb->public_key, | ||
571 | name, | ||
572 | exp, | ||
573 | num_records, | ||
574 | rd, | ||
575 | &nrb->signature, | ||
576 | &on_namestore_record_put_result, //cont | ||
577 | NULL); //cls | ||
578 | } | ||
579 | } | ||
580 | |||
581 | if (rh->answered) | ||
582 | { | ||
583 | rh->answered = 0; | ||
584 | /** | ||
585 | * delegate | ||
586 | * FIXME in this case. should we ask namestore again? | ||
587 | */ | ||
588 | if (strcmp(rh->name, "") == 0) | ||
589 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
590 | else | ||
591 | resolve_delegation_dht(rh); | ||
592 | return; | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * should never get here unless false dht key/put | ||
597 | * block plugin should handle this | ||
598 | **/ | ||
599 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DHT authority lookup error!\n"); | ||
600 | GNUNET_break(0); | ||
601 | } | ||
602 | |||
603 | |||
604 | /** | ||
605 | * Process DHT lookup result for record. | ||
606 | * | ||
607 | * @param cls the closure | ||
608 | * @param rh resolver handle | ||
609 | * @param rd_count number of results (always 0) | ||
610 | * @param rd record data (always NULL) | ||
611 | */ | ||
612 | static void | ||
613 | handle_record_dht(void* cls, struct ResolverHandle *rh, | ||
614 | unsigned int rd_count, | ||
615 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
616 | { | ||
617 | struct RecordLookupHandle* rlh; | ||
618 | rlh = (struct RecordLookupHandle*)cls; | ||
619 | if (rd_count == 0) | ||
620 | { | ||
621 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
622 | "No records for %s found in DHT. Aborting\n", | ||
623 | rh->name); | ||
624 | /* give up, cannot resolve */ | ||
625 | rlh->proc(rlh->proc_cls, 0, NULL); | ||
626 | return; | ||
627 | } | ||
628 | |||
629 | /* results found yay */ | ||
630 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
631 | "Record resolved from namestore!"); | ||
632 | rlh->proc(rlh->proc_cls, rd_count, rd); | ||
633 | |||
634 | } | ||
635 | |||
636 | |||
637 | /** | ||
638 | * Process namestore lookup result for record. | ||
639 | * | ||
640 | * @param cls the closure | ||
641 | * @param rh resolver handle | ||
642 | * @param rd_count number of results (always 0) | ||
643 | * @param rd record data (always NULL) | ||
644 | */ | ||
645 | static void | ||
646 | handle_record_ns(void* cls, struct ResolverHandle *rh, | ||
647 | unsigned int rd_count, | ||
648 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
649 | { | ||
650 | struct RecordLookupHandle* rlh; | ||
651 | rlh = (struct RecordLookupHandle*) cls; | ||
652 | if (rd_count == 0) | ||
653 | { | ||
654 | /* ns entry expired. try dht */ | ||
655 | if (rh->status & (EXPIRED | !EXISTS)) | ||
656 | { | ||
657 | rh->proc = &handle_record_dht; | ||
658 | resolve_record_dht(rh); | ||
659 | return; | ||
660 | } | ||
661 | /* give up, cannot resolve */ | ||
662 | rlh->proc(rlh->proc_cls, 0, NULL); | ||
663 | return; | ||
664 | } | ||
665 | |||
666 | /* results found yay */ | ||
667 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
668 | "Record resolved from namestore!"); | ||
669 | rlh->proc(rlh->proc_cls, rd_count, rd); | ||
670 | |||
671 | } | ||
672 | |||
673 | |||
674 | /** | ||
675 | * Determine if this name is canonical. | ||
676 | * i.e. | ||
677 | * a.b.gnunet = not canonical | ||
678 | * a = canonical | ||
679 | * | ||
680 | * @param name the name to test | ||
681 | * @return 1 if canonical | ||
682 | */ | ||
683 | static int | ||
684 | is_canonical(char* name) | ||
685 | { | ||
686 | uint32_t len = strlen(name); | ||
687 | int i; | ||
688 | |||
689 | for (i=0; i<len; i++) | ||
690 | { | ||
691 | if (*(name+i) == '.') | ||
692 | return 0; | ||
693 | } | ||
694 | return 1; | ||
695 | } | ||
696 | |||
697 | /** | ||
698 | * Move one level up in the domain hierarchy and return the | ||
699 | * passed top level domain. | ||
700 | * | ||
701 | * @param name the domain | ||
702 | * @param dest the destination where the tld will be put | ||
703 | */ | ||
704 | void | ||
705 | pop_tld(char* name, char* dest) | ||
706 | { | ||
707 | uint32_t len; | ||
708 | |||
709 | if (is_canonical(name)) | ||
710 | { | ||
711 | strcpy(dest, name); | ||
712 | strcpy(name, ""); | ||
713 | return; | ||
714 | } | ||
715 | |||
716 | for (len = strlen(name); len > 0; len--) | ||
717 | { | ||
718 | if (*(name+len) == '.') | ||
719 | break; | ||
720 | } | ||
721 | |||
722 | //Was canonical? | ||
723 | if (len == 0) | ||
724 | return; | ||
725 | |||
726 | name[len] = '\0'; | ||
727 | |||
728 | strcpy(dest, (name+len+1)); | ||
729 | } | ||
730 | |||
731 | /** | ||
732 | * DHT resolution for delegation finished. Processing result. | ||
733 | * | ||
734 | * @param cls the closure | ||
735 | * @param rh resolver handle | ||
736 | * @param rd_count number of results (always 0) | ||
737 | * @param rd record data (always NULL) | ||
738 | */ | ||
739 | static void | ||
740 | handle_delegation_dht(void* cls, struct ResolverHandle *rh, | ||
741 | unsigned int rd_count, | ||
742 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
743 | { | ||
744 | struct RecordLookupHandle* rlh; | ||
745 | rlh = (struct RecordLookupHandle*) cls; | ||
746 | |||
747 | if (strcmp(rh->name, "") == 0) | ||
748 | { | ||
749 | /* We resolved full name for delegation. resolving record */ | ||
750 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
751 | "Resolved full name for delegation via DHT. resolving record '' in ns\n"); | ||
752 | rh->proc = &handle_record_ns; | ||
753 | resolve_record_ns(rh); | ||
754 | return; | ||
755 | } | ||
756 | |||
757 | /** | ||
758 | * we still have some left | ||
759 | **/ | ||
760 | if (is_canonical(rh->name)) | ||
761 | { | ||
762 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
763 | "Resolving canonical record %s in ns\n", rh->name); | ||
764 | rh->proc = &handle_record_ns; | ||
765 | resolve_record_ns(rh); | ||
766 | return; | ||
767 | } | ||
768 | /* give up, cannot resolve */ | ||
769 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
770 | "Cannot fully resolve delegation for %s via DHT!\n", | ||
771 | rh->name); | ||
772 | rlh->proc(rlh->proc_cls, 0, NULL); | ||
773 | } | ||
774 | |||
775 | |||
776 | /** | ||
777 | * Start DHT lookup for a name -> PKEY (compare NS) record in | ||
778 | * rh->authority's zone | ||
779 | * | ||
780 | * @param rh the pending gns query | ||
781 | * @param name the name of the PKEY record | ||
782 | */ | ||
783 | static void | ||
784 | resolve_delegation_dht(struct ResolverHandle *rh) | ||
785 | { | ||
786 | uint32_t xquery; | ||
787 | GNUNET_HashCode name_hash; | ||
788 | GNUNET_HashCode lookup_key; | ||
789 | |||
790 | GNUNET_CRYPTO_hash(rh->authority_name, | ||
791 | strlen(rh->authority_name), | ||
792 | &name_hash); | ||
793 | GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); | ||
794 | |||
795 | rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, | ||
796 | &dht_authority_lookup_timeout, | ||
797 | rh); | ||
798 | |||
799 | xquery = htonl(GNUNET_GNS_RECORD_PKEY); | ||
800 | |||
801 | rh->get_handle = GNUNET_DHT_get_start(dht_handle, | ||
802 | DHT_OPERATION_TIMEOUT, | ||
803 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
804 | &lookup_key, | ||
805 | DHT_GNS_REPLICATION_LEVEL, | ||
806 | GNUNET_DHT_RO_NONE, | ||
807 | &xquery, | ||
808 | sizeof(xquery), | ||
809 | &process_delegation_result_dht, | ||
810 | rh); | ||
811 | |||
812 | } | ||
813 | |||
814 | |||
815 | /** | ||
816 | * Namestore resolution for delegation finished. Processing result. | ||
817 | * | ||
818 | * @param cls the closure | ||
819 | * @param rh resolver handle | ||
820 | * @param rd_count number of results (always 0) | ||
821 | * @param rd record data (always NULL) | ||
822 | */ | ||
823 | static void | ||
824 | handle_delegation_ns(void* cls, struct ResolverHandle *rh, | ||
825 | unsigned int rd_count, | ||
826 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
827 | { | ||
828 | struct RecordLookupHandle* rlh; | ||
829 | rlh = (struct RecordLookupHandle*) cls; | ||
830 | |||
831 | if (strcmp(rh->name, "") == 0) | ||
832 | { | ||
833 | /* We resolved full name for delegation. resolving record */ | ||
834 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
835 | "Resolved full name for delegation. resolving record ''\n"); | ||
836 | rh->proc = &handle_record_ns; | ||
837 | resolve_record_ns(rh); | ||
838 | return; | ||
839 | } | ||
840 | |||
841 | /** | ||
842 | * we still have some left | ||
843 | * check if ns entry is fresh | ||
844 | **/ | ||
845 | if (rh->status & (EXISTS | !EXPIRED)) | ||
846 | { | ||
847 | if (is_canonical(rh->name)) | ||
848 | { | ||
849 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
850 | "Resolving canonical record %s\n", rh->name); | ||
851 | rh->proc = &handle_record_ns; | ||
852 | resolve_record_ns(rh); | ||
853 | } | ||
854 | else | ||
855 | { | ||
856 | /* give up, cannot resolve */ | ||
857 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
858 | "Cannot fully resolve delegation for %s!\n", | ||
859 | rh->name); | ||
860 | rlh->proc(rlh->proc_cls, 0, NULL); | ||
861 | } | ||
862 | return; | ||
863 | } | ||
864 | |||
865 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
866 | "Trying to resolve delegation for %s via DHT\n", | ||
867 | rh->name); | ||
868 | rh->proc = &handle_delegation_dht; | ||
869 | resolve_delegation_dht(rh); | ||
870 | } | ||
871 | |||
872 | //Prototype | ||
873 | static void resolve_delegation_ns(struct ResolverHandle *rh); | ||
874 | |||
875 | |||
876 | /** | ||
877 | * This is a callback function that should give us only PKEY | ||
878 | * records. Used to query the namestore for the authority (PKEY) | ||
879 | * for 'name'. It will recursively try to resolve the | ||
880 | * authority for a given name from the namestore. | ||
881 | * | ||
882 | * @param cls the pending query | ||
883 | * @param key the key of the zone we did the lookup | ||
884 | * @param expiration expiration date of the record data set in the namestore | ||
885 | * @param name the name for which we need an authority | ||
886 | * @param rd_count the number of records with 'name' | ||
887 | * @param rd the record data | ||
888 | * @param signature the signature of the authority for the record data | ||
889 | */ | ||
890 | static void | ||
891 | process_delegation_result_ns(void* cls, | ||
892 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *key, | ||
893 | struct GNUNET_TIME_Absolute expiration, | ||
894 | const char *name, | ||
895 | unsigned int rd_count, | ||
896 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
897 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
898 | { | ||
899 | struct ResolverHandle *rh; | ||
900 | struct GNUNET_TIME_Relative remaining_time; | ||
901 | GNUNET_HashCode zone; | ||
902 | char* new_name; | ||
903 | |||
904 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %d records from authority lookup\n", | ||
905 | rd_count); | ||
906 | |||
907 | rh = (struct ResolverHandle *)cls; | ||
908 | GNUNET_CRYPTO_hash(key, | ||
909 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
910 | &zone); | ||
911 | remaining_time = GNUNET_TIME_absolute_get_remaining (expiration); | ||
912 | |||
913 | rh->status = 0; | ||
914 | |||
915 | if (name != NULL) | ||
916 | { | ||
917 | rh->status |= EXISTS; | ||
918 | } | ||
919 | |||
920 | if (remaining_time.rel_value == 0) | ||
921 | { | ||
922 | rh->status |= EXPIRED; | ||
923 | } | ||
924 | |||
925 | /** | ||
926 | * No authority found in namestore. | ||
927 | */ | ||
928 | if (rd_count == 0) | ||
929 | { | ||
930 | /** | ||
931 | * We did not find an authority in the namestore | ||
932 | */ | ||
933 | |||
934 | /** | ||
935 | * No PKEY in zone. | ||
936 | * Promote this authority back to a name maybe it is | ||
937 | * our record. | ||
938 | */ | ||
939 | if (strcmp(rh->name, "") == 0) | ||
940 | { | ||
941 | /* simply promote back */ | ||
942 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
943 | "Promoting %s back to name\n", rh->authority_name); | ||
944 | strcpy(rh->name, rh->authority_name); | ||
945 | } | ||
946 | else | ||
947 | { | ||
948 | /* add back to existing name */ | ||
949 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
950 | "Adding %s back to %s\n", | ||
951 | rh->authority_name, rh->name); | ||
952 | new_name = GNUNET_malloc(strlen(rh->name) | ||
953 | + strlen(rh->authority_name) + 2); | ||
954 | memset(new_name, 0, strlen(rh->name) + strlen(rh->authority_name) + 2); | ||
955 | strcpy(new_name, rh->name); | ||
956 | strcpy(new_name+strlen(new_name)+1, "."); | ||
957 | strcpy(new_name+strlen(new_name)+2, rh->authority_name); | ||
958 | GNUNET_free(rh->name); | ||
959 | rh->name = new_name; | ||
960 | } | ||
961 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
962 | return; | ||
963 | } | ||
964 | |||
965 | //Note only 1 pkey should have been returned.. anything else would be strange | ||
966 | /** | ||
967 | * We found an authority that may be able to help us | ||
968 | * move on with query | ||
969 | */ | ||
970 | int i; | ||
971 | for (i=0; i<rd_count;i++) | ||
972 | { | ||
973 | |||
974 | if (rd[i].record_type != GNUNET_GNS_RECORD_PKEY) | ||
975 | continue; | ||
976 | |||
977 | if ((GNUNET_TIME_absolute_get_remaining (rd[i].expiration)).rel_value | ||
978 | == 0) | ||
979 | { | ||
980 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This pkey is expired.\n"); | ||
981 | if (remaining_time.rel_value == 0) | ||
982 | { | ||
983 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
984 | "This dht entry is expired.\n"); | ||
985 | rh->authority_chain_head->fresh = 0; | ||
986 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
987 | return; | ||
988 | } | ||
989 | |||
990 | continue; | ||
991 | } | ||
992 | |||
993 | /** | ||
994 | * Resolve rest of query with new authority | ||
995 | */ | ||
996 | GNUNET_assert(rd[i].record_type == GNUNET_GNS_RECORD_PKEY); | ||
997 | memcpy(&rh->authority, rd[i].data, sizeof(GNUNET_HashCode)); | ||
998 | struct AuthorityChain *auth = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
999 | auth->zone = rh->authority; | ||
1000 | auth->name = GNUNET_malloc(strlen(rh->authority_name)+1); | ||
1001 | memset(auth->name, 0, strlen(rh->authority_name)+1); | ||
1002 | strcpy(auth->name, rh->authority_name); | ||
1003 | GNUNET_CONTAINER_DLL_insert (rh->authority_chain_head, | ||
1004 | rh->authority_chain_tail, | ||
1005 | auth); | ||
1006 | |||
1007 | /** | ||
1008 | * We are done with PKEY resolution if name is empty | ||
1009 | * else resolve again with new authority | ||
1010 | */ | ||
1011 | if (strcmp(rh->name, "") == 0) | ||
1012 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1013 | else | ||
1014 | resolve_delegation_ns(rh); | ||
1015 | return; | ||
1016 | } | ||
1017 | |||
1018 | /** | ||
1019 | * no answers found | ||
1020 | */ | ||
1021 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1022 | "Authority lookup successful but no PKEY... never get here\n"); | ||
1023 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1024 | } | ||
1025 | |||
1026 | |||
1027 | /** | ||
1028 | * Resolve the delegation chain for the request in our namestore | ||
1029 | * | ||
1030 | * @param rh the resolver handle | ||
1031 | */ | ||
1032 | static void | ||
1033 | resolve_delegation_ns(struct ResolverHandle *rh) | ||
1034 | { | ||
1035 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1036 | "Resolving delegation for %s\n", rh->name); | ||
1037 | pop_tld(rh->name, rh->authority_name); | ||
1038 | GNUNET_NAMESTORE_lookup_record(namestore_handle, | ||
1039 | &rh->authority, | ||
1040 | rh->authority_name, | ||
1041 | GNUNET_GNS_RECORD_PKEY, | ||
1042 | &process_delegation_result_ns, | ||
1043 | rh); | ||
1044 | |||
1045 | } | ||
1046 | |||
1047 | |||
1048 | /** | ||
1049 | * Lookup of a record in a specific zone | ||
1050 | * calls lookup result processor on result | ||
1051 | * | ||
1052 | * @param zone the root zone | ||
1053 | * @param record_type the record type to look up | ||
1054 | * @param proc the processor to call | ||
1055 | * @param cls the closure to pass to proc | ||
1056 | */ | ||
1057 | void | ||
1058 | gns_resolver_lookup_record(GNUNET_HashCode zone, | ||
1059 | uint32_t record_type, | ||
1060 | const char* name, | ||
1061 | RecordLookupProcessor proc, | ||
1062 | void* cls) | ||
1063 | { | ||
1064 | struct ResolverHandle *rh; | ||
1065 | struct RecordLookupHandle* rlh; | ||
1066 | |||
1067 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1068 | "Starting resolution for %s (type=%d)!\n", | ||
1069 | name, record_type); | ||
1070 | |||
1071 | rlh = GNUNET_malloc(sizeof(struct RecordLookupHandle)); | ||
1072 | rh = GNUNET_malloc(sizeof (struct ResolverHandle)); | ||
1073 | |||
1074 | rh->authority = zone; | ||
1075 | rh->proc_cls = rlh; | ||
1076 | rh->name = GNUNET_malloc(strlen(name) | ||
1077 | - strlen(GNUNET_GNS_TLD)); | ||
1078 | memset(rh->name, 0, | ||
1079 | strlen(name)-strlen(GNUNET_GNS_TLD)); | ||
1080 | memcpy(rh->name, name, | ||
1081 | strlen(name)-strlen(GNUNET_GNS_TLD) - 1); | ||
1082 | rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); | ||
1083 | rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
1084 | rh->authority_chain_head->prev = NULL; | ||
1085 | rh->authority_chain_head->next = NULL; | ||
1086 | rh->authority_chain_tail = rh->authority_chain_head; | ||
1087 | rh->authority_chain_head->zone = zone; | ||
1088 | |||
1089 | rlh->record_type = record_type; | ||
1090 | rlh->name = (char*)name; //FIXME | ||
1091 | rlh->proc = proc; | ||
1092 | rlh->proc_cls = cls; | ||
1093 | |||
1094 | rh->proc = &handle_delegation_ns; | ||
1095 | resolve_delegation_ns(rh); | ||
1096 | } | ||
1097 | |||
1098 | /******** END Record Resolver ***********/ | ||
1099 | |||
1100 | |||
1101 | static void | ||
1102 | process_pseu_result_ns_shorten(void *cls, | ||
1103 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, | ||
1104 | struct GNUNET_TIME_Absolute expire, | ||
1105 | const char *name, | ||
1106 | unsigned int rd_len, | ||
1107 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
1108 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
1109 | { | ||
1110 | struct ResolverHandle *rh = | ||
1111 | (struct ResolverHandle *)cls; | ||
1112 | struct GNUNET_TIME_Relative remaining_time; | ||
1113 | |||
1114 | GNUNET_TIME_absolute_get_remaining (expire); | ||
1115 | rh->status = 0; | ||
1116 | |||
1117 | if (name != NULL) | ||
1118 | { | ||
1119 | rh->status |= EXISTS; | ||
1120 | } | ||
1121 | |||
1122 | if (remaining_time.rel_value == 0) | ||
1123 | { | ||
1124 | rh->status |= EXPIRED; | ||
1125 | } | ||
1126 | |||
1127 | rh->proc(rh->proc_cls, rh, rd_len, rd); | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /** | ||
1132 | * Function called when we get a result from the dht | ||
1133 | * for our record query | ||
1134 | * | ||
1135 | * @param cls the request handle | ||
1136 | * @param exp lifetime | ||
1137 | * @param key the key the record was stored under | ||
1138 | * @param get_path get path | ||
1139 | * @param get_path_length get path length | ||
1140 | * @param put_path put path | ||
1141 | * @param put_path_length put path length | ||
1142 | * @param type the block type | ||
1143 | * @param size the size of the record | ||
1144 | * @param data the record data | ||
1145 | */ | ||
1146 | static void | ||
1147 | process_pseu_dht_result(void* cls, | ||
1148 | struct GNUNET_TIME_Absolute exp, | ||
1149 | const GNUNET_HashCode * key, | ||
1150 | const struct GNUNET_PeerIdentity *get_path, | ||
1151 | unsigned int get_path_length, | ||
1152 | const struct GNUNET_PeerIdentity *put_path, | ||
1153 | unsigned int put_path_length, | ||
1154 | enum GNUNET_BLOCK_Type type, | ||
1155 | size_t size, const void *data) | ||
1156 | { | ||
1157 | struct ResolverHandle *rh; | ||
1158 | struct RecordLookupHandle *rlh; | ||
1159 | struct GNSNameRecordBlock *nrb; | ||
1160 | uint32_t num_records; | ||
1161 | char* name = NULL; | ||
1162 | char* rd_data = (char*)data; | ||
1163 | int i; | ||
1164 | int rd_size; | ||
1165 | |||
1166 | GNUNET_HashCode zone, name_hash; | ||
1167 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "got PSEU dht result (size=%d)\n", size); | ||
1168 | |||
1169 | if (data == NULL) | ||
1170 | return; | ||
1171 | |||
1172 | //FIXME maybe check expiration here, check block type | ||
1173 | |||
1174 | rh = (struct ResolverHandle *)cls; | ||
1175 | rlh = (struct RecordLookupHandle *) rh->proc_cls; | ||
1176 | nrb = (struct GNSNameRecordBlock*)data; | ||
1177 | |||
1178 | /* stop lookup and timeout task */ | ||
1179 | GNUNET_DHT_get_stop (rh->get_handle); | ||
1180 | GNUNET_SCHEDULER_cancel(rh->dht_timeout_task); | ||
1181 | |||
1182 | rh->get_handle = NULL; | ||
1183 | name = (char*)&nrb[1]; | ||
1184 | num_records = ntohl(nrb->rd_count); | ||
1185 | { | ||
1186 | struct GNUNET_NAMESTORE_RecordData rd[num_records]; | ||
1187 | |||
1188 | rd_data += strlen(name) + 1 + sizeof(struct GNSNameRecordBlock); | ||
1189 | rd_size = size - strlen(name) - 1 - sizeof(struct GNSNameRecordBlock); | ||
1190 | |||
1191 | if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_size, | ||
1192 | rd_data, | ||
1193 | num_records, | ||
1194 | rd)) | ||
1195 | { | ||
1196 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Error deserializing data!\n"); | ||
1197 | return; | ||
1198 | } | ||
1199 | |||
1200 | for (i=0; i<num_records; i++) | ||
1201 | { | ||
1202 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1203 | "Got name: %s (wanted %s)\n", name, rh->name); | ||
1204 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1205 | "Got type: %d\n", | ||
1206 | rd[i].record_type); | ||
1207 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1208 | "Got data length: %d\n", rd[i].data_size); | ||
1209 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1210 | "Got flag %d\n", rd[i].flags); | ||
1211 | |||
1212 | if ((strcmp(name, "+") == 0) && | ||
1213 | (rd[i].record_type == GNUNET_GNS_RECORD_PSEU)) | ||
1214 | { | ||
1215 | rh->answered++; | ||
1216 | } | ||
1217 | |||
1218 | } | ||
1219 | |||
1220 | GNUNET_CRYPTO_hash(name, strlen(name), &name_hash); | ||
1221 | GNUNET_CRYPTO_hash_xor(key, &name_hash, &zone); | ||
1222 | |||
1223 | /** | ||
1224 | * FIXME check pubkey against existing key in namestore? | ||
1225 | * https://gnunet.org/bugs/view.php?id=2179 | ||
1226 | */ | ||
1227 | |||
1228 | /* Save to namestore */ | ||
1229 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
1230 | &nrb->public_key, | ||
1231 | name, | ||
1232 | exp, | ||
1233 | num_records, | ||
1234 | rd, | ||
1235 | &nrb->signature, | ||
1236 | &on_namestore_record_put_result, //cont | ||
1237 | NULL); //cls | ||
1238 | |||
1239 | if (rh->answered) | ||
1240 | rh->proc(rh->proc_cls, rh, num_records, rd); | ||
1241 | else | ||
1242 | rh->proc(rh->proc_cls, rh, 0, NULL); | ||
1243 | } | ||
1244 | |||
1245 | } | ||
1246 | |||
1247 | |||
1248 | /** | ||
1249 | * Start DHT lookup for a PSEUdonym record in | ||
1250 | * rh->authority's zone | ||
1251 | * | ||
1252 | * @param rh the pending gns query | ||
1253 | */ | ||
1254 | static void | ||
1255 | resolve_pseu_dht(struct ResolverHandle *rh) | ||
1256 | { | ||
1257 | uint32_t xquery; | ||
1258 | GNUNET_HashCode name_hash; | ||
1259 | GNUNET_HashCode lookup_key; | ||
1260 | |||
1261 | GNUNET_CRYPTO_hash("+", | ||
1262 | strlen("+"), | ||
1263 | &name_hash); | ||
1264 | |||
1265 | GNUNET_CRYPTO_hash_xor(&name_hash, &rh->authority, &lookup_key); | ||
1266 | |||
1267 | rh->dht_timeout_task = GNUNET_SCHEDULER_add_delayed (DHT_LOOKUP_TIMEOUT, | ||
1268 | &dht_lookup_timeout, | ||
1269 | rh); | ||
1270 | |||
1271 | xquery = htonl(GNUNET_GNS_RECORD_PSEU); | ||
1272 | |||
1273 | rh->get_handle = GNUNET_DHT_get_start(dht_handle, | ||
1274 | DHT_OPERATION_TIMEOUT, | ||
1275 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
1276 | &lookup_key, | ||
1277 | DHT_GNS_REPLICATION_LEVEL, | ||
1278 | GNUNET_DHT_RO_NONE, | ||
1279 | &xquery, | ||
1280 | sizeof(xquery), | ||
1281 | &process_pseu_dht_result, | ||
1282 | rh); | ||
1283 | |||
1284 | } | ||
1285 | |||
1286 | //Prototype | ||
1287 | static void | ||
1288 | handle_shorten_pseu_ns_result(void* cls, | ||
1289 | struct ResolverHandle *rh, | ||
1290 | uint32_t rd_count, | ||
1291 | const struct GNUNET_NAMESTORE_RecordData *rd); | ||
1292 | |||
1293 | static void | ||
1294 | process_zone_to_name_shorten(void *cls, | ||
1295 | const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key, | ||
1296 | struct GNUNET_TIME_Absolute expire, | ||
1297 | const char *name, | ||
1298 | unsigned int rd_len, | ||
1299 | const struct GNUNET_NAMESTORE_RecordData *rd, | ||
1300 | const struct GNUNET_CRYPTO_RsaSignature *signature) | ||
1301 | { | ||
1302 | struct ResolverHandle *rh = | ||
1303 | (struct ResolverHandle *)cls; | ||
1304 | struct NameShortenHandle* nsh = (struct NameShortenHandle*)rh->proc_cls; | ||
1305 | struct AuthorityChain *next_authority; | ||
1306 | |||
1307 | char* result; | ||
1308 | char* next_authority_name; | ||
1309 | size_t answer_len; | ||
1310 | |||
1311 | /* we found a match in our own zone */ | ||
1312 | if (rd_len != 0) | ||
1313 | { | ||
1314 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1315 | "result strlen %d\n", strlen(name)); | ||
1316 | answer_len = strlen(rh->name) + strlen(name) + strlen(GNUNET_GNS_TLD) + 3; | ||
1317 | result = GNUNET_malloc(answer_len); | ||
1318 | memset(result, 0, answer_len); | ||
1319 | strcpy(result, rh->name); | ||
1320 | strcpy(result+strlen(rh->name), "."); | ||
1321 | strcpy(result+strlen(rh->name)+1, name); | ||
1322 | strcpy(result+strlen(rh->name)+strlen(name)+1, "."); | ||
1323 | strcpy(result+strlen(rh->name)+strlen(name)+2, GNUNET_GNS_TLD); | ||
1324 | |||
1325 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1326 | "Sending shorten result %s\n", result); | ||
1327 | |||
1328 | nsh->proc(nsh->proc_cls, result); | ||
1329 | free_resolver_handle(rh); | ||
1330 | GNUNET_free(result); | ||
1331 | } | ||
1332 | else if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone, | ||
1333 | &rh->authority_chain_tail->zone)) | ||
1334 | { | ||
1335 | /* our zone, just append .gnunet */ | ||
1336 | answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2; | ||
1337 | result = GNUNET_malloc(answer_len); | ||
1338 | memset(result, 0, answer_len); | ||
1339 | strcpy(result, rh->name); | ||
1340 | strcpy(result+strlen(rh->name), "."); | ||
1341 | strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD); | ||
1342 | |||
1343 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1344 | "Our zone: Sending name as shorten result %s\n", rh->name); | ||
1345 | |||
1346 | nsh->proc(nsh->proc_cls, result); //FIXME +.gnunet! | ||
1347 | free_resolver_handle(rh); | ||
1348 | GNUNET_free(result); | ||
1349 | } | ||
1350 | else | ||
1351 | { | ||
1352 | /** | ||
1353 | * No PSEU found. | ||
1354 | * continue with next authority | ||
1355 | */ | ||
1356 | next_authority = rh->authority_chain_head; | ||
1357 | next_authority_name = GNUNET_malloc(strlen(rh->name)+ | ||
1358 | strlen(next_authority->name) + 2); | ||
1359 | memset(next_authority_name, 0, strlen(rh->name)+ | ||
1360 | strlen(next_authority->name) + 2); | ||
1361 | strcpy(next_authority_name, rh->name); | ||
1362 | strcpy(next_authority_name+strlen(rh->name)+1, "."); | ||
1363 | strcpy(next_authority_name+strlen(rh->name)+2, next_authority->name); | ||
1364 | |||
1365 | GNUNET_free(rh->name); | ||
1366 | rh->name = next_authority_name; | ||
1367 | GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, | ||
1368 | rh->authority_chain_tail, | ||
1369 | next_authority); | ||
1370 | |||
1371 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, | ||
1372 | &rh->authority_chain_tail->zone, | ||
1373 | &rh->authority_chain_head->zone, | ||
1374 | &process_zone_to_name_shorten, | ||
1375 | rh); | ||
1376 | } | ||
1377 | } | ||
1378 | |||
1379 | |||
1380 | /** | ||
1381 | * Process result from namestore PSEU lookup | ||
1382 | * for shorten operation | ||
1383 | * | ||
1384 | * @param cls the client shorten handle | ||
1385 | * @param rh the resolver handle | ||
1386 | * @param rd_count number of results (0 if none found) | ||
1387 | * @param rd data (NULL if none found) | ||
1388 | */ | ||
1389 | static void | ||
1390 | handle_pseu_ns_result_shorten(void* cls, | ||
1391 | struct ResolverHandle *rh, | ||
1392 | uint32_t rd_len, | ||
1393 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
1394 | { | ||
1395 | struct NameShortenHandle* nsh = (struct NameShortenHandle*) cls; | ||
1396 | struct AuthorityChain *next_authority; | ||
1397 | char* pseu; | ||
1398 | char* result; | ||
1399 | char* new_name; | ||
1400 | size_t answer_len; | ||
1401 | int i; | ||
1402 | |||
1403 | /** | ||
1404 | * PSEU found | ||
1405 | */ | ||
1406 | if (rd_len != 0) | ||
1407 | { | ||
1408 | for (i=0; i < rd_len; i++) | ||
1409 | { | ||
1410 | if (rd[i].record_type == GNUNET_GNS_RECORD_PSEU) | ||
1411 | { | ||
1412 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1413 | "Found PSEU %s len %d\n", (char*) rd[i].data, | ||
1414 | strlen((char*) rd[i].data)); | ||
1415 | break; | ||
1416 | } | ||
1417 | } | ||
1418 | |||
1419 | pseu = (char*) rd[i].data; | ||
1420 | answer_len = strlen(rh->name) + strlen(pseu) + strlen(GNUNET_GNS_TLD) + 3; | ||
1421 | result = GNUNET_malloc(answer_len); | ||
1422 | memset(result, 0, answer_len); | ||
1423 | strcpy(result, rh->name); | ||
1424 | strcpy(result+strlen(rh->name), "."); | ||
1425 | strcpy(result+strlen(rh->name)+1, pseu); | ||
1426 | strcpy(result+strlen(rh->name)+strlen(pseu)+1, "."); | ||
1427 | strcpy(result+strlen(rh->name)+strlen(pseu)+2, GNUNET_GNS_TLD); | ||
1428 | |||
1429 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1430 | "Sending shorten result %s\n", result); | ||
1431 | |||
1432 | nsh->proc(nsh->proc_cls, result); | ||
1433 | free_resolver_handle(rh); | ||
1434 | GNUNET_free(result); | ||
1435 | return; | ||
1436 | } | ||
1437 | |||
1438 | /** | ||
1439 | * No PSEU found. | ||
1440 | * continue with next authority | ||
1441 | * Note that we never have <2 authorities | ||
1442 | * in our list at this point since tail is always our root | ||
1443 | * And we filter fot this in handle_delegation_ns_shorten | ||
1444 | */ | ||
1445 | next_authority = rh->authority_chain_head; | ||
1446 | new_name = GNUNET_malloc(strlen(rh->name)+ | ||
1447 | strlen(next_authority->name) + 2); | ||
1448 | memset(new_name, 0, strlen(rh->name)+ | ||
1449 | strlen(next_authority->name) + 2); | ||
1450 | strcpy(new_name, rh->name); | ||
1451 | strcpy(new_name+strlen(rh->name)+1, "."); | ||
1452 | strcpy(new_name+strlen(rh->name)+2, next_authority->name); | ||
1453 | |||
1454 | GNUNET_free(rh->name); | ||
1455 | rh->name = new_name; | ||
1456 | GNUNET_CONTAINER_DLL_remove(rh->authority_chain_head, | ||
1457 | rh->authority_chain_tail, | ||
1458 | next_authority); | ||
1459 | |||
1460 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, | ||
1461 | &rh->authority_chain_tail->zone, | ||
1462 | &rh->authority_chain_head->zone, | ||
1463 | &process_zone_to_name_shorten, | ||
1464 | rh); | ||
1465 | |||
1466 | } | ||
1467 | |||
1468 | |||
1469 | |||
1470 | /** | ||
1471 | * Process result from namestore delegation lookup | ||
1472 | * for shorten operation | ||
1473 | * | ||
1474 | * @param cls the client shorten handle | ||
1475 | * @param rh the resolver handle | ||
1476 | * @param rd_count number of results (0) | ||
1477 | * @param rd data (NULL) | ||
1478 | */ | ||
1479 | void | ||
1480 | handle_delegation_ns_shorten(void* cls, | ||
1481 | struct ResolverHandle *rh, | ||
1482 | uint32_t rd_count, | ||
1483 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
1484 | { | ||
1485 | struct NameShortenHandle *nsh; | ||
1486 | char* result; | ||
1487 | size_t answer_len; | ||
1488 | |||
1489 | nsh = (struct NameShortenHandle *)cls; | ||
1490 | |||
1491 | /** | ||
1492 | * At this point rh->name contains the part of the name | ||
1493 | * that we do not have a PKEY in our namestore to resolve. | ||
1494 | * The authority chain in the resolver handle is now | ||
1495 | * useful to backtrack if needed | ||
1496 | */ | ||
1497 | |||
1498 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1499 | "PKEY resolved as far as possible in ns up to %s!\n", rh->name); | ||
1500 | |||
1501 | if (GNUNET_CRYPTO_hash_cmp(&rh->authority_chain_head->zone, | ||
1502 | &rh->authority_chain_tail->zone) == 0) | ||
1503 | { | ||
1504 | /** | ||
1505 | * This is our zone append .gnunet unless name is empty | ||
1506 | * (it shouldn't be, usually FIXME what happens if we | ||
1507 | * shorten to our zone to a "" record??) | ||
1508 | **/ | ||
1509 | |||
1510 | answer_len = strlen(rh->name) + strlen(GNUNET_GNS_TLD) + 2; | ||
1511 | result = GNUNET_malloc(answer_len); | ||
1512 | memset(result, 0, answer_len); | ||
1513 | strcpy(result, rh->name); | ||
1514 | strcpy(result+strlen(rh->name), "."); | ||
1515 | strcpy(result+strlen(rh->name)+1, GNUNET_GNS_TLD); | ||
1516 | |||
1517 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1518 | "Our zone: Sending name as shorten result %s\n", rh->name); | ||
1519 | |||
1520 | nsh->proc(nsh->proc_cls, result); //FIXME +.gnunet! | ||
1521 | free_resolver_handle(rh); | ||
1522 | GNUNET_free(result); | ||
1523 | return; | ||
1524 | } | ||
1525 | |||
1526 | /* backtrack authorities for names */ | ||
1527 | GNUNET_NAMESTORE_zone_to_name (namestore_handle, | ||
1528 | &rh->authority_chain_tail->zone, //ours | ||
1529 | &rh->authority_chain_head->zone, | ||
1530 | &process_zone_to_name_shorten, | ||
1531 | rh); | ||
1532 | |||
1533 | } | ||
1534 | |||
1535 | /** | ||
1536 | * Shorten api from resolver | ||
1537 | * | ||
1538 | * @param zone the zone to use | ||
1539 | * @param name the name to shorten | ||
1540 | * @param proc the processor to call with result | ||
1541 | * @param cls closure to pass to proc | ||
1542 | */ | ||
1543 | void | ||
1544 | gns_resolver_shorten_name(GNUNET_HashCode zone, | ||
1545 | const char* name, | ||
1546 | ShortenResultProcessor proc, | ||
1547 | void* cls) | ||
1548 | { | ||
1549 | struct ResolverHandle *rh; | ||
1550 | struct NameShortenHandle *nsh; | ||
1551 | |||
1552 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1553 | "Starting shorten for %s!\n", name); | ||
1554 | |||
1555 | nsh = GNUNET_malloc(sizeof (struct NameShortenHandle)); | ||
1556 | rh = GNUNET_malloc(sizeof (struct ResolverHandle)); | ||
1557 | rh->authority = zone; | ||
1558 | rh->name = GNUNET_malloc(strlen(name) | ||
1559 | - strlen(GNUNET_GNS_TLD)); | ||
1560 | memset(rh->name, 0, | ||
1561 | strlen(name)-strlen(GNUNET_GNS_TLD)); | ||
1562 | memcpy(rh->name, name, | ||
1563 | strlen(name)-strlen(GNUNET_GNS_TLD)-1); | ||
1564 | |||
1565 | rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH); | ||
1566 | rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
1567 | rh->authority_chain_tail = rh->authority_chain_head; | ||
1568 | rh->authority_chain_head->zone = zone; | ||
1569 | rh->proc = &handle_delegation_ns_shorten; | ||
1570 | rh->proc_cls = nsh; | ||
1571 | |||
1572 | nsh->proc = proc; | ||
1573 | nsh->proc_cls = cls; | ||
1574 | |||
1575 | /* Start delegation resolution in our namestore */ | ||
1576 | resolve_delegation_ns(rh); | ||
1577 | } | ||
1578 | |||
1579 | /*********** END NAME SHORTEN ********************/ | ||
1580 | |||
1581 | |||
1582 | /** | ||
1583 | * Process result from namestore delegation lookup | ||
1584 | * for get authority operation | ||
1585 | * | ||
1586 | * @param cls the client get auth handle | ||
1587 | * @param rh the resolver handle | ||
1588 | * @param rd_count number of results (0) | ||
1589 | * @param rd data (NULL) | ||
1590 | */ | ||
1591 | void | ||
1592 | handle_delegation_result_ns_get_auth(void* cls, | ||
1593 | struct ResolverHandle *rh, | ||
1594 | uint32_t rd_count, | ||
1595 | const struct GNUNET_NAMESTORE_RecordData *rd) | ||
1596 | { | ||
1597 | struct GetNameAuthorityHandle* nah; | ||
1598 | char* result; | ||
1599 | size_t answer_len; | ||
1600 | |||
1601 | nah = (struct GetNameAuthorityHandle*) rh->proc_cls; | ||
1602 | |||
1603 | /** | ||
1604 | * At this point rh->name contains the part of the name | ||
1605 | * that we do not have a PKEY in our namestore to resolve. | ||
1606 | * The authority chain in the resolver handle is now | ||
1607 | * useful to backtrack if needed | ||
1608 | */ | ||
1609 | |||
1610 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1611 | "PKEY resolved as far as possible in ns up to %s!\n", rh->name); | ||
1612 | |||
1613 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1614 | "Building response!\n"); | ||
1615 | if (is_canonical(rh->name)) | ||
1616 | { | ||
1617 | /** | ||
1618 | * We successfully resolved the authority in the ns | ||
1619 | * FIXME for our purposes this is fine | ||
1620 | * but maybe we want to have an api that also looks | ||
1621 | * into the dht (i.e. option in message) | ||
1622 | **/ | ||
1623 | if (strlen(rh->name) > strlen(nah->name)) | ||
1624 | { | ||
1625 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1626 | "Record name longer than original lookup name... odd!\n"); | ||
1627 | //FIXME to sth here | ||
1628 | } | ||
1629 | |||
1630 | answer_len = strlen(nah->name) - strlen(rh->name) | ||
1631 | + strlen(GNUNET_GNS_TLD) + 1; | ||
1632 | result = GNUNET_malloc(answer_len); | ||
1633 | memset(result, 0, answer_len); | ||
1634 | strcpy(result, nah->name + strlen(rh->name) + 1); | ||
1635 | |||
1636 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1637 | "Got authority result %s\n", result); | ||
1638 | |||
1639 | nah->proc(nah->proc_cls, result); | ||
1640 | free_resolver_handle(rh); | ||
1641 | GNUNET_free(result); | ||
1642 | GNUNET_free(nah); | ||
1643 | } | ||
1644 | else | ||
1645 | { | ||
1646 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
1647 | "Unable to resolve authority for remaining %s!\n", rh->name); | ||
1648 | nah->proc(nah->proc_cls, ""); | ||
1649 | free_resolver_handle(rh); | ||
1650 | GNUNET_free(nah); | ||
1651 | } | ||
1652 | |||
1653 | |||
1654 | } | ||
1655 | |||
1656 | |||
1657 | /** | ||
1658 | * Tries to resolve the authority for name | ||
1659 | * in our namestore | ||
1660 | * | ||
1661 | * @param zone the root zone to look up for | ||
1662 | * @param name the name to lookup up | ||
1663 | * @param proc the processor to call when finished | ||
1664 | * @param cls the closure to pass to the processor | ||
1665 | */ | ||
1666 | void | ||
1667 | gns_resolver_get_authority(GNUNET_HashCode zone, | ||
1668 | const char* name, | ||
1669 | GetAuthorityResultProcessor proc, | ||
1670 | void* cls) | ||
1671 | { | ||
1672 | struct ResolverHandle *rh; | ||
1673 | struct GetNameAuthorityHandle *nah; | ||
1674 | |||
1675 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1676 | "Starting authority resolution for %s!\n", name); | ||
1677 | |||
1678 | nah = GNUNET_malloc(sizeof (struct GetNameAuthorityHandle)); | ||
1679 | rh = GNUNET_malloc(sizeof (struct ResolverHandle)); | ||
1680 | rh->authority = zone; | ||
1681 | |||
1682 | rh->name = GNUNET_malloc(strlen(name) | ||
1683 | - strlen(GNUNET_GNS_TLD)); | ||
1684 | memset(rh->name, 0, | ||
1685 | strlen(name)-strlen(GNUNET_GNS_TLD)); | ||
1686 | memcpy(rh->name, name, | ||
1687 | strlen(name)-strlen(GNUNET_GNS_TLD) - 1); | ||
1688 | |||
1689 | nah->name = GNUNET_malloc(strlen(name)+1); | ||
1690 | memset(nah->name, 0, | ||
1691 | strlen(name)+1); | ||
1692 | strcpy(nah->name, name); | ||
1693 | |||
1694 | rh->authority_name = GNUNET_malloc(MAX_DNS_LABEL_LENGTH); | ||
1695 | |||
1696 | rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain)); | ||
1697 | rh->authority_chain_tail = rh->authority_chain_head; | ||
1698 | rh->authority_chain_head->zone = zone; | ||
1699 | rh->proc = &handle_delegation_result_ns_get_auth; | ||
1700 | rh->proc_cls = (void*)nah; | ||
1701 | |||
1702 | nah->proc = proc; | ||
1703 | nah->proc_cls = cls; | ||
1704 | |||
1705 | /* Start delegation resolution in our namestore */ | ||
1706 | resolve_delegation_ns(rh); | ||
1707 | |||
1708 | } | ||
1709 | |||
1710 | /******** END GET AUTHORITY *************/ | ||
1711 | |||
1712 | /* end of gns_resolver.c */ | ||
diff --git a/src/gns/gnunet-service-gns_resolver.h b/src/gns/gnunet-service-gns_resolver.h new file mode 100644 index 000000000..2b0c4755d --- /dev/null +++ b/src/gns/gnunet-service-gns_resolver.h | |||
@@ -0,0 +1,226 @@ | |||
1 | #ifndef GNS_RESOLVER_H | ||
2 | #define GNS_RESOLVER_H | ||
3 | |||
4 | #include "gns.h" | ||
5 | |||
6 | #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) | ||
7 | #define DHT_LOOKUP_TIMEOUT DHT_OPERATION_TIMEOUT | ||
8 | #define DHT_GNS_REPLICATION_LEVEL 5 | ||
9 | #define MAX_DNS_LABEL_LENGTH 63 | ||
10 | |||
11 | /* | ||
12 | * DLL to hold the authority chain | ||
13 | * we had to pass in the resolution process | ||
14 | */ | ||
15 | struct AuthorityChain | ||
16 | { | ||
17 | struct AuthorityChain *prev; | ||
18 | |||
19 | struct AuthorityChain *next; | ||
20 | |||
21 | /* the zone hash of the authority */ | ||
22 | GNUNET_HashCode zone; | ||
23 | |||
24 | /* (local) name of the authority */ | ||
25 | char* name; | ||
26 | |||
27 | /* was the ns entry fresh */ | ||
28 | int fresh; | ||
29 | }; | ||
30 | |||
31 | /* handle to a resolution process */ | ||
32 | struct ResolverHandle; | ||
33 | |||
34 | /** | ||
35 | * processor for a resultion result | ||
36 | * | ||
37 | * @param cls the closure | ||
38 | * @param rh the resolution handle | ||
39 | * @param rd_count number of results | ||
40 | * @pram rd resukt data | ||
41 | */ | ||
42 | typedef void (*RecordLookupProcessor) (void *cls, | ||
43 | uint32_t rd_count, | ||
44 | const struct GNUNET_NAMESTORE_RecordData *rd); | ||
45 | |||
46 | |||
47 | /** | ||
48 | * processor for a shorten result | ||
49 | * | ||
50 | * @param cls the closure | ||
51 | * @param name shortened name | ||
52 | */ | ||
53 | typedef void (*ShortenResultProcessor) (void *cls, const char* name); | ||
54 | |||
55 | |||
56 | /** | ||
57 | * processor for an authority result | ||
58 | * | ||
59 | * @param cls the closure | ||
60 | * @param name name | ||
61 | */ | ||
62 | typedef void (*GetAuthorityResultProcessor) (void *cls, const char* name); | ||
63 | |||
64 | /** | ||
65 | * processor for a resultion result | ||
66 | * | ||
67 | * @param cls the closure | ||
68 | * @param rh the resolution handle | ||
69 | * @param rd_count number of results | ||
70 | * @param rd result data | ||
71 | */ | ||
72 | typedef void (*ResolutionResultProcessor) (void *cls, | ||
73 | struct ResolverHandle *rh, | ||
74 | uint32_t rd_count, | ||
75 | const struct GNUNET_NAMESTORE_RecordData *rd); | ||
76 | |||
77 | |||
78 | /** | ||
79 | * Resoltion status indicator | ||
80 | * EXISTS: the name to lookup exists | ||
81 | * EXPIRED: the name in the record expired | ||
82 | */ | ||
83 | enum ResolutionStatus | ||
84 | { | ||
85 | EXISTS = 1, | ||
86 | EXPIRED = 2 | ||
87 | }; | ||
88 | |||
89 | /** | ||
90 | * Handle to a currenty pending resolution | ||
91 | */ | ||
92 | struct ResolverHandle | ||
93 | { | ||
94 | /* The name to resolve */ | ||
95 | char *name; | ||
96 | |||
97 | /* has this query been answered? how many matches */ | ||
98 | int answered; | ||
99 | |||
100 | /* the authoritative zone to query */ | ||
101 | GNUNET_HashCode authority; | ||
102 | |||
103 | /* the name of the authoritative zone to query */ | ||
104 | char *authority_name; | ||
105 | |||
106 | /** | ||
107 | * we have an authority in namestore that | ||
108 | * may be able to resolve | ||
109 | */ | ||
110 | int authority_found; | ||
111 | |||
112 | /* a handle for dht lookups. should be NULL if no lookups are in progress */ | ||
113 | struct GNUNET_DHT_GetHandle *get_handle; | ||
114 | |||
115 | /* timeout task for dht lookups */ | ||
116 | GNUNET_SCHEDULER_TaskIdentifier dht_timeout_task; | ||
117 | |||
118 | /* called when resolution phase finishes */ | ||
119 | ResolutionResultProcessor proc; | ||
120 | |||
121 | /* closure passed to proc */ | ||
122 | void* proc_cls; | ||
123 | |||
124 | /* DLL to store the authority chain */ | ||
125 | struct AuthorityChain *authority_chain_head; | ||
126 | |||
127 | /* DLL to store the authority chain */ | ||
128 | struct AuthorityChain *authority_chain_tail; | ||
129 | |||
130 | /* status of the resolution result */ | ||
131 | enum ResolutionStatus status; | ||
132 | |||
133 | }; | ||
134 | |||
135 | |||
136 | /** | ||
137 | * Handle to a record lookup | ||
138 | */ | ||
139 | struct RecordLookupHandle | ||
140 | { | ||
141 | /* the record type to look up */ | ||
142 | enum GNUNET_GNS_RecordType record_type; | ||
143 | |||
144 | /* the name to look up */ | ||
145 | char *name; | ||
146 | |||
147 | /* Method to call on record resolution result */ | ||
148 | RecordLookupProcessor proc; | ||
149 | |||
150 | /* closure to pass to proc */ | ||
151 | void* proc_cls; | ||
152 | |||
153 | }; | ||
154 | |||
155 | |||
156 | /** | ||
157 | * Handle to a shorten context | ||
158 | */ | ||
159 | struct NameShortenHandle | ||
160 | { | ||
161 | |||
162 | |||
163 | /* Method to call on shorten result */ | ||
164 | ShortenResultProcessor proc; | ||
165 | |||
166 | /* closure to pass to proc */ | ||
167 | void* proc_cls; | ||
168 | |||
169 | }; | ||
170 | |||
171 | /** | ||
172 | * Handle to a get authority context | ||
173 | */ | ||
174 | struct GetNameAuthorityHandle | ||
175 | { | ||
176 | |||
177 | /* the name to look up authority for */ | ||
178 | char* name; | ||
179 | |||
180 | /* Method to call on result */ | ||
181 | GetAuthorityResultProcessor proc; | ||
182 | |||
183 | /* closure to pass to proc */ | ||
184 | void* proc_cls; | ||
185 | |||
186 | }; | ||
187 | |||
188 | |||
189 | /** | ||
190 | * Lookup of a record in a specific zone | ||
191 | * calls lookup result processor on result | ||
192 | * | ||
193 | * @param zone the root zone | ||
194 | * @param record_type the record type to look up | ||
195 | * @param proc the processor to call | ||
196 | * @param cls the closure to pass to proc | ||
197 | */ | ||
198 | void | ||
199 | gns_resolver_lookup_record(GNUNET_HashCode zone, | ||
200 | uint32_t record_type, | ||
201 | const char* name, | ||
202 | RecordLookupProcessor proc, | ||
203 | void* cls); | ||
204 | |||
205 | void | ||
206 | gns_resolver_shorten_name(GNUNET_HashCode zone, | ||
207 | const char* name, | ||
208 | ShortenResultProcessor proc, | ||
209 | void* cls); | ||
210 | |||
211 | /** | ||
212 | * Tries to resolve the authority for name | ||
213 | * in our namestore | ||
214 | * | ||
215 | * @param zone the root zone to look up for | ||
216 | * @param name the name to lookup up | ||
217 | * @param proc the processor to call when finished | ||
218 | * @param cls the closure to pass to the processor | ||
219 | */ | ||
220 | void | ||
221 | gns_resolver_get_authority(GNUNET_HashCode zone, | ||
222 | const char* name, | ||
223 | GetAuthorityResultProcessor proc, | ||
224 | void* cls); | ||
225 | |||
226 | #endif | ||
diff --git a/src/gns/test_gns_dht_shorten.c b/src/gns/test_gns_dht_shorten.c deleted file mode 100644 index 32d978290..000000000 --- a/src/gns/test_gns_dht_shorten.c +++ /dev/null | |||
@@ -1,500 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
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 | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file gns/test_gns_twopeer.c | ||
22 | * @brief base testcase for testing DHT service with | ||
23 | * two running peers. | ||
24 | * | ||
25 | * This testcase starts peers using the GNUNET_TESTING_daemons_start | ||
26 | * function call. On peer start, connects to the peers DHT service | ||
27 | * by calling GNUNET_DHT_connected. Once notified about all peers | ||
28 | * being started (by the peers_started_callback function), calls | ||
29 | * GNUNET_TESTING_connect_topology, which connects the peers in a | ||
30 | * "straight line" topology. On notification that all peers have | ||
31 | * been properly connected, calls the do_get function which initiates | ||
32 | * a GNUNET_DHT_get from the *second* peer. Once the GNUNET_DHT_get | ||
33 | * function starts, runs the do_put function to insert data at the first peer. | ||
34 | * If the GET is successful, schedules finish_testing | ||
35 | * to stop the test and shut down peers. If GET is unsuccessful | ||
36 | * after GET_TIMEOUT seconds, prints an error message and shuts down | ||
37 | * the peers. | ||
38 | */ | ||
39 | #include "platform.h" | ||
40 | #include "gnunet_testing_lib.h" | ||
41 | #include "gnunet_core_service.h" | ||
42 | #include "block_gns.h" | ||
43 | #include "gnunet_signatures.h" | ||
44 | #include "gnunet_namestore_service.h" | ||
45 | #include "../namestore/namestore.h" | ||
46 | #include "gnunet_dnsparser_lib.h" | ||
47 | #include "gnunet_dht_service.h" | ||
48 | #include "gnunet_gns_service.h" | ||
49 | |||
50 | /* DEFINES */ | ||
51 | #define VERBOSE GNUNET_YES | ||
52 | |||
53 | /* Timeout for entire testcase */ | ||
54 | #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10) | ||
55 | |||
56 | /* If number of peers not in config file, use this number */ | ||
57 | #define DEFAULT_NUM_PEERS 2 | ||
58 | |||
59 | /* test records to resolve */ | ||
60 | #define TEST_DOMAIN "www.alice.bob.gnunet" | ||
61 | #define TEST_IP "127.0.0.1" | ||
62 | #define TEST_RECORD_NAME "www" | ||
63 | |||
64 | #define TEST_AUTHORITY_NAME "bob" | ||
65 | #define TEST_AUTHORITY_ALICE "alice" | ||
66 | #define TEST_ALICE_PSEU "carol" | ||
67 | #define TEST_EXPECTED_RESULT "www.carol.gnunet" | ||
68 | |||
69 | #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) | ||
70 | |||
71 | /* Globals */ | ||
72 | |||
73 | /** | ||
74 | * Directory to store temp data in, defined in config file | ||
75 | */ | ||
76 | static char *test_directory; | ||
77 | |||
78 | struct GNUNET_TESTING_Daemon *d1; | ||
79 | |||
80 | |||
81 | /* Task handle to use to schedule test failure */ | ||
82 | GNUNET_SCHEDULER_TaskIdentifier die_task; | ||
83 | |||
84 | /* Global return value (0 for success, anything else for failure) */ | ||
85 | static int ok; | ||
86 | |||
87 | static struct GNUNET_NAMESTORE_Handle *namestore_handle; | ||
88 | |||
89 | static struct GNUNET_GNS_Handle *gns_handle; | ||
90 | |||
91 | static struct GNUNET_DHT_Handle *dht_handle; | ||
92 | |||
93 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
94 | |||
95 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded alice_pkey; | ||
96 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded bob_pkey; | ||
97 | struct GNUNET_CRYPTO_RsaPrivateKey *alice_key; | ||
98 | struct GNUNET_CRYPTO_RsaPrivateKey *bob_key; | ||
99 | |||
100 | /** | ||
101 | * Check whether peers successfully shut down. | ||
102 | */ | ||
103 | void | ||
104 | shutdown_callback (void *cls, const char *emsg) | ||
105 | { | ||
106 | if (emsg != NULL) | ||
107 | { | ||
108 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error on shutdown! ret=%d\n", ok); | ||
109 | if (ok == 0) | ||
110 | ok = 2; | ||
111 | } | ||
112 | |||
113 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "done(ret=%d)!\n", ok); | ||
114 | } | ||
115 | |||
116 | |||
117 | /** | ||
118 | * Called when gns shorten finishes | ||
119 | */ | ||
120 | static void | ||
121 | process_shorten_result(void* cls, const char* sname) | ||
122 | { | ||
123 | GNUNET_GNS_disconnect(gns_handle); | ||
124 | |||
125 | ok = 0; | ||
126 | |||
127 | if (sname == NULL) | ||
128 | { | ||
129 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
130 | "shorten test failed!\n"); | ||
131 | ok = 1; | ||
132 | } | ||
133 | else | ||
134 | { | ||
135 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
136 | "%s shortened to %s\n", (char*)cls, sname); | ||
137 | if (0 != strcmp(sname, TEST_EXPECTED_RESULT)) | ||
138 | { | ||
139 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
140 | "shorten test failed! (wanted: %s got: %s\n", | ||
141 | (char*)cls, sname); | ||
142 | ok = 1; | ||
143 | } | ||
144 | |||
145 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shorten test succeeded!\n"); | ||
146 | |||
147 | } | ||
148 | |||
149 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down peer1!\n"); | ||
150 | GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL, | ||
151 | GNUNET_YES, GNUNET_NO); | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * Function scheduled to be run on the successful start of services | ||
156 | * tries to look up the dns record for TEST_DOMAIN | ||
157 | */ | ||
158 | static void | ||
159 | commence_testing (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
160 | { | ||
161 | GNUNET_NAMESTORE_disconnect(namestore_handle, GNUNET_YES); | ||
162 | |||
163 | gns_handle = GNUNET_GNS_connect(cfg); | ||
164 | |||
165 | if (NULL == gns_handle) | ||
166 | { | ||
167 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
168 | "Failed to connect to GNS!\n"); | ||
169 | ok = 1; | ||
170 | } | ||
171 | |||
172 | GNUNET_GNS_shorten(gns_handle, TEST_DOMAIN, &process_shorten_result, | ||
173 | TEST_DOMAIN); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut | ||
178 | * down the peers without freeing memory associated with GET request. | ||
179 | */ | ||
180 | static void | ||
181 | end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
182 | { | ||
183 | |||
184 | if (d1 != NULL) | ||
185 | GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &shutdown_callback, NULL, | ||
186 | GNUNET_YES, GNUNET_NO); | ||
187 | GNUNET_SCHEDULER_cancel (die_task); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Check if the get_handle is being used, if so stop the request. Either | ||
192 | * way, schedule the end_badly_cont function which actually shuts down the | ||
193 | * test. | ||
194 | */ | ||
195 | static void | ||
196 | end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
197 | { | ||
198 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test with error: `%s'!\n", | ||
199 | (char *) cls); | ||
200 | GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL); | ||
201 | ok = 1; | ||
202 | } | ||
203 | |||
204 | |||
205 | static void | ||
206 | put_www_dht(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
207 | { | ||
208 | struct GNSNameRecordBlock *nrb; | ||
209 | GNUNET_HashCode name_hash; | ||
210 | GNUNET_HashCode xor_hash; | ||
211 | GNUNET_HashCode zone_hash; | ||
212 | uint32_t rd_payload_length; | ||
213 | char* nrb_data = NULL; | ||
214 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
215 | struct GNUNET_NAMESTORE_RecordData rd; | ||
216 | char* ip = TEST_IP; | ||
217 | struct in_addr *web = GNUNET_malloc(sizeof(struct in_addr)); | ||
218 | |||
219 | rd.expiration = GNUNET_TIME_absolute_get_forever (); | ||
220 | GNUNET_assert(1 == inet_pton (AF_INET, ip, web)); | ||
221 | rd.data_size = sizeof(struct in_addr); | ||
222 | rd.data = web; | ||
223 | rd.record_type = GNUNET_DNSPARSER_TYPE_A; | ||
224 | |||
225 | sig = GNUNET_NAMESTORE_create_signature(alice_key, | ||
226 | GNUNET_TIME_absolute_get_forever(), | ||
227 | TEST_RECORD_NAME, | ||
228 | &rd, 1); | ||
229 | rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd); | ||
230 | nrb = GNUNET_malloc(rd_payload_length + strlen(TEST_RECORD_NAME) + 1 | ||
231 | + sizeof(struct GNSNameRecordBlock)); | ||
232 | nrb->signature = *sig; | ||
233 | nrb->public_key = alice_pkey; | ||
234 | nrb->rd_count = htonl(1); | ||
235 | memset(&nrb[1], 0, strlen(TEST_RECORD_NAME) + 1); | ||
236 | memcpy(&nrb[1], TEST_RECORD_NAME, strlen(TEST_RECORD_NAME)); | ||
237 | nrb_data = (char*)&nrb[1]; | ||
238 | nrb_data += strlen(TEST_RECORD_NAME) + 1; | ||
239 | |||
240 | if (-1 == GNUNET_NAMESTORE_records_serialize (1, | ||
241 | &rd, | ||
242 | rd_payload_length, | ||
243 | nrb_data)) | ||
244 | { | ||
245 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); | ||
246 | ok = 3; | ||
247 | GNUNET_free (nrb); | ||
248 | return; | ||
249 | } | ||
250 | GNUNET_CRYPTO_hash(TEST_RECORD_NAME, strlen(TEST_RECORD_NAME), &name_hash); | ||
251 | GNUNET_CRYPTO_hash(&alice_pkey, | ||
252 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
253 | &zone_hash); | ||
254 | GNUNET_CRYPTO_hash_xor(&zone_hash, &name_hash, &xor_hash); | ||
255 | |||
256 | rd_payload_length += sizeof(struct GNSNameRecordBlock) + | ||
257 | strlen(TEST_RECORD_NAME) + 1; | ||
258 | GNUNET_DHT_put (dht_handle, &xor_hash, | ||
259 | 0, | ||
260 | GNUNET_DHT_RO_NONE, | ||
261 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
262 | rd_payload_length, | ||
263 | (char*)nrb, | ||
264 | rd.expiration, | ||
265 | DHT_OPERATION_TIMEOUT, | ||
266 | NULL, | ||
267 | NULL); | ||
268 | GNUNET_free (nrb); | ||
269 | GNUNET_SCHEDULER_add_delayed(TIMEOUT, &commence_testing, NULL); | ||
270 | } | ||
271 | |||
272 | |||
273 | static void | ||
274 | put_alice_pseu_dht(void *cls, int32_t success, const char *emsg) | ||
275 | { | ||
276 | struct GNSNameRecordBlock *nrb; | ||
277 | GNUNET_HashCode name_hash; | ||
278 | GNUNET_HashCode xor_hash; | ||
279 | GNUNET_HashCode zone_hash; | ||
280 | uint32_t rd_payload_length; | ||
281 | char* nrb_data = NULL; | ||
282 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
283 | struct GNUNET_NAMESTORE_RecordData rd; | ||
284 | |||
285 | rd.expiration = GNUNET_TIME_absolute_get_forever (); | ||
286 | rd.data_size = strlen(TEST_ALICE_PSEU); | ||
287 | rd.data = TEST_ALICE_PSEU; | ||
288 | rd.record_type = GNUNET_GNS_RECORD_PSEU; | ||
289 | |||
290 | sig = GNUNET_NAMESTORE_create_signature(alice_key, | ||
291 | GNUNET_TIME_absolute_get_forever(), | ||
292 | "+", //empty name for pseu | ||
293 | &rd, 1); | ||
294 | rd_payload_length = GNUNET_NAMESTORE_records_get_size (1, &rd); | ||
295 | nrb = GNUNET_malloc(rd_payload_length + strlen("") + 1 | ||
296 | + sizeof(struct GNSNameRecordBlock)); | ||
297 | nrb->signature = *sig; | ||
298 | nrb->public_key = alice_pkey; | ||
299 | nrb->rd_count = htonl(1); | ||
300 | memset(&nrb[1], 0, strlen("+") + 1); | ||
301 | memcpy(&nrb[1], "+", strlen("+")); | ||
302 | nrb_data = (char*)&nrb[1]; | ||
303 | nrb_data += strlen("+") + 1; | ||
304 | |||
305 | if (-1 == GNUNET_NAMESTORE_records_serialize (1, | ||
306 | &rd, | ||
307 | rd_payload_length, | ||
308 | nrb_data)) | ||
309 | { | ||
310 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Record serialization failed!\n"); | ||
311 | ok = 3; | ||
312 | GNUNET_free (nrb); | ||
313 | return; | ||
314 | } | ||
315 | GNUNET_CRYPTO_hash("+", strlen("+"), &name_hash); | ||
316 | GNUNET_CRYPTO_hash(&alice_pkey, | ||
317 | sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), | ||
318 | &zone_hash); | ||
319 | GNUNET_CRYPTO_hash_xor(&zone_hash, &name_hash, &xor_hash); | ||
320 | |||
321 | rd_payload_length += sizeof(struct GNSNameRecordBlock) + | ||
322 | strlen("+") + 1; | ||
323 | GNUNET_DHT_put (dht_handle, &xor_hash, | ||
324 | 0, | ||
325 | GNUNET_DHT_RO_NONE, | ||
326 | GNUNET_BLOCK_TYPE_GNS_NAMERECORD, | ||
327 | rd_payload_length, | ||
328 | (char*)nrb, | ||
329 | rd.expiration, | ||
330 | DHT_OPERATION_TIMEOUT, | ||
331 | NULL, | ||
332 | NULL); | ||
333 | GNUNET_free (nrb); | ||
334 | GNUNET_SCHEDULER_add_delayed(TIMEOUT, &put_www_dht, NULL); | ||
335 | } | ||
336 | |||
337 | static void | ||
338 | do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, | ||
339 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
340 | struct GNUNET_TESTING_Daemon *d, const char *emsg) | ||
341 | { | ||
342 | |||
343 | char* my_keyfile; | ||
344 | struct GNUNET_CRYPTO_RsaPrivateKey *my_key; | ||
345 | GNUNET_HashCode bob_hash; | ||
346 | GNUNET_HashCode alice_hash; | ||
347 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
348 | |||
349 | |||
350 | GNUNET_SCHEDULER_cancel (die_task); | ||
351 | |||
352 | /* put records into namestore */ | ||
353 | namestore_handle = GNUNET_NAMESTORE_connect(cfg); | ||
354 | if (NULL == namestore_handle) | ||
355 | { | ||
356 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n"); | ||
357 | ok = -1; | ||
358 | return; | ||
359 | } | ||
360 | |||
361 | /* dht */ | ||
362 | dht_handle = GNUNET_DHT_connect(cfg, 1); | ||
363 | if (NULL == dht_handle) | ||
364 | { | ||
365 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to dht\n"); | ||
366 | ok = -1; | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "gns", | ||
371 | "ZONEKEY", | ||
372 | &my_keyfile)) | ||
373 | { | ||
374 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); | ||
375 | ok = -1; | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | my_key = GNUNET_CRYPTO_rsa_key_create_from_file (my_keyfile); | ||
380 | alice_key = GNUNET_CRYPTO_rsa_key_create (); | ||
381 | bob_key = GNUNET_CRYPTO_rsa_key_create (); | ||
382 | |||
383 | GNUNET_CRYPTO_rsa_key_get_public (alice_key, &alice_pkey); | ||
384 | GNUNET_CRYPTO_rsa_key_get_public (bob_key, &bob_pkey); | ||
385 | GNUNET_CRYPTO_hash(&bob_pkey, sizeof(bob_pkey), &bob_hash); | ||
386 | GNUNET_CRYPTO_hash(&alice_pkey, sizeof(alice_pkey), &alice_hash); | ||
387 | |||
388 | struct GNUNET_NAMESTORE_RecordData rd; | ||
389 | rd.expiration = GNUNET_TIME_absolute_get_forever (); | ||
390 | rd.data_size = sizeof(GNUNET_HashCode); | ||
391 | rd.data = &bob_hash; | ||
392 | rd.record_type = GNUNET_GNS_RECORD_PKEY; | ||
393 | |||
394 | GNUNET_NAMESTORE_record_create (namestore_handle, | ||
395 | my_key, | ||
396 | TEST_AUTHORITY_NAME, | ||
397 | &rd, | ||
398 | NULL, | ||
399 | NULL); | ||
400 | |||
401 | rd.data = &alice_hash; | ||
402 | |||
403 | sig = GNUNET_NAMESTORE_create_signature(bob_key, | ||
404 | GNUNET_TIME_absolute_get_forever(), | ||
405 | TEST_AUTHORITY_ALICE, | ||
406 | &rd, | ||
407 | 1); | ||
408 | |||
409 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
410 | &bob_pkey, | ||
411 | TEST_AUTHORITY_ALICE, | ||
412 | GNUNET_TIME_absolute_get_forever(), | ||
413 | 1, | ||
414 | &rd, | ||
415 | sig, | ||
416 | &put_alice_pseu_dht, | ||
417 | NULL); | ||
418 | |||
419 | |||
420 | |||
421 | |||
422 | |||
423 | } | ||
424 | |||
425 | static void | ||
426 | run (void *cls, char *const *args, const char *cfgfile, | ||
427 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
428 | { | ||
429 | cfg = c; | ||
430 | /* Get path from configuration file */ | ||
431 | if (GNUNET_YES != | ||
432 | GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome", | ||
433 | &test_directory)) | ||
434 | { | ||
435 | ok = 404; | ||
436 | return; | ||
437 | } | ||
438 | |||
439 | |||
440 | /* Set up a task to end testing if peer start fails */ | ||
441 | die_task = | ||
442 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, | ||
443 | "didn't start all daemons in reasonable amount of time!!!"); | ||
444 | |||
445 | /* Start alice */ | ||
446 | d1 = GNUNET_TESTING_daemon_start(cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, | ||
447 | NULL, NULL, NULL, &do_shorten, NULL); | ||
448 | } | ||
449 | |||
450 | static int | ||
451 | check () | ||
452 | { | ||
453 | int ret; | ||
454 | |||
455 | /* Arguments for GNUNET_PROGRAM_run */ | ||
456 | char *const argv[] = { "test-gns-dht-delegated-lookup", /* Name to give running binary */ | ||
457 | "-c", | ||
458 | "test_gns_simple_lookup.conf", /* Config file to use */ | ||
459 | #if VERBOSE | ||
460 | "-L", "DEBUG", | ||
461 | #endif | ||
462 | NULL | ||
463 | }; | ||
464 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
465 | GNUNET_GETOPT_OPTION_END | ||
466 | }; | ||
467 | /* Run the run function as a new program */ | ||
468 | ret = | ||
469 | GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, | ||
470 | "test-gns-dht-delegated-lookup", "nohelp", options, &run, | ||
471 | &ok); | ||
472 | if (ret != GNUNET_OK) | ||
473 | { | ||
474 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
475 | "`test-gns-dht-delegated-lookup': Failed with error code %d\n", ret); | ||
476 | } | ||
477 | return ok; | ||
478 | } | ||
479 | |||
480 | int | ||
481 | main (int argc, char *argv[]) | ||
482 | { | ||
483 | int ret; | ||
484 | |||
485 | GNUNET_log_setup ("test-gns-simple-lookup", | ||
486 | #if VERBOSE | ||
487 | "DEBUG", | ||
488 | #else | ||
489 | "WARNING", | ||
490 | #endif | ||
491 | NULL); | ||
492 | ret = check (); | ||
493 | /** | ||
494 | * Need to remove base directory, subdirectories taken care | ||
495 | * of by the testing framework. | ||
496 | */ | ||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | /* end of test_gns_twopeer.c */ | ||
diff --git a/src/gns/test_gns_simple_shorten.c b/src/gns/test_gns_simple_shorten.c index 17076bb4a..8f93c471f 100644 --- a/src/gns/test_gns_simple_shorten.c +++ b/src/gns/test_gns_simple_shorten.c | |||
@@ -285,25 +285,18 @@ do_shorten(void *cls, const struct GNUNET_PeerIdentity *id, | |||
285 | NULL, | 285 | NULL, |
286 | NULL); | 286 | NULL); |
287 | 287 | ||
288 | rd.data_size = strlen(TEST_ALICE_PSEU); | 288 | rd.data_size = sizeof(GNUNET_HashCode); |
289 | rd.data = TEST_ALICE_PSEU; | 289 | rd.data = &alice_hash; |
290 | rd.record_type = GNUNET_GNS_RECORD_PSEU; | 290 | rd.record_type = GNUNET_GNS_RECORD_PKEY; |
291 | GNUNET_free(sig); | 291 | GNUNET_free(sig); |
292 | 292 | ||
293 | sig = GNUNET_NAMESTORE_create_signature(alice_key,GNUNET_TIME_absolute_get_forever(), "+", | 293 | GNUNET_NAMESTORE_record_create (namestore_handle, |
294 | &rd, 1); | 294 | our_key, |
295 | 295 | TEST_ALICE_PSEU, | |
296 | GNUNET_NAMESTORE_record_put (namestore_handle, | ||
297 | &alice_pkey, | ||
298 | "+", | ||
299 | GNUNET_TIME_absolute_get_forever(), | ||
300 | 1, | ||
301 | &rd, | 296 | &rd, |
302 | sig, | ||
303 | &commence_testing, | 297 | &commence_testing, |
304 | NULL); | 298 | NULL); |
305 | 299 | ||
306 | GNUNET_free(sig); | ||
307 | 300 | ||
308 | } | 301 | } |
309 | 302 | ||