-copied block-related functions from namestore to namecache
[oweals/gnunet.git] / src / namecache / gnunet-namecache.c
1
2 /*
3      This file is part of GNUnet.
4      (C) 2012, 2013 Christian Grothoff (and other contributing authors)
5
6      GNUnet is free software; you can redistribute it and/or modify
7      it under the terms of the GNU General Public License as published
8      by the Free Software Foundation; either version 3, or (at your
9      option) any later version.
10
11      GNUnet is distributed in the hope that it will be useful, but
12      WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      General Public License for more details.
15
16      You should have received a copy of the GNU General Public License
17      along with GNUnet; see the file COPYING.  If not, write to the
18      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19      Boston, MA 02111-1307, USA.
20 */
21 /**
22  * @file gnunet-namecache.c
23  * @brief command line tool to inspect the name cache
24  * @author Christian Grothoff
25  *
26  * TODO:
27  * - test
28  */
29 #include "platform.h"
30 #include <gnunet_util_lib.h>
31 #include <gnunet_dnsparser_lib.h>
32 #include <gnunet_identity_service.h>
33 #include <gnunet_gnsrecord_lib.h>
34 #include <gnunet_namecache_service.h>
35 #include <gnunet_namestore_service.h>
36
37
38 /**
39  * Handle to the namecache.
40  */
41 static struct GNUNET_NAMECACHE_Handle *ns;
42
43 /**
44  * Queue entry for the 'query' operation.
45  */
46 static struct GNUNET_NAMECACHE_QueueEntry *qe;
47
48 /**
49  * Name (label) of the records to list.
50  */
51 static char *name;
52
53 /**
54  * Public key of the zone to look in.
55  */
56 static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
57
58 /**
59  * Public key of the zone to look in, in ASCII.
60  */
61 static char *pkey;
62
63 /**
64  * Global return value
65  */
66 static int ret;
67
68
69 /**
70  * Task run on shutdown.  Cleans up everything.
71  *
72  * @param cls unused
73  * @param tc scheduler context
74  */
75 static void
76 do_shutdown (void *cls,
77              const struct GNUNET_SCHEDULER_TaskContext *tc)
78 {
79   if (NULL != qe)
80   {
81     GNUNET_NAMECACHE_cancel (qe);
82     qe = NULL;
83   }
84   if (NULL != ns)
85   {
86     GNUNET_NAMECACHE_disconnect (ns);
87     ns = NULL;
88   }
89 }
90
91
92 /**
93  * Process a record that was stored in the namecache in a block.
94  *
95  * @param cls closure, NULL
96  * @param rd_len number of entries in @a rd array
97  * @param rd array of records with data to store
98  */
99 static void
100 display_records_from_block (void *cls,
101                             unsigned int rd_len,
102                             const struct GNUNET_NAMESTORE_RecordData *rd)
103 {
104   const char *typestring;
105   char *s;
106   unsigned int i;
107
108   if (0 == rd_len)
109   {
110     FPRINTF (stdout,
111              _("No records found for `%s'"),
112              name);
113     return;
114   }
115   FPRINTF (stdout,
116            "%s:\n",
117            name);
118   for (i=0;i<rd_len;i++)
119   {
120     typestring = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
121     s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
122                                           rd[i].data,
123                                           rd[i].data_size);
124     if (NULL == s)
125     {
126       FPRINTF (stdout, _("\tCorrupt or unsupported record of type %u\n"),
127                (unsigned int) rd[i].record_type);
128       continue;
129     }
130     FPRINTF (stdout,
131              "\t%s: %s\n",
132              typestring,
133              s);
134     GNUNET_free (s);
135   }
136   FPRINTF (stdout, "%s", "\n");
137 }
138
139
140 /**
141  * Display block obtained from listing (by name).
142  *
143  * @param cls NULL
144  * @param block NULL if not found
145  */
146 static void
147 handle_block (void *cls,
148               const struct GNUNET_NAMESTORE_Block *block)
149 {
150   qe = NULL;
151   if (NULL == block)
152   {
153     fprintf (stderr,
154              "No matching block found\n");
155   }
156   else if (GNUNET_OK !=
157            GNUNET_NAMESTORE_block_decrypt (block,
158                                            &pubkey,
159                                            name,
160                                            &display_records_from_block,
161                                            NULL))
162   {
163     fprintf (stderr,
164              "Failed to decrypt block!\n");
165   }
166   GNUNET_SCHEDULER_shutdown ();
167 }
168
169
170 /**
171  * Main function that will be run.
172  *
173  * @param cls closure
174  * @param args remaining command-line arguments
175  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
176  * @param cfg configuration
177  */
178 static void
179 run (void *cls, char *const *args, const char *cfgfile,
180      const struct GNUNET_CONFIGURATION_Handle *cfg)
181 {
182   struct GNUNET_HashCode dhash;
183
184   if (NULL == pkey)
185   {
186     fprintf (stderr,
187              _("You must specify which zone should be accessed\n"));
188     return;
189   }
190
191   if (GNUNET_OK !=
192       GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey,
193                                                   strlen (pkey),
194                                                   &pubkey))
195   {
196     fprintf (stderr,
197              _("Invalid public key for reverse lookup `%s'\n"),
198              pkey);
199     GNUNET_SCHEDULER_shutdown ();
200     return;
201   }
202   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
203                                 &do_shutdown,
204                                 NULL);
205   GNUNET_NAMESTORE_query_from_public_key (&pubkey,
206                                           name,
207                                           &dhash);
208   qe = GNUNET_NAMECACHE_lookup_block (ns,
209                                       &dhash,
210                                       &handle_block,
211                                       NULL);
212 }
213
214
215 /**
216  * The main function for gnunet-namecache.
217  *
218  * @param argc number of arguments from the command line
219  * @param argv command line arguments
220  * @return 0 ok, 1 on error
221  */
222 int
223 main (int argc, char *const *argv)
224 {
225   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
226     {'n', "name", "NAME",
227      gettext_noop ("name of the record to add/delete/display"), 1,
228      &GNUNET_GETOPT_set_string, &name},
229     {'z', "zone", "PKEY",
230      gettext_noop ("spezifies the public key of the zone to look in"), 1,
231      &GNUNET_GETOPT_set_string, &pkey},
232     GNUNET_GETOPT_OPTION_END
233   };
234
235   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
236     return 2;
237
238   GNUNET_log_setup ("gnunet-namecache", "WARNING", NULL);
239   if (GNUNET_OK !=
240       GNUNET_PROGRAM_run (argc, argv, "gnunet-namecache",
241                           _("GNUnet zone manipulation tool"),
242                           options,
243                           &run, NULL))
244   {
245     GNUNET_free ((void*) argv);
246     return 1;
247   }
248   GNUNET_free ((void*) argv);
249   return ret;
250 }
251
252 /* end of gnunet-namecache.c */