src: for every AGPL3.0 file, add SPDX identifier.
[oweals/gnunet.git] / src / gns / gnunet-gns.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012-2013, 2017-2018 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      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 /**
21  * @file gnunet-gns.c
22  * @brief command line tool to access distributed GNS
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include <gnunet_util_lib.h>
27 #include <gnunet_dnsparser_lib.h>
28 #include <gnunet_gnsrecord_lib.h>
29 #include <gnunet_namestore_service.h>
30 #include <gnunet_gns_service.h>
31
32 /**
33  * Configuration we are using.
34  */
35 static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37 /**
38  * Handle to GNS service.
39  */
40 static struct GNUNET_GNS_Handle *gns;
41
42 /**
43  * GNS name to lookup. (-u option)
44  */
45 static char *lookup_name;
46
47 /**
48  * record type to look up (-t option)
49  */
50 static char *lookup_type;
51
52 /**
53  * raw output
54  */
55 static int raw;
56
57 /**
58  * Desired record type.
59  */
60 static uint32_t rtype;
61
62 /**
63  * Handle to lookup request
64  */
65 static struct GNUNET_GNS_LookupWithTldRequest *lr;
66
67 /**
68  * Global return value.
69  * 0 on success (default),
70  * 1 on internal failures
71  * 2 on launch failure,
72  * 4 if the name is not a GNS-supported TLD,
73  */
74 static int global_ret;
75
76
77 /**
78  * Task run on shutdown.  Cleans up everything.
79  *
80  * @param cls unused
81  */
82 static void
83 do_shutdown (void *cls)
84 {
85   (void) cls;
86   if (NULL != lr)
87   {
88     GNUNET_GNS_lookup_with_tld_cancel (lr);
89     lr = NULL;
90   }
91   if (NULL != gns)
92   {
93     GNUNET_GNS_disconnect (gns);
94     gns = NULL;
95   }
96 }
97
98
99 /**
100  * Function called with the result of a GNS lookup.
101  *
102  * @param cls the 'const char *' name that was resolved
103  * @param was_gns #GNUNET_NO if TLD did not indicate use of GNS
104  * @param rd_count number of records returned
105  * @param rd array of @a rd_count records with the results
106  */
107 static void
108 process_lookup_result (void *cls,
109                        int was_gns,
110                        uint32_t rd_count,
111                        const struct GNUNET_GNSRECORD_Data *rd)
112 {
113   const char *name = cls;
114   const char *typename;
115   char* string_val;
116
117   lr = NULL;
118   if (GNUNET_NO == was_gns)
119   {
120     global_ret = 4; /* not for GNS */
121     GNUNET_SCHEDULER_shutdown ();
122     return;
123   }
124   if (! raw)
125   {
126     if (0 == rd_count)
127       printf ("No results.\n");
128     else
129       printf ("%s:\n",
130               name);
131   }
132   for (uint32_t i=0; i<rd_count; i++)
133   {
134     if ( (rd[i].record_type != rtype) &&
135          (GNUNET_GNSRECORD_TYPE_ANY != rtype) )
136       continue;
137     typename = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
138     string_val = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
139                                                    rd[i].data,
140                                                    rd[i].data_size);
141     if (NULL == string_val)
142     {
143       fprintf (stderr,
144                "Record %u of type %d malformed, skipping\n",
145                (unsigned int) i,
146                (int) rd[i].record_type);
147       continue;
148     }
149     if (raw)
150       printf ("%s\n",
151               string_val);
152     else
153       printf ("Got `%s' record: %s\n",
154               typename,
155               string_val);
156     GNUNET_free (string_val);
157   }
158   GNUNET_SCHEDULER_shutdown ();
159 }
160
161
162 /**
163  * Main function that will be run.
164  *
165  * @param cls closure
166  * @param args remaining command-line arguments
167  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
168  * @param c configuration
169  */
170 static void
171 run (void *cls,
172      char *const *args,
173      const char *cfgfile,
174      const struct GNUNET_CONFIGURATION_Handle *c)
175 {
176   (void) cls;
177   (void) args;
178   (void) cfgfile;
179
180   cfg = c;
181   gns = GNUNET_GNS_connect (cfg);
182   if (NULL == gns)
183   {
184     fprintf (stderr,
185              _("Failed to connect to GNS\n"));
186     global_ret = 2;
187     return;
188   }
189   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
190                                  NULL);
191
192   if (NULL != lookup_type)
193     rtype = GNUNET_GNSRECORD_typename_to_number (lookup_type);
194   else
195     rtype = GNUNET_DNSPARSER_TYPE_A;
196   if (UINT32_MAX == rtype)
197   {
198     fprintf (stderr,
199              _("Invalid typename specified, assuming `ANY'\n"));
200     rtype = GNUNET_GNSRECORD_TYPE_ANY;
201   }
202   lr = GNUNET_GNS_lookup_with_tld (gns,
203                                    lookup_name,
204                                    rtype,
205                                    GNUNET_GNS_LO_DEFAULT,
206                                    &process_lookup_result,
207                                    lookup_name);
208   if (NULL == lr)
209   {
210     global_ret = 2;
211     GNUNET_SCHEDULER_shutdown ();
212     return;
213   }
214 }
215
216
217 /**
218  * The main function for gnunet-gns.
219  *
220  * @param argc number of arguments from the command line
221  * @param argv command line arguments
222  * @return 0 ok, 1 on error
223  */
224 int
225 main (int argc,
226       char *const *argv)
227 {
228   struct GNUNET_GETOPT_CommandLineOption options[] = {
229     GNUNET_GETOPT_option_mandatory
230     (GNUNET_GETOPT_option_string ('u',
231                                   "lookup",
232                                   "NAME",
233                                   gettext_noop ("Lookup a record for the given name"),
234                                   &lookup_name)),
235     GNUNET_GETOPT_option_string ('t',
236                                  "type",
237                                  "TYPE",
238                                  gettext_noop ("Specify the type of the record to lookup"),
239                                  &lookup_type),
240     GNUNET_GETOPT_option_flag ('r',
241                                "raw",
242                                gettext_noop ("No unneeded output"),
243                                &raw),
244     GNUNET_GETOPT_OPTION_END
245   };
246   int ret;
247
248   if (GNUNET_OK !=
249       GNUNET_STRINGS_get_utf8_args (argc, argv,
250                                     &argc, &argv))
251     return 2;
252
253   GNUNET_log_setup ("gnunet-gns",
254                     "WARNING",
255                     NULL);
256   ret = GNUNET_PROGRAM_run (argc, argv,
257                             "gnunet-gns",
258                             _("GNUnet GNS resolver tool"),
259                             options,
260                             &run, NULL);
261   GNUNET_free ((void*) argv);
262   if (GNUNET_OK != ret)
263     return 1;
264   return global_ret;
265 }
266
267 /* end of gnunet-gns.c */