2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file namestore/gnunet-service-namestore.c
23 * @brief namestore for the GNUnet naming system
24 * @author Matthias Wachs
27 #include "gnunet_util_lib.h"
28 #include "gnunet_dnsparser_lib.h"
29 #include "gnunet_namestore_service.h"
30 #include "gnunet_namestore_plugin.h"
31 #include "gnunet_signatures.h"
32 #include "namestore.h"
34 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
37 * A namestore operation.
39 struct GNUNET_NAMESTORE_ZoneIteration
42 * Next element in the DLL
44 struct GNUNET_NAMESTORE_ZoneIteration *next;
47 * Previous element in the DLL
49 struct GNUNET_NAMESTORE_ZoneIteration *prev;
52 * Namestore client which intiated this zone iteration
54 struct GNUNET_NAMESTORE_Client *client;
57 * GNUNET_YES if we iterate over a specific zone
58 * GNUNET_NO if we iterate over all zones
63 * Hash of the specific zone if 'has_zone' is GNUNET_YES,
64 * othwerwise set to '\0'
66 struct GNUNET_CRYPTO_ShortHashCode zone;
69 * The operation id fot the zone iteration in the response for the client
74 * Offset of the zone iteration used to address next result of the zone
75 * iteration in the store
77 * Initialy set to 0 in handle_iteration_start
78 * Incremented with by every call to handle_iteration_next
83 * Which flags must be included
85 uint16_t must_have_flags;
88 * Which flags must not be included
90 uint16_t must_not_have_flags;
97 struct GNUNET_NAMESTORE_Client
100 * Next element in the DLL
102 struct GNUNET_NAMESTORE_Client *next;
105 * Previous element in the DLL
107 struct GNUNET_NAMESTORE_Client *prev;
112 struct GNUNET_SERVER_Client *client;
116 * Zone iteration operations in progress initiated by this client
118 struct GNUNET_NAMESTORE_ZoneIteration *op_head;
122 * Zone iteration operations in progress initiated by this client
124 struct GNUNET_NAMESTORE_ZoneIteration *op_tail;
129 * A container struct to store information belonging to a zone crypto key pair
131 struct GNUNET_NAMESTORE_CryptoContainer
134 * Filename where to store the container
139 * Short hash of the zone's public key
141 struct GNUNET_CRYPTO_ShortHashCode zone;
146 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
152 * Configuration handle.
154 static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
159 static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
164 static char *zonefile_directory;
167 * Name of the database plugin
169 static char *db_lib_name;
172 * Our notification context.
174 static struct GNUNET_SERVER_NotificationContext *snc;
177 * Head of the Client DLL
179 static struct GNUNET_NAMESTORE_Client *client_head;
182 * Tail of the Client DLL
184 static struct GNUNET_NAMESTORE_Client *client_tail;
187 * Hashmap containing the zone keys this namestore has is authoritative for
189 * Keys are the GNUNET_CRYPTO_HashCode of the GNUNET_CRYPTO_ShortHashCode
190 * The values are 'struct GNUNET_NAMESTORE_CryptoContainer *'
192 static struct GNUNET_CONTAINER_MultiHashMap *zonekeys;
196 * Writes the encrypted private key of a zone in a file
198 * @param filename where to store the zone
199 * @param c the crypto container containing private key of the zone
200 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
203 write_key_to_file (const char *filename,
204 struct GNUNET_NAMESTORE_CryptoContainer *c)
206 struct GNUNET_CRYPTO_RsaPrivateKey *ret = c->privkey;
207 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
208 struct GNUNET_DISK_FileHandle *fd;
209 struct GNUNET_CRYPTO_ShortHashCode zone;
210 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
211 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
213 fd = GNUNET_DISK_file_open (filename,
214 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS,
215 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
216 if ( (NULL == fd) && (EEXIST == errno) )
218 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
221 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
222 _("Failed to write zone key to file `%s': %s\n"),
224 _("file exists but reading key failed"));
225 return GNUNET_SYSERR;
227 GNUNET_CRYPTO_rsa_key_get_public (privkey, &pubkey);
228 GNUNET_CRYPTO_short_hash (&pubkey, sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), &zone);
229 GNUNET_CRYPTO_rsa_key_free (privkey);
230 if (0 == memcmp (&zone, &c->zone, sizeof(zone)))
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233 "File zone `%s' containing this key already exists\n",
234 GNUNET_short_h2s (&zone));
237 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
238 _("Failed to write zone key to file `%s': %s\n"),
240 _("file exists with different key"));
245 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
246 return GNUNET_SYSERR;
248 if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES))
250 GNUNET_break (GNUNET_YES == GNUNET_DISK_file_close (fd));
251 return GNUNET_SYSERR;
253 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
254 GNUNET_assert (NULL != enc);
255 GNUNET_assert (ntohs (enc->len) == GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
257 GNUNET_DISK_file_sync (fd);
258 if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
259 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
260 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
262 "Stored zonekey for zone `%s' in file `%s'\n",
263 GNUNET_short_h2s(&c->zone), c->filename);
269 * Write allthe given zone key to disk and then removes the entry from the
270 * 'zonekeys' hash map.
273 * @param key zone key
274 * @param value 'struct GNUNET_NAMESTORE_CryptoContainer' containing the private
276 * @return GNUNET_OK to continue iteration
279 zone_to_disk_it (void *cls,
280 const struct GNUNET_HashCode *key,
283 struct GNUNET_NAMESTORE_CryptoContainer *c = value;
285 if (NULL == c->filename)
286 GNUNET_asprintf(&c->filename,
289 GNUNET_short_h2s (&c->zone));
290 (void) write_key_to_file(c->filename, c);
291 GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (zonekeys, key, value));
292 GNUNET_CRYPTO_rsa_key_free (c->privkey);
293 GNUNET_free (c->filename);
300 * Add the given private key to the set of private keys
301 * this namestore can use to sign records when needed.
303 * @param pkey private key to add to our list (reference will
304 * be taken over or freed and should not be used afterwards)
307 learn_private_key (struct GNUNET_CRYPTO_RsaPrivateKey *pkey)
309 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
310 struct GNUNET_HashCode long_hash;
311 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
312 struct GNUNET_NAMESTORE_CryptoContainer *cc;
314 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
315 GNUNET_CRYPTO_short_hash (&pub,
316 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
318 GNUNET_CRYPTO_short_hash_double (&pubkey_hash, &long_hash);
320 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains(zonekeys, &long_hash))
322 GNUNET_CRYPTO_rsa_key_free (pkey);
325 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
326 "Received new private key for zone `%s'\n",
327 GNUNET_short_h2s(&pubkey_hash));
328 cc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_CryptoContainer));
330 cc->zone = pubkey_hash;
331 GNUNET_assert (GNUNET_YES ==
332 GNUNET_CONTAINER_multihashmap_put(zonekeys, &long_hash, cc,
333 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
338 * Returns the expiration time of the given block of records. The block
339 * expiration time is the expiration time of the block with smallest
342 * @param rd_count number of records given in 'rd'
343 * @param rd array of records
344 * @return absolute expiration time
346 static struct GNUNET_TIME_Absolute
347 get_block_expiration_time (unsigned int rd_count, const struct GNUNET_NAMESTORE_RecordData *rd)
350 struct GNUNET_TIME_Absolute expire;
351 struct GNUNET_TIME_Absolute at;
352 struct GNUNET_TIME_Relative rt;
355 return GNUNET_TIME_UNIT_ZERO_ABS;
356 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
357 for (c = 0; c < rd_count; c++)
359 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
361 rt.rel_value = rd[c].expiration_time;
362 at = GNUNET_TIME_relative_to_absolute (rt);
366 at.abs_value = rd[c].expiration_time;
368 expire = GNUNET_TIME_absolute_min (at, expire);
375 * Task run during shutdown.
381 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
383 struct GNUNET_NAMESTORE_ZoneIteration *no;
384 struct GNUNET_NAMESTORE_Client *nc;
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
389 GNUNET_SERVER_notification_context_destroy (snc);
392 GNUNET_CONTAINER_multihashmap_iterate (zonekeys, &zone_to_disk_it, NULL);
393 GNUNET_CONTAINER_multihashmap_destroy (zonekeys);
395 while (NULL != (nc = client_head))
397 while (NULL != (no = nc->op_head))
399 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
402 GNUNET_SERVER_client_drop(nc->client);
403 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
406 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
407 GNUNET_free (db_lib_name);
409 GNUNET_free_non_null (zonefile_directory);
410 zonefile_directory = NULL;
415 * Lookup our internal data structure for a given client.
417 * @param client server client handle to use for the lookup
418 * @return our internal structure for the client, NULL if
419 * we do not have any yet
421 static struct GNUNET_NAMESTORE_Client *
422 client_lookup (struct GNUNET_SERVER_Client *client)
424 struct GNUNET_NAMESTORE_Client *nc;
426 GNUNET_assert (NULL != client);
427 for (nc = client_head; NULL != nc; nc = nc->next)
428 if (client == nc->client)
435 * Called whenever a client is disconnected.
436 * Frees our resources associated with that client.
439 * @param client identification of the client
442 client_disconnect_notification (void *cls,
443 struct GNUNET_SERVER_Client *client)
445 struct GNUNET_NAMESTORE_ZoneIteration *no;
446 struct GNUNET_NAMESTORE_Client *nc;
450 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
451 "Client %p disconnected\n",
453 if (NULL == (nc = client_lookup (client)))
455 while (NULL != (no = nc->op_head))
457 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
460 GNUNET_SERVER_client_drop (nc->client);
461 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc);
467 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_START' message
470 * @param client GNUNET_SERVER_Client sending the message
471 * @param message unused
474 handle_start (void *cls,
475 struct GNUNET_SERVER_Client *client,
476 const struct GNUNET_MessageHeader *message)
478 struct GNUNET_NAMESTORE_Client *nc;
480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
481 "Client %p connected\n", client);
482 if (NULL != client_lookup (client))
485 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
488 nc = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Client));
490 GNUNET_SERVER_notification_context_add (snc, client);
491 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc);
492 GNUNET_SERVER_client_keep (client);
493 GNUNET_SERVER_receive_done (client, GNUNET_OK);
498 * Context for name lookups passed from 'handle_lookup_name' to
499 * 'handle_lookup_name_it' as closure
501 struct LookupNameContext
504 * The client to send the response to
506 struct GNUNET_NAMESTORE_Client *nc;
511 const struct GNUNET_CRYPTO_ShortHashCode *zone;
519 * Operation id for the name lookup
524 * Requested specific record type
526 uint32_t record_type;
531 * A 'GNUNET_NAMESTORE_RecordIterator' for name lookups in handle_lookup_name
533 * @param cls a 'struct LookupNameContext *' with information about the request
534 * @param zone_key zone key of the zone
535 * @param expire expiration time
537 * @param rd_count number of records
538 * @param rd array of records
539 * @param signature signature
542 handle_lookup_name_it (void *cls,
543 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
544 struct GNUNET_TIME_Absolute expire,
546 unsigned int rd_count,
547 const struct GNUNET_NAMESTORE_RecordData *rd,
548 const struct GNUNET_CRYPTO_RsaSignature *signature)
550 struct LookupNameContext *lnc = cls;
551 struct LookupNameResponseMessage *lnr_msg;
552 struct GNUNET_NAMESTORE_RecordData *rd_selected;
553 struct GNUNET_NAMESTORE_CryptoContainer *cc;
554 struct GNUNET_CRYPTO_RsaSignature *signature_new;
555 struct GNUNET_TIME_Absolute e;
556 struct GNUNET_TIME_Relative re;
557 struct GNUNET_CRYPTO_ShortHashCode zone_key_hash;
558 struct GNUNET_HashCode long_hash;
565 int contains_signature;
570 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
571 "Found %u records under name `%s'\n",
574 authoritative = GNUNET_NO;
575 signature_new = NULL;
577 if (NULL != zone_key)
579 GNUNET_CRYPTO_short_hash (zone_key,
580 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
582 GNUNET_CRYPTO_short_hash_double (&zone_key_hash, &long_hash);
583 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get (zonekeys, &long_hash)))
585 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
586 "Am authoritative for zone `%s'\n",
587 GNUNET_short_h2s (&zone_key_hash));
588 authoritative = GNUNET_YES;
593 rd_modified = GNUNET_NO;
595 /* count records to copy */
596 for (c = 0; c < rd_count; c++)
598 if ( (GNUNET_YES == authoritative) &&
600 GNUNET_NAMESTORE_is_expired (&rd[c]) ) )
602 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
603 "Skipping expired record\n");
606 if ( (GNUNET_NAMESTORE_TYPE_ANY == lnc->record_type) ||
607 (rd[c].record_type == lnc->record_type) )
608 copied_elements++; /* found matching record */
611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
612 "Skipping non-mtaching record\n");
613 rd_modified = GNUNET_YES;
616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
617 "Found %u records with type %u for name `%s' in zone `%s'\n",
621 GNUNET_short_h2s(lnc->zone));
622 if (copied_elements > 0)
624 rd_selected = GNUNET_malloc (copied_elements * sizeof (struct GNUNET_NAMESTORE_RecordData));
626 for (c = 0; c < rd_count; c++)
628 if ( (GNUNET_YES == authoritative) &&
630 GNUNET_NAMESTORE_is_expired (&rd[c])) )
632 if ( (GNUNET_NAMESTORE_TYPE_ANY == lnc->record_type) ||
633 (rd[c].record_type == lnc->record_type) )
635 if (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
637 GNUNET_break (GNUNET_YES == authoritative);
638 rd_modified = GNUNET_YES;
639 re.rel_value = rd[c].expiration_time;
640 e = GNUNET_TIME_relative_to_absolute (re);
644 e.abs_value = rd[c].expiration_time;
646 /* found matching record, copy and convert flags to public format */
647 rd_selected[copied_elements] = rd[c]; /* shallow copy! */
648 rd_selected[copied_elements].expiration_time = e.abs_value;
649 if (0 != (rd_selected[copied_elements].flags &
650 (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION | GNUNET_NAMESTORE_RF_AUTHORITY)))
652 rd_selected[copied_elements].flags &= ~ (GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION |
653 GNUNET_NAMESTORE_RF_AUTHORITY);
654 rd_modified = GNUNET_YES;
660 rd_modified = GNUNET_YES;
667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
668 "Found %u matching records for name `%s' in zone `%s'\n",
671 GNUNET_short_h2s (lnc->zone));
672 contains_signature = GNUNET_NO;
673 if (copied_elements > 0)
675 if (GNUNET_YES == authoritative)
677 GNUNET_assert (NULL != cc);
678 e = get_block_expiration_time (rd_count, rd);
679 signature_new = GNUNET_NAMESTORE_create_signature (cc->privkey, e, name, rd_selected, copied_elements);
680 GNUNET_assert (NULL != signature_new);
681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
682 "Creating signature for name `%s' with %u records in zone `%s'\n",
685 GNUNET_short_h2s(&zone_key_hash));
689 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
690 "Not authoritative, records modified is %d, have sig is %d\n",
693 if ((GNUNET_NO == rd_modified) && (NULL != signature))
694 contains_signature = GNUNET_YES; /* returning all records, so include signature */
698 rd_ser_len = GNUNET_NAMESTORE_records_get_size (copied_elements, rd_selected);
699 name_len = (NULL == name) ? 0 : strlen(name) + 1;
700 r_size = sizeof (struct LookupNameResponseMessage) +
701 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "Sending `%s' message\n",
706 "NAMESTORE_LOOKUP_NAME_RESPONSE");
707 lnr_msg = GNUNET_malloc (r_size);
708 lnr_msg->gns_header.header.type = ntohs (GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE);
709 lnr_msg->gns_header.header.size = ntohs (r_size);
710 lnr_msg->gns_header.r_id = htonl (lnc->request_id);
711 lnr_msg->rd_count = htons (copied_elements);
712 lnr_msg->rd_len = htons (rd_ser_len);
713 lnr_msg->name_len = htons (name_len);
714 lnr_msg->expire = GNUNET_TIME_absolute_hton (get_block_expiration_time (copied_elements,
716 name_tmp = (char *) &lnr_msg[1];
717 memcpy (name_tmp, name, name_len);
718 rd_tmp = &name_tmp[name_len];
719 GNUNET_NAMESTORE_records_serialize (copied_elements, rd_selected, rd_ser_len, rd_tmp);
720 if (rd_selected != rd)
721 GNUNET_free_non_null (rd_selected);
722 if (NULL != zone_key)
723 lnr_msg->public_key = *zone_key;
724 if ( (GNUNET_YES == authoritative) &&
725 (copied_elements > 0) )
727 /* use new created signature */
728 lnr_msg->contains_sig = htons (GNUNET_YES);
729 GNUNET_assert (NULL != signature_new);
730 lnr_msg->signature = *signature_new;
731 GNUNET_free (signature_new);
733 else if (GNUNET_YES == contains_signature)
735 /* use existing signature */
736 lnr_msg->contains_sig = htons (GNUNET_YES);
737 GNUNET_assert (NULL != signature);
738 lnr_msg->signature = *signature;
740 GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client,
741 &lnr_msg->gns_header.header,
743 GNUNET_free (lnr_msg);
748 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME' message
751 * @param client GNUNET_SERVER_Client sending the message
752 * @param message message of type 'struct LookupNameMessage'
755 handle_lookup_name (void *cls,
756 struct GNUNET_SERVER_Client *client,
757 const struct GNUNET_MessageHeader *message)
759 const struct LookupNameMessage *ln_msg;
760 struct LookupNameContext lnc;
761 struct GNUNET_NAMESTORE_Client *nc;
767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768 "Received `%s' message\n",
769 "NAMESTORE_LOOKUP_NAME");
770 if (ntohs (message->size) < sizeof (struct LookupNameMessage))
773 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
776 if (NULL == (nc = client_lookup(client)))
779 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
782 ln_msg = (const struct LookupNameMessage *) message;
783 rid = ntohl (ln_msg->gns_header.r_id);
784 name_len = ntohl (ln_msg->name_len);
785 type = ntohl (ln_msg->record_type);
786 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
789 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
792 name = (const char *) &ln_msg[1];
793 if ('\0' != name[name_len -1])
796 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
799 if (GNUNET_NAMESTORE_TYPE_ANY == type)
800 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
801 "Looking up all records for name `%s' in zone `%s'\n",
803 GNUNET_short_h2s(&ln_msg->zone));
805 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
806 "Looking up records with type %u for name `%s' in zone `%s'\n",
808 GNUNET_short_h2s(&ln_msg->zone));
810 /* do the actual lookup */
811 lnc.request_id = rid;
813 lnc.record_type = type;
815 lnc.zone = &ln_msg->zone;
817 GSN_database->iterate_records (GSN_database->cls,
818 &ln_msg->zone, name, 0 /* offset */,
819 &handle_lookup_name_it, &lnc))
821 /* internal error (in database plugin); might be best to just hang up on
822 plugin rather than to signal that there are 'no' results, which
823 might also be false... */
825 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
828 GNUNET_SERVER_receive_done (client, GNUNET_OK);
833 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT' message
836 * @param client GNUNET_SERVER_Client sending the message
837 * @param message message of type 'struct RecordPutMessage'
840 handle_record_put (void *cls,
841 struct GNUNET_SERVER_Client *client,
842 const struct GNUNET_MessageHeader *message)
844 struct GNUNET_NAMESTORE_Client *nc;
845 const struct RecordPutMessage *rp_msg;
846 struct GNUNET_TIME_Absolute expire;
847 const struct GNUNET_CRYPTO_RsaSignature *signature;
848 struct RecordPutResponseMessage rpr_msg;
849 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
861 "Received `%s' message\n",
862 "NAMESTORE_RECORD_PUT");
863 if (ntohs (message->size) < sizeof (struct RecordPutMessage))
866 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
869 if (NULL == (nc = client_lookup (client)))
872 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
875 rp_msg = (const struct RecordPutMessage *) message;
876 rid = ntohl (rp_msg->gns_header.r_id);
877 msg_size = ntohs (rp_msg->gns_header.header.size);
878 name_len = ntohs (rp_msg->name_len);
879 rd_count = ntohs (rp_msg->rd_count);
880 rd_ser_len = ntohs (rp_msg->rd_len);
881 if ((rd_count < 1) || (rd_ser_len < 1) || (name_len >= MAX_NAME_LEN) || (0 == name_len))
884 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
887 msg_size_exp = sizeof (struct RecordPutMessage) + name_len + rd_ser_len;
888 if (msg_size != msg_size_exp)
891 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
894 name = (const char *) &rp_msg[1];
895 if ('\0' != name[name_len -1])
898 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
901 expire = GNUNET_TIME_absolute_ntoh (rp_msg->expire);
902 signature = &rp_msg->signature;
903 rd_ser = &name[name_len];
905 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
908 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
911 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
914 GNUNET_CRYPTO_short_hash (&rp_msg->public_key,
915 sizeof (rp_msg->public_key),
917 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
918 "Putting %u records under name `%s' in zone `%s'\n",
920 GNUNET_short_h2s (&zone_hash));
921 res = GSN_database->put_records(GSN_database->cls,
927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
928 "Putting record for name `%s': %s\n",
930 (GNUNET_OK == res) ? "OK" : "FAILED");
932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
933 "Sending `%s' message\n",
934 "RECORD_PUT_RESPONSE");
935 rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT_RESPONSE);
936 rpr_msg.gns_header.header.size = htons (sizeof (struct RecordPutResponseMessage));
937 rpr_msg.gns_header.r_id = htonl (rid);
938 rpr_msg.op_result = htonl (res);
939 GNUNET_SERVER_notification_context_unicast (snc,
941 &rpr_msg.gns_header.header,
943 GNUNET_SERVER_receive_done (client, GNUNET_OK);
948 * Context for record create operations passed from 'handle_record_create' to
949 * 'handle_create_record_it' as closure
951 struct CreateRecordContext
956 const struct GNUNET_NAMESTORE_RecordData *rd;
961 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pubkey;
964 * Name for the record to create
969 * Record expiration time
971 struct GNUNET_TIME_Absolute expire;
974 * result returned from 'handle_create_record_it'
975 * GNUNET_SYSERR: failed to create the record
976 * GNUNET_NO: we updated an existing record or identical entry existed
977 * GNUNET_YES : we created a new record
984 * A 'GNUNET_NAMESTORE_RecordIterator' for record create operations
985 * in handle_record_create
987 * @param cls a 'struct CreateRecordContext *' with information about the request
988 * @param pubkey zone key of the zone
989 * @param expire expiration time
991 * @param rd_count number of records
992 * @param rd array of records
993 * @param signature signature
996 handle_create_record_it (void *cls,
997 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pubkey,
998 struct GNUNET_TIME_Absolute expire,
1000 unsigned int rd_count,
1001 const struct GNUNET_NAMESTORE_RecordData *rd,
1002 const struct GNUNET_CRYPTO_RsaSignature *signature)
1004 static struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1005 struct CreateRecordContext *crc = cls;
1006 struct GNUNET_NAMESTORE_RecordData *rd_new;
1007 struct GNUNET_TIME_Absolute block_expiration;
1011 unsigned int rd_count_new;
1013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1014 "Found %u existing records for `%s'\n",
1015 rd_count, crc->name);
1018 for (c = 0; c < rd_count; c++)
1020 if ( (crc->rd->record_type != rd[c].record_type) ||
1021 ((crc->rd->flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)
1022 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1023 continue; /* no match */
1024 if ( (GNUNET_NAMESTORE_TYPE_PKEY == crc->rd->record_type) ||
1025 (GNUNET_NAMESTORE_TYPE_PSEU == crc->rd->record_type) ||
1026 (GNUNET_DNSPARSER_TYPE_CNAME == crc->rd->record_type) )
1028 /* Update unique PKEY, PSEU or CNAME record; for these
1029 record types, only one can be active at any time */
1031 if ( (crc->rd->data_size != rd[c].data_size) ||
1032 (0 != memcmp (crc->rd->data, rd[c].data, rd[c].data_size)) ||
1033 (crc->rd->expiration_time != rd[c].expiration_time) )
1034 update = GNUNET_YES;
1037 if ( (crc->rd->data_size == rd[c].data_size) &&
1038 (0 == memcmp (crc->rd->data, rd[c].data, rd[c].data_size)))
1040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1041 "Found matching existing record for `%s'; only updating expiration date!\n",
1044 if (crc->rd->expiration_time != rd[c].expiration_time)
1045 update = GNUNET_YES;
1050 if ( (-1 != exist) &&
1051 (GNUNET_NO == update) )
1053 /* Exact same record already exists */
1054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1055 "Matching record for %s' exists, no change required!\n",
1057 crc->res = GNUNET_NO; /* identical record existed */
1062 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1063 "No existing record for name `%s'!\n",
1065 rd_count_new = rd_count + 1;
1066 rd_new = GNUNET_malloc (rd_count_new * sizeof (struct GNUNET_NAMESTORE_RecordData));
1067 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1068 rd_new[rd_count] = *(crc->rd);
1072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1073 "Updating existing records for `%s'!\n",
1075 rd_count_new = rd_count;
1076 rd_new = GNUNET_malloc (rd_count_new * sizeof (struct GNUNET_NAMESTORE_RecordData));
1077 memcpy (rd_new, rd, rd_count * sizeof (struct GNUNET_NAMESTORE_RecordData));
1078 rd_new[exist] = *(crc->rd);
1080 block_expiration = GNUNET_TIME_absolute_max (crc->expire, expire);
1082 GSN_database->put_records (GSN_database->cls,
1086 rd_count_new, rd_new,
1088 crc->res = GNUNET_SYSERR; /* error */
1089 else if (GNUNET_YES == update)
1090 crc->res = GNUNET_NO; /* update */
1092 crc->res = GNUNET_YES; /* created new record */
1093 GNUNET_free (rd_new);
1098 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE' message
1101 * @param client GNUNET_SERVER_Client sending the message
1102 * @param message message of type 'struct RecordCreateMessage'
1105 handle_record_create (void *cls,
1106 struct GNUNET_SERVER_Client *client,
1107 const struct GNUNET_MessageHeader *message)
1109 struct GNUNET_NAMESTORE_Client *nc;
1110 const struct RecordCreateMessage *rp_msg;
1111 struct CreateRecordContext crc;
1112 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1113 struct RecordCreateResponseMessage rcr_msg;
1116 size_t msg_size_exp;
1120 const char *pkey_tmp;
1121 const char *name_tmp;
1123 unsigned int rd_count;
1125 struct GNUNET_NAMESTORE_RecordData rd;
1126 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1128 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1129 "Received `%s' message\n", "NAMESTORE_RECORD_CREATE");
1130 if (ntohs (message->size) < sizeof (struct RecordCreateMessage))
1133 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1136 if (NULL == (nc = client_lookup (client)))
1139 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1142 rp_msg = (const struct RecordCreateMessage *) message;
1143 rid = ntohl (rp_msg->gns_header.r_id);
1144 name_len = ntohs (rp_msg->name_len);
1145 msg_size = ntohs (message->size);
1146 rd_count = ntohs (rp_msg->rd_count);
1147 rd_ser_len = ntohs (rp_msg->rd_len);
1148 key_len = ntohs (rp_msg->pkey_len);
1149 msg_size_exp = sizeof (struct RecordCreateMessage) + key_len + name_len + rd_ser_len;
1150 if ( (msg_size != msg_size_exp) || (1 != rd_count) )
1153 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1156 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1159 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1162 pkey_tmp = (const char *) &rp_msg[1];
1163 name_tmp = &pkey_tmp[key_len];
1164 rd_ser = &name_tmp[name_len];
1165 if ('\0' != name_tmp[name_len -1])
1168 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1171 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1174 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1178 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, &rd))
1181 GNUNET_CRYPTO_rsa_key_free (pkey);
1182 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1186 /* Extracting and converting private key */
1187 GNUNET_CRYPTO_rsa_key_get_public (pkey, &crc.pubkey);
1188 GNUNET_CRYPTO_short_hash (&crc.pubkey,
1189 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1191 learn_private_key (pkey);
1192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1193 "Creating record for name `%s' in zone `%s'\n",
1194 name_tmp, GNUNET_short_h2s(&pubkey_hash));
1195 crc.expire = GNUNET_TIME_absolute_ntoh(rp_msg->expire);
1196 crc.res = GNUNET_SYSERR;
1198 crc.name = name_tmp;
1200 /* Get existing records for name */
1201 res = GSN_database->iterate_records (GSN_database->cls, &pubkey_hash, name_tmp, 0,
1202 &handle_create_record_it, &crc);
1203 if (res != GNUNET_SYSERR)
1207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1208 "Sending `%s' message\n", "RECORD_CREATE_RESPONSE");
1209 rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE_RESPONSE);
1210 rcr_msg.gns_header.header.size = htons (sizeof (struct RecordCreateResponseMessage));
1211 rcr_msg.gns_header.r_id = htonl (rid);
1212 if ((GNUNET_OK == res) && (crc.res == GNUNET_YES))
1213 rcr_msg.op_result = htonl (GNUNET_YES);
1214 else if ((GNUNET_OK == res) && (crc.res == GNUNET_NO))
1215 rcr_msg.op_result = htonl (GNUNET_NO);
1217 rcr_msg.op_result = htonl (GNUNET_SYSERR);
1218 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
1219 &rcr_msg.gns_header.header,
1221 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1226 * Context for record remove operations passed from 'handle_record_remove' to
1227 * 'handle_record_remove_it' as closure
1229 struct RemoveRecordContext
1234 const struct GNUNET_NAMESTORE_RecordData *rd;
1237 * See RECORD_REMOVE_RESULT_*-codes. Set by 'handle_record_remove_it'
1238 * to the result of the operation.
1245 * We are to remove a record (or all records for a given name). This function
1246 * will be called with the existing records (if there are any) and is to then
1247 * compute what to keep and trigger the necessary changes.
1249 * @param cls the 'struct RecordRemoveContext' with information about what to remove
1250 * @param zone_key public key of the zone
1251 * @param expire when does the corresponding block in the DHT expire (until
1252 * when should we never do a DHT lookup for the same name again)?
1253 * @param name name that is being mapped (at most 255 characters long)
1254 * @param rd_count number of entries in 'rd' array
1255 * @param rd array of records with data to store
1256 * @param signature signature of the record block, NULL if signature is unavailable (i.e.
1257 * because the user queried for a particular record type only)
1260 handle_record_remove_it (void *cls,
1261 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1262 struct GNUNET_TIME_Absolute expire,
1264 unsigned int rd_count,
1265 const struct GNUNET_NAMESTORE_RecordData *rd,
1266 const struct GNUNET_CRYPTO_RsaSignature *signature)
1268 static struct GNUNET_CRYPTO_RsaSignature dummy_signature;
1269 struct RemoveRecordContext *rrc = cls;
1272 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1275 "Name `%s 'currently has %u records\n",
1279 /* Could not find record to remove */
1280 rrc->op_res = RECORD_REMOVE_RESULT_NO_RECORDS;
1283 /* Find record to remove */
1285 for (c = 0; c < rd_count; c++)
1288 GNUNET_NAMESTORE_records_cmp (&rd[c],
1291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found record to remove!\n", rd_count);
1297 /* Could not find record to remove */
1298 rrc->op_res = RECORD_REMOVE_RESULT_RECORD_NOT_FOUND;
1303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1304 "No records left for name `%s', removing name\n",
1306 GNUNET_CRYPTO_short_hash (zone_key,
1307 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1310 GSN_database->remove_records (GSN_database->cls,
1314 /* Could not remove records from database */
1315 rrc->op_res = RECORD_REMOVE_RESULT_FAILED_TO_REMOVE;
1318 rrc->op_res = RECORD_REMOVE_RESULT_SUCCESS;
1323 struct GNUNET_NAMESTORE_RecordData rd_new[rd_count - 1];
1324 unsigned int c2 = 0;
1326 for (c = 0; c < rd_count; c++)
1330 rd_new[c2++] = rd[c];
1333 GSN_database->put_records(GSN_database->cls,
1337 rd_count - 1, rd_new,
1340 /* Could not put records into database */
1341 rrc->op_res = RECORD_REMOVE_RESULT_FAILED_TO_PUT_UPDATE;
1345 rrc->op_res = RECORD_REMOVE_RESULT_SUCCESS;
1350 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE' message
1353 * @param client GNUNET_SERVER_Client sending the message
1354 * @param message message of type 'struct RecordRemoveMessage'
1357 handle_record_remove (void *cls,
1358 struct GNUNET_SERVER_Client *client,
1359 const struct GNUNET_MessageHeader *message)
1361 struct GNUNET_NAMESTORE_Client *nc;
1362 const struct RecordRemoveMessage *rr_msg;
1363 struct RecordRemoveResponseMessage rrr_msg;
1364 struct GNUNET_CRYPTO_RsaPrivateKey *pkey;
1365 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
1366 struct GNUNET_CRYPTO_ShortHashCode pubkey_hash;
1367 struct GNUNET_NAMESTORE_RecordData rd;
1368 const char *pkey_tmp;
1369 const char *name_tmp;
1375 size_t msg_size_exp;
1378 struct RemoveRecordContext rrc;
1382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1383 "Received `%s' message\n",
1384 "NAMESTORE_RECORD_REMOVE");
1385 if (ntohs (message->size) < sizeof (struct RecordRemoveMessage))
1388 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1391 if (NULL == (nc = client_lookup(client)))
1394 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1397 rr_msg = (const struct RecordRemoveMessage *) message;
1398 rid = ntohl (rr_msg->gns_header.r_id);
1399 name_len = ntohs (rr_msg->name_len);
1400 rd_ser_len = ntohs (rr_msg->rd_len);
1401 rd_count = ntohs (rr_msg->rd_count);
1402 key_len = ntohs (rr_msg->pkey_len);
1403 msg_size = ntohs (message->size);
1404 if ((name_len >= MAX_NAME_LEN) || (0 == name_len) || (1 < rd_count) )
1407 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1410 msg_size_exp = sizeof (struct RecordRemoveMessage) + key_len + name_len + rd_ser_len;
1411 if (msg_size != msg_size_exp)
1414 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1417 pkey_tmp = (const char *) &rr_msg[1];
1418 name_tmp = &pkey_tmp[key_len];
1419 rd_ser = &name_tmp[name_len];
1420 if ('\0' != name_tmp[name_len -1])
1423 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1426 if (NULL == (pkey = GNUNET_CRYPTO_rsa_decode_key (pkey_tmp, key_len)))
1429 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1432 GNUNET_CRYPTO_rsa_key_get_public (pkey, &pub);
1433 GNUNET_CRYPTO_short_hash (&pub,
1434 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1436 learn_private_key (pkey);
1438 GNUNET_NAMESTORE_records_deserialize (rd_ser_len, rd_ser, rd_count, &rd))
1441 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1447 /* remove the whole name and all records */
1448 res = GSN_database->remove_records (GSN_database->cls,
1451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1452 "Removing name `%s': %s\n",
1453 name_tmp, (GNUNET_OK == res) ? "OK" : "FAILED");
1454 if (GNUNET_OK != res)
1455 /* Could not remove entry from database */
1456 res = RECORD_REMOVE_RESULT_FAILED_TO_PUT_UPDATE;
1458 res = RECORD_REMOVE_RESULT_SUCCESS;
1462 /* remove a single record */
1463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1464 "Removing record for name `%s' in zone `%s'\n", name_tmp,
1465 GNUNET_short_h2s (&pubkey_hash));
1467 rrc.op_res = RECORD_REMOVE_RESULT_RECORD_NOT_FOUND;
1470 while ( (RECORD_REMOVE_RESULT_RECORD_NOT_FOUND == rrc.op_res) &&
1471 (GNUNET_OK == res) )
1473 res = GSN_database->iterate_records (GSN_database->cls,
1477 &handle_record_remove_it, &rrc);
1485 GNUNET_break (RECORD_REMOVE_RESULT_NO_RECORDS == rrc.op_res);
1486 res = RECORD_REMOVE_RESULT_NO_RECORDS;
1487 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1488 _("Failed to find record to remove\n"));
1491 res = RECORD_REMOVE_RESULT_FAILED_ACCESS_DATABASE;
1495 res = RECORD_REMOVE_RESULT_FAILED_INTERNAL_ERROR;
1499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1500 "Sending `%s' message\n",
1501 "RECORD_REMOVE_RESPONSE");
1502 rrr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE_RESPONSE);
1503 rrr_msg.gns_header.header.size = htons (sizeof (struct RecordRemoveResponseMessage));
1504 rrr_msg.gns_header.r_id = htonl (rid);
1505 rrr_msg.op_result = htonl (res);
1506 GNUNET_SERVER_notification_context_unicast (snc, nc->client,
1507 &rrr_msg.gns_header.header,
1509 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1514 * Context for record remove operations passed from 'handle_zone_to_name' to
1515 * 'handle_zone_to_name_it' as closure
1517 struct ZoneToNameCtx
1522 struct GNUNET_NAMESTORE_Client *nc;
1525 * Request id (to be used in the response to the client).
1530 * Set to GNUNET_OK on success, GNUNET_SYSERR on error. Note that
1531 * not finding a name for the zone still counts as a 'success' here,
1532 * as this field is about the success of executing the IPC protocol.
1539 * Zone to name iterator
1541 * @param cls struct ZoneToNameCtx *
1542 * @param zone_key the zone key
1543 * @param expire expiration date
1545 * @param rd_count number of records
1546 * @param rd record data
1547 * @param signature signature
1550 handle_zone_to_name_it (void *cls,
1551 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1552 struct GNUNET_TIME_Absolute expire,
1554 unsigned int rd_count,
1555 const struct GNUNET_NAMESTORE_RecordData *rd,
1556 const struct GNUNET_CRYPTO_RsaSignature *signature)
1558 struct ZoneToNameCtx *ztn_ctx = cls;
1559 struct ZoneToNameResponseMessage *ztnr_msg;
1568 if ((NULL != zone_key) && (NULL != name))
1571 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1572 "Found result: name `%s' has %u records\n",
1575 name_len = strlen (name) + 1;
1579 /* no result found */
1580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1581 "Found no results\n");
1585 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1586 "Sending `%s' message\n",
1587 "ZONE_TO_NAME_RESPONSE");
1588 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
1589 msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1590 if (NULL != signature)
1591 msg_size += sizeof (struct GNUNET_CRYPTO_RsaSignature);
1592 if (msg_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
1595 ztn_ctx->success = GNUNET_SYSERR;
1598 ztnr_msg = GNUNET_malloc (msg_size);
1599 ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1600 ztnr_msg->gns_header.header.size = htons (msg_size);
1601 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1602 ztnr_msg->res = htons (res);
1603 ztnr_msg->rd_len = htons (rd_ser_len);
1604 ztnr_msg->rd_count = htons (rd_count);
1605 ztnr_msg->name_len = htons (name_len);
1606 ztnr_msg->expire = GNUNET_TIME_absolute_hton (expire);
1607 if (NULL != zone_key)
1608 ztnr_msg->zone_key = *zone_key;
1609 name_tmp = (char *) &ztnr_msg[1];
1611 memcpy (name_tmp, name, name_len);
1612 rd_tmp = &name_tmp[name_len];
1613 GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_tmp);
1614 sig_tmp = &rd_tmp[rd_ser_len];
1615 if (NULL != signature)
1616 memcpy (sig_tmp, signature, sizeof (struct GNUNET_CRYPTO_RsaSignature));
1617 ztn_ctx->success = GNUNET_OK;
1618 GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client,
1619 &ztnr_msg->gns_header.header,
1621 GNUNET_free (ztnr_msg);
1626 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME' message
1629 * @param client GNUNET_SERVER_Client sending the message
1630 * @param message message of type 'struct ZoneToNameMessage'
1633 handle_zone_to_name (void *cls,
1634 struct GNUNET_SERVER_Client *client,
1635 const struct GNUNET_MessageHeader *message)
1637 struct GNUNET_NAMESTORE_Client *nc;
1638 const struct ZoneToNameMessage *ztn_msg;
1639 struct ZoneToNameCtx ztn_ctx;
1641 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1642 "Received `%s' message\n",
1644 ztn_msg = (const struct ZoneToNameMessage *) message;
1645 if (NULL == (nc = client_lookup(client)))
1648 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1651 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1653 ztn_ctx.success = GNUNET_SYSERR;
1654 if (GNUNET_SYSERR ==
1655 GSN_database->zone_to_name (GSN_database->cls,
1657 &ztn_msg->value_zone,
1658 &handle_zone_to_name_it, &ztn_ctx))
1660 /* internal error, hang up instead of signalling something
1661 that might be wrong */
1663 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1666 GNUNET_SERVER_receive_done (client, ztn_ctx.success);
1671 * Zone iteration processor result
1673 enum ZoneIterationResult
1676 * Found records, but all records were filtered
1677 * Continue to iterate
1679 IT_ALL_RECORDS_FILTERED = -1,
1683 * Continue to iterate with next iteration_next call
1685 IT_SUCCESS_MORE_AVAILABLE = 0,
1688 * Iteration complete
1690 IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 1,
1695 * Context for record remove operations passed from
1696 * 'run_zone_iteration_round' to 'zone_iteraterate_proc' as closure
1698 struct ZoneIterationProcResult
1701 * The zone iteration handle
1703 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1706 * Iteration result: iteration done?
1707 * IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but
1708 * we got one for now and have sent it to the client
1709 * IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results,
1710 * IT_ALL_RECORDS_FILTERED: if all results were filtered so far.
1712 int res_iteration_finished;
1718 * Process results for zone iteration from database
1720 * @param cls struct ZoneIterationProcResult *proc
1721 * @param zone_key the zone key
1722 * @param expire expiration time
1724 * @param rd_count number of records for this name
1725 * @param rd record data
1726 * @param signature block signature
1729 zone_iteraterate_proc (void *cls,
1730 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *zone_key,
1731 struct GNUNET_TIME_Absolute expire,
1733 unsigned int rd_count,
1734 const struct GNUNET_NAMESTORE_RecordData *rd,
1735 const struct GNUNET_CRYPTO_RsaSignature *signature)
1737 struct ZoneIterationProcResult *proc = cls;
1738 struct GNUNET_NAMESTORE_RecordData rd_filtered[rd_count];
1739 struct GNUNET_CRYPTO_RsaSignature *new_signature = NULL;
1740 struct GNUNET_NAMESTORE_CryptoContainer *cc;
1741 struct GNUNET_HashCode long_hash;
1742 struct GNUNET_CRYPTO_ShortHashCode zone_hash;
1743 struct ZoneIterationResponseMessage *zir_msg;
1744 struct GNUNET_TIME_Relative rt;
1745 unsigned int rd_count_filtered;
1753 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1754 if ((NULL == zone_key) && (NULL == name))
1756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1757 "Iteration done\n");
1758 proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE;
1761 if ((NULL == zone_key) || (NULL == name))
1763 /* what is this!? should never happen */
1767 rd_count_filtered = 0;
1768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1769 "Received result for zone iteration: `%s'\n",
1771 for (c = 0; c < rd_count; c++)
1773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1774 "Record %u has flags: %x must have flags are %x, must not have flags are %x\n",
1776 proc->zi->must_have_flags,
1777 proc->zi->must_not_have_flags);
1778 /* Checking must have flags, except 'relative-expiration' which is a special flag */
1779 if ((rd[c].flags & proc->zi->must_have_flags & (~GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION))
1780 != (proc->zi->must_have_flags & (~ GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)))
1782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record %u lacks 'must-have' flags: Not included\n", c);
1785 /* Checking must-not-have flags */
1786 if (0 != (rd[c].flags & proc->zi->must_not_have_flags))
1788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1789 "Record %u has 'must-not-have' flags: Not included\n", c);
1792 rd_filtered[rd_count_filtered] = rd[c];
1793 /* convert relative to absolute expiration time unless explicitly requested otherwise */
1794 if ( (0 == (proc->zi->must_have_flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) &&
1795 (0 != (rd[c].flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1797 /* should convert relative-to-absolute expiration time */
1798 rt.rel_value = rd[c].expiration_time;
1799 rd_filtered[c].expiration_time = GNUNET_TIME_relative_to_absolute (rt).abs_value;
1800 rd_filtered[c].flags &= ~ GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION;
1802 /* we NEVER keep the 'authority' flag */
1803 rd_filtered[c].flags &= ~ GNUNET_NAMESTORE_RF_AUTHORITY;
1804 rd_count_filtered++;
1806 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1807 "Included %u of %u records\n",
1808 rd_count_filtered, rd_count);
1811 if ( (rd_count_filtered > 0) &&
1812 (0 == (proc->zi->must_have_flags & GNUNET_NAMESTORE_RF_RELATIVE_EXPIRATION)) )
1814 /* compute / obtain signature, but only if we (a) have records and (b) expiration times were
1815 converted to absolute expiration times */
1816 GNUNET_CRYPTO_short_hash (zone_key,
1817 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1819 GNUNET_CRYPTO_short_hash_double (&zone_hash, &long_hash);
1820 if (NULL != (cc = GNUNET_CONTAINER_multihashmap_get(zonekeys, &long_hash)))
1822 expire = get_block_expiration_time (rd_count_filtered, rd_filtered);
1823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1824 "Creating signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1825 name, GNUNET_short_h2s(&zone_hash),
1827 (unsigned long long) expire.abs_value);
1828 new_signature = GNUNET_NAMESTORE_create_signature (cc->privkey, expire, name,
1829 rd_filtered, rd_count_filtered);
1830 GNUNET_assert (NULL != new_signature);
1831 signature = new_signature;
1833 else if (rd_count_filtered == rd_count)
1835 if (NULL != signature)
1837 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1838 "Using provided signature for `%s' in zone `%s' with %u records and expiration %llu\n",
1839 name, GNUNET_short_h2s (&zone_hash), rd_count_filtered,
1840 (unsigned long long) expire.abs_value);
1845 if (rd_count_filtered == 0)
1847 /* After filtering records there are no records left to return */
1848 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No records to transmit\n");
1849 proc->res_iteration_finished = IT_ALL_RECORDS_FILTERED;
1853 if (GNUNET_YES == proc->zi->has_zone)
1854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1855 "Sending name `%s' for iteration over zone `%s'\n",
1856 name, GNUNET_short_h2s(&proc->zi->zone));
1858 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1859 "Sending name `%s' for iteration over all zones\n",
1861 name_len = strlen (name) + 1;
1862 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count_filtered, rd_filtered);
1863 msg_size = sizeof (struct ZoneIterationResponseMessage) + name_len + rd_ser_len;
1865 zir_msg = GNUNET_malloc (msg_size);
1866 zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1867 zir_msg->gns_header.header.size = htons (msg_size);
1868 zir_msg->gns_header.r_id = htonl (proc->zi->request_id);
1869 zir_msg->expire = GNUNET_TIME_absolute_hton (expire);
1870 zir_msg->reserved = htons (0);
1871 zir_msg->name_len = htons (name_len);
1872 zir_msg->rd_count = htons (rd_count_filtered);
1873 zir_msg->rd_len = htons (rd_ser_len);
1874 if (NULL != signature)
1875 zir_msg->signature = *signature;
1876 zir_msg->public_key = *zone_key;
1877 name_tmp = (char *) &zir_msg[1];
1878 memcpy (name_tmp, name, name_len);
1879 rd_ser = &name_tmp[name_len];
1880 GNUNET_NAMESTORE_records_serialize (rd_count_filtered, rd_filtered, rd_ser_len, rd_ser);
1881 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1882 "Sending `%s' message with size %u\n",
1883 "ZONE_ITERATION_RESPONSE",
1885 GNUNET_SERVER_notification_context_unicast (snc, proc->zi->client->client,
1886 (const struct GNUNET_MessageHeader *) zir_msg,
1888 proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE;
1889 GNUNET_free (zir_msg);
1890 GNUNET_free_non_null (new_signature);
1895 * Perform the next round of the zone iteration.
1897 * @param zi zone iterator to process
1900 run_zone_iteration_round (struct GNUNET_NAMESTORE_ZoneIteration *zi)
1902 struct ZoneIterationProcResult proc;
1903 struct ZoneIterationResponseMessage zir_end;
1904 struct GNUNET_CRYPTO_ShortHashCode *zone;
1906 memset (&proc, 0, sizeof (proc));
1908 if (GNUNET_YES == zi->has_zone)
1912 proc.res_iteration_finished = IT_ALL_RECORDS_FILTERED;
1913 while (IT_ALL_RECORDS_FILTERED == proc.res_iteration_finished)
1915 if (GNUNET_SYSERR ==
1916 GSN_database->iterate_records (GSN_database->cls, zone, NULL,
1918 &zone_iteraterate_proc, &proc))
1925 if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished)
1927 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1928 "More results available\n");
1929 return; /* more results later */
1931 if (GNUNET_YES == zi->has_zone)
1932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1933 "No more results for zone `%s'\n",
1934 GNUNET_short_h2s(&zi->zone));
1936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1937 "No more results for all zones\n");
1938 memset (&zir_end, 0, sizeof (zir_end));
1939 zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_RESPONSE);
1940 zir_end.gns_header.header.size = htons (sizeof (struct ZoneIterationResponseMessage));
1941 zir_end.gns_header.r_id = htonl(zi->request_id);
1942 GNUNET_SERVER_notification_context_unicast (snc,
1944 &zir_end.gns_header.header, GNUNET_NO);
1945 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1946 "Removing zone iterator\n");
1947 GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi);
1953 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START' message
1956 * @param client GNUNET_SERVER_Client sending the message
1957 * @param message message of type 'struct ZoneIterationStartMessage'
1960 handle_iteration_start (void *cls,
1961 struct GNUNET_SERVER_Client *client,
1962 const struct GNUNET_MessageHeader *message)
1964 static struct GNUNET_CRYPTO_ShortHashCode zeros;
1965 const struct ZoneIterationStartMessage *zis_msg;
1966 struct GNUNET_NAMESTORE_Client *nc;
1967 struct GNUNET_NAMESTORE_ZoneIteration *zi;
1969 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START");
1970 if (NULL == (nc = client_lookup (client)))
1973 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1976 zis_msg = (const struct ZoneIterationStartMessage *) message;
1977 zi = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_ZoneIteration));
1978 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1981 zi->must_have_flags = ntohs (zis_msg->must_have_flags);
1982 zi->must_not_have_flags = ntohs (zis_msg->must_not_have_flags);
1983 if (0 == memcmp (&zeros, &zis_msg->zone, sizeof (zeros)))
1985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to iterate over all zones\n");
1986 zi->zone = zis_msg->zone;
1987 zi->has_zone = GNUNET_NO;
1991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1992 "Starting to iterate over zone `%s'\n", GNUNET_short_h2s (&zis_msg->zone));
1993 zi->zone = zis_msg->zone;
1994 zi->has_zone = GNUNET_YES;
1996 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1997 run_zone_iteration_round (zi);
1998 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2003 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP' message
2006 * @param client GNUNET_SERVER_Client sending the message
2007 * @param message message of type 'struct ZoneIterationStopMessage'
2010 handle_iteration_stop (void *cls,
2011 struct GNUNET_SERVER_Client *client,
2012 const struct GNUNET_MessageHeader *message)
2014 struct GNUNET_NAMESTORE_Client *nc;
2015 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2016 const struct ZoneIterationStopMessage *zis_msg;
2019 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2020 "Received `%s' message\n",
2021 "ZONE_ITERATION_STOP");
2022 if (NULL == (nc = client_lookup(client)))
2025 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2028 zis_msg = (const struct ZoneIterationStopMessage *) message;
2029 rid = ntohl (zis_msg->gns_header.r_id);
2030 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2031 if (zi->request_id == rid)
2036 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2039 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2040 if (GNUNET_YES == zi->has_zone)
2041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2042 "Stopped zone iteration for zone `%s'\n",
2043 GNUNET_short_h2s (&zi->zone));
2045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2046 "Stopped zone iteration over all zones\n");
2048 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2053 * Handles a 'GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT' message
2056 * @param client GNUNET_SERVER_Client sending the message
2057 * @param message message of type 'struct ZoneIterationNextMessage'
2060 handle_iteration_next (void *cls,
2061 struct GNUNET_SERVER_Client *client,
2062 const struct GNUNET_MessageHeader *message)
2064 struct GNUNET_NAMESTORE_Client *nc;
2065 struct GNUNET_NAMESTORE_ZoneIteration *zi;
2066 const struct ZoneIterationNextMessage *zis_msg;
2069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT");
2070 if (NULL == (nc = client_lookup(client)))
2073 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2076 zis_msg = (const struct ZoneIterationNextMessage *) message;
2077 rid = ntohl (zis_msg->gns_header.r_id);
2078 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2079 if (zi->request_id == rid)
2084 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2087 run_zone_iteration_round (zi);
2088 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2093 * Load zone keys from directory by reading all .zkey files in this directory
2095 * @param cls int * 'counter' to store the number of files found
2096 * @param filename directory to scan
2097 * @return GNUNET_OK to continue
2100 zonekey_file_it (void *cls, const char *filename)
2102 unsigned int *counter = cls;
2103 struct GNUNET_CRYPTO_RsaPrivateKey *privkey;
2105 if ((NULL == filename) ||
2106 (NULL == strstr(filename, ".zkey")))
2108 privkey = GNUNET_CRYPTO_rsa_key_create_from_file (filename);
2109 if (NULL == privkey)
2111 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2112 _("Could not parse zone key file `%s'\n"),
2116 learn_private_key (privkey);
2123 * Process namestore requests.
2125 * @param cls closure
2126 * @param server the initialized server
2127 * @param cfg configuration to use
2130 run (void *cls, struct GNUNET_SERVER_Handle *server,
2131 const struct GNUNET_CONFIGURATION_Handle *cfg)
2133 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
2134 {&handle_start, NULL,
2135 GNUNET_MESSAGE_TYPE_NAMESTORE_START, sizeof (struct StartMessage)},
2136 {&handle_lookup_name, NULL,
2137 GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME, 0},
2138 {&handle_record_put, NULL,
2139 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_PUT, 0},
2140 {&handle_record_create, NULL,
2141 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_CREATE, 0},
2142 {&handle_record_remove, NULL,
2143 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_REMOVE, 0},
2144 {&handle_zone_to_name, NULL,
2145 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, sizeof (struct ZoneToNameMessage) },
2146 {&handle_iteration_start, NULL,
2147 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage) },
2148 {&handle_iteration_next, NULL,
2149 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, sizeof (struct ZoneIterationNextMessage) },
2150 {&handle_iteration_stop, NULL,
2151 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage) },
2155 unsigned int counter;
2157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2160 /* Load private keys from disk */
2162 GNUNET_CONFIGURATION_get_value_filename (cfg, "namestore",
2163 "zonefile_directory",
2164 &zonefile_directory))
2166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2167 _("No directory to load zonefiles specified in configuration\n"));
2168 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2172 if (GNUNET_NO == GNUNET_DISK_file_test (zonefile_directory))
2174 if (GNUNET_SYSERR == GNUNET_DISK_directory_create (zonefile_directory))
2176 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2177 _("Creating directory `%s' for zone files failed!\n"),
2178 zonefile_directory);
2179 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2183 "Created directory `%s' for zone files\n",
2184 zonefile_directory);
2187 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2188 "Scanning directory `%s' for zone files\n", zonefile_directory);
2189 zonekeys = GNUNET_CONTAINER_multihashmap_create (16);
2191 GNUNET_DISK_directory_scan (zonefile_directory, zonekey_file_it, &counter);
2192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2193 "Found %u zone files\n",
2196 /* Loading database plugin */
2198 GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database",
2200 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2202 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2203 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2204 GNUNET_free (database);
2205 if (NULL == GSN_database)
2207 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2208 "Could not load database backend `%s'\n",
2210 GNUNET_SCHEDULER_add_now (&cleanup_task, NULL);
2214 /* Configuring server handles */
2215 GNUNET_SERVER_add_handlers (server, handlers);
2216 snc = GNUNET_SERVER_notification_context_create (server, 16);
2217 GNUNET_SERVER_disconnect_notify (server,
2218 &client_disconnect_notification,
2220 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
2226 * The main function for the template service.
2228 * @param argc number of arguments from the command line
2229 * @param argv command line arguments
2230 * @return 0 ok, 1 on error
2233 main (int argc, char *const *argv)
2235 return (GNUNET_OK ==
2236 GNUNET_SERVICE_run (argc, argv, "namestore",
2237 GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
2240 /* end of gnunet-service-namestore.c */