aboutsummaryrefslogtreecommitdiff
path: root/src/gns/gnunet-service-gns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns/gnunet-service-gns.c')
-rw-r--r--src/gns/gnunet-service-gns.c601
1 files changed, 0 insertions, 601 deletions
diff --git a/src/gns/gnunet-service-gns.c b/src/gns/gnunet-service-gns.c
deleted file mode 100644
index b28236fed..000000000
--- a/src/gns/gnunet-service-gns.c
+++ /dev/null
@@ -1,601 +0,0 @@
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 */
20/**
21 * @file gns/gnunet-service-gns.c
22 * @brief GNU Name System (main service)
23 * @author Martin Schanzenbach
24 * @author Christian Grothoff
25 */
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"
31#include "gnunet_namecache_service.h"
32#include "gnunet_gnsrecord_lib.h"
33#include "gnunet_gns_service.h"
34#include "gnunet_statistics_service.h"
35#include "gns.h"
36#include "gnunet-service-gns_resolver.h"
37#include "gnunet-service-gns_interceptor.h"
38#include "gnunet_protocols.h"
39
40
41/**
42 * GnsClient prototype
43 */
44struct GnsClient;
45
46/**
47 * Handle to a lookup operation from client via API.
48 */
49struct ClientLookupHandle
50{
51 /**
52 * We keep these in a DLL.
53 */
54 struct ClientLookupHandle *next;
55
56 /**
57 * We keep these in a DLL.
58 */
59 struct ClientLookupHandle *prev;
60
61 /**
62 * Client handle
63 */
64 struct GnsClient *gc;
65
66 /**
67 * Active handle for the lookup.
68 */
69 struct GNS_ResolverHandle *lookup;
70
71 /**
72 * request id
73 */
74 uint32_t request_id;
75};
76
77
78/**
79 * Information we track per connected client.
80 */
81struct GnsClient
82{
83 /**
84 * The client
85 */
86 struct GNUNET_SERVICE_Client *client;
87
88 /**
89 * The MQ
90 */
91 struct GNUNET_MQ_Handle *mq;
92
93 /**
94 * Head of the DLL.
95 */
96 struct ClientLookupHandle *clh_head;
97
98 /**
99 * Tail of the DLL.
100 */
101 struct ClientLookupHandle *clh_tail;
102};
103
104
105/**
106 * Representation of a TLD, mapping the respective TLD string
107 * (e.g. ".gnu") to the respective public key of the zone.
108 */
109struct GNS_TopLevelDomain
110{
111 /**
112 * Kept in a DLL, as there are unlikely enough of these to
113 * warrant a hash map.
114 */
115 struct GNS_TopLevelDomain *next;
116
117 /**
118 * Kept in a DLL, as there are unlikely enough of these to
119 * warrant a hash map.
120 */
121 struct GNS_TopLevelDomain *prev;
122
123 /**
124 * Public key associated with the @a tld.
125 */
126 struct GNUNET_IDENTITY_PublicKey pkey;
127
128 /**
129 * Top-level domain as a string, including leading ".".
130 */
131 char *tld;
132};
133
134
135/**
136 * Our handle to the DHT
137 */
138static struct GNUNET_DHT_Handle *dht_handle;
139
140/**
141 * Our handle to the namecache service
142 */
143static struct GNUNET_NAMECACHE_Handle *namecache_handle;
144
145/**
146 * #GNUNET_YES if ipv6 is supported
147 */
148static int v6_enabled;
149
150/**
151 * #GNUNET_YES if ipv4 is supported
152 */
153static int v4_enabled;
154
155/**
156 * Handle to the statistics service
157 */
158static struct GNUNET_STATISTICS_Handle *statistics;
159
160/**
161 * Head of DLL of TLDs we map to GNS zones.
162 */
163static struct GNS_TopLevelDomain *tld_head;
164
165/**
166 * Tail of DLL of TLDs we map to GNS zones.
167 */
168static struct GNS_TopLevelDomain *tld_tail;
169
170
171/**
172 * Find GNS zone belonging to TLD @a tld.
173 *
174 * @param tld_str top-level domain to look up
175 * @param[out] pkey public key to set
176 * @return #GNUNET_YES if @a tld was found #GNUNET_NO if not
177 */
178int
179GNS_find_tld (const char *tld_str,
180 struct GNUNET_IDENTITY_PublicKey *pkey)
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
203/**
204 * Obtain the TLD of the given @a name.
205 *
206 * @param name a name
207 * @return the part of @a name after the last ".",
208 * or @a name if @a name does not contain a "."
209 */
210const char *
211GNS_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
225/**
226 * Task run during shutdown.
227 *
228 * @param cls unused, NULL
229 */
230static void
231shutdown_task (void *cls)
232{
233 struct GNS_TopLevelDomain *tld;
234
235 (void) cls;
236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
237 "Shutting down!\n");
238 GNS_interceptor_done ();
239 GNS_resolver_done ();
240 if (NULL != statistics)
241 {
242 GNUNET_STATISTICS_destroy (statistics,
243 GNUNET_NO);
244 statistics = NULL;
245 }
246 if (NULL != namecache_handle)
247 {
248 GNUNET_NAMECACHE_disconnect (namecache_handle);
249 namecache_handle = NULL;
250 }
251 if (NULL != dht_handle)
252 {
253 GNUNET_DHT_disconnect (dht_handle);
254 dht_handle = NULL;
255 }
256 while (NULL != (tld = tld_head))
257 {
258 GNUNET_CONTAINER_DLL_remove (tld_head,
259 tld_tail,
260 tld);
261 GNUNET_free (tld->tld);
262 GNUNET_free (tld);
263 }
264}
265
266
267/**
268 * Called whenever a client is disconnected.
269 *
270 * @param cls closure
271 * @param client identification of the client
272 * @param app_ctx @a client
273 */
274static void
275client_disconnect_cb (void *cls,
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;
283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
284 "Client %p disconnected\n",
285 client);
286 while (NULL != (clh = gc->clh_head))
287 {
288 if (NULL != clh->lookup)
289 GNS_resolver_lookup_cancel (clh->lookup);
290 GNUNET_CONTAINER_DLL_remove (gc->clh_head,
291 gc->clh_tail,
292 clh);
293 GNUNET_free (clh);
294 }
295 GNUNET_free (gc);
296}
297
298
299/**
300 * Add a client to our list of active clients.
301 *
302 * @param cls NULL
303 * @param client client to add
304 * @param mq message queue for @a client
305 * @return internal namestore client structure for this client
306 */
307static void *
308client_connect_cb (void *cls,
309 struct GNUNET_SERVICE_Client *client,
310 struct GNUNET_MQ_Handle *mq)
311{
312 struct GnsClient *gc;
313
314 (void) cls;
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
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
325/**
326 * Reply to client with the result from our lookup.
327 *
328 * @param cls the closure (our client lookup handle)
329 * @param rd_count the number of records in @a rd
330 * @param rd the record data
331 */
332static void
333send_lookup_response (void *cls,
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
343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
344 "Sending LOOKUP_RESULT message with %u results\n",
345 (unsigned int) rd_count);
346 len = GNUNET_GNSRECORD_records_get_size (rd_count,
347 rd);
348 if (len < 0)
349 {
350 GNUNET_break (0);
351 GNUNET_SERVICE_client_drop (gc->client);
352 return;
353 }
354 if (len > UINT16_MAX - sizeof(*rmsg))
355 {
356 GNUNET_break (0);
357 GNUNET_SERVICE_client_drop (gc->client);
358 return;
359 }
360 env = GNUNET_MQ_msg_extra (rmsg,
361 len,
362 GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT);
363 rmsg->id = clh->request_id;
364 rmsg->rd_count = htonl (rd_count);
365 GNUNET_assert (len ==
366 GNUNET_GNSRECORD_records_serialize (rd_count,
367 rd,
368 len,
369 (char *) &rmsg[1]));
370 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (gc->client),
371 env);
372 GNUNET_CONTAINER_DLL_remove (gc->clh_head,
373 gc->clh_tail,
374 clh);
375 GNUNET_free (clh);
376 GNUNET_STATISTICS_update (statistics,
377 "Completed lookups", 1,
378 GNUNET_NO);
379 GNUNET_STATISTICS_update (statistics,
380 "Records resolved",
381 rd_count,
382 GNUNET_NO);
383}
384
385
386/**
387 * Checks a #GNUNET_MESSAGE_TYPE_GNS_LOOKUP message
388 *
389 * @param cls client sending the message
390 * @param l_msg message of type `struct LookupMessage`
391 * @return #GNUNET_OK if @a l_msg is well-formed
392 */
393static int
394check_lookup (void *cls,
395 const struct LookupMessage *l_msg)
396{
397 size_t nlen;
398
399 (void) cls;
400 GNUNET_MQ_check_zero_termination (l_msg);
401 nlen = ntohs (l_msg->header.size) - sizeof(struct LookupMessage);
402 if (nlen > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
403 {
404 GNUNET_break (0);
405 return GNUNET_SYSERR;
406 }
407 return GNUNET_OK;
408}
409
410
411/**
412 * Handle lookup requests from client
413 *
414 * @param cls the closure
415 * @param client the client
416 * @param message the message
417 */
418static void
419handle_lookup (void *cls,
420 const struct LookupMessage *sh_msg)
421{
422 struct GnsClient *gc = cls;
423 struct ClientLookupHandle *clh;
424 const char *name;
425
426 GNUNET_SERVICE_client_continue (gc->client);
427 name = (const char *) &sh_msg[1];
428 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
429 "Received LOOKUP `%s' message\n",
430 name);
431 clh = GNUNET_new (struct ClientLookupHandle);
432 GNUNET_CONTAINER_DLL_insert (gc->clh_head,
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 {
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
441 "LOOKUP: Query for A record but AF_INET not supported!");
442 send_lookup_response (clh,
443 0,
444 NULL);
445 return;
446 }
447 if ((GNUNET_DNSPARSER_TYPE_AAAA == ntohl (sh_msg->type)) &&
448 (GNUNET_OK != v6_enabled))
449 {
450 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
451 "LOOKUP: Query for AAAA record but AF_INET6 not supported!");
452 send_lookup_response (clh,
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);
464 GNUNET_STATISTICS_update (statistics,
465 "Lookup attempts",
466 1, GNUNET_NO);
467}
468
469
470/**
471 * Reads the configuration and populates TLDs
472 *
473 * @param cls unused
474 * @param section name of section in config, always "gns"
475 * @param option name of the option, TLDs start with "."
476 * @param value value for the option, public key for TLDs
477 */
478static void
479read_service_conf (void *cls,
480 const char *section,
481 const char *option,
482 const char *value)
483{
484 struct GNUNET_IDENTITY_PublicKey pk;
485 struct GNS_TopLevelDomain *tld;
486
487 (void) cls;
488 (void) section;
489 if (option[0] != '.')
490 return;
491 if (GNUNET_OK !=
492 GNUNET_STRINGS_string_to_data (value,
493 strlen (value),
494 &pk,
495 sizeof(pk)))
496 {
497 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
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;
507 GNUNET_CONTAINER_DLL_insert (tld_head,
508 tld_tail,
509 tld);
510}
511
512
513/**
514 * Process GNS requests.
515 *
516 * @param cls closure
517 * @param server the initialized server
518 * @param c configuration to use
519 */
520static void
521run (void *cls,
522 const struct GNUNET_CONFIGURATION_Handle *c,
523 struct GNUNET_SERVICE_Handle *service)
524{
525 unsigned long long max_parallel_bg_queries = 16;
526
527 GNUNET_CONFIGURATION_iterate_section_values (c,
528 "gns",
529 &read_service_conf,
530 NULL);
531 v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6);
532 v4_enabled = GNUNET_NETWORK_test_pf (PF_INET);
533 namecache_handle = GNUNET_NAMECACHE_connect (c);
534 if (NULL == namecache_handle)
535 {
536 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
537 _ ("Failed to connect to the namecache!\n"));
538 GNUNET_SCHEDULER_shutdown ();
539 return;
540 }
541 if (GNUNET_OK ==
542 GNUNET_CONFIGURATION_get_value_number (c,
543 "gns",
544 "MAX_PARALLEL_BACKGROUND_QUERIES",
545 &max_parallel_bg_queries))
546 {
547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
548 "Number of allowed parallel background queries: %llu\n",
549 max_parallel_bg_queries);
550 }
551 dht_handle = GNUNET_DHT_connect (c,
552 (unsigned int) max_parallel_bg_queries);
553 if (NULL == dht_handle)
554 {
555 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
556 _ ("Could not connect to DHT!\n"));
557 GNUNET_SCHEDULER_add_now (&shutdown_task,
558 NULL);
559 return;
560 }
561 GNS_resolver_init (namecache_handle,
562 dht_handle,
563 c,
564 max_parallel_bg_queries);
565 if ((GNUNET_YES ==
566 GNUNET_CONFIGURATION_get_value_yesno (c,
567 "gns",
568 "INTERCEPT_DNS")) &&
569 (GNUNET_SYSERR ==
570 GNS_interceptor_init (c)))
571 {
572 GNUNET_break (0);
573 GNUNET_SCHEDULER_add_now (&shutdown_task,
574 NULL);
575 return;
576 }
577 statistics = GNUNET_STATISTICS_create ("gns",
578 c);
579 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
580 NULL);
581}
582
583
584/**
585 * Define "main" method using service macro.
586 */
587GNUNET_SERVICE_MAIN
588 ("gns",
589 GNUNET_SERVICE_OPTION_NONE,
590 &run,
591 &client_connect_cb,
592 &client_disconnect_cb,
593 NULL,
594 GNUNET_MQ_hd_var_size (lookup,
595 GNUNET_MESSAGE_TYPE_GNS_LOOKUP,
596 struct LookupMessage,
597 NULL),
598 GNUNET_MQ_handler_end ());
599
600
601/* end of gnunet-service-gns.c */