2 This file is part of GNUnet.
3 Copyright (C) 2012-2013, 2017-2018 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @brief command line tool to access distributed GNS
23 * @author Christian Grothoff
29 #elif HAVE_IDN2_IDN2_H
30 #include <idn2/idn2.h>
39 #include <gnunet_util_lib.h>
40 #include <gnunet_dnsparser_lib.h>
41 #include <gnunet_gnsrecord_lib.h>
42 #include <gnunet_namestore_service.h>
43 #include <gnunet_gns_service.h>
47 * Configuration we are using.
49 static const struct GNUNET_CONFIGURATION_Handle *cfg;
52 * Handle to GNS service.
54 static struct GNUNET_GNS_Handle *gns;
57 * GNS name to lookup. (-u option)
59 static char *lookup_name;
62 * DNS IDNA name to lookup. (set if -d option is set)
67 * DNS compatibility (name is given as DNS name, possible IDNA).
69 static int dns_compat;
72 * record type to look up (-t option)
74 static char *lookup_type;
82 * Desired record type.
84 static uint32_t rtype;
89 static struct GNUNET_TIME_Relative timeout;
94 static struct GNUNET_SCHEDULER_Task *to_task;
97 * Handle to lookup request
99 static struct GNUNET_GNS_LookupWithTldRequest *lr;
102 * Global return value.
103 * 0 on success (default),
104 * 1 on internal failures
105 * 2 on launch failure,
106 * 4 if the name is not a GNS-supported TLD,
108 static int global_ret;
112 * Task run on shutdown. Cleans up everything.
117 do_shutdown (void *cls)
122 GNUNET_SCHEDULER_cancel (to_task);
127 GNUNET_GNS_lookup_with_tld_cancel (lr);
132 GNUNET_GNS_disconnect (gns);
135 if (NULL != idna_name)
137 GNUNET_free (idna_name);
144 * Task to run on timeout
149 do_timeout (void*cls)
152 global_ret = 3; // Timeout
153 GNUNET_SCHEDULER_shutdown ();
158 * Function called with the result of a GNS lookup.
160 * @param cls the 'const char *' name that was resolved
161 * @param was_gns #GNUNET_NO if TLD did not indicate use of GNS
162 * @param rd_count number of records returned
163 * @param rd array of @a rd_count records with the results
166 process_lookup_result (void *cls,
169 const struct GNUNET_GNSRECORD_Data *rd)
171 const char *name = cls;
172 const char *typename;
176 if (GNUNET_NO == was_gns)
178 global_ret = 4; /* not for GNS */
179 GNUNET_SCHEDULER_shutdown ();
185 printf ("No results.\n");
187 printf ("%s:\n", name);
189 for (uint32_t i = 0; i < rd_count; i++)
191 if ((rd[i].record_type != rtype) && (GNUNET_GNSRECORD_TYPE_ANY != rtype))
193 typename = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
194 string_val = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
197 if (NULL == string_val)
200 "Record %u of type %d malformed, skipping\n",
202 (int) rd[i].record_type);
206 printf ("%s\n", string_val);
208 printf ("Got `%s' record: %s%s\n",
211 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SUPPLEMENTAL)) ?
212 " (supplemental)" : "");
213 GNUNET_free (string_val);
215 GNUNET_SCHEDULER_shutdown ();
220 * Main function that will be run.
223 * @param args remaining command-line arguments
224 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
225 * @param c configuration
231 const struct GNUNET_CONFIGURATION_Handle *c)
242 if (NULL != (colon = strchr (lookup_name, ':')))
247 * If DNS compatibility is requested, we first verify that the
248 * lookup_name is in a DNS format. If yes, we convert it to UTF-8.
250 if (GNUNET_YES == dns_compat)
254 if (GNUNET_OK != GNUNET_DNSPARSER_check_name (lookup_name))
257 _ ("`%s' is not a valid DNS domain name\n"),
263 (rc = idna_to_unicode_8z8z (lookup_name, &idna_name,
264 IDNA_ALLOW_UNASSIGNED)))
267 _ ("Failed to convert DNS IDNA name `%s' to UTF-8: %s\n"),
273 lookup_name = idna_name;
277 GNUNET_CLIENT_test (cfg,
280 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
281 _ ("Cannot resolve using GNS: GNUnet peer not running\n"));
285 to_task = GNUNET_SCHEDULER_add_delayed (timeout,
288 gns = GNUNET_GNS_connect (cfg);
292 _ ("Failed to connect to GNS\n"));
296 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
298 if (NULL != lookup_type)
299 rtype = GNUNET_GNSRECORD_typename_to_number (lookup_type);
301 rtype = GNUNET_DNSPARSER_TYPE_A;
302 if (UINT32_MAX == rtype)
305 _ ("Invalid typename specified, assuming `ANY'\n"));
306 rtype = GNUNET_GNSRECORD_TYPE_ANY;
308 lr = GNUNET_GNS_lookup_with_tld (gns,
311 GNUNET_GNS_LO_DEFAULT,
312 &process_lookup_result,
317 GNUNET_SCHEDULER_shutdown ();
324 * The main function for gnunet-gns.
326 * @param argc number of arguments from the command line
327 * @param argv command line arguments
328 * @return 0 ok, 1 on error
331 main (int argc, char *const *argv)
333 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
334 struct GNUNET_GETOPT_CommandLineOption options[] =
335 { GNUNET_GETOPT_option_mandatory (
336 GNUNET_GETOPT_option_string ('u',
340 "Lookup a record for the given name"),
342 GNUNET_GETOPT_option_string ('t',
346 "Specify the type of the record to lookup"),
348 GNUNET_GETOPT_option_relative_time ('T',
352 "Specify a timeout for the lookup"),
354 GNUNET_GETOPT_option_flag ('r',
356 gettext_noop ("No unneeded output"),
358 GNUNET_GETOPT_option_flag ('d',
361 "DNS Compatibility: Name is passed in IDNA instead of UTF-8"),
363 GNUNET_GETOPT_OPTION_END };
367 GNUNET_STRINGS_get_utf8_args (argc, argv,
371 GNUNET_log_setup ("gnunet-gns", "WARNING", NULL);
372 ret = GNUNET_PROGRAM_run (argc,
375 _ ("GNUnet GNS resolver tool"),
379 GNUNET_free ((void *) argv);
380 if (GNUNET_OK != ret)
386 /* end of gnunet-gns.c */