GNUnet 0.22.0
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 "gnunet_common.h"
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dns_service.h"
30#include "gnunet_dht_service.h"
33#include "gnunet_gns_service.h"
35#include "gns.h"
36#include "gnunet-service-gns.h"
39#include "gnunet_protocols.h"
40
41
45struct GnsClient;
46
51{
56
61
65 struct GnsClient *gc;
66
71
75 uint32_t request_id;
76};
77
78
83{
88
93
98
103};
104
105
111{
117
123
128
132 char *tld;
133};
134
135
140
145
149static int v6_enabled;
150
154static int v4_enabled;
155
160
165
170
171
180GNS_find_tld (const char *tld_str,
182{
183 if ('\0' == *tld_str)
184 return GNUNET_NO;
185 for (struct GNS_TopLevelDomain *tld = tld_head;
186 NULL != tld;
187 tld = tld->next)
188 {
189 if (0 == strcasecmp (tld_str,
190 tld->tld))
191 {
192 *pkey = tld->pkey;
193 return GNUNET_YES;
194 }
195 }
196 if (GNUNET_OK ==
198 pkey))
199 return GNUNET_YES; /* TLD string *was* the public key */
200 return GNUNET_NO;
201}
202
203
211const char *
212GNS_get_tld (const char *name)
213{
214 const char *tld;
215
216 tld = strrchr (name,
217 (unsigned char) '.');
218 if (NULL == tld)
219 tld = name;
220 else
221 tld++; /* skip the '.' */
222 return tld;
223}
224
225
231static void
232shutdown_task (void *cls)
233{
234 struct GNS_TopLevelDomain *tld;
235
236 (void) cls;
238 "Shutting down!\n");
241 if (NULL != statistics)
242 {
244 GNUNET_NO);
245 statistics = NULL;
246 }
247 if (NULL != namecache_handle)
248 {
250 namecache_handle = NULL;
251 }
252 if (NULL != dht_handle)
253 {
255 dht_handle = NULL;
256 }
257 while (NULL != (tld = tld_head))
258 {
260 tld_tail,
261 tld);
262 GNUNET_free (tld->tld);
264 }
265}
266
267
275static void
277 struct GNUNET_SERVICE_Client *client,
278 void *app_ctx)
279{
280 struct ClientLookupHandle *clh;
281 struct GnsClient *gc = app_ctx;
282
283 (void) cls;
285 "Client %p disconnected\n",
286 client);
287 while (NULL != (clh = gc->clh_head))
288 {
289 if (NULL != clh->lookup)
292 gc->clh_tail,
293 clh);
294 GNUNET_free (clh);
295 }
296 GNUNET_free (gc);
297}
298
299
308static void *
311 struct GNUNET_MQ_Handle *mq)
312{
313 struct GnsClient *gc;
314
315 (void) cls;
317 "Client %p connected\n",
318 client);
319 gc = GNUNET_new (struct GnsClient);
320 gc->client = client;
321 gc->mq = mq;
322 return gc;
323}
324
325
333static void
335 uint32_t rd_count,
336 const struct GNUNET_GNSRECORD_Data *rd)
337{
338 struct ClientLookupHandle *clh = cls;
339 struct GnsClient *gc = clh->gc;
340 struct GNUNET_MQ_Envelope *env;
341 struct LookupResultMessage *rmsg;
342 ssize_t len;
343
345 "Sending LOOKUP_RESULT message with %u results\n",
346 (unsigned int) rd_count);
348 rd);
349 if (len < 0)
350 {
351 GNUNET_break (0);
353 return;
354 }
355 if (len > UINT16_MAX - sizeof(*rmsg))
356 {
357 GNUNET_break (0);
359 return;
360 }
361 env = GNUNET_MQ_msg_extra (rmsg,
362 len,
364 rmsg->id = clh->request_id;
365 rmsg->rd_count = htonl (rd_count);
366 GNUNET_assert (len ==
368 rd,
369 len,
370 (char *) &rmsg[1]));
372 env);
374 gc->clh_tail,
375 clh);
376 GNUNET_free (clh);
378 "Completed lookups", 1,
379 GNUNET_NO);
381 "Records resolved",
382 rd_count,
383 GNUNET_NO);
384}
385
386
394static int
395check_lookup (void *cls,
396 const struct LookupMessage *l_msg)
397{
398 size_t nlen;
399 size_t klen;
400
401 (void) cls;
402 klen = ntohl (l_msg->key_len);
403 nlen = ntohs (l_msg->header.size) - sizeof(struct LookupMessage) - klen;
405 {
406 GNUNET_break (0);
407 return GNUNET_SYSERR;
408 }
409 return GNUNET_OK;
410}
411
412
419static void
420handle_lookup (void *cls,
421 const struct LookupMessage *sh_msg)
422{
423 struct GnsClient *gc = cls;
424 struct ClientLookupHandle *clh;
425 struct GNUNET_CRYPTO_PublicKey zone;
426 const char *name;
427 size_t key_len;
428 size_t read;
429
431 key_len = ntohl (sh_msg->key_len);
432 clh = GNUNET_new (struct ClientLookupHandle);
434 gc->clh_tail,
435 clh);
436 clh->gc = gc;
437 clh->request_id = sh_msg->id;
438 if ((GNUNET_SYSERR ==
440 key_len,
441 &zone,
442 &read)) ||
443 (read != key_len))
444 {
446 "LOOKUP: Failed to read zone key!");
448 0,
449 NULL);
450 return;
451 }
452 name = (const char *) &sh_msg[1] + key_len;
454 "Received LOOKUP `%s' message\n",
455 name);
456 if ((GNUNET_DNSPARSER_TYPE_A == ntohl (sh_msg->type)) &&
458 {
460 "LOOKUP: Query for A record but AF_INET not supported!");
462 0,
463 NULL);
464 return;
465 }
466 if ((GNUNET_DNSPARSER_TYPE_AAAA == ntohl (sh_msg->type)) &&
468 {
470 "LOOKUP: Query for AAAA record but AF_INET6 not supported!");
472 0,
473 NULL);
474 return;
475 }
476 clh->lookup = GNS_resolver_lookup (&zone,
477 ntohl (sh_msg->type),
478 name,
479 (enum GNUNET_GNS_LocalOptions) ntohs (
480 sh_msg->options),
481 ntohs (sh_msg->recursion_depth_limit),
484 "Lookup attempts",
485 1, GNUNET_NO);
486}
487
488
497static void
499 const char *section,
500 const char *option,
501 const char *value)
502{
504 struct GNS_TopLevelDomain *tld;
505
506 (void) cls;
507 (void) section;
508 if (option[0] != '.')
509 return;
510 if (GNUNET_OK !=
512 strlen (value),
513 &pk,
514 sizeof(pk)))
515 {
517 section,
518 option,
519 _ (
520 "Properly base32-encoded public key required"));
521 return;
522 }
524 tld->tld = GNUNET_strdup (&option[1]);
525 tld->pkey = pk;
527 tld_tail,
528 tld);
529}
530
531
539static void
540run (void *cls,
541 const struct GNUNET_CONFIGURATION_Handle *c,
543{
544 unsigned long long max_parallel_bg_queries = 16;
545
547 "gns",
549 NULL);
553 if (NULL == namecache_handle)
554 {
556 _ ("Failed to connect to the namecache!\n"));
558 return;
559 }
560 if (GNUNET_OK ==
562 "gns",
563 "MAX_PARALLEL_BACKGROUND_QUERIES",
564 &max_parallel_bg_queries))
565 {
567 "Number of allowed parallel background queries: %llu\n",
568 max_parallel_bg_queries);
569 }
571 (unsigned int) max_parallel_bg_queries);
572 if (NULL == dht_handle)
573 {
575 _ ("Could not connect to DHT!\n"));
577 NULL);
578 return;
579 }
582 c,
583 max_parallel_bg_queries);
584 if ((GNUNET_YES ==
586 "gns",
587 "INTERCEPT_DNS")) &&
588 (GNUNET_SYSERR ==
590 {
591 GNUNET_break (0);
593 NULL);
594 return;
595 }
597 c);
599 NULL);
600}
601
602
607 ("gns",
609 &run,
612 NULL,
613 GNUNET_MQ_hd_var_size (lookup,
615 struct LookupMessage,
616 NULL),
618
619
620/* 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.
struct GNUNET_CRYPTO_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 * name
Name (label) of the records to list.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static char * value
Value of the record to add/remove.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
enum GNUNET_GenericReturnValue GNS_find_tld(const char *tld_str, struct GNUNET_CRYPTO_PublicKey *pkey)
Find GNS zone belonging to TLD tld.
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 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 struct GNUNET_DHT_Handle * dht_handle
Our handle to the DHT.
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_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
Called whenever a client is disconnected.
static int v6_enabled
GNUNET_YES if ipv6 is supported
const char * GNS_get_tld(const char *name)
Obtain the TLD of the given name.
static struct GNUNET_NAMECACHE_Handle * namecache_handle
Our handle to the namecache service.
GNU Name System (main 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.
void GNS_resolver_done()
Shutdown resolver.
struct GNS_ResolverHandle * GNS_resolver_lookup(const struct GNUNET_CRYPTO_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.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
API to the DHT service.
API to access the DNS service.
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:1037
void GNUNET_DHT_disconnect(struct GNUNET_DHT_Handle *handle)
Shutdown connection with the DHT service.
Definition: dht_api.c:1060
#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.
int GNUNET_GNSRECORD_zkey_to_pkey(const char *zkey, struct GNUNET_CRYPTO_PublicKey *pkey)
Convert an absolute domain name to the respective public key.
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.
#define GNUNET_log(kind,...)
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_read_public_key_from_buffer(const void *buffer, size_t len, struct GNUNET_CRYPTO_PublicKey *key, size_t *read)
Reads a GNUNET_CRYPTO_PublicKey from a compact buffer.
Definition: crypto_pkey.c:102
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#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:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#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:63
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
struct GNUNET_NAMECACHE_Handle * GNUNET_NAMECACHE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namecache service.
void GNUNET_NAMECACHE_disconnect(struct GNUNET_NAMECACHE_Handle *h)
Disconnect from the namecache service (and free associated resources).
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:566
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:1338
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:1303
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2377
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2459
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2348
@ 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:178
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_CRYPTO_PublicKey pkey
Public key associated with the tld.
An identity key as per LSD0001.
Connection to the DHT service.
Definition: dht_api.c:235
Handle to a message queue.
Definition: mq.c:87
Connection to the NAMECACHE service.
Definition: namecache_api.c:93
Handle to a client that is connected to a service.
Definition: service.c:245
Handle to a service.
Definition: service.c:116
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:52
uint32_t id
Unique identifier for this request (for key collisions).
Definition: gns.h:46
uint32_t key_len
Length of the zone key.
Definition: gns.h:69
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:59
int32_t type
the type of record to look up
Definition: gns.h:64
Message from GNS service to client: new results.
Definition: gns.h:80
uint32_t id
Unique identifier for this request (for key collisions).
Definition: gns.h:89
uint32_t rd_count
The number of records contained in response.
Definition: gns.h:96