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