- fix compile error
[oweals/gnunet.git] / src / gns / gnunet-gns.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file gnunet-gns.c
22  * @brief command line tool to access distributed GNS
23  * @author Christian Grothoff
24  *
25  * TODO:
26  * - everything
27  */
28 #include "platform.h"
29 #include <gnunet_util_lib.h>
30 #include <gnunet_dnsparser_lib.h>
31 #include <gnunet_namestore_service.h>
32 #include <gnunet_gns_service.h>
33
34 /**
35  * Handle to GNS service.
36  */
37 static struct GNUNET_GNS_Handle *gns;
38
39 /**
40  * GNS name to shorten. (-s option)
41  */
42 static char *shorten_name;
43
44 /**
45  * GNS name to lookup. (-u option)
46  */
47 static char *lookup_name;
48
49
50 /**
51  * record type to look up (-t option)
52  */
53 static char *lookup_type;
54
55 /**
56  * name to look up authority for (-a option)
57  */
58 static char *auth_name;
59
60 /**
61  * raw output
62  */
63 static int raw = 0;
64
65 static enum GNUNET_GNS_RecordType rtype;
66
67 /* Handle to lookup request */
68 static struct GNUNET_GNS_LookupRequest *lookup_request;
69
70 /* Handle to shorten request */
71 static struct GNUNET_GNS_ShortenRequest *shorten_request;
72
73 /* Handle to get authority request */
74 static struct GNUNET_GNS_GetAuthRequest *getauth_request;
75
76 /* shutdown task */
77 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
78
79 /**
80  * Task run on shutdown.  Cleans up everything.
81  *
82  * @param cls unused
83  * @param tc scheduler context
84  */
85 static void
86 do_shutdown (void *cls,
87              const struct GNUNET_SCHEDULER_TaskContext *tc)
88 {
89   if (NULL != lookup_request)
90     GNUNET_GNS_cancel_lookup_request (lookup_request);
91
92   if (NULL != shorten_request)
93     GNUNET_GNS_cancel_shorten_request (shorten_request);
94
95   if (NULL != getauth_request)
96     GNUNET_GNS_cancel_get_auth_request (getauth_request);
97
98   if (NULL != gns)
99     GNUNET_GNS_disconnect (gns);
100 }
101
102
103 static void
104 process_shorten_result(void* cls, const char* nshort)
105 {
106   shorten_request = NULL;
107   if (raw)
108     printf("%s", nshort);
109   else
110     printf("%s shortened to %s\n", (char*) cls, nshort);
111   GNUNET_SCHEDULER_cancel (shutdown_task);
112   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
113 }
114
115 static void
116 process_lookup_result(void* cls, uint32_t rd_count,
117                       const struct GNUNET_NAMESTORE_RecordData *rd)
118 {
119   int i;
120   char* name = (char*) cls;
121   const char* typename;
122   char* string_val;
123   lookup_request = NULL;
124   
125   if (!raw) {
126     if (rd_count == 0)
127       printf("No results.\n");
128     else
129       printf("%s:\n", name);
130   }
131
132
133
134   for (i=0; i<rd_count; i++)
135   {
136     typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type);
137     string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
138                                                   rd[i].data,
139                                                   rd[i].data_size);
140     if (raw)
141       printf("%s\n", string_val);
142     else
143       printf("Got %s record: %s\n", typename, string_val);
144
145   }
146   GNUNET_SCHEDULER_cancel (shutdown_task);
147   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
148 }
149
150 static void
151 process_auth_result(void* cls, const char* auth)
152 {
153   getauth_request = NULL;
154   printf ("%s\n", auth);
155   GNUNET_SCHEDULER_cancel (shutdown_task);
156   GNUNET_SCHEDULER_add_now (&do_shutdown, NULL);
157 }
158
159 /**
160  * Main function that will be run.
161  *
162  * @param cls closure
163  * @param args remaining command-line arguments
164  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
165  * @param cfg configuration
166  */
167 static void
168 run (void *cls, char *const *args, const char *cfgfile,
169      const struct GNUNET_CONFIGURATION_Handle *cfg)
170 {
171   char* keyfile;
172   struct GNUNET_CRYPTO_RsaPrivateKey *key = NULL;
173   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
174   struct GNUNET_CRYPTO_ShortHashCode *zone = NULL;
175   struct GNUNET_CRYPTO_ShortHashCode user_zone;
176   struct GNUNET_CRYPTO_ShortHashAsciiEncoded zonename;
177   struct GNUNET_CRYPTO_RsaPrivateKey *shorten_key = NULL;
178   struct GNUNET_CRYPTO_RsaPrivateKey *private_key = NULL;
179   struct GNUNET_CRYPTO_ShortHashCode *private_zone = NULL;
180   struct GNUNET_CRYPTO_ShortHashCode *shorten_zone = NULL;
181
182   shorten_request = NULL;
183   lookup_request = NULL;
184   getauth_request = NULL;
185
186   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
187                                                            "ZONEKEY", &keyfile))
188   {
189     if (!raw)
190       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
191                   "No private key for root zone found, using default!\n");
192     zone = NULL;
193   }
194   else
195   {
196     if (GNUNET_YES == GNUNET_DISK_file_test (keyfile))
197     {
198       key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
199       GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
200       GNUNET_CRYPTO_short_hash(&pkey,
201                          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
202                          &user_zone);
203       zone = &user_zone;
204       GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename);
205       if (!raw)
206         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
207                     "Using zone: %s!\n", &zonename);
208       GNUNET_CRYPTO_rsa_key_free(key);
209     }
210     GNUNET_free(keyfile);
211   }
212   
213   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
214                                                    "SHORTEN_ZONEKEY", &keyfile))
215   {
216     if (!raw)
217       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
218                   "No shorten key found!\n");
219     shorten_key = NULL;
220   }
221   else
222   {
223     if (GNUNET_YES == GNUNET_DISK_file_test (keyfile))
224     {
225       shorten_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
226       GNUNET_CRYPTO_rsa_key_get_public (shorten_key, &pkey);
227       shorten_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode));
228       GNUNET_CRYPTO_short_hash(&pkey,
229                          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
230                          shorten_zone);
231       GNUNET_CRYPTO_short_hash_to_enc (shorten_zone, &zonename);
232       if (!raw)
233         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
234                     "Using shorten zone: %s!\n", &zonename);
235
236     }
237     GNUNET_free(keyfile);
238   }
239   
240   
241   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
242                                                             "PRIVATE_ZONEKEY", &keyfile))
243   {
244     if (!raw)
245       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
246                   "No private zone key file name specified in configuration!\n");
247     shorten_key = NULL;
248   }
249   else
250   {
251     if (GNUNET_YES == GNUNET_DISK_file_test (keyfile))
252     {
253       private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
254       GNUNET_CRYPTO_rsa_key_get_public (private_key, &pkey);
255       private_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode));
256       GNUNET_CRYPTO_short_hash(&pkey,
257                          sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
258                          private_zone);
259       GNUNET_CRYPTO_short_hash_to_enc (private_zone, &zonename);
260       if (!raw)
261         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
262                     "Using private zone: %s!\n", &zonename);
263     }
264     else
265     {
266       /* FIXME: shouldn't we just create the private key in this case? */
267       if (!raw)
268         fprintf (stderr,
269                  _("Key file `%s' for private zone does not exist!\n"),
270                  keyfile);
271
272     }
273     GNUNET_free(keyfile);
274     if (NULL != private_key)
275     {
276       GNUNET_CRYPTO_rsa_key_free (private_key);
277       private_key = NULL;
278     }
279   }
280   
281   
282   gns = GNUNET_GNS_connect (cfg);
283   if (NULL != lookup_type)
284     rtype = GNUNET_NAMESTORE_typename_to_number (lookup_type);
285   else
286     rtype = GNUNET_GNS_RECORD_A;
287
288   if (NULL == gns)
289   {
290     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
291                 _("Failed to connect to GNS\n"));
292     return;
293   }
294   
295   if (NULL != shorten_name)
296   {
297     shorten_request = GNUNET_GNS_shorten_zone (gns, shorten_name,
298                              private_zone,
299                              shorten_zone,
300                              zone,
301                              &process_shorten_result,
302                              shorten_name);
303   }
304
305   if (NULL != lookup_name)
306   {
307     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
308                 "Lookup\n");
309     lookup_request = GNUNET_GNS_lookup_zone (gns, lookup_name,
310                             zone,
311                             rtype,
312                             GNUNET_NO, //Use DHT
313                             shorten_key,
314                             &process_lookup_result, lookup_name);
315   }
316
317   if (NULL != auth_name)
318   {
319     getauth_request = GNUNET_GNS_get_authority(gns, auth_name,
320                                                &process_auth_result, auth_name);
321   }
322
323   if (NULL != shorten_key)
324     GNUNET_CRYPTO_rsa_key_free (shorten_key);
325
326   if (NULL != shorten_zone)
327     GNUNET_free (shorten_zone);
328
329   if (NULL != private_zone)
330     GNUNET_free (private_zone);
331   
332   shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
333                                                 &do_shutdown, NULL);
334 }
335
336
337 /**
338  * The main function for gnunet-gns.
339  *
340  * @param argc number of arguments from the command line
341  * @param argv command line arguments
342  * @return 0 ok, 1 on error
343  */
344 int
345 main (int argc, char *const *argv)
346 {
347   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
348     {'s', "shorten", NULL,
349      gettext_noop ("try to shorten a given GNS name"), 1,
350      &GNUNET_GETOPT_set_string, &shorten_name},
351     {'u', "lookup", NULL,
352       gettext_noop ("Lookup a record using GNS (NOT IMPLEMENTED)"), 1,
353       &GNUNET_GETOPT_set_string, &lookup_name},
354     {'a', "authority", NULL,
355       gettext_noop ("Get the authority of a particular name"), 1,
356       &GNUNET_GETOPT_set_string, &auth_name},
357     {'t', "type", NULL,
358       gettext_noop ("Specify the type of the record lookup"), 1,
359       &GNUNET_GETOPT_set_string, &lookup_type},
360     {'r', "raw", NULL,
361       gettext_noop ("No unneeded output"), 0,
362       &GNUNET_GETOPT_set_one, &raw},
363     GNUNET_GETOPT_OPTION_END
364   };
365
366   int ret;
367
368   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
369     return 2;
370
371   GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
372   ret =
373       (GNUNET_OK ==
374        GNUNET_PROGRAM_run (argc, argv, "gnunet-gns",
375                            _("GNUnet GNS access tool"), 
376                            options,
377                            &run, NULL)) ? 0 : 1;
378
379   return ret;
380 }
381
382 /* end of gnunet-gns.c */