aboutsummaryrefslogtreecommitdiff
path: root/src/namestore/gnunet-namestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore/gnunet-namestore.c')
-rw-r--r--src/namestore/gnunet-namestore.c876
1 files changed, 503 insertions, 373 deletions
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
index 6444d446d..7288db902 100644
--- a/src/namestore/gnunet-namestore.c
+++ b/src/namestore/gnunet-namestore.c
@@ -27,11 +27,11 @@
27 */ 27 */
28#include "platform.h" 28#include "platform.h"
29#include <gnunet_util_lib.h> 29#include <gnunet_util_lib.h>
30#include <gnunet_dnsparser_lib.h>
31#include <gnunet_identity_service.h> 30#include <gnunet_identity_service.h>
32#include <gnunet_gnsrecord_lib.h> 31#include <gnunet_gnsrecord_lib.h>
33#include <gnunet_gns_service.h> 32#include <gnunet_gns_service.h>
34#include <gnunet_namestore_service.h> 33#include <gnunet_namestore_service.h>
34#include <inttypes.h>
35 35
36/** 36/**
37 * The upper bound for the zone iteration interval 37 * The upper bound for the zone iteration interval
@@ -119,11 +119,6 @@ static struct GNUNET_NAMESTORE_Handle *ns;
119static struct GNUNET_IDENTITY_PrivateKey zone_pkey; 119static struct GNUNET_IDENTITY_PrivateKey zone_pkey;
120 120
121/** 121/**
122 * Handle to identity lookup.
123 */
124static struct GNUNET_IDENTITY_EgoLookup *el;
125
126/**
127 * Identity service handle 122 * Identity service handle
128 */ 123 */
129static struct GNUNET_IDENTITY_Handle *idh; 124static struct GNUNET_IDENTITY_Handle *idh;
@@ -134,11 +129,6 @@ static struct GNUNET_IDENTITY_Handle *idh;
134static char *ego_name; 129static char *ego_name;
135 130
136/** 131/**
137 * Desired action is to add a record.
138 */
139static int add;
140
141/**
142 * Queue entry for the 'add-uri' operation. 132 * Queue entry for the 'add-uri' operation.
143 */ 133 */
144static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri; 134static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri;
@@ -168,6 +158,10 @@ static struct MarkedRecord *marked_head;
168 */ 158 */
169static struct MarkedRecord *marked_tail; 159static struct MarkedRecord *marked_tail;
170 160
161/**
162 * Configuration handle
163 */
164const struct GNUNET_CONFIGURATION_Handle *cfg;
171 165
172/** 166/**
173 * Ego list 167 * Ego list
@@ -180,14 +174,24 @@ static struct EgoEntry *ego_head;
180static struct EgoEntry *ego_tail; 174static struct EgoEntry *ego_tail;
181 175
182/** 176/**
177 * List iterator for the 'list' operation.
178 */
179static struct GNUNET_NAMESTORE_ZoneIterator *list_it;
180
181/**
182 * Run in read from stdin mode.
183 */
184static int read_from_stdin;
185
186/**
183 * Desired action is to list records. 187 * Desired action is to list records.
184 */ 188 */
185static int list; 189static int list;
186 190
187/** 191/**
188 * List iterator for the 'list' operation. 192 * Desired action is to add a record.
189 */ 193 */
190static struct GNUNET_NAMESTORE_ZoneIterator *list_it; 194static int add;
191 195
192/** 196/**
193 * Desired action is to remove a record. 197 * Desired action is to remove a record.
@@ -200,7 +204,7 @@ static int del;
200static int is_public; 204static int is_public;
201 205
202/** 206/**
203 * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW_RECORD) 207 * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW)
204 */ 208 */
205static int is_shadow; 209static int is_shadow;
206 210
@@ -210,6 +214,12 @@ static int is_shadow;
210static int omit_private; 214static int omit_private;
211 215
212/** 216/**
217 * Output in recordline format
218 */
219static int output_recordline;
220
221
222/**
213 * Purge zone contents 223 * Purge zone contents
214 */ 224 */
215static int purge_zone; 225static int purge_zone;
@@ -240,6 +250,11 @@ static struct GNUNET_NAMESTORE_QueueEntry *del_qe;
240static struct GNUNET_NAMESTORE_QueueEntry *set_qe; 250static struct GNUNET_NAMESTORE_QueueEntry *set_qe;
241 251
242/** 252/**
253 * Queue entry for begin/commit
254 */
255static struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
256
257/**
243 * Name of the records to add/list/remove. 258 * Name of the records to add/list/remove.
244 */ 259 */
245static char *name; 260static char *name;
@@ -325,37 +340,186 @@ static struct RecordSetEntry *recordset;
325static struct GNUNET_SCHEDULER_Task *purge_task; 340static struct GNUNET_SCHEDULER_Task *purge_task;
326 341
327/** 342/**
328 * Task run on shutdown. Cleans up everything. 343 * Parse expiration time.
329 * 344 *
330 * @param cls unused 345 * @param expirationstring text to parse
346 * @param[out] etime_is_rel set to #GNUNET_YES if time is relative
347 * @param[out] etime set to expiration time (abs or rel)
348 * @return #GNUNET_OK on success
331 */ 349 */
350static int
351parse_expiration (const char *expirationstring,
352 int *etime_is_rel,
353 uint64_t *etime)
354{
355 struct GNUNET_TIME_Relative etime_rel;
356 struct GNUNET_TIME_Absolute etime_abs;
357
358 if (0 == strcmp (expirationstring, "never"))
359 {
360 *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
361 *etime_is_rel = GNUNET_NO;
362 return GNUNET_OK;
363 }
364 if (GNUNET_OK ==
365 GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
366 {
367 *etime_is_rel = GNUNET_YES;
368 *etime = etime_rel.rel_value_us;
369 if (GNUNET_TIME_relative_cmp (etime_rel, <, WARN_RELATIVE_EXPIRATION_LIMIT))
370 {
371 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
372 "Relative expiration times of less than %s are not recommended. To improve availability, consider increasing this value.\n",
373 GNUNET_STRINGS_relative_time_to_string (
374 WARN_RELATIVE_EXPIRATION_LIMIT, GNUNET_NO));
375 }
376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
377 "Storing record with relative expiration time of %s\n",
378 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
379 return GNUNET_OK;
380 }
381 if (GNUNET_OK ==
382 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
383 {
384 *etime_is_rel = GNUNET_NO;
385 *etime = etime_abs.abs_value_us;
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
387 "Storing record with absolute expiration time of %s\n",
388 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
389 return GNUNET_OK;
390 }
391 return GNUNET_SYSERR;
392}
393
394
395static int
396parse_recordline (const char *line)
397{
398 struct RecordSetEntry **head = &recordset;
399 struct RecordSetEntry *r;
400 struct GNUNET_GNSRECORD_Data record;
401 char *cp;
402 char *tok;
403 char *saveptr;
404 void *raw_data;
405
406 cp = GNUNET_strdup (line);
407 tok = strtok_r (cp, " ", &saveptr);
408 if (NULL == tok)
409 {
410 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
411 _ ("Missing entries in record line `%s'.\n"),
412 line);
413 GNUNET_free (cp);
414 return GNUNET_SYSERR;
415 }
416 record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
417 if (UINT32_MAX == record.record_type)
418 {
419 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok);
420 GNUNET_free (cp);
421 return GNUNET_SYSERR;
422 }
423 tok = strtok_r (NULL, " ", &saveptr);
424 if (NULL == tok)
425 {
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427 _ ("Empty record line argument is not allowed.\n"));
428 GNUNET_free (cp);
429 return GNUNET_SYSERR;
430 }
431 if (1 != sscanf (tok, "%" SCNu64, &record.expiration_time))
432 {
433 fprintf (stderr,
434 _ ("Error parsing expiration time %s.\n"), tok);
435 GNUNET_free (cp);
436 return GNUNET_SYSERR;
437 }
438 tok = strtok_r (NULL, " ", &saveptr);
439 if (NULL == tok)
440 {
441 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
442 _ ("Empty record line argument is not allowed.\n"));
443 GNUNET_free (cp);
444 return GNUNET_SYSERR;
445 }
446 record.flags = GNUNET_GNSRECORD_RF_NONE;
447 if (NULL != strchr (tok, (unsigned char) 'r'))
448 record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
449 if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
450 record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
451 if (NULL != strchr (tok, (unsigned char) 'S'))
452 record.flags |= GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
453 if (NULL != strchr (tok, (unsigned char) 's'))
454 record.flags |= GNUNET_GNSRECORD_RF_SHADOW;
455 if (NULL != strchr (tok, (unsigned char) 'C'))
456 record.flags |= GNUNET_GNSRECORD_RF_CRITICAL;
457 tok += strlen (tok) + 1;
458 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type,
459 tok,
460 &raw_data,
461 &record.data_size))
462 {
463 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
464 _ ("Invalid record data for type %s: `%s'.\n"),
465 GNUNET_GNSRECORD_number_to_typename (record.record_type),
466 tok);
467 return GNUNET_SYSERR;
468 }
469
470 r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size);
471 r->next = *head;
472 record.data = &r[1];
473 memcpy (&r[1], raw_data, record.data_size);
474 GNUNET_free (raw_data);
475 r->record = record;
476 *head = r;
477 return GNUNET_OK;
478}
479
332static void 480static void
333do_shutdown (void *cls) 481reset_handles (void)
334{ 482{
335 struct EgoEntry *ego_entry;
336 struct EgoEntry *ego_tmp;
337 struct MarkedRecord *mrec; 483 struct MarkedRecord *mrec;
338 struct MarkedRecord *mrec_tmp; 484 struct MarkedRecord *mrec_tmp;
339 (void) cls; 485 struct RecordSetEntry *rs_entry;
486
487 rs_entry = recordset;
488 while (NULL != (rs_entry = recordset))
489 {
490 recordset = recordset->next;
491 GNUNET_free (rs_entry);
492 }
493 recordset = NULL;
340 if (NULL != ego_name) 494 if (NULL != ego_name)
341 { 495 {
342 GNUNET_free (ego_name); 496 GNUNET_free (ego_name);
343 ego_name = NULL; 497 ego_name = NULL;
344 } 498 }
345 if (NULL != purge_task) 499 if (NULL != name)
346 { 500 {
347 GNUNET_SCHEDULER_cancel (purge_task); 501 GNUNET_free (name);
348 purge_task = NULL; 502 name = NULL;
349 } 503 }
350 if (NULL != idh) 504 if (NULL != value)
351 { 505 {
352 GNUNET_IDENTITY_disconnect (idh); 506 GNUNET_free (value);
353 idh = NULL; 507 value = NULL;
508 }
509 if (NULL != uri)
510 {
511 GNUNET_free (uri);
512 uri = NULL;
513 }
514 if (NULL != expirationstring)
515 {
516 GNUNET_free (expirationstring);
517 expirationstring = NULL;
354 } 518 }
355 if (NULL != el) 519 if (NULL != purge_task)
356 { 520 {
357 GNUNET_IDENTITY_ego_lookup_cancel (el); 521 GNUNET_SCHEDULER_cancel (purge_task);
358 el = NULL; 522 purge_task = NULL;
359 } 523 }
360 for (mrec = marked_head; NULL != mrec;) 524 for (mrec = marked_head; NULL != mrec;)
361 { 525 {
@@ -364,13 +528,6 @@ do_shutdown (void *cls)
364 GNUNET_free (mrec_tmp->name); 528 GNUNET_free (mrec_tmp->name);
365 GNUNET_free (mrec_tmp); 529 GNUNET_free (mrec_tmp);
366 } 530 }
367 for (ego_entry = ego_head; NULL != ego_entry;)
368 {
369 ego_tmp = ego_entry;
370 ego_entry = ego_entry->next;
371 GNUNET_free (ego_tmp->identifier);
372 GNUNET_free (ego_tmp);
373 }
374 if (NULL != list_it) 531 if (NULL != list_it)
375 { 532 {
376 GNUNET_NAMESTORE_zone_iteration_stop (list_it); 533 GNUNET_NAMESTORE_zone_iteration_stop (list_it);
@@ -401,17 +558,12 @@ do_shutdown (void *cls)
401 GNUNET_NAMESTORE_cancel (del_qe); 558 GNUNET_NAMESTORE_cancel (del_qe);
402 del_qe = NULL; 559 del_qe = NULL;
403 } 560 }
404 if (NULL != ns) 561 if (NULL != reverse_qe)
405 { 562 {
406 GNUNET_NAMESTORE_disconnect (ns); 563 GNUNET_NAMESTORE_cancel (reverse_qe);
407 ns = NULL; 564 reverse_qe = NULL;
408 } 565 }
409 memset (&zone_pkey, 0, sizeof(zone_pkey)); 566 memset (&zone_pkey, 0, sizeof(zone_pkey));
410 if (NULL != uri)
411 {
412 GNUNET_free (uri);
413 uri = NULL;
414 }
415 if (NULL != zm) 567 if (NULL != zm)
416 { 568 {
417 GNUNET_NAMESTORE_zone_monitor_stop (zm); 569 GNUNET_NAMESTORE_zone_monitor_stop (zm);
@@ -422,18 +574,83 @@ do_shutdown (void *cls)
422 GNUNET_free (data); 574 GNUNET_free (data);
423 data = NULL; 575 data = NULL;
424 } 576 }
577 if (NULL != typestring)
578 {
579 GNUNET_free (typestring);
580 typestring = NULL;
581 }
582 list = 0;
583 is_public = 0;
584 is_shadow = 0;
585 purge_zone = 0;
425} 586}
426 587
427 588
589
428/** 590/**
429 * Check if we are finished, and if so, perform shutdown. 591 * Task run on shutdown. Cleans up everything.
592 *
593 * @param cls unused
430 */ 594 */
431static void 595static void
432test_finished () 596do_shutdown (void *cls)
433{ 597{
434 if ((NULL == add_qe) && (NULL == add_qe_uri) && (NULL == get_qe) && 598 struct EgoEntry *ego_entry;
435 (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it)) 599 struct EgoEntry *ego_tmp;
436 GNUNET_SCHEDULER_shutdown (); 600 (void) cls;
601
602 reset_handles ();
603 if (NULL != ns_qe)
604 {
605 GNUNET_NAMESTORE_cancel (ns_qe);
606 ns_qe = NULL;
607 }
608 if (NULL != ns)
609 {
610 GNUNET_NAMESTORE_disconnect (ns);
611 ns = NULL;
612 }
613 if (NULL != idh)
614 {
615 GNUNET_IDENTITY_disconnect (idh);
616 idh = NULL;
617 }
618 for (ego_entry = ego_head; NULL != ego_entry;)
619 {
620 ego_tmp = ego_entry;
621 ego_entry = ego_entry->next;
622 GNUNET_free (ego_tmp->identifier);
623 GNUNET_free (ego_tmp);
624 }
625}
626
627static void
628commit_cb (void *cls, enum GNUNET_ErrorCode ec)
629{
630 ns_qe = NULL;
631 if (GNUNET_EC_NONE != ec)
632 {
633 fprintf (stderr, "Failed to commit to namestore: `%s'\n",
634 GNUNET_ErrorCode_get_hint (ec));
635 ret = 1;
636 }
637 GNUNET_SCHEDULER_shutdown ();
638}
639
640static void
641process_command_stdin ();
642
643
644static void
645finish_command (void)
646{
647 reset_handles ();
648 if (read_from_stdin)
649 {
650 process_command_stdin ();
651 return;
652 }
653 ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL);
437} 654}
438 655
439 656
@@ -452,7 +669,7 @@ add_continuation (void *cls, enum GNUNET_ErrorCode ec)
452 ret = 1; 669 ret = 1;
453 } 670 }
454 ret = 0; 671 ret = 0;
455 test_finished (); 672 finish_command ();
456} 673}
457 674
458 675
@@ -467,7 +684,7 @@ del_continuation (void *cls, enum GNUNET_ErrorCode ec)
467 _ ("Deleting record failed: %s\n"), GNUNET_ErrorCode_get_hint ( 684 _ ("Deleting record failed: %s\n"), GNUNET_ErrorCode_get_hint (
468 ec)); 685 ec));
469 } 686 }
470 test_finished (); 687 finish_command ();
471} 688}
472 689
473static void 690static void
@@ -496,7 +713,7 @@ purge_next_record (void *cls)
496 if (NULL == marked_head) 713 if (NULL == marked_head)
497 { 714 {
498 ret = 0; 715 ret = 0;
499 test_finished (); 716 finish_command ();
500 return; 717 return;
501 } 718 }
502 mrec = marked_head; 719 mrec = marked_head;
@@ -527,7 +744,7 @@ zone_iteration_finished (void *cls)
527 return; 744 return;
528 } 745 }
529 ret = 0; 746 ret = 0;
530 test_finished (); 747 finish_command ();
531} 748}
532 749
533 750
@@ -541,7 +758,7 @@ zone_iteration_error_cb (void *cls)
541 list_it = NULL; 758 list_it = NULL;
542 fprintf (stderr, "Error iterating over zone\n"); 759 fprintf (stderr, "Error iterating over zone\n");
543 ret = 1; 760 ret = 1;
544 test_finished (); 761 finish_command ();
545} 762}
546 763
547static void 764static void
@@ -681,18 +898,33 @@ display_record (const struct GNUNET_IDENTITY_PrivateKey *zone_key,
681 at.abs_value_us = rd[i].expiration_time; 898 at.abs_value_us = rd[i].expiration_time;
682 ets = GNUNET_STRINGS_absolute_time_to_string (at); 899 ets = GNUNET_STRINGS_absolute_time_to_string (at);
683 } 900 }
684 fprintf (stdout, 901 char flgstr[16];
685 "\t%s: %s (%s)\t%s\t%s\n", 902 sprintf (flgstr, "[%s%s%s%s%s]",
686 typestr, 903 (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE) ? "" : "p",
687 s, 904 (rd[i].flags & GNUNET_GNSRECORD_RF_SUPPLEMENTAL) ? "S" : "",
688 ets, 905 (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION) ? "r" : "",
689 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE" 906 (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW) ? "S" : "",
907 (rd[i].flags & GNUNET_GNSRECORD_RF_CRITICAL) ? "C" : "");
908 if (output_recordline)
909 fprintf (stdout,
910 " %s %" PRIu64 " %s %s\n",
911 typestr,
912 rd[i].expiration_time,
913 flgstr,
914 s);
915 else
916 fprintf (stdout,
917 "\t%s: %s (%s)\t%s\t%s\n",
918 typestr,
919 s,
920 ets,
921 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE"
690 : "PUBLIC", 922 : "PUBLIC",
691 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) ? "SHADOW" 923 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW)) ? "SHADOW"
692 : ""); 924 : "");
693 GNUNET_free (s); 925 GNUNET_free (s);
694 } 926 }
695 fprintf (stdout, "%s", "\n"); 927 // fprintf (stdout, "%s", "\n");
696} 928}
697 929
698static void 930static void
@@ -797,7 +1029,7 @@ display_record_lookup (void *cls,
797 (void) zone_key; 1029 (void) zone_key;
798 get_qe = NULL; 1030 get_qe = NULL;
799 display_record (zone_key, rname, rd_len, rd); 1031 display_record (zone_key, rname, rd_len, rd);
800 test_finished (); 1032 finish_command ();
801} 1033}
802 1034
803 1035
@@ -838,7 +1070,7 @@ lookup_error_cb (void *cls)
838 (void) cls; 1070 (void) cls;
839 get_qe = NULL; 1071 get_qe = NULL;
840 fprintf (stderr, "%s", "Failed to lookup record.\n"); 1072 fprintf (stderr, "%s", "Failed to lookup record.\n");
841 test_finished (); 1073 finish_command ();
842} 1074}
843 1075
844 1076
@@ -852,7 +1084,7 @@ add_error_cb (void *cls)
852 add_qe = NULL; 1084 add_qe = NULL;
853 GNUNET_break (0); 1085 GNUNET_break (0);
854 ret = 1; 1086 ret = 1;
855 test_finished (); 1087 finish_command ();
856} 1088}
857 1089
858 1090
@@ -883,7 +1115,7 @@ get_existing_record (void *cls,
883 { 1115 {
884 GNUNET_break (0); 1116 GNUNET_break (0);
885 ret = 1; 1117 ret = 1;
886 test_finished (); 1118 finish_command ();
887 return; 1119 return;
888 } 1120 }
889 1121
@@ -904,7 +1136,7 @@ get_existing_record (void *cls,
904 "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"), 1136 "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"),
905 rec_name); 1137 rec_name);
906 ret = 1; 1138 ret = 1;
907 test_finished (); 1139 finish_command ();
908 return; 1140 return;
909 } 1141 }
910 break; 1142 break;
@@ -917,7 +1149,7 @@ get_existing_record (void *cls,
917 rde->data_size = data_size; 1149 rde->data_size = data_size;
918 rde->record_type = type; 1150 rde->record_type = type;
919 if (1 == is_shadow) 1151 if (1 == is_shadow)
920 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; 1152 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW;
921 if (1 != is_public) 1153 if (1 != is_public)
922 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; 1154 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
923 rde->expiration_time = etime; 1155 rde->expiration_time = etime;
@@ -974,7 +1206,7 @@ handle_reverse_lookup (void *cls,
974 fprintf (stdout, "%s\n", reverse_pkey); 1206 fprintf (stdout, "%s\n", reverse_pkey);
975 else 1207 else
976 fprintf (stdout, "%s.%s\n", label, ego_name); 1208 fprintf (stdout, "%s.%s\n", label, ego_name);
977 test_finished (); 1209 finish_command ();
978} 1210}
979 1211
980 1212
@@ -988,7 +1220,7 @@ del_lookup_error_cb (void *cls)
988 del_qe = NULL; 1220 del_qe = NULL;
989 GNUNET_break (0); 1221 GNUNET_break (0);
990 ret = 1; 1222 ret = 1;
991 test_finished (); 1223 finish_command ();
992} 1224}
993 1225
994 1226
@@ -1025,7 +1257,7 @@ del_monitor (void *cls,
1025 "There are no records under label `%s' that could be deleted.\n"), 1257 "There are no records under label `%s' that could be deleted.\n"),
1026 label); 1258 label);
1027 ret = 1; 1259 ret = 1;
1028 test_finished (); 1260 finish_command ();
1029 return; 1261 return;
1030 } 1262 }
1031 if ((NULL == value) && (NULL == typestring)) 1263 if ((NULL == value) && (NULL == typestring))
@@ -1067,7 +1299,7 @@ del_monitor (void *cls,
1067 _ ( 1299 _ (
1068 "There are no records under label `%s' that match the request for deletion.\n"), 1300 "There are no records under label `%s' that match the request for deletion.\n"),
1069 label); 1301 label);
1070 test_finished (); 1302 finish_command ();
1071 return; 1303 return;
1072 } 1304 }
1073 /* delete everything but what we copied to 'rdx' */ 1305 /* delete everything but what we copied to 'rdx' */
@@ -1081,59 +1313,6 @@ del_monitor (void *cls,
1081} 1313}
1082 1314
1083 1315
1084/**
1085 * Parse expiration time.
1086 *
1087 * @param expirationstring text to parse
1088 * @param[out] etime_is_rel set to #GNUNET_YES if time is relative
1089 * @param[out] etime set to expiration time (abs or rel)
1090 * @return #GNUNET_OK on success
1091 */
1092static int
1093parse_expiration (const char *expirationstring,
1094 int *etime_is_rel,
1095 uint64_t *etime)
1096{
1097 struct GNUNET_TIME_Relative etime_rel;
1098 struct GNUNET_TIME_Absolute etime_abs;
1099
1100 if (0 == strcmp (expirationstring, "never"))
1101 {
1102 *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
1103 *etime_is_rel = GNUNET_NO;
1104 return GNUNET_OK;
1105 }
1106 if (GNUNET_OK ==
1107 GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
1108 {
1109 *etime_is_rel = GNUNET_YES;
1110 *etime = etime_rel.rel_value_us;
1111 if (GNUNET_TIME_relative_cmp (etime_rel, <, WARN_RELATIVE_EXPIRATION_LIMIT))
1112 {
1113 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1114 "Relative expiration times of less than %s are not recommended. To improve availability, consider increasing this value.\n",
1115 GNUNET_STRINGS_relative_time_to_string (
1116 WARN_RELATIVE_EXPIRATION_LIMIT, GNUNET_NO));
1117 }
1118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1119 "Storing record with relative expiration time of %s\n",
1120 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
1121 return GNUNET_OK;
1122 }
1123 if (GNUNET_OK ==
1124 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
1125 {
1126 *etime_is_rel = GNUNET_NO;
1127 *etime = etime_abs.abs_value_us;
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1129 "Storing record with absolute expiration time of %s\n",
1130 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
1131 return GNUNET_OK;
1132 }
1133 return GNUNET_SYSERR;
1134}
1135
1136
1137static void 1316static void
1138replace_cont (void *cls, enum GNUNET_ErrorCode ec) 1317replace_cont (void *cls, enum GNUNET_ErrorCode ec)
1139{ 1318{
@@ -1147,7 +1326,7 @@ replace_cont (void *cls, enum GNUNET_ErrorCode ec)
1147 GNUNET_ErrorCode_get_hint (ec)); 1326 GNUNET_ErrorCode_get_hint (ec));
1148 ret = 1; /* fail from 'main' */ 1327 ret = 1; /* fail from 'main' */
1149 } 1328 }
1150 GNUNET_SCHEDULER_shutdown (); 1329 finish_command ();
1151} 1330}
1152 1331
1153 1332
@@ -1173,14 +1352,7 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1173 { 1352 {
1174 /* nothing more to be done */ 1353 /* nothing more to be done */
1175 fprintf (stderr, _ ("No options given\n")); 1354 fprintf (stderr, _ ("No options given\n"));
1176 GNUNET_SCHEDULER_shutdown (); 1355 finish_command ();
1177 return;
1178 }
1179 ns = GNUNET_NAMESTORE_connect (cfg);
1180 if (NULL == ns)
1181 {
1182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1183 _ ("Failed to connect to namestore\n"));
1184 return; 1356 return;
1185 } 1357 }
1186 1358
@@ -1190,24 +1362,23 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1190 unsigned int rd_count; 1362 unsigned int rd_count;
1191 struct GNUNET_GNSRECORD_Data *rd; 1363 struct GNUNET_GNSRECORD_Data *rd;
1192 1364
1193 if (NULL == ego_name) 1365 /* FIXME: We could easily support append and delete with this as well */
1366 if (! add)
1194 { 1367 {
1195 fprintf (stderr, 1368 fprintf (stderr, _ ("Recordlines only work with option `%s'\n"),
1196 _ ("Missing option `%s' for operation `%s'\n"), 1369 "-a");
1197 "-z",
1198 _ ("replace"));
1199 GNUNET_SCHEDULER_shutdown ();
1200 ret = 1; 1370 ret = 1;
1371 finish_command ();
1201 return; 1372 return;
1202 } 1373 }
1203 if (NULL == name) 1374 if (NULL == name)
1204 { 1375 {
1205 fprintf (stderr, 1376 fprintf (stderr,
1206 _ ("Missing option `%s' for operation `%s'\n"), 1377 _ ("Missing option `%s' for operation `%s'\n"),
1207 "-R", 1378 "-n",
1208 _ ("replace")); 1379 _ ("name"));
1209 GNUNET_SCHEDULER_shutdown ();
1210 ret = 1; 1380 ret = 1;
1381 finish_command ();
1211 return; 1382 return;
1212 } 1383 }
1213 rd_count = 0; 1384 rd_count = 0;
@@ -1235,8 +1406,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1235 if (0 == strlen (nickstring)) 1406 if (0 == strlen (nickstring))
1236 { 1407 {
1237 fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring); 1408 fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring);
1238 GNUNET_SCHEDULER_shutdown ();
1239 ret = 1; 1409 ret = 1;
1410 finish_command ();
1240 return; 1411 return;
1241 } 1412 }
1242 add = 1; 1413 add = 1;
@@ -1258,8 +1429,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1258 _ ("Missing option `%s' for operation `%s'\n"), 1429 _ ("Missing option `%s' for operation `%s'\n"),
1259 "-z", 1430 "-z",
1260 _ ("add")); 1431 _ ("add"));
1261 GNUNET_SCHEDULER_shutdown ();
1262 ret = 1; 1432 ret = 1;
1433 finish_command ();
1263 return; 1434 return;
1264 } 1435 }
1265 if (NULL == name) 1436 if (NULL == name)
@@ -1268,8 +1439,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1268 _ ("Missing option `%s' for operation `%s'\n"), 1439 _ ("Missing option `%s' for operation `%s'\n"),
1269 "-n", 1440 "-n",
1270 _ ("add")); 1441 _ ("add"));
1271 GNUNET_SCHEDULER_shutdown ();
1272 ret = 1; 1442 ret = 1;
1443 finish_command ();
1273 return; 1444 return;
1274 } 1445 }
1275 if (NULL == typestring) 1446 if (NULL == typestring)
@@ -1278,16 +1449,16 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1278 _ ("Missing option `%s' for operation `%s'\n"), 1449 _ ("Missing option `%s' for operation `%s'\n"),
1279 "-t", 1450 "-t",
1280 _ ("add")); 1451 _ ("add"));
1281 GNUNET_SCHEDULER_shutdown ();
1282 ret = 1; 1452 ret = 1;
1453 finish_command ();
1283 return; 1454 return;
1284 } 1455 }
1285 type = GNUNET_GNSRECORD_typename_to_number (typestring); 1456 type = GNUNET_GNSRECORD_typename_to_number (typestring);
1286 if (UINT32_MAX == type) 1457 if (UINT32_MAX == type)
1287 { 1458 {
1288 fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring); 1459 fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring);
1289 GNUNET_SCHEDULER_shutdown ();
1290 ret = 1; 1460 ret = 1;
1461 finish_command ();
1291 return; 1462 return;
1292 } 1463 }
1293 if ((GNUNET_DNSPARSER_TYPE_SRV == type) || 1464 if ((GNUNET_DNSPARSER_TYPE_SRV == type) ||
@@ -1297,8 +1468,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1297 fprintf (stderr, 1468 fprintf (stderr,
1298 _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'")); 1469 _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"));
1299 fprintf (stderr, ", please use a `BOX' record instead\n"); 1470 fprintf (stderr, ", please use a `BOX' record instead\n");
1300 GNUNET_SCHEDULER_shutdown ();
1301 ret = 1; 1471 ret = 1;
1472 finish_command ();
1302 return; 1473 return;
1303 } 1474 }
1304 if (NULL == value) 1475 if (NULL == value)
@@ -1308,7 +1479,7 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1308 "-V", 1479 "-V",
1309 _ ("add")); 1480 _ ("add"));
1310 ret = 1; 1481 ret = 1;
1311 GNUNET_SCHEDULER_shutdown (); 1482 finish_command ();
1312 return; 1483 return;
1313 } 1484 }
1314 if (GNUNET_OK != 1485 if (GNUNET_OK !=
@@ -1318,8 +1489,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1318 _ ("Value `%s' invalid for record type `%s'\n"), 1489 _ ("Value `%s' invalid for record type `%s'\n"),
1319 value, 1490 value,
1320 typestring); 1491 typestring);
1321 GNUNET_SCHEDULER_shutdown ();
1322 ret = 1; 1492 ret = 1;
1493 finish_command ();
1323 return; 1494 return;
1324 } 1495 }
1325 if (NULL == expirationstring) 1496 if (NULL == expirationstring)
@@ -1328,15 +1499,15 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1328 _ ("Missing option `%s' for operation `%s'\n"), 1499 _ ("Missing option `%s' for operation `%s'\n"),
1329 "-e", 1500 "-e",
1330 _ ("add")); 1501 _ ("add"));
1331 GNUNET_SCHEDULER_shutdown ();
1332 ret = 1; 1502 ret = 1;
1503 finish_command ();
1333 return; 1504 return;
1334 } 1505 }
1335 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) 1506 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1336 { 1507 {
1337 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); 1508 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1338 GNUNET_SCHEDULER_shutdown ();
1339 ret = 1; 1509 ret = 1;
1510 finish_command ();
1340 return; 1511 return;
1341 } 1512 }
1342 add_qe = GNUNET_NAMESTORE_records_lookup (ns, 1513 add_qe = GNUNET_NAMESTORE_records_lookup (ns,
@@ -1355,8 +1526,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1355 _ ("Missing option `%s' for operation `%s'\n"), 1526 _ ("Missing option `%s' for operation `%s'\n"),
1356 "-z", 1527 "-z",
1357 _ ("del")); 1528 _ ("del"));
1358 GNUNET_SCHEDULER_shutdown ();
1359 ret = 1; 1529 ret = 1;
1530 finish_command ();
1360 return; 1531 return;
1361 } 1532 }
1362 if (NULL == name) 1533 if (NULL == name)
@@ -1365,8 +1536,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1365 _ ("Missing option `%s' for operation `%s'\n"), 1536 _ ("Missing option `%s' for operation `%s'\n"),
1366 "-n", 1537 "-n",
1367 _ ("del")); 1538 _ ("del"));
1368 GNUNET_SCHEDULER_shutdown ();
1369 ret = 1; 1539 ret = 1;
1540 finish_command ();
1370 return; 1541 return;
1371 } 1542 }
1372 del_qe = GNUNET_NAMESTORE_records_lookup (ns, 1543 del_qe = GNUNET_NAMESTORE_records_lookup (ns,
@@ -1398,8 +1569,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1398 _ ("Missing option `%s' for operation `%s'\n"), 1569 _ ("Missing option `%s' for operation `%s'\n"),
1399 "-z", 1570 "-z",
1400 _ ("purge-zone")); 1571 _ ("purge-zone"));
1401 GNUNET_SCHEDULER_shutdown ();
1402 ret = 1; 1572 ret = 1;
1573 finish_command ();
1403 return; 1574 return;
1404 } 1575 }
1405 list_it = GNUNET_NAMESTORE_zone_iteration_start2 (ns, 1576 list_it = GNUNET_NAMESTORE_zone_iteration_start2 (ns,
@@ -1423,8 +1594,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1423 _ ("Missing option `%s' for operation `%s'\n"), 1594 _ ("Missing option `%s' for operation `%s'\n"),
1424 "-z", 1595 "-z",
1425 _ ("list")); 1596 _ ("list"));
1426 GNUNET_SCHEDULER_shutdown ();
1427 ret = 1; 1597 ret = 1;
1598 finish_command ();
1428 return; 1599 return;
1429 } 1600 }
1430 get_qe = GNUNET_NAMESTORE_records_lookup (ns, 1601 get_qe = GNUNET_NAMESTORE_records_lookup (ns,
@@ -1457,8 +1628,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1457 _ ("Missing option `%s' for operation `%s'\n"), 1628 _ ("Missing option `%s' for operation `%s'\n"),
1458 "-z", 1629 "-z",
1459 _ ("reverse-pkey")); 1630 _ ("reverse-pkey"));
1460 GNUNET_SCHEDULER_shutdown ();
1461 ret = 1; 1631 ret = 1;
1632 finish_command ();
1462 return; 1633 return;
1463 } 1634 }
1464 if (GNUNET_OK != 1635 if (GNUNET_OK !=
@@ -1468,7 +1639,9 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1468 fprintf (stderr, 1639 fprintf (stderr,
1469 _ ("Invalid public key for reverse lookup `%s'\n"), 1640 _ ("Invalid public key for reverse lookup `%s'\n"),
1470 reverse_pkey); 1641 reverse_pkey);
1471 GNUNET_SCHEDULER_shutdown (); 1642 ret = 1;
1643 finish_command ();
1644 return;
1472 } 1645 }
1473 reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns, 1646 reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns,
1474 &zone_pkey, 1647 &zone_pkey,
@@ -1489,8 +1662,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1489 _ ("Missing option `%s' for operation `%s'\n"), 1662 _ ("Missing option `%s' for operation `%s'\n"),
1490 "-z", 1663 "-z",
1491 _ ("uri")); 1664 _ ("uri"));
1492 GNUNET_SCHEDULER_shutdown ();
1493 ret = 1; 1665 ret = 1;
1666 finish_command ();
1494 return; 1667 return;
1495 } 1668 }
1496 1669
@@ -1502,8 +1675,8 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1502 GNUNET_IDENTITY_public_key_from_string (sh, &pkey))) 1675 GNUNET_IDENTITY_public_key_from_string (sh, &pkey)))
1503 { 1676 {
1504 fprintf (stderr, _ ("Invalid URI `%s'\n"), uri); 1677 fprintf (stderr, _ ("Invalid URI `%s'\n"), uri);
1505 GNUNET_SCHEDULER_shutdown ();
1506 ret = 1; 1678 ret = 1;
1679 finish_command ();
1507 return; 1680 return;
1508 } 1681 }
1509 if (NULL == expirationstring) 1682 if (NULL == expirationstring)
@@ -1512,15 +1685,15 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1512 _ ("Missing option `%s' for operation `%s'\n"), 1685 _ ("Missing option `%s' for operation `%s'\n"),
1513 "-e", 1686 "-e",
1514 _ ("add")); 1687 _ ("add"));
1515 GNUNET_SCHEDULER_shutdown ();
1516 ret = 1; 1688 ret = 1;
1689 finish_command ();
1517 return; 1690 return;
1518 } 1691 }
1519 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime)) 1692 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1520 { 1693 {
1521 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring); 1694 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1522 GNUNET_SCHEDULER_shutdown ();
1523 ret = 1; 1695 ret = 1;
1696 finish_command ();
1524 return; 1697 return;
1525 } 1698 }
1526 memset (&rd, 0, sizeof(rd)); 1699 memset (&rd, 0, sizeof(rd));
@@ -1531,7 +1704,7 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1531 if (GNUNET_YES == etime_is_rel) 1704 if (GNUNET_YES == etime_is_rel)
1532 rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; 1705 rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1533 if (1 == is_shadow) 1706 if (1 == is_shadow)
1534 rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; 1707 rd.flags |= GNUNET_GNSRECORD_RF_SHADOW;
1535 add_qe_uri = GNUNET_NAMESTORE_records_store (ns, 1708 add_qe_uri = GNUNET_NAMESTORE_records_store (ns,
1536 &zone_pkey, 1709 &zone_pkey,
1537 sname, 1710 sname,
@@ -1556,34 +1729,153 @@ run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
1556 } 1729 }
1557} 1730}
1558 1731
1732#define MAX_LINE_LEN 4086
1733
1734#define MAX_ARGS 20
1735
1736static int
1737get_identity_for_string (const char *str,
1738 struct GNUNET_IDENTITY_PrivateKey *zk)
1739{
1740 const struct GNUNET_IDENTITY_PrivateKey *privkey;
1741 struct GNUNET_IDENTITY_PublicKey pubkey;
1742 struct GNUNET_IDENTITY_PublicKey ego_pubkey;
1743 struct EgoEntry *ego_entry;
1744
1745 if (GNUNET_OK == GNUNET_IDENTITY_public_key_from_string (str,
1746 &pubkey))
1747 {
1748 for (ego_entry = ego_head;
1749 NULL != ego_entry; ego_entry = ego_entry->next)
1750 {
1751 privkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1752 GNUNET_IDENTITY_ego_get_public_key (ego_entry->ego, &ego_pubkey);
1753 if (0 == memcmp (&ego_pubkey, &pubkey, sizeof (pubkey)))
1754 {
1755 *zk = *privkey;
1756 return GNUNET_OK;
1757 }
1758 }
1759 }
1760 else
1761 {
1762 for (ego_entry = ego_head; NULL != ego_entry; ego_entry = ego_entry->next)
1763 {
1764 /** FIXME: Check for zTLD? **/
1765 if (0 != strcmp (str, ego_entry->identifier))
1766 continue;
1767 *zk = *GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1768 return GNUNET_OK;
1769 }
1770 }
1771 return GNUNET_NO;
1772}
1559 1773
1560/**
1561 * Callback invoked from identity service with ego information.
1562 * An @a ego of NULL means the ego was not found.
1563 *
1564 * @param cls closure with the configuration
1565 * @param ego an ego known to identity service, or NULL
1566 */
1567static void 1774static void
1568identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego) 1775process_command_stdin ()
1569{ 1776{
1570 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 1777 char buf[MAX_LINE_LEN];
1778 static struct GNUNET_IDENTITY_PrivateKey next_zone_key;
1779 static char next_name[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
1780 static int finished = GNUNET_NO;
1781 static int have_next_zonekey = GNUNET_NO;
1782 int zonekey_set = GNUNET_NO;
1783 char *tmp;
1571 1784
1572 el = NULL;
1573 1785
1574 if (NULL == ego) 1786 if (GNUNET_YES == have_next_zonekey)
1575 { 1787 {
1576 if (NULL != ego_name) 1788 zone_pkey = next_zone_key;
1789 if (NULL != name)
1790 GNUNET_free (name);
1791 name = GNUNET_strdup (next_name);
1792 zonekey_set = GNUNET_YES;
1793 }
1794 while (NULL != fgets (buf, sizeof (buf), stdin))
1795 {
1796 if (1 >= strlen (buf))
1797 continue;
1798 if (buf[strlen (buf) - 1] == '\n')
1799 buf[strlen (buf) - 1] = '\0';
1800 /**
1801 * Check if this is a new name. If yes, and we have records, store them.
1802 */
1803 if (buf[strlen (buf) - 1] == ':')
1577 { 1804 {
1578 fprintf (stderr, 1805 memset (next_name, 0, sizeof (next_name));
1579 _ ("Ego `%s' not known to identity service\n"), 1806 strncpy (next_name, buf, strlen (buf) - 1);
1580 ego_name); 1807 tmp = strchr (next_name, '.');
1808 if (NULL == tmp)
1809 {
1810 fprintf (stderr, "Error parsing name `%s'\n", next_name);
1811 ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL);
1812 ret = 1;
1813 return;
1814 }
1815 if (GNUNET_OK != get_identity_for_string (tmp + 1, &next_zone_key))
1816 {
1817 fprintf (stderr, "Error parsing zone name `%s'\n", tmp + 1);
1818 ret = 1;
1819 GNUNET_SCHEDULER_shutdown ();
1820 return;
1821 }
1822 *tmp = '\0';
1823 have_next_zonekey = GNUNET_YES;
1824 /* Run a command for the previous record set */
1825 if (NULL != recordset)
1826 {
1827 run_with_zone_pkey (cfg);
1828 return;
1829 }
1830 zone_pkey = next_zone_key;
1831 if (NULL != name)
1832 GNUNET_free (name);
1833 name = GNUNET_strdup (next_name);
1834 zonekey_set = GNUNET_YES;
1835 continue;
1836 }
1837 if (GNUNET_NO == zonekey_set)
1838 {
1839 fprintf (stderr, "Warning, encountered recordline without zone\n");
1840 continue;
1581 } 1841 }
1842 parse_recordline (buf);
1843 }
1844 if (GNUNET_NO == finished)
1845 {
1846 if (NULL != recordset)
1847 {
1848 if (GNUNET_YES == zonekey_set)
1849 {
1850 run_with_zone_pkey (cfg); /** one last time **/
1851 finished = GNUNET_YES;
1852 return;
1853 }
1854 fprintf (stderr, "Warning, encountered recordline without zone\n");
1855 }
1856 }
1857 ns_qe = GNUNET_NAMESTORE_transaction_commit (ns, &commit_cb, NULL);
1858 return;
1859}
1860
1861
1862static void
1863begin_cb (void *cls, enum GNUNET_ErrorCode ec)
1864{
1865 ns_qe = NULL;
1866 if (GNUNET_EC_NONE != ec)
1867 {
1868 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1869 "Failed to start transaction: %s\n",
1870 GNUNET_ErrorCode_get_hint (ec));
1582 GNUNET_SCHEDULER_shutdown (); 1871 GNUNET_SCHEDULER_shutdown ();
1583 ret = -1;
1584 return; 1872 return;
1585 } 1873 }
1586 zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); 1874 if (read_from_stdin)
1875 {
1876 process_command_stdin ();
1877 return;
1878 }
1587 run_with_zone_pkey (cfg); 1879 run_with_zone_pkey (cfg);
1588} 1880}
1589 1881
@@ -1606,7 +1898,6 @@ id_connect_cb (void *cls,
1606 void **ctx, 1898 void **ctx,
1607 const char *name) 1899 const char *name)
1608{ 1900{
1609 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1610 struct GNUNET_IDENTITY_PublicKey pk; 1901 struct GNUNET_IDENTITY_PublicKey pk;
1611 struct EgoEntry *ego_entry; 1902 struct EgoEntry *ego_entry;
1612 1903
@@ -1621,17 +1912,20 @@ id_connect_cb (void *cls,
1621 GNUNET_CONTAINER_DLL_insert_tail (ego_head, 1912 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
1622 ego_tail, 1913 ego_tail,
1623 ego_entry); 1914 ego_entry);
1915 if ((NULL != ego_name) &&
1916 (0 == strcmp (name, ego_name)))
1917 zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
1624 return; 1918 return;
1625 } 1919 }
1626 if (NULL != ego) 1920 if (NULL != ego)
1627 return; 1921 return;
1628 if (NULL == ego_name) 1922 ns_qe = GNUNET_NAMESTORE_transaction_begin (ns, &begin_cb, (void *) cfg);
1629 run_with_zone_pkey (cfg);
1630 else
1631 el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg);
1632} 1923}
1633 1924
1634 1925
1926
1927
1928
1635/** 1929/**
1636 * Main function that will be run. 1930 * Main function that will be run.
1637 * 1931 *
@@ -1644,202 +1938,36 @@ static void
1644run (void *cls, 1938run (void *cls,
1645 char *const *args, 1939 char *const *args,
1646 const char *cfgfile, 1940 const char *cfgfile,
1647 const struct GNUNET_CONFIGURATION_Handle *cfg) 1941 const struct GNUNET_CONFIGURATION_Handle *_cfg)
1648{ 1942{
1649 const char *pkey_str;
1650
1651 (void) cls; 1943 (void) cls;
1652 (void) args; 1944 (void) args;
1653 (void) cfgfile; 1945 (void) cfgfile;
1946 cfg = _cfg;
1654 if (NULL != args[0]) 1947 if (NULL != args[0])
1655 GNUNET_log ( 1948 GNUNET_log (
1656 GNUNET_ERROR_TYPE_WARNING, 1949 GNUNET_ERROR_TYPE_WARNING,
1657 _ ("Superfluous command line arguments (starting with `%s') ignored\n"), 1950 _ ("Superfluous command line arguments (starting with `%s') ignored\n"),
1658 args[0]); 1951 args[0]);
1659 if ((NULL != args[0]) && (NULL == uri))
1660 uri = GNUNET_strdup (args[0]);
1661 1952
1662 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg); 1953 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg);
1663 pkey_str = getenv ("GNUNET_NAMESTORE_EGO_PRIVATE_KEY"); 1954 ns = GNUNET_NAMESTORE_connect (cfg);
1664 if (NULL != pkey_str) 1955 if (NULL == ns)
1665 { 1956 {
1666 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pkey_str, 1957 fprintf (stderr, _ ("Failed to connect to namestore\n"));
1667 strlen (pkey_str), 1958 GNUNET_SCHEDULER_shutdown ();
1668 &zone_pkey,
1669 sizeof(zone_pkey)))
1670 {
1671 fprintf (stderr,
1672 "Malformed private key `%s' in $%s\n",
1673 pkey_str,
1674 "GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
1675 ret = 1;
1676 GNUNET_SCHEDULER_shutdown ();
1677 return;
1678 }
1679 run_with_zone_pkey (cfg);
1680 return; 1959 return;
1681 } 1960 }
1682 idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg); 1961 idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg);
1683 if (NULL == idh) 1962 if (NULL == idh)
1684 fprintf (stderr, _ ("Cannot connect to identity service\n"));
1685 ret = -1;
1686}
1687
1688
1689/**
1690 * Command-line option parser function that allows the user to specify
1691 * a complete record as one argument for adding/removing. A pointer
1692 * to the head of the list of record sets must be passed as the "scls"
1693 * argument.
1694 *
1695 * @param ctx command line processor context
1696 * @param scls must be of type "struct GNUNET_FS_Uri **"
1697 * @param option name of the option (typically 'R')
1698 * @param value command line argument given; format is
1699 * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs),
1700 * always given in seconds (without the unit),
1701 * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or
1702 * a combination of 's' (shadow) and 'p' (public) and VALUE is the
1703 * value (in human-readable format)
1704 * @return #GNUNET_OK on success
1705 */
1706static int
1707multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
1708 void *scls,
1709 const char *option,
1710 const char *value)
1711{
1712 struct RecordSetEntry **head = scls;
1713 struct RecordSetEntry *r;
1714 struct GNUNET_GNSRECORD_Data record;
1715 char *cp;
1716 char *tok;
1717 char *saveptr;
1718 int etime_is_rel;
1719 void *raw_data;
1720
1721 (void) ctx;
1722 (void) option;
1723 cp = GNUNET_strdup (value);
1724 tok = strtok_r (cp, " ", &saveptr);
1725 if (NULL == tok)
1726 {
1727 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1728 _ ("Empty record line argument is not allowed.\n"));
1729 GNUNET_free (cp);
1730 return GNUNET_SYSERR;
1731 }
1732 {
1733 char *etime_in_s;
1734
1735 GNUNET_asprintf (&etime_in_s, "%s s", tok);
1736 if (GNUNET_OK !=
1737 parse_expiration (etime_in_s, &etime_is_rel, &record.expiration_time))
1738 {
1739 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1740 _ ("Invalid expiration time `%s' (must be without unit)\n"),
1741 tok);
1742 GNUNET_free (cp);
1743 GNUNET_free (etime_in_s);
1744 return GNUNET_SYSERR;
1745 }
1746 GNUNET_free (etime_in_s);
1747 }
1748 tok = strtok_r (NULL, " ", &saveptr);
1749 if (NULL == tok)
1750 {
1751 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1752 _ ("Missing entries in record line `%s'.\n"),
1753 value);
1754 GNUNET_free (cp);
1755 return GNUNET_SYSERR;
1756 }
1757 record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
1758 if (UINT32_MAX == record.record_type)
1759 {
1760 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok);
1761 GNUNET_free (cp);
1762 return GNUNET_SYSERR;
1763 }
1764 tok = strtok_r (NULL, " ", &saveptr);
1765 if (NULL == tok)
1766 { 1963 {
1767 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1964 ret = -1;
1768 _ ("Missing entries in record line `%s'.\n"), 1965 fprintf (stderr, _ ("Cannot connect to identity service\n"));
1769 value); 1966 GNUNET_SCHEDULER_shutdown ();
1770 GNUNET_free (cp);
1771 return GNUNET_SYSERR;
1772 }
1773 record.flags = GNUNET_GNSRECORD_RF_NONE;
1774 if (etime_is_rel)
1775 record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1776 if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
1777 record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1778 if (NULL != strchr (tok, (unsigned char) 's'))
1779 record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
1780 /* find beginning of record value */
1781 tok = strchr (&value[tok - cp], (unsigned char) ' ');
1782 if (NULL == tok)
1783 {
1784 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1785 _ ("Missing entries in record line `%s'.\n"),
1786 value);
1787 GNUNET_free (cp);
1788 return GNUNET_SYSERR;
1789 }
1790 GNUNET_free (cp);
1791 tok++; /* skip space */
1792 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type,
1793 tok,
1794 &raw_data,
1795 &record.data_size))
1796 {
1797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1798 _ ("Invalid record data for type %s: `%s'.\n"),
1799 GNUNET_GNSRECORD_number_to_typename (record.record_type),
1800 tok);
1801 return GNUNET_SYSERR;
1802 } 1967 }
1803
1804 r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size);
1805 r->next = *head;
1806 record.data = &r[1];
1807 memcpy (&r[1], raw_data, record.data_size);
1808 GNUNET_free (raw_data);
1809 r->record = record;
1810 *head = r;
1811 return GNUNET_OK;
1812} 1968}
1813 1969
1814 1970
1815/**
1816 * Allow user to specify keywords.
1817 *
1818 * @param shortName short name of the option
1819 * @param name long name of the option
1820 * @param argumentHelp help text for the option argument
1821 * @param description long help text for the option
1822 * @param[out] topKeywords set to the desired value
1823 */
1824struct GNUNET_GETOPT_CommandLineOption
1825multirecord_option (char shortName,
1826 const char *name,
1827 const char *argumentHelp,
1828 const char *description,
1829 struct RecordSetEntry **rs)
1830{
1831 struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName,
1832 .name = name,
1833 .argumentHelp = argumentHelp,
1834 .description = description,
1835 .require_argument = 1,
1836 .processor =
1837 &multirecord_process,
1838 .scls = (void *) rs };
1839
1840 return clo;
1841}
1842
1843 1971
1844/** 1972/**
1845 * The main function for gnunet-namestore. 1973 * The main function for gnunet-namestore.
@@ -1851,6 +1979,7 @@ multirecord_option (char shortName,
1851int 1979int
1852main (int argc, char *const *argv) 1980main (int argc, char *const *argv)
1853{ 1981{
1982 int lret;
1854 struct GNUNET_GETOPT_CommandLineOption options[] = 1983 struct GNUNET_GETOPT_CommandLineOption options[] =
1855 { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add), 1984 { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add),
1856 GNUNET_GETOPT_option_flag ('d', 1985 GNUNET_GETOPT_option_flag ('d',
@@ -1861,6 +1990,10 @@ main (int argc, char *const *argv)
1861 "display", 1990 "display",
1862 gettext_noop ("display records"), 1991 gettext_noop ("display records"),
1863 &list), 1992 &list),
1993 GNUNET_GETOPT_option_flag ('S',
1994 "from-stdin",
1995 gettext_noop ("read commands from stdin"),
1996 &read_from_stdin),
1864 GNUNET_GETOPT_option_string ( 1997 GNUNET_GETOPT_option_string (
1865 'e', 1998 'e',
1866 "expiration", 1999 "expiration",
@@ -1885,19 +2018,16 @@ main (int argc, char *const *argv)
1885 gettext_noop ( 2018 gettext_noop (
1886 "name of the record to add/delete/display"), 2019 "name of the record to add/delete/display"),
1887 &name), 2020 &name),
1888 GNUNET_GETOPT_option_string ('r', 2021 GNUNET_GETOPT_option_flag ('r',
1889 "reverse", 2022 "recordline",
1890 "PKEY", 2023 gettext_noop ("Output in recordline format"),
2024 &output_recordline),
2025 GNUNET_GETOPT_option_string ('Z',
2026 "zone-to-name",
2027 "KEY",
1891 gettext_noop ( 2028 gettext_noop (
1892 "determine our name for the given PKEY"), 2029 "determine our name for the given KEY"),
1893 &reverse_pkey), 2030 &reverse_pkey),
1894 multirecord_option (
1895 'R',
1896 "replace",
1897 "RECORDLINE",
1898 gettext_noop (
1899 "set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"),
1900 &recordset),
1901 GNUNET_GETOPT_option_string ('t', 2031 GNUNET_GETOPT_option_string ('t',
1902 "type", 2032 "type",
1903 "TYPE", 2033 "TYPE",
@@ -1956,7 +2086,7 @@ main (int argc, char *const *argv)
1956 "name of the ego controlling the zone"), 2086 "name of the ego controlling the zone"),
1957 &ego_name), 2087 &ego_name),
1958 GNUNET_GETOPT_OPTION_END }; 2088 GNUNET_GETOPT_OPTION_END };
1959 int lret; 2089
1960 2090
1961 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 2091 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1962 return 2; 2092 return 2;