2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2016, 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/>.
19 * @file gns/gns_tld_api.c
20 * @brief library to access the GNS service, including TLD lookup
21 * @author Martin Schanzenbach
22 * @author Christian Grothoff
25 #include "gnunet_util_lib.h"
26 #include "gnunet_constants.h"
27 #include "gnunet_arm_service.h"
28 #include "gnunet_identity_service.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_dht_service.h"
36 #define LOG(kind,...) GNUNET_log_from (kind, "gns-tld-api",__VA_ARGS__)
41 * Handle to a lookup request
43 struct GNUNET_GNS_LookupWithTldRequest
49 struct GNUNET_GNS_Handle *gns_handle;
52 * processor to call on lookup result
54 GNUNET_GNS_LookupResultProcessor2 lookup_proc;
57 * Domain name we are resolving.
62 * @e lookup_proc closure
64 void *lookup_proc_cls;
67 * Underlying GNS lookup.
69 struct GNUNET_GNS_LookupRequest *lr;
72 * Lookup an ego with the identity service.
74 struct GNUNET_IDENTITY_EgoLookup *id_op;
77 * Desired result record type.
84 enum GNUNET_GNS_LocalOptions options;
89 * Obtain the TLD of the given @a name.
92 * @return the part of @a name after the last ".",
93 * or @a name if @a name does not contain a "."
96 get_tld (const char *name)
101 (unsigned char) '.');
105 tld++; /* skip the '.' */
111 * Eat the "TLD" (last bit) of the given @a name.
113 * @param[in,out] name a name
114 * @param tld what to eat (can be more than just the tld)
120 GNUNET_assert (0 < strlen (name));
124 GNUNET_GNS_EMPTY_LABEL_AT);
128 GNUNET_assert (strlen (tld) < strlen (name));
129 name[strlen(name) - strlen(tld) - 1] = '\0';
135 * Function called with the result of a GNS lookup.
137 * @param cls a `struct GNUNET_GNS_LookupWithTldRequest *`
138 * @param rd_count number of records returned
139 * @param rd array of @a rd_count records with the results
142 process_lookup_result (void *cls,
144 const struct GNUNET_GNSRECORD_Data *rd)
146 struct GNUNET_GNS_LookupWithTldRequest *ltr = cls;
149 ltr->lookup_proc (ltr->lookup_proc_cls,
153 GNUNET_GNS_lookup_with_tld_cancel (ltr);
158 * Perform the actual resolution, starting with the zone
159 * identified by the given public key.
161 * @param pkey public key to use for the zone, can be NULL
164 lookup_with_public_key (struct GNUNET_GNS_LookupWithTldRequest *ltr,
165 const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey)
167 ltr->lr = GNUNET_GNS_lookup (ltr->gns_handle,
172 &process_lookup_result,
178 * Method called to with the ego we are to use for the lookup,
179 * when the ego is determined by a name.
181 * @param cls a `struct GNUNET_GNS_LookupWithTldRequest *`
182 * @param ego ego handle, NULL if not found
185 identity_zone_cb (void *cls,
186 const struct GNUNET_IDENTITY_Ego *ego)
188 struct GNUNET_GNS_LookupWithTldRequest *ltr = cls;
189 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
194 ltr->lookup_proc (ltr->lookup_proc_cls,
198 GNUNET_GNS_lookup_with_tld_cancel (ltr);
203 GNUNET_IDENTITY_ego_get_public_key (ego,
205 lookup_with_public_key (ltr,
212 * Perform an asynchronous lookup operation on the GNS,
213 * determining the zone using the TLD of the given name
214 * and the current configuration to resolve TLDs to zones.
216 * @param handle handle to the GNS service
217 * @param name the name to look up, including TLD
218 * @param type the record type to look up
219 * @param options local options for the lookup
220 * @param proc processor to call on result
221 * @param proc_cls closure for @a proc
222 * @return handle to the get request, NULL on error (i.e. bad configuration)
224 struct GNUNET_GNS_LookupWithTldRequest *
225 GNUNET_GNS_lookup_with_tld (struct GNUNET_GNS_Handle *handle,
228 enum GNUNET_GNS_LocalOptions options,
229 GNUNET_GNS_LookupResultProcessor2 proc,
232 struct GNUNET_GNS_LookupWithTldRequest *ltr;
236 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
238 ltr = GNUNET_new (struct GNUNET_GNS_LookupWithTldRequest);
239 ltr->gns_handle = handle;
240 ltr->name = GNUNET_strdup (name);
242 ltr->options = options;
243 ltr->lookup_proc = proc;
244 ltr->lookup_proc_cls = proc_cls;
245 /* start with trivial case: TLD is zkey */
246 tld = get_tld (ltr->name);
248 GNUNET_CRYPTO_ecdsa_public_key_from_string (tld,
254 lookup_with_public_key (ltr,
259 /* second case: domain is mapped in our configuration file */
260 for (const char *domain = name;
262 domain = strchr (domain,
263 (unsigned char) '.'))
265 if ('.' == domain[0])
267 GNUNET_asprintf (&dot_tld,
271 GNUNET_CONFIGURATION_get_value_string (handle->cfg,
277 GNUNET_CRYPTO_ecdsa_public_key_from_string (zonestr,
281 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
284 _("Expected a base32-encoded public zone key\n"));
285 GNUNET_free (zonestr);
286 GNUNET_free (dot_tld);
287 GNUNET_free (ltr->name);
293 GNUNET_free (zonestr);
294 GNUNET_free (dot_tld);
295 lookup_with_public_key (ltr,
299 GNUNET_free (dot_tld);
302 /* Final case: TLD matches one of our egos */
306 /* if the name is of the form 'label' (and not 'label.SUBDOMAIN'), never go to the DHT */
307 if (NULL == strchr (ltr->name,
308 (unsigned char) '.'))
309 ltr->options = GNUNET_GNS_LO_NO_DHT;
311 ltr->options = GNUNET_GNS_LO_LOCAL_MASTER;
312 ltr->id_op = GNUNET_IDENTITY_ego_lookup (ltr->gns_handle->cfg,
316 if (NULL == ltr->id_op)
318 GNUNET_free (ltr->name);
327 * Cancel pending lookup request
329 * @param ltr the lookup request to cancel
330 * @return closure from the lookup result processor
333 GNUNET_GNS_lookup_with_tld_cancel (struct GNUNET_GNS_LookupWithTldRequest *ltr)
335 void *ret = ltr->lookup_proc_cls;
337 if (NULL != ltr->id_op)
339 GNUNET_IDENTITY_ego_lookup_cancel (ltr->id_op);
344 GNUNET_GNS_lookup_cancel (ltr->lr);
347 GNUNET_free (ltr->name);
352 /* end of gns_tld_api.c */