GNUnet  0.17.6
gnunet-service-gns.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2011-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  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_dns_service.h"
29 #include "gnunet_dnsparser_lib.h"
30 #include "gnunet_dht_service.h"
32 #include "gnunet_gnsrecord_lib.h"
33 #include "gnunet_gns_service.h"
35 #include "gns.h"
38 #include "gnunet_protocols.h"
39 
40 
44 struct GnsClient;
45 
50 {
55 
60 
64  struct GnsClient *gc;
65 
70 
74  uint32_t request_id;
75 };
76 
77 
81 struct GnsClient
82 {
87 
92 
97 
102 };
103 
104 
110 {
116 
122 
127 
131  char *tld;
132 };
133 
134 
139 
144 
148 static int v6_enabled;
149 
153 static int v4_enabled;
154 
159 
164 
169 
170 
178 int
179 GNS_find_tld (const char *tld_str,
181 {
182  if ('\0' == *tld_str)
183  return GNUNET_NO;
184  for (struct GNS_TopLevelDomain *tld = tld_head;
185  NULL != tld;
186  tld = tld->next)
187  {
188  if (0 == strcasecmp (tld_str,
189  tld->tld))
190  {
191  *pkey = tld->pkey;
192  return GNUNET_YES;
193  }
194  }
195  if (GNUNET_OK ==
196  GNUNET_GNSRECORD_zkey_to_pkey (tld_str + 1,
197  pkey))
198  return GNUNET_YES; /* TLD string *was* the public key */
199  return GNUNET_NO;
200 }
201 
202 
210 const char *
211 GNS_get_tld (const char *name)
212 {
213  const char *tld;
214 
215  tld = strrchr (name,
216  (unsigned char) '.');
217  if (NULL == tld)
218  tld = name;
219  else
220  tld++; /* skip the '.' */
221  return tld;
222 }
223 
224 
230 static void
231 shutdown_task (void *cls)
232 {
233  struct GNS_TopLevelDomain *tld;
234 
235  (void) cls;
237  "Shutting down!\n");
240  if (NULL != statistics)
241  {
243  GNUNET_NO);
244  statistics = NULL;
245  }
246  if (NULL != namecache_handle)
247  {
249  namecache_handle = NULL;
250  }
251  if (NULL != dht_handle)
252  {
254  dht_handle = NULL;
255  }
256  while (NULL != (tld = tld_head))
257  {
259  tld_tail,
260  tld);
261  GNUNET_free (tld->tld);
262  GNUNET_free (tld);
263  }
264 }
265 
266 
274 static void
276  struct GNUNET_SERVICE_Client *client,
277  void *app_ctx)
278 {
279  struct ClientLookupHandle *clh;
280  struct GnsClient *gc = app_ctx;
281 
282  (void) cls;
284  "Client %p disconnected\n",
285  client);
286  while (NULL != (clh = gc->clh_head))
287  {
288  if (NULL != clh->lookup)
291  gc->clh_tail,
292  clh);
293  GNUNET_free (clh);
294  }
295  GNUNET_free (gc);
296 }
297 
298 
307 static void *
308 client_connect_cb (void *cls,
310  struct GNUNET_MQ_Handle *mq)
311 {
312  struct GnsClient *gc;
313 
314  (void) cls;
316  "Client %p connected\n",
317  client);
318  gc = GNUNET_new (struct GnsClient);
319  gc->client = client;
320  gc->mq = mq;
321  return gc;
322 }
323 
324 
332 static void
334  uint32_t rd_count,
335  const struct GNUNET_GNSRECORD_Data *rd)
336 {
337  struct ClientLookupHandle *clh = cls;
338  struct GnsClient *gc = clh->gc;
339  struct GNUNET_MQ_Envelope *env;
340  struct LookupResultMessage *rmsg;
341  ssize_t len;
342 
344  "Sending LOOKUP_RESULT message with %u results\n",
345  (unsigned int) rd_count);
347  rd);
348  if (len < 0)
349  {
350  GNUNET_break (0);
352  return;
353  }
354  if (len > UINT16_MAX - sizeof(*rmsg))
355  {
356  GNUNET_break (0);
358  return;
359  }
360  env = GNUNET_MQ_msg_extra (rmsg,
361  len,
363  rmsg->id = clh->request_id;
364  rmsg->rd_count = htonl (rd_count);
365  GNUNET_assert (len ==
367  rd,
368  len,
369  (char *) &rmsg[1]));
371  env);
373  gc->clh_tail,
374  clh);
375  GNUNET_free (clh);
377  "Completed lookups", 1,
378  GNUNET_NO);
380  "Records resolved",
381  rd_count,
382  GNUNET_NO);
383 }
384 
385 
393 static int
394 check_lookup (void *cls,
395  const struct LookupMessage *l_msg)
396 {
397  size_t nlen;
398 
399  (void) cls;
401  nlen = ntohs (l_msg->header.size) - sizeof(struct LookupMessage);
403  {
404  GNUNET_break (0);
405  return GNUNET_SYSERR;
406  }
407  return GNUNET_OK;
408 }
409 
410 
418 static void
419 handle_lookup (void *cls,
420  const struct LookupMessage *sh_msg)
421 {
422  struct GnsClient *gc = cls;
423  struct ClientLookupHandle *clh;
424  const char *name;
425 
427  name = (const char *) &sh_msg[1];
429  "Received LOOKUP `%s' message\n",
430  name);
431  clh = GNUNET_new (struct ClientLookupHandle);
433  gc->clh_tail,
434  clh);
435  clh->gc = gc;
436  clh->request_id = sh_msg->id;
437  if ((GNUNET_DNSPARSER_TYPE_A == ntohl (sh_msg->type)) &&
438  (GNUNET_OK != v4_enabled))
439  {
441  "LOOKUP: Query for A record but AF_INET not supported!");
443  0,
444  NULL);
445  return;
446  }
447  if ((GNUNET_DNSPARSER_TYPE_AAAA == ntohl (sh_msg->type)) &&
448  (GNUNET_OK != v6_enabled))
449  {
451  "LOOKUP: Query for AAAA record but AF_INET6 not supported!");
453  0,
454  NULL);
455  return;
456  }
457  clh->lookup = GNS_resolver_lookup (&sh_msg->zone,
458  ntohl (sh_msg->type),
459  name,
460  (enum GNUNET_GNS_LocalOptions) ntohs (
461  sh_msg->options),
462  ntohs (sh_msg->recursion_depth_limit),
463  &send_lookup_response, clh);
465  "Lookup attempts",
466  1, GNUNET_NO);
467 }
468 
469 
478 static void
479 read_service_conf (void *cls,
480  const char *section,
481  const char *option,
482  const char *value)
483 {
485  struct GNS_TopLevelDomain *tld;
486 
487  (void) cls;
488  (void) section;
489  if (option[0] != '.')
490  return;
491  if (GNUNET_OK !=
493  strlen (value),
494  &pk,
495  sizeof(pk)))
496  {
498  section,
499  option,
500  _ (
501  "Properly base32-encoded public key required"));
502  return;
503  }
504  tld = GNUNET_new (struct GNS_TopLevelDomain);
505  tld->tld = GNUNET_strdup (&option[1]);
506  tld->pkey = pk;
508  tld_tail,
509  tld);
510 }
511 
512 
520 static void
521 run (void *cls,
522  const struct GNUNET_CONFIGURATION_Handle *c,
524 {
525  unsigned long long max_parallel_bg_queries = 16;
526 
528  "gns",
530  NULL);
531  v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6);
534  if (NULL == namecache_handle)
535  {
537  _ ("Failed to connect to the namecache!\n"));
539  return;
540  }
541  if (GNUNET_OK ==
543  "gns",
544  "MAX_PARALLEL_BACKGROUND_QUERIES",
545  &max_parallel_bg_queries))
546  {
548  "Number of allowed parallel background queries: %llu\n",
549  max_parallel_bg_queries);
550  }
552  (unsigned int) max_parallel_bg_queries);
553  if (NULL == dht_handle)
554  {
556  _ ("Could not connect to DHT!\n"));
558  NULL);
559  return;
560  }
562  dht_handle,
563  c,
564  max_parallel_bg_queries);
565  if ((GNUNET_YES ==
567  "gns",
568  "INTERCEPT_DNS")) &&
569  (GNUNET_SYSERR ==
571  {
572  GNUNET_break (0);
574  NULL);
575  return;
576  }
578  c);
580  NULL);
581 }
582 
583 
588  ("gns",
590  &run,
593  NULL,
594  GNUNET_MQ_hd_var_size (lookup,
596  struct LookupMessage,
597  NULL),
599 
600 
601 /* end of gnunet-service-gns.c */
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
IPC messages between GNS API and GNS service.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
static char * pkey
Public key of the zone to look in, in ASCII.
static char * value
Value of the record to add/remove.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNS_TopLevelDomain * tld_tail
Tail of DLL of TLDs we map to GNS zones.
static void send_lookup_response(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Reply to client with the result from our lookup.
static struct GNS_TopLevelDomain * tld_head
Head of DLL of TLDs we map to GNS zones.
GNUNET_SERVICE_MAIN("gns", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(lookup, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, struct LookupMessage, NULL), GNUNET_MQ_handler_end())
Define "main" method using service macro.
static void handle_lookup(void *cls, const struct LookupMessage *sh_msg)
Handle lookup requests from client.
static void shutdown_task(void *cls)
Task run during shutdown.
static struct GNUNET_STATISTICS_Handle * statistics
Handle to the statistics service.
static int v4_enabled
GNUNET_YES if ipv4 is supported
static struct GNUNET_DHT_Handle * dht_handle
Our handle to the DHT.
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
static void read_service_conf(void *cls, const char *section, const char *option, const char *value)
Reads the configuration and populates TLDs.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
Process GNS requests.
static int check_lookup(void *cls, const struct LookupMessage *l_msg)
Checks a GNUNET_MESSAGE_TYPE_GNS_LOOKUP message.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
Add a client to our list of active clients.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
int GNS_find_tld(const char *tld_str, struct GNUNET_IDENTITY_PublicKey *pkey)
Find GNS zone belonging to TLD tld.
static int v6_enabled
GNUNET_YES if ipv6 is supported
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
int GNS_interceptor_init(const struct GNUNET_CONFIGURATION_Handle *c)
Initialize DNS interceptor.
void GNS_interceptor_done()
Disconnect from interceptor.
void GNS_resolver_init(struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries)
Initialize the resolver.
void GNS_resolver_lookup_cancel(struct GNS_ResolverHandle *rh)
Cancel active resolution (i.e.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_IDENTITY_PublicKey *zone, uint32_t record_type, const char *name, enum GNUNET_GNS_LocalOptions options, uint16_t recursion_depth_limit, GNS_ResultProcessor proc, void *proc_cls)
Lookup of a record in a specific zone calls lookup result processor on result.
void GNS_resolver_done()
Shutdown resolver.
API to the DHT service.
API to access the DNS service.
API for helper library to parse DNS packets.
API to the GNS service.
API that can be used to manipulate GNS record data.
API that can be used to store naming information on a GNUnet node.
Constants for network protocols.
API to create, modify and access statistics.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
void GNUNET_CONFIGURATION_iterate_section_values(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls)
Iterate over values of a section in the configuration.
struct GNUNET_DHT_Handle * GNUNET_DHT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len)
Initialize the connection with the DHT service.
Definition: dht_api.c:1039
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition: dht_api.c:1062
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_DNSPARSER_TYPE_A
#define GNUNET_DNSPARSER_TYPE_AAAA
#define GNUNET_DNSPARSER_MAX_NAME_LENGTH
Maximum length of a name in DNS.
GNUNET_GNS_LocalOptions
Options for the GNS lookup.
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_IDENTITY_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
#define GNUNET_log(kind,...)
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:302
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:56
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_NAMECACHE_disconnect(struct GNUNET_NAMECACHE_Handle *h)
Disconnect from the namecache service (and free associated resources).
struct GNUNET_NAMECACHE_Handle * GNUNET_NAMECACHE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namecache service.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:79
#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP
Client would like to resolve a name.
#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT
Service response to name resolution request from client.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:533
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1281
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1316
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2329
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2442
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2248
@ GNUNET_SERVICE_OPTION_NONE
Use defaults.
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
enum GNUNET_GenericReturnValue GNUNET_STRINGS_string_to_data(const char *enc, size_t enclen, void *out, size_t out_size)
Convert CrockfordBase32 encoding back to data.
Definition: strings.c:789
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
Handle to a lookup operation from client via API.
struct GnsClient * gc
Client handle.
struct ClientLookupHandle * next
We keep these in a DLL.
struct GNS_ResolverHandle * lookup
Active handle for the lookup.
uint32_t request_id
request id
struct ClientLookupHandle * prev
We keep these in a DLL.
Handle to a currently pending resolution.
Representation of a TLD, mapping the respective TLD string (e.g.
struct GNS_TopLevelDomain * prev
Kept in a DLL, as there are unlikely enough of these to warrant a hash map.
char * tld
Top-level domain as a string, including leading ".".
struct GNS_TopLevelDomain * next
Kept in a DLL, as there are unlikely enough of these to warrant a hash map.
struct GNUNET_IDENTITY_PublicKey pkey
Public key associated with the tld.
Connection to the DHT service.
Definition: dht_api.c:237
An identity key as per LSD0001.
Handle to a message queue.
Definition: mq.c:86
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Connection to the NAMECACHE service.
Definition: namecache_api.c:95
Handle to a client that is connected to a service.
Definition: service.c:251
Handle to a service.
Definition: service.c:117
Handle for the service.
Information we track per connected client.
struct ClientLookupHandle * clh_tail
Tail of the DLL.
struct GNUNET_MQ_Handle * mq
The MQ.
struct ClientLookupHandle * clh_head
Head of the DLL.
struct GNUNET_SERVICE_Client * client
The client.
Message from client to GNS service to lookup records.
Definition: gns.h:37
int16_t options
Local options for where to look for results (an enum GNUNET_GNS_LocalOptions in NBO).
Definition: gns.h:57
uint32_t id
Unique identifier for this request (for key collisions).
Definition: gns.h:46
struct GNUNET_MessageHeader header
Header of type GNUNET_MESSAGE_TYPE_GNS_LOOKUP.
Definition: gns.h:41
uint16_t recursion_depth_limit
Recursion depth limit, i.e.
Definition: gns.h:64
int32_t type
the type of record to look up
Definition: gns.h:69
struct GNUNET_IDENTITY_PublicKey zone
Zone that is to be used for lookup.
Definition: gns.h:51
Message from GNS service to client: new results.
Definition: gns.h:79
uint32_t id
Unique identifier for this request (for key collisions).
Definition: gns.h:88
uint32_t rd_count
The number of records contained in response.
Definition: gns.h:95