/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-namestore.c * @brief command line tool to manipulate the local zone * @author Christian Grothoff * * TODO: * - test */ #include "platform.h" #include #include #include #include /** * Handle to the namestore. */ static struct GNUNET_NAMESTORE_Handle *ns; /** * Private key for the our zone. */ static struct GNUNET_CRYPTO_EccPrivateKey zone_pkey; /** * Handle to identity lookup. */ static struct GNUNET_IDENTITY_EgoLookup *el; /** * Name of the ego controlling the zone. */ static char *ego_name; /** * Desired action is to add a record. */ static int add; /** * Iterator for the 'add' operation. */ static struct GNUNET_NAMESTORE_ZoneIterator *add_zit; /** * Queue entry for the 'add-uri' operation. */ static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri; /** * Queue entry for the 'add' operation. */ static struct GNUNET_NAMESTORE_QueueEntry *add_qe; /** * Queue entry for the 'list' operation (in combination with a name). */ static struct GNUNET_NAMESTORE_QueueEntry *list_qe; /** * Queue entry for the 'reverse lookup' operation (in combination with a name). */ static struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; /** * Desired action is to list records. */ static int list; /** * List iterator for the 'list' operation. */ static struct GNUNET_NAMESTORE_ZoneIterator *list_it; /** * Desired action is to remove a record. */ static int del; /** * Is record public (opposite of #GNUNET_NAMESTORE_RF_PRIVATE) */ static int public; /** * Is record a shadow record (#GNUNET_NAMESTORE_RF_SHADOW_RECORD) */ static int shadow; /** * Queue entry for the 'del' operation. */ static struct GNUNET_NAMESTORE_QueueEntry *del_qe; /** * Name of the records to add/list/remove. */ static char *name; /** * Value of the record to add/remove. */ static char *value; /** * URI to import. */ static char *uri; /** * Reverse lookup to perform. */ static char *reverse_pkey; /** * Type of the record to add/remove, NULL to remove all. */ static char *typestring; /** * Desired expiration time. */ static char *expirationstring; /** * Global return value */ static int ret; /** * Type string converted to DNS type value. */ static uint32_t type; /** * Value in binary format. */ static void *data; /** * Number of bytes in 'data'. */ static size_t data_size; /** * Expirationstring converted to relative time. */ static struct GNUNET_TIME_Relative etime_rel; /** * Expirationstring converted to absolute time. */ static struct GNUNET_TIME_Absolute etime_abs; /** * Is expiration time relative or absolute time? */ static int etime_is_rel = GNUNET_SYSERR; /** * Monitor handle. */ static struct GNUNET_NAMESTORE_ZoneMonitor *zm; /** * Enables monitor mode. */ static int monitor; /** * Task run on shutdown. Cleans up everything. * * @param cls unused * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != el) { GNUNET_IDENTITY_ego_lookup_cancel (el); el = NULL; } if (NULL != list_it) { GNUNET_NAMESTORE_zone_iteration_stop (list_it); list_it = NULL; } if (NULL != add_qe) { GNUNET_NAMESTORE_cancel (add_qe); add_qe = NULL; } if (NULL != list_qe) { GNUNET_NAMESTORE_cancel (list_qe); list_qe = NULL; } if (NULL != add_qe_uri) { GNUNET_NAMESTORE_cancel (add_qe_uri); add_qe_uri = NULL; } if (NULL != del_qe) { GNUNET_NAMESTORE_cancel (del_qe); del_qe = NULL; } if (NULL != ns) { GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } memset (&zone_pkey, 0, sizeof (zone_pkey)); if (NULL != uri) { GNUNET_free (uri); uri = NULL; } if (NULL != zm) { GNUNET_NAMESTORE_zone_monitor_stop (zm); zm = NULL; } if (NULL != data) { GNUNET_free (data); data = NULL; } } /** * Check if we are finished, and if so, perform shutdown. */ static void test_finished () { if ( (NULL == add_qe) && (NULL == list_qe) && (NULL == add_qe_uri) && (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it) ) GNUNET_SCHEDULER_shutdown (); } /** * Continuation called to notify client about result of the * operation. * * @param cls closure, location of the QueueEntry pointer to NULL out * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) * #GNUNET_NO if content was already there * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ static void add_continuation (void *cls, int32_t success, const char *emsg) { struct GNUNET_NAMESTORE_QueueEntry **qe = cls; *qe = NULL; if (GNUNET_YES != success) { fprintf (stderr, _("Adding record failed: %s\n"), (GNUNET_NO == success) ? "record exists" : emsg); if (GNUNET_NO != success) ret = 1; } test_finished (); } /** * Continuation called to notify client about result of the * operation. * * @param cls closure, unused * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) * #GNUNET_NO if content was already there * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ static void del_continuation (void *cls, int32_t success, const char *emsg) { del_qe = NULL; if (success != GNUNET_YES) fprintf (stderr, _("Deleting record failed: %s\n"), emsg); test_finished (); } /** * Process a record that was stored in the namestore. * * @param cls closure * @param zone_key private key of the zone * @param name name that is being mapped (at most 255 characters long) * @param rd_len number of entries in @a rd array * @param rd array of records with data to store */ static void display_record (void *cls, const struct GNUNET_CRYPTO_EccPrivateKey *zone_key, const char *name, unsigned int rd_len, const struct GNUNET_NAMESTORE_RecordData *rd) { const char *typestring; char *s; unsigned int i; const char *ets; struct GNUNET_TIME_Absolute at; struct GNUNET_TIME_Relative rt; if (NULL == name) { list_it = NULL; test_finished (); return; } FPRINTF (stdout, "%s:\n", name); for (i=0;idata = data; rde->data_size = data_size; rde->record_type = type; if (1 != shadow) rde->flags |= GNUNET_NAMESTORE_RF_SHADOW_RECORD; if (1 != public) rde->flags |= GNUNET_NAMESTORE_RF_PRIVATE; if (GNUNET_YES == etime_is_rel) { rde->expiration_time = etime_rel.rel_value_us; rde->flags |= GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION; } else if (GNUNET_NO == etime_is_rel) rde->expiration_time = etime_abs.abs_value_us; else rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; GNUNET_assert (NULL != name); add_qe = GNUNET_NAMESTORE_records_store (ns, &zone_pkey, name, rd_count + 1, rde, &add_continuation, &add_qe); /* only cancel if we were not told that this was the end of the iteration already */ if (NULL != rec_name) GNUNET_NAMESTORE_zone_iteration_stop (add_zit); add_zit = NULL; } /** * Process a record that was stored in the namestore in a block. * * @param cls closure, NULL * @param rd_len number of entries in @a rd array * @param rd array of records with data to store */ static void display_records_from_block (void *cls, unsigned int rd_len, const struct GNUNET_NAMESTORE_RecordData *rd) { const char *typestring; char *s; unsigned int i; if (0 == rd_len) { FPRINTF (stdout, _("No records found for `%s'"), name); return; } FPRINTF (stdout, "%s:\n", name); for (i=0;i