aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2016-10-06 15:54:30 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2016-10-06 15:54:30 +0000
commit810bc9ef12ddcc67cfc7cd762759ee13ecd14a8d (patch)
treee6950609e302c8cee5dd49cd75a890e660dde02a /src
parent16f524720ce08aadb35912731217eaeafc690dba (diff)
downloadgnunet-810bc9ef12ddcc67cfc7cd762759ee13ecd14a8d.tar.gz
gnunet-810bc9ef12ddcc67cfc7cd762759ee13ecd14a8d.zip
- Add reverse resolution with limited functionality
Diffstat (limited to 'src')
-rw-r--r--src/gns/Makefile.am4
-rw-r--r--src/gns/gns.h44
-rw-r--r--src/gns/gns_api.c203
-rw-r--r--src/gns/gnunet-gns.c110
-rw-r--r--src/gns/gnunet-service-gns.c89
-rw-r--r--src/gns/gnunet-service-gns_reverser.c244
-rw-r--r--src/gns/gnunet-service-gns_reverser.h72
-rw-r--r--src/gns/plugin_gnsrecord_gns.c319
-rw-r--r--src/include/gnunet_gns_service.h27
-rw-r--r--src/include/gnunet_gnsrecord_lib.h25
-rw-r--r--src/include/gnunet_protocols.h10
11 files changed, 987 insertions, 160 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am
index 33fd96d9d..0b65a3d17 100644
--- a/src/gns/Makefile.am
+++ b/src/gns/Makefile.am
@@ -184,6 +184,7 @@ w32nsp_resolve_LDADD = -lws2_32
184gnunet_service_gns_SOURCES = \ 184gnunet_service_gns_SOURCES = \
185 gnunet-service-gns.c \ 185 gnunet-service-gns.c \
186 gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ 186 gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \
187 gnunet-service-gns_reverser.c gnunet-service-gns_reverser.h \
187 gnunet-service-gns_shorten.c gnunet-service-gns_shorten.h \ 188 gnunet-service-gns_shorten.c gnunet-service-gns_shorten.h \
188 gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h 189 gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h
189gnunet_service_gns_LDADD = \ 190gnunet_service_gns_LDADD = \
@@ -258,7 +259,8 @@ check_SCRIPTS = \
258 test_gns_rel_expiration.sh\ 259 test_gns_rel_expiration.sh\
259 test_gns_soa_lookup.sh\ 260 test_gns_soa_lookup.sh\
260 test_gns_revocation.sh\ 261 test_gns_revocation.sh\
261 test_gns_cname_lookup.sh 262 test_gns_cname_lookup.sh \
263 test_gns_reverse_lookup.sh
262 264
263if ENABLE_TEST_RUN 265if ENABLE_TEST_RUN
264if HAVE_SQLITE 266if HAVE_SQLITE
diff --git a/src/gns/gns.h b/src/gns/gns.h
index 476cb0fd2..ca5525f80 100644
--- a/src/gns/gns.h
+++ b/src/gns/gns.h
@@ -91,6 +91,32 @@ struct LookupMessage
91 91
92 92
93/** 93/**
94 * Message from client to GNS service to lookup records.
95 */
96struct ReverseLookupMessage
97{
98 /**
99 * Header of type #GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP
100 */
101 struct GNUNET_MessageHeader header;
102
103 /**
104 * Unique identifier for this request (for key collisions).
105 */
106 uint32_t id GNUNET_PACKED;
107
108 /**
109 * Zone that is target for reverse lookup
110 */
111 struct GNUNET_CRYPTO_EcdsaPublicKey zone_pkey;
112
113 /**
114 * Root zone
115 */
116 struct GNUNET_CRYPTO_EcdsaPublicKey root_pkey;
117};
118
119/**
94 * Message from GNS service to client: new results. 120 * Message from GNS service to client: new results.
95 */ 121 */
96struct LookupResultMessage 122struct LookupResultMessage
@@ -114,6 +140,24 @@ struct LookupResultMessage
114 140
115}; 141};
116 142
143/**
144 * Message from GNS service to client: new results.
145 */
146struct ReverseLookupResultMessage
147{
148 /**
149 * Header of type #GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT
150 */
151 struct GNUNET_MessageHeader header;
152
153 /**
154 * Unique identifier for this request (for key collisions).
155 */
156 uint32_t id GNUNET_PACKED;
157
158 /* followed by the resulting name of the reverse lookup */
159};
160
117 161
118GNUNET_NETWORK_STRUCT_END 162GNUNET_NETWORK_STRUCT_END
119 163
diff --git a/src/gns/gns_api.c b/src/gns/gns_api.c
index b9b95b7c2..3f6425b42 100644
--- a/src/gns/gns_api.c
+++ b/src/gns/gns_api.c
@@ -79,6 +79,49 @@ struct GNUNET_GNS_LookupRequest
79 79
80}; 80};
81 81
82/**
83 * Handle to a lookup request
84 */
85struct GNUNET_GNS_ReverseLookupRequest
86{
87
88 /**
89 * DLL
90 */
91 struct GNUNET_GNS_ReverseLookupRequest *next;
92
93 /**
94 * DLL
95 */
96 struct GNUNET_GNS_ReverseLookupRequest *prev;
97
98 /**
99 * handle to gns
100 */
101 struct GNUNET_GNS_Handle *gns_handle;
102
103 /**
104 * processor to call on lookup result
105 */
106 GNUNET_GNS_ReverseLookupResultProcessor lookup_proc;
107
108 /**
109 * @e lookup_proc closure
110 */
111 void *proc_cls;
112
113 /**
114 * Envelope with the message for this queue entry.
115 */
116 struct GNUNET_MQ_Envelope *env;
117
118 /**
119 * request id
120 */
121 uint32_t r_id;
122
123};
124
82 125
83/** 126/**
84 * Connection to the GNS service. 127 * Connection to the GNS service.
@@ -107,6 +150,15 @@ struct GNUNET_GNS_Handle
107 struct GNUNET_GNS_LookupRequest *lookup_tail; 150 struct GNUNET_GNS_LookupRequest *lookup_tail;
108 151
109 /** 152 /**
153 * Head of linked list of active reverse lookup requests.
154 */
155 struct GNUNET_GNS_ReverseLookupRequest *rev_lookup_head;
156
157 /**
158 * Tail of linked list of active reverse lookup requests.
159 */
160 struct GNUNET_GNS_ReverseLookupRequest *rev_lookup_tail;
161 /**
110 * Reconnect task 162 * Reconnect task
111 */ 163 */
112 struct GNUNET_SCHEDULER_Task *reconnect_task; 164 struct GNUNET_SCHEDULER_Task *reconnect_task;
@@ -180,10 +232,71 @@ mq_error_handler (void *cls,
180 enum GNUNET_MQ_Error error) 232 enum GNUNET_MQ_Error error)
181{ 233{
182 struct GNUNET_GNS_Handle *handle = cls; 234 struct GNUNET_GNS_Handle *handle = cls;
183 235 LOG (GNUNET_ERROR_TYPE_WARNING, "Problem with message queue. error: %i\n",
236 error);
184 force_reconnect (handle); 237 force_reconnect (handle);
185} 238}
186 239
240/**
241 * Check validity of message received from the GNS service
242 *
243 * @param cls the `struct GNUNET_GNS_Handle *`
244 * @param loookup_msg the incoming message
245 */
246static int
247check_rev_result (void *cls,
248 const struct ReverseLookupResultMessage *lookup_msg)
249{
250 size_t mlen = ntohs (lookup_msg->header.size) - sizeof (*lookup_msg);
251 char *name;
252
253 name = (char*) &lookup_msg[1];
254 if ('\0' != name[mlen-1])
255 {
256 GNUNET_break (0);
257 return GNUNET_SYSERR;
258 }
259 return GNUNET_OK;
260}
261
262
263/**
264 * Handler for messages received from the GNS service
265 *
266 * @param cls the `struct GNUNET_GNS_Handle *`
267 * @param loookup_msg the incoming message
268 */
269static void
270handle_rev_result (void *cls,
271 const struct ReverseLookupResultMessage *lookup_msg)
272{
273 struct GNUNET_GNS_Handle *handle = cls;
274 char *name;
275 uint32_t r_id = ntohl (lookup_msg->id);
276 struct GNUNET_GNS_ReverseLookupRequest *rlr;
277 GNUNET_GNS_ReverseLookupResultProcessor proc;
278 void *proc_cls;
279
280 name = (char*)&lookup_msg[1];
281 LOG (GNUNET_ERROR_TYPE_DEBUG,
282 "Received reverse lookup reply from GNS service (%s)\n",
283 name);
284 for (rlr = handle->rev_lookup_head; NULL != rlr; rlr = rlr->next)
285 if (rlr->r_id == r_id)
286 break;
287 if (NULL == rlr)
288 return;
289 proc = rlr->lookup_proc;
290 proc_cls = rlr->proc_cls;
291 GNUNET_CONTAINER_DLL_remove (handle->rev_lookup_head,
292 handle->rev_lookup_tail,
293 rlr);
294 GNUNET_free (rlr);
295 proc (proc_cls,
296 name);
297}
298
299
187 300
188/** 301/**
189 * Check validity of message received from the GNS service 302 * Check validity of message received from the GNS service
@@ -269,9 +382,14 @@ reconnect (struct GNUNET_GNS_Handle *handle)
269 GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT, 382 GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT,
270 struct LookupResultMessage, 383 struct LookupResultMessage,
271 handle), 384 handle),
385 GNUNET_MQ_hd_var_size (rev_result,
386 GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT,
387 struct ReverseLookupResultMessage,
388 handle),
272 GNUNET_MQ_handler_end () 389 GNUNET_MQ_handler_end ()
273 }; 390 };
274 struct GNUNET_GNS_LookupRequest *lh; 391 struct GNUNET_GNS_LookupRequest *lh;
392 struct GNUNET_GNS_ReverseLookupRequest *rlh;
275 393
276 GNUNET_assert (NULL == handle->mq); 394 GNUNET_assert (NULL == handle->mq);
277 LOG (GNUNET_ERROR_TYPE_DEBUG, 395 LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -286,6 +404,9 @@ reconnect (struct GNUNET_GNS_Handle *handle)
286 for (lh = handle->lookup_head; NULL != lh; lh = lh->next) 404 for (lh = handle->lookup_head; NULL != lh; lh = lh->next)
287 GNUNET_MQ_send_copy (handle->mq, 405 GNUNET_MQ_send_copy (handle->mq,
288 lh->env); 406 lh->env);
407 for (rlh = handle->rev_lookup_head; NULL != rlh; rlh = rlh->next)
408 GNUNET_MQ_send_copy (handle->mq,
409 rlh->env);
289} 410}
290 411
291 412
@@ -331,6 +452,7 @@ GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle)
331 handle->reconnect_task = NULL; 452 handle->reconnect_task = NULL;
332 } 453 }
333 GNUNET_assert (NULL == handle->lookup_head); 454 GNUNET_assert (NULL == handle->lookup_head);
455 GNUNET_assert (NULL == handle->rev_lookup_head);
334 GNUNET_free (handle); 456 GNUNET_free (handle);
335} 457}
336 458
@@ -352,6 +474,22 @@ GNUNET_GNS_lookup_cancel (struct GNUNET_GNS_LookupRequest *lr)
352 GNUNET_free (lr); 474 GNUNET_free (lr);
353} 475}
354 476
477/**
478 * Cancel pending reverse lookup request
479 *
480 * @param lr the lookup request to cancel
481 */
482void
483GNUNET_GNS_reverse_lookup_cancel (struct GNUNET_GNS_ReverseLookupRequest *lr)
484{
485 struct GNUNET_GNS_Handle *handle = lr->gns_handle;
486
487 GNUNET_CONTAINER_DLL_remove (handle->rev_lookup_head,
488 handle->rev_lookup_tail,
489 lr);
490 GNUNET_MQ_discard (lr->env);
491 GNUNET_free (lr);
492}
355 493
356/** 494/**
357 * Perform an asynchronous lookup operation on the GNS. 495 * Perform an asynchronous lookup operation on the GNS.
@@ -368,13 +506,13 @@ GNUNET_GNS_lookup_cancel (struct GNUNET_GNS_LookupRequest *lr)
368 */ 506 */
369struct GNUNET_GNS_LookupRequest* 507struct GNUNET_GNS_LookupRequest*
370GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle, 508GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
371 const char *name, 509 const char *name,
372 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, 510 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone,
373 uint32_t type, 511 uint32_t type,
374 enum GNUNET_GNS_LocalOptions options, 512 enum GNUNET_GNS_LocalOptions options,
375 const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone_key, 513 const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone_key,
376 GNUNET_GNS_LookupResultProcessor proc, 514 GNUNET_GNS_LookupResultProcessor proc,
377 void *proc_cls) 515 void *proc_cls)
378{ 516{
379 /* IPC to shorten gns names, return shorten_handle */ 517 /* IPC to shorten gns names, return shorten_handle */
380 struct LookupMessage *lookup_msg; 518 struct LookupMessage *lookup_msg;
@@ -413,8 +551,8 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
413 lookup_msg->shorten_key = *shorten_zone_key; 551 lookup_msg->shorten_key = *shorten_zone_key;
414 } 552 }
415 GNUNET_memcpy (&lookup_msg[1], 553 GNUNET_memcpy (&lookup_msg[1],
416 name, 554 name,
417 nlen); 555 nlen);
418 GNUNET_CONTAINER_DLL_insert (handle->lookup_head, 556 GNUNET_CONTAINER_DLL_insert (handle->lookup_head,
419 handle->lookup_tail, 557 handle->lookup_tail,
420 lr); 558 lr);
@@ -424,5 +562,50 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
424 return lr; 562 return lr;
425} 563}
426 564
565/**
566 * Perform an asynchronous reverse lookup operation on the GNS.
567 *
568 * @param handle handle to the GNS service
569 * @param zone_key zone to find a name for
570 * @param root_key our zone
571 * @param proc processor to call on result
572 * @param proc_cls closure for @a proc
573 * @return handle to the request
574 */
575struct GNUNET_GNS_ReverseLookupRequest*
576GNUNET_GNS_reverse_lookup (struct GNUNET_GNS_Handle *handle,
577 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
578 const struct GNUNET_CRYPTO_EcdsaPublicKey *root_key,
579 GNUNET_GNS_ReverseLookupResultProcessor proc,
580 void *proc_cls)
581{
582 /* IPC to shorten gns names, return shorten_handle */
583 struct ReverseLookupMessage *rev_lookup_msg;
584 struct GNUNET_GNS_ReverseLookupRequest *lr;
427 585
586 if ((NULL == zone_key) || (NULL == root_key))
587 {
588 GNUNET_break (0);
589 return NULL;
590 }
591 LOG (GNUNET_ERROR_TYPE_DEBUG,
592 "Trying to reverse lookup in GNS\n");
593 lr = GNUNET_new (struct GNUNET_GNS_ReverseLookupRequest);
594 lr->gns_handle = handle;
595 lr->lookup_proc = proc;
596 lr->proc_cls = proc_cls;
597 lr->r_id = handle->r_id_gen++;
598 lr->env = GNUNET_MQ_msg (rev_lookup_msg,
599 GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP);
600 rev_lookup_msg->id = htonl (lr->r_id);
601 rev_lookup_msg->zone_pkey = *zone_key;
602 rev_lookup_msg->root_pkey = *root_key;
603 GNUNET_CONTAINER_DLL_insert (handle->rev_lookup_head,
604 handle->rev_lookup_tail,
605 lr);
606 if (NULL != handle->mq)
607 GNUNET_MQ_send_copy (handle->mq,
608 lr->env);
609 return lr;
610}
428/* end of gns_api.c */ 611/* end of gns_api.c */
diff --git a/src/gns/gnunet-gns.c b/src/gns/gnunet-gns.c
index 62cec54cb..17fe4cbda 100644
--- a/src/gns/gnunet-gns.c
+++ b/src/gns/gnunet-gns.c
@@ -66,6 +66,16 @@ static char *zone_ego_name;
66static char *public_key; 66static char *public_key;
67 67
68/** 68/**
69 * Reverse key
70 */
71static char *reverse_key;
72
73/**
74 * Reverse key
75 */
76static struct GNUNET_CRYPTO_EcdsaPublicKey rkey;
77
78/**
69 * Set to GNUNET_GNS_LO_LOCAL_MASTER if we are looking up in the master zone. 79 * Set to GNUNET_GNS_LO_LOCAL_MASTER if we are looking up in the master zone.
70 */ 80 */
71static enum GNUNET_GNS_LocalOptions local_options; 81static enum GNUNET_GNS_LocalOptions local_options;
@@ -86,6 +96,11 @@ static int rtype;
86static struct GNUNET_GNS_LookupRequest *lookup_request; 96static struct GNUNET_GNS_LookupRequest *lookup_request;
87 97
88/** 98/**
99 * Handle to reverse lookup request
100 */
101static struct GNUNET_GNS_ReverseLookupRequest *rev_lookup_request;
102
103/**
89 * Lookup an ego with the identity service. 104 * Lookup an ego with the identity service.
90 */ 105 */
91static struct GNUNET_IDENTITY_EgoLookup *el; 106static struct GNUNET_IDENTITY_EgoLookup *el;
@@ -159,6 +174,24 @@ do_timeout (void *cls)
159 GNUNET_SCHEDULER_shutdown (); 174 GNUNET_SCHEDULER_shutdown ();
160} 175}
161 176
177static void
178process_reverse_result (void *cls,
179 const char *name)
180{
181 rev_lookup_request = NULL;
182 if (NULL == name)
183 {
184 printf ("No name found.\n");
185 return;
186 }
187 if (raw)
188 printf ("%s\n", name);
189 else
190 printf ("%s is known as %s\n",
191 reverse_key,
192 name);
193 GNUNET_SCHEDULER_shutdown ();
194}
162 195
163/** 196/**
164 * Function called with the result of a GNS lookup. 197 * Function called with the result of a GNS lookup.
@@ -248,6 +281,14 @@ lookup_with_keys (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey,
248 &process_lookup_result, 281 &process_lookup_result,
249 lookup_name); 282 lookup_name);
250 } 283 }
284 else if (NULL != reverse_key)
285 {
286 rev_lookup_request = GNUNET_GNS_reverse_lookup (gns,
287 &rkey,
288 pkey,
289 &process_reverse_result,
290 NULL);
291 }
251 else 292 else
252 { 293 {
253 fprintf (stderr, 294 fprintf (stderr,
@@ -416,49 +457,77 @@ run (void *cls,
416 return; 457 return;
417 } 458 }
418 tt = GNUNET_SCHEDULER_add_delayed (timeout, 459 tt = GNUNET_SCHEDULER_add_delayed (timeout,
419 &do_timeout, NULL); 460 &do_timeout, NULL);
420 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); 461 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
462 if (NULL != reverse_key)
463 {
464 if (GNUNET_OK !=
465 GNUNET_CRYPTO_ecdsa_public_key_from_string (reverse_key,
466 strlen (reverse_key),
467 &rkey))
468 {
469 fprintf (stderr,
470 _("Reverse key `%s' is not well-formed\n"),
471 reverse_key);
472 GNUNET_SCHEDULER_shutdown ();
473 return;
474 }
475 }
421 if (NULL != public_key) 476 if (NULL != public_key)
422 { 477 {
423 if (GNUNET_OK != 478 if (GNUNET_OK !=
424 GNUNET_CRYPTO_ecdsa_public_key_from_string (public_key, 479 GNUNET_CRYPTO_ecdsa_public_key_from_string (public_key,
425 strlen (public_key), 480 strlen (public_key),
426 &pkey)) 481 &pkey))
427 { 482 {
428 fprintf (stderr, 483 fprintf (stderr,
429 _("Public key `%s' is not well-formed\n"), 484 _("Public key `%s' is not well-formed\n"),
430 public_key); 485 public_key);
431 GNUNET_SCHEDULER_shutdown (); 486 GNUNET_SCHEDULER_shutdown ();
432 return; 487 return;
433 } 488 }
434 lookup_with_public_key (&pkey); 489 lookup_with_public_key (&pkey);
435 return; 490 return;
436 } 491 }
492 if (NULL != reverse_key)
493 {
494 if (GNUNET_OK !=
495 GNUNET_CRYPTO_ecdsa_public_key_from_string (reverse_key,
496 strlen (reverse_key),
497 &rkey))
498 {
499 fprintf (stderr,
500 _("Reverse key `%s' is not well-formed\n"),
501 reverse_key);
502 GNUNET_SCHEDULER_shutdown ();
503 return;
504 }
505 }
437 if (NULL != zone_ego_name) 506 if (NULL != zone_ego_name)
438 { 507 {
439 el = GNUNET_IDENTITY_ego_lookup (cfg, 508 el = GNUNET_IDENTITY_ego_lookup (cfg,
440 zone_ego_name, 509 zone_ego_name,
441 &identity_zone_cb, 510 &identity_zone_cb,
442 NULL); 511 NULL);
443 return; 512 return;
444 } 513 }
445 if ( (NULL != lookup_name) && 514 if ( (NULL != lookup_name) &&
446 (strlen (lookup_name) > 4) && 515 (strlen (lookup_name) > 4) &&
447 (0 == strcmp (".zkey", 516 (0 == strcmp (".zkey",
448 &lookup_name[strlen (lookup_name) - 4])) ) 517 &lookup_name[strlen (lookup_name) - 4])) )
449 { 518 {
450 /* no zone required, use 'anonymous' zone */ 519 /* no zone required, use 'anonymous' zone */
451 GNUNET_CRYPTO_ecdsa_key_get_public (GNUNET_CRYPTO_ecdsa_key_get_anonymous (), 520 GNUNET_CRYPTO_ecdsa_key_get_public (GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
452 &pkey); 521 &pkey);
453 lookup_with_public_key (&pkey); 522 lookup_with_public_key (&pkey);
454 } 523 }
455 else 524 else
456 { 525 {
457 GNUNET_break (NULL == id_op); 526 GNUNET_break (NULL == id_op);
458 id_op = GNUNET_IDENTITY_get (identity, 527 id_op = GNUNET_IDENTITY_get (identity,
459 "gns-master", 528 "gns-master",
460 &identity_master_cb, 529 &identity_master_cb,
461 NULL); 530 NULL);
462 GNUNET_assert (NULL != id_op); 531 GNUNET_assert (NULL != id_op);
463 } 532 }
464} 533}
@@ -493,6 +562,9 @@ main (int argc, char *const *argv)
493 {'z', "zone", "NAME", 562 {'z', "zone", "NAME",
494 gettext_noop ("Specify the name of the ego of the zone to lookup the record in"), 1, 563 gettext_noop ("Specify the name of the ego of the zone to lookup the record in"), 1,
495 &GNUNET_GETOPT_set_string, &zone_ego_name}, 564 &GNUNET_GETOPT_set_string, &zone_ego_name},
565 {'R', "reverse", "PKEY",
566 gettext_noop ("Specify the public key of the zone to reverse lookup a name for"), 1,
567 &GNUNET_GETOPT_set_string, &reverse_key},
496 GNUNET_GETOPT_OPTION_END 568 GNUNET_GETOPT_OPTION_END
497 }; 569 };
498 int ret; 570 int ret;
@@ -503,11 +575,11 @@ main (int argc, char *const *argv)
503 575
504 GNUNET_log_setup ("gnunet-gns", "WARNING", NULL); 576 GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
505 ret = 577 ret =
506 (GNUNET_OK == 578 (GNUNET_OK ==
507 GNUNET_PROGRAM_run (argc, argv, "gnunet-gns", 579 GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
508 _("GNUnet GNS resolver tool"), 580 _("GNUnet GNS resolver tool"),
509 options, 581 options,
510 &run, NULL)) ? 0 : 1; 582 &run, NULL)) ? 0 : 1;
511 GNUNET_free ((void*) argv); 583 GNUNET_free ((void*) argv);
512 return ret; 584 return ret;
513} 585}
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
index 386e6d744..221d75bba 100644
--- a/src/gns/gnunet-service-gns.c
+++ b/src/gns/gnunet-service-gns.c
@@ -35,6 +35,7 @@
35#include "gnunet_statistics_service.h" 35#include "gnunet_statistics_service.h"
36#include "gns.h" 36#include "gns.h"
37#include "gnunet-service-gns_resolver.h" 37#include "gnunet-service-gns_resolver.h"
38#include "gnunet-service-gns_reverser.h"
38#include "gnunet-service-gns_shorten.h" 39#include "gnunet-service-gns_shorten.h"
39#include "gnunet-service-gns_interceptor.h" 40#include "gnunet-service-gns_interceptor.h"
40#include "gnunet_protocols.h" 41#include "gnunet_protocols.h"
@@ -109,6 +110,11 @@ struct ClientLookupHandle
109 struct GNS_ResolverHandle *lookup; 110 struct GNS_ResolverHandle *lookup;
110 111
111 /** 112 /**
113 * Active handle for a reverse lookup
114 */
115 struct GNS_ReverserHandle *rev_lookup;
116
117 /**
112 * request id 118 * request id
113 */ 119 */
114 uint32_t request_id; 120 uint32_t request_id;
@@ -367,7 +373,10 @@ client_disconnect_cb (void *cls,
367 client); 373 client);
368 while (NULL != (clh = gc->clh_head)) 374 while (NULL != (clh = gc->clh_head))
369 { 375 {
370 GNS_resolver_lookup_cancel (clh->lookup); 376 if (NULL != clh->lookup)
377 GNS_resolver_lookup_cancel (clh->lookup);
378 if (NULL != clh->rev_lookup)
379 GNS_reverse_lookup_cancel (clh->rev_lookup);
371 GNUNET_CONTAINER_DLL_remove (gc->clh_head, 380 GNUNET_CONTAINER_DLL_remove (gc->clh_head,
372 gc->clh_tail, 381 gc->clh_tail,
373 clh); 382 clh);
@@ -846,6 +855,47 @@ send_lookup_response (void* cls,
846 GNUNET_NO); 855 GNUNET_NO);
847} 856}
848 857
858/**
859 * Reply to client with the result from our reverse lookup.
860 *
861 * @param cls the closure (our client lookup handle)
862 * @param rd_count the number of records in @a rd
863 * @param rd the record data
864 */
865static void
866send_reverse_lookup_response (void* cls,
867 const char *name)
868{
869 struct ClientLookupHandle *clh = cls;
870 struct GNUNET_MQ_Envelope *env;
871 struct ReverseLookupResultMessage *rmsg;
872 size_t len;
873
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
875 "Sending LOOKUP_RESULT message with %s\n",
876 name);
877
878 if (NULL == name)
879 len = 1;
880 else
881 len = strlen (name) + 1;
882 env = GNUNET_MQ_msg_extra (rmsg,
883 len,
884 GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT);
885 rmsg->id = clh->request_id;
886 if (1 < len)
887 GNUNET_memcpy ((char*) &rmsg[1],
888 name,
889 strlen (name));
890 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq(clh->gc->client),
891 env);
892 GNUNET_CONTAINER_DLL_remove (clh->gc->clh_head, clh->gc->clh_tail, clh);
893 GNUNET_free (clh);
894 GNUNET_STATISTICS_update (statistics,
895 "Completed reverse lookups", 1,
896 GNUNET_NO);
897}
898
849 899
850/** 900/**
851 * Checks a #GNUNET_MESSAGE_TYPE_GNS_LOOKUP message 901 * Checks a #GNUNET_MESSAGE_TYPE_GNS_LOOKUP message
@@ -856,7 +906,7 @@ send_lookup_response (void* cls,
856 */ 906 */
857static int 907static int
858check_lookup (void *cls, 908check_lookup (void *cls,
859 const struct LookupMessage *l_msg) 909 const struct LookupMessage *l_msg)
860{ 910{
861 size_t msg_size; 911 size_t msg_size;
862 const char* name; 912 const char* name;
@@ -936,6 +986,37 @@ handle_lookup (void *cls,
936 1, GNUNET_NO); 986 1, GNUNET_NO);
937} 987}
938 988
989/**
990 * Handle reverse lookup requests from client
991 *
992 * @param cls the closure
993 * @param client the client
994 * @param message the message
995 */
996static void
997handle_rev_lookup (void *cls,
998 const struct ReverseLookupMessage *sh_msg)
999{
1000 struct GnsClient *gc = cls;
1001 struct ClientLookupHandle *clh;
1002
1003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1004 "Received REVERSE_LOOKUP message\n");
1005 GNUNET_SERVICE_client_continue (gc->client);
1006
1007 clh = GNUNET_new (struct ClientLookupHandle);
1008 GNUNET_CONTAINER_DLL_insert (gc->clh_head, gc->clh_tail, clh);
1009 clh->gc = gc;
1010 clh->request_id = sh_msg->id;
1011 clh->rev_lookup = GNS_reverse_lookup (&sh_msg->zone_pkey,
1012 &sh_msg->root_pkey,
1013 &send_reverse_lookup_response,
1014 clh);
1015 GNUNET_STATISTICS_update (statistics,
1016 "Reverse lookup attempts",
1017 1, GNUNET_NO);
1018}
1019
939 1020
940/** 1021/**
941 * The zone monitor is now in SYNC with the current state of the 1022 * The zone monitor is now in SYNC with the current state of the
@@ -1149,6 +1230,10 @@ GNUNET_SERVICE_MAIN
1149 GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 1230 GNUNET_MESSAGE_TYPE_GNS_LOOKUP,
1150 struct LookupMessage, 1231 struct LookupMessage,
1151 NULL), 1232 NULL),
1233 GNUNET_MQ_hd_fixed_size (rev_lookup,
1234 GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP,
1235 struct ReverseLookupMessage,
1236 NULL),
1152 GNUNET_MQ_handler_end()); 1237 GNUNET_MQ_handler_end());
1153 1238
1154 1239
diff --git a/src/gns/gnunet-service-gns_reverser.c b/src/gns/gnunet-service-gns_reverser.c
new file mode 100644
index 000000000..6bae20b61
--- /dev/null
+++ b/src/gns/gnunet-service-gns_reverser.c
@@ -0,0 +1,244 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gns/gnunet-service-gns_reverser.c
22 * @brief GNUnet GNS service
23 * @author Martin Schanzenbach
24 */
25
26
27#include "platform.h"
28#include "gnunet_gns_service.h"
29#include "gnunet-service-gns_resolver.h"
30#include "gnunet-service-gns_reverser.h"
31
32struct ReverseTreeNode
33{
34 /**
35 * DLL
36 */
37 struct ReverseTreeNode *next;
38
39 /**
40 * DLL
41 */
42 struct ReverseTreeNode *prev;
43
44 /**
45 * Resolved name until now
46 */
47 char *name;
48
49 /**
50 * Depth of the resolution at this node
51 */
52 uint8_t depth;
53
54 /**
55 * The pkey of the namespace
56 */
57 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
58
59};
60
61
62struct GNS_ReverserHandle
63{
64 /**
65 * GNS resolver handle
66 */
67 struct GNS_ResolverHandle *rh;
68
69 /**
70 * The authority to look for
71 */
72 struct GNUNET_CRYPTO_EcdsaPublicKey authority;
73
74 /**
75 * Resolution candidate queue
76 */
77 struct ReverseTreeNode *node_queue_head;
78
79 /**
80 * Resolution candidate queue
81 */
82 struct ReverseTreeNode *node_queue_tail;
83
84 /**
85 * Max depth for the resolution
86 */
87 uint8_t max_depth;
88
89 /**
90 * Result callback
91 */
92 GNS_ReverseResultProcessor proc;
93
94 /**
95 * Callback closure
96 */
97 void *proc_cls;
98};
99
100void
101cleanup_handle (struct GNS_ReverserHandle *rh)
102{
103 struct ReverseTreeNode *rtn;
104
105 for (rtn = rh->node_queue_head; NULL != rtn; rtn = rh->node_queue_head)
106 {
107 if (NULL != rtn->name)
108 GNUNET_free (rtn->name);
109 GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
110 rh->node_queue_tail,
111 rtn);
112 GNUNET_free (rtn);
113 }
114}
115
116void
117handle_gns_result (void *cls,
118 uint32_t rd_count,
119 const struct GNUNET_GNSRECORD_Data *rd)
120{
121 struct GNS_ReverserHandle *rh = cls;
122 const struct GNUNET_GNSRECORD_ReverseRecord *rr;
123 struct ReverseTreeNode *rtn;
124 char *result;
125 const char *name;
126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
127 "Got result (%d)\n", rd_count);
128
129 for (int i = 0; i < rd_count; i++)
130 {
131 /**
132 * Check if we are in the delegation set
133 */
134 if (GNUNET_GNSRECORD_TYPE_REVERSE != rd[i].record_type)
135 continue;
136 rr = rd[i].data;
137 name = (const char*) &rr[1];
138 if (0 == memcmp (&rh->authority,
139 &rr->pkey,
140 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
141 {
142 //Found!
143 GNUNET_asprintf (&result,
144 "%s.%s.gnu",
145 rh->node_queue_head->name,
146 name);
147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148 "Found path from %s\n", result);
149
150 rh->proc (rh->proc_cls, result);
151 cleanup_handle (rh);
152 GNUNET_free (result);
153 return;
154 } else {
155 if (rh->node_queue_head->depth >= rh->max_depth)
156 break;
157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
158 "Found REVERSE from %s\n", name);
159
160 rtn = GNUNET_new (struct ReverseTreeNode);
161 if (NULL == rh->node_queue_head->name)
162 rtn->name = GNUNET_strdup (name);
163 else
164 GNUNET_asprintf (&rtn->name,
165 "%s.%s",
166 rh->node_queue_head->name,
167 name);
168 rtn->depth = rh->node_queue_head->depth + 1;
169 rtn->pkey = rr->pkey;
170 GNUNET_CONTAINER_DLL_insert_tail (rh->node_queue_head,
171 rh->node_queue_tail,
172 rtn);
173 }
174 }
175
176 /**
177 * Done here remove node from queue
178 */
179 rtn = rh->node_queue_head;
180 GNUNET_CONTAINER_DLL_remove (rh->node_queue_head,
181 rh->node_queue_tail,
182 rtn);
183 if (NULL == rh->node_queue_head)
184 {
185 //No luck
186 rh->proc (rh->proc_cls, NULL);
187 cleanup_handle (rh);
188 return;
189 }
190 rh->rh = GNS_resolver_lookup (&rh->node_queue_head->pkey,
191 GNUNET_GNSRECORD_TYPE_REVERSE,
192 "+.gnu",
193 NULL,
194 GNUNET_GNS_LO_DEFAULT,
195 &handle_gns_result,
196 rh);
197}
198
199struct GNS_ReverserHandle *
200GNS_reverse_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *target,
201 const struct GNUNET_CRYPTO_EcdsaPublicKey *authority,
202 GNS_ReverseResultProcessor proc,
203 void *proc_cls)
204{
205 struct GNS_ReverserHandle *rh;
206 struct ReverseTreeNode *rtn;
207
208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
209 "Starting reverse resolution\n");
210 rh = GNUNET_new (struct GNS_ReverserHandle);
211 rh->proc = proc;
212 rh->proc_cls = proc_cls;
213 rtn = GNUNET_new (struct ReverseTreeNode);
214 rtn->name = NULL;
215 rtn->pkey = *target;
216 rtn->depth = 0;
217 GNUNET_CONTAINER_DLL_insert (rh->node_queue_head,
218 rh->node_queue_tail,
219 rtn);
220 rh->authority = *authority;
221 rh->max_depth = 3; //TODO make argument
222 rh->rh = GNS_resolver_lookup (target,
223 GNUNET_GNSRECORD_TYPE_REVERSE,
224 "+.gnu",
225 NULL,
226 GNUNET_GNS_LO_DEFAULT,
227 &handle_gns_result,
228 rh);
229 return rh;
230}
231
232/**
233 * Cancel active resolution (i.e. client disconnected).
234 *
235 * @param rh resolution to abort
236 */
237void
238GNS_reverse_lookup_cancel (struct GNS_ReverserHandle *rh)
239{
240 cleanup_handle (rh);
241 return;
242}
243
244
diff --git a/src/gns/gnunet-service-gns_reverser.h b/src/gns/gnunet-service-gns_reverser.h
new file mode 100644
index 000000000..ecec7d743
--- /dev/null
+++ b/src/gns/gnunet-service-gns_reverser.h
@@ -0,0 +1,72 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20/**
21 * @file gns/gnunet-service-gns_reverser.h
22 * @brief GNUnet GNS service
23 * @author Martin Schanzenbach
24 */
25#ifndef GNS_REVERSER_H
26#define GNS_REVERSER_H
27#include "gns.h"
28#include "gnunet_gns_service.h"
29
30/**
31 * Handle for an active request.
32 */
33struct GNS_ReverserHandle;
34
35
36/**
37 * Function called with results for a GNS resolution.
38 *
39 * @param cls closure
40 * @param rd_count number of records in @a rd
41 * @param rd records returned for the lookup
42 */
43typedef void (*GNS_ReverseResultProcessor)(void *cls,
44 const char *name);
45
46
47/**
48 * Reverse lookup of a specific zone
49 * calls RecordLookupProcessor on result or timeout
50 *
51 * @param target the zone to perform the lookup in
52 * @param authority the authority
53 * @param proc the processor to call
54 * @param proc_cls the closure to pass to @a proc
55 * @return handle to cancel operation
56 */
57struct GNS_ReverserHandle *
58GNS_reverse_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *target,
59 const struct GNUNET_CRYPTO_EcdsaPublicKey *authority,
60 GNS_ReverseResultProcessor proc,
61 void *proc_cls);
62
63
64/**
65 * Cancel active resolution (i.e. client disconnected).
66 *
67 * @param rh resolution to abort
68 */
69void
70GNS_reverse_lookup_cancel (struct GNS_ReverserHandle *rh);
71
72#endif
diff --git a/src/gns/plugin_gnsrecord_gns.c b/src/gns/plugin_gnsrecord_gns.c
index 360500af7..5faca4578 100644
--- a/src/gns/plugin_gnsrecord_gns.c
+++ b/src/gns/plugin_gnsrecord_gns.c
@@ -31,6 +31,7 @@
31#include "gnunet_gnsrecord_lib.h" 31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_dnsparser_lib.h" 32#include "gnunet_dnsparser_lib.h"
33#include "gnunet_gnsrecord_plugin.h" 33#include "gnunet_gnsrecord_plugin.h"
34#include <inttypes.h>
34 35
35 36
36/** 37/**
@@ -139,6 +140,30 @@ gns_value_to_string (void *cls,
139 GNUNET_free (ival); 140 GNUNET_free (ival);
140 return box_str; 141 return box_str;
141 } 142 }
143 case GNUNET_GNSRECORD_TYPE_REVERSE:
144 {
145 struct GNUNET_GNSRECORD_ReverseRecord rev;
146 char *rev_str;
147 char *pkey_str;
148
149 if (data_size < sizeof (struct GNUNET_GNSRECORD_ReverseRecord))
150 return NULL; /* malformed */
151
152 memcpy (&rev,
153 data,
154 sizeof (rev));
155 cdata = data;
156 pkey_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&rev.pkey);
157
158 GNUNET_asprintf (&rev_str,
159 "%s %s %"SCNu64,
160 &cdata[sizeof (rev)],
161 pkey_str,
162 rev.expiration.abs_value_us);
163 GNUNET_free (pkey_str);
164 return rev_str;
165
166 }
142 default: 167 default:
143 return NULL; 168 return NULL;
144 } 169 }
@@ -170,147 +195,184 @@ gns_string_to_value (void *cls,
170 switch (type) 195 switch (type)
171 { 196 {
172 197
173 case GNUNET_GNSRECORD_TYPE_PKEY: 198 case GNUNET_GNSRECORD_TYPE_PKEY:
174 if (GNUNET_OK != 199 if (GNUNET_OK !=
175 GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey)) 200 GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey))
176 {
177 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
178 _("Unable to parse PKEY record `%s'\n"),
179 s);
180 return GNUNET_SYSERR;
181 }
182 *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
183 GNUNET_memcpy (*data, &pkey, sizeof (pkey));
184 *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
185 return GNUNET_OK;
186
187 case GNUNET_GNSRECORD_TYPE_NICK:
188 *data = GNUNET_strdup (s);
189 *data_size = strlen (s);
190 return GNUNET_OK;
191 case GNUNET_GNSRECORD_TYPE_LEHO:
192 *data = GNUNET_strdup (s);
193 *data_size = strlen (s);
194 return GNUNET_OK;
195 case GNUNET_GNSRECORD_TYPE_GNS2DNS:
196 {
197 char nsbuf[514];
198 char *cpy;
199 char *at;
200 size_t off;
201
202 cpy = GNUNET_strdup (s);
203 at = strchr (cpy, '@');
204 if (NULL == at)
205 { 201 {
206 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 202 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
207 _("Unable to parse GNS2DNS record `%s'\n"), 203 _("Unable to parse PKEY record `%s'\n"),
208 s); 204 s);
209 GNUNET_free (cpy);
210 return GNUNET_SYSERR; 205 return GNUNET_SYSERR;
211 } 206 }
212 *at = '\0'; 207 *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
213 at++; 208 GNUNET_memcpy (*data, &pkey, sizeof (pkey));
209 *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
210 return GNUNET_OK;
214 211
215 off = 0; 212 case GNUNET_GNSRECORD_TYPE_NICK:
216 if ( (GNUNET_OK != 213 *data = GNUNET_strdup (s);
217 GNUNET_DNSPARSER_builder_add_name (nsbuf, 214 *data_size = strlen (s);
218 sizeof (nsbuf), 215 return GNUNET_OK;
219 &off, 216 case GNUNET_GNSRECORD_TYPE_LEHO:
220 cpy)) || 217 *data = GNUNET_strdup (s);
221 (GNUNET_OK != 218 *data_size = strlen (s);
222 GNUNET_DNSPARSER_builder_add_name (nsbuf, 219 return GNUNET_OK;
223 sizeof (nsbuf), 220 case GNUNET_GNSRECORD_TYPE_GNS2DNS:
224 &off,
225 at)) )
226 { 221 {
227 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 222 char nsbuf[514];
228 _("Failed to serialize GNS2DNS record with value `%s'\n"), 223 char *cpy;
229 s); 224 char *at;
225 size_t off;
226
227 cpy = GNUNET_strdup (s);
228 at = strchr (cpy, '@');
229 if (NULL == at)
230 {
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 _("Unable to parse GNS2DNS record `%s'\n"),
233 s);
234 GNUNET_free (cpy);
235 return GNUNET_SYSERR;
236 }
237 *at = '\0';
238 at++;
239
240 off = 0;
241 if ( (GNUNET_OK !=
242 GNUNET_DNSPARSER_builder_add_name (nsbuf,
243 sizeof (nsbuf),
244 &off,
245 cpy)) ||
246 (GNUNET_OK !=
247 GNUNET_DNSPARSER_builder_add_name (nsbuf,
248 sizeof (nsbuf),
249 &off,
250 at)) )
251 {
252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
253 _("Failed to serialize GNS2DNS record with value `%s'\n"),
254 s);
255 GNUNET_free (cpy);
256 return GNUNET_SYSERR;
257 }
230 GNUNET_free (cpy); 258 GNUNET_free (cpy);
231 return GNUNET_SYSERR; 259 *data_size = off;
260 *data = GNUNET_malloc (off);
261 GNUNET_memcpy (*data, nsbuf, off);
262 return GNUNET_OK;
232 } 263 }
233 GNUNET_free (cpy); 264 case GNUNET_GNSRECORD_TYPE_VPN:
234 *data_size = off;
235 *data = GNUNET_malloc (off);
236 GNUNET_memcpy (*data, nsbuf, off);
237 return GNUNET_OK;
238 }
239 case GNUNET_GNSRECORD_TYPE_VPN:
240 {
241 struct GNUNET_TUN_GnsVpnRecord *vpn;
242 char s_peer[103 + 1];
243 char s_serv[253 + 1];
244 unsigned int proto;
245
246 if (3 != SSCANF (s,
247 "%u %103s %253s",
248 &proto, s_peer, s_serv))
249 { 265 {
250 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 266 struct GNUNET_TUN_GnsVpnRecord *vpn;
251 _("Unable to parse VPN record string `%s'\n"), 267 char s_peer[103 + 1];
252 s); 268 char s_serv[253 + 1];
253 return GNUNET_SYSERR; 269 unsigned int proto;
270
271 if (3 != SSCANF (s,
272 "%u %103s %253s",
273 &proto, s_peer, s_serv))
274 {
275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
276 _("Unable to parse VPN record string `%s'\n"),
277 s);
278 return GNUNET_SYSERR;
279 }
280 *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
281 *data = vpn = GNUNET_malloc (*data_size);
282 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer,
283 strlen (s_peer),
284 &vpn->peer.public_key))
285 {
286 GNUNET_free (vpn);
287 *data_size = 0;
288 return GNUNET_SYSERR;
289 }
290 vpn->proto = htons ((uint16_t) proto);
291 strcpy ((char*)&vpn[1], s_serv);
292 return GNUNET_OK;
254 } 293 }
255 *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1; 294 case GNUNET_GNSRECORD_TYPE_BOX:
256 *data = vpn = GNUNET_malloc (*data_size);
257 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer,
258 strlen (s_peer),
259 &vpn->peer.public_key))
260 { 295 {
261 GNUNET_free (vpn); 296 struct GNUNET_GNSRECORD_BoxRecord *box;
262 *data_size = 0; 297 size_t rest;
263 return GNUNET_SYSERR; 298 unsigned int protocol;
299 unsigned int service;
300 unsigned int record_type;
301 void *bval;
302 size_t bval_size;
303
304 if (3 != SSCANF (s,
305 "%u %u %u ",
306 &protocol,
307 &service,
308 &record_type))
309 {
310 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
311 _("Unable to parse BOX record string `%s'\n"),
312 s);
313 return GNUNET_SYSERR;
314 }
315 rest = snprintf (NULL, 0,
316 "%u %u %u ",
317 protocol,
318 service,
319 record_type);
320 if (GNUNET_OK !=
321 GNUNET_GNSRECORD_string_to_value (record_type,
322 &s[rest],
323 &bval,
324 &bval_size))
325 return GNUNET_SYSERR;
326 *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
327 *data = box = GNUNET_malloc (*data_size);
328 box->protocol = htons (protocol);
329 box->service = htons (service);
330 box->record_type = htonl (record_type);
331 GNUNET_memcpy (&box[1],
332 bval,
333 bval_size);
334 GNUNET_free (bval);
335 return GNUNET_OK;
264 } 336 }
265 vpn->proto = htons ((uint16_t) proto); 337 case GNUNET_GNSRECORD_TYPE_REVERSE:
266 strcpy ((char*)&vpn[1], s_serv);
267 return GNUNET_OK;
268 }
269 case GNUNET_GNSRECORD_TYPE_BOX:
270 {
271 struct GNUNET_GNSRECORD_BoxRecord *box;
272 size_t rest;
273 unsigned int protocol;
274 unsigned int service;
275 unsigned int record_type;
276 void *bval;
277 size_t bval_size;
278
279 if (3 != SSCANF (s,
280 "%u %u %u ",
281 &protocol,
282 &service,
283 &record_type))
284 { 338 {
285 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 339 struct GNUNET_GNSRECORD_ReverseRecord *rev;
286 _("Unable to parse BOX record string `%s'\n"), 340 char known_by[253 + 1];
287 s); 341 struct GNUNET_TIME_Absolute expiration;
288 return GNUNET_SYSERR; 342
343 /* TODO: From crypto_ecc.c
344 * Why is this not a constant???
345 */
346 size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
347 if (enclen % 5 > 0)
348 enclen += 5 - enclen % 5;
349 enclen /= 5; /* 260/5 = 52 */
350 char pkey_str[enclen + 1];
351
352 if (3 != SSCANF (s,
353 "%253s %52s %"SCNu64,
354 known_by,
355 pkey_str,
356 &expiration.abs_value_us))
357 {
358 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
359 _("Unable to parse REVERSE record string `%s'\n"),
360 s);
361 return GNUNET_SYSERR;
362 }
363 *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1;
364 *data = rev = GNUNET_malloc (*data_size);
365 GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
366 strlen (pkey_str),
367 &rev->pkey);
368 rev->expiration = expiration;
369 GNUNET_memcpy (&rev[1],
370 known_by,
371 strlen (known_by));
372 return GNUNET_OK;
289 } 373 }
290 rest = snprintf (NULL, 0, 374 default:
291 "%u %u %u ", 375 return GNUNET_SYSERR;
292 protocol,
293 service,
294 record_type);
295 if (GNUNET_OK !=
296 GNUNET_GNSRECORD_string_to_value (record_type,
297 &s[rest],
298 &bval,
299 &bval_size))
300 return GNUNET_SYSERR;
301 *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
302 *data = box = GNUNET_malloc (*data_size);
303 box->protocol = htons (protocol);
304 box->service = htons (service);
305 box->record_type = htonl (record_type);
306 GNUNET_memcpy (&box[1],
307 bval,
308 bval_size);
309 GNUNET_free (bval);
310 return GNUNET_OK;
311 }
312 default:
313 return GNUNET_SYSERR;
314 } 376 }
315} 377}
316 378
@@ -329,6 +391,7 @@ static struct {
329 { "VPN", GNUNET_GNSRECORD_TYPE_VPN }, 391 { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
330 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS }, 392 { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
331 { "BOX", GNUNET_GNSRECORD_TYPE_BOX }, 393 { "BOX", GNUNET_GNSRECORD_TYPE_BOX },
394 { "REVERSE", GNUNET_GNSRECORD_TYPE_REVERSE },
332 { NULL, UINT32_MAX } 395 { NULL, UINT32_MAX }
333}; 396};
334 397
@@ -348,7 +411,7 @@ gns_typename_to_number (void *cls,
348 411
349 i=0; 412 i=0;
350 while ( (NULL != gns_name_map[i].name) && 413 while ( (NULL != gns_name_map[i].name) &&
351 (0 != strcasecmp (gns_typename, 414 (0 != strcasecmp (gns_typename,
352 gns_name_map[i].name)) ) 415 gns_name_map[i].name)) )
353 i++; 416 i++;
354 return gns_name_map[i].number; 417 return gns_name_map[i].number;
@@ -370,7 +433,7 @@ gns_number_to_typename (void *cls,
370 433
371 i=0; 434 i=0;
372 while ( (NULL != gns_name_map[i].name) && 435 while ( (NULL != gns_name_map[i].name) &&
373 (type != gns_name_map[i].number) ) 436 (type != gns_name_map[i].number) )
374 i++; 437 i++;
375 return gns_name_map[i].name; 438 return gns_name_map[i].name;
376} 439}
diff --git a/src/include/gnunet_gns_service.h b/src/include/gnunet_gns_service.h
index 1d74408fc..8a1099444 100644
--- a/src/include/gnunet_gns_service.h
+++ b/src/include/gnunet_gns_service.h
@@ -94,6 +94,16 @@ typedef void (*GNUNET_GNS_LookupResultProcessor) (void *cls,
94 uint32_t rd_count, 94 uint32_t rd_count,
95 const struct GNUNET_GNSRECORD_Data *rd); 95 const struct GNUNET_GNSRECORD_Data *rd);
96 96
97/**
98 * Iterator called on obtained result for a GNS lookup.
99 *
100 * @param cls closure
101 * @param rd_count number of records in @a rd
102 * @param rd the records in reply
103 */
104typedef void (*GNUNET_GNS_ReverseLookupResultProcessor) (void *cls,
105 const char* name);
106
97 107
98/** 108/**
99 * Options for the GNS lookup. 109 * Options for the GNS lookup.
@@ -146,6 +156,23 @@ GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle,
146 GNUNET_GNS_LookupResultProcessor proc, 156 GNUNET_GNS_LookupResultProcessor proc,
147 void *proc_cls); 157 void *proc_cls);
148 158
159/**
160 * Perform an asynchronous reverse lookup operation on the GNS.
161 *
162 * @param handle handle to the GNS service
163 * @param zone_key zone to find a name for
164 * @param root_key our zone
165 * @param proc processor to call on result
166 * @param proc_cls closure for @a proc
167 * @return handle to the request
168 */
169struct GNUNET_GNS_ReverseLookupRequest*
170GNUNET_GNS_reverse_lookup (struct GNUNET_GNS_Handle *handle,
171 const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
172 const struct GNUNET_CRYPTO_EcdsaPublicKey *root_key,
173 GNUNET_GNS_ReverseLookupResultProcessor proc,
174 void *proc_cls);
175
149 176
150/** 177/**
151 * Cancel pending lookup request 178 * Cancel pending lookup request
diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h
index b7920cbb8..985ae1f7a 100644
--- a/src/include/gnunet_gnsrecord_lib.h
+++ b/src/include/gnunet_gnsrecord_lib.h
@@ -108,6 +108,10 @@ extern "C"
108 */ 108 */
109#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546 109#define GNUNET_GNSRECORD_TYPE_ID_TOKEN_METADATA 65546
110 110
111/**
112 * Record type for reverse lookups
113 */
114#define GNUNET_GNSRECORD_TYPE_REVERSE 65548
111 115
112/** 116/**
113 * Flags that can be set for a record. 117 * Flags that can be set for a record.
@@ -286,6 +290,27 @@ struct GNUNET_GNSRECORD_BoxRecord
286 290
287}; 291};
288 292
293/**
294 * Record type used internally to keep track of reverse mappings into a
295 * namespace.
296 * The record contains data related to PKEY delegations from other namespaces to
297 * the namespace the record belongs to.
298 * It is exclusively found under the label ``+''.
299 */
300struct GNUNET_GNSRECORD_ReverseRecord
301{
302 /**
303 * The public key of the namespace the is delegating to our namespace
304 */
305 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
306
307 /**
308 * The expiration time of the delegation
309 */
310 struct GNUNET_TIME_Absolute expiration;
311
312 /* followed by the name the delegator uses to refer to our namespace */
313};
289 314
290GNUNET_NETWORK_STRUCT_END 315GNUNET_NETWORK_STRUCT_END
291 316
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index f9f6cbd9c..0da6780cb 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -1529,6 +1529,16 @@ extern "C"
1529 */ 1529 */
1530#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 501 1530#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 501
1531 1531
1532/**
1533 * Reverse lookup
1534 */
1535#define GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP 503
1536
1537/**
1538 * Response to reverse lookup
1539 */
1540#define GNUNET_MESSAGE_TYPE_GNS_REVERSE_LOOKUP_RESULT 504
1541
1532 1542
1533/******************************************************************************* 1543/*******************************************************************************
1534 * CONSENSUS message types 1544 * CONSENSUS message types